/* ============================================================================
 *  STYLES.CSS — Hero a pantalla completa
 *  Optimizado para iPhone (safe areas, 100dvh) y Android (touch targets).
 * ========================================================================== */

*, *::before, *::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html, body {
  width: 100%;
  height: 100dvh;
  overflow: hidden;
  font-family: var(--font-body);
  background-color: var(--bg-dark);
  color: var(--text-main);
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;      /* mata el zoom por doble toque */
}

/* Fallback para navegadores sin dvh */
@supports not (height: 100dvh) {
  html, body { height: 100vh; }
}

/* Foco visible y accesible en todo el sitio */
:focus-visible {
  outline: 3px solid var(--accent-light);
  outline-offset: 3px;
  border-radius: 4px;
}

button { font: inherit; color: inherit; }

/* ---------------------------------------------------------------- HERO -- */
.landing {
  position: relative;
  width: 100%;
  height: 100dvh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: radial-gradient(circle at 50% 40%, #1A1710 0%, #0A0A0A 75%);
  padding: calc(0.8rem + env(safe-area-inset-top, 0px))
           calc(1.25rem + env(safe-area-inset-right, 0px))
           calc(1rem + env(safe-area-inset-bottom, 0px))
           calc(1.25rem + env(safe-area-inset-left, 0px));
  /*  overflow-x:hidden recorta las partículas, que se salen a propósito por
   *  los lados (left:-10%, right:-15%).
   *  overflow-y:auto es el arreglo de accesibilidad: con `hidden` a secas, un
   *  usuario que amplía el texto (WCAG 1.4.4) veía el contenido CORTADO y sin
   *  forma de llegar a él — el zoom que dejamos activo no servía de nada. Con
   *  `auto` no aparece scrollbar mientras todo quepa, y aparece cuando no. */
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain;
}

@supports not (height: 100dvh) {
  .landing { height: 100vh; }
}

/*  Textura de fondo (papel, lino, mármol…).
 *  Se superpone al degradado oscuro como GRANO mediante mix-blend-mode, no
 *  como fondo literal. Así una textura CLARA funciona sobre el negro sin
 *  arruinar la legibilidad del texto blanco y dorado.
 *  Las variables las inyecta app.js desde config.js → fondo. */
.landing::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image: var(--fondo-img, none);
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  opacity: var(--fondo-opacidad, 0);
  mix-blend-mode: var(--fondo-mezcla, overlay);
}

/* Partículas de fondo */
.cloud-particles { position: absolute; inset: 0; pointer-events: none; z-index: 1; }

/*  will-change:transform fuerza a que cada partícula viva en su propia capa
 *  de composición: el blur(65px) se rasteriza UNA vez y las animaciones sólo
 *  mueven la capa. Sin esto, el navegador puede rehacer el desenfoque en cada
 *  fotograma, que es de lo más caro que hay en un móvil de gama media. */
.cp {
  position: absolute;
  background: radial-gradient(circle, var(--accent-glow) 0%, transparent 70%);
  filter: blur(65px);
  border-radius: 50%;
  opacity: 0.55;
  animation: drift 20s linear infinite alternate;
  will-change: transform;
}
.cp1 { top: 10%; left: -10%; width: 320px; height: 320px; }
.cp2 { bottom: 15%; right: -15%; width: 380px; height: 380px; animation-delay: -5s; }
.cp3 { top: 40%; right: 20%; width: 260px; height: 260px; animation-delay: -10s; }

@keyframes drift {
  0%   { transform: translate(0, 0) rotate(0deg); }
  50%  { transform: translate(25px, -18px) rotate(3deg); }
  100% { transform: translate(-15px, 12px) rotate(-2deg); }
}

.hero-content {
  position: relative;
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  height: 100%;
  max-height: 920px;
  max-width: 540px;
  width: 100%;
  text-align: center;
  padding: 0.4rem 0;
}

/* En un flex column con align-items:center los hijos se dimensionan a su
   contenido (max-content), así que un titular largo NO rompe línea y se sale
   por los lados. Atarlos al ancho del contenedor lo evita. */
.hero-content > * { max-width: 100%; }

