/* ══════════════════════════════════════════════════════════════════════════
   ED TechMobile — hoja de estilos principal
   Identidad de marca (manual del cliente):
   - Títulos: Mortend Bold · Cuerpo/UI: NEXT ART (Heavy/Light)
   - Acento: #2547F1 · Fondos: #FFFFFF / #F5F5F7 · Texto: #1D1D1F
   Breakpoints revisados: 360px, 768px, 1280px.
   ══════════════════════════════════════════════════════════════════════════ */

@font-face {
  font-family: "Mortend";
  src: url("../fonts/Mortend_Bold.34edea30d375.otf") format("opentype");
  font-weight: 700;
  font-display: swap;
}
@font-face {
  font-family: "NEXT ART";
  src: url("../fonts/NEXT_ART_Light.1baec8718768.otf") format("opentype");
  font-weight: 300;
  font-display: swap;
}
@font-face {
  font-family: "NEXT ART";
  src: url("../fonts/NEXT_ART_Heavy.6fe0ff69a6c6.otf") format("opentype");
  font-weight: 800;
  font-display: swap;
}

:root {
  --acento: #2547F1;
  --acento-oscuro: #1c38c4;
  --fondo: #FFFFFF;
  --fondo-alt: #F5F5F7;
  --texto: #1D1D1F;
  --texto-suave: #6e6e73;
  --borde: #e3e3e8;
  --exito: #1e8449;
  --error: #c0392b;
  --radio: 16px;
  --radio-sm: 10px;
  --sombra: 0 8px 30px rgba(29, 29, 31, .08);
  --fuente-titulo: "Mortend", "NEXT ART", system-ui, sans-serif;
  --fuente-ui: "NEXT ART", system-ui, -apple-system, sans-serif;
}

*, *::before, *::after { box-sizing: border-box; }
[x-cloak] { display: none !important; }

body {
  margin: 0;
  font-family: var(--fuente-ui);
  font-weight: 300;
  color: var(--texto);
  background: var(--fondo);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; display: block; }
a { color: var(--acento); text-decoration: none; }
a:hover { text-decoration: underline; }

h1, h2, h3 { font-family: var(--fuente-titulo); font-weight: 700; line-height: 1.15; margin: 0 0 .5em; }
h1 { font-size: clamp(1.9rem, 5vw, 3.2rem); letter-spacing: -.01em; }
h2 { font-size: clamp(1.4rem, 3.5vw, 2.1rem); }
h3 { font-size: 1.05rem; }

.contenedor { max-width: 1200px; margin: 0 auto; padding: 0 20px; }

