/* =============================================================================
   DropDigitals — Home (reconstrucción con carácter)
   Mismo ADN claro + verde, pero roto a mano: hero asimétrico con ilustración de
   activación propia, bento de piezas variadas (incluye tiles oscuro y verde),
   pasos en línea de tiempo, soporte con mini-chat. Sin rótulos en mayúsculas,
   sin banda de "números gigantes", sin iconos flotando.
   ============================================================================= */

/* ============================================================ HERO (foto) === */
.hero {
  position: relative;
  display: flex;
  align-items: center;
  min-height: clamp(460px, 78vh, 700px);
  overflow: hidden;
  isolation: isolate;
  /* Hero oscuro fijo (no depende de foto ni del tema): el texto blanco y el panel de
     marca se leen siempre igual, en claro y en oscuro. */
  background: radial-gradient(120% 105% at 8% 0%, oklch(0.155 0.034 51) 0%, oklch(0.082 0.015 51) 46%, oklch(0.05 0.008 51) 100%);
}

.hero>.container,
.hero .hero__sticky>.container {
  width: 100%;
}

/* Capa de brillo esmeralda detrás del panel (da profundidad, reemplaza la foto). */
.hero__bg {
  position: absolute;
  inset: 0;
  z-index: -3;
  background: radial-gradient(72% 68% at 82% 24%, oklch(0.34 0.10 51 / 0.42), transparent 60%);
}

/* Video de fondo: invisible hasta que carga un fotograma (entonces hace fundido).
   Si el archivo no existe, nunca aparece y queda la foto .hero__bg de respaldo. */
.hero__video {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: transparent;
  opacity: 0;
  transition: opacity 0.8s var(--ease-out);
  pointer-events: none;
}

.hero__video.is-ready {
  opacity: 1;
}

/* Con el video activo, la composición flotante cede el protagonismo (se evita
   que dos "dashboards" compitan). Si el video falla, la composición sigue ahí. */
@media (min-width: 641px) {

  /* !important + animation:none para ganarle a la animación "reveal" que fija
     opacity:1 (las animaciones CSS tienen prioridad sobre las reglas normales). */
  .hero--video .hero__visual {
    animation: none !important;
    opacity: 0 !important;
    visibility: hidden;
    pointer-events: none;
    transition: opacity 0.6s var(--ease-out);
  }
}

@media (max-width: 640px) {
  .hero__video {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .hero__video {
    display: none;
  }
}

.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(95deg, oklch(0.045 0.006 51 / 0.93) 0%, oklch(0.05 0.006 51 / 0.8) 30%, oklch(0.05 0.006 51 / 0.42) 56%, oklch(0.05 0.006 51 / 0.12) 82%, oklch(0.05 0.006 51 / 0.02) 100%),
    radial-gradient(95% 85% at 6% 100%, oklch(0.5 0.15 51 / 0.24), transparent 55%),
    linear-gradient(0deg, oklch(0.045 0.006 51 / 0.55), transparent 30%);
}

/* En móvil/tablet el texto ocupa todo el ancho sobre la foto: oscurecido uniforme */
@media (max-width: 860px) {
  .hero::after {
    background:
      linear-gradient(180deg, oklch(0.05 0.006 51 / 0.74) 0%, oklch(0.05 0.006 51 / 0.82) 55%, oklch(0.045 0.006 51 / 0.95) 100%),
      radial-gradient(110% 60% at 50% 110%, oklch(0.5 0.15 51 / 0.22), transparent 60%);
  }
}

.hero__watermark {
  position: absolute;
  z-index: 0;
  right: clamp(1.2rem, 5vw, 4rem);
  bottom: clamp(1.2rem, 5vw, 3rem);
  width: clamp(96px, 14vw, 168px);
  opacity: 0.22;
  filter: drop-shadow(0 6px 16px oklch(0 0 0 / 0.45));
  pointer-events: none;
}

@media (min-width: 961px) {
  .hero__watermark {
    display: none;
  }
}

.hero__content {
  position: relative;
  max-width: 640px;
  color: #fff;
  padding-block: clamp(3.5rem, 9vw, 6.5rem);
}

/* --- Composición 3D del hero (panel de activación + cajas flotando) --- */
@media (min-width: 961px) {

  .hero>.container,
  .hero .hero__sticky>.container {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(360px, 0.8fr);
    align-items: center;
    gap: clamp(1.5rem, 3.5vw, 3.5rem);
  }
}

/* Composición 3D de marca: oculta en móvil (el texto ocupa todo el ancho), y visible
   en escritorio como segunda columna del hero (panel de activación + cajas flotando). */
.hero__visual {
  display: none;
}

@media (min-width: 961px) {
  .hero__visual {
    display: block;
  }
}

.hero__beam {
  position: absolute;
  width: 130%;
  height: 130%;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(40% 36% at 58% 44%, oklch(0.72 0.18 51 / 0.5), transparent 70%);
  filter: blur(8px);
}

.hero__stage {
  position: relative;
  transform-style: preserve-3d;
  z-index: 1;
  width: min(410px, 100%);
}

.hero__panel {
  position: relative;
  z-index: 2;
  border-radius: var(--r-lg);
  padding: 1.15rem 1.25rem;
  transform: rotateY(-15deg) rotateX(6deg);
  background: linear-gradient(160deg, oklch(0.21 0.02 51 / 0.92), oklch(0.115 0.014 51 / 0.96));
  border: 1px solid oklch(1 0 0 / 0.12);
  box-shadow: 0 34px 74px oklch(0 0 0 / 0.62), 0 0 0 1px oklch(0.7 0.16 51 / 0.12), inset 0 1px 0 oklch(1 0 0 / 0.1);
  animation: heroFloat 7s var(--ease-out-soft) infinite alternate;
  will-change: transform;
}

@keyframes heroFloat {
  from {
    transform: rotateY(-15deg) rotateX(6deg) translateY(6px);
  }

  to {
    transform: rotateY(-11deg) rotateX(4deg) translateY(-10px);
  }
}

.hp__top {
  display: flex;
  align-items: center;
  gap: 0.7rem;
}

.hp__app {
  width: 2.7rem;
  height: 2.7rem;
  border-radius: 13px;
  overflow: hidden;
  flex: none;
  display: grid;
  place-items: center;
  box-shadow: var(--shadow-sm);
}

.hp__app .brand-glyph {
  width: 2.7rem !important;
  height: 2.7rem !important;
  border-radius: 13px;
}

.hp__id {
  flex: 1;
  min-width: 0;
}

.hp__id b {
  display: block;
  color: #fff;
  font-family: var(--font-display);
  font-size: 1.02rem;
  letter-spacing: -0.01em;
}

.hp__id span {
  font-size: 0.78rem;
  color: rgba(255, 255, 255, 0.62);
}

.hp__status {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.74rem;
  font-weight: 700;
  white-space: nowrap;
  color: oklch(0.88 0.16 51);
  background: oklch(0.7 0.16 51 / 0.16);
  border: 1px solid oklch(0.7 0.16 51 / 0.3);
  padding: 0.3rem 0.55rem;
  border-radius: var(--r-pill);
}

.hp__status svg {
  width: 0.85rem;
  height: 0.85rem;
}

.hp__bar {
  margin: 1.05rem 0 0.95rem;
  height: 7px;
  border-radius: 99px;
  background: oklch(1 0 0 / 0.1);
  overflow: hidden;
}

.hp__bar>span {
  display: block;
  height: 100%;
  width: 100%;
  border-radius: inherit;
  transform-origin: left;
  background: linear-gradient(90deg, oklch(0.6 0.16 51), oklch(0.82 0.17 51));
  box-shadow: 0 0 14px oklch(0.72 0.16 51 / 0.6);
  animation: hp-fill 1.6s var(--ease-out) 0.4s both;
}

@keyframes hp-fill {
  from {
    transform: scaleX(0);
  }

  to {
    transform: scaleX(1);
  }
}

.hp__steps {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin: 0;
}

.hp__steps li {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  font-size: 0.84rem;
  color: rgba(255, 255, 255, 0.82);
}

.hp__steps svg {
  width: 1rem;
  height: 1rem;
  color: oklch(0.82 0.16 51);
  flex: none;
}

.hp__key {
  margin-top: 0.95rem;
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.5rem 0.65rem;
  border-radius: var(--r-sm);
  background: oklch(0 0 0 / 0.35);
  border: 1px solid oklch(1 0 0 / 0.08);
}

.hp__key span {
  font-size: 0.62rem;
  letter-spacing: 0.14em;
  font-weight: 700;
  color: rgba(255, 255, 255, 0.45);
}

/* min-width:0 + recorte con puntos suspensivos, igual que sus dos gemelas
   (.lic-card__key code y .pd-lic__key code en liccard.css). Sin esto, un
   elemento flexible no se encoge por debajo de su contenido: con la letra del
   sistema en grande la clave empujaba el escudo fuera del panel del hero.
   (29-jul-2026) */
.hp__key code {
  flex: 1;
  min-width: 0;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  color: rgba(255, 255, 255, 0.8);
  letter-spacing: 0.06em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.hp__key svg {
  width: 1rem;
  height: 1rem;
  color: oklch(0.82 0.16 51);
  flex: none;
}

.hero__float {
  position: absolute;
  z-index: 1;
  width: 4.7rem;
  height: 4.7rem;
  border-radius: 16px;
  display: grid;
  place-items: center;
  background: linear-gradient(160deg, oklch(0.22 0.02 51 / 0.9), oklch(0.12 0.015 51 / 0.94));
  border: 1px solid oklch(1 0 0 / 0.1);
  box-shadow: 0 18px 42px oklch(0 0 0 / 0.5);
}

.hero__float .brand-glyph {
  width: 2.6rem !important;
  height: 2.6rem !important;
  border-radius: 12px;
}

.hero__float--a {
  top: -2.3rem;
  right: -1.3rem;
  transform: rotateY(-15deg) translateZ(40px);
  animation: heroFloat2 6s var(--ease-out-soft) infinite alternate;
}

.hero__float--b {
  bottom: -2.1rem;
  left: -1.7rem;
  transform: rotateY(-15deg) translateZ(22px);
  animation: heroFloat2 6.6s var(--ease-out-soft) -2s infinite alternate;
}

@keyframes heroFloat2 {
  from {
    translate: 0 0;
  }

  to {
    translate: 0 -14px;
  }
}

@media (prefers-reduced-motion: reduce) {

  .hero__panel,
  .hero__float {
    animation: none;
  }

  .hp__bar>span {
    animation: none;
  }
}

.hero__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font-size: 0.9rem;
  color: rgba(255, 255, 255, 0.92);
  margin-bottom: 1.4rem;
}

.hero__eyebrow .tp-stars {
  display: inline-flex;
  gap: 2px;
}

.hero__eyebrow .tp-stars i {
  width: 0.95rem;
  height: 0.95rem;
  color: #ffc24b;
}

.hero__eyebrow .tp-stars svg {
  width: 100%;
  height: 100%;
  fill: currentColor;
  stroke: none;
}

.hero__eyebrow b {
  color: #fff;
}

.hero h1 {
  font-size: clamp(1.72rem, 0.45rem + 4.7vw, 4.2rem);
  line-height: 1.05;
  letter-spacing: -0.035em;
  font-weight: 800;
  color: #fff;
  text-wrap: balance;
  text-shadow: 0 2px 30px oklch(0.1 0 0 / 0.35);
}

.hero h1 em {
  font-style: normal;
  position: relative;
  color: oklch(0.85 0.15 54);
}

.hero h1 em::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -0.1em;
  height: 0.085em;
  border-radius: 99px;
  background: linear-gradient(90deg, oklch(0.78 0.17 51), oklch(0.86 0.13 57));
  transform: scaleX(0);
  transform-origin: left;
  animation: hl-draw 0.85s var(--ease-out) 0.55s forwards;
}

@keyframes hl-draw {
  to {
    transform: scaleX(1);
  }
}

.hero__lede {
  margin-top: 1.3rem;
  font-size: clamp(1.05rem, 0.95rem + 0.6vw, 1.25rem);
  color: rgba(255, 255, 255, 0.9);
  max-width: 50ch;
  line-height: 1.55;
}

.hero__cta {
  margin-top: 2.1rem;
  display: flex;
  gap: 0.9rem;
  flex-wrap: wrap;
  align-items: center;
}

.btn--onphoto {
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
  border: 1px solid rgba(255, 255, 255, 0.5);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
}

.btn--onphoto:hover {
  background: rgba(255, 255, 255, 0.22);
  border-color: #fff;
}

.hero__trust {
  list-style: none;
  margin: 2rem 0 0;
  padding: 0;
  display: flex;
  gap: 1.4rem;
  flex-wrap: wrap;
}

.hero__trust li {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.9rem;
  color: rgba(255, 255, 255, 0.86);
}

.hero__trust svg {
  width: 1.05rem;
  height: 1.05rem;
  color: oklch(0.83 0.16 51);
}

@media (max-width: 640px) {
  .hero {
    min-height: clamp(420px, 82vh, 560px);
  }

  .hero__content {
    max-width: none;
  }

  .hero__cta {
    flex-direction: column;
    align-items: stretch;
  }

  .hero__cta .btn {
    width: 100%;
    justify-content: center;
  }
}

/* ===================================================== MARCAS (strip) ======= */
.brandstrip {
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}

.brandstrip__inner {
  display: flex;
  align-items: center;
  gap: clamp(1.25rem, 4vw, 3rem);
  padding-block: 1.4rem;
  flex-wrap: wrap;
}

.brandstrip__label {
  font-size: 0.82rem;
  color: var(--ink-faint);
  max-width: 14ch;
  line-height: 1.35;
  font-weight: 500;
}

.brandstrip__logos {
  position: relative;
  flex: 1;
  min-width: 0;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
}

.brandstrip__track {
  display: flex;
  align-items: center;
  gap: clamp(1.75rem, 3.5vw, 3rem);
  width: max-content;
  animation: bs-marquee 30s linear infinite;
}

.brandstrip__logos:hover .brandstrip__track {
  animation-play-state: paused;
}

@keyframes bs-marquee {
  to {
    transform: translateX(-50%);
  }
}

.brandstrip__logos .bl {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  color: var(--ink-muted);
  font-weight: 600;
  font-size: 0.92rem;
  white-space: nowrap;
  filter: saturate(0.85);
  transition: filter var(--t), color var(--t);
}

.brandstrip__logos .bl:hover {
  filter: none;
  color: var(--ink);
}

.brandstrip__logos .bl .brand-glyph {
  box-shadow: inset 0 0 0 1px oklch(0.24 0.05 255 / 0.06);
}

/* Móvil: la leyenda encima del carrusel (compartir fila los estrujaba a ambos) */
@media (max-width: 640px) {
  .brandstrip__inner {
    padding-block: 1.1rem;
    gap: 0.7rem;
  }

  .brandstrip__label {
    flex-basis: 100%;
    max-width: none;
    text-align: center;
  }
}

/* =========================================================== BENTO ========== */
.bento {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-auto-rows: minmax(150px, auto);
  gap: clamp(0.8rem, 1.4vw, 1.15rem);
}

.bento__tile {
  position: relative;
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: clamp(1.25rem, 1rem + 1vw, 1.7rem);
  background: var(--surface);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  transition: transform var(--t) var(--ease-out), box-shadow var(--t);
}

.bento__tile:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-md);
}

.bento__tile h3 {
  font-size: 1.15rem;
  letter-spacing: -0.02em;
}

.bento__tile p {
  font-size: 0.9rem;
  color: var(--ink-muted);
  line-height: 1.5;
  margin-top: 0.4rem;
}

.bento__tile .spacer {
  flex: 1;
}

/* Tile destacado: oferta/producto (ancho) */
.bento__tile--feature {
  grid-column: span 2;
  grid-row: span 2;
}

.bt-offer {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.bt-offer__top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
}

.bt-offer__top .badge {
  background: var(--brand-50);
  color: var(--brand-ink);
  border: none;
}

.bt-offer h3 {
  font-size: clamp(1.5rem, 1.1rem + 1.4vw, 2rem);
  margin-top: 1rem;
  line-height: 1.1;
}