@keyframes fadeDown { from { opacity: 0; transform: translateY(-25px); } to { opacity: 1; transform: none; } }
@keyframes fadeUp   { from { opacity: 0; transform: translateY(35px);  } to { opacity: 1; transform: none; } }

/* ------------------------------------------------------------- BADGES -- */
.badges-group {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.4rem;
  width: 100%;
  animation: fadeDown 0.8s var(--ease) both;
}

.brand-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.4rem 1.25rem;
  background: rgba(0, 0, 0, 0.55);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-full);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 2.5px;
  text-transform: uppercase;
  color: var(--accent-light);
  box-shadow: 0 0 20px rgba(var(--accent-rgb), 0.15);
}

/*  El backdrop-filter aquí desenfoca un fondo que está ANIMADO: se recalcula
 *  en cada fotograma, para siempre. Sobre un fondo casi negro con un 55% de
 *  opacidad encima el efecto casi no se aprecia, así que en móvil no compensa.
 *  Se deja sólo donde hay GPU de sobra (puntero fino = escritorio). */
@media (pointer: fine) {
  .brand-badge {
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
  }
}

.badge-dot {
  width: 6px; height: 6px;
  background-color: var(--accent);
  border-radius: 50%;
  flex-shrink: 0;
  animation: pulseDot 2s ease-in-out infinite;
}
@keyframes pulseDot { 0%,100% { opacity: 1; transform: scale(1); } 50% { opacity: 0.4; transform: scale(0.65); } }