/* ── Botones ─────────────────────────────────────────────────────────────── */
.boton {
  display: inline-block;
  font-family: var(--fuente-ui);
  font-weight: 800;
  font-size: .95rem;
  border: none;
  border-radius: 999px;
  padding: 13px 28px;
  cursor: pointer;
  text-align: center;
  transition: background .15s ease, transform .1s ease, box-shadow .15s ease;
}
.boton:hover { text-decoration: none; transform: translateY(-1px); }
.boton:active { transform: translateY(0); }
.boton-primario { background: var(--acento); color: #fff; }
.boton-primario:hover { background: var(--acento-oscuro); box-shadow: 0 6px 18px rgba(37, 71, 241, .35); }
.boton-secundario { background: #fff; color: var(--texto); border: 1px solid var(--borde); }
.boton-secundario:hover { border-color: var(--texto-suave); }
.boton-whatsapp { background: #25d366; color: #fff; }
.boton-whatsapp:hover { background: #1da851; box-shadow: 0 6px 18px rgba(37, 211, 102, .35); }
.boton-bloque { display: block; width: 100%; }
.boton[disabled] { opacity: .45; cursor: not-allowed; transform: none; }

/* ── Header ──────────────────────────────────────────────────────────────── */
.header {
  position: sticky; top: 0; z-index: 50;
  background: rgba(255, 255, 255, .92);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--borde);
}
.header-inner { display: flex; align-items: center; gap: 24px; height: 60px; }
.logo img { height: 26px; width: auto; }
.nav-principal { display: flex; gap: 22px; margin: 0 auto; }
.nav-principal a { color: var(--texto); font-size: .92rem; }
.nav-principal a:hover, .nav-principal a.activo { color: var(--acento); text-decoration: none; }
.header-acciones { display: flex; align-items: center; gap: 18px; }
.header-acciones a { color: var(--texto); font-size: .92rem; }
.boton-carrito { position: relative; background: none; border: none; cursor: pointer; padding: 4px; color: var(--texto); }
.contador-carrito {
  position: absolute; top: -6px; right: -10px;
  background: var(--acento); color: #fff;
  font-size: .68rem; font-weight: 800;
  min-width: 18px; height: 18px; line-height: 18px;
  border-radius: 999px; text-align: center; padding: 0 4px;
}
.boton-menu { display: none; background: none; border: none; cursor: pointer; padding: 6px; color: var(--texto); }

/* ── Hero ────────────────────────────────────────────────────────────────── */
.hero { text-align: center; padding: 72px 0 40px; }
.hero .eyebrow { color: var(--texto-suave); font-size: .95rem; margin-bottom: 10px; }
.hero p.subtitulo { color: var(--texto-suave); font-size: 1.15rem; max-width: 560px; margin: 0 auto 22px; }
.hero-enlaces { display: flex; gap: 28px; justify-content: center; }
.hero-imagen {
  margin: 44px auto 0; max-width: 900px;
  background: var(--fondo-alt); border-radius: 24px;
  min-height: 280px; display: flex; align-items: center; justify-content: center;
  overflow: hidden;
}
.hero-imagen img { object-fit: cover; width: 100%; height: 100%; }

/* ── Escena 3D del hero ──────────────────────────────────────────────────────
   El producto flota y se inclina siguiendo el puntero. core/js/hero-3d.js
   escribe las variables de abajo; el CSS arma la transformación. Sin JS los
   valores por defecto dejan la foto quieta y perfectamente visible.          */
.hero-imagen.escena-3d {
  --rx: 0deg; --ry: 0deg; --ty: 0px;
  --gx: 50%; --gy: 35%;
  --piso-escala: 1; --piso-opacidad: .75;

  position: relative;
  min-height: 460px;
  padding: 40px 20px 64px;
  border-radius: 28px;
  background: radial-gradient(120% 85% at 50% 0%, #ffffff 0%, var(--fondo-alt) 58%, #e9e9ee 100%);
  perspective: 1100px;
  perspective-origin: 50% 45%;
}
.hero-imagen.escena-3d .hero-pieza {
  position: relative; z-index: 1;
  display: block; width: 100%; max-width: 300px;
  transform: translate3d(0, var(--ty), 0) rotateX(var(--rx)) rotateY(var(--ry));
  transform-style: preserve-3d;
  will-change: transform;
}
.hero-imagen.escena-3d .hero-pieza:hover { text-decoration: none; }
.hero-imagen.escena-3d .hero-pieza img {
  display: block; width: 100%; height: auto;
  object-fit: contain; border-radius: 18px;
  filter: drop-shadow(0 26px 40px rgba(29, 29, 31, .22));
}
.hero-brillo {
  position: absolute; inset: 0; border-radius: 18px; pointer-events: none;
  background: radial-gradient(36% 34% at var(--gx) var(--gy),
              rgba(255, 255, 255, .6), rgba(255, 255, 255, 0) 72%);
  mix-blend-mode: screen;
}
.hero-piso {
  position: absolute; z-index: 0; bottom: 40px; left: 50%;
  width: 220px; height: 24px; translate: -50% 0;
  background: radial-gradient(50% 50% at 50% 50%,
              rgba(29, 29, 31, .3), rgba(29, 29, 31, 0) 72%);
  filter: blur(3px);
  scale: var(--piso-escala) 1;
  opacity: var(--piso-opacidad);
}

@media (prefers-reduced-motion: reduce) {
  .hero-imagen.escena-3d .hero-pieza { transform: none; }
}

/* ── Badges de confianza ─────────────────────────────────────────────────── */
.franja-badges { background: var(--fondo-alt); padding: 56px 0; margin-top: 64px; }
.badges { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; text-align: center; }
.badge-icono {
  width: 48px; height: 48px; margin: 0 auto 12px;
  background: #fff; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  color: var(--acento); box-shadow: var(--sombra);
}
.badge h3 { font-family: var(--fuente-ui); font-weight: 800; margin-bottom: 2px; }
.badge p { color: var(--texto-suave); font-size: .9rem; margin: 0; }

/* ── Secciones ───────────────────────────────────────────────────────────── */
.seccion { padding: 64px 0; }
.seccion-titulo { text-align: center; margin-bottom: 36px; }

.tarjetas-marca { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; }
.tarjeta-marca {
  background: var(--fondo-alt); border-radius: var(--radio);
  padding: 28px; min-height: 210px;
  display: flex; flex-direction: column;
  transition: transform .15s ease, box-shadow .15s ease;
}
.tarjeta-marca:hover { transform: translateY(-3px); box-shadow: var(--sombra); }
.tarjeta-marca p { color: var(--texto-suave); margin: 2px 0 auto; }
.tarjeta-marca a { margin-top: 18px; font-weight: 800; font-size: .92rem; }

/* ── Grilla de productos ─────────────────────────────────────────────────── */
.grilla-productos {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 22px;
}
.tarjeta-producto { text-align: center; position: relative; }
.tarjeta-producto .foto {
  background: var(--fondo-alt); border-radius: var(--radio);
  aspect-ratio: 1; margin-bottom: 12px;
  display: flex; align-items: center; justify-content: center;
  overflow: hidden; position: relative;
}
.tarjeta-producto .foto img { object-fit: cover; width: 100%; height: 100%; transition: transform .25s ease; }
.tarjeta-producto:hover .foto img { transform: scale(1.04); }
.tarjeta-producto h3 { font-family: var(--fuente-ui); font-weight: 800; font-size: .95rem; margin: 0; }
.tarjeta-producto .precio { color: var(--texto-suave); font-size: .9rem; margin-top: 2px; }
.tarjeta-producto > a { color: inherit; }
.tarjeta-producto > a:hover { text-decoration: none; }
.sin-foto { color: var(--texto-suave); font-size: .8rem; }
.agotado-etiqueta {
  position: absolute; top: 10px; left: 10px;
  background: var(--texto); color: #fff;
  font-size: .7rem; font-weight: 800;
  padding: 4px 10px; border-radius: 999px;
}
.boton-vista-rapida {
  position: absolute; bottom: 12px; left: 50%; translate: -50% 0;
  background: rgba(255,255,255,.95); border: none; cursor: pointer;
  font-family: var(--fuente-ui); font-weight: 800; font-size: .8rem;
  padding: 8px 16px; border-radius: 999px; box-shadow: var(--sombra);
  opacity: 0; transition: opacity .15s ease;
}
.tarjeta-producto:hover .boton-vista-rapida,
.tarjeta-producto:focus-within .boton-vista-rapida { opacity: 1; }

/* ── Filtros del catálogo ────────────────────────────────────────────────── */
.filtros { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 28px; align-items: center; }
.chip {
  border: 1px solid var(--borde); background: #fff; color: var(--texto);
  border-radius: 999px; padding: 8px 16px; font-size: .85rem;
  font-family: var(--fuente-ui); cursor: pointer;
}
.chip:hover { border-color: var(--acento); color: var(--acento); text-decoration: none; }
.chip.activo { background: var(--acento); border-color: var(--acento); color: #fff; }
.buscador { margin-left: auto; }
.buscador input {
  border: 1px solid var(--borde); border-radius: 999px;
  padding: 9px 18px; font-family: var(--fuente-ui); font-size: .9rem;
  width: 210px; background: var(--fondo-alt);
}
.buscador input:focus { outline: 2px solid var(--acento); border-color: transparent; }

/* ── Detalle de producto ─────────────────────────────────────────────────── */
.detalle { display: grid; grid-template-columns: 1.1fr 1fr; gap: 48px; padding: 48px 0; }
.detalle-galeria .foto-grande {
  background: var(--fondo-alt); border-radius: var(--radio);
  aspect-ratio: 1; display: flex; align-items: center; justify-content: center; overflow: hidden;
}
.detalle-galeria .foto-grande img { object-fit: contain; width: 100%; height: 100%; }
.miniaturas { display: flex; gap: 10px; margin-top: 12px; }
.miniaturas img {
  width: 64px; height: 64px; object-fit: cover;
  border-radius: var(--radio-sm); background: var(--fondo-alt); cursor: pointer;
  border: 2px solid transparent;
}
.miniaturas img.activa { border-color: var(--acento); }
.detalle-info .precio { font-size: 1.5rem; font-weight: 800; margin: 8px 0 20px; }
.detalle-info .descripcion { color: var(--texto-suave); }
.selector-variantes { margin: 22px 0; }
.selector-variantes .titulo-selector { font-weight: 800; font-size: .9rem; margin-bottom: 10px; }
.selector-variantes .valor-elegido { font-weight: 300; color: var(--texto-suave); margin-left: 6px; }
.opciones-variante { display: flex; flex-wrap: wrap; gap: 10px; }
.opcion-variante {
  border: 1.5px solid var(--borde); border-radius: var(--radio-sm);
  background: #fff; padding: 10px 16px; cursor: pointer;
  font-family: var(--fuente-ui); font-size: .88rem;
}
.opcion-variante:hover { border-color: var(--texto-suave); }
.opcion-variante.activa { border-color: var(--acento); color: var(--acento); font-weight: 800; }
/* Agotada, pero elegible: quien compra quiere ver el color aunque no haya
   unidades. Antes se apagaba al 40% y no se leía; ahora se marca con el borde
   discontinuo y el tachado, sin sacrificar el contraste del texto. */
.opcion-variante.agotada {
  color: var(--texto-suave); border-style: dashed;
  text-decoration: line-through; text-decoration-thickness: 1px;
}
.opcion-variante.agotada.activa {
  color: var(--acento); border-color: var(--acento); border-style: solid;
}

/* Selector de color: muestra circular de la tinta + nombre.
   El tono llega en --muestra desde core/js/variantes.js. */
.opciones-color { display: flex; flex-wrap: wrap; gap: 10px; }
.opcion-color {
  --muestra: var(--fondo-alt);
  display: inline-flex; align-items: center; gap: 9px;
  border: 1.5px solid var(--borde); border-radius: 999px;
  background: #fff; padding: 5px 15px 5px 6px; cursor: pointer;
  font-family: var(--fuente-ui); font-size: .85rem; color: var(--texto);
}
.opcion-color::before {
  content: ""; width: 20px; height: 20px; border-radius: 50%; flex: none;
  background: var(--muestra); box-shadow: inset 0 0 0 1px rgba(29, 29, 31, .18);
}
.opcion-color:hover { border-color: var(--texto-suave); }
.opcion-color.activa { border-color: var(--acento); color: var(--acento); font-weight: 800; }
.opcion-color.agotada {
  color: var(--texto-suave); border-style: dashed;
  text-decoration: line-through; text-decoration-thickness: 1px;
}
.opcion-color.agotada.activa {
  color: var(--acento); border-color: var(--acento); border-style: solid;
}
/* Compatibilidad: los modelos que acepta el accesorio, como fichas sueltas.
   En lista y no en un párrafo largo porque se lee de un vistazo, que es como
   se consulta —el comprador busca el suyo, no lee los diez—. */
.compatibilidad { margin-top: 26px; }
.compatibilidad h3 {
  font-family: var(--fuente-ui); font-size: .7rem; font-weight: 800;
  letter-spacing: .09em; text-transform: uppercase; color: var(--texto-suave);
  margin: 0 0 9px;
}
.lista-modelos { display: flex; flex-wrap: wrap; gap: 6px; list-style: none; margin: 0; padding: 0; }
.lista-modelos li {
  font-family: var(--fuente-ui); font-size: .78rem; font-weight: 600;
  padding: 5px 11px; border-radius: 999px;
  border: 1px solid var(--borde); color: var(--texto);
}
.compat-linea {
  margin: 0 0 10px; font-size: .78rem; color: var(--texto-suave);
  font-family: var(--fuente-ui);
}

.stock-info { font-size: .85rem; color: var(--texto-suave); margin: 10px 0 20px; }
.stock-info.poco { color: var(--error); }

/* ── Panel lateral del carrito ───────────────────────────────────────────── */
.overlay-carrito {
  position: fixed; inset: 0; background: rgba(29,29,31,.45); z-index: 90;
}
.panel-carrito {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 100;
  width: min(420px, 100vw);
  background: #fff; box-shadow: -12px 0 40px rgba(0,0,0,.18);
  border-radius: 20px 0 0 20px;
  display: flex; flex-direction: column;
  padding: 24px;
}
.panel-carrito h2 { font-family: var(--fuente-ui); font-weight: 800; font-size: 1.15rem; }
.panel-carrito .cerrar {
  position: absolute; top: 18px; right: 18px;
  background: none; border: none; cursor: pointer; color: var(--texto-suave);
  font-size: 1rem; font-family: var(--fuente-ui);
}
.lineas-carrito { flex: 1; overflow-y: auto; margin: 12px 0; }
.linea-carrito {
  display: flex; gap: 14px; padding: 14px 0;
  border-bottom: 1px solid var(--borde); align-items: center;
}
.linea-carrito .mini-foto {
  width: 56px; height: 56px; border-radius: var(--radio-sm);
  background: var(--fondo-alt); overflow: hidden; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
}
.linea-carrito .mini-foto img { object-fit: cover; width: 100%; height: 100%; }
.linea-carrito .datos { flex: 1; min-width: 0; }
.linea-carrito .nombre { font-weight: 800; font-size: .88rem; }
.linea-carrito .variante { color: var(--texto-suave); font-size: .8rem; }
.linea-carrito .precio-linea { font-size: .88rem; white-space: nowrap; }
.control-cantidad { display: inline-flex; align-items: center; gap: 8px; margin-top: 6px; }
.control-cantidad button {
  width: 26px; height: 26px; border-radius: 50%;
  border: 1px solid var(--borde); background: #fff; cursor: pointer;
  font-size: .9rem; line-height: 1;
}
.control-cantidad button:hover { border-color: var(--acento); color: var(--acento); }
.quitar-linea { background: none; border: none; color: var(--texto-suave); cursor: pointer; font-size: .75rem; padding: 0; }
.quitar-linea:hover { color: var(--error); }
.resumen-carrito { border-top: 1px solid var(--borde); padding-top: 14px; }
.fila-total { display: flex; justify-content: space-between; font-size: .92rem; margin-bottom: 6px; }
.fila-total.grande { font-weight: 800; font-size: 1.05rem; }
.nota-envio { font-size: .8rem; color: var(--texto-suave); margin: 6px 0 12px; }
.carrito-vacio { text-align: center; color: var(--texto-suave); padding: 48px 0; }

/* ── Checkout ────────────────────────────────────────────────────────────── */
.checkout { display: grid; grid-template-columns: 1.2fr 1fr; gap: 48px; padding: 40px 0 64px; align-items: start; }
.campo {
  width: 100%; border: 1px solid var(--borde); border-radius: var(--radio-sm);
  background: var(--fondo-alt); padding: 13px 16px;
  font-family: var(--fuente-ui); font-size: .95rem; color: var(--texto);
}
.campo:focus { outline: 2px solid var(--acento); border-color: transparent; background: #fff; }
.fila-campos { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin-bottom: 14px; }
.fila-campos.una { grid-template-columns: 1fr; }
.error-campo { color: var(--error); font-size: .8rem; margin: 4px 0 0; }
.metodos-pago { display: flex; gap: 12px; margin: 14px 0 6px; flex-wrap: wrap; }
.metodo-pago {
  border: 1.5px solid var(--borde); border-radius: var(--radio-sm);
  padding: 12px 20px; cursor: pointer; font-size: .9rem; background: #fff;
  display: flex; align-items: center; gap: 8px;
}
.metodo-pago.activo { border-color: var(--acento); color: var(--acento); font-weight: 800; }
.metodo-pago input { accent-color: var(--acento); }
.ayuda-metodo { color: var(--texto-suave); font-size: .85rem; margin: 8px 0 0; }
.resumen-pedido {
  background: var(--fondo-alt); border-radius: var(--radio);
  padding: 26px; position: sticky; top: 84px;
}
.resumen-pedido h2 { font-family: var(--fuente-ui); font-weight: 800; font-size: 1.05rem; }
.resumen-pedido .fila { display: flex; justify-content: space-between; font-size: .9rem; margin-bottom: 8px; gap: 12px; }
.resumen-pedido .fila span:first-child { color: var(--texto-suave); }
.resumen-pedido .fila.total { font-weight: 800; font-size: 1.05rem; border-top: 1px solid var(--borde); padding-top: 12px; margin-top: 12px; }
.resumen-pedido .fila.total span:first-child { color: var(--texto); }

/* ── Confirmación / estados ──────────────────────────────────────────────── */
.pagina-estado { text-align: center; padding: 72px 20px; max-width: 560px; margin: 0 auto; }
.icono-estado {
  width: 64px; height: 64px; border-radius: 50%; margin: 0 auto 20px;
  background: var(--acento); color: #fff;
  display: flex; align-items: center; justify-content: center;
}
.icono-estado.error { background: var(--error); }
.icono-estado.espera { background: #8e44ad; }
.tarjeta-resumen {
  background: var(--fondo-alt); border-radius: var(--radio);
  padding: 22px 26px; text-align: left; margin-top: 28px;
}
.tarjeta-resumen p { margin: 4px 0; color: var(--texto-suave); font-size: .92rem; }
.tarjeta-resumen p b { color: var(--texto); }

/* ── Línea de tiempo del pedido (rastrear) ───────────────────────────────── */
.timeline { list-style: none; padding: 0; margin: 24px 0; text-align: left; }
.timeline li {
  position: relative;
  display: flex; gap: 14px; padding: 10px 0;
  color: var(--texto-suave);
}
/* Tres marcas distintas para tres significados. Un paso cumplido lleva ✓, el
   actual es un punto lleno que late, y lo que falta es un aro vacío: el estado
   del pedido se entiende de un vistazo, sin leer una palabra. */
.timeline .punto {
  position: relative;
  width: 14px; height: 14px; border-radius: 50%; box-sizing: border-box;
  background: transparent; border: 2px solid var(--borde);
  margin-top: 5px; flex-shrink: 0;
  transition: background var(--anim-corta), border-color var(--anim-corta);
}
.timeline li.hecho { color: var(--texto); }
.timeline li.hecho .punto { background: var(--acento); border-color: var(--acento); }

/* ✓ en los pasos ya superados (los que tienen otro cumplido detrás). */
.timeline li.hecho:has(+ li.hecho) .punto::after,
.timeline li.hecho:last-child .punto::after {
  content: "";
  position: absolute; left: 3px; top: 0;
  width: 3px; height: 6px;
  border: solid #fff; border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

/* El paso actual: sin ✓, porque no está terminado. Late hacia afuera para
   decir «tu pedido está aquí ahora». El aro es un pseudo-elemento aparte y no
   un box-shadow, para animar solo transform y opacidad. */
.timeline li.hecho:has(+ li:not(.hecho)) .punto::before {
  content: "";
  position: absolute; inset: -2px;
  border-radius: 50%;
  /* Anillo hueco, no disco: al crecer no tapa el punto y no depende del
     orden de apilado, que un ancestro con fondo podría echar a perder. */
  border: 2px solid var(--acento);
}
@media (prefers-reduced-motion: no-preference) {
  .timeline li.hecho:has(+ li:not(.hecho)).vista .punto::before {
    animation: pulso-punto 2.4s var(--anim-entrada) 1s infinite;
  }
}
@keyframes pulso-punto {
  0%        { transform: scale(1);   opacity: .5; }
  70%, 100% { transform: scale(2.8); opacity: 0; }
}

/* El texto del paso actual pesa más: es la línea que el comprador busca. */
.timeline li.hecho:has(+ li:not(.hecho)) { font-weight: 700; }

/* El tramo entre dos pasos. Se pinta según el paso de DESTINO, no el de
   origen: el trecho que lleva a algo que todavía no ocurre no está recorrido.
   Los tres estados —hecho, en curso y pendiente— se leen sin texto. */
.timeline li:not(:last-child)::before {
  content: "";
  position: absolute; left: 6px; top: 31px; bottom: -4px;
  width: 2px; border-radius: 2px;
  background: var(--borde);
  transform-origin: top;
  transition: transform var(--anim-suave) var(--anim-entrada);
}
/* Tramo recorrido: los dos extremos están cumplidos. */
.timeline li.hecho:has(+ li.hecho)::before { background: var(--acento); }
/* Tramo en curso: sale del último paso cumplido y se desvanece hacia el que
   falta. El degradado dice «vamos por aquí» sin necesidad de moverse. */
.timeline li.hecho:has(+ li:not(.hecho))::before {
  background: linear-gradient(var(--acento), var(--borde));
}
/* El tramo en curso respira: dice que el pedido se está moviendo ahora mismo,
   no que se quedó a medias. Solo opacidad —nada que fuerce repintado— y
   quieto para quien pidió menos movimiento. */
@media (prefers-reduced-motion: no-preference) {
  .timeline li.hecho:has(+ li:not(.hecho)).vista::before {
    animation: latido-tramo 2.6s ease-in-out 1.1s infinite;
  }
}
@keyframes latido-tramo {
  0%, 100% { opacity: 1; }
  50%      { opacity: .45; }
}

/* Carga progresiva: cada tramo crece desde su punto hacia el siguiente, en
   cascada. El retardo va después de la entrada del punto que lo origina
   (0/90/180 ms), para que el trazo parezca salir de él. */
.anim .timeline li::before { transform: scaleY(0); }
.timeline li.vista::before { transform: scaleY(1); }
.timeline li:nth-child(1)::before { transition-delay: 260ms; }
.timeline li:nth-child(2)::before { transition-delay: 350ms; }
.timeline li:nth-child(3)::before { transition-delay: 440ms; }
.timeline li:nth-child(4)::before { transition-delay: 530ms; }

/* Dónde va el pedido AHORA: el último paso cumplido lleva un halo. `:has`
   lo resuelve sin tocar la plantilla; donde no exista, simplemente no se ve. */
.timeline li.hecho:last-child .punto {
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--acento) 20%, transparent);
}

/* ── Datos bancarios (transferencia) ─────────────────────────────────────── */
.datos-banco {
  background: var(--fondo-alt); border-radius: var(--radio);
  padding: 22px 26px; margin: 20px 0; text-align: left;
}
.datos-banco dt { font-size: .78rem; color: var(--texto-suave); margin-top: 10px; }
.datos-banco dd { margin: 0; font-weight: 800; }

/* ── Páginas estáticas ───────────────────────────────────────────────────── */
.pagina-texto { max-width: 760px; margin: 0 auto; padding: 48px 20px 72px; }
.pagina-texto h2 { margin-top: 40px; font-size: 1.3rem; }
.pagina-texto p, .pagina-texto li { color: var(--texto-suave); }

/* ── Mensajes flash ──────────────────────────────────────────────────────── */
.mensajes { position: fixed; top: 72px; left: 50%; translate: -50% 0; z-index: 200; width: min(480px, 92vw); }
.mensaje {
  background: var(--texto); color: #fff; border-radius: var(--radio-sm);
  padding: 12px 18px; font-size: .9rem; margin-bottom: 8px; box-shadow: var(--sombra);
}
.mensaje.error { background: var(--error); }

/* ── Footer ──────────────────────────────────────────────────────────────── */
.footer { background: var(--fondo-alt); margin-top: 72px; padding: 48px 0 28px; }
.footer-columnas { display: grid; grid-template-columns: repeat(4, 1fr); gap: 24px; }
.footer h4 { font-family: var(--fuente-ui); font-weight: 800; font-size: .88rem; margin: 0 0 12px; }
.footer ul { list-style: none; padding: 0; margin: 0; }
.footer li { margin-bottom: 8px; }
.footer a, .footer span { color: var(--texto-suave); font-size: .85rem; }
.footer-logo img { height: 20px; margin-bottom: 14px; }
.footer-legal {
  border-top: 1px solid var(--borde); margin-top: 36px; padding-top: 18px;
  color: var(--texto-suave); font-size: .8rem;
}

/* ── Popup vista rápida ──────────────────────────────────────────────────── */
.overlay-popup {
  position: fixed; inset: 0; background: rgba(29,29,31,.5); z-index: 110;
  display: flex; align-items: center; justify-content: center; padding: 20px;
}
.popup-vista-rapida {
  background: #fff; border-radius: 20px; overflow: hidden;
  display: grid; grid-template-columns: 1fr 1fr;
  max-width: 640px; width: 100%; box-shadow: 0 24px 80px rgba(0,0,0,.3);
}
.popup-vista-rapida .foto {
  background: var(--fondo-alt); aspect-ratio: 1;
  display: flex; align-items: center; justify-content: center; overflow: hidden;
}
.popup-vista-rapida .foto img { object-fit: cover; width: 100%; height: 100%; }
.popup-vista-rapida .info { padding: 26px; position: relative; }
.popup-vista-rapida .cerrar {
  position: absolute; top: 14px; right: 16px;
  background: none; border: none; color: var(--texto-suave); cursor: pointer; font-size: .85rem;
}

/* ══ Responsive ═══════════════════════════════════════════════════════════ */
@media (max-width: 1024px) {
  .grilla-productos { grid-template-columns: repeat(3, 1fr); }
}

@media (max-width: 768px) {
  .nav-principal {
    display: none;
    position: absolute; top: 60px; left: 0; right: 0;
    background: #fff; border-bottom: 1px solid var(--borde);
    flex-direction: column; gap: 0; padding: 8px 20px 16px;
  }
  .nav-principal.abierto { display: flex; }
  .nav-principal a { padding: 10px 0; }
  .boton-menu { display: block; }
  .header-acciones a { font-size: .78rem; white-space: nowrap; }
  .grilla-productos { grid-template-columns: repeat(2, 1fr); gap: 14px; }
  .detalle, .checkout { grid-template-columns: 1fr; gap: 28px; }
  .resumen-pedido { position: static; }
  .badges { grid-template-columns: 1fr; gap: 32px; }
  .tarjetas-marca { grid-template-columns: 1fr; }
  .footer-columnas { grid-template-columns: 1fr 1fr; }
  .popup-vista-rapida { grid-template-columns: 1fr; max-width: 400px; }
  .hero { padding: 48px 0 24px; }
  .hero-imagen.escena-3d { min-height: 360px; padding: 28px 16px 48px; }
  .hero-imagen.escena-3d .hero-pieza { max-width: 220px; }
  .hero-piso { width: 165px; bottom: 30px; }
  .buscador { margin-left: 0; width: 100%; }
  .buscador input { width: 100%; }
}

@media (max-width: 400px) {
  .fila-campos { grid-template-columns: 1fr; }
  .contenedor { padding: 0 14px; }
}

/* ══════════════════════════════════════════════════════════════════════════
   CAPA DE ANIMACIÓN
   ══════════════════════════════════════════════════════════════════════════
   Adaptada de la maqueta aprobada. Todo lo de aquí abajo es ADITIVO: reescribe
   presentación, nunca lógica. Reglas del bloque:

   · Un único juego de tiempos. Ningún componente inventa su propia duración.
   · Nada arranca oculto "a secas": los estados iniciales cuelgan de .anim, que
     el JS añade a <html> SOLO tras comprobar IntersectionObserver y que el
     usuario no pidió movimiento reducido. Sin JS se ve el 100% del contenido.
   · Se anima transform, opacity, clip-path y filter. La única excepción es el
     padding del header, y está justificada donde ocurre.
   ══════════════════════════════════════════════════════════════════════════ */

:root {
  --anim-corta:     .2s cubic-bezier(.7, 0, .3, 1);
  --anim-rapida:    .3s cubic-bezier(.7, 0, .3, 1);
  --anim-principal: .5s cubic-bezier(.3, 1, .3, 1);
  --anim-suave:     .7s cubic-bezier(.7, 0, .3, 1);
  --anim-nav:       .5s cubic-bezier(.6, 0, .4, 1);
  --anim-drawer:    .6s cubic-bezier(.7, 0, .2, 1);
  --anim-relleno:   .6s cubic-bezier(.7, 0, .3, 1);
  --anim-entrada:   cubic-bezier(.16, 1, .3, 1);

  --entrada-fade-up:       1500ms;
  --entrada-fade-up-large: 1000ms;
  --entrada-zoom-out:      1300ms;
  --entrada-fade-in:       1500ms;

  --carta-recorrido: 50px;
  --carta-dur: 500ms;
  --carta-paso: 100ms;

  --texto-tenue: #c7ccd6;
  --alto-header: 60px;
}
@media (max-width: 767px) {
  :root { --carta-recorrido: 30px; --carta-dur: 300ms; --carta-paso: 50ms; }
}

/* ── Estados iniciales de las entradas ───────────────────────────────────── */
.anim [data-animar] { opacity: 0; }
.anim [data-animar="fade-up"]       { transform: translateY(2rem); }
.anim [data-animar="fade-up-large"] { transform: translateY(90%); }
.anim [data-animar="zoom-out"]      { transform: scale(1.3); }

[data-animar] {
  transition-property: opacity, transform;
  transition-timing-function: var(--anim-entrada);
  transition-duration: var(--entrada-fade-up);
}
[data-animar="fade-up-large"] { transition-duration: var(--entrada-fade-up-large); }
[data-animar="zoom-out"]      { transition-duration: var(--entrada-zoom-out); }
[data-animar="fade-in"]       { transition-duration: var(--entrada-fade-in); }
[data-animar].vista { opacity: 1; transform: none; }

.anim img[data-fade]:not(.cargada) { opacity: 0; }
img[data-fade] { transition: opacity var(--anim-suave); }

.anim .tarjeta-producto[data-carta] { opacity: 0; transform: translateY(var(--carta-recorrido)); }
.tarjeta-producto[data-carta] {
  transition-property: opacity, transform;
  transition-timing-function: var(--anim-entrada);
  transition-duration: var(--carta-dur);
}
.tarjeta-producto[data-carta].vista { opacity: 1; transform: none; }

/* Salida de emergencia: sin JS, sin IntersectionObserver o con movimiento
   reducido el contenido se ENTREGA visible, sin transición a medias. */
.sin-entradas .timeline li::before,
.sin-entradas .movimiento::before {
  transform: none !important;
  transition: none !important;
}
.sin-entradas [data-animar],
.sin-entradas .tarjeta-producto[data-carta],
.sin-entradas img[data-fade],
.sin-entradas .nav-principal a {
  opacity: 1 !important;
  transform: none !important;
  transition: none !important;
}

/* ── Marca de agua ───────────────────────────────────────────────────────────
   Hermana directa de <body> y NUNCA contenedora del contenido: lleva transform
   para la deriva, y un ancestro transformado se convertiría en el bloque
   contenedor de .panel-carrito y .overlay-popup (ambos fixed) descolocándolos. */
.marca-agua { position: fixed; inset: 0; z-index: 0; pointer-events: none; overflow: hidden; }
.marca-agua-txt {
  position: absolute;
  font-family: var(--fuente-titulo);
  font-size: clamp(30vh, 46vw, 70vh);
  line-height: .8;
  color: var(--acento);
  opacity: .05;
  white-space: nowrap;
  transition: opacity var(--anim-suave), transform var(--anim-suave);
}
.marca-agua-txt[data-pos="centro"] { left: 50%; top: 50%; transform: translate(-50%, -50%); }
.marca-agua-txt[data-pos="izq"]    { left: -6vw; top: 50%; transform: translateY(-50%); }
.marca-agua-txt[data-pos="der"]    { right: -6vw; top: 50%; transform: translateY(-50%); }
.marca-agua-txt[data-pos="abajo"]  { left: 50%; bottom: -14vh; transform: translateX(-50%); }
.marca-agua-txt[data-pos="grande"] { left: 50%; top: 50%; transform: translate(-50%, -50%) scale(1.25); }
.js .marca-agua-txt.saliendo { opacity: 0; }
.js .marca-agua-txt[data-pos="centro"].saliendo { transform: translate(-50%, calc(-50% + 20px)); }
.js .marca-agua-txt[data-pos="izq"].saliendo    { transform: translateY(calc(-50% + 20px)); }
.js .marca-agua-txt[data-pos="der"].saliendo    { transform: translateY(calc(-50% + 20px)); }
.js .marca-agua-txt[data-pos="abajo"].saliendo  { transform: translate(-50%, 20px); }
.js .marca-agua-txt[data-pos="grande"].saliendo { transform: translate(-50%, calc(-50% + 20px)) scale(1.25); }
@media (max-width: 760px) { .marca-agua-txt { font-size: clamp(22vh, 52vw, 44vh); opacity: .035; } }

/* El contenido se apila por encima elemento a elemento, sin envolverlo. */
.barra-novedades, .header, main, .footer, .mensajes { position: relative; z-index: 1; }
.header { z-index: 50; }

/* ── Botones: relleno circular ───────────────────────────────────────────────
   Un círculo mucho mayor que el botón, aparcado abajo, que sube y lo llena. Al
   salir el puntero NO vuelve por donde vino: sigue de largo hacia arriba. Va en
   ::before para no añadir ni un elemento al marcado — los botones del proyecto
   llevan hx-* y Alpine y su contenido no se toca. */
.boton {
  --btn-relleno: var(--acento-oscuro);
  --btn-texto-hover: #fff;
  position: relative;
  overflow: hidden;
  isolation: isolate;
  transition: color var(--anim-principal) .1s, border-color var(--anim-corta);
}
.boton::before {
  content: "";
  position: absolute; z-index: -1;
  top: -50%; left: -25%;
  width: 150%; height: 200%;
  border-radius: 50%;
  background: var(--btn-relleno);
  transform: translate3d(0, 76%, 0);
  transition: transform var(--anim-relleno);
}
@media (hover: hover) {
  .boton:hover, .boton:focus-visible { color: var(--btn-texto-hover); }
  .boton:hover::before, .boton:focus-visible::before { transform: translate3d(0, 0, 0); }
}
.boton.sale::before { transform: translate3d(0, -76%, 0); }
.boton.sin-trans::before { transition: none; }
/* El anillo de foco tiene que sobrevivir al overflow:hidden del botón. */
.boton:focus-visible { outline: 2px solid var(--acento); outline-offset: 3px; }
/* Anulan el levantamiento anterior: ahora el movimiento lo lleva el relleno. */
.boton:hover { transform: none; box-shadow: none; }
.boton-primario:hover { background: var(--acento); box-shadow: none; }
.boton-secundario { --btn-relleno: var(--texto); --btn-texto-hover: #fff; }
.boton-secundario:hover { border-color: var(--texto); }
.boton-whatsapp { --btn-relleno: #1da851; }
.boton-whatsapp:hover { background: #25d366; box-shadow: none; }
.boton-bloque { display: block; }
.boton[disabled]::before { transform: translate3d(0, 76%, 0); }

/* Confirmación de «añadido»: el ancho no puede cambiar o la ficha salta, así
   que el ✓ se superpone y el texto se desvanece debajo. */
.boton .tick {
  position: absolute; inset: 0; z-index: 2;
  display: grid; place-items: center;
  opacity: 0; transition: opacity var(--anim-rapida);
  /* Color propio y NO heredado: al confirmar, el botón pone su texto en
     transparent para ocultar la etiqueta, y el ✓ heredaría esa transparencia
     y no se vería nunca. */
  color: var(--btn-tick, #fff);
}
.boton.confirmado .tick { opacity: 1; }
.boton.confirmado { color: transparent; }
.boton-secundario { --btn-tick: var(--texto); }
@media (hover: hover) { .boton-secundario:hover .tick { color: #fff; } }

/* Enlaces de texto: subrayado que crece. Con border-bottom solo se puede
   animar el color, no el crecimiento; con background-size sí. */
.hero-enlaces a, .tarjeta-marca a, .footer-columnas a {
  background-image: linear-gradient(currentColor, currentColor);
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 0% 1px;
  padding-bottom: 2px;
  transition: background-size var(--anim-principal), color var(--anim-corta);
}
.hero-enlaces a:hover, .tarjeta-marca a:hover, .footer-columnas a:hover {
  background-size: 100% 1px;
  text-decoration: none;
}

/* ── Flechas de navegación: un solo componente ───────────────────────────────
   Las usan la barra de novedades, la banda de marcas y «Más vendidos». Mismo
   tamaño y el mismo relleno circular que el resto: entra en el sistema en vez
   de ser una excepción. */
.flecha-nav {
  position: relative; overflow: hidden; isolation: isolate;
  width: 40px; height: 40px; flex: 0 0 auto;
  display: grid; place-items: center;
  border: 1px solid var(--borde);
  background: var(--fondo);
  border-radius: 999px;
  cursor: pointer;
  color: var(--texto);
  transition: color var(--anim-principal) .1s, border-color var(--anim-corta), opacity var(--anim-rapida);
}
.flecha-nav::before {
  content: "";
  position: absolute; z-index: -1;
  top: -50%; left: -25%;
  width: 150%; height: 200%;
  border-radius: 50%;
  background: var(--acento);
  transform: translate3d(0, 76%, 0);
  transition: transform var(--anim-relleno);
}
@media (hover: hover) {
  .flecha-nav:not(:disabled):hover { color: #fff; border-color: var(--acento); }
  .flecha-nav:not(:disabled):hover::before { transform: translate3d(0, 0, 0); }
}
.flecha-nav.sale:not(:disabled)::before { transform: translate3d(0, -76%, 0); }
.flecha-nav.sin-trans::before { transition: none; }
.flecha-nav:disabled { opacity: .35; cursor: default; }
.flecha-nav:disabled::before { transform: translate3d(0, 76%, 0); }
.flecha-nav[hidden] { display: none; }

/* ── Pasarelas: desplazamiento nativo ────────────────────────────────────────
   No hay arrastre propio: el navegador ya sabe hacerlo con el dedo y
   reimplementarlo solo añade formas de romper el scroll de la página. */
.desliz-envoltura { position: relative; flex: 1; min-width: 0; }
.desliz {
  display: flex;
  overflow-x: auto;
  /* proximity y no mandatory: con pocos elementos el recorrido total puede ser
     menor que la separación entre anclajes, y entonces el único punto válido es
     el origen — con mandatory el navegador devuelve el scroll a 0 y las flechas
     parecen no funcionar. proximity da el mismo imán sin esa trampa. */
  scroll-snap-type: x proximity;
  scroll-behavior: smooth;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.desliz::-webkit-scrollbar { display: none; }
.desliz > * { scroll-snap-align: start; flex: 0 0 auto; }
.desliz-envoltura::before,
.desliz-envoltura::after {
  content: "";
  position: absolute; top: 0; bottom: 0; width: 48px;
  z-index: 2; pointer-events: none; opacity: 0;
  transition: opacity var(--anim-rapida);
}
.desliz-envoltura::before { left: 0; background: linear-gradient(90deg, var(--fondo), rgba(255,255,255,0)); }
.desliz-envoltura::after  { right: 0; background: linear-gradient(270deg, var(--fondo), rgba(255,255,255,0)); }
.desliz-envoltura.hay-izq::before { opacity: 1; }
.desliz-envoltura.hay-der::after  { opacity: 1; }

/* Controles centrados debajo: el título de sección conserva su eje. */
.desliz-controles { display: flex; align-items: center; justify-content: center; gap: 16px; margin-top: 28px; }
.desliz-progreso { width: 140px; height: 3px; border-radius: 999px; background: var(--borde); overflow: hidden; }
.desliz-progreso span {
  display: block; height: 100%; border-radius: 999px;
  background: var(--texto);
  transform: scaleX(var(--avance, .3));
  transform-origin: left;
  transition: transform var(--anim-rapida);
}
.desliz--fichas { gap: 22px; padding: 2px; }
.desliz--fichas > * { width: calc((100% - 66px) / 4); }
@media (max-width: 980px) { .desliz--fichas > * { width: calc((100% - 22px) / 2); } }
@media (max-width: 720px) {
  .desliz--fichas { gap: 16px; }
  .desliz--fichas > * { width: calc((100% - 16px) / 1.2); }
}

/* ── Promociones vigentes ────────────────────────────────────────────────────
   Tarjeta grande con la foto a sangre y el texto encima, al estilo de las
   franjas editoriales de Apple. Dos por pantalla en escritorio: menos que eso
   las convierte en banners y más las vuelve ilegibles. */
.desliz--promos { gap: 20px; padding: 2px; }
.desliz--promos > * { width: calc((100% - 20px) / 2); }
@media (max-width: 980px) { .desliz--promos > * { width: calc((100% - 16px) / 1.15); } }

.promo { border-radius: var(--radio-lg, 20px); overflow: hidden; }
.promo-enlace {
  position: relative; display: block; aspect-ratio: 3 / 2;
  color: #fff; text-decoration: none; background: #17181c;
  border-radius: inherit; overflow: hidden;
}
.promo-fondo {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; display: block;
  transition: transform var(--anim-larga, .6s) ease;
}
.promo-enlace:hover .promo-fondo { transform: scale(1.035); }

/* La capa oscura solo en la mitad inferior: si cubre toda la foto, la promo
   deja de verse y queda un rectángulo gris con letras. */
.promo-capa {
  position: absolute; inset: 0; z-index: 1;
  display: flex; flex-direction: column; justify-content: flex-end;
  gap: 6px; padding: 24px;
  background: linear-gradient(to top, rgba(0,0,0,.78) 0%, rgba(0,0,0,.45) 38%, rgba(0,0,0,0) 68%);
}
.promo-etiqueta {
  margin: 0; font-family: var(--fuente-ui); font-size: .68rem; font-weight: 800;
  letter-spacing: .1em; text-transform: uppercase; opacity: .85;
}
.promo-titulo {
  margin: 0; font-size: clamp(1.25rem, 2.4vw, 1.9rem); line-height: 1.08;
  letter-spacing: -.02em; text-wrap: balance;
}
.promo-precios { margin: 2px 0 0; display: flex; align-items: baseline; gap: 9px; }
.promo-precio { font-family: var(--fuente-ui); font-weight: 800; font-size: 1.15rem; }
.promo-antes { font-size: .85rem; opacity: .6; }

.promo-pie { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 8px; }
.promo-boton {
  flex: 0 0 auto;
  font-family: var(--fuente-ui); font-size: .8rem; font-weight: 700;
  padding: 8px 17px; border-radius: 999px;
  background: #fff; color: #1d1d1f;
  transition: background var(--anim-corta), transform var(--anim-corta);
}
.promo-enlace:hover .promo-boton { background: #e9e9ec; }
.promo-desc { font-size: .82rem; opacity: .88; }

/* Sin enlace la tarjeta es solo un aviso: no debe fingir que se puede pulsar. */
.promo-enlace:not([href]) { cursor: default; }

@media (max-width: 720px) {
  .promo-capa { padding: 18px; }
  .promo-pie { gap: 9px; }
}

@media (prefers-reduced-motion: reduce) {
  .promo-fondo, .promo-enlace:hover .promo-fondo { transition: none; transform: none; }
}

/* ── Barra de novedades ──────────────────────────────────────────────────────
   Se entrega con el primer mensaje ya escrito en el HTML: sin JS sigue diciendo
   algo útil y el rotado es una mejora encima.

   Los mensajes se apilan en UNA celda de grid en lugar de con position:absolute.
   Así el contenedor toma la altura del mensaje más alto y, si uno se parte en
   dos líneas en móvil, no se sale de la barra ni se cruza con las flechas. */
.barra-novedades { background: var(--fondo-alt); border-bottom: 1px solid var(--borde); }
.barra-novedades[hidden] { display: none; }
.barra-novedades-inner { display: flex; align-items: center; gap: 10px; min-height: 52px; }
.barra-mensajes { display: grid; flex: 1; min-width: 0; text-align: center; font-size: .82rem; color: var(--texto); }
.barra-msg {
  grid-area: 1 / 1;
  align-self: center;
  padding: 6px 0;
  transition: opacity var(--anim-suave), transform var(--anim-suave);
}
.barra-msg.sale  { opacity: 0; transform: translateY(6px); pointer-events: none; }
.barra-msg.entra { opacity: 0; transform: translateY(-6px); }
.barra-cerrar {
  border: 0; background: none; cursor: pointer;
  color: var(--texto-suave); font-size: .78rem; line-height: 1;
  padding: 6px 8px; font-family: var(--fuente-ui);
  transition: color var(--anim-corta);
}
.barra-cerrar:hover { color: var(--texto); }
@media (max-width: 560px) {
  .barra-novedades-inner { gap: 4px; }
  .flecha-nav[data-nov] { width: 32px; height: 32px; }
  .barra-mensajes { font-size: .74rem; }
}

/* ── Encabezado de dos umbrales ──────────────────────────────────────────────
   La altura de .header-inner es la única propiedad de layout que se anima en
   todo el archivo, y es una excepción deliberada: compactar con transform
   desplazaría también el logo y el menú de dentro, y se vería como un salto.
   Es un único elemento de altura fija, así que el coste está acotado. */
.header {
  transition: box-shadow var(--anim-nav);
}
.header.compacto { box-shadow: var(--sombra); }
.header.compacto .header-inner { height: 50px; }
.header-inner { transition: height var(--anim-nav); }
.nav-principal { transition: opacity var(--anim-nav), transform var(--anim-nav); }
/* Segundo umbral: se desvanece pero NO se hace display:none, para que el orden
   de tabulación no cambie nunca. */
.header.nav-oculta .nav-principal { opacity: 0; transform: translateY(-6px); pointer-events: none; }
.header.nav-oculta:focus-within .nav-principal { opacity: 1; transform: none; pointer-events: auto; }
.nav-principal a { transition: color var(--anim-corta); }
.header-acciones a { transition: color var(--anim-corta); }
.header-acciones a:hover { color: var(--acento); text-decoration: none; }
.boton-carrito { transition: transform var(--anim-corta), color var(--anim-corta); }
.boton-carrito:hover { color: var(--acento); }
.boton-carrito:active { transform: scale(.92); }
.logo img { transition: opacity var(--anim-corta); }
.logo:hover img { opacity: .65; }

/* Latido del contador: confirma la acción sin robar atención. */
@keyframes latido {
  0%   { transform: scale(1); }
  40%  { transform: scale(1.2); }
  100% { transform: scale(1); }
}
.contador-carrito.late { animation: latido 450ms cubic-bezier(.3, 1, .3, 1); }

/* Menú móvil en cascada: la opacidad llega mucho antes que el movimiento
   (1s frente a 2s). El enlace ya se lee mientras todavía se acomoda.

   Va con @keyframes y no con transition a propósito: el menú alterna entre
   display:none y display:flex, y una transición sobre un elemento que acaba de
   pasar a mostrarse no tiene estado inicial que interpolar — no se vería nada.
   Una animación sí arranca al mostrarse. Así no hay que tocar el responsive
   que ya existe. */
@keyframes menu-entra {
  from { opacity: 0; transform: translateX(40px); }
  to   { opacity: 1; transform: none; }
}
/* El menú de hamburguesa entra a 900px y no a 768px: con seis enlaces más
   «Rastrear pedido» y el carrito, la fila del encabezado se desbordaba entre
   769 y ~830px y aparecía scroll horizontal. Estas reglas adelantan solo lo
   del encabezado; el resto del bloque responsive sigue en su breakpoint. */
@media (max-width: 900px) {
  .nav-principal {
    display: none;
    position: absolute; top: 100%; left: 0; right: 0;
    background: #fff; border-bottom: 1px solid var(--borde);
    flex-direction: column; gap: 0; padding: 8px 20px 16px;
    box-shadow: var(--sombra);
  }
  .nav-principal.abierto { display: flex; }
  .nav-principal a { padding: 10px 0; }
  .boton-menu { display: block; }
  .header-acciones a { font-size: .82rem; white-space: nowrap; }

  /* Cascada de entrada. Los retardos van explícitos porque CSS no sabe
     multiplicar el índice de :nth-child; el último tramo los agrupa para que
     añadir un enlace nunca deje uno sin retardo. */
  .anim .nav-principal.abierto a {
    animation: menu-entra 1s var(--anim-entrada) backwards;
  }
  .anim .nav-principal.abierto a:nth-child(2) { animation-delay: .06s; }
  .anim .nav-principal.abierto a:nth-child(3) { animation-delay: .12s; }
  .anim .nav-principal.abierto a:nth-child(4) { animation-delay: .18s; }
  .anim .nav-principal.abierto a:nth-child(5) { animation-delay: .24s; }
  .anim .nav-principal.abierto a:nth-child(6) { animation-delay: .30s; }
  .anim .nav-principal.abierto a:nth-child(7) { animation-delay: .36s; }
  .anim .nav-principal.abierto a:nth-child(n+8) { animation-delay: .42s; }
}

/* ── Tarjeta de producto ─────────────────────────────────────────────────────
   Tres cosas a la vez y con la MISMA curva: la foto a 1.05 exacto (1.1 se ve
   barato), crossfade a la segunda foto y la vista rápida entrando por
   opacidad. Nada rebota, nada se levanta. */
.tarjeta-producto .foto img {
  transition: transform var(--anim-principal), opacity var(--anim-principal);
}
.tarjeta-producto:hover .foto img { transform: scale(1.05); }
.tarjeta-producto .foto .foto-b { position: absolute; inset: 0; opacity: 0; }
.tarjeta-producto:hover .foto .foto-a { opacity: 0; }
.tarjeta-producto:hover .foto .foto-b { opacity: 1; }
.boton-vista-rapida { transition: opacity var(--anim-principal); }
/* En táctil no hay hover: si no se muestra siempre, queda un botón inalcanzable
   en el teléfono del cliente. */
@media (hover: none) { .boton-vista-rapida { opacity: 1; } }
.tarjeta-marca { transition: transform var(--anim-principal), box-shadow var(--anim-principal); }

/* ── Banda de marcas: fila quieta que el usuario mueve a mano ────────────────
   No es un carrusel infinito, es una lista: por eso las flechas se apagan en
   los extremos en vez de dar la vuelta. */
.banda { border-block: 1px solid var(--borde); padding: 16px 0; }
.banda-fila { display: flex; align-items: center; gap: 12px; }
.banda .desliz { gap: 34px; align-items: center; }
.banda a {
  color: var(--texto-suave);
  font-weight: 800; font-size: 1.1rem;
  white-space: nowrap; padding: 4px 0;
  transition: color var(--anim-corta);
}
.banda a:hover { color: var(--texto); text-decoration: none; }

/* ── Selector de categoría ───────────────────────────────────────────────────
   La sección es alta y dentro va un bloque sticky: el activo avanza con el
   scroll de la página, sin secuestrarlo. Al pulsar un título NO se cambia el
   activo a mano — se desplaza hasta su posición y el mismo cálculo del scroll
   decide. Así clic y scroll comparten un único estado. */
.selector { position: relative; }
.js .selector.alto { height: 360vh; }
.selector-sticky { padding: 64px 0; }
.js .selector.alto .selector-sticky {
  position: sticky; top: var(--alto-header);
  height: calc(100vh - var(--alto-header));
  display: flex; align-items: center;
  padding: 0;
}
.selector-grid {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: clamp(28px, 5vw, 64px); align-items: center;
  width: 100%;
}
.selector-foto {
  position: relative; aspect-ratio: 4 / 5; max-height: 62vh;
  border-radius: var(--radio); background: var(--fondo-alt); overflow: hidden;
}
/* Dos capas apiladas que hacen crossfade. El nodo de la imagen nunca se quita
   ni se repone: eso provocaría un parpadeo en cada cambio. */
.selector-capa {
  position: absolute; inset: 0;
  opacity: 0; transform: scale(1.02);
  transition: opacity var(--anim-principal), transform var(--anim-principal);
}
.selector-capa.activa { opacity: 1; transform: scale(1); }
.selector-capa img { width: 100%; height: 100%; object-fit: contain; }
.selector-lista { display: flex; flex-direction: column; }
.selector-item { border-top: 1px solid var(--borde); transition: border-color var(--anim-principal); }
.selector-item:last-child { border-bottom: 1px solid var(--borde); }
/* La línea del activo se vuelve negra: es el detalle que hace que se lea como
   una lista viva y no como un acordeón cualquiera. */
.selector-item.activo { border-top-color: var(--texto); }
.selector-titulo {
  width: 100%; text-align: left;
  background: none; border: 0; padding: 18px 0 0; cursor: pointer;
  font-family: var(--fuente-titulo); font-weight: 700;
  font-size: clamp(1.4rem, 3.5vw, 2.1rem);
  letter-spacing: -.01em; line-height: 1.2;
  color: var(--texto-tenue);
  transition: color var(--anim-principal);
}
.selector-item.activo .selector-titulo { color: var(--texto); }
/* 0fr → 1fr en lugar de height: la única forma de desplegar una altura
   desconocida sin animar layout. */
.selector-desc { display: grid; grid-template-rows: 1fr; transition: grid-template-rows var(--anim-principal), opacity var(--anim-principal); }
.js .selector-item:not(.activo) .selector-desc { grid-template-rows: 0fr; opacity: 0; }
.selector-desc > div { overflow: hidden; }
.selector-desc p { margin: 0; padding: 10px 0 18px; color: var(--texto-suave); font-size: .95rem; max-width: 42ch; }
@media (max-width: 900px) {
  .selector-grid { grid-template-columns: 1fr; }
  .selector-foto { max-height: 46vh; order: -1; }
  .selector-titulo { font-size: 1.35rem; }
}

/* ── Comparador ──────────────────────────────────────────────────────────────
   Dos fotos en un mismo marco y una manija que revela una u otra. UNA sola
   variable, --percent, recorta la capa superior y coloca la manija: un único
   punto de verdad, y clip-path es de las propiedades baratas. */
.comparador {
  --percent: 50%;
  position: relative; border-radius: var(--radio); overflow: hidden;
  aspect-ratio: 4 / 3; max-width: 760px; margin-inline: auto;
  background: var(--fondo-alt);
  touch-action: pan-y;  /* el scroll vertical de la página nunca se secuestra */
  user-select: none;
}
.comparador-capa { position: absolute; inset: 0; }
.comparador-capa img { width: 100%; height: 100%; object-fit: cover; }
.comparador-capa--top { clip-path: inset(0 0 0 var(--percent)); }
.comparador::after {
  content: ""; position: absolute; inset: auto 0 0 0; height: 34%;
  background: linear-gradient(rgba(0,0,0,0), rgba(0,0,0,.42));
  pointer-events: none;
}
.comparador-rotulo { position: absolute; bottom: 20px; z-index: 3; color: #fff; line-height: 1.25; pointer-events: none; }
.comparador-rotulo--izq { left: 24px; }
.comparador-rotulo--der { right: 24px; text-align: right; }
.comparador-rotulo small { display: block; font-size: .78rem; color: rgba(255,255,255,.72); }
.comparador-rotulo b { font-weight: 800; font-size: 1.05rem; }
.comparador-manija {
  position: absolute; top: 0; bottom: 0; z-index: 4;
  left: var(--percent); width: 2px; margin-left: -1px;
  background: rgba(255,255,255,.92);
  cursor: ew-resize; border: 0; padding: 0;
}
.comparador-manija::after {
  content: ""; position: absolute; left: 50%; top: 50%;
  width: 40px; height: 40px; margin: -20px 0 0 -20px;
  border-radius: 999px; background: #fff; box-shadow: var(--sombra);
  transition: transform var(--anim-principal);
}
.comparador-manija:hover::after { transform: scale(1.08); }
/* Las rayitas van en un hijo real; el ::after de la píldora es el último del
   árbol y a igual z-index pintaría encima, de ahí el z-index explícito. */
.comparador-rayas {
  position: absolute; left: 50%; top: 50%; z-index: 1;
  transform: translate(-50%, -50%);
  display: flex; gap: 3px; pointer-events: none;
}
.comparador-rayas i { width: 2px; height: 13px; border-radius: 2px; background: #c8c8d0; }
@media (max-width: 700px) { .comparador { aspect-ratio: 1; } }

/* ── Muro de reseñas ─────────────────────────────────────────────────────────
   Sin carrusel: nada de flechas, puntitos ni avance automático. El movimiento
   ya lo pone la entrada escalonada. La rejilla es deliberadamente desigual para
   que no se lea como cinco tarjetas clonadas. */
.resenas-resumen { display: flex; align-items: center; justify-content: center; gap: 14px; margin-bottom: 36px; flex-wrap: wrap; }
.resenas-nota { font-family: var(--fuente-titulo); font-size: 2.4rem; line-height: 1; }
.resenas-total { font-size: .9rem; color: var(--texto-suave); }
.estrellas { display: flex; gap: 3px; }
/* Estrellas en negro y gris: el amarillo rompería la paleta. */
.estrellas svg { color: var(--texto); }
.estrellas svg.vacia { color: var(--borde); }
.resenas { display: grid; grid-template-columns: repeat(3, 1fr); gap: 22px; }
.resena {
  background: var(--fondo-alt); border-radius: var(--radio); padding: 24px;
  display: flex; flex-direction: column; gap: 14px;
  transition: background var(--anim-principal);
}
.resena:hover { background: #eeeef1; }
.resena--destacada { grid-column: span 2; }
.resena--destacada p { font-size: 1.12rem; }
.resena p { margin: 0; font-size: 1rem; }
.resena-autor { margin-top: auto; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; font-size: .85rem; }
.resena-autor b { font-weight: 800; }
.resena-autor span { color: var(--texto-suave); }
.verificada { background: var(--fondo); color: var(--texto-suave); border-radius: 999px; padding: 4px 10px; font-size: .7rem; }
@media (max-width: 900px) {
  .resenas { grid-template-columns: 1fr; }
  .resena--destacada { grid-column: span 1; }
}

/* ── Franja de garantías: al final, como cierre ──────────────────────────────
   Pegada al hero competía con el producto; al final funciona como cierre
   tranquilizador. Sin fondo de color: basta una línea fina arriba. */
.franja-badges { background: none; border-top: 1px solid var(--borde); margin-top: 0; }
.badge-icono { transition: transform var(--anim-principal); }
.badge:hover .badge-icono { transform: translateY(-3px); }

/* ── Filtros: relleno en los chips y sombras de scroll ───────────────────────
   En móvil la fila de chips se desborda y no se nota que hay más: el degradado
   aparece solo cuando queda contenido por ese lado. */
.chip { position: relative; overflow: hidden; isolation: isolate; scroll-snap-align: start; }
.chip:not(.activo)::before {
  content: "";
  position: absolute; z-index: -1;
  top: -50%; left: -25%;
  width: 150%; height: 200%;
  border-radius: 50%;
  background: var(--acento);
  transform: translate3d(0, 76%, 0);
  transition: transform var(--anim-relleno);
}
@media (hover: hover) {
  .chip:not(.activo):hover { color: #fff; border-color: var(--acento); }
  .chip:not(.activo):hover::before { transform: translate3d(0, 0, 0); }
}
.chip { transition: color var(--anim-principal) .1s, border-color var(--anim-corta), background var(--anim-corta); }
.chip.sale:not(.activo)::before { transform: translate3d(0, -76%, 0); }
.chip.sin-trans::before { transition: none; }

.chips-envoltura { position: relative; flex: 1 1 auto; min-width: 0; }
.chips {
  display: flex; gap: 10px; align-items: center;
  overflow-x: auto;
  scroll-snap-type: x proximity;
  scrollbar-width: none; -ms-overflow-style: none;
  padding: 2px 0;
}
.chips::-webkit-scrollbar { display: none; }
.chips-envoltura::before,
.chips-envoltura::after {
  content: ""; position: absolute; top: 0; bottom: 0; width: 42px;
  pointer-events: none; opacity: 0;
  transition: opacity var(--anim-rapida);
}
.chips-envoltura::before { left: 0; background: linear-gradient(90deg, var(--fondo), rgba(255,255,255,0)); }
.chips-envoltura::after  { right: 0; background: linear-gradient(270deg, var(--fondo), rgba(255,255,255,0)); }
.chips-envoltura.hay-izq::before { opacity: 1; }
.chips-envoltura.hay-der::after  { opacity: 1; }

/* ── Carrito: el momento en capas ────────────────────────────────────────────
   El panel entra en 600ms y el oscurecimiento tarda 800ms: el panel LLEGA ANTES
   de que el fondo termine de oscurecer. Esa desincronización de 200ms es lo
   único que separa «una escena con capas» de «una caja que aparece».

   Se resuelve con clases de x-transition de Alpine: x-show, los @click y toda
   la lógica del panel siguen intactos. */
.pc-anim   { transition: transform var(--anim-drawer); }
.pc-fuera  { transform: translateX(100%); }
.oc-anim   { transition: opacity 800ms cubic-bezier(.7, 0, .2, 1); }
.oc-anim-salida { transition: opacity var(--anim-rapida); }
.oc-fuera  { opacity: 0; }

/* Escalonado hacia dentro: la mirada entra por la primera línea. Va con
   animation y no con transition porque el panel se inyecta ya montado por
   HTMX y una transición no tendría estado inicial que interpolar. */
@keyframes linea-entra {
  from { opacity: 0; transform: translateX(24px); }
  to   { opacity: 1; transform: none; }
}
.anim .panel-carrito .linea-carrito { animation: linea-entra .5s var(--anim-entrada) backwards; }
.anim .panel-carrito .linea-carrito:nth-child(2) { animation-delay: .08s; }
.anim .panel-carrito .linea-carrito:nth-child(3) { animation-delay: .16s; }
.anim .panel-carrito .linea-carrito:nth-child(4) { animation-delay: .24s; }
.anim .panel-carrito .linea-carrito:nth-child(n+5) { animation-delay: .32s; }

/* Progreso hacia el envío gratis. Se rellena con scaleX y nunca con width:
   animar el ancho dispararía layout en cada actualización del carrito. */
.envio-progreso { padding: 12px 0 14px; border-bottom: 1px solid var(--borde); display: grid; gap: 8px; margin-bottom: 6px; }
.envio-progreso p { margin: 0; font-size: .8rem; color: var(--texto-suave); }
.envio-progreso b { font-weight: 800; color: var(--texto); }
.envio-barra { height: 3px; border-radius: 999px; background: var(--borde); overflow: hidden; }
.envio-barra span {
  display: block; height: 100%; border-radius: 999px;
  background: var(--acento);
  transform: scaleX(var(--avance, 0));
  transform-origin: left;
  transition: transform var(--anim-suave);
}
.envio-barra span.late { animation: latido 450ms cubic-bezier(.3, 1, .3, 1); }

/* ── Vista rápida ────────────────────────────────────────────────────────────
   Entra desde scale(.96) con la curva principal. Va con @keyframes porque HTMX
   inyecta el popup ya montado: una transición no tendría estado inicial.
   El cierre lo hace $el.remove() de Alpine y no se toca — animar la salida
   exigiría interceptar ese evento, y la lógica manda sobre la estética. */
@keyframes popup-entra {
  from { opacity: 0; transform: scale(.96); }
  to   { opacity: 1; transform: none; }
}
@keyframes overlay-entra { from { opacity: 0; } to { opacity: 1; } }
.anim .overlay-popup { animation: overlay-entra var(--anim-rapida) backwards; }
.anim .overlay-popup .popup-vista-rapida { animation: popup-entra .5s var(--anim-entrada) backwards; }

/* ── Movimiento reducido ─────────────────────────────────────────────────────
   Refuerzo en CSS de lo que el JS ya corta en su primera línea: si algo se
   escapa, aquí se detiene igualmente. */
@media (prefers-reduced-motion: reduce) {
  .marca-agua-txt,
  .barra-msg,
  .selector-capa,
  .comparador-manija::after,
  .envio-barra span,
  .desliz-progreso span { transition: none !important; }
  .desliz { scroll-behavior: auto; }
  [data-animar], .tarjeta-producto[data-carta], img[data-fade] {
    opacity: 1 !important; transform: none !important; transition: none !important;
  }
}

/* Piezas de las filas desplazables que no deben encogerse dentro del flex. */
.chips > *, .banda .desliz > * { flex: 0 0 auto; }
.filtros { align-items: center; }

/* ── Página de comentarios ───────────────────────────────────────────────────
   Minimalista con un único golpe de vista: la nota media en grande y el
   desglose creciendo. Todo lo demás se mantiene en gris y sin marcos. */
.comentarios-cab { text-align: center; max-width: 620px; margin: 0 auto 44px; }
.comentarios-cab h1 { margin-bottom: 10px; }
.comentarios-cab .subtitulo { color: var(--texto-suave); margin: 0; font-size: 1.02rem; }

.nota-panel {
  display: grid; grid-template-columns: auto 1fr; gap: clamp(28px, 6vw, 72px);
  align-items: center;
  max-width: 720px; margin: 0 auto 32px;
  padding: 28px 32px;
  background: var(--fondo-alt); border-radius: var(--radio);
}
.nota-global { text-align: center; display: grid; gap: 6px; justify-items: center; }
.nota-cifra { font-family: var(--fuente-titulo); font-size: clamp(2.6rem, 7vw, 3.6rem); line-height: 1; }
.nota-total { font-size: .82rem; color: var(--texto-suave); }
.estrellas { display: inline-flex; gap: 3px; }
.estrellas svg { color: var(--texto); }
.estrellas svg.vacia { color: var(--borde); }
.estrellas--grande svg { color: var(--texto); }

.desglose { display: grid; gap: 7px; }
.desglose-fila { display: grid; grid-template-columns: auto auto 1fr auto; gap: 8px; align-items: center; font-size: .8rem; color: var(--texto-suave); }
.desglose-nivel { font-weight: 800; color: var(--texto); }
.desglose-estrella { color: var(--texto); }
.desglose-barra { height: 6px; border-radius: 999px; background: var(--fondo); overflow: hidden; }
/* Arrancan vacías y crecen cuando el panel recibe .vista: la misma clase que
   el resto de entradas, sin JavaScript propio. */
.desglose-barra span {
  display: block; height: 100%; border-radius: 999px;
  background: var(--texto);
  transform: scaleX(0); transform-origin: left;
  transition: transform var(--anim-suave) .25s;
}
.anim [data-animar].vista .desglose-barra span,
.sin-entradas .desglose-barra span { transform: scaleX(var(--nivel, 0)); }
.desglose-cant { min-width: 18px; text-align: right; font-variant-numeric: tabular-nums; }

.filtro-notas { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; margin-bottom: 32px; }

.muro { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; align-items: start; }
.comentario {
  position: relative;
  background: var(--fondo-alt); border-radius: var(--radio);
  padding: 24px;
  display: flex; flex-direction: column; gap: 14px;
  overflow: hidden;
  transition: background var(--anim-principal);
}
/* Único acento de color de la página: una barra que crece al pasar el cursor.
   Se anima con scaleY, no con height. */
.comentario::before {
  content: "";
  position: absolute; inset: 0 auto 0 0; width: 2px;
  background: var(--acento);
  transform: scaleY(0); transform-origin: top;
  transition: transform var(--anim-principal);
}
.comentario:hover { background: #ebebef; }
.comentario:hover::before { transform: scaleY(1); }
/* Los que traen foto ocupan dos columnas: son los que más convencen, así que
   se les da el espacio para que la foto se vea de verdad. */
.comentario--foto { grid-column: span 2; }

.comentario-cab { display: grid; grid-template-columns: auto 1fr auto; gap: 12px; align-items: center; }
.avatar {
  width: 44px; height: 44px; border-radius: 50%; object-fit: cover;
  background: var(--fondo); flex-shrink: 0;
}
.avatar--inicial {
  display: grid; place-items: center;
  background: hsl(var(--tono, 220) 55% 90%);
  color: hsl(var(--tono, 220) 55% 32%);
  font-family: var(--fuente-ui); font-weight: 800; font-size: 1.05rem;
}
.comentario-quien b { display: block; font-weight: 800; font-size: .88rem; }
.comentario-quien span { font-size: .78rem; color: var(--texto-suave); }
.comentario-texto { margin: 0; font-size: 1rem; line-height: 1.6; }

/* Foto del producto recibido: se amplía al pulsarla. */
.comentario-foto {
  position: relative; display: block; width: 100%; padding: 0;
  border: 0; border-radius: var(--radio-sm); overflow: hidden;
  background: var(--fondo); cursor: zoom-in; line-height: 0;
}
.comentario-foto img {
  width: 100%; height: 100%; max-height: 260px; object-fit: cover;
  transition: transform var(--anim-principal);
}
.comentario-foto:hover img { transform: scale(1.03); }
.comentario-foto-lupa {
  position: absolute; right: 10px; bottom: 10px;
  display: grid; place-items: center; width: 30px; height: 30px;
  border-radius: 50%; background: rgba(255,255,255,.92); color: var(--texto);
  opacity: 0; transition: opacity var(--anim-corta);
}
.comentario-foto:hover .comentario-foto-lupa { opacity: 1; }

.comentario-pie { margin-top: auto; display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.verificada { background: var(--fondo); color: var(--texto-suave); border-radius: 999px; padding: 4px 10px; font-size: .7rem; white-space: nowrap; }
.comentario-producto { font-size: .74rem; color: var(--texto-suave); }

.muro-vacio { text-align: center; color: var(--texto-suave); padding: 48px 0 0; }
.nota-cta { grid-column: 1 / -1; justify-self: start; margin-top: 4px; }
.chip--foto { display: inline-flex; align-items: center; gap: 6px; }

/* ── Lightbox de las fotos de los clientes ──────────────────────────────── */
.lightbox {
  position: fixed; inset: 0; z-index: 120;
  display: grid; place-items: center; padding: 28px;
  background: rgba(20, 20, 24, .88); backdrop-filter: blur(3px);
  cursor: zoom-out;
}
.lightbox img {
  max-width: min(900px, 92vw); max-height: 86vh;
  border-radius: var(--radio); cursor: default;
  box-shadow: 0 24px 70px rgba(0,0,0,.5);
}
.lightbox-cerrar {
  position: absolute; top: 18px; right: 22px;
  width: 40px; height: 40px; border-radius: 50%; border: 0;
  background: rgba(255,255,255,.16); color: #fff; font-size: 1.05rem;
  cursor: pointer;
}
.lightbox-cerrar:hover { background: rgba(255,255,255,.3); }

/* ── Dejar un comentario ────────────────────────────────────────────────── */
.dejar-comentario { margin-top: 56px; padding-top: 40px; border-top: 1px solid var(--borde); }
.dejar-abrir {
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
  width: 100%; text-align: left; cursor: pointer;
  padding: 22px 26px; border-radius: var(--radio);
  border: 1px dashed var(--line, var(--borde)); background: transparent;
  color: var(--texto); font-family: inherit; font-size: .95rem;
  transition: border-color var(--anim-corta), background var(--anim-corta);
}
.dejar-abrir:hover { border-color: var(--acento); background: var(--fondo-alt); }
.dejar-abrir b { display: block; font-family: var(--fuente-ui); font-size: 1rem; margin-bottom: 3px; }
.dejar-abrir span { color: var(--texto-suave); }
.dejar-abrir svg { color: var(--acento); flex-shrink: 0; }

.form-comentario {
  background: var(--fondo-alt); border-radius: var(--radio);
  padding: 30px; display: flex; flex-direction: column; gap: 18px;
}
.form-comentario h2 { margin: 0; font-size: 1.3rem; }
.form-nota { margin: -12px 0 0; font-size: .82rem; color: var(--texto-suave); }

.campo { display: flex; flex-direction: column; gap: 6px; position: relative; }
.campo > span {
  font-family: var(--fuente-ui); font-size: .72rem; font-weight: 800;
  letter-spacing: .07em; text-transform: uppercase; color: var(--texto-suave);
}
.campo > span i { font-style: normal; font-weight: 500; text-transform: none; letter-spacing: 0; }
.campo input[type="text"], .campo textarea {
  width: 100%; padding: 11px 14px; border-radius: var(--radio-sm);
  border: 1px solid var(--borde); background: #fff; color: var(--texto);
  font-family: inherit; font-size: .95rem;
}
.campo textarea { resize: vertical; min-height: 110px; }
.campo input:focus, .campo textarea:focus { outline: 2px solid var(--acento); outline-offset: 1px; border-color: transparent; }
.campo-fila { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
.campo-error { font-size: .78rem; color: var(--error); }
.campo-contador {
  position: absolute; right: 4px; bottom: -18px;
  font-size: .7rem; color: var(--texto-suave); font-variant-numeric: tabular-nums;
}

/* Estrellas: los botones son la interfaz, los radios de debajo son lo que
   se envía. Sin JavaScript, los radios siguen ahí y el formulario funciona. */
.campo--estrellas { border: 0; padding: 0; margin: 0; }
.campo--estrellas legend {
  font-family: var(--fuente-ui); font-size: .72rem; font-weight: 800;
  letter-spacing: .07em; text-transform: uppercase; color: var(--texto-suave);
  padding: 0; margin-bottom: 8px;
}
.selector-estrellas { display: flex; align-items: center; gap: 2px; }
.estrella-boton {
  padding: 2px; border: 0; background: transparent; cursor: pointer;
  color: var(--borde); line-height: 0;
  transition: color var(--anim-corta), transform var(--anim-corta);
}
.estrella-boton.marcada { color: #f5b40a; }
.estrella-boton:hover { transform: scale(1.14); }
.estrellas-leyenda {
  margin-left: 10px; font-family: var(--fuente-ui); font-size: .82rem;
  font-weight: 700; color: var(--texto-suave);
}
/* Accesible para lectores de pantalla y teclado, invisible en pantalla. */
.radios-ocultos {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap;
}

.campo--foto { gap: 8px; }
.soltar-foto {
  position: relative; display: grid; place-items: center;
  min-height: 104px; padding: 14px; cursor: pointer;
  border: 1px dashed var(--borde); border-radius: var(--radio-sm);
  background: #fff; overflow: hidden;
  transition: border-color var(--anim-corta);
}
.soltar-foto:hover { border-color: var(--acento); }
.soltar-foto input[type="file"] { position: absolute; inset: 0; opacity: 0; cursor: pointer; }
.soltar-texto {
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  font-family: var(--fuente-ui); font-size: .8rem; color: var(--texto-suave);
  text-align: center;
}
.soltar-foto.con-previa { border-style: solid; padding: 0; }
.previa { width: 100%; max-height: 180px; object-fit: cover; display: block; }
.previa--redonda { width: 84px; height: 84px; border-radius: 50%; margin: 10px; }

.form-acciones { display: flex; gap: 12px; justify-content: flex-end; margin-top: 4px; }

@media (max-width: 900px) {
  .muro { grid-template-columns: 1fr 1fr; }
  .comentario--foto { grid-column: span 2; }
}
@media (max-width: 640px) {
  .nota-panel { grid-template-columns: 1fr; gap: 22px; padding: 24px; }
  .muro { grid-template-columns: 1fr; }
  .comentario--foto { grid-column: span 1; }
  .campo-fila { grid-template-columns: 1fr; }
  .form-comentario { padding: 22px; }
  .dejar-abrir { padding: 18px 20px; }
}

/* ── Cuentas para transferencia ───────────────────────────────────────────────
   Una ficha por entidad, con su color. Se dibujan con CSS y no con imágenes:
   el número queda seleccionable, se ve nítido en cualquier pantalla y los
   datos vienen del admin. Los monogramas son tipográficos, no logotipos. */
.cuentas { display: grid; gap: 18px; margin: 18px 0 26px; text-align: left; }

.cuenta {
  border: 1px solid var(--borde);
  border-radius: 16px;
  overflow: hidden;
  background: #fff;
  box-shadow: 0 2px 10px rgba(0, 0, 0, .05);
}
.cuenta-pichincha { --cuenta-fondo: #ffdd00; --cuenta-texto: #111; --cuenta-mono-fondo: #111; --cuenta-mono-texto: #fff; }
.cuenta-guayaquil { --cuenta-fondo: #16305c; --cuenta-texto: #fff; --cuenta-mono-fondo: #ffd100; --cuenta-mono-texto: #16305c; --cuenta-borde: #ffd100; }
.cuenta-peigo     { --cuenta-fondo: #fa3556; --cuenta-texto: #fff; --cuenta-mono-fondo: #fff; --cuenta-mono-texto: #fa3556; }
.cuenta-otra      { --cuenta-fondo: var(--acento); --cuenta-texto: #fff; --cuenta-mono-fondo: #fff; --cuenta-mono-texto: var(--acento); }

.cuenta-cabecera {
  display: flex; align-items: center; gap: 12px;
  padding: 14px 18px;
  background: var(--cuenta-fondo);
  color: var(--cuenta-texto);
  border-bottom: 3px solid var(--cuenta-borde, #111);
}
.cuenta-monograma {
  flex: none;
  display: grid; place-items: center;
  width: 40px; height: 40px;
  border-radius: 9px;
  background: var(--cuenta-mono-fondo);
  color: var(--cuenta-mono-texto);
  font-family: var(--fuente-titulo); font-weight: 700; font-size: 1.05rem;
}
.cuenta-nombre {
  flex: 1;
  font-family: var(--fuente-titulo); font-weight: 700;
  font-size: 1.05rem; line-height: 1.1; text-transform: uppercase;
}
.cuenta-nombre small { display: block; font-size: .72rem; font-weight: 400; opacity: .8; text-transform: none; }
/* Bandera del Ecuador: tres franjas, la amarilla del doble de alto. */
.cuenta-bandera {
  flex: none; width: 26px; height: 17px; border-radius: 3px;
  border: 1px solid rgba(0, 0, 0, .25);
  background: linear-gradient(#ffdd00 0 50%, #0033a0 50% 75%, #ef3340 75% 100%);
}

.cuenta-cuerpo { padding: 18px; }
.cuenta-titulo {
  font-size: .78rem; letter-spacing: .08em; text-transform: uppercase;
  color: var(--texto-suave); margin: 0 0 14px;
  padding-bottom: 10px; border-bottom: 1px solid var(--borde);
}

/* El dato que hay que copiar: destacado y pulsable. */
.cuenta-destacado {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  width: 100%; margin-bottom: 14px; padding: 12px 14px;
  border: 2px dashed var(--cuenta-fondo);
  border-radius: 11px;
  background: color-mix(in srgb, var(--cuenta-fondo) 8%, #fff);
  font: inherit; text-align: left; cursor: pointer;
  transition: background .15s ease;
}
.cuenta-destacado:hover { background: color-mix(in srgb, var(--cuenta-fondo) 16%, #fff); }
.cuenta-etiqueta { font-size: .85rem; color: var(--texto-suave); }
.cuenta-valor {
  margin-left: auto;
  font-family: var(--fuente-titulo); font-weight: 700; font-size: 1.2rem;
  letter-spacing: .02em;
}
.cuenta-copiar { flex-basis: 100%; font-size: .72rem; color: var(--texto-suave); }

.cuenta-datos { display: grid; grid-template-columns: auto 1fr; gap: 8px 16px; margin: 0; }
.cuenta-datos dt { font-size: .9rem; color: var(--texto-suave); }
.cuenta-datos dd { margin: 0; text-align: right; font-weight: 700; font-size: .95rem; }

.cuenta-pie {
  padding: 11px 18px;
  background: var(--fondo-suave, #f7f7f8);
  border-top: 1px solid var(--borde);
  font-size: .78rem; color: var(--texto-suave); text-align: center;
}
@media (max-width: 420px) {
  .cuenta-valor { font-size: 1.05rem; }
  .cuenta-nombre { font-size: .95rem; }
}

.titulo-cuentas {
  font-family: var(--fuente-ui); font-size: .9rem; font-weight: 800;
  margin: 18px 0 10px;
}
.otras-cuentas { margin-top: 18px; text-align: left; }
.otras-cuentas summary {
  cursor: pointer; font-size: .9rem; color: var(--acento); font-weight: 700;
}
.otras-cuentas summary:hover { text-decoration: underline; }

/* ── Recorrido del envío ─────────────────────────────────────────────────────
   Los movimientos que reporta la transportadora, dentro de la tienda: el
   comprador no tiene que salir a una página ajena para ver dónde va su
   paquete. Los datos llegan en la consulta periódica, que no cuesta cuota. */
.recorrido { text-align: left; margin-top: 28px; }
.recorrido-titulo { font-family: var(--fuente-titulo); font-size: 1.1rem; margin: 0 0 4px; }
.recorrido-meta { font-size: .85rem; color: var(--texto-suave); margin: 0 0 18px; }

.movimientos { list-style: none; margin: 0; padding: 0; }
.movimiento {
  position: relative;
  display: grid; grid-template-columns: 22px 1fr; gap: 12px;
  padding-bottom: 18px;
}
/* La línea baja desde cada punto hasta el siguiente; el último no la lleva. */
.movimiento::before {
  content: ""; position: absolute; left: 6px; top: 14px; bottom: 0;
  width: 2px; background: var(--borde);
  transform-origin: top;
  transition: transform var(--anim-principal) var(--anim-entrada);
}
.anim .movimiento::before { transform: scaleY(0); }
.movimiento.vista::before { transform: scaleY(1); }
/* El trazo entra justo detrás de su movimiento (60 ms de separación). */
.movimiento:nth-child(1)::before { transition-delay: 200ms; }
.movimiento:nth-child(2)::before { transition-delay: 260ms; }
.movimiento:nth-child(3)::before { transition-delay: 320ms; }
.movimiento:nth-child(4)::before { transition-delay: 380ms; }
.movimiento:nth-child(5)::before { transition-delay: 440ms; }
.movimiento:nth-child(6)::before { transition-delay: 500ms; }
.movimiento:nth-child(n+7)::before { transition-delay: 560ms; }
.movimiento:last-child::before { display: none; }
.movimiento-punto {
  width: 11px; height: 11px; margin-top: 5px; border-radius: 50%;
  background: #fff; border: 2px solid var(--borde); z-index: 1;
}
.movimiento.ultimo .movimiento-punto {
  background: var(--acento); border-color: var(--acento);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--acento) 18%, transparent);
}
.movimiento-desc { margin: 0; font-size: .92rem; font-weight: 700; line-height: 1.35; }
.movimiento.ultimo .movimiento-desc { color: var(--acento); }
.movimiento-datos {
  margin: 2px 0 0; font-size: .8rem; color: var(--texto-suave);
  font-variant-numeric: tabular-nums;
}
.recorrido-origen { margin: 4px 0 0; font-size: .82rem; }

/* ── Zonas de envío (checkout) ───────────────────────────────────────────── */
.zonas { display: grid; gap: 8px; margin: 14px 0 4px; }
.zona {
  display: flex; align-items: center; gap: 11px;
  padding: 13px 16px;
  border: 1px solid var(--borde); border-radius: 12px;
  background: #fff; cursor: pointer;
  transition: border-color var(--anim-corta), background var(--anim-corta);
}
.zona:hover { border-color: var(--texto-suave); }
.zona.activo { border-color: var(--acento); background: color-mix(in srgb, var(--acento) 5%, #fff); }
.zona input { accent-color: var(--acento); flex: none; }
.zona-texto { font-size: .93rem; line-height: 1.35; }

/* ── Configurador 3D del hero ────────────────────────────────────────────────
   El recuadro solo contiene la escena; los controles van DEBAJO, fuera de él.
   Así el panel no puede taparle la base al teléfono por mucho que crezca al
   partirse en varias líneas. Mientras WebGL no confirme se ve el hero de
   siempre: la clase «listo» hace el cambio en un único punto. */
.configurador {
  position: relative; display: flex; flex-direction: column; align-items: center;
  /* Mismo ancho que la escena: el panel se posiciona contra este borde, y si
     el contenedor fuera más ancho quedaría flotando fuera del recuadro. */
  max-width: 900px; margin: 0 auto; width: 100%;
}

.cfg-escena {
  position: relative; display: grid;
  margin: 40px auto 0; max-width: 900px; width: 100%;
  background: var(--fondo-alt); border-radius: 24px;
  min-height: 400px; overflow: hidden;
}
.cfg-escena > * { grid-area: 1 / 1; min-width: 0; }
.configurador .cfg-respaldo { margin: 0; max-width: none; border-radius: 0; }

.cfg-lienzo { position: relative; width: 100%; opacity: 0; transition: opacity var(--anim-suave); }
/* El canvas va fuera del flujo: con height:100% dentro de un contenedor de
   altura automática se retroalimentaba —canvas más alto, contenedor más alto—
   y crecía sin freno hasta miles de píxeles. La altura la fija .cfg-escena. */
.cfg-lienzo canvas {
  position: absolute; inset: 0;
  display: block; width: 100% !important; height: 100% !important;
  touch-action: none; cursor: grab;
}
.cfg-lienzo canvas:active { cursor: grabbing; }
.configurador.listo .cfg-lienzo { opacity: 1; }
.configurador.listo .cfg-respaldo { display: none; }

/* Los controles van al costado derecho, sobre el vacío que deja el teléfono:
   abajo competían con la sección siguiente y cargaban la vista. El modelo se
   desplaza a la izquierda desde el JS, así que no se solapan. */
.cfg-panel {
  position: absolute; top: 50%; right: 26px; transform: translateY(-50%);
  z-index: 2; width: 268px;
  display: none; flex-direction: column; align-items: stretch;
  gap: 11px;
  padding: 13px 15px;
  /* Con seis protectores la lista crece más que el recuadro: se limita a su alto y
     el sobrante se desplaza dentro del propio panel. El valor es fijo porque
     el contenedor incluye el margen superior de la escena y calcularlo en
     porcentaje daba un panel más alto que el recuadro. */
  max-height: 344px;
  overflow-y: auto;
  overscroll-behavior: contain;
  background: rgba(255, 255, 255, .72);
  backdrop-filter: blur(12px);
  border: 1px solid var(--borde);
  border-radius: 16px;
}
.configurador.listo .cfg-panel { display: flex; }

.cfg-grupo { display: flex; flex-direction: column; align-items: stretch; gap: 6px; }
.cfg-grupo + .cfg-grupo { border-top: 1px solid var(--borde); padding-top: 10px; }
.cfg-etiqueta {
  font-family: var(--fuente-ui); font-size: .66rem; font-weight: 800;
  letter-spacing: .09em; text-transform: uppercase; color: var(--texto-suave);
  white-space: nowrap;
}
.cfg-opciones { display: flex; gap: 7px; flex-wrap: wrap; }

.cfg-chip {
  font-family: var(--fuente-ui); font-size: .82rem; font-weight: 700;
  padding: 7px 13px; border-radius: 999px;
  border: 1px solid var(--borde); background: #fff; color: var(--texto);
  cursor: pointer; transition: border-color var(--anim-corta), background var(--anim-corta);
}
.cfg-chip:hover { border-color: var(--texto-suave); }
.cfg-chip.activo { background: var(--texto); border-color: var(--texto); color: #fff; }

.cfg-color {
  width: 26px; height: 26px; border-radius: 50%; padding: 0;
  background: var(--tono); border: 2px solid #fff; cursor: pointer;
  box-shadow: 0 0 0 1px var(--borde);
  transition: box-shadow var(--anim-corta), transform var(--anim-corta);
}
.cfg-color:hover { transform: scale(1.08); }
.cfg-color.activo { box-shadow: 0 0 0 2px var(--acento); }

/* Dentro del recuadro, discreta y sin robar altura. */
.cfg-pista {
  position: absolute; left: 0; right: 0; bottom: 10px; z-index: 1;
  margin: 0; text-align: center; pointer-events: none;
  font-size: .7rem; letter-spacing: .04em; color: var(--texto-suave); opacity: .7;
}

@media (max-width: 900px) {
  /* Sin sitio al costado, el panel vuelve al flujo, debajo de la escena. */
  .cfg-panel {
    position: static; transform: none; width: auto; max-width: 900px;
    margin-top: 14px; flex-direction: row; flex-wrap: wrap;
    align-items: center; justify-content: center; gap: 9px 16px;
    background: transparent; backdrop-filter: none; border: 0; padding: 0;
  }
  .cfg-grupo { flex-direction: row; align-items: center; }
  .cfg-grupo + .cfg-grupo { border-top: 0; padding-top: 0; }
}

@media (max-width: 760px) {
  .cfg-escena { min-height: 330px; margin-top: 28px; }
  .cfg-chip { font-size: .76rem; padding: 6px 10px; }
}

/* Ficha del protector que se está probando: convierte el juguete en una vía
   de compra —nombre, precio, colores reales y enlace al producto—. */
/* Una columna: en dos, los nombres reales del catálogo se cortaban a la
   mitad y el cliente no sabía qué estaba probando. */
.cfg-protectores { display: grid; grid-template-columns: 1fr; gap: 5px; }
.cfg-protectores .cfg-chip {
  text-align: left; padding: 6px 11px; font-size: .74rem;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.cfg-ficha {
  display: flex; flex-direction: column; gap: 5px;
  padding-top: 10px; border-top: 1px solid var(--borde);
}
.cfg-ficha[hidden] { display: none; }
.cfg-ficha-nombre {
  margin: 0; font-family: var(--fuente-ui); font-weight: 800; font-size: .86rem;
  line-height: 1.25;
}
.cfg-ficha-precio { margin: 0; font-size: .8rem; color: var(--texto-suave); }
/* Si carga o no sin cable: el dato que decide la compra de un protector. */
.cfg-ficha-nota {
  margin: 0; font-family: var(--fuente-ui); font-size: .68rem; font-weight: 700;
  letter-spacing: .04em; color: var(--texto-suave);
}
.cfg-ficha-nota::before { content: "◎ "; }
.cfg-ficha-nota.sin::before { content: "○ "; opacity: .55; }
.cfg-ficha-nota:empty { display: none; }
.cfg-ficha-enlace {
  font-family: var(--fuente-ui); font-weight: 700; font-size: .8rem;
  color: var(--acento); text-decoration: none;
}
.cfg-ficha-enlace:hover { text-decoration: underline; }

@media (max-width: 900px) {
  /* Fuera del panel estrecho sí caben varias columnas, y con siete
     opciones en una sola el bloque se hacía muy alto en el móvil. */
  .cfg-protectores { grid-template-columns: repeat(auto-fit, minmax(132px, 1fr)); }
  .cfg-ficha { border-top: 0; padding-top: 0; flex-direction: row; align-items: center; gap: 12px; }
}