.bt-offer__glyphwrap {
  margin: 1.25rem 0;
  display: flex;
  align-items: flex-end;
  gap: 0.9rem;
}

.bt-offer__price {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
}

.bt-offer__price .now {
  font-size: 2.1rem;
  font-weight: 800;
  letter-spacing: -0.03em;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.bt-offer__price .old {
  font-size: 1rem;
  color: var(--ink-faint);
  text-decoration: line-through;
}

.bt-offer__foot {
  margin-top: auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding-top: 1.1rem;
}

/* Tile de proceso (antes oscuro; ahora claro, coherente con la página blanca) */
.bento__tile--dark {
  background: linear-gradient(170deg, var(--surface), var(--surface-2));
  border-color: var(--border);
  color: var(--ink-body);
  grid-column: span 2;
  grid-row: span 2;
}

.bento__tile--dark h3 {
  color: var(--ink);
}

.bento__tile--dark p {
  color: var(--ink-muted);
}

.bt-mini {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  margin-bottom: 1.1rem;
}

.bt-mini .row {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  color: var(--ink-muted);
}

.bt-mini .row .d {
  width: 0.55rem;
  height: 0.55rem;
  border-radius: 50%;
  background: #ff8a31;
  box-shadow: 0 0 0 0 #ff8a31;
  animation: pulseDot 2.2s var(--ease-out) infinite;
}

.bt-mini .row.q .d {
  background: oklch(0.55 0.02 230);
  animation: none;
}

@keyframes pulseDot {
  0% {
    box-shadow: 0 0 0 0 oklch(0.78 0.18 51 / 0.5);
  }

  70% {
    box-shadow: 0 0 0 7px oklch(0.78 0.18 51 / 0);
  }

  100% {
    box-shadow: 0 0 0 0 transparent;
  }
}

/* Tile verde (CTA WhatsApp) */
.bento__tile--green {
  background: var(--brand-strong);
  border-color: transparent;
  color: #fff;
}

.bento__tile--green h3 {
  color: #fff;
}

.bento__tile--green p {
  color: rgba(255, 255, 255, 0.9);
}

.bento__tile--green .wa-ic {
  display: inline-grid;
  place-items: center;
  width: 2.6rem;
  height: 2.6rem;
  border-radius: var(--r);
  background: rgba(255, 255, 255, 0.16);
  color: #fff;
  margin-bottom: auto;
}

.bento__tile--green .wa-ic svg {
  width: 1.4rem;
  height: 1.4rem;
}

.bento__tile--green .go {
  margin-top: 1rem;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-weight: 700;
}

.bento__tile--green .go svg {
  width: 1.05rem;
  height: 1.05rem;
  transition: transform var(--t);
}

.bento__tile--green:hover .go svg {
  transform: translateX(3px);
}

/* Tile proof (ancho, prueba integrada — NO números gigantes sueltos) */
.bento__tile--proof {
  grid-column: span 2;
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 1.5rem;
}

.bt-proof__fig {
  flex: none;
  width: 96px;
  height: 96px;
  display: grid;
  place-items: center;
  position: relative;
}

.bt-proof__num {
  font-size: 1.9rem;
  font-weight: 800;
  letter-spacing: -0.03em;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.bt-proof__txt b {
  color: var(--ink);
}

.bt-proof__flags {
  display: flex;
  gap: 0.4rem;
  margin-top: 0.7rem;
  flex-wrap: wrap;
}

.bt-proof__flags span {
  font-size: 0.72rem;
  font-weight: 600;
  padding: 0.2rem 0.5rem;
  border-radius: var(--r-pill);
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--ink-muted);
}

/* Tile simple con micro-ilustración */
.bt-icon {
  width: 2.8rem;
  height: 2.8rem;
  border-radius: var(--r);
  display: grid;
  place-items: center;
  background: var(--brand-50);
  color: var(--brand-ink);
  margin-bottom: auto;
}

.bt-icon svg {
  width: 1.4rem;
  height: 1.4rem;
}

@media (max-width: 860px) {
  .bento {
    grid-template-columns: repeat(2, 1fr);
  }

  .bento__tile--feature,
  .bento__tile--proof {
    grid-column: span 2;
  }

  .bento__tile--feature {
    grid-row: auto;
  }

  .bento__tile--dark {
    grid-column: span 2;
    grid-row: auto;
  }
}

@media (max-width: 520px) {
  .bento {
    grid-template-columns: 1fr;
  }

  .bento__tile--feature,
  .bento__tile--proof,
  .bento__tile--dark {
    grid-column: auto;
    grid-row: auto;
  }

  .bento__tile--proof {
    flex-direction: column;
    align-items: flex-start;
    text-align: left;
  }
}

/* ====================================================== CATEGORÍAS =========== */
.cats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(0.7rem, 1.4vw, 1rem);
}

.cat-tile {
  display: flex;
  flex-direction: column;
  gap: 0.8rem;
  padding: 1.3rem;
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--surface);
  transition: border-color var(--t), transform var(--t) var(--ease-out), box-shadow var(--t);
}

.cat-tile:hover {
  transform: translateY(-3px);
  border-color: var(--border-strong);
  box-shadow: var(--shadow-sm);
}

.cat-tile .glyphrow {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.cat-tile h4 {
  font-size: 1rem;
}

.cat-tile .cnt {
  font-size: 0.8rem;
  color: var(--ink-faint);
}

.cat-tile .arrow {
  color: var(--ink-faint);
  display: inline-flex;
  transition: color var(--t), transform var(--t);
}

.cat-tile:hover .arrow {
  color: var(--brand-ink);
  transform: translateX(2px);
}

.cat-tile .arrow svg {
  width: 1.1rem;
  height: 1.1rem;
}

/* primera categoría destacada (rompe la uniformidad) */
.cat-tile--lead {
  grid-column: span 2;
  flex-direction: row;
  align-items: center;
  gap: 1.2rem;
  background: var(--bg-subtle);
}

.cat-tile--lead .glyphrow {
  flex-direction: column;
  align-items: flex-start;
}

.cat-tile--lead .body {
  flex: 1;
}

.cat-tile--lead p {
  font-size: 0.88rem;
  color: var(--ink-muted);
  margin-top: 0.25rem;
}

@media (max-width: 820px) {
  .cats {
    grid-template-columns: repeat(2, 1fr);
  }

  .cat-tile--lead {
    grid-column: span 2;
  }
}

@media (max-width: 460px) {
  .cats {
    grid-template-columns: 1fr;
  }

  .cat-tile--lead {
    grid-column: auto;
    flex-direction: column;
    align-items: flex-start;
  }
}

/* ====================================================== PRODUCTOS ============ */
/* auto-fit (no auto-fill) colapsa las pistas vacías y, con un máximo fijo (no 1fr), las
   tarjetas no se estiran; justify-content:center centra la fila. Así 1-3 productos se ven
   intencionales (centrados) y muchos llenan y hacen wrap sin dejar huecos rotos. */
.product-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 256px), 340px));
  justify-content: center;
  gap: clamp(1rem, 2vw, 1.4rem);
}

.sec-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1.5rem;
  flex-wrap: wrap;
  margin-bottom: clamp(1.5rem, 1rem + 2vw, 2.5rem);
}

/* Titular editorial (referencia Ari): grande, ligero y apretado */
.sec-head__t h2 {
  font-size: clamp(1.9rem, 1rem + 3.1vw, 3.9rem);
  font-weight: 360;
  letter-spacing: -0.035em;
  line-height: 1.04;
  text-wrap: balance;
}

/* :not(.sec-eyebrow): la ceja "— CATÁLOGO" es <p> pero va en verde (styles.css) */
.sec-head__t p:not(.sec-eyebrow) {
  color: var(--ink-muted);
  margin-top: 0.5rem;
  max-width: 48ch;
}

/* Variante centrada del encabezado de sección (usada en "Cómo funciona tu
   compra en vivo": título, ceja y bajada alineados al centro). */
.sec-head--center { justify-content: center; text-align: center; }
/* Columna centrada: así la ceja, el título y la bajada quedan al medio en el
   celular sin importar su display propio (la ceja "Proceso" es flex y no
   obedecía a text-align, por eso se veía pegada a la izquierda). En desktop con
   el tour 3D manda la rejilla editorial de hero3d.css (más específica); esto
   solo endereza el móvil. */
.sec-head--center .sec-head__t {
  width: 100%; margin-inline: auto;
  display: flex; flex-direction: column; align-items: center;
}
.sec-head--center .sec-head__t p:not(.sec-eyebrow) { margin-inline: auto; }
.sec-head--center .sec-eyebrow { justify-content: center; }

/* ==================================================== CÓMO FUNCIONA ========== */
.flow {
  position: relative;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: clamp(1rem, 2vw, 1.75rem);
}

.flow::before {
  content: "";
  position: absolute;
  top: 1.4rem;
  left: 7%;
  right: 7%;
  height: 2px;
  background: repeating-linear-gradient(90deg, var(--border-strong) 0 8px, transparent 8px 16px);
  z-index: 0;
}

.flow__step {
  position: relative;
  z-index: 1;
}

.flow__num {
  width: 2.8rem;
  height: 2.8rem;
  border-radius: 50%;
  background: var(--surface);
  border: 2px solid var(--border-strong);
  display: grid;
  place-items: center;
  font-weight: 800;
  color: var(--ink);
  font-size: 1.05rem;
  margin-bottom: 1.1rem;
  transition: border-color var(--t), background-color var(--t), color var(--t);
}

.flow__step:hover .flow__num {
  border-color: var(--brand);
  color: var(--brand-ink);
  background: var(--brand-50);
}

.flow__step h4 {
  font-size: 1.05rem;
}

.flow__step p {
  font-size: 0.9rem;
  color: var(--ink-muted);
  margin-top: 0.4rem;
  line-height: 1.5;
}

.flow__step .ic {
  color: var(--brand);
  margin-bottom: 0.6rem;
  display: inline-flex;
}

.flow__step .ic svg {
  width: 1.3rem;
  height: 1.3rem;
}

@media (max-width: 1080px) {
  .flow {
    grid-template-columns: repeat(3, 1fr);
  }

  .flow::before {
    display: none;
  }
}

@media (max-width: 820px) {
  .flow {
    grid-template-columns: 1fr 1fr;
  }
}

/* Móvil: cada paso en FILA (número a la izquierda, texto a la derecha).
   Los 5 pasos pasan de ~5 pantallas apiladas a una lista corta y escaneable. */
@media (max-width: 640px) {
  .flow {
    grid-template-columns: 1fr;
    gap: 0.85rem;
  }

  .flow__step {
    display: grid;
    grid-template-columns: 2.4rem minmax(0, 1fr);
    column-gap: 0.9rem;
    align-items: start;
  }

  .flow__num {
    width: 2.4rem;
    height: 2.4rem;
    font-size: 0.95rem;
    margin-bottom: 0;
    grid-row: 1 / span 2;
  }

  .flow__step .ic {
    display: none;
  }

  .flow__step h4 {
    grid-column: 2;
    align-self: center;
    font-size: 1rem;
  }

  .flow__step p {
    grid-column: 2;
    margin-top: 0.2rem;
  }
}

/* ========================================================== CÓMO PAGAR ======= */
/* Dos columnas: el panel de la pasarela con las tarjetas aceptadas y, al lado,
   por qué el pago es seguro + la salida por WhatsApp. Las marcas (.paymark) las
   dibuja icons.js y su tarjetita blanca vive en commerce.css. */
/* minmax(0, …): las columnas se reparten el ancho disponible y NO se estiran
   hasta el elemento más ancho de dentro (los logos de tarjetas, el sello de la
   pasarela). Con `1.15fr 0.85fr` a secas, el apartado entero se salía. */
.paysec {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
  gap: clamp(1.1rem, 2vw, 1.75rem);
  align-items: start;
  max-width: 78rem;
  margin-inline: auto;
}

.paysec > * {
  min-width: 0;
}

/* ---- Panel de la pasarela ---- */
.paypanel {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
  padding: clamp(1.35rem, 2.4vw, 2rem);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--surface);
  box-shadow: var(--shadow-md);
}

.paypanel__head {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  flex-wrap: wrap;
  padding-bottom: 1.15rem;
  border-bottom: 1px solid var(--border);
}

/* Tarjetita dibujada del encabezado: se inclina y levanta al pasar el cursor */
.paycard3d {
  display: block;
  width: 3.3rem;
  flex: none;
  transform: rotate(-8deg);
  filter: drop-shadow(0 5px 10px oklch(0.45 0.13 51 / 0.32));
  transition: transform var(--t-slow) var(--ease-out);
}

.paycard3d svg {
  display: block;
  width: 100%;
  height: auto;
}

.paypanel:hover .paycard3d {
  transform: rotate(-2deg) translateY(-3px) scale(1.04);
}

.paypanel__id {
  display: flex;
  flex-direction: column;
  gap: 0.12rem;
  min-width: 0;
  flex: 1 1 12rem;
}

.paypanel__id b {
  font-size: 1.02rem;
  color: var(--ink);
}

.paypanel__id span {
  font-size: 0.86rem;
  color: var(--ink-muted);
}

/* ---- Sello animado de la pasarela -----------------------------------------
   Bucle de 6 s: pasa un destello (la tarjeta leyéndose) y el sello cambia de
   "Procesado por izipay" a un "Pago realizado" en verde, y vuelve. Las dos
   caras se apilan en la MISMA celda de la rejilla, así el sello no cambia de
   tamaño ni empuja nada al alternar. */
.paygw {
  position: relative;
  display: inline-grid;
  place-items: center;
  overflow: hidden;
  padding: 0.45rem 0.75rem;
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  background: var(--surface-2);
  flex: none;
  animation: gwPiel 6s var(--ease-out) infinite;
}

.paygw__face {
  grid-area: 1 / 1;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  white-space: nowrap;
}

.paygw__face--gw {
  animation: gwCaraSello 6s var(--ease-out) infinite;
}

.paygw__face--ok {
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--brand-ink);
  opacity: 0;
  animation: gwCaraOk 6s var(--ease-out) infinite;
}

.paygw__face--ok svg {
  width: 1.05rem;
  height: 1.05rem;
  flex: none;
}

.paygw .paymark {
  width: 3.5rem;
  height: 2.1rem;
}

.paygw small {
  font-size: 0.72rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--ink-faint);
}

/* La tarjeta que cruza el sello, como al pasarla por el datáfono.
   Se anima `left` (y no transform) a propósito: el porcentaje es del ancho del
   sello, así cruza igual de bien el sello angosto del escritorio que el de
   ancho completo del celular, sin recalcular distancias. */