.rating-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;          /* en móviles estrechos parte en 2 líneas */
  max-width: 100%;
  gap: 0.1rem 0.35rem;
  font-size: 0.78rem;
  font-weight: 600;
  color: #FFD166;
  background: rgba(255, 209, 102, 0.1);
  padding: 0.28rem 0.85rem;
  border-radius: var(--radius-full);
  border: 1px solid rgba(255, 209, 102, 0.25);
}
.rating-badge span { color: #FFFFFF; font-weight: 700; }
.rating-count { color: var(--text-muted) !important; font-weight: 400 !important; font-size: 0.72rem; }

/* ------------------------------------------------------------ PRODUCTO -- */
/*  La escena del producto es FLUIDA: ocupa todo el alto que sobre tras
 *  colocar badges, titular y CTA. Así encaja en cualquier móvil (desde el
 *  iPhone SE hasta un Pixel alto) sin tener que afinar alturas por modelo. */
.shoe-stage {
  position: relative;
  z-index: 4;
  width: 100%;
  max-width: 520px;
  flex: 1 1 auto;
  min-height: 120px;
  /* Atado al alto de pantalla, no a un píxel fijo: el hero es una columna de
     altura fija que no hace scroll, así que un tope alto en un móvil bajo se
     comería la nota de stock. El escenario crece con flex y absorbe el hueco
     que sobra; el tope sólo marca hasta dónde. */
  max-height: min(520px, 56dvh);
  display: flex;
  align-items: center;
  justify-content: center;
  animation: fadeUp 0.9s var(--ease) 0.12s both;
  perspective: 1000px;
}

.shoe-glow {
  position: absolute;
  inset: 10%;
  background: radial-gradient(ellipse at center, rgba(var(--accent-rgb), 0.45), transparent 70%);
  z-index: 1;
  filter: blur(30px);
  border-radius: 50%;
  animation: glowPulse 3.6s ease-in-out infinite;
}
@keyframes glowPulse { 0%,100% { opacity: 0.55; transform: scale(1); } 50% { opacity: 1; transform: scale(1.18); } }

/*  IMPORTANTE — separación de capas de animación:
 *  .shoe-float lleva el keyframe de levitación (CSS).
 *  .shoe-img recibe el giro 3D por JavaScript (estilo inline).
 *  Si ambas cosas vivieran en el mismo elemento, la animación CSS ganaría
 *  en la cascada y el parallax no se vería nunca. */
.shoe-float {
  position: relative;
  z-index: 2;
  height: 100%;
  /* Mismo criterio que .shoe-stage. En móvil el 53dvh deja el producto justo
     en el punto donde el ancho de la pantalla pasa a ser el límite: más alto
     no se vería más grande, sólo dejaría aire arriba y abajo. */
  max-height: min(500px, 53dvh);
  display: flex;
  align-items: center;
  transform-style: preserve-3d;
  animation: levitate 3.6s ease-in-out infinite;
}
.shoe-float picture { display: contents; }
@keyframes levitate {
  0%,100% { transform: translateY(0) rotate(-2deg); }
  50%     { transform: translateY(-16px) rotate(1.5deg); }
}

/* Alto marcado por el envoltorio; el ancho lo deduce el navegador de los
   atributos width/height del <img> (780x990), así que nunca se deforma.

   SIN marco, SIN fondo y SIN box-shadow a propósito. Esos tres venían de la
   landing de agendas, donde la foto era una tarjeta rectangular que llenaba
   todo el recuadro. Aquí el PNG es transparente: el borde y el box-shadow
   siguen la CAJA de la imagen, no el producto, así que dibujaban un rectángulo
   flotando alrededor de un montón de aire.

   La sombra la da drop-shadow, que sí sigue el contorno real del alfa: la
   sombra cae sobre los cargadores y no sobre un cuadrado invisible. */
.shoe-img {
  display: block;
  height: 100%;
  width: auto;
  max-width: 100%;
  object-fit: contain;
  filter: drop-shadow(0 22px 34px rgba(0, 0, 0, 0.75))
          drop-shadow(0 0 26px rgba(var(--accent-rgb), 0.35));
  transition: opacity 0.28s ease, transform 0.18s cubic-bezier(0.1, 1, 0.1, 1);
  will-change: transform;
}

.shoe-shadow {
  position: absolute;
  bottom: -5px; left: 50%;
  width: 200px; height: 20px;
  background: rgba(var(--accent-rgb), 0.45);
  border-radius: 50%;
  filter: blur(14px);
  z-index: 0;
  animation: shadowFloat 3.6s ease-in-out infinite;
}
@keyframes shadowFloat {
  0%,100% { transform: translateX(-50%) scale(1); opacity: 0.5; }
  50%     { transform: translateX(-50%) scale(0.7); opacity: 0.22; }
}

/* ------------------------------------------------------------ SWATCHES -- */
.hero-swatches {
  display: flex;
  gap: 0.85rem;
  z-index: 5;
  animation: fadeUp 0.9s var(--ease) 0.2s both;
}

/* Área táctil real de 44x44 (accesible) con el círculo dibujado dentro.
   El color llega desde JS como custom property --sw. */
.hero-swatch-btn {
  width: var(--tap-min);
  height: var(--tap-min);
  padding: 0;
  border: none;
  background: none;
  cursor: pointer;
  position: relative;
  border-radius: 50%;
  touch-action: manipulation;
}
.hero-swatch-btn::after {
  content: '';
  position: absolute;
  inset: 6px;
  border-radius: 50%;
  background: var(--sw, #888);
  border: 2px solid rgba(255, 255, 255, 0.25);
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.4);
  transition: transform var(--transition-fast), border-color var(--transition-fast), box-shadow var(--transition-fast);
}
.hero-swatch-btn:hover::after { transform: scale(1.16); border-color: var(--accent); }
.hero-swatch-btn.active::after {
  transform: scale(1.22);
  border-color: #FFFFFF;
  box-shadow: 0 0 15px var(--accent);
}

/* ------------------------------------------------------------ TITULAR -- */
.headline-block { width: 100%; animation: fadeUp 0.9s var(--ease) 0.25s both; }

/*  El titular debe aguantar aunque Bebas Neue NO llegue a cargar (conexión
 *  lenta, Google Fonts bloqueado). Por eso: coeficiente vw conservador, y
 *  cada palabra en inline-block para garantizar un punto de salto de línea
 *  limpio en vez de que el texto se salga y quede recortado. */
.headline-main {
  font-family: var(--font-display);
  font-size: clamp(2.4rem, 10.5vw, 4.4rem);
  line-height: 0.95;
  letter-spacing: 2px;
  text-transform: uppercase;
  overflow-wrap: break-word;
  text-shadow: 0 2px 25px rgba(0, 0, 0, 0.8), 0 0 20px var(--accent-glow);
}
.headline-main > span { display: inline-block; max-width: 100%; }
.headline-accent { color: var(--accent); text-shadow: 0 0 30px rgba(var(--accent-rgb), 0.6); }

.headline-sub {
  font-size: 1rem;
  color: var(--text-muted);
  font-weight: 300;
  line-height: 1.4;
  margin-top: 0.35rem;
  letter-spacing: 0.8px;
}

/* ---------------------------------------------------------------- CTA -- */
.cta-wrapper {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  animation: fadeUp 0.9s var(--ease) 0.35s both;
}

.main-price {
  font-family: var(--font-display);
  font-size: 2.8rem;
  color: var(--accent-light);
  line-height: 1;
  letter-spacing: 2px;
  text-shadow: 0 2px 10px rgba(0, 0, 0, 0.8), 0 0 15px rgba(var(--accent-rgb), 0.4);
}
.main-price .currency {
  font-family: var(--font-body);
  font-size: 1.05rem;
  color: var(--accent);
  font-weight: 600;
  vertical-align: top;
}

/* Producto a cotización: sin cifra que mostrar.
   El tamaño de precio (2.8rem en fuente display) está pensado para un "$19.99"
   de tres caracteres; "Precio a cotizar" ahí dentro se comería el titular y le
   quitaría el protagonismo al botón, que aquí es lo que de verdad importa.
   Se baja a texto normal y se le pone forma de etiqueta para que se lea como
   una condición del producto, no como un precio a medias. */
.main-price.is-cotizacion {
  font-family: var(--font-body);
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: 0.5px;
  color: var(--accent-light);
  text-shadow: none;
  display: inline-block;
  padding: 8px 20px;
  border: 1px solid rgba(var(--accent-rgb), 0.35);
  border-radius: 999px;
  background: rgba(var(--accent-rgb), 0.08);
}

.btn-cloud {
  background: linear-gradient(135deg, var(--accent-bright) 0%, var(--accent) 50%, var(--accent-deep) 100%);
  border: 1.5px solid var(--accent-light);
  padding: 1.05rem 2.5rem;
  min-height: var(--tap-min);
  border-radius: var(--radius-full);
  cursor: pointer;
  box-shadow: 0 0 30px rgba(var(--accent-rgb), 0.45), inset 0 2px 4px rgba(255, 255, 255, 0.4);
  transition: transform var(--transition-fast), box-shadow var(--transition-fast);
  width: 100%;
  max-width: 380px;
  touch-action: manipulation;
  animation: attentionPulse 3s infinite ease-in-out;
}
@keyframes attentionPulse { 0%,100% { transform: scale(1); } 50% { transform: scale(1.035); } }

.btn-cloud:hover {
  transform: translateY(-3px) scale(1.03);
  box-shadow: 0 0 45px rgba(var(--accent-rgb), 0.7), inset 0 2px 6px rgba(255, 255, 255, 0.6);
  animation-play-state: paused;
}
.btn-cloud:active { transform: scale(0.98); animation-play-state: paused; }

.btn-inner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.7rem;
  font-family: var(--font-display);
  font-size: 1.55rem;
  letter-spacing: 2px;
  color: #0A0A0A;
}
.btn-sparkle { font-size: 1.2rem; animation: sparklePulse 2.5s ease-in-out infinite alternate; }
@keyframes sparklePulse { 0% { transform: scale(0.9) rotate(-8deg); } 100% { transform: scale(1.18) rotate(12deg); } }