.paygw__swipe {
  position: absolute;
  top: 50%;
  left: -2.2rem;
  width: 1.7rem;
  height: 1.1rem;
  margin-top: -0.55rem;
  border-radius: 3px;
  pointer-events: none;
  transform: rotate(-7deg);
  background: linear-gradient(150deg, #e7883b, #723e14);
  box-shadow: 0 2px 6px oklch(0.45 0.13 51 / 0.45);
  animation: gwPasada 6s var(--ease-out-soft) infinite;
}

/* Chip dorado y banda: a este tamaño es lo que la vuelve "una tarjeta" */
.paygw__swipe::before {
  content: "";
  position: absolute;
  left: 0.24rem;
  top: 0.38rem;
  width: 0.36rem;
  height: 0.28rem;
  border-radius: 1px;
  background: linear-gradient(180deg, #ffdd85, #dda037);
}

.paygw__swipe::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 0.14rem;
  height: 0.2rem;
  background: #06301f;
  opacity: 0.78;
}

/* Guion del bucle (6 s), pensado para que la tarjeta nunca pise el texto:
   0–10%  el sello dice "Procesado por izipay"
   10–16% ese texto se retira
   14–34% la tarjeta cruza el sello vacío
   36–42% el sello se pone verde y confirma "Pago realizado"
   42–84% se queda ahí (lo que el visitante alcanza a leer)
   84–100% vuelve al principio */
@keyframes gwPasada {
  0%, 12% {
    left: -2.2rem;
    opacity: 0;
  }

  16% {
    opacity: 1;
  }

  32% {
    left: 100%;
    opacity: 1;
  }

  36%, 100% {
    left: 100%;
    opacity: 0;
  }
}

@keyframes gwCaraSello {
  0%, 10% {
    opacity: 1;
    transform: translateY(0);
  }

  16%, 84% {
    opacity: 0;
    transform: translateY(-0.45rem);
  }

  92%, 100% {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes gwCaraOk {
  0%, 36% {
    opacity: 0;
    transform: translateY(0.45rem);
  }

  43%, 84% {
    opacity: 1;
    transform: translateY(0);
  }

  90%, 100% {
    opacity: 0;
    transform: translateY(0.45rem);
  }
}

@keyframes gwPiel {
  0%, 36% {
    background: var(--surface-2);
    border-color: var(--border);
  }

  43%, 84% {
    background: var(--brand-50);
    border-color: color-mix(in oklch, var(--brand) 45%, transparent);
  }

  92%, 100% {
    background: var(--surface-2);
    border-color: var(--border);
  }
}

.paypanel__brands {
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
}

.paypanel__label {
  font-size: 0.76rem;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

/* Las tarjetas se muestran más grandes aquí que en el pie o el modal: es el
   apartado donde el visitante viene justamente a mirarlas. */
.paypanel__marks {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
}

.paypanel__marks .paymark {
  width: 4.4rem;
  height: 2.75rem;
  padding: 0.3rem 0.42rem;
  border-radius: 8px;
}

.paypanel__facts {
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
}

.paypanel__facts li {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  font-size: 0.94rem;
  color: var(--ink-body);
  line-height: 1.5;
}

.paypanel__facts b {
  color: var(--ink);
}

.paypanel__facts svg {
  width: 1.1rem;
  height: 1.1rem;
  color: var(--brand);
  flex: none;
  margin-top: 0.15rem;
}

.paypanel__cta {
  align-self: flex-start;
}

/* ---- Columna derecha: confianza + WhatsApp ---- */
.paysec__side {
  display: flex;
  flex-direction: column;
  gap: clamp(1.1rem, 2vw, 1.5rem);
}

.paytrust {
  padding: clamp(1.35rem, 2.4vw, 1.75rem);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--bg-subtle);
}

.paytrust h3 {
  font-size: 1.08rem;
  margin-bottom: 1.1rem;
}

.paytrust__list {
  display: flex;
  flex-direction: column;
  gap: 1.05rem;
}

.paytrust__list li {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
}

/* Pastilla con relieve (no el cuadrado plano de antes): degradado, filo de luz
   arriba, aro verde tenue y sombra propia. Se levanta al pasar por la fila. */
.paytrust__ic {
  position: relative;
  display: grid;
  place-items: center;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 0.85rem;
  border: 1px solid color-mix(in oklch, var(--brand) 26%, var(--border));
  background: linear-gradient(155deg, var(--surface) 8%, var(--brand-50) 100%);
  box-shadow:
    inset 0 1px 0 #fff,
    0 1px 2px oklch(0.45 0.13 51 / 0.10),
    0 5px 12px oklch(0.45 0.13 51 / 0.14);
  color: var(--brand-ink);
  flex: none;
  transition: transform var(--t) var(--ease-out), box-shadow var(--t) var(--ease-out);
}

/* Aro interior: le da el borde "de vidrio" sin sumar otro elemento */
.paytrust__ic::after {
  content: "";
  position: absolute;
  inset: 2px;
  border-radius: 0.65rem;
  border: 1px solid color-mix(in oklch, #fff 70%, transparent);
  pointer-events: none;
}

.paytrust__list li:hover .paytrust__ic {
  transform: translateY(-2px);
  box-shadow:
    inset 0 1px 0 #fff,
    0 2px 4px oklch(0.45 0.13 51 / 0.12),
    0 9px 18px oklch(0.45 0.13 51 / 0.20);
}

.paytrust__ic svg {
  width: 1.1rem;
  height: 1.1rem;
}

.paytrust__list b {
  display: block;
  font-size: 0.95rem;
  color: var(--ink);
}

.paytrust__list div span {
  display: block;
  margin-top: 0.2rem;
  font-size: 0.88rem;
  color: var(--ink-muted);
  line-height: 1.55;
}

@media (max-width: 1080px) {
  .paysec {
    grid-template-columns: minmax(0, 1fr);
    max-width: 44rem;
  }
}

/* Celular: el apartado entra en una pantalla y media, sin aire de más */
@media (max-width: 560px) {
  .paysec {
    gap: 0.9rem;
  }

  .paypanel {
    gap: 1rem;
    padding: 1.15rem 1rem;
  }

  .paypanel__head {
    gap: 0.7rem;
    padding-bottom: 0.95rem;
  }

  .paycard3d {
    width: 2.8rem;
  }

  .paypanel__id b {
    font-size: 0.97rem;
  }

  .paygw {
    order: 3;
    width: 100%;
    padding: 0.4rem 0.6rem;
  }

  .paypanel__marks .paymark {
    width: 3.7rem;
    height: 2.3rem;
  }

  .paypanel__facts {
    gap: 0.6rem;
  }

  .paypanel__facts li {
    font-size: 0.9rem;
  }

  .paypanel__cta {
    align-self: stretch;
    justify-content: center;
  }

  .paytrust {
    padding: 1.15rem 1rem;
  }

  .paytrust h3 {
    margin-bottom: 0.9rem;
  }

  .paytrust__list {
    gap: 0.85rem;
  }

  .paytrust__ic {
    width: 2.2rem;
    height: 2.2rem;
    border-radius: 0.7rem;
  }

  .paytrust__list div span {
    font-size: 0.86rem;
  }
}

/* Con movimiento reducido el sello se queda quieto en "Procesado por izipay":
   nada parpadea ni se desliza, pero la información sigue completa. */
@media (prefers-reduced-motion: reduce) {

  .paygw,
  .paygw__face--gw {
    animation: none;
  }

  .paygw__swipe,
  .paygw__face--ok {
    display: none;
  }

  .paycard3d,
  .paytrust__ic {
    transition: none;
  }
}

/* ====================================================== SOPORTE + CHAT ======= */
/* Centrado en una sola columna al medio (pedido del dueño), en móvil y web,
   igual que el apartado de Proceso: encabezado arriba y el chat debajo. */
.support2 {
  display: grid;
  /* minmax(0,1fr): con `1fr` la columna nunca baja del contenido más ancho
     (un botón con rótulo largo) y el bloque se salía por la derecha en celular */
  grid-template-columns: minmax(0, 1fr);
  justify-items: center;
  text-align: center;
  gap: clamp(2rem, 4vw, 3rem);
  max-width: 60rem;
  margin-inline: auto;
}

.support2__copy,
.support2__copy h2,
.support2__copy p {
  min-width: 0;
  overflow-wrap: break-word;
}

.support2__copy {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
}

/* La ceja "SOPORTE REAL" en verde de marca: la regla genérica .support2__copy p
   (más específica que .sec-eyebrow) la teñía de gris. */
.support2__copy .sec-eyebrow { color: oklch(0.55 0.16 47); justify-content: center; }

.support2__copy h2 {
  font-size: clamp(1.7rem, 1.2rem + 2vw, 2.4rem);
  letter-spacing: -0.025em;
}

.support2__copy p {
  color: var(--ink-muted);
  margin-top: 1rem;
  font-size: 1.05rem;
  max-width: 46ch;
  margin-inline: auto;
}

/* La lista de garantías se centra como bloque, pero cada ítem mantiene su
   texto alineado a la izquierda para que se lea cómodo. */
.support2__list { text-align: left; }
.support2__cta { display: flex; justify-content: center; }
.chat { width: 100%; max-width: 34rem; margin-inline: auto; }

.support2__list {
  margin-top: 1.6rem;
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
}

.support2__list li {
  display: flex;
  gap: 0.65rem;
  align-items: flex-start;
  color: var(--ink-body);
}

.support2__list li svg {
  width: 1.25rem;
  height: 1.25rem;
  color: var(--brand);
  flex: none;
  margin-top: 0.1rem;
}

.support2__cta {
  margin-top: 1.9rem;
}

.chat {
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  padding: clamp(1.25rem, 1rem + 1.5vw, 1.85rem);
  box-shadow: var(--shadow-sm);
}

.chat__head {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding-bottom: 1rem;
  margin-bottom: 1.1rem;
  border-bottom: 1px solid var(--border);
}

/* El bloque de texto de la cabecera del chat tiene que poder encogerse: "así se
   ve una conversación típica" es largo y empujaba la fila fuera de la tarjeta. */
.chat__head > span {
  min-width: 0;
  overflow-wrap: break-word;
}

.chat__head span {
  flex-wrap: wrap;
}

.chat__head .av {
  width: 2.4rem;
  height: 2.4rem;
  border-radius: 50%;
  background: var(--brand-strong);
  color: #fff;
  display: grid;
  place-items: center;
  flex: none;
  object-fit: cover;
}

.chat__head .av svg {
  width: 1.25rem;
  height: 1.25rem;
}

.chat__head b {
  display: block;
  font-size: 0.95rem;
  color: var(--ink);
}

.chat__head span {
  font-size: 0.8rem;
  color: var(--brand-ink);
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}

.chat__head span::before {
  content: "";
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--brand);
}

.chat__thread {
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
}

.chat__b {
  max-width: 82%;
  padding: 0.7rem 0.95rem;
  font-size: 0.9rem;
  line-height: 1.45;
  border-radius: 1.1rem;
}

.chat__b--in {
  align-self: flex-start;
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--ink-body);
  border-bottom-left-radius: 0.3rem;
}

.chat__b--out {
  align-self: flex-end;
  background: var(--brand-strong);
  color: #fff;
  border-bottom-right-radius: 0.3rem;
}

.chat__b--ok {
  align-self: flex-end;
  background: var(--brand-50);
  color: var(--brand-ink);
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  border: 1px solid color-mix(in oklch, var(--brand) 25%, transparent);
}

.chat__b--ok svg {
  width: 1.1rem;
  height: 1.1rem;
}

/* Honestidad: la conversación es una ilustración y se declara como tal */
.chat__example {
  margin: 1rem 0 0;
  padding-top: 0.85rem;
  border-top: 1px dashed var(--border);
  font-size: 0.78rem;
  color: var(--ink-faint);
  text-align: center;
}

/* (En móvil ya no se invierte el orden: el encabezado va arriba y el chat
   debajo, coherente con el centrado en una sola columna.) */

/* ---- Chat en vivo: la conversación se reproduce sola, como asistencia real --- */
.chat__thread {
  min-height: clamp(12.5rem, 30vh, 16rem);
  justify-content: flex-end;
}

.chat__b {
  opacity: 0;
  transform: translateY(9px) scale(0.985);
  transform-origin: bottom left;
  animation: chatIn 0.34s var(--ease-out) forwards;
}

.chat__b--out,
.chat__b--ok {
  transform-origin: bottom right;
}

@keyframes chatIn {
  to {
    opacity: 1;
    transform: none;
  }
}

.chat__typing {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 0.32rem;
  padding: 0.85rem 1rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 1.1rem;
  border-bottom-left-radius: 0.3rem;
  opacity: 0;
  animation: chatIn 0.22s var(--ease-out) forwards;
}

.chat__typing--out {
  align-self: flex-end;
  background: var(--brand-strong);
  border-color: transparent;
  border-bottom-left-radius: 1.1rem;
  border-bottom-right-radius: 0.3rem;
}

.chat__typing i {
  width: 0.42rem;
  height: 0.42rem;
  border-radius: 50%;
  background: var(--ink-faint);
  animation: chatDot 1.1s infinite ease-in-out;
}

.chat__typing--out i {
  background: rgba(255, 255, 255, 0.9);
}

.chat__typing i:nth-child(2) {
  animation-delay: 0.16s;
}

.chat__typing i:nth-child(3) {
  animation-delay: 0.32s;
}

@keyframes chatDot {

  0%,
  70%,
  100% {
    transform: translateY(0);
    opacity: 0.45;
  }

  35% {
    transform: translateY(-0.3rem);
    opacity: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .chat__b {
    opacity: 1;
    transform: none;
    animation: none;
  }

  .chat__typing i {
    animation: none;
  }
}

/* ============================================ DEMO: compra en vivo (web) === */
.demo {
  display: grid;
  grid-template-columns: 230px 1fr;
  gap: clamp(1.5rem, 3vw, 2.75rem);
  align-items: start;
  margin-top: clamp(1.5rem, 3vw, 2.5rem);
}

/* Demo protagonista: una sola columna con la tarjeta centrada y un ancho
   contenido. Los 5 pasos van ARRIBA en fila (clicables para volver o saltar
   a cualquier paso, pedido del dueño 23-jul-2026). */
.demo--center { grid-template-columns: 1fr; max-width: 44rem; margin-inline: auto; }
.demo--center .demo__steps {
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.35rem clamp(0.9rem, 2.5vw, 1.6rem);
  position: static;
  margin-bottom: 0.35rem;
}
/* En fila no aplica la línea vertical que conecta los pasos de la barra lateral */
.demo--center .demo-step:not(:last-child)::after { display: none; }

.demo__steps {
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 6rem;
}

.demo-step {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.85rem;
  padding: 0.55rem 0;
}

.demo-step:not(:last-child)::after {
  content: "";
  position: absolute;
  left: 1.05rem;
  top: 2.4rem;
  bottom: -0.25rem;
  width: 2px;
  background: var(--border-strong);
  transition: background-color 0.5s var(--ease-out) 0.15s;
}

.demo-step__n {
  z-index: 1;
  flex: none;
  width: 2.15rem;
  height: 2.15rem;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-weight: 800;
  font-size: 0.92rem;
  background: var(--surface);
  border: 2px solid var(--border-strong);
  color: var(--ink-muted);
  transition: border-color var(--t), background-color var(--t), color var(--t), box-shadow var(--t);
}

.demo-step__n svg {
  width: 1.05rem;
  height: 1.05rem;
}

.demo-step__k {
  font-weight: 600;
  color: var(--ink-muted);
  transition: color var(--t);
}

.demo-step.is-active .demo-step__n {
  border-color: var(--brand);
  background: var(--brand-50);
  color: var(--brand-ink);
  box-shadow: 0 0 0 4px var(--brand-50);
  animation: stepPopA 0.5s var(--ease-out), stepPulse 2.2s var(--ease-out) 0.7s infinite;
}

.demo-step.is-active .demo-step__k {
  color: var(--ink);
}

.demo-step.is-done .demo-step__n {
  border-color: var(--brand);
  background: var(--brand);
  color: #fff;
  animation: stepPopB 0.45s var(--ease-out);
}

@keyframes stepPopA {
  0% {
    transform: scale(0.72);
  }

  55% {
    transform: scale(1.14);
  }

  100% {
    transform: none;
  }
}

@keyframes stepPopB {
  0% {
    transform: scale(0.72);
  }

  55% {
    transform: scale(1.14);
  }

  100% {
    transform: none;
  }
}

@keyframes stepPulse {
  0% {
    box-shadow: 0 0 0 4px var(--brand-50), 0 0 0 4px color-mix(in oklch, var(--brand) 35%, transparent);
  }

  60% {
    box-shadow: 0 0 0 4px var(--brand-50), 0 0 0 11px transparent;
  }

  100% {
    box-shadow: 0 0 0 4px var(--brand-50), 0 0 0 0 transparent;
  }
}

.demo-step.is-done .demo-step__k {
  color: var(--ink-body);
}

.demo-step.is-done:not(:last-child)::after {
  background: var(--brand);
}

.demo__stage {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  min-width: 0;
}

.demo__app {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-md);
  overflow: hidden;
}

.demo__chrome {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem 0.8rem;
  flex-wrap: wrap;              /* "dropdigitals.com" y "Pago seguro" se apilan si no caben */
  padding: 0.65rem clamp(0.7rem, 3vw, 1rem);
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
}

.demo__brand,
.demo__safe {
  min-width: 0;
}

.demo__brand {
  overflow-wrap: anywhere;
}

.demo__brand {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-weight: 700;
  font-size: 0.88rem;
  color: var(--ink-strong);
}

.demo__logo {
  display: inline-grid;
  width: 1.65rem;
  height: 1.65rem;
  flex: none;
}

/* Barra de tiempo de la pantalla en curso (avanza mientras dura el paso) */
.demo__timer {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 2px;
  background: var(--brand);
  transform: scaleX(0);
  transform-origin: 0 50%;
  z-index: 1;
  pointer-events: none;
}

.demo__safe {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--brand-ink);
}

.demo__safe svg {
  width: 0.95rem;
  height: 0.95rem;
  color: var(--brand);
}

.demo__screen {
  position: relative;
  min-height: 360px;
  padding: clamp(0.9rem, 2.5vw, 2rem);
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-content: center;
  min-width: 0;
}

.dsc {
  animation: scIn 0.4s var(--ease-out) both;
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  /* La ficha de la simulación jamás debe ser más ancha que la pantalla */
  min-width: 0;
  max-width: 100%;
}

.dsc--center {
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: 0.9rem;
}

@keyframes scIn {
  from {
    opacity: 0;
    transform: translateY(10px);
  }

  to {
    opacity: 1;
    transform: none;
  }
}

/* Entrada en cascada: cada elemento de la pantalla aparece uno tras otro */
.dsc>* {
  animation: scIn 0.5s var(--ease-out) both;
}

.dsc> :nth-child(2) {
  animation-delay: 90ms;
}

.dsc> :nth-child(3) {
  animation-delay: 180ms;
}

.dsc> :nth-child(4) {
  animation-delay: 270ms;
}

.dsc> :nth-child(5) {
  animation-delay: 360ms;
}

.dsc> :nth-child(6) {
  animation-delay: 450ms;
}

.dsc> :nth-child(7) {
  animation-delay: 540ms;
}

.dsc>.dsc-spin {
  animation: spin 0.8s linear infinite;
}

/* "Clic" simulado sobre el botón justo antes de pasar de pantalla */
.dsc .dsc-press.is-tapped {
  animation: tapPress 0.42s var(--ease-out) both;
}

@keyframes tapPress {
  0% {
    transform: scale(1);
  }

  38% {
    transform: scale(0.94);
  }

  100% {
    transform: scale(1);
  }
}

.dsc h4 {
  font-size: 1.25rem;
  letter-spacing: -0.015em;
}

.dsc-mut {
  color: var(--ink-muted);
  font-size: 0.95rem;
  line-height: 1.5;
  max-width: 40ch;
}

.dsc--center .dsc-mut {
  margin-inline: auto;
}

.dsc--prod {
  align-items: center;
  text-align: center;
}

.dsc-prod__media {
  display: grid;
  place-items: center;
}

.dsc-prod__img {
  width: 96px;
  height: 96px;
  object-fit: contain;
  border-radius: var(--r);
}

.dsc-tag {
  align-self: center;
  font-size: 0.72rem;
  font-weight: 700;
  color: #fff;
  background: var(--brand-strong);
  padding: 0.25rem 0.7rem;
  border-radius: var(--r-pill);
}

.dsc-price {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;          /* el precio tachado baja de línea si no cabe */
  gap: 0.15rem 0.6rem;
  justify-content: center;
  min-width: 0;
}

.dsc-price b {
  font-size: 1.7rem;
  font-weight: 800;
  color: var(--ink);
}

.dsc-price s {
  color: var(--ink-faint);
}

.dsc-press {
  margin-top: 0.4rem;
  max-width: 320px;
  align-self: center;
  animation: scIn 0.5s var(--ease-out) both, press 1.5s var(--ease-out) 0.8s infinite;
}

@keyframes press {

  0%,
  100% {
    box-shadow: 0 0 0 0 color-mix(in oklch, var(--brand) 45%, transparent);
  }

  55% {
    box-shadow: 0 0 0 9px transparent;
  }
}

.dsc-h {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-weight: 700;
  color: var(--ink);
}

.dsc-h svg {
  width: 1rem;
  height: 1rem;
  color: var(--brand);
}

.dsc-sum {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.25rem 0.6rem;
  min-width: 0;
  padding: 0.85rem 1rem;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r);
}

.dsc-sum b {
  font-size: 1.1rem;
}

.dsc-pm {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.7rem 0.9rem;
  border: 2px solid var(--brand);
  border-radius: var(--r);
  font-weight: 600;
  background: var(--brand-50);
  color: var(--ink);
}

.dsc-pm svg {
  width: 1.15rem;
  height: 1.15rem;
  color: var(--brand-ink);
}

.dsc-pm-row {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.dsc-pm-row span {
  font-size: 0.78rem;
  color: var(--ink-muted);
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  padding: 0.3rem 0.7rem;
}

.dsc-secure {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.8rem;
  color: var(--ink-faint);
}

.dsc-secure svg {
  width: 1rem;
  height: 1rem;
  color: var(--brand);
}

.dsc-spin {
  width: 3rem;
  height: 3rem;
  border-radius: 50%;
  border: 3px solid var(--border);
  border-top-color: var(--brand);
  animation: spin 0.8s linear infinite;
}

/* Puntos suspensivos animados de "Procesando tu pago..." */
.dsc-ell i {
  font-style: normal;
  animation: ellBlink 1.2s infinite;
}

.dsc-ell i:nth-child(2) {
  animation-delay: 0.2s;
}

.dsc-ell i:nth-child(3) {
  animation-delay: 0.4s;
}

@keyframes ellBlink {

  0%,
  100% {
    opacity: 0.15;
  }

  40% {
    opacity: 1;
  }
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

.dsc-prog {
  width: min(260px, 80%);
  height: 6px;
  border-radius: var(--r-pill);
  background: var(--surface-2);
  overflow: hidden;
}

.dsc-prog i {
  display: block;
  height: 100%;
  width: 0;
  background: var(--brand);
  border-radius: inherit;
  animation: prog 1.6s var(--ease-out) forwards;
}

@keyframes prog {
  to {
    width: 100%;
  }
}

.dsc-check {
  width: 4rem;
  height: 4rem;
  border-radius: 50%;
  display: grid;
  place-items: center;
}

.dsc-check svg {
  width: 2.3rem;
  height: 2.3rem;
}

.dsc-check.ok {
  background: var(--brand-50);
  color: var(--brand);
  animation: pop 0.4s var(--ease-out) both, ringOut 0.9s var(--ease-out) 0.35s;
}

@keyframes ringOut {
  from {
    box-shadow: 0 0 0 0 color-mix(in oklch, var(--brand) 40%, transparent);
  }

  to {
    box-shadow: 0 0 0 20px transparent;
  }
}

.dsc-check.soft {
  background: var(--surface-2);
  color: var(--brand-ink);
}

.dsc-check.big {
  width: 4.8rem;
  height: 4.8rem;
}

.dsc-check.big svg {
  width: 2.8rem;
  height: 2.8rem;
}

@keyframes pop {
  from {
    opacity: 0;
    transform: scale(0.85);
  }

  to {
    opacity: 1;
    transform: none;
  }
}

.dsc-deliver {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  flex-wrap: wrap;
}

/* Check minimalista junto a "Tu licencia está disponible" (reemplaza al chip
   "🎉 Listo", pedido del dueño 23-jul-2026: coherente con el resto, sin pill). */
.dsc-deliver__ok { display: inline-grid; place-items: center; color: var(--brand-ink); }
.dsc-deliver__ok svg { width: 1.35rem; height: 1.35rem; }

.dsc-lic {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.7rem 0.85rem;
  background: var(--surface-2);
  border: 1px dashed color-mix(in oklch, var(--brand) 35%, var(--border));
  border-radius: var(--r);
}

.dsc-lic span {
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  color: var(--ink-faint);
}

.dsc-lic code {
  flex: 1;
  font-family: var(--font-mono);
  font-size: 0.85rem;
  color: var(--ink-strong);
  letter-spacing: 0.02em;
  overflow: hidden;
  text-overflow: ellipsis;
}

.dsc-lic svg {
  width: 1rem;
  height: 1rem;
  color: var(--ink-faint);
}

.dsc-steps__t {
  font-weight: 700;
  font-size: 0.85rem;
  margin-top: 0.3rem;
}

.dsc-steps {
  margin: 0;
  padding-left: 1.15rem;
  display: grid;
  gap: 0.3rem;
  font-size: 0.9rem;
  color: var(--ink-body);
}

.dsc-help {
  font-size: 0.82rem;
  color: var(--ink-faint);
}

.dsc--win .dsc-win__tags {
  display: flex;
  gap: 0.6rem;
  flex-wrap: wrap;
  justify-content: center;
  margin-top: 0.3rem;
}

.dsc-win__tags span {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--brand-ink);
  background: var(--brand-50);
  border-radius: var(--r-pill);
  padding: 0.4rem 0.8rem;
}

.dsc-win__tags svg {
  width: 1rem;
  height: 1rem;
  color: var(--brand);
}

/* Pasos clicables: cada paso es un botón para volver/saltar en la demo */
.demo-step {
  background: none;
  border: 0;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.demo-step:hover .demo-step__n {
  border-color: var(--brand);
  color: var(--brand-ink);
}

.demo-step:hover .demo-step__k {
  color: var(--ink);
}

.demo-step:focus-visible {
  outline: none;
  border-radius: var(--r-sm);
  box-shadow: var(--ring);
}

/* Botonera fiel de la ficha (Comprar por WhatsApp / Pagar ahora / Agregar) */
.dsc-wbtn {
  max-width: 340px;
  width: 100%;
  align-self: center;
}

/* minmax(0,1fr) y no 1fr: con `1fr` cada columna nunca baja del ancho natural
   de su botón ("Comprar por WhatsApp" no parte línea), así que la pantalla de la
   simulación se quedaba clavada en 340 px y en un celular de 320 px —o con la
   letra del sistema en grande— empujaba la página entera hacia la derecha. */
.dsc-btnrow {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 0.5rem;
  width: 100%;
  max-width: 340px;
  align-self: center;
}

/* Los dos botones de la fila reparten el ancho y parten línea si hace falta:
   recortarlos (overflow) dejaba "Comprar por WhatsApp" cortado a la mitad. */
.dsc-btnrow > .btn {
  min-width: 0;
  padding-inline: 0.5rem;
  white-space: normal;
  line-height: 1.2;
}

/* Pantalla muy angosta: los dos botones se apilan. "WhatsApp" es una palabra
   larga y sin cortarla no cabe en media columna de 120 px. */
@media (max-width: 430px) {
  .dsc-btnrow {
    grid-template-columns: minmax(0, 1fr);
  }
}

.dsc-btnrow .dsc-press {
  margin-top: 0;
  max-width: none;
}

/* Réplica del modal "¿Cómo quieres completar tu compra?" (cuenta o invitado) */
.dsc--co {
  gap: 0.6rem;
  text-align: left;
}

.dsc--co h4 {
  text-align: center;
  font-size: 1.08rem;
}

.dsc-co {
  border: 1px solid var(--border);
  border-radius: var(--r);
  background: var(--surface);
  padding: 0.75rem 0.85rem;
  display: grid;
  gap: 0.45rem;
}

.dsc-co--rec {
  border-color: color-mix(in oklch, var(--brand) 45%, var(--border));
  box-shadow: 0 0 0 3px var(--brand-50);
}

.dsc-co__head {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  font-size: 0.92rem;
}

.dsc-co__head svg {
  width: 1rem;
  height: 1rem;
  color: var(--brand-ink);
  flex: none;
}

.dsc-co__badge {
  font-size: 0.64rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--brand-ink);
  background: var(--brand-50);
  border-radius: var(--r-pill);
  padding: 0.16rem 0.5rem;
  margin-left: auto;
}

.dsc-co p {
  font-size: 0.8rem;
  color: var(--ink-muted);
  line-height: 1.45;
  margin: 0;
}

.dsc-co .btn {
  padding-block: 0.55rem;
  font-size: 0.86rem;
}

.dsc-co__input {
  display: flex;
  align-items: center;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--surface);
  padding: 0.5rem 0.7rem;
  font-size: 0.86rem;
  color: var(--ink);
  min-height: 2.35rem;
}

/* El correo del invitado se escribe solo, con cursor (como la tarjeta) */
.co-type {
  display: inline-block;
  overflow: hidden;
  white-space: nowrap;
  max-width: 16ch;
  border-right: 2px solid var(--brand);
  padding-right: 2px;
  animation: coType 1.2s steps(16) 0.6s both, iziCaret 0.8s step-end infinite;
}

@keyframes coType {
  from {
    max-width: 0;
  }

  to {
    max-width: 16ch;
  }
}

/* Réplica del modal "Completa tu pago" (resumen + total + botón Pagar) */
.dsc-paysum {
  border: 1px solid var(--border);
  border-radius: var(--r);
  background: var(--surface-2);
  padding: 0.75rem 0.9rem;
  display: grid;
  gap: 0.55rem;
}

.dsc-paysum__line {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-size: 0.9rem;
}

.dsc-paysum__line>span:not(.dsc-paysum__thumb) {
  flex: 1;
  min-width: 0;
  overflow-wrap: anywhere;
}

.dsc-paysum__thumb {
  width: 38px;
  height: 38px;
  border-radius: 8px;
  object-fit: cover;
  flex: none;
}

.dsc-paysum__thumb--glyph {
  display: grid;
  place-items: center;
  background: var(--surface);
  border: 1px solid var(--border);
}

.dsc-paysum__total {
  display: flex;
  justify-content: space-between;
  border-top: 1px dashed var(--border);
  padding-top: 0.55rem;
  font-weight: 700;
}

.dsc-gwmeta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  font-size: 0.78rem;
  color: var(--ink-faint);
  text-align: center;
}

.dsc-gwmeta svg {
  width: 0.95rem;
  height: 0.95rem;
  color: var(--brand);
  flex: none;
}

/* Réplica de la pantalla real de éxito (comprobante + qué sigue) */
.dsc--ok .dsc-check {
  align-self: center;
  width: 3.2rem;
  height: 3.2rem;
}

.dsc--ok .dsc-check svg {
  width: 1.9rem;
  height: 1.9rem;
}

.dsc-paysum__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem 1.2rem;
  border-top: 1px dashed var(--border);
  padding-top: 0.55rem;
}

.dsc-paysum__meta>div {
  display: grid;
  gap: 0.06rem;
}

.dsc-paysum__meta i {
  font-style: normal;
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.dsc-paysum__meta b {
  font-size: 0.82rem;
  color: var(--ink);
}

.dsc-next {
  display: grid;
  gap: 0.42rem;
  padding-inline: 0.15rem;
}

.dsc-next>span {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.85rem;
  color: var(--ink-muted);
}

.dsc-next svg {
  width: 0.95rem;
  height: 0.95rem;
  flex: none;
}

.dsc-next .is-done {
  color: var(--ink-body);
}

.dsc-next .is-done svg {
  color: var(--brand);
}

.dsc-next .is-now {
  color: var(--ink);
  font-weight: 600;
}

.dsc-next u {
  width: 0.55rem;
  height: 0.55rem;
  flex: none;
  border-radius: 50%;
  background: var(--brand);
  margin-inline: 0.2rem;
  animation: payDotDemo 1.4s var(--ease-out) infinite;
}

@keyframes payDotDemo {

  0%,
  100% {
    transform: scale(0.8);
    opacity: 0.55;
  }

  50% {
    transform: scale(1.2);
    opacity: 1;
  }
}

/* Réplica visual del formulario de pago de Izipay (paso "Pagas") */
.dsc--izi {
  gap: 0.55rem;
}

.izi-brands {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.5rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  font-size: 0.78rem;
  color: var(--ink-muted);
}

.izi-brands>span {
  margin-right: 0.2rem;
}

.izb {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 1.4rem;
  padding: 0 0.4rem;
  border-radius: 4px;
  /* Visa, Mastercard y Diners están dibujados para fondo claro: el azul marino
     de Visa sobre el carbón no se ve. La chapita se queda en marfil aunque la
     web sea oscura, porque son marcas ajenas y no se repintan. */
  border: 1px solid rgb(0 0 0 / 0.14);
  background: #faf7f2;
  font-size: 0.58rem;
  font-weight: 800;
  font-style: normal;
}

.izb--visa {
  color: #1a1f71;
  font-style: italic;
}

.izb--mc u {
  display: inline-block;
  width: 0.72rem;
  height: 0.72rem;
  border-radius: 50%;
  background: #eb001b;
}

.izb--mc u+u {
  background: #f79e1b;
  margin-left: -0.32rem;
  opacity: 0.9;
}

.izb--amex {
  background: #1f72cd;
  border-color: #1f72cd;
  color: #fff;
}

.izb--dc {
  color: #0079be;
}

.izi-field {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  padding: 0.62rem 0.75rem;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--surface);
  font-size: 0.88rem;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.izi-field .ph {
  color: var(--ink-faint);
}

.izi-field svg {
  width: 1.05rem;
  height: 1.05rem;
  color: var(--ink-faint);
  flex: none;
}

/* El número de tarjeta se "escribe" solo, con cursor parpadeando */
.izi-type {
  display: inline-block;
  overflow: hidden;
  white-space: nowrap;
  max-width: 19ch;
  font-family: var(--font-mono);
  font-size: 0.92em;
  border-right: 2px solid var(--brand);
  padding-right: 2px;
  animation: iziType 1.15s steps(19) 0.45s both, iziCaret 0.8s step-end infinite;
}

@keyframes iziType {
  from {
    max-width: 0;
  }

  to {
    max-width: 19ch;
  }
}

@keyframes iziCaret {
  50% {
    border-right-color: transparent;
  }
}

.izi-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.55rem;
}