.stock-note {
  font-size: 0.78rem;
  color: rgba(244, 244, 244, 0.65);
  font-weight: 500;
  letter-spacing: 1.4px;
  text-transform: uppercase;
}

/* --------------------------------------------------------- SIN JAVASCRIPT */
.noscript-box {
  position: fixed;
  inset: 0;
  z-index: 2000;
  background: var(--bg-dark);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  padding: 2rem;
  text-align: center;
}
.noscript-box a {
  background: var(--accent);
  color: #0A0A0A;
  font-weight: 700;
  padding: 1rem 2rem;
  border-radius: var(--radius-full);
  text-decoration: none;
}

/* ============================ RESPONSIVE ================================= */

/* Móviles bajos (iPhone SE, Android compactos).
   La imagen ya se encoge sola — su tope va en dvh — así que aquí sólo se
   ajusta la tipografía. */
@media (max-height: 740px) {
  .headline-main { font-size: clamp(2.1rem, 9.5vw, 2.7rem); letter-spacing: 1.5px; }
  .headline-sub  { font-size: 0.88rem; margin-top: 0.2rem; }
  .main-price    { font-size: 2rem; }
  .btn-cloud     { padding: 0.8rem 2rem; }
  .btn-inner     { font-size: 1.25rem; }
  .brand-badge   { font-size: 0.63rem; padding: 0.28rem 0.9rem; letter-spacing: 2px; }
  .hero-swatches { gap: 0.5rem; }
  .stock-note    { font-size: 0.7rem; }
  .rating-badge  { font-size: 0.72rem; }
  .rating-count  { font-size: 0.68rem; }
}