.izi-pay {
  margin-top: 0.2rem;
  padding: 0.78rem 1rem;
  border: 0;
  border-radius: 8px;
  background: #2bd3c6;
  color: #fff;
  font-weight: 700;
  font-size: 0.92rem;
  letter-spacing: 0.04em;
  cursor: pointer;
  transition: filter var(--t);
}

.izi-pay:hover {
  filter: brightness(0.96);
}

.demo__controls {
  display: flex;
  gap: 0.7rem;
}

.demo__controls button[hidden] {
  display: none;
}

@media (max-width: 760px) {
  .demo {
    grid-template-columns: 1fr;
  }

  .demo__steps {
    flex-direction: row;
    flex-wrap: wrap;
    gap: 0.4rem 1rem;
    position: static;
  }

  .demo-step {
    padding: 0.25rem 0;
  }

  .demo-step:not(:last-child)::after {
    display: none;
  }

  .demo__screen {
    min-height: 340px;
  }
}

@media (prefers-reduced-motion: reduce) {

  .dsc,
  .dsc>*,
  .dsc-check.ok,
  .dsc-press,
  .dsc .dsc-press.is-tapped,
  .dsc-ell i,
  .demo-step.is-active .demo-step__n,
  .demo-step.is-done .demo-step__n {
    animation: none;
  }

  .dsc-prog i {
    width: 100%;
    animation: none;
  }

  .izi-type {
    animation: none;
    border-right: 0;
  }

  .co-type {
    animation: none;
    border-right: 0;
  }

  .dsc-next u {
    animation: none;
  }

  .demo__timer {
    display: none;
  }

  .demo-step:not(:last-child)::after,
  .demo-step__n {
    transition: none;
  }
}

/* ==================================== FAQ home (centrada, 1 columna) === */
/* Centrada al medio (pedido del dueño), en móvil y web, como el apartado de
   Proceso: encabezado + tarjeta de ayuda arriba, y las preguntas debajo. */
.faq-layout {
  display: grid;
  /* minmax(0,1fr) y no 1fr: con `1fr` la columna se estira hasta el elemento
     más ancho que haya dentro (el botón "Hablar con una persona" no parte
     línea) y con la letra del sistema en grande el bloque de preguntas se
     salía de la pantalla por la derecha. */
  grid-template-columns: minmax(0, 1fr);
  justify-items: center;
  gap: clamp(1.75rem, 3vw, 2.5rem);
  max-width: 52rem;
  margin-inline: auto;
}

.faq-layout > *,
.faq-aside h2,
.faq-aside p {
  min-width: 0;
  max-width: 100%;
  overflow-wrap: break-word;
}

.faq-aside {
  position: static;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
}

/* La ceja "DUDAS" en verde de marca: la regla genérica .faq-aside>p (más
   específica que .sec-eyebrow) la teñía de gris. */
.faq-aside .sec-eyebrow { color: oklch(0.55 0.16 47); justify-content: center; }

.faq-aside h2 {
  text-wrap: balance;
  margin-bottom: 0.65rem;
}

.faq-aside>p {
  color: var(--ink-muted);
  line-height: 1.6;
  max-width: 46ch;
  margin: 0 auto 1.6rem;
}

/* La tarjeta "¿Te queda otra duda?" mantiene su interior alineado a la izq. */
.faq-help { text-align: center; width: 100%; max-width: 32rem; }
.faq { width: 100%; }

.faq-help {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: 1.4rem;
  box-shadow: var(--shadow-sm);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.95rem;
}

.faq-help__av {
  flex: none;
  width: 2.7rem;
  height: 2.7rem;
  border-radius: 50%;
  background: var(--brand-50);
  color: var(--brand-ink);
  display: grid;
  place-items: center;
}

.faq-help__av svg {
  width: 1.35rem;
  height: 1.35rem;
}

.faq-help__body {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.55rem;
  min-width: 0;
}

.faq-help__body b {
  color: var(--ink);
  font-size: 1.02rem;
}

.faq-help__body>span {
  color: var(--ink-muted);
  font-size: 0.9rem;
  line-height: 1.5;
  text-wrap: pretty;
}

.faq-help .btn {
  margin-top: 0.45rem;
}

.faq-help__note {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-size: 0.82rem;
  font-weight: 500;
  color: var(--brand-ink);
}

.faq-help__note svg {
  width: 0.95rem;
  height: 0.95rem;
  color: var(--brand);
  flex: none;
}

.faq-layout .faq {
  max-width: none;
  gap: 0.65rem;
}

.faq-layout .faq summary {
  transition: color var(--t);
}

.faq-layout .faq summary:hover {
  color: var(--brand-ink);
}

.faq-layout .faq summary:hover .chev {
  background: var(--brand-50);
  color: var(--brand-ink);
}

.faq-layout .faq details[open] {
  background: var(--surface-2);
}

@media (max-width: 860px) {
  .faq-layout {
    grid-template-columns: 1fr;
    gap: 1.75rem;
  }

  .faq-aside {
    position: static;
  }

  .faq-aside>p {
    max-width: none;
  }
}

/* ========================================================== CTA ============== */
.cta-band {
  position: relative;
  overflow: hidden;
  background: var(--brand-strong);
  border-radius: var(--r-xl);
  padding: clamp(2.5rem, 1.5rem + 4vw, 4rem);
  color: #fff;
  display: grid;
  grid-template-columns: 1.3fr 1fr;
  gap: 2rem;
  align-items: center;
}

.cta-band::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: radial-gradient(rgba(255, 255, 255, 0.14) 1px, transparent 1.4px);
  background-size: 22px 22px;
  -webkit-mask-image: radial-gradient(80% 100% at 100% 50%, #000, transparent 70%);
  mask-image: radial-gradient(80% 100% at 100% 50%, #000, transparent 70%);
}

.cta-band>* {
  position: relative;
}

.cta-band h2 {
  color: #fff;
  font-size: clamp(1.8rem, 1.2rem + 2.4vw, 2.6rem);
  letter-spacing: -0.025em;
}

.cta-band p {
  color: rgba(255, 255, 255, 0.9);
  margin-top: 0.9rem;
  max-width: 44ch;
}

.cta-band__actions {
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  align-items: stretch;
}

.cta-band .btn--secondary {
  --btn-bg: #fff;
  --btn-bd: #fff;
  --btn-fg: var(--brand-strong);
}

.cta-band .btn--ghost {
  --btn-fg: #fff;
  border-color: rgba(255, 255, 255, 0.45);
}

.cta-band .btn--ghost:hover {
  background: rgba(255, 255, 255, 0.12);
}

@media (max-width: 760px) {
  .cta-band {
    grid-template-columns: 1fr;
  }
}

/* ============================================ entrada del hero (apertura) ===
   El hero no pasa por el observador (se ve desde el primer instante), así que
   entra con animación pura de CSS. Mismos tiempos, curva y distancia que el
   resto de la página — ver el bloque APERTURA de cinematic.css. */
.reveal {
  opacity: 0;
  animation: reveal-up var(--in-move) var(--in-ease) forwards;
}

.reveal.d1 {
  animation-delay: calc(var(--in-step) * 1);
}

.reveal.d2 {
  animation-delay: calc(var(--in-step) * 2);
}

.reveal.d3 {
  animation-delay: calc(var(--in-step) * 3);
}

.reveal.d4 {
  animation-delay: calc(var(--in-step) * 4);
}

/* Las cifras del hero son lo primero que se ve al abrir: en vez de entrar el
   bloque entero de una, cada fila entra un paso después de la anterior. */
.hero__stats>.reveal:nth-child(1) {
  animation-delay: calc(var(--in-step) * 2);
}

.hero__stats>.reveal:nth-child(2) {
  animation-delay: calc(var(--in-step) * 3);
}

.hero__stats>.reveal:nth-child(3) {
  animation-delay: calc(var(--in-step) * 4);
}

.hero__stats>.reveal:nth-child(4) {
  animation-delay: calc(var(--in-step) * 5);
}

.hero__stats>.reveal:nth-child(5) {
  animation-delay: calc(var(--in-step) * 6);
}

@keyframes reveal-up {
  from {
    opacity: 0;
    transform: translateY(var(--in-shift));
  }

  to {
    opacity: 1;
    transform: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .reveal {
    opacity: 1;
    animation: none;
  }

  .hero h1 .mark .underline path {
    stroke-dashoffset: 0;
    animation: none;
  }

  .actpanel__status .bar>span {
    width: 100%;
    animation: none;
  }

  .actpanel__status .st {
    opacity: 1;
    animation: none;
  }

  .bt-mini .row .d {
    animation: none;
  }
}

/* ============================================ PREMIUM: refinamiento + scroll === */

/* La aparición del contenido (.r-up / .is-in) vive ahora solo en cinematic.css
   — bloque APERTURA. Aquí había una copia con otros tiempos que, al cargarse
   antes, solo servía para confundir. Retirada el 27-jul-2026. */

/* Cifra grande con conteo ascendente (comparte la tipografía display) */
.bt-proof__big {
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-size: 1.55rem;
  font-weight: 800;
  color: var(--ink);
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}

/* Tile destacado (oferta): tinte de marca plano y sutil, sin resplandores */
.bento__tile--feature {
  background: color-mix(in oklch, var(--brand) 4%, var(--surface));
}

.bt-offer__top .badge {
  box-shadow: var(--shadow-xs);
}

/* El icono de categoría reacciona al hover de su tarjeta */
.cat-tile:hover .icon-tile {
  transform: translateY(-2px) scale(1.04);
  box-shadow: inset 0 1px 0 oklch(1 0 0 / 0.25), var(--shadow-sm);
}

/* CTA final con un poco más de profundidad */
.cta-band {
  box-shadow: var(--shadow-lg), inset 0 1px 0 oklch(1 0 0 / 0.14);
}

@media (prefers-reduced-motion: reduce) {

  /* Sin movimiento: el hero se ve puesto, sin recorrido ni espera. */
  .reveal {
    opacity: 1;
    animation: none;
  }

  .hero__bg {
    animation: none;
    transform: scale(1.04);
  }

  .hero h1 em::after {
    animation: none;
    transform: scaleX(1);
  }

  .brandstrip__track {
    animation: none;
    flex-wrap: wrap;
  }

  .has-reveal .r-up {
    transform: none;
  }
}
/* ============================================ VITRINA PROTAGONISTA ========== */
/* La sección "Nuestros productos" a lo grande (pedido del dueño, 20-jul-2026):
   título centrado, estuches más grandes tipo hero, aire generoso y el enlace
   al catálogo centrado al final, debajo del "Comprar ahora" de la vitrina. */
.deck-hero {
  /* Padding superior CORTO: esta sección llega solapándose sobre el hero en
     relevo (hero3d.css) y un padding alto dejaba un tramo blanco feo entre
     ambos, en escritorio y en celular (20-jul-2026). El de abajo sigue amplio. */
  padding-block: clamp(1.75rem, 3.5vw, 2.75rem) clamp(3.5rem, 8vw, 6.5rem);
}

.deck-hero__head {
  justify-content: center;
  text-align: center;
  margin-bottom: clamp(2rem, 5vw, 3.5rem);
}

.deck-hero__head .sec-head__t {
  display: grid;
  justify-items: center;
}

/* La ceja "— Catálogo" centra su rayita junto al texto */
.deck-hero__head .sec-eyebrow {
  justify-content: center;
}

.deck-hero__head .sec-head__t p:not(.sec-eyebrow) {
  margin-inline: auto;
  max-width: 52ch;
}

/* Estuches a escala protagonista (el carrusel general vive en commerce.css) */
.deck-hero .deck__stage {
  --deck-box: clamp(150px, 21vw, 250px);
  height: calc(var(--deck-box) + 4rem);
}

.deck-hero .deck__info {
  gap: 0.75rem;
  margin-top: 1.1rem;
}

/* En el celular los dos accesos van UNO DEBAJO DEL OTRO (como siempre): en
   fila quedarían dos botones estrechos y apretados. Al lado solo en escritorio,
   donde sí hay ancho de sobra. */
.deck-hero__more {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.75rem;
  margin-top: clamp(1.5rem, 3.5vw, 2.5rem);
}

@media (min-width: 700px) {
  /* Hueco generoso entre los dos: son botones sólidos del MISMO verde y del
     mismo tamaño, así que con 1rem se leían como una sola barra verde partida
     por la mitad (aviso del dueño, 28-jul-2026). Crece con la pantalla. */
  .deck-hero__more {
    flex-direction: row;
    justify-content: center;
    gap: clamp(1.75rem, 4vw, 3rem);
  }
}

/* =============================================================================
   RESEÑAS / TESTIMONIOS (portada) — reseñas REALES editables desde el panel.
   La sección nace con [hidden]; home.js la muestra solo si hay reseñas.
   ============================================================================= */
/* Seguro anti-sección-vacía: mientras no haya reseñas, la sección no se pinta. */
#sec-testimonials[hidden] {
  display: none;
}
/* Las estrellas (.rstars) y la insignia (.trustbadge) viven en chrome.css:
   la insignia va en el pie, que es compartido por todas las páginas. */

/* ---- Resumen: nota media calculada de las reseñas publicadas ------------- */
.revsum {
  display: grid;
  justify-items: center;
  gap: 0.5rem;
  text-align: center;
  margin-top: clamp(1.2rem, 3vw, 1.9rem);
}
.revsum__word {
  margin: 0;
  font-size: clamp(1.45rem, 1.15rem + 1.4vw, 2rem);
  font-weight: 800;
  letter-spacing: -0.01em;
  color: var(--ink-strong);
}
.revsum__base {
  margin: 0;
  font-size: 0.95rem;
  color: var(--ink-muted);
}
.revsum__base b {
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.revsum__by {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0.1rem 0 0;
  font-size: 0.9rem;
  color: var(--ink-muted);
}
.revsum__seal {
  display: inline-flex;
  color: var(--brand);
}
.revsum__seal svg {
  width: 1.1rem;
  height: 1.1rem;
}

/* ---- Carrusel de reseñas (se arrastra con el dedo y con las flechas) ----- */
.revcar {
  position: relative;
  margin-top: clamp(1.4rem, 3vw, 2.2rem);
}
.revcar__track {
  display: flex;
  gap: clamp(0.8rem, 1.6vw, 1.1rem);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  padding: 0.35rem 0.25rem 0.9rem;
  scrollbar-width: none;
}
.revcar__track::-webkit-scrollbar {
  display: none;
}
.revcar__nav {
  position: absolute;
  top: 50%;
  translate: 0 -50%;
  z-index: 2;
  display: grid;
  place-items: center;
  width: 2.4rem;
  height: 2.4rem;
  border-radius: 50%;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-md);
  transition: background-color var(--t), color var(--t), border-color var(--t), opacity var(--t);
}
.revcar__nav:hover {
  color: #fff;
  background: var(--brand);
  border-color: var(--brand);
}
.revcar__nav[disabled] {
  opacity: 0.3;
  pointer-events: none;
}
.revcar__nav svg {
  width: 1.25rem;
  height: 1.25rem;
}
/* Escritorio: las flechas tienen carril propio a los lados, así nunca tapan el
   texto de la primera ni de la última tarjeta. */
.revcar__nav--prev { left: 0; }
.revcar__nav--next { right: 0; }
@media (min-width: 641px) {
  .revcar { padding-inline: 3rem; }
}
/* Móvil: manda el dedo (las tarjetas cortadas ya avisan que hay más). */
@media (max-width: 640px) {
  .revcar__nav { display: none; }
}

/* ---- Tarjeta de reseña --------------------------------------------------- */
.rcard {
  flex: 0 0 min(82vw, 17.5rem);
  scroll-snap-align: start;
  display: flex;
  flex-direction: column;
  gap: 0.65rem;
  margin: 0;
  padding: clamp(1.05rem, 2vw, 1.35rem);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 16px;
  box-shadow: 0 1px 2px color-mix(in oklch, var(--ink) 6%, transparent);
  transition: transform 0.25s ease, box-shadow 0.25s ease, border-color 0.25s ease;
}
.rcard:hover {
  transform: translateY(-3px);
  border-color: color-mix(in oklch, var(--brand) 35%, var(--border));
  box-shadow: 0 14px 34px -18px color-mix(in oklch, var(--brand) 45%, transparent);
}
.rcard__head {
  display: flex;
  align-items: center;
  gap: 0.7rem;
}
.rcard__avatar {
  display: grid;
  place-items: center;
  width: 2.6rem;
  height: 2.6rem;
  flex: 0 0 auto;
  border-radius: 50%;
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: #fff;
  background: linear-gradient(140deg, var(--brand), color-mix(in oklch, var(--brand) 55%, #965525));
}
.rcard__id {
  display: flex;
  flex-direction: column;
  min-width: 0;
  line-height: 1.3;
}
.rcard__id b {
  font-weight: 700;
  font-size: 0.98rem;
  color: var(--ink-strong);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.rcard__date {
  font-size: 0.8rem;
  color: color-mix(in oklch, var(--ink) 55%, transparent);
}
.rcard__check {
  margin-left: auto;
  display: inline-flex;
  color: var(--brand);
}
.rcard__check svg {
  width: 1.2rem;
  height: 1.2rem;
}
.rcard__body {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  margin: 0;
  font-size: 0.98rem;
  line-height: 1.55;
  color: var(--ink);
}
.rcard__title {
  font-weight: 700;
  color: var(--ink-strong);
}
/* Recorte a 2 líneas hasta que el visitante pulse "Leer más" */
.rcard__body.is-clamped .rcard__text {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.rcard__more {
  align-self: flex-start;
  font-size: 0.86rem;
  font-weight: 600;
  color: var(--brand-ink);
}
.rcard__more:hover {
  text-decoration: underline;
}
.rcard__sub {
  margin-top: auto;
  padding-top: 0.5rem;
  border-top: 1px solid var(--border);
  font-size: 0.8rem;
  color: color-mix(in oklch, var(--ink) 55%, transparent);
}


/* ---- Fondo de imagen por apartado (18-ago-2026) --------------------------
   Cada sección de la portada lleva su propia foto detrás, atenuada y con un
   velo encima para que el texto siga leyéndose. Al bajar, la foto se desplaza
   más despacio que el contenido (parallax): es lo que hace que la página se
   sienta viva de arriba abajo.
   El movimiento es CSS puro (animación atada al scroll, sin JavaScript). Donde
   el navegador no la soporte —Firefox hoy— la foto se queda quieta: el efecto
   es adorno, no contenido, así que no se le pone muleta. */
.section--pic {
  position: relative;
  isolation: isolate;
  overflow: clip;                      /* la foto ampliada no se sale */
  view-timeline: --secpic;
}
.secpic {
  position: absolute;
  inset: 0;
  z-index: -1;
  overflow: clip;
  pointer-events: none;
}
.secpic img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0.3;
  /* Ampliada de fábrica: el desplazamiento del parallax necesita margen por
     arriba y por abajo, si no se vería el borde de la foto. */
  transform: scale(1.14);
}
/* Velo: oscurece por arriba y por abajo, donde se apoyan los títulos, y deja
   respirar el centro. Sin él, el texto blanco se pierde en las zonas claras. */
.secpic::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg, var(--bg) 0%, color-mix(in oklch, var(--bg) 55%, transparent) 28%,
      color-mix(in oklch, var(--bg) 45%, transparent) 72%, var(--bg) 100%);
}
/* En claro la foto pesa más sobre el texto: se atenúa un poco más. */
:root:not([data-theme="dark"]) .secpic img {
  opacity: 0.16;
}

/* El parallax solo en pantallas grandes: en el celular, animar seis fotos a
   pantalla completa mientras se hace scroll es justo lo que lo pone a tirones,
   y el efecto casi no se aprecia en 6 pulgadas. */
@supports ((animation-timeline: view()) and (animation-range: entry)) {
  @media (prefers-reduced-motion: no-preference) and (min-width: 861px) {
    .secpic img {
      animation: secpic-parallax linear both;
      animation-timeline: --secpic;
      animation-range: entry 0% exit 100%;
      /* SIN will-change (19-ago-2026). Eran seis fotos a pantalla completa, y
         cada una con will-change se lleva su propia capa en la tarjeta gráfica
         (unos 8 MB por foto en Full HD) durante TODA la visita, se estén viendo
         o no. En un portátil con gráfica integrada eso era buena parte del
         tirón al desplazar. Las animaciones atadas al scroll ya corren fuera
         del hilo principal: no necesitan el aviso. */
    }
  }
}
@keyframes secpic-parallax {
  from { transform: scale(1.14) translateY(-4%); }
  to   { transform: scale(1.14) translateY(4%); }
}

/* Una sección con foto no debe quedar más baja que la foto: en escritorio se
   le pide casi una pantalla, que es lo que da la sensación de "un apartado,
   una vista". En móvil manda el contenido: forzar alto ahí deja huecos. */
@media (min-width: 861px) {
  .section--pic {
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-height: min(88svh, 60rem);
  }
}

/* El hero tiene su propia capa: sin parallax (es pegajoso: mover el fondo
   mientras el contenido se queda quieto marea) y algo más tenue, porque encima
   van el título de la marca y las cifras. */
.hero--3d .hero__sticky {
  isolation: isolate;
}

/* SIN z-index NEGATIVO en el hero (19-ago-2026). La capa de la foto/vídeo nace
   en -1, que es lo correcto para las fotos de fondo del resto de apartados. Pero
   el hero está dentro de un grupo aislado (isolation: isolate, aquí arriba) y
   con fondo negro OPACO, y varias versiones de WebKit pintan un hijo en z
   negativo POR DETRÁS del fondo de su propio grupo: el vídeo desaparece entero
   —con su cartel y todo— en el iPhone, mientras en Chrome se ve perfecto.
   Con 0 se pinta igual de atrás que antes (todo lo que va encima ya lleva su
   z-index: el velo va en 2 y el contenido en 3) pero sin depender de ese caso
   límite. */
.secpic--hero {
  z-index: 0;
}
.secpic--hero img {
  opacity: 0.78;
  transform: scale(1.06);
  animation: none;
}
/* El velo del hero es PAREJO (18-ago-2026, pedido del dueño): antes tapaba los
   costados para proteger el texto y el vídeo solo asomaba por el centro, que se
   veía mal. Ahora se ve entero, con un oscurecido suave y uniforme; la
   legibilidad del texto la sostiene la sombra de .hero__content / .hero__stats,
   más abajo. Solo se cierra en el borde inferior, para empalmar con la sección
   siguiente sin un corte seco. */
.secpic--hero::after {
  /* Bajado de 52/48 a 34/26 (19-ago-2026): el texto ya no vive encima del
     dibujo —se fue a los dos costados— así que aquí queda poco que proteger, y
     lo que quedaba solo servía para apagar el vídeo. La legibilidad la
     sostienen las sombras radiales de .hero__content / .hero__stats. */
  background:
    linear-gradient(180deg,
      color-mix(in oklch, var(--bg) 34%, transparent) 0%,
      color-mix(in oklch, var(--bg) 26%, transparent) 45%,
      color-mix(in oklch, var(--bg) 58%, transparent) 84%,
      var(--bg) 100%);
  transition: opacity 900ms ease;
}

/* Durante la obertura no hay NADA que proteger: el velo se apaga entero y el
   vídeo se ve tal cual, que es lo que se pidió. */
html.hero-cine .secpic--hero::after {
  opacity: 0;
}

/* Y la foto de respaldo se apaga casi entera mientras el vídeo llega: se pidió
   ver el vídeo, no un banner de espera. No se apaga del TODO a propósito —una
   pantalla completamente negra parece una página rota— y si el vídeo no llegara
   a arrancar, home.js quita hero-cine a los 3 s y la foto vuelve sola. */
html.hero-cine .secpic--hero:not(.has-vid) img {
  opacity: 0.1;
}

/* En el celular la sección mide dos o tres pantallas: estirar la foto a todo
   ese alto la recortaba hasta dejarla irreconocible. Se queda arriba, del alto
   de una portada, y se funde con el fondo; el texto va debajo, limpio. */
@media (max-width: 860px) {
  .secpic {
    bottom: auto;
    height: min(64svh, 30rem);
  }
  /* El hero es una sola pantalla: ahí la foto sí cubre de arriba abajo. */
  .secpic--hero {
    bottom: 0;
    height: auto;
  }
  .secpic::after {
    background: linear-gradient(180deg,
      color-mix(in oklch, var(--bg) 42%, transparent) 0%,
      color-mix(in oklch, var(--bg) 62%, transparent) 55%,
      var(--bg) 96%);
  }
}

/* ---- Foto en el pie (solo la portada) -----------------------------------
   El pie lo pinta components.js y es el mismo en todas las páginas, así que
   la foto se pone desde aquí (home.css solo lo carga la portada) y con un
   pseudo-elemento, sin tocar el guion compartido.
   Es la foto de la entrega, la misma de "Cómo funciona": están a cuatro
   secciones de distancia y nunca se ven juntas. Va muy tenue porque encima
   hay texto pequeño (enlaces del menú y el aviso legal). */
body[data-page="inicio"] .site-footer {
  position: relative;
  isolation: isolate;
  background: var(--bg);
  border-top-color: color-mix(in oklch, var(--brand) 22%, var(--border));
}
body[data-page="inicio"] .site-footer::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: url("../img/banners/banner-2.jpg") center / cover no-repeat;
  opacity: 0.38;
}
/* En el celular, la de 800 px (19-ago-2026). Esta foto va al 38 % de opacidad
   y con un velo encima, detrás de la letra pequeña del pie: nadie la mira. La
   grande son 152 KB —el archivo más pesado de la portada después del vídeo— y
   se bajaban enteros para una franja de tres dedos de alto. Las <img> de
   sección ya eligen la chica por srcset; un fondo de CSS no tiene srcset, así
   que aquí se dice a mano. */
@media (max-width: 860px) {
  body[data-page="inicio"] .site-footer::before {
    background-image: url("../img/banners/banner-2-800.jpg");
  }
}
/* Velo: el pie es lo último que se lee (garantías, legal, medios de pago) y
   no puede pelearse con la foto. */
body[data-page="inicio"] .site-footer::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(180deg,
    var(--bg) 0%,
    color-mix(in oklch, var(--bg) 45%, transparent) 40%,
    color-mix(in oklch, var(--bg) 60%, transparent) 75%,
    var(--bg) 100%);
}
:root:not([data-theme="dark"]) body[data-page="inicio"] .site-footer::before {
  opacity: 0.12;
}

/* ---- Vídeo de fondo de la portada ---------------------------------------
   Lo cuelga home.js dentro de la capa de la foto. La foto sigue debajo y hace
   de cartel: se ve al instante y se retira con un fundido cuando el vídeo ya
   tiene imagen, así no hay parpadeo negro ni salto. */
.secpic__vid {
  position: absolute;
  /* Centrado con inset:0 + margin:auto. Hace falta esa pareja (y no un
     translate) porque abajo se le pone un tamaño TOPE y el translate se pelea
     con la animación de reposo. */
  inset: 0;
  margin: auto;
  z-index: 0;
  /* NITIDEZ (19-ago-2026). El archivo es de 1280x720. Estirado a un monitor de
     1920 se agrandaba un 50 % y todo salía blando: eso era lo que se veía como
     "poca calidad", no el color. Aquí la caja NUNCA pasa de 78rem (1248 px), o
     sea que el vídeo se pinta a su tamaño real o algo por debajo — que es donde
     se ve limpio. En pantallas más chicas manda el 100 % y encoge, que también
     afina. Si algún día se sube un archivo en 1080p o 4K, sube este tope a la
     par (por ejemplo 100rem) y volverá a llenar más pantalla sin emborronarse. */
  width: min(100%, 78rem);
  height: min(100%, 44rem);
  /* ENTERO, sin recortar (pedido del dueño, 19-ago-2026). */
  object-fit: contain;
  /* SIN máscara (19-ago-2026). La máscara se puso para disimular el filo del
     rectángulo, pero hacía lo contrario: dibujaba un halo ovalado que, sobre un
     fondo negro puro, se veía como una mancha. El filo se quita de raíz abajo,
     en el filtro, dejando el negro del vídeo en negro DE VERDAD. */
  -webkit-mask-image: none;
  mask-image: none;
  opacity: 0;
  transition: opacity 900ms ease;
}

/* Halo detrás del vídeo: es lo que le da cuerpo de objeto en un escenario en
   vez de "un vídeo puesto de fondo". Va en una capa aparte y no en un
   drop-shadow del propio vídeo, que se recalcularía en CADA fotograma. */
.secpic--hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0;
  transition: opacity 1.2s ease;
  /* Muy abierto y muy flojo a propósito: cerrado y fuerte se le veía el canto
     y quedaba una nube naranja pegada detrás del vídeo, que era parte de lo
     que se notaba feo. Así solo se intuye que el aire de alrededor está tibio. */
  background:
    radial-gradient(62% 58% at 50% 50%, color-mix(in oklch, var(--brand) 6%, transparent), transparent 78%),
    radial-gradient(90% 80% at 50% 52%, oklch(0.2 0.04 51 / 0.07), transparent 85%);
}

.secpic--hero.has-vid::before {
  opacity: 1;
}
/* ---- El cartel: un fotograma del vídeo, como imagen normal --------------
   (19-ago-2026.) Ocupa EXACTAMENTE el mismo sitio que el vídeo y lleva su
   mismo realce, para que el relevo no se note: cuando el vídeo arranca, este
   se apaga y aquel se enciende sobre el mismo dibujo.
   Todo lo que sea "dónde va y cómo se pinta" tiene que estar duplicado aquí y
   en .secpic__vid, o el cambio dará un salto. Si tocas uno, toca el otro. */
.secpic__cartel {
  position: absolute;
  inset: 0;
  margin: auto;
  width: min(100%, 78rem);
  height: min(100%, 44rem);
  background: url("../img/hero-poster.webp") center / contain no-repeat;
  /* POR ENCIMA del vídeo, no por debajo (19-ago-2026). Aquí está la salida al
     callejón del botón de play del iPhone:

       · el vídeo tiene que estar VISIBLE o WebKit no le deja autoarrancar
         (una opacidad de cero cuenta como invisible);
       · pero si está visible y el teléfono no lo deja arrancar, Safari le
         dibuja su botón de reproducción encima.

     Las dos cosas a la vez se consiguen tapándolo: para el navegador el vídeo
     sigue visible —lo que mira es la opacidad y si está en pantalla, no si
     algo se le pone delante—, así que le deja arrancar; y el botón, si llega a
     salir, queda debajo de esta capa y no lo ve nadie.

     Cuando el vídeo confirma que está reproduciendo, esta capa se funde y deja
     ver la animación. Como la imagen ES un fotograma del vídeo, el relevo no
     se nota. */
  z-index: 1;
  pointer-events: none;
  /* VISIBLE de entrada. Solo se retira cuando el vídeo confirma que está
     reproduciendo. Así el orden de aparición nunca puede dejar la portada en
     negro: primero el cartel, y el vídeo encima si llega. */
  opacity: 1;
  filter: brightness(1.84) contrast(1.25) saturate(1.25);
  transition: opacity 600ms ease;
}