@media (max-height: 640px) {
  .rating-badge { display: none; }
  .headline-sub { display: none; }
  .main-price   { font-size: 1.8rem; }
}

/* Móvil apaisado: dos columnas para no perder de vista el CTA */
@media (max-height: 500px) and (orientation: landscape) {
  .hero-content {
    display: grid;
    grid-template-columns: 1fr 1.15fr;
    align-items: center;
    gap: 0.5rem 1.25rem;
    max-width: 900px;
  }
  /* En apaisado el hero es grid, así que .shoe-float no tiene altura definida
     y la <img> se dimensionaría por ancho (saliéndose por abajo). El tope va
     directo sobre la imagen: al ser un elemento reemplazado, el ancho sigue
     solo la proporción. */
  .shoe-stage { grid-row: span 4; min-height: 0; max-height: 100%; }
  .shoe-float { max-height: 100%; height: auto; }
  /* Las 5rem son el sitio que necesitan el titular y el botón, que en apaisado
     van en la columna de al lado pero comparten el alto de la pantalla. Con
     3rem la imagen se pasaba y empujaba el bloque hacia abajo. */
  .shoe-img   { height: auto; max-height: calc(100dvh - 5rem); }
  .badges-group, .hero-swatches, .headline-block, .cta-wrapper { grid-column: 2; }
  .hero-swatches { justify-content: center; }
  .headline-main { font-size: 1.9rem; }
  .main-price    { font-size: 1.6rem; }
  .btn-inner     { font-size: 1.05rem; }
  .btn-cloud     { padding: 0.6rem 1.5rem; }
  .stock-note, .headline-sub { display: none; }
}

/* Escritorio grande.
   El producto manda: sin el marco ni el selector de color, sobra sitio para
   que los cargadores se vean grandes sin apretar el titular ni el botón. */
@media (min-width: 1024px) and (min-height: 800px) {
  .hero-content { max-width: 640px; }
  .shoe-stage   { max-height: min(520px, 54dvh); }
  .shoe-float   { max-height: min(490px, 52dvh); }
}

/* ================== PAUSA DE ANIMACIONES CON EL MODAL ==================== */
/*  Con el modal abierto, el hero sigue detrás animando partículas, glow,
 *  levitación y el latido del CTA — y encima el overlay les aplica un
 *  backdrop-filter: blur(12px), que obliga a recalcular ese desenfoque en
 *  cada fotograma. Nada de eso se ve (está tapado), así que se congela
 *  mientras el cliente rellena el formulario, que es justo el momento en el
 *  que no queremos que el móvil vaya a tirones.
 *  app.js pone/quita .modal-abierto en el <body>. */
body.modal-abierto .cp,
body.modal-abierto .shoe-float,
body.modal-abierto .shoe-glow,
body.modal-abierto .shoe-shadow,
body.modal-abierto .btn-cloud,
body.modal-abierto .btn-sparkle,
body.modal-abierto .badge-dot {
  animation-play-state: paused;
}

/* ===================== ACCESIBILIDAD: MENOS MOVIMIENTO =================== */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  .shoe-float, .shoe-shadow, .shoe-glow, .cp, .btn-cloud, .btn-sparkle { animation: none !important; }
}