.secpic--hero.reproduciendo .secpic__cartel {
  opacity: 0;
}

/* El cartel va SIEMPRE en el mismo encuadre que el vídeo: sin zoom en ningún
   tamaño de pantalla. Si el uno se recorta y el otro no, el relevo pega un
   salto justo cuando el vídeo arranca. */

/* EL VÍDEO ES VISIBLE DESDE QUE SE CUELGA. Y esto no es un detalle de gusto:
   es la causa de que no arrancara solo en el celular (19-ago-2026).

   Durante unas horas estuvo al revés —transparente hasta que el evento
   "playing" confirmara que había imagen— para que, si el teléfono no lo dejaba
   arrancar, no se viera su botón de play. Pero WebKit NO AUTOARRANCA UN VÍDEO
   QUE CONSIDERA INVISIBLE, y una opacidad de cero cuenta como invisible. O sea
   que el vídeo no arrancaba porque estaba invisible, y estaba invisible porque
   no había arrancado. Un pez mordiéndose la cola.

   En Chrome no se notaba: ahí la opacidad no entra en la política de
   autoarranque, y por eso "en la computadora sí y en el celular no".

   Lo que se ve antes de que lleguen los fotogramas es el poster del propio
   elemento, que es un fotograma del vídeo: no hay salto ni imagen ajena. Y el
   botón de play de iOS, si llegara a salir, lo tapan las reglas de más abajo. */
.secpic--hero.has-vid .secpic__vid {
  /* VISIBLE. Sin esta línea el vídeo se queda transparente para siempre y lo
     único que se ve es el cartel: una imagen fija donde tiene que haber una
     animación. Se perdió al mover reglas de sitio y costó dar con ello, así
     que va la primera y con aviso — si esto desaparece, la portada se queda
     quieta. Y además es lo que permite que el celular la autoarranque: WebKit
     no arranca solo un vídeo que considere invisible. */
  opacity: 1;
  /* NIVELES, no "brillo a ojo" (19-ago-2026). Aquí está el arreglo del
     rectángulo que se veía flotando en la portada.
     El fondo de la web en oscuro es NEGRO PURO (--bg: #000). El negro del vídeo
     no lo es: la compresión lo deja en 3–10 sobre 255. Al subirle el brillo,
     ese casi-negro subía con todo lo demás y el recuadro del vídeo quedaba más
     claro que la página — o sea, se veía la caja.
     Encadenando brillo y contraste sale una recta: resultado = 2.2·x − 0.095.
     Lo que está por debajo de 11/255 se va a cero (negro real, la caja
     desaparece) y de ahí para arriba el dibujo sube MÁS que antes: los brillos
     quedan como estaban y lo único que se pierde es el gris de fondo. Es la
     herramienta "niveles" de toda la vida, hecha con dos filtros de CSS.
     Si cambias uno de los dos números, recalcula: pendiente = brillo·contraste,
     corte = 0.5·(1 − contraste); el negro se limpia en corte/pendiente. */
  /* Los dos números salen de la recta de niveles: pendiente = brillo·contraste,
     corte = 0.5·(1 − contraste), y el negro se limpia hasta corte/pendiente.
     Aquí: 1.9·x − 0.283, o sea que todo lo que esté por debajo de 38/255 se va
     a NEGRO REAL. Ese es el número a mover si el fondo del vídeo sigue
     asomando (súbelo) o si el logo se está quedando sin cuerpo (bájalo).
     Para afinarlo sin adivinar: abre la portada con ?video=niveles y mueve las
     dos barras; el panel te da la línea ya escrita para pegar aquí. */
  /* CUIDADO CON EL CORTE. Este vídeo es oscurísimo: su brillo medio va de 13 a
     32 sobre 255. Cortar en 38 (como se probó el 19-ago-2026) no le quitaba el
     fondo: le borraba el DIBUJO, y la portada se quedaba en negro.
     Con estos dos números el corte cae en 14/255 — justo por encima del ruido
     de compresión y muy por debajo de donde vive la imagen. */
  filter: brightness(1.84) contrast(1.25) saturate(1.25);
  /* SIN mix-blend-mode (19-ago-2026). Estaba puesto de red por si el fondo del
     vídeo volvía a asomar, pero SAFARI NO PINTA UN <video> QUE LLEVE MEZCLA:
     lo manda a una capa aparte que la mezcla no alcanza, y el elemento entero
     desaparece — el vídeo y también su cartel. Eso era el "en el iPhone no se
     ve nada" (reportado el 19-ago-2026).
     Y no hacía falta para nada: el fondo de la página es NEGRO PURO, y "screen"
     sobre negro deja la imagen igual. Lo comprobé lado a lado, con y sin
     mezcla: la misma captura, píxel por píxel. Lo que quita el recuadro es la
     curva de niveles de aquí arriba, no esto. */
}

/* Vídeo CON canal alfa (la clase la pone home.js mirando qué archivo eligió el
   navegador): aquí el fondo ya viene recortado de origen, así que no hay nada
   que hundir. Los niveles y el blend se retiran —aplicados a un vídeo limpio le
   comen el dibujo— y solo queda un punto de color. Esto se activa solo el día
   que existan home-loop.webm / home-loop.mov (ver assets/video/LEEME.txt). */
.secpic--hero.con-alfa .secpic__vid {
  filter: saturate(1.12);
}
.secpic--hero img {
  transition: opacity 900ms ease;
}
.secpic--hero.has-vid img {
  opacity: 0;
}

/* ---- El botón de "play" de iOS ------------------------------------------
   (19-ago-2026, reportado desde un iPhone: "aparece un icono para reproducir".)
   Safari dibuja sus propios controles ENCIMA del vídeo cuando no ha conseguido
   arrancarlo solo — lo más común, el ahorro de batería del teléfono, que apaga
   el autoarranque sin avisar. Aparece entonces un botón de play gigante en
   medio de la portada.
   Son pseudo-elementos internos de WebKit: no se quitan con controls=false ni
   con nada del HTML, solo desde aquí. En los demás navegadores estas reglas no
   existen y se ignoran sin más.
   Y si el vídeo no arranca, lo que queda es el cartel: la portada sigue
   enseñando la pieza, que es lo que importa. */
.secpic__vid::-webkit-media-controls,
.secpic__vid::-webkit-media-controls-panel,
.secpic__vid::-webkit-media-controls-play-button,
.secpic__vid::-webkit-media-controls-start-playback-button,
.secpic__vid::-webkit-media-controls-overlay-play-button {
  display: none !important;
  -webkit-appearance: none;
  appearance: none;
  opacity: 0;
  pointer-events: none;
}

/* El vídeo es decorado: no se pulsa, no se selecciona, no abre menús. Así
   tampoco hay forma de que el teléfono lo trate como un reproductor. */
.secpic__vid {
  pointer-events: none;
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}
/* El velo va SIEMPRE por encima del vídeo, no solo de la foto. */
.secpic::after {
  z-index: 1;
}

/* CELULAR: el vídeo manda arriba, de cabecera (19-ago-2026). Puesto a
   pantalla completa quedaba una tira pequeña perdida en el medio, porque el
   vídeo es apaisado y la pantalla es alta. Aquí la caja toma el formato EXACTO
   del vídeo (56.25vw = 16:9 sobre el ancho de la pantalla): así se ve entero y
   además llena de borde a borde, sin franjas. Debajo, el texto. */
@media (max-width: 860px) {
  /* La caja se define por PROPORCIÓN y no por una altura a ojo: así encaja
     igual en un teléfono de 320 px que en uno de 430 o en una tablet, y el
     vídeo llena exactamente, sin descuadres ni franjas. Todo sale de estas
     tres medidas, que también usa el contenido de abajo para saber dónde
     empezar. */
  .hero--3d {
    --vid-lado: 0.9rem;
    --vid-arriba: 4.25rem;
    --vid-alto: calc((100vw - var(--vid-lado) * 2) * 0.5625);
    /* Con vídeo la caja va a sangre (sin marco que la encierre), así que su
       16:9 se calcula sobre el ancho ENTERO de la pantalla. Tener las dos
       medidas aquí es lo que evita que se vuelva a descuadrar: el texto de
       abajo lee la misma variable que usa la caja, no un número a ojo. */
    --vid-alto-lleno: calc(100vw * 0.5625);
    /* Aire entre el vídeo y el título. */
    --vid-aire: 1.25rem;
  }
  .secpic--hero {
    top: var(--vid-arriba);
    left: var(--vid-lado);
    right: var(--vid-lado);
    bottom: auto;
    height: var(--vid-alto);
  }
  /* La pieza va ENTERA (19-ago-2026). Con "cover" se le recortaba un dedo por
     arriba y otro por abajo, y a un objeto que ahora flota sobre el negro eso
     le corta los anillos. Con "contain" cabe completo, y lo que sobra a los
     lados es negro sobre negro: no se ve. */
  .secpic--hero .secpic__vid {
    object-fit: contain;
    -webkit-mask-image: none;
    mask-image: none;
    /* SIN ZOOM (19-ago-2026). Llegó a tener un scale(1.18) para que la pieza
       llenara más la pantalla, calculado sobre el margen muerto que rodea al
       logo. El cálculo se hizo mirando solo los primeros segundos, y falló: al
       final de la animación el vídeo enseña el NOMBRE DE LA MARCA a todo lo
       ancho del fotograma, y el zoom se lo comía por los lados — se leía
       "opDigitals" y "AS ORIGINALES".
       El vídeo va entero. Si alguna vez se quiere más grande, la forma correcta
       es re-encuadrar el archivo, no recortarlo aquí. */
    transform: none;
  }

  .secpic--hero img {
    /* La caja es un pelín más alta que el vídeo, para que tenga más presencia;
       el recorte es de un dedo por arriba y otro por abajo, no se nota. La
       máscara lo funde contra el texto que viene debajo. */
    object-fit: cover;
    /* SIN máscara (19-ago-2026): el degradado de los bordes era justo lo que
       hacía que el vídeo pareciera transparente y se fundiera con el negro.
       Ahora se corta limpio y se lee como un bloque. */
    -webkit-mask-image: none;
    mask-image: none;
  }
  /* Velo flojo: en el celular el texto ya no cae encima del vídeo (va debajo),
     así que aquí no hay nada que proteger y el vídeo puede verse de verdad. */
  /* Ni velo ni nada encima: el texto va DEBAJO del vídeo, no hay nada que
     proteger. */
  .secpic--hero::after {
    background: none;
  }
  /* Aquí el vídeo no tiene texto encima, así que se le puede dar más caña. */
  .secpic--hero.has-vid .secpic__vid {
    /* Mismo criterio de niveles que en escritorio (ver arriba), un punto más
       de brillo porque aquí el vídeo no tiene texto encima. */
    /* EL MISMO que en escritorio, a propósito (19-ago-2026). Aquí llevaba más
       ganancia "porque la pantalla es chica y no hay texto encima", y el
       resultado era el contrario del buscado: con brillo 2,2 el canal rojo se
       satura a tope antes que el verde y el azul, y el naranja de los anillos
       salía gris oliva. En el PC, con esta curva, se ve vivo; no había ninguna
       razón para que el teléfono llevara otra. */
    filter: brightness(1.84) contrast(1.25) saturate(1.25);
  }
  /* El contenido arranca DEBAJO de la cabecera, y el hero deja de forzar una
     pantalla exacta: con el vídeo arriba no cabía todo y las cifras quedaban
     cortadas. */
  /* Selector largo a propósito: hero3d.css se carga DESPUÉS y ahí el sticky
     ya tiene su propio alto; con un selector corto ganaba aquel y el título
     se subía encima del vídeo. */
  .hero--3d .hero__sticky {
    min-height: 0;
  }
  .hero--3d .hero__sticky > .container.hero__ari {
    padding-top: calc(var(--vid-arriba) + var(--vid-alto) + var(--vid-aire));
  }
}

/* Sin paneles ni recuadros (pedido del dueño): el texto va suelto sobre el
   vídeo, como estaba antes. Lo que sostiene la lectura es el velo parejo de
   arriba, calibrado al mínimo que deja pasar el vídeo sin que las letras se
   pierdan en los destellos, más esta sombra: una dura pegada a la letra, que
   le dibuja el contorno, y otra amplia que despega el bloque del fondo. */
.hero--3d .hero__content,
.hero--3d .hero__stats {
  text-shadow:
    0 1px 2px oklch(0.10 0.02 255 / 0.95),
    0 0 10px oklch(0.10 0.02 255 / 0.85),
    0 3px 24px oklch(0.10 0.02 255 / 0.8);
}
/* El menú de la portada ya tiene su propio fondo; se le refuerza un punto para
   que no dependa solo de la sombra. */
.hero--3d .gmenu__i {
  backdrop-filter: blur(6px);
}

/* Sobre el vídeo, el párrafo de bienvenida va en blanco y no en el gris de
   siempre. No es capricho: con el gris (0.8 de claridad) el peor fotograma del
   bucle daba 3,8:1 y hace falta 4,5:1. Aclarar el texto sale más barato que
   apagar el vídeo, que es lo que se quería ver. */
.hero--3d .hero__ari .hero__lede {
  color: var(--ink);
}

/* ---- Que el navegador no trabaje en lo que no se ve ----------------------
   Cada apartado con foto es una pantalla entera de píxeles. Sin esto, el
   navegador los pinta TODOS aunque estén a tres pantallas de distancia, y en
   un celular modesto eso se nota en cada dedazo. Con content-visibility solo
   se pinta lo que está a la vista; `auto` en el tamaño hace que el navegador
   recuerde cuánto medía cada uno, así la barra de scroll no pega saltos. */
/* 19-ago-2026: esto valía solo hasta 1100 px, y el problema es exactamente el
   mismo (o peor) en un monitor grande, donde cada apartado son dos millones de
   píxeles. Ahora va en todas las anchuras. El hero se queda fuera a propósito:
   es lo primero que se ve y no puede saltarse el pintado. */
.section--pic {
  content-visibility: auto;
  contain-intrinsic-size: auto 720px;
}

/* La vitrina de estuches es la excepción por encima de 1100 px, donde nunca lo
   tuvo: ui.js MIDE las tarjetas para colocarlas en abanico, y a un apartado
   cuyo pintado se saltó el navegador le devuelve ceros. Debajo de 1100 px se
   queda como estaba, que ahí ya funcionaba. */
@media (min-width: 1101px) {
  .s-productos {
    content-visibility: visible;
  }
}

/* Sombra de apoyo bajo el texto del hero (19-ago-2026). No es un panel ni una
   tarjeta —eso ya se probó y no gustó—: es un degradado radial SIN bordes ni
   esquinas, que solo oscurece la zona justo detrás de las letras y se disuelve
   antes de llegar a ningún canto. Se percibe como que el fondo está más oscuro
   ahí, no como una caja.
   Hace falta porque el vídeo va realzado y a plena vista: medido fotograma a
   fotograma, sin esto el nombre de la marca caía a 1,8:1. */
@media (min-width: 861px) {
  .hero--3d .hero__content {
    background: radial-gradient(125% 105% at 22% 50%,
      color-mix(in oklch, var(--bg) 84%, transparent) 0%,
      color-mix(in oklch, var(--bg) 55%, transparent) 55%,
      transparent 78%);
  }
  .hero--3d .hero__stats {
    background: radial-gradient(135% 105% at 78% 50%,
      color-mix(in oklch, var(--bg) 84%, transparent) 0%,
      color-mix(in oklch, var(--bg) 55%, transparent) 55%,
      transparent 78%);
  }
}

/* El marco del celular pasa a ser SOLO de la foto de respaldo (19-ago-2026).
   Se puso porque el vídeo suelto "se leía como un reflejo del fondo", pero eso
   era cuando arrastraba su recuadro gris; ahora el fondo está hundido a negro y
   la pieza flota sola, así que encerrarla entre esquinas y un filo de cobre la
   convertía en una tele. La foto sí lo conserva: una foto sin marco sobre negro
   sigue pareciendo un fondo a medio cargar. */
@media (max-width: 860px) {
  .secpic--hero:not(.has-vid) {
    border-radius: var(--r-lg);
    overflow: clip;
    border: 1px solid color-mix(in oklch, var(--brand) 38%, transparent);
    box-shadow:
      0 10px 30px -12px oklch(0.10 0.02 255 / 0.9),
      0 0 24px -8px color-mix(in oklch, var(--brand) 45%, transparent);
  }

  /* Sin marco que la encierre, la pieza va A SANGRE y crece con la pantalla.
     El alto es su 16:9 EXACTO sobre el ancho entero: así el vídeo llena la caja
     de borde a borde y no quedan franjas muertas arriba y abajo (antes se le
     puso 74vw a ojo y sobraban 43 px por cada lado en un teléfono de 390). */
  .secpic--hero.has-vid {
    left: 0;
    right: 0;
    height: var(--vid-alto-lleno);
    /* Con el zoom, lo que sobra tiene que quedarse dentro: sin esto se derrama
       por arriba (sobre la cabecera) y por abajo (sobre el título). */
    overflow: hidden;
  }

  /* Y el texto arranca justo debajo del vídeo: dónde empieza la caja MÁS lo que
     mide, más el aire. Va por hermano (~) porque .container.hero__ari es el
     hermano siguiente de .secpic--hero en el HTML; con .has-vid, para que si el
     vídeo no arranca mande la regla de arriba (caja con marco, más estrecha) y
     no quede un hueco debajo de la foto. */
  .secpic--hero.has-vid ~ .container.hero__ari {
    padding-top: calc(var(--vid-arriba) + var(--vid-alto-lleno) + var(--vid-aire));
  }
}

/* La foto de respaldo del hero, en el celular, va TAMBIÉN a plena vista dentro
   del marco. Si el teléfono no deja arrancar el vídeo (ahorro de batería en
   iOS, por ejemplo) lo que se ve es esta foto, y estaba al 78 % con el aspecto
   de siempre: por eso "no se notaba" ningún cambio por más que se realzara el
   vídeo, que ni siquiera llegaba a verse. */
@media (max-width: 860px) {
  .secpic--hero img {
    opacity: 1;
    transform: none;
    filter: brightness(1.15) saturate(1.1);
  }
}

/* ---- OBERTURA: primero el vídeo, luego la portada ------------------------
   (19-ago-2026, pedido del dueño; antes esto solo pasaba en el celular.)
   Al abrir, la portada no enseña nada: solo el vídeo, entero y sin velo. La
   clase html.hero-cine la pone el guion de <head> de index.html —antes del
   primer pintado, para que el contenido no asome y se esconda después— y la
   quita home.js cuando el vídeo termina su vuelta, dejando html.hero-fin.

   REDES DE SEGURIDAD, porque esto esconde la portada unos segundos:
     · se destapa al terminar el vídeo, al primer toque/scroll/tecla, o por
       varios relojes de respaldo (ver home.js y el guion de <head>);
     · si el vídeo no arranca (ahorro de batería, autoarranque bloqueado) se
       destapa a los 3 s;
     · con "reducir movimiento" o con ahorro de datos no hay obertura: la
       portada se ve entera desde el primer instante.
   La portada NUNCA puede quedarse esperando a un vídeo. */

/* Lo que se esconde: la bienvenida, las cifras, la pista de "desliza" y la
   propia cabecera. Con visibility, no solo con opacity: un enlace invisible
   pero pulsable es una trampa para quien navega con el teclado. */
html.hero-cine .hero__ari,
html.hero-cine .hero__cue,
html.hero-cine .site-header {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

/* La pista de "desliza" y la cabecera vuelven con un fundido simple. El bloque
   central NO lleva transición: su entrada la hacen las dos animaciones de aquí
   abajo, y encadenar las dos cosas se veía como un doble fundido.
   Ojo con la cabecera: aquí se REESCRIBE su transition, así que hay que
   arrastrar las tres propiedades que ya traía de chrome.css (el filo y la
   sombra de .is-stuck) o dejarían de suavizarse. */
.hero__cue {
  transition: opacity 800ms var(--ease-out), visibility 0s;
}

.site-header {
  transition: opacity 800ms var(--ease-out), visibility 0s,
    border-color var(--t), background-color var(--t), box-shadow var(--t);
}

/* La vuelta: cada costado entra desde AFUERA —la marca por la izquierda, las
   cifras por la derecha—, que es lo que hace leer el gesto de "se apartan para
   no tapar el dibujo". El recorrido es corto a propósito: más largo se siente
   lento, y esto se ve en cada carga de la portada. */

/* "backwards" y no "both" a propósito: con "both" la animación se queda
   mandando sobre transform para siempre, y el parallax del hero (cinematic.js,
   que escribe un translateY en el estilo del elemento) dejaba de moverse. Con
   "backwards" solo fija el estado de ANTES de arrancar —que es lo que evita el
   destello— y al terminar suelta el control. */
/* Los dos costados entran A LA VEZ. Antes las cifras salían 120 ms después que
   la marca, y ese desfase se leía como que la página iba a destiempo, no como
   un escalonado. El recorrido también se acortó (26 → 14 px): lo que tiene que
   contar el gesto es "se apartan", y para eso basta con insinuarlo. */
html.hero-fin .hero__content {
  animation: heroEntraIzq 1s var(--ease-out) backwards;
}

html.hero-fin .hero__stats {
  animation: heroEntraDer 1s var(--ease-out) backwards;
}

@keyframes heroEntraIzq {
  from { opacity: 0; transform: translateX(-14px); }
  to   { opacity: 1; transform: none; }
}

@keyframes heroEntraDer {
  from { opacity: 0; transform: translateX(14px); }
  to   { opacity: 1; transform: none; }
}

/* Ya no hay deriva de reposo: desde el 19-ago-2026 el vídeo NO se congela al
   terminar la obertura, sigue en bucle detrás de la portada. El movimiento lo
   pone el propio vídeo; sumarle una animación de escala encima era trabajo de
   más y se notaba como un temblor. Los fotogramas de heroReposo se quedan por
   si algún día vuelve el modo congelado. */

/* Recorte de recorrido (19-ago-2026): con 3,5 % de escala y 10 px la deriva se
   NOTABA, y una imagen fija que se mueve parece un fallo de dibujo, no una
   pieza viva. Con la mitad ya no se ve moverse: se percibe que respira. */
/* Parte del zoom que tenga la pieza (1 en escritorio, 1.18 en el celular) y le
   suma la respiración. Sin el var(), esta animación pisaba el zoom del móvil y
   la pieza pegaba un salto hacia atrás en cuanto terminaba el vídeo. */
/* Dos juegos de fotogramas con números escritos a mano, en vez de uno solo con
   var() dentro. Es más largo pero Safari lo entiende siempre: las variables
   dentro de @keyframes son terreno resbaladizo en WebKit, y esta animación
   escribe transform sobre el vídeo — si falla, la pieza pega un salto.
   El móvil parte de su zoom (1.18) en vez de 1; el resto es igual. */
@keyframes heroReposo {
  from { transform: scale(1) translateY(0); }
  to   { transform: scale(1.016) translateY(-5px); }
}

/* (heroReposoMovil retirado: partía del zoom de 1.18, que ya no existe.) */

/* Con el hero fuera de pantalla la deriva se para (la clase la pone home.js
   desde el mismo observador que ya pausaba el vídeo). */
.secpic--hero.fuera .secpic__vid {
  animation-play-state: paused;
}

/* LA OBERTURA EN EL CELULAR (19-ago-2026).
   Antes esto era un empujón de 18svh, un número puesto a ojo: la pieza bajaba
   un poco y se quedaba en cualquier sitio, ni arriba ni en el centro, con el
   resto de la pantalla en negro. No se leía como una obertura sino como una
   página a medio cargar.

   Ahora la cuenta es exacta: durante la obertura la pieza se planta en el
   CENTRO de la pantalla —el negro le queda repartido arriba y abajo, como en
   un cine— y al terminar sube sola a su sitio de cabecera mientras el texto
   aparece debajo. El recorrido es
       mitad de la pantalla − donde empieza la caja − la mitad de su alto,
   así que sale centrada en cualquier teléfono, de 320 px a una tablet, sin
   volver a tocar ningún número.

   Se mueve con transform y no con top: así el navegador no recalcula la
   maquetación en cada fotograma, que en un teléfono se nota. */
@media (max-width: 860px) {
  .secpic--hero {
    transition: transform 900ms cubic-bezier(0.22, 0.61, 0.36, 1);
  }

  /* A sangre desde el primer instante, no solo cuando el vídeo ya carga: si la
     caja cambiara de ancho al llegar el vídeo se vería un salto. */
  html.hero-cine .secpic--hero {
    left: 0;
    right: 0;
    height: var(--vid-alto-lleno);
    /* Dos veces, y no es un descuido: la de arriba usa vh y la entiende
       cualquier teléfono; la de abajo usa svh —la altura REAL sin contar la
       barra del navegador, que es la buena— y solo la aplican los que saben.
       Un iPhone viejo se queda con la primera en vez de quedarse sin centrar. */
    transform: translateY(calc(50vh - var(--vid-arriba) - var(--vid-alto-lleno) / 2));
    transform: translateY(calc(50svh - var(--vid-arriba) - var(--vid-alto-lleno) / 2));
  }

  /* La entrada del contenido, en el celular, es DISTINTA. En escritorio la
     marca llega por la izquierda y las cifras por la derecha porque están en
     dos columnas, una a cada canto, y el gesto cuenta que se apartan para no
     tapar el vídeo. Aquí no hay dos columnas: va todo apilado en una sola,
     debajo de la pieza. Ese mismo movimiento lateral se veía como si el bloque
     se hubiera descolocado.
     Lo que corresponde es lo que hace el propio vídeo: subir. Los dos suben
     juntos, un palmo, detrás de la pieza que se va a su sitio. */
  /* Y sin animación de entrada: en el celular ya no hay obertura de la que
     salir, así que el contenido no tiene que "aparecer" — está ahí desde el
     principio, como en cualquier página. */
  html.hero-fin .hero__content,
  html.hero-fin .hero__stats {
    animation: none;
  }
}

@keyframes heroEntraSube {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: none; }
}

/* Lo mismo en computadora (19-ago-2026, pedido del dueño: "al medio y luego
   que suba, también en PC"). Ahí el vídeo ya ocupa el hero entero, así que el
   gesto se cuenta al revés: durante la obertura baja al centro y se encoge un
   punto, y al abrirse la portada sube a su sitio y recupera su tamaño. Es
   transform puro: lo resuelve la tarjeta gráfica y no recalcula la página. */
@media (min-width: 861px) {
  .secpic--hero {
    transition: transform 900ms cubic-bezier(0.22, 0.61, 0.36, 1);
  }

  html.hero-cine .secpic--hero {
    transform: translateY(9svh) scale(0.9);
  }
}

/* Con "reducir movimiento" no hay obertura ni deriva: todo quieto y a la vista.
   Va al final para ganar por orden a lo de arriba. */
@media (prefers-reduced-motion: reduce) {
  html.hero-cine .hero__ari,
  html.hero-cine .hero__cue,
  html.hero-cine .site-header {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transform: none;
  }

  /* Ojo: aquí NO se puede borrar el transform del vídeo. Antes ahí vivía una
     deriva de reposo, pero ahora vive el zoom del celular, y quitarlo encogía
     la pieza justo para quien pidió menos movimiento. Se para la animación (que
     es lo que molesta) y se deja el zoom (que es maquetación, no movimiento).
     La caja del hero sí vuelve a su sitio: ese transform es el de la obertura. */
  html.hero-cine .secpic--hero {
    transform: none;
  }

  .secpic--hero .secpic__vid {
    animation: none;
  }

  html.hero-fin .hero__content,
  html.hero-fin .hero__stats {
    animation: none;
  }
}

/* ---- Sin fondo: el vídeo se funde con la página -------------------------
   (19-ago-2026, pedido del dueño: "¿no se puede quitar el fondo?".)
   El vídeo está grabado sobre negro. Con la mezcla `screen`, el negro se
   vuelve INVISIBLE y solo quedan las luces, que se suman al fondo de la
   portada. Es la forma limpia de quitarle el fondo a un vídeo sin canal de
   transparencia: nada de recortes ni de máscaras.
   Efectos secundarios buenos: ya no se ve el recuadro oscuro flotando sobre
   la página, y como `screen` suma luz, el vídeo se percibe mucho más brillante
   sin tener que forzarle el filtro. Por eso el brillo baja de 3,1 a 1,5. */
.secpic--hero.has-vid .secpic__vid {
  /* EL CORTE ES LO DELICADO DE ESTA REGLA. Brillo y contraste encadenados
     hacen una recta: resultado = brillo·contraste·x − (contraste−1)/2. Todo lo
     que quede por debajo de (contraste−1)/(2·brillo·contraste) se va a negro
     puro, y ESE es el número que borra el recuadro… o el vídeo.

     Con contraste 2,0 el corte caía en 40/255. Suena poco, pero este vídeo es
     oscurísimo —su brillo medio va de 13 a 32 sobre 255—, así que 40 no le
     quitaba el fondo: le borraba el dibujo, y la portada se quedaba en negro
     (reportado en celular el 19-ago-2026, y en escritorio pasaba igual).

     Con 1,25 el corte queda en 14/255: por encima del ruido de compresión, que
     es lo que dibujaba el recuadro, y muy por debajo de donde vive la imagen.
     Si vuelves a tocarlo, mira primero cuánto vale el corte; y para no adivinar,
     usa ?video=niveles, que te lo dice mientras mueves las barras. */
  filter: brightness(1.84) contrast(1.25) saturate(1.25);
}

/* Sin fondo no hay pieza que enmarcar: el borde y la sombra dibujaban un
   rectángulo alrededor de nada. */
@media (max-width: 860px) {
  .secpic--hero {
    border: 0;
    box-shadow: none;
    border-radius: 0;
    overflow: visible;
  }
  .secpic--hero.has-vid .secpic__vid {
    /* Mismo corte que en escritorio (14/255) pero con más ganancia: aquí el
       vídeo no tiene texto encima y la pantalla es pequeña, así que necesita
       más cuerpo. Cortaba en 38/255 y dejaba la pantalla en negro. */
    /* EL MISMO que en escritorio, a propósito (19-ago-2026). Aquí llevaba más
       ganancia "porque la pantalla es chica y no hay texto encima", y el
       resultado era el contrario del buscado: con brillo 2,2 el canal rojo se
       satura a tope antes que el verde y el azul, y el naranja de los anillos
       salía gris oliva. En el PC, con esta curva, se ve vivo; no había ninguna
       razón para que el teléfono llevara otra. */
    filter: brightness(1.84) contrast(1.25) saturate(1.25);
  }
}

/* ---- Que el marco del vídeo desaparezca de verdad ------------------------
   (19-ago-2026.) La mezcla `screen` no bastaba: para que el negro del vídeo se
   vuelva invisible, la mezcla necesita tener DEBAJO el color de la página, y
   la capa del vídeo era transparente y además vive en un grupo aislado
   (isolation: isolate en el hero). Resultado: el vídeo se pintaba tal cual y
   su rectángulo negro se recortaba contra el azul noche del fondo — el marco
   que se veía.
   Se le pinta el mismo fondo de la página a la capa: ahora `screen` tiene con
   qué mezclarse, el negro del vídeo da exactamente el color del fondo (o sea,
   desaparece) y solo quedan las luces. */
.secpic--hero {
  background: var(--bg);
}
/* Y nada de recortes ni filos alrededor, en ningún tamaño de pantalla. */
.secpic--hero,
.secpic--hero .secpic__vid {
  border: 0;
  box-shadow: none;
}

/* SIN máscara en el vídeo (19-ago-2026), por el mismo motivo que la mezcla:
   Safari tiene el mismo problema al enmascarar un <video>, y esto era un
   remate cosmético —un fundido del 8 % en el borde— que ya no hace falta
   desde que la curva de niveles deja el fondo en negro real. Entre un adorno y
   que la portada se vea en los iPhone, se va el adorno. */
