/* NOTA DE ALCANCE (11-ago-2026)
   Este archivo colgaba de [data-page="inicio"], o sea, solo de la portada. Al
   pedir el dueño que el catálogo se viera igual, se cambió el ancla por la
   CLASE .pd-negro, que se le pone al <body> de cada página que tenga que ir en
   negro. Añadir una página al lienzo oscuro es ahora: poner la clase, cargar
   este archivo y fijar el tema oscuro. Nada más.
   Las reglas del hero (.pd-hero, .pd-escena, .pd-cinta…) siguen aquí y
   simplemente no encuentran nada que pintar en las demás páginas. */
/* =============================================================================
   Vault Solutions — Portada estilo página de producto (referencia: la página
   del Mac mini de Apple, apple.com/la/mac-mini, 10-ago-2026)

   Qué se copió y POR QUÉ, para que nadie lo deshaga sin querer:

   · Una frase por pantalla. Apple no amontona: cada tramo dice UNA cosa, en
     letra enorme y centrada, con mucho aire arriba y abajo. Eso es lo que hace
     que se lea como catálogo de producto y no como folleto.
   · Barra de producto pegajosa bajo la cabecera ("Vault Solutions · anclas ·
     Comprar"). Es la que sostiene la venta: por más que bajes, el botón de
     comprar nunca se va de la pantalla.
   · Capítulos a sangre que ALTERNAN claro y oscuro. Aquí el oscuro es el navy
     de marca (#0B0B0D) y el acento el oro (#D4AF37): sobre el navy el oro se
     enciende, y es justo el contraste del manual de marca.
   · Radio pequeño en las piezas de imagen y grande en las tarjetas. Apple usa
     esquinas casi rectas en las fotos para que la foto sea la protagonista.
   · Nada de animación obligatoria: todo lo que se mueve entra por opacidad y
     unos píxeles, y con "movimiento reducido" no se mueve nada.

   Este archivo SOLO afecta a la portada (body.pd-negro) para no
   arrastrar al catálogo, la ficha ni el panel.
   ============================================================================= */

.pd-negro {
  /* Escala tipográfica de la portada. Son tres tamaños y basta: el del hero,
     el de los capítulos y el del texto de apoyo. Todo con clamp() para que en
     el celular no haya que escribir un tamaño aparte en cada regla. */
  --pd-display: clamp(2.6rem, 8.2vw, 6.5rem);
  --pd-titular: clamp(2.1rem, 6vw, 4.75rem);
  --pd-lede: clamp(1.02rem, 1.05rem + 0.5vw, 1.5rem);

  /* El aire vertical entre capítulos. Es EL parámetro del estilo Apple: si se
     achica, la página deja de respirar y vuelve a parecer un folleto. */
  --pd-aire: clamp(4.5rem, 10vw, 9.5rem);

  /* Alto de la cabecera del sitio: la barra de producto se pega justo debajo. */
  --pd-headerH: 4.5rem;

  /* ---------------------------------------------------------------------
     UN SOLO NEGRO de la cabecera al pie (pedido del dueño, 10-ago-2026).
     El sistema alterna --bg y --bg-subtle para separar secciones, y eso
     dibujaba franjas de distinto tono a lo largo de la portada. Aquí los dos
     tokens valen lo MISMO, así que el lienzo es continuo y las secciones se
     separan solo por el aire vertical, que es lo que hace la plantilla de
     referencia.

     Se cambian solo los dos tokens del LIENZO. --surface y --surface-2
     (tarjetas, vitrina, acordeón) siguen un punto más claros a propósito: sin
     esa diferencia las tarjetas desaparecerían contra el fondo.

     11-ago-2026: NEGRO PURO, #000. Se probó primero con el navy de marca
     (#0B0B0D) y con un casi-negro azulado (#050506); los dos tiran a azul y el
     dueño quiere negro, negro. Aquí no se busca un tono "bonito": se busca que
     el lienzo desaparezca y solo se vean el oro y las tarjetas. */
  --pd-negro: #000000;
  --bg: var(--pd-negro);
  --bg-subtle: var(--pd-negro);

  /* ---------------------------------------------------------------------
     RECETA DE VIDRIO (pedido del dueño, 10-ago-2026: "que se vea tipo Apple").

     El brillo y el filo NO se inventan aquí: son los mismos --gloss-* que
     styles.css ya usa en todos los botones de la tienda. Al principio escribí
     un velo propio, un degradado que bajaba liso de 7% a 0, y quedaba MATE: lo
     que hace que una superficie se lea como pulida no es el degradado, es el
     CORTE seco a media altura (en --gloss-face, del 8% al 0% entre el 40% y el
     58%). Reutilizarlo, además, hace que la píldora, las tarjetas y los botones
     brillen todos igual, que es lo que se nota cuando está bien hecho.

       --pd-brillo  velo con el corte de brillo (= --gloss-face)
       --pd-filo    canto claro arriba y oscuro abajo (= --gloss-rim); es lo
                    que dibuja el GROSOR del cristal
       --pd-reflejo barrido diagonal. Este sí es propio y más flojo que
                    --gloss-sweep: el de la casa está pensado para un botón al
                    pasar el cursor, y al 28% sobre un panel de 74rem se veía
                    una franja diagonal cruzándolo entero.
     Se aplican con .pd-vidrio para no repetirlas caja por caja. */
  --pd-brillo: var(--gloss-face);
  --pd-filo: var(--gloss-rim);
  --pd-reflejo: linear-gradient(118deg, transparent 30%, oklch(1 0 0 / 0.05) 44%, transparent 58%);
}

/* Solo para lectores de pantalla. La regla existía en auth.css, pero la portada
   no carga ese archivo, así que aquí va su copia: la usa el <h1> del hero, que
   se conserva por accesibilidad y SEO aunque no se vea. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ---------------------------------------------------------------------------
   FUERA LOS RESPLANDORES DORADOS
   El tema oscuro pinta dos capas fijas sobre TODA la página — tres halos de oro
   (body::before, animados) y una cuadrícula de puntos con viñeta (body::after).
   Eran las manchas amarillas del fondo, y en la portada sobran: el oro queda
   solo donde significa algo (la píldora, el titular, el botón y los precios).

   Se apagan los dos, y hay que dejarlos apagados: el fondo de la portada lo
   pinta ahora .vs-fondo (ver «EL FONDO ANIMADO» más abajo), que trae sus
   propias manchas de oro. Si estos volvieran, se sumarían a las de allí y el
   fondo saldría con el doble de color del que se diseñó.

   AVISO PARA QUIEN VENGA A AÑADIR UNA CAPA DE FONDO: este `!important` es una
   trampa cara. Los pseudoelementos del body son el sitio natural para una capa
   fija a pantalla completa, y cualquier intento de usarlos muere aquí sin dejar
   rastro —la regla se aplica, el elemento nunca se pinta, y en las herramientas
   del navegador todo se ve correcto—. Si necesitas una capa así, cuélgala de
   .vs-fondo, que para eso está.
   --------------------------------------------------------------------------- */
.pd-negro::before,
.pd-negro::after {
  display: none !important;
}

/* --- La receta de vidrio, aplicada ------------------------------------------
   ::before lleva el velo y ::after el barrido. Van en pseudoelementos para no
   pisar el `background` propio de cada caja, y sin capturar clics. */
.pd-vidrio {
  position: relative;
  box-shadow: var(--pd-filo);
}

.pd-vidrio > * {
  position: relative;
  z-index: 1;
}

.pd-vidrio::before,
.pd-vidrio::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: inherit;
  pointer-events: none;
}

.pd-vidrio::before {
  background: var(--pd-brillo);
}

.pd-vidrio::after {
  background: var(--pd-reflejo);
}

/* ---------------------------------------------------------------------------
   CABECERA EN PÍLDORA FLOTANTE
   En la plantilla de referencia la cabecera no es una barra pegada al borde:
   es una cápsula centrada, despegada de los cuatro lados, con el fondo negro
   pasándole por detrás. Aquí se consigue dejando <header> transparente y
   convirtiendo su interior en la píldora.

   La cabecera la escribe components.js y la comparten TODAS las páginas: por
   eso el cambio vive aquí, colgado de .pd-negro, y el catálogo, la
   ficha y el panel conservan su barra de siempre.
   --------------------------------------------------------------------------- */
.pd-negro .site-header {
  background: transparent;
  border-bottom: 0;
  padding-block: clamp(0.6rem, 1.6vw, 1.1rem);
}

/* LA PÍLDORA ES UNA BURBUJA (pedido del dueño, 11-ago-2026).
   Antes llevaba un relleno gris translúcido (oklch 0.20 al 72%) y se leía como
   una barra pintada de gris flotando sobre el negro. Una burbuja no tiene
   relleno: lo que se ve de ella es el CANTO y un par de reflejos, y por dentro
   se ve lo que hay detrás. De ahí los tres cambios:

     · Fondo casi inexistente. Solo un velo blanquísimo (5% arriba, 1% al medio)
       que da la curvatura de la pared del jabón. Nada de gris.
     · La única capa que "tapa" es el desenfoque del fondo, y baja de 20px a
       12px con menos saturación: así el negro del cuerpo se sigue viendo por
       dentro y la burbuja no se convierte en una pastilla opaca.
     · Los reflejos: un filo de luz arriba y un rebote abajo (ambos por dentro),
       y un brillo especular arriba a la izquierda, que es lo que el ojo lee
       como "esto es una pompa" y no "esto es una caja redondeada". */
.pd-negro .site-header__inner {
  position: relative;
  max-width: 74rem;
  margin-inline: auto;
  min-height: 3.4rem;
  padding-inline: clamp(0.9rem, 2vw, 1.5rem);
  border-radius: var(--r-pill);
  background: linear-gradient(
    180deg,
    oklch(1 0 0 / 0.055),
    oklch(1 0 0 / 0.012) 48%,
    oklch(1 0 0 / 0.032)
  );
  border: 1px solid oklch(1 0 0 / 0.1);
  backdrop-filter: saturate(140%) blur(12px);
  -webkit-backdrop-filter: saturate(140%) blur(12px);
  box-shadow:
    inset 0 1px 0 oklch(1 0 0 / 0.28),      /* filo de luz del borde de arriba */
    inset 0 -1px 0 oklch(1 0 0 / 0.09),     /* rebote del borde de abajo */
    inset 0 0 26px oklch(1 0 0 / 0.045),    /* el aire de dentro de la pompa */
    0 16px 38px -26px oklch(0 0 0 / 0.85);
}

/* Los dos reflejos de la burbuja, en z-index -1.
   OJO: aquí NO se puede subir el contenido con `> * { position: relative }`
   como en el resto de cajas de cristal. A partir de 1200px chrome.css centra
   el menú con `position:absolute; left:50%`, y darle `relative` a los hijos lo
   sacaba de sitio: el menú se iba arriba y a la izquierda de la píldora.
   Con -1 el velo queda encima del fondo y debajo del contenido sin tocar la
   posición de nadie. Funciona porque backdrop-filter ya crea un contexto de
   apilamiento en la píldora, así que el -1 no se escapa hacia atrás. */
.pd-negro .site-header__inner::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  pointer-events: none;
  /* Brillo especular arriba a la izquierda + un segundo, más flojo, abajo a la
     derecha: en una pompa real el reflejo de la luz y el rebote del suelo
     salen siempre en esquinas opuestas. Es ESO lo que la hace esférica. */
  background:
    radial-gradient(58% 150% at 20% -40%, oklch(1 0 0 / 0.17), transparent 62%),
    radial-gradient(42% 130% at 82% 150%, oklch(1 0 0 / 0.07), transparent 66%);
}

/* Al desplazar, la burbuja se cierra un punto para que el texto que le pasa por
   debajo no se lea a través. Sigue sin ser gris: se sube el mismo velo blanco y
   se aprieta el desenfoque, que es lo que hace una pompa cuando engorda. */
.pd-negro .site-header.is-stuck .site-header__inner {
  background: linear-gradient(
    180deg,
    oklch(1 0 0 / 0.085),
    oklch(1 0 0 / 0.03) 48%,
    oklch(1 0 0 / 0.055)
  );
  backdrop-filter: saturate(150%) blur(20px);
  -webkit-backdrop-filter: saturate(150%) blur(20px);
}

/* --- El buscador de la píldora: CHIP, no caja ------------------------------
   chrome.css cambia el icono de buscar por una caja de texto de 256px a partir
   de 1240px. En la píldora esa caja desequilibraba todo: en la plantilla de
   referencia ese sitio lo ocupa un chip pequeño (la banderita de idioma) y no
   un campo. Aquí mandan el chip y el icono SIEMPRE, en todos los anchos, que
   además es lo que se pidió: "en el idioma debe ir el icono de buscar".
   El campo grande sigue vivo en el resto del sitio. */
.pd-negro .hsearch {
  display: none;
}

.pd-negro .header-actions .has-search {
  display: block;
}

.pd-negro .header-actions .icon-btn {
  width: auto;
  min-width: 2.3rem;
  height: 2.3rem;
  padding-inline: 0.62rem;
  border-radius: var(--r-pill);
  background: oklch(1 0 0 / 0.06);
  border: 1px solid oklch(1 0 0 / 0.1);
  color: oklch(0.82 0 0 );
  transition: background-color var(--t), color var(--t), transform var(--t);
}

.pd-negro .header-actions .icon-btn:hover {
  background: oklch(1 0 0 / 0.12);
  color: #fff;
  transform: translateY(-1px);
}

/* La animación pedida: la lupa "busca" sola cada pocos segundos —un giro corto
   de ida y vuelta— para que se vea que ese chip sirve para buscar y no es un
   adorno. Es transform, que resuelve el compositor: no cuesta nada. */
.pd-negro #searchBtn svg {
  animation: pd-lupa 5.5s ease-in-out infinite;
  transform-origin: 45% 45%;
}

@keyframes pd-lupa {
  0%, 62%, 100% { transform: rotate(0) scale(1); }
  68% { transform: rotate(-14deg) scale(1.12); }
  76% { transform: rotate(12deg) scale(1.12); }
  84% { transform: rotate(0) scale(1.05); }
}

/* Menú con el aire de la referencia: allí "Pricing · Blog · Contact" respiran
   mucho más que los 0.15rem de hueco que trae chrome.css. */
.pd-negro .main-nav {
  gap: clamp(0.2rem, 1.4vw, 1.1rem);
}

@media (prefers-reduced-motion: reduce) {
  .pd-negro #searchBtn svg {
    animation: none;
  }

  .pd-negro .header-actions .icon-btn:hover {
    transform: none;
  }
}

.pd-bar__in {
  display: flex;
  align-items: center;
  gap: clamp(0.5rem, 2vw, 1.5rem);
  min-height: 3rem;
  padding-inline: clamp(0.85rem, 2.5vw, 2.25rem);
}

.pd-bar__name {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.05rem;
  letter-spacing: -0.01em;
  color: var(--ink);
  white-space: nowrap;
}

/* Las anclas empujan el botón de comprar al extremo derecho. Se desplazan en
   horizontal en vez de partirse en dos líneas: una barra de dos pisos comería
   la primera pantalla, que es la que vende. */
.pd-bar__links {
  display: flex;
  align-items: center;
  gap: clamp(0.75rem, 2vw, 1.6rem);
  margin-left: auto;
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}

.pd-bar__links::-webkit-scrollbar {
  display: none;
}

.pd-bar__links a {
  font-size: 0.86rem;
  font-weight: 500;
  color: var(--ink-body);
  white-space: nowrap;
  transition: color var(--t);
}

.pd-bar__links a:hover {
  color: var(--ink);
}

.pd-bar__buy {
  flex: none;
  margin-left: clamp(0.5rem, 2vw, 1.25rem);
  padding: 0.42rem 1.05rem;
  border-radius: var(--r-pill);
  background: var(--brand-strong);
  color: var(--on-brand);
  font-size: 0.86rem;
  font-weight: 700;
  white-space: nowrap;
  box-shadow: var(--gloss-rim);
  transition: background-color var(--t), transform var(--t);
}

.pd-bar__buy:hover {
  background: var(--brand-strong-hover);
  transform: translateY(-1px);
}

/* En el celular las anclas sobran: ocupan toda la barra y dejan el botón de
   comprar arrinconado. Se queda el nombre y el botón, que es lo que importa. */
@media (max-width: 700px) {
  .pd-bar__links {
    display: none;
  }

  .pd-bar__buy {
    margin-left: auto;
  }
}

/* ---------------------------------------------------------------------------
   HERO — formato de portada SaaS (referencia: template-2.aniq-ui.com)
   El original es azul sobre negro; aquí el acento es el ORO del manual de
   marca. Las capas, de atrás hacia adelante:
     halo (0) < esfera (1) < piezas flotantes (2) < texto (3)
   El texto va SIEMPRE encima: las piezas son decoración y no deben tapar ni
   el titular ni el botón, que es lo único que tiene que pulsarse aquí.
   --------------------------------------------------------------------------- */
/* =============================================================================
   EL FONDO ANIMADO (11-ago-2026)

   Aquí hubo una foto de fondo (assets/img/fondo-licencias.jpg) y el dueño la
   quitó: quería movimiento de verdad, no una imagen quieta con un zoom encima.
   Este fondo está DIBUJADO CON CSS, sin una sola imagen y sin JavaScript. Pesa
   cero bytes de descarga y anima solo `transform`, así que el navegador se
   lleva cada capa a la GPU y no repinta un píxel mientras corre.

   POR QUÉ ES UN <div> Y NO LOS PSEUDOELEMENTOS DEL BODY
   Con ::before y ::after solo caben dos capas, y aquí hacen falta cuatro que se
   mueven a ritmos distintos. Ese es justo el punto: si dos efectos comparten
   elemento, comparten `transform`, y al animar uno se arrastra el otro —una
   viñeta que se desplaza se lee como una mancha cruzando la pantalla—. Cada
   capa va suelta para que cada una tenga su propio tiempo.

   LAS CUATRO CAPAS, de atrás hacia adelante:
     1 · AURORA    manchas de oro que respiran; dan el color y la profundidad
     2 · REJILLA   retícula técnica que cae despacio; da la escala y el «digital»
     3 · HAZ       un barrido de luz que cruza cada 19 s; es el latido
     4 · VIÑETA    quieta, cierra los bordes y protege la lectura del texto

   Los tiempos son primos entre sí (34 s, 26 s, 19 s) a propósito: así las tres
   nunca coinciden dos veces seguidas y el conjunto no se siente en bucle.
   --------------------------------------------------------------------------- */
.vs-fondo {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  overflow: hidden;
  background: var(--pd-negro);
  /* Las escribe fondo.js con la posición del cursor, de -1 a 1. Nacen en 0 para
     que sin JavaScript —o en un móvil— el fondo se quede centrado y correcto. */
  --vs-x: 0;
  --vs-y: 0;
}

.vs-fondo > * {
  position: absolute;
  display: block;
}

/* ================== LA CINTA DE LUZ — 13-ago-2026 ==========================
   El vídeo del dueño, DETRÁS DE TODA LA PÁGINA. Vive dentro de .vs-fondo, que
   es fija y va en z-index -1, así que no está atada al hero: se ve de arriba
   abajo mientras se baja, y además viaja con el scroll (fondo.js escribe
   --cinta-x / --cinta-y).

   OJO CON EL NOMBRE. La primera versión se llamó `.pd-cinta` y rompió la
   portada: ese nombre YA era de la cinta de marcas de más abajo, y la regla
   que llegaba después le ganaba el `position`. El vídeo se quedó dentro del
   flujo y empujó la bóveda media pantalla hacia abajo. De ahí el `vs-`, que es
   el prefijo de esta capa de fondo.

   ---------------------------------------------------------------------------
   POR QUÉ NO SE VEÍA (revisión del 13-ago-2026, tarde)
   El dueño avisó de que «en web se pierde y en el móvil no se ve nada». Las dos
   quejas tenían causas distintas y las dos eran mías:

   · EN ESCRITORIO era una multiplicación mal hecha. El vídeo iba al 45%, pero
     ENCIMA llevaba un velo que en el centro oscurecía un 54%. El resultado real
     no era 45%, era 0.45 × 0.46 ≈ 21%. Ahora el vídeo sube al 62% y el velo
     baja al 31% en el centro: ≈ 43% efectivo, el doble que antes.

   · EN EL MÓVIL era el recorte. La cinta es una banda HORIZONTAL en mitad del
     fotograma, con el tercio de arriba y el de abajo en negro puro. Metida en
     una pantalla vertical con `cover`, sólo cabía el 26% central: un borrón de
     un solo color. Por eso ahora hay un segundo archivo GIRADO 90°, y en
     vertical la cinta BAJA por la pantalla en lugar de cruzarla. Encaja casi
     entero (se recorta un 18%) y acompaña al scroll en vez de pelearse con él.

   EL VELO SIGUE SIN SER ADORNO: es lo que sostiene la lectura. Se ha aflojado,
   no quitado, y después de aflojarlo se volvió a medir texto por texto en las
   trece páginas. Si alguien vuelve a tocar estos números, que vuelva a medir.

   La escala cubre el viaje: el desplazamiento llega a ±7% horizontal y ±5%
   vertical, así que hace falta al menos un 14% de margen. 1.18 deja un 9% por
   cada lado — suficiente en cualquier proporción de ventana, porque `cover`
   siempre desborda por el otro eje. */
.vs-cinta {
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0.62;
  border: 0;
  pointer-events: none;
  /* `translate` y `scale` sueltos, no `transform`: así se componen con las
     animaciones de las otras capas sin pisarse, igual que ya hacen la aurora y
     el haz de esta misma hoja. */
  translate: calc(var(--cinta-x, 0) * 1%) calc(var(--cinta-y, 0) * 1%);
  scale: 1.18;
  will-change: translate;
}

.vs-cinta__velo {
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    radial-gradient(118% 82% at 50% 42%, oklch(0 0 0 / 0.18), oklch(0 0 0 / 0.62) 78%),
    linear-gradient(180deg,
      oklch(0 0 0 / 0.50) 0%,
      oklch(0 0 0 / 0.16) 34%,
      oklch(0 0 0 / 0.34) 74%,
      oklch(0 0 0 / 0.72) 100%);
}

/* PANTALLA VERTICAL — móviles y tablets de pie.
   Aquí manda `cinta-vert.mp4` (el giro de 90°, lo elige fondo.js). Se recorta
   poco, así que basta una escala corta para dejar sitio al viaje. Y va algo más
   bajo de opacidad que en escritorio porque en un móvil el texto ocupa
   proporcionalmente mucha más pantalla: el mismo brillo estorba más. */
@media (orientation: portrait) {
  .vs-cinta {
    opacity: 0.58;
    scale: 1.14;
  }

  .vs-cinta__velo {
    background:
      radial-gradient(120% 70% at 50% 44%, oklch(0 0 0 / 0.16), oklch(0 0 0 / 0.58) 76%),
      linear-gradient(180deg,
        oklch(0 0 0 / 0.48) 0%,
        oklch(0 0 0 / 0.16) 30%,
        oklch(0 0 0 / 0.32) 72%,
        oklch(0 0 0 / 0.70) 100%);
  }
}

/* Pantallas pequeñas TUMBADAS (un móvil de lado): el alto útil es mínimo y el
   contenido se apretuja, así que la cinta se aparta un poco más. */
@media (orientation: landscape) and (max-height: 500px) {
  .vs-cinta {
    opacity: 0.42;
  }
}

/* Con movimiento reducido no hay vídeo ni viaje: queda el póster quieto, que es
   exactamente lo que ese ajuste del sistema pide. Al no moverse tampoco hace
   falta el margen de la escala. */
@media (prefers-reduced-motion: reduce) {
  .vs-cinta {
    opacity: 0.34;
    translate: none;
    scale: 1;
  }
}

/* 1 · AURORA. Tres manchas de oro de la paleta de marca. Se desbordan un 25%
   por cada lado para que al moverse nunca asome un borde. */
.vs-fondo__aurora {
  inset: -25%;
  background:
    radial-gradient(38vmax 30vmax at 18% 12%, oklch(0.72 0.17 91 / 0.24), transparent 62%),
    radial-gradient(34vmax 28vmax at 86% 22%, oklch(0.70 0.16 91 / 0.17), transparent 64%),
    radial-gradient(46vmax 36vmax at 50% 104%, oklch(0.62 0.15 91 / 0.21), transparent 68%);
  animation: vs-aurora 34s ease-in-out infinite alternate;
  /* EL PARALAJE. Va en `translate` y NO en `transform` a propósito: son dos
     propiedades distintas y el navegador las compone, así que este
     desplazamiento se suma a la deriva de los keyframes sin pisarla. Si las dos
     escribieran `transform`, una anularía a la otra.
     La aurora es la capa «lejana» y por eso es la que más se mueve. */
  translate: calc(var(--vs-x) * -24px) calc(var(--vs-y) * -17px);
  /* El aviso de la bóveda entra y sale con calma; un salto seco delataría que
     es un cambio de clase. */
  transition: filter 0.85s var(--ease-out, ease-out);
  will-change: transform, translate;
}

/* Cuando la bóveda se abre, el oro del fondo se aviva. Es lo que ata el fondo
   con lo que está haciendo el cliente: lo enciende fondo.js al oír
   «vault:abrir», el mismo evento con el que home.js saca la ficha del precio. */
.vs-fondo.is-viva .vs-fondo__aurora {
  filter: brightness(1.5) saturate(1.12);
}

/* 2 · REJILLA. Dos degradados de una línea cruzados. El truco del bucle: la
   animación desplaza EXACTAMENTE una celda (62px), así el fotograma final es
   idéntico al primero y la caída no tiene costura. Por eso es `linear` e
   `infinite` en vez de `alternate` — tiene que caer siempre hacia el mismo
   lado, como una cortina de datos.
   La máscara la desvanece hacia los bordes: una retícula que llega hasta el
   filo de la ventana se ve como un mantel, no como profundidad. */
.vs-fondo__rejilla {
  inset: -62px 0 0;
  background-image:
    linear-gradient(oklch(0.78 0.16 91 / 0.05) 1px, transparent 1px),
    linear-gradient(90deg, oklch(0.78 0.16 91 / 0.05) 1px, transparent 1px);
  background-size: 62px 62px, 62px 62px;
  -webkit-mask-image: radial-gradient(100% 78% at 50% 32%, #000 22%, transparent 76%);
  mask-image: radial-gradient(100% 78% at 50% 32%, #000 22%, transparent 76%);
  animation: vs-rejilla 26s linear infinite;
  /* La rejilla es la capa «cercana»: se mueve MENOS que la aurora. Esa
     diferencia es todo el truco del paralaje — si las dos se movieran igual,
     se leería como una sola lámina deslizándose. */
  translate: calc(var(--vs-x) * -9px) calc(var(--vs-y) * -6px);
  will-change: transform, translate;
}

/* 3 · HAZ. Una banda de luz inclinada que cruza la pantalla y se apaga en los
   extremos. Es lo único que «pasa» de verdad, y por eso va tan espaciado: cada
   19 s, encendiéndose y apagándose en los bordes para que no se vea entrar ni
   salir. Sin `filter: blur` a propósito —el propio degradado ya es suave y el
   desenfoque en una capa de este tamaño es caro en móviles. */
.vs-fondo__haz {
  top: -60%;
  bottom: -60%;
  left: -35%;
  width: 38%;
  background: linear-gradient(90deg,
    transparent,
    oklch(0.85 0.14 91 / 0.09),
    transparent);
  animation: vs-haz 19s ease-in-out infinite;
  will-change: transform, opacity;
}

/* 4 · VIÑETA. QUIETA. Cierra las esquinas para que las capas de arriba asomen
   de la oscuridad en vez de quedar recortadas por el borde de la ventana, y
   oscurece la franja central donde cae el titular. Va la última: es la que
   garantiza el contraste del texto pase lo que pase por detrás. */
.vs-fondo__vineta {
  inset: 0;
  background:
    radial-gradient(60% 44% at 50% 40%,
      oklch(0 0 0 / 0.42) 0%,
      oklch(0 0 0 / 0.16) 58%,
      oklch(0 0 0 / 0) 100%),
    radial-gradient(122% 96% at 50% 36%,
      oklch(0 0 0 / 0) 44%,
      oklch(0 0 0 / 0.42) 78%,
      oklch(0 0 0 / 0.80) 100%),
    linear-gradient(180deg,
      oklch(0 0 0 / 0) 0%,
      oklch(0 0 0 / 0.22) 55%,
      oklch(0 0 0 / 0.55) 100%);
}

@keyframes vs-aurora {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to   { transform: translate3d(2.6%, 1.8%, 0) scale(1.09); }
}

@keyframes vs-rejilla {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(0, 62px, 0); }
}

@keyframes vs-haz {
  0%   { transform: rotate(13deg) translate3d(0, 0, 0); opacity: 0; }
  14%  { opacity: 1; }
  86%  { opacity: 1; }
  100% { transform: rotate(13deg) translate3d(340%, 0, 0); opacity: 0; }
}

/* Con «movimiento reducido» se para todo y queda un fondo fijo perfectamente
   presentable: las manchas, la rejilla y la viñeta siguen ahí; lo único que se
   va es el haz, que sin movimiento sería una banda clara sin sentido. */
@media (prefers-reduced-motion: reduce) {
  .vs-fondo__aurora,
  .vs-fondo__rejilla {
    animation: none;
    translate: none;
    will-change: auto;
  }

  .vs-fondo__haz {
    display: none;
  }
}

/* =============================================================================
   TRES DE LAS CUATRO CAPAS, APAGADAS (12-ago-2026)

   «Quítale la iluminación al fondo de página y eso tipo cuadrículas», con una
   captura del rincón superior izquierdo: la mancha dorada y las líneas.

     · AURORA   era la mancha de oro. Se va.
     · REJILLA  era la cuadrícula de 62px. Se va.
     · HAZ      el barrido de luz cada 19 s. Se va con ellas: es de la misma
                familia y sin las otras dos quedaba una banda clara cruzando un
                fondo liso, más rara todavía que antes.
     · VIÑETA   se QUEDA. No emite luz, la resta: cierra las esquinas y protege
                el contraste del texto. Es la única de las cuatro que no entra
                en lo que se pidió quitar.

   Lo mismo se hizo antes en la versión blanca por otro motivo (allí las capas
   se leían como suciedad sobre el papel); aquí es una decisión de gusto sobre
   el negro. Las cuatro siguen definidas arriba, enteras, con sus keyframes y su
   paralaje: reactivarlas es borrar este bloque.

   `display: none` y no `opacity: 0`: así el navegador además deja de animarlas
   y de componerlas, que era trabajo de GPU en cada fotograma para pintar algo
   que no se ve.
   ============================================================================= */
.vs-fondo__aurora,
.vs-fondo__rejilla,
.vs-fondo__haz {
  display: none;
}

/* fondo.js se queda: no pinta nada por su cuenta —solo movía las capas que
   ahora están apagadas—, se detiene solo a los 20 fotogramas en reposo, y sigue
   siendo quien enciende .is-viva cuando se abre la bóveda. */

/* (Aquí estuvo un fundido de secciones ligado al scroll con
   `animation-timeline: view()`, retirado el 12-ago-2026 ANTES de publicarse.
   Al medirlo con capturas —única forma fiable, porque estas animaciones corren
   en el compositor y getComputedStyle devuelve un valor obsoleto— la ventana
   entera salía NEGRA a media página: las secciones se quedaban en opacidad 0
   en vez de recuperarla. En una tienda en producción eso es contenido que
   desaparece, así que no se subió. Si se retoma, tiene que hacerse con un
   mecanismo cuyo estado por defecto sea VISIBLE. Se rehízo así el mismo día:
   lo mueve cinematic.js (fundidoSecciones) y aquí solo queda la transición. */

/* La clase la pone cinematic.js al observar cada sección. Sin ese guion, la
   clase no existe y no hay ninguna regla que baje la opacidad: el estado por
   defecto es opaco pase lo que pase.
   `will-change` NO se pone a propósito: son ocho secciones enormes y
   promoverlas todas a capa propia cuesta más memoria de vídeo de lo que ahorra;
   la transición de opacidad ya la compone la GPU por su cuenta. */
.vs-fade {
  transition: opacity 0.45s var(--ease-out, cubic-bezier(0.22, 1, 0.36, 1));
}

/* --- Las capas que tapaban el fondo -----------------------------------------
   El hero y el pie pintaban negro OPACO por encima: son las que impedían ver la
   imagen aunque estuviera puesta.
   La CABECERA no se toca. Ya está en transparente más arriba y es a propósito
   —es una píldora flotante y la burbuja de dentro lleva su propio desenfoque—;
   ponerle fondo aquí la convertiría en una barra oscura de lado a lado y se
   perdería la cápsula. */
.pd-negro .site-footer {
  background: transparent;
}

.pd-hero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  /* Transparente: el fondo de la página se ve a través. Antes era
     var(--pd-negro) opaco y tapaba la imagen justo en la primera pantalla. */
  background: transparent;
  color: #fff;
  /* UNA PANTALLA, ni más ni menos (11-ago-2026).
     Antes el alto salía de un relleno inferior enorme (26rem) y el hero medía
     ~780px: en una ventana baja la bóveda se cortaba por abajo y arriba
     quedaba un hueco negro vacío. Ahora el alto lo manda la ventana menos la
     cabecera flotante (~5.5rem), con tope de 46rem para que en pantallas muy
     altas no vuelva a abrirse ese hueco. La bóveda se encaja sola dentro:
     vault3d.js calcula la distancia de cámara a partir de esta caja. */
  min-height: min(44rem, calc(100svh - 9rem));
  /* Relleno de arriba corto a propósito: la bóveda es lo primero y el dueño la
     quiere ALTA, casi pegada a la cabecera flotante. */
  padding-block: clamp(2.25rem, 5vw, 3.75rem) clamp(2rem, 4vw, 3rem);
  text-align: center;
}

/* En móvil la puerta 3D se encoge (tiene que caber a lo ANCHO, no a lo alto) y
   con el hero a pantalla completa quedaba un socavón negro debajo. El hero baja
   de alto para acompañarla. */
@media (max-width: 760px) {
  .pd-hero {
    min-height: min(38rem, calc(100svh - 8rem));
    padding-block: clamp(3.5rem, 9vw, 5rem) clamp(1.5rem, 4vw, 2.5rem);
  }
}

/* El halo se apagó del todo (10-ago-2026): el dueño pidió negro total, sin
   ninguna iluminación de fondo. Ahora la única luz de la portada vive DENTRO
   de la escena 3D, sobre el metal, y no se derrama al lienzo.
   El elemento se conserva en el HTML por si algún día vuelve a hacer falta. */
.pd-hero__halo {
  display: none;
}

.pd-hero__in {
  position: relative;
  z-index: 3;
  /* 74rem y no 62rem (11-ago-2026): es el ancho de la píldora de la cabecera,
     así que la bóveda, las cifras y el botón caen dentro de las MISMAS guías
     verticales que el menú. De paso la escena 3D gana casi 200px de ancho, que
     es parte de lo que la hace más grande. */
  max-width: 74rem;
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* --- Píldora de aviso sobre el titular -------------------------------------
   RETIRADA del HTML el 10-ago-2026 al entrar la bóveda 3D: con la escena
   detrás, el titular tiene que ser lo primero que se ve. Los estilos se
   conservan porque volver a ponerla es añadir un <p>. */
.pd-hero__pill {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0 0 clamp(1.1rem, 2.5vw, 1.75rem);
  padding: 0.4rem 0.95rem;
  border-radius: var(--r-pill);
  background: oklch(0.72 0.14 91 / 0.1);
  border: 1px solid oklch(0.72 0.14 91 / 0.32);
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--brand);
}

/* Punto que late: dice "esto está vivo" con un elemento de 6px. */
.pd-hero__punto {
  width: 0.42rem;
  height: 0.42rem;
  border-radius: 50%;
  background: var(--brand);
  box-shadow: 0 0 0 0 oklch(0.76 0.15 91 / 0.7);
  animation: pd-late 2.4s ease-out infinite;
}

@keyframes pd-late {
  0% { box-shadow: 0 0 0 0 oklch(0.76 0.15 91 / 0.7); }
  70% { box-shadow: 0 0 0 0.5rem oklch(0.76 0.15 91 / 0); }
  100% { box-shadow: 0 0 0 0 oklch(0.76 0.15 91 / 0); }
}

/* --- Titular --------------------------------------------------------------
   Dos líneas: la primera blanca, la segunda en oro. En el original la segunda
   es gris; aquí es el acento de marca, que es lo que se pidió cambiar. */
.pd-hero__h1 {
  font-family: var(--font-display);
  font-size: clamp(2.6rem, 8.2vw, 6.25rem);
  font-weight: 600;
  line-height: 1.0;
  letter-spacing: -0.035em;
  margin: 0;
  color: #fff;
  text-wrap: balance;
}

.pd-hero__h1 em {
  font-style: normal;
  color: var(--brand);
  background: linear-gradient(102deg, #F1D27A 0%, #D4AF37 45%, #E7C75D 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

.pd-hero__lede {
  max-width: 36rem;
  margin: clamp(1.2rem, 2.5vw, 1.9rem) auto 0;
  font-size: clamp(1rem, 1.02rem + 0.4vw, 1.28rem);
  line-height: 1.55;
  color: oklch(0.78 0 0 );
  text-wrap: pretty;
}

.pd-hero__cta {
  display: flex;
  justify-content: center;
  margin-top: clamp(1.6rem, 3.5vw, 2.5rem);
}

/* El botón crece (pedido del dueño, 11-ago-2026). Es lo ÚNICO que se pulsa en
   la primera pantalla, así que con .btn--lg de serie se quedaba pequeño al lado
   de unas cifras de 4rem. Se toca solo aquí para no engordar los botones del
   resto de la tienda. */
.pd-hero__cta .btn {
  /* Segunda subida (11-ago-2026): al quitar la línea "Licencias desde S/ …"
     de debajo, el botón se quedó solo en ese hueco y podía ocuparlo entero.
     Lleva min-width para que sea LARGO aunque el texto sea corto: "Ver
     productos" son trece letras y sin el mínimo la cápsula salía apretada. */
  min-width: min(20rem, 100%);
  padding: 1.2rem clamp(2.5rem, 4.5vw, 3.75rem);
  font-size: clamp(1.1rem, 1rem + 0.4vw, 1.35rem);
  border-radius: var(--r-pill);
}

/* Línea de confianza bajo el botón, como el "Trusted by…" del original. El
   precio lo pone home.js con el producto más barato REAL: aquí no hay ninguna
   cifra escrita a mano que se pueda quedar vieja. */
.pd-hero__trust {
  margin: clamp(1rem, 2vw, 1.5rem) 0 0;
  font-size: 0.92rem;
  color: oklch(0.66 0 0 );
}

.pd-hero__trust b {
  font-weight: 700;
  color: oklch(0.88 0 0 );
  font-variant-numeric: tabular-nums;
}

/* --- La escena 3D, ahora una PIEZA de la pila ------------------------------
   Hasta el 11-ago-2026 el lienzo cubría el hero entero (inset:0) y hacía de
   fondo: el texto y las tarjetas le pasaban por delante. Con el orden nuevo
   —bóveda, cifras, botón, productos— la bóveda ya no es fondo de nada, así
   que se le da su propia caja con su propio alto. Es esa caja la que
   vault3d.js mide para encuadrar: cambiar este alto reencuadra la escena sola,
   sin tocar una línea de JavaScript.

   El alto sale de la ALTURA de la ventana (vh) y no del ancho: la bóveda es
   redonda y lo que la corta siempre es el alto de la pantalla. */
.pd-escena {
  position: relative;
  width: 100%;
  /* Bajó de clamp(23rem, 68vh, 42rem) el 11-ago-2026, al salir el titular de
     esta caja. Aquel alto se calculó cuando el texto iba DENTRO y superpuesto
     al lienzo: la caja tenía que dar para la bóveda y para el texto a la vez.
     Ahora el titular va debajo y suma su propio alto, así que con 68vh el hero
     se pasaba de una pantalla y las cifras y el botón se salían.
     La bóveda NO se ve más pequeña por esto: vault3d.js encuadra sobre esta
     caja y ya no reserva las 5,3 unidades que antes guardaba para el texto en
     partículas, así que ocupa mucho más de lo que le toca. */
  height: clamp(15rem, 44vh, 27rem);
  margin-bottom: clamp(0.5rem, 1.5vw, 1rem);
}

/* Nace invisible y vault3d.js le pone .is-on cuando la escena ya está armada:
   sin eso se veía un salto al aparecer el primer fotograma. Si el 3D no llega
   a arrancar, el lienzo se queda transparente y la caja queda vacía. */
.pd-gl {
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  display: block;
  pointer-events: none;
  opacity: 0;
  transition: opacity 1.1s var(--ease-out);
}

.pd-gl.is-on {
  opacity: 1;
}

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

/* --- Los productos del hero (RETIRADOS, estilos en reserva) -----------------
   11-ago-2026: el dueño los quitó de la portada. Estaban sueltos a izquierda y
   derecha, colocados uno a uno con coordenadas fijas (.pd-pieza--1…6), y en el
   móvil no cabían.
   Los estilos se quedan aquí, ya PREPARADOS para volver en fila centrada en
   vez de flotando: basta con reponer <div class="pd-flota" id="heroFlota">
   donde toque y home.js (heroFlota) los vuelve a pintar solo. */
.pd-flota {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: clamp(0.6rem, 1.4vw, 1rem);
  margin-top: clamp(2rem, 5vw, 3.25rem);
}

.pd-pieza {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  width: 12.5rem;
  padding: 0.7rem 0.85rem;
  border-radius: var(--r-lg);
  text-align: left;
  background: linear-gradient(158deg, oklch(0.25 0 0 / 0.9), oklch(0.145 0 0 / 0.9));
  border: 1px solid oklch(1 0 0 / 0.1);
  /* El filo de cristal va PRIMERO y la sombra de caída después: si se invierten,
     la sombra exterior se come la línea de luz del canto superior. */
  box-shadow: var(--pd-filo), 0 26px 50px -24px oklch(0 0 0 / 0.9);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  animation: pd-flota-sube var(--pd-dur, 7s) ease-in-out var(--pd-lag, 0s) infinite alternate;
}

.pd-pieza__ic {
  display: grid;
  place-items: center;
  width: 2.1rem;
  height: 2.1rem;
  flex: none;
  border-radius: 0.6rem;
  background: oklch(1 0 0 / 0.07);
}

.pd-pieza__ic svg {
  width: 1.3rem;
  height: 1.3rem;
}

.pd-pieza__id {
  min-width: 0;
}

/* Dos líneas como máximo: con una sola, "Adobe Creative Cloud" salía cortado
   en "Adobe Creative Clo…", que es justo el producto más caro del catálogo. */
.pd-pieza__id b {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  font-size: 0.8rem;
  font-weight: 600;
  line-height: 1.25;
  color: #fff;
}

.pd-pieza__id span {
  display: block;
  margin-top: 0.1rem;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--brand);
  font-variant-numeric: tabular-nums;
}

/* El vaivén. Cada pieza recibe su duración y su retardo desde la variable, así
   ninguna sube a la vez que su vecina y el conjunto no parece un ascensor. */
@keyframes pd-flota-sube {
  from { translate: 0 0; }
  to { translate: 0 -1.1rem; }
}

/* Seis posiciones fijas. Van en porcentajes del hero para que acompañen al
   alto real de la sección en cada pantalla. La rotación se aplica con
   `rotate:` y no con transform, porque la animación usa `translate:` — así las
   dos propiedades conviven sin pisarse. */
/* Las cuatro de arriba flanquean el titular; las dos de abajo se apoyan en las
   esquinas superiores del panel, igual que "Traffic source" y "Clients Report"
   en el original. */
/* Las seis posiciones sueltas quedan ANULADAS (11-ago-2026): ahora el orden lo
   pone el flex. Solo sobrevive lo que sigue teniendo sentido en una fila —el
   ritmo del vaivén, distinto en cada una para que no suban a la vez— y una
   inclinación mínima que evita que la fila parezca una tabla.
   Las coordenadas viejas se conservan comentadas por si el hero vuelve a la
   composición anterior:
     --1 left 4%  top 15%   --2 right 4% top 11%
     --3 left 1%  top 42%   --4 right 1% top 38%
     --5 left 2%  top 69%   --6 right 2% top 65% */
.pd-pieza--1 { rotate: -1.2deg; --pd-dur: 6.5s; --pd-lag: 0s; }
.pd-pieza--2 { rotate: 1deg;    --pd-dur: 7.8s; --pd-lag: -1.2s; }
.pd-pieza--3 { rotate: -0.8deg; --pd-dur: 8.4s; --pd-lag: -2.4s; }
.pd-pieza--4 { rotate: 1.2deg;  --pd-dur: 7.1s; --pd-lag: -0.6s; }
.pd-pieza--5 { rotate: -1deg;   --pd-dur: 9s;   --pd-lag: -3.1s; }
.pd-pieza--6 { rotate: 0.9deg;  --pd-dur: 6.9s; --pd-lag: -1.8s; }

/* El vaivén se acorta ahora que están en fila: el de 1.1rem venía de cuando
   flotaban sueltas sobre el fondo y en una fila se lee como un temblor. */
.pd-flota .pd-pieza {
  --pd-sube: 0.45rem;
}

/* En pantallas medianas y en el móvil ya NO se esconden: son contenido, no
   adorno. Solo se estrechan para que quepan tres o dos por fila. */
@media (max-width: 1280px) {
  .pd-pieza { width: 11rem; }
}

@media (max-width: 560px) {
  .pd-pieza {
    width: calc(50% - 0.3rem);
    min-width: 0;
  }
}

/* ---------------------------------------------------------------------------
   PANEL DEL CLIENTE — la pantalla grande que asoma bajo el hero
   Es la pieza de más peso de la plantilla de referencia. Está DIBUJADA con
   HTML y CSS, no es una captura: pesa unos KB, se ve nítida en cualquier
   densidad de pantalla y se puede corregir un texto sin volver a exportar
   nada. Va por encima de la esfera (z-index 4) para taparle la mitad, que es
   como está compuesto el original.
   --------------------------------------------------------------------------- */
.pd-panel {
  position: relative;
  z-index: 4;
  width: min(100%, 74rem);
  margin: clamp(2.5rem, 6vw, 5rem) auto 0;
  padding-inline: var(--gutter);
}

.pd-panel__marco {
  display: grid;
  grid-template-columns: 13.5rem minmax(0, 1fr);
  overflow: hidden;
  border-radius: clamp(0.9rem, 1.6vw, 1.4rem);
  background: oklch(0.145 0 0 );
  border: 1px solid oklch(1 0 0 / 0.1);
  /* Filo de cristal + sombra de caída. La caída es enorme y hacia abajo para
     que el panel se sienta apoyado sobre la esfera, no pegado al fondo. */
  box-shadow:
    var(--pd-filo),
    0 40px 90px -30px oklch(0 0 0 / 0.95),
    0 0 0 1px oklch(0 0 0 / 0.5);
  text-align: left;
}

/* --- Barra lateral --- */
.pd-panel__lado {
  padding: 1rem 0.8rem;
  background: oklch(0.105 0 0 );
  border-right: 1px solid oklch(1 0 0 / 0.07);
}

.pd-panel__marca {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.2rem 0.5rem 0.9rem;
  font-size: 0.86rem;
  font-weight: 700;
  color: #fff;
}

.pd-panel__marca img {
  width: 1.35rem;
  height: 1.35rem;
  object-fit: contain;
}

.pd-panel__grupo {
  margin: 0.9rem 0 0.4rem;
  padding-inline: 0.5rem;
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: oklch(0.55 0 0 );
}

.pd-panel__enlace {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.45rem 0.55rem;
  border-radius: 0.5rem;
  font-size: 0.78rem;
  color: oklch(0.76 0 0 );
}

.pd-panel__enlace svg {
  width: 0.95rem;
  height: 0.95rem;
  flex: none;
  opacity: 0.8;
}

.pd-panel__enlace b {
  margin-left: auto;
  padding: 0.05rem 0.4rem;
  border-radius: var(--r-pill);
  background: oklch(1 0 0 / 0.08);
  font-size: 0.68rem;
  font-weight: 700;
}

.pd-panel__enlace.is-on {
  background: oklch(0.72 0.14 91 / 0.14);
  color: var(--brand);
}

.pd-panel__enlace.is-on svg {
  opacity: 1;
}

/* --- Cuerpo --- */
.pd-panel__cuerpo {
  padding: 0.85rem 1rem 1.1rem;
  min-width: 0;
}

.pd-panel__top {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  padding-bottom: 0.85rem;
  border-bottom: 1px solid oklch(1 0 0 / 0.07);
}

.pd-panel__top > b {
  font-size: 0.95rem;
  color: #fff;
}

.pd-panel__buscar {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-left: auto;
  padding: 0.32rem 0.7rem;
  border-radius: var(--r-pill);
  background: oklch(1 0 0 / 0.05);
  border: 1px solid oklch(1 0 0 / 0.08);
  font-size: 0.72rem;
  color: oklch(0.6 0 0 );
}

.pd-panel__buscar svg {
  width: 0.8rem;
  height: 0.8rem;
}

.pd-panel__yo {
  display: grid;
  place-items: center;
  width: 1.7rem;
  height: 1.7rem;
  flex: none;
  border-radius: 50%;
  background: oklch(0.72 0.14 91 / 0.18);
  color: var(--brand);
  font-size: 0.66rem;
  font-weight: 700;
}

/* --- Fichas de datos --- */
.pd-panel__fichas {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0.55rem;
  margin-top: 0.85rem;
}

.pd-ficha {
  padding: 0.6rem 0.7rem;
  border-radius: 0.65rem;
  background: oklch(0.195 0 0 );
  border: 1px solid oklch(1 0 0 / 0.08);
  box-shadow: var(--pd-filo);
}

.pd-ficha span {
  display: block;
  font-size: 0.63rem;
  color: oklch(0.62 0 0 );
}

.pd-ficha b {
  display: block;
  margin-top: 0.15rem;
  font-family: var(--font-display);
  font-size: 1.35rem;
  font-weight: 600;
  line-height: 1.1;
  color: #fff;
  font-variant-numeric: tabular-nums;
}

.pd-ficha b small {
  font-size: 0.45em;
  font-weight: 700;
  margin-left: 0.1em;
  color: var(--brand);
}

.pd-ficha i {
  display: block;
  margin-top: 0.15rem;
  font-style: normal;
  font-size: 0.62rem;
  color: oklch(0.58 0 0 );
}

.es-ok { color: oklch(0.78 0.13 150) !important; }
.es-aviso { color: var(--brand) !important; }

/* --- Dos cajas de abajo --- */
.pd-panel__abajo {
  display: grid;
  grid-template-columns: minmax(0, 1.65fr) minmax(0, 1fr);
  gap: 0.55rem;
  margin-top: 0.55rem;
}

.pd-panel__caja {
  padding: 0.75rem 0.85rem 0.85rem;
  border-radius: 0.65rem;
  background: oklch(0.195 0 0 );
  border: 1px solid oklch(1 0 0 / 0.08);
  box-shadow: var(--pd-filo);
}

.pd-panel__cabeza {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  margin-bottom: 0.6rem;
}

.pd-panel__cabeza b {
  font-size: 0.8rem;
  color: #fff;
}

.pd-panel__cabeza span {
  margin-left: auto;
  font-size: 0.65rem;
  color: oklch(0.58 0 0 );
}

/* --- Lista de licencias --- */
.pd-lic {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.35rem;
}

.pd-lic li {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.42rem 0.5rem;
  border-radius: 0.5rem;
  background: oklch(0.13 0 0 );
  box-shadow: inset 0 1px 0 oklch(1 0 0 / 0.05);
}

.pd-lic__ic {
  display: grid;
  place-items: center;
  width: 1.7rem;
  height: 1.7rem;
  flex: none;
  border-radius: 0.42rem;
  background: oklch(1 0 0 / 0.07);
}

.pd-lic__ic svg {
  width: 1.05rem;
  height: 1.05rem;
}

.pd-lic__id {
  min-width: 0;
}

.pd-lic__id b {
  display: block;
  font-size: 0.75rem;
  font-weight: 600;
  color: #fff;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.pd-lic__id code {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.66rem;
  color: oklch(0.6 0 0 );
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.pd-lic__est {
  margin-left: auto;
  flex: none;
  padding: 0.16rem 0.5rem;
  border-radius: var(--r-pill);
  background: oklch(1 0 0 / 0.07);
  font-size: 0.62rem;
  font-weight: 700;
  white-space: nowrap;
}

/* --- Dona --- */
.pd-dona {
  position: relative;
  width: 7.5rem;
  margin: 0.2rem auto 0.7rem;
}

.pd-dona svg {
  width: 100%;
  display: block;
  transform: rotate(-90deg);
}

.pd-dona circle {
  fill: none;
  stroke-width: 4.2;
}

.pd-dona__base { stroke: oklch(0.28 0 0 ); }
.pd-dona__a { stroke: oklch(0.80 0.145 91); }
.pd-dona__b { stroke: oklch(0.62 0.12 91); }
.pd-dona__c { stroke: oklch(0.45 0.08 91); }

.pd-dona__centro {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  text-align: center;
  font-size: 0.6rem;
  line-height: 1.2;
  color: oklch(0.6 0 0 );
}

.pd-dona__centro b {
  display: block;
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-weight: 600;
  color: #fff;
}

.pd-leyenda {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.3rem;
}

.pd-leyenda li {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  font-size: 0.7rem;
  color: oklch(0.72 0 0 );
}

.pd-leyenda b {
  margin-left: auto;
  color: #fff;
}

.pd-leyenda i {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  flex: none;
}

.pd-leyenda__a { background: oklch(0.80 0.145 91); }
.pd-leyenda__b { background: oklch(0.62 0.12 91); }
.pd-leyenda__c { background: oklch(0.45 0.08 91); }

.pd-panel__nota {
  margin: 0.9rem 0 0;
  text-align: center;
  font-size: 0.72rem;
  color: oklch(0.52 0 0 );
}

/* En pantallas estrechas el panel se lee como una maqueta, no como una
   aplicación usable: se quita la barra lateral y las fichas bajan a dos
   columnas. Meter cinco columnas en 360px lo dejaba ilegible. */
@media (max-width: 860px) {
  .pd-panel__marco {
    grid-template-columns: minmax(0, 1fr);
  }

  .pd-panel__lado {
    display: none;
  }

  .pd-panel__fichas {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .pd-panel__abajo {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* Por debajo de ~420px la clave le comía el ancho al sello "Activada" y el
   sello salía cortado por el borde de la fila. Se esconde la clave: el nombre
   y el estado son lo que cuenta la maqueta. */
@media (max-width: 420px) {
  .pd-lic__id code {
    display: none;
  }

  .pd-lic__est {
    font-size: 0.58rem;
    padding: 0.14rem 0.42rem;
  }
}

/* --- Cinta de marcas en bucle ---------------------------------------------
   Va PEGADA al hero (mismo negro) y con los bordes desvanecidos por una
   máscara: sin ella, los logotipos aparecían y desaparecían de golpe en el
   filo. La cinta en sí (.brandstrip*) la estiliza home.css; aquí solo va el
   desvanecido de los bordes.

   11-ago-2026: SIN fondo propio y sin líneas. Antes pintaba su propio
   var(--pd-negro) y, aunque el tono coincidía, seguía siendo una caja: al
   cambiar el lienzo cualquier desajuste habría dibujado una franja. Ahora los
   logotipos pasan directamente SOBRE el cuerpo de la página, como en la
   referencia. */
.pd-cinta {
  position: relative;
  background: transparent;
  padding-block: clamp(2rem, 4.5vw, 3.4rem);
  overflow: hidden;
  /* SOLO LA COLUMNA CENTRAL (pedido del dueño, 11-ago-2026), como la
     referencia: la cinta ocupa alrededor de la mitad del ancho y va centrada,
     no de borde a borde. A pantalla completa una fila de dieciséis marcas
     cruzando los 1440px se lee como un ticker de bolsa; recogida al centro se
     lee como lo que es, la lista de lo que se vende. */
  max-width: min(56rem, 90vw);
  margin-inline: auto;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 14%, #000 86%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 14%, #000 86%, transparent);
}

.pd-cinta .brandstrip {
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
}

/* Paso LENTO (pedido del dueño). home.css la mueve en 30s, que en una fila de
   16 marcas se lee como un carrusel corriendo; a 78s el ojo alcanza a leer cada
   nombre y la cinta pasa a ser fondo en movimiento, no un elemento que compite
   con el hero. Se mantiene la pausa al pasar el cursor que ya trae la casa.
   El hueco entre marcas también crece: con los logotipos más grandes y pegados
   la fila se leía como una sola mancha larga. */
.pd-cinta .brandstrip__track {
  animation-duration: 78s;
  gap: clamp(2.2rem, 4.5vw, 4rem);
}

/* --- Marca a marca: logotipo real + nombre, todo en un gris ----------------
   Más grande y más limpia (pedido del dueño, 11-ago-2026). Dos cambios:
     · el logotipo es el OFICIAL y va monocromo (SI.brandLogo), no el azulejo
       de color; el color lo hereda del texto, así que marca y nombre son una
       sola pieza y no dieciséis pegatinas;
     · el tamaño sube de 0.92rem a ~1.5rem, que es lo que la hace legible de
       pasada — que es el único momento en que alguien la lee.
   Al pasar el cursor la marca entera se enciende en oro: el fill del trazo es
   currentColor, así que el logotipo cambia con el texto sin una regla más.

   OJO CON EL SELECTOR: aquí NO se puede colgar de .brandstrip__logos. home.css
   estiliza .brandstrip__logos .bl, pero ese contenedor solo existe en la tira
   de la home antigua; en la portada brands() escribe el carril directamente
   dentro de #brandLogos. Al copiar el selector de home.css no aplicaba NADA:
   .bl se quedaba sin display:inline-flex y, como el <svg> es de bloque, el
   logotipo caía ENCIMA del nombre en vez de a su lado. */
.pd-cinta .bl {
  display: inline-flex;
  align-items: center;
  gap: 0.8rem;
  font-size: clamp(1.15rem, 1rem + 0.55vw, 1.55rem);
  font-weight: 500;
  letter-spacing: -0.01em;
  white-space: nowrap;
  color: oklch(0.68 0 0 );
  transition: color var(--t);
}

.pd-cinta .bl svg {
  width: 1.45em;
  height: 1.45em;
  flex: none;
  opacity: 0.92;
}

.pd-cinta .bl:hover {
  color: var(--brand);
}

/* --- Tira de marcas bajo la pieza (versión compacta, se conserva por si se
   vuelve a usar en otra sección) -------------------------------------------- */
.pd-compat {
  list-style: none;
  margin: clamp(1.75rem, 4vw, 2.75rem) 0 0;
  padding: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.6rem clamp(1.1rem, 3vw, 2.4rem);
}

.pd-compat li {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-size: 0.84rem;
  font-weight: 600;
  color: oklch(0.72 0 0 );
}

.pd-compat svg {
  width: 1.15rem;
  height: 1.15rem;
  flex: none;
}

/* ---------------------------------------------------------------------------
   CIFRAS — tres datos grandes
   Sin fondo ni línea propios: el lienzo es un solo negro continuo y lo que las
   separa del resto es el aire, no un cambio de color.
   11-ago-2026: dejan de ser una franja suelta después de la cinta de marcas y
   pasan a vivir DENTRO del hero, entre la bóveda y el botón. Por eso el relleno
   baja: ahí es un escalón de la pila, no un capítulo aparte.
   --------------------------------------------------------------------------- */
.pd-cifras {
  padding-block: clamp(1.25rem, 3vw, 2.25rem);
}

/* A LOS EXTREMOS (pedido del dueño, 11-ago-2026). Antes era una rejilla de
   columnas iguales y las tres cifras salían apiñadas en el centro, debajo de la
   bóveda, compitiendo con ella. Ahora se reparten: la primera pegada al margen
   izquierdo, la última al derecho y el resto repartido en medio, alineada cada
   una con su lado. Así enmarcan la escena en vez de estorbarla.
   Es flex y no grid a propósito: la cifra de "Productos vendidos" nace oculta y
   aparece sola cuando el servidor manda un número, así que la fila tiene que
   funcionar con tres piezas o con cuatro sin reescribir las columnas. */
.pd-cifras__in {
  max-width: none;
  margin-inline: auto;
  /* Sin relleno lateral propio dentro del hero: .pd-hero__in ya lo pone y
     sumar los dos estrechaba la fila de cifras en el móvil. */
  padding-inline: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: start;
  gap: clamp(1.5rem, 4vw, 3rem);
  text-align: center;
}

.pd-cifras__in > :first-child {
  text-align: left;
}

.pd-cifras__in > :last-child {
  text-align: right;
}

/* En cuanto la fila se parte en varias líneas, repartirlas a los extremos deja
   la última suelta y descolgada: por debajo de 720px vuelven a ir centradas y
   apiladas, que es lo único que se lee bien en un móvil. */
@media (max-width: 720px) {
  .pd-cifras__in {
    justify-content: center;
  }

  .pd-cifras__in > :first-child,
  .pd-cifras__in > :last-child {
    text-align: center;
  }

  .pd-cifra {
    flex: 1 1 8rem;
  }
}

.pd-cifra b {
  display: block;
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.03em;
  font-size: clamp(2.4rem, 1.6rem + 2.6vw, 4.25rem);
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

/* El guión del rango necesita aire propio: pegado entre los dos números y
   con el letter-spacing negativo de la cifra encima, «5–30» se leeía de un
   tirón, casi como un solo número. Va en su propia etiqueta y no como
   espacios escritos a mano porque un espacio de verdad deja que el rango se
   parta en dos líneas al estrechar la pantalla. */
.pd-cifra__guion {
  margin-inline: 0.16em;
  letter-spacing: normal;
}

.pd-cifra b i {
  font-style: normal;
  font-size: 0.4em;
  font-weight: 700;
  color: var(--brand-ink);
  vertical-align: super;
  margin-left: 0.12em;
}

.pd-cifra > span {
  display: block;
  margin-top: 0.6rem;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

/* ---------------------------------------------------------------------------
   CAPÍTULOS — el ritmo de la página
   Un capítulo = una idea, un titular enorme centrado y (opcional) una pieza
   debajo. .pd-cap--navy invierte el fondo; se alternan para que la página
   avance por contraste en vez de por separadores.
   --------------------------------------------------------------------------- */
.pd-cap {
  padding-block: var(--pd-aire);
  text-align: center;
}

/* Ya no invierte el fondo (el lienzo es un solo negro): --navy se conserva
   porque de ella cuelgan los colores de texto, ceja y tarjetas del capítulo. */
.pd-cap--navy {
  color: #fff;
}

.pd-cap__in {
  max-width: 62rem;
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.pd-cap__eyebrow {
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--brand-ink);
  margin: 0 0 clamp(0.8rem, 2vw, 1.2rem);
}

.pd-cap--navy .pd-cap__eyebrow {
  color: var(--brand);
}

.pd-cap__h2 {
  font-family: var(--font-display);
  font-size: var(--pd-titular);
  font-weight: 700;
  line-height: 1.02;
  letter-spacing: -0.035em;
  margin: 0;
  color: var(--ink);
  text-wrap: balance;
}

.pd-cap--navy .pd-cap__h2 {
  color: #fff;
}

.pd-cap__h2 em {
  font-style: normal;
  color: var(--brand-ink);
}

.pd-cap--navy .pd-cap__h2 em {
  color: var(--brand);
}

.pd-cap__p {
  max-width: 36rem;
  margin: clamp(1rem, 2.5vw, 1.6rem) auto 0;
  font-size: var(--pd-lede);
  line-height: 1.55;
  color: var(--ink-body);
  text-wrap: pretty;
}

.pd-cap--navy .pd-cap__p {
  color: oklch(0.84 0 0 );
}

.pd-cap__cta {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 0.7rem 1.5rem;
  margin-top: clamp(1.4rem, 3vw, 2.2rem);
}

/* Tres piezas en fila bajo el titular del capítulo (el "bento" de Apple, en su
   versión sencilla: mismas cajas, mismo alto, sin collage). */
.pd-trio {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(16rem, 100%), 1fr));
  gap: clamp(0.85rem, 2vw, 1.35rem);
  margin-top: clamp(2rem, 5vw, 3.5rem);
  text-align: left;
}

.pd-tile {
  padding: clamp(1.25rem, 3vw, 1.8rem);
  border-radius: var(--r-xl);
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-sm);
}

.pd-cap--navy .pd-tile {
  background: oklch(0.235 0 0 );
  border-color: oklch(0.36 0 0 );
  box-shadow: none;
}

.pd-tile__ic {
  display: grid;
  place-items: center;
  width: 2.6rem;
  height: 2.6rem;
  border-radius: var(--r);
  background: var(--brand-50);
  color: var(--brand-ink);
  margin-bottom: 1rem;
}

.pd-cap--navy .pd-tile__ic {
  background: oklch(0.72 0.14 91 / 0.16);
  color: var(--brand);
}

.pd-tile__ic svg {
  width: 1.3rem;
  height: 1.3rem;
}

.pd-tile h3 {
  font-family: var(--font-display);
  font-size: 1.2rem;
  font-weight: 600;
  letter-spacing: -0.015em;
  margin: 0 0 0.45rem;
  color: var(--ink);
}

.pd-cap--navy .pd-tile h3 {
  color: #fff;
}

.pd-tile p {
  margin: 0;
  font-size: 0.95rem;
  line-height: 1.55;
  color: var(--ink-body);
}

.pd-cap--navy .pd-tile p {
  color: oklch(0.80 0 0 );
}

/* ---------------------------------------------------------------------------
   Las secciones que ya existían (vitrina, demo, pagos, soporte, reseñas, FAQ)
   se quedan como están por dentro, pero su ENCABEZADO adopta la escala de la
   portada: titular grande y centrado, con el mismo aire. Así el resto de la
   página sigue el ritmo del hero sin tener que reescribirlas.
   --------------------------------------------------------------------------- */
.pd-negro main > .section {
  padding-block: var(--pd-aire);
}

.pd-negro main > .section .sec-head {
  text-align: center;
  margin-bottom: clamp(2rem, 5vw, 3.5rem);
}

.pd-negro main > .section .sec-head__t {
  max-width: 46rem;
  margin-inline: auto;
}

.pd-negro main > .section .sec-head h2 {
  font-family: var(--font-display);
  font-size: var(--pd-titular);
  font-weight: 700;
  line-height: 1.02;
  letter-spacing: -0.035em;
  text-wrap: balance;
}

.pd-negro main > .section .sec-head > .sec-head__t > p:last-child {
  max-width: 36rem;
  margin-inline: auto;
  font-size: var(--pd-lede);
  line-height: 1.55;
}

/* La ceja de sección centrada: con justify-content la rayita queda pegada al
   texto en vez de irse al borde izquierdo del contenedor. */
.pd-negro main > .section .sec-eyebrow {
  justify-content: center;
}

/* ---------------------------------------------------------------------------
   Los dos filos que rompían la continuidad del negro: el que separa el pie del
   contenido y el que aparece bajo la cabecera al desplazar. Con un solo lienzo
   negro esas líneas se veían como costuras a lo ancho de la página.
   --------------------------------------------------------------------------- */
.pd-negro .site-footer {
  border-top: 0;
}

.pd-negro .site-header.is-stuck {
  border-bottom-color: transparent;
  box-shadow: none;
}

/* ---------------------------------------------------------------------------
   La vitrina en carrusel (.deck, commerce.css) nació para fondo claro: su
   pedestal es un degradado blanco escrito a mano y su cuadrícula son líneas
   NEGRAS. Sobre la portada en negro quedaba una caja blanca en medio de la
   página. Aquí se invierte solo para el tema oscuro; /productos sigue claro y
   no se entera.
   Las cajas de producto (.deck__box) se quedan BLANCAS a propósito: son los
   iconos de las aplicaciones, y sobre el pedestal oscuro se leen como los
   iconos de un escritorio, que es justo el efecto que se busca.
   --------------------------------------------------------------------------- */
[data-theme="dark"] .deck__stage {
  background: linear-gradient(170deg, oklch(0.205 0 0 ), oklch(0.135 0 0 ));
  border-color: oklch(0.31 0 0 );
}

[data-theme="dark"] .deck__stage::before {
  background-image:
    linear-gradient(oklch(1 0 0 / 0.05) 1px, transparent 1px),
    linear-gradient(90deg, oklch(1 0 0 / 0.05) 1px, transparent 1px);
}

/* ---------------------------------------------------------------------------
   El riel de puntos fijo a la derecha (experience.js, .xp-rail) se apaga en la
   portada: hace el mismo trabajo que la barra de producto de arriba, y como el
   contenedor de esta web llega a 1520px, en pantallas de 1440 se montaba encima
   de las cifras y de las cejas de sección.
   --------------------------------------------------------------------------- */
.pd-negro .xp-rail {
  display: none;
}

/* --- Tambor de cifras (slot machine, home.js statOdometer) -------------------
   Cada dígito es una ventanita de 1em con una columna 0-9 que gira (transform)
   y cae en su valor. Los signos (+, –, espacio) van en la misma caja de 1em
   para que toda la cifra alinee pareja.
   Vivía en hero3d.css; se trajo aquí el 10-ago-2026 al quitar la constelación,
   porque era lo ÚNICO de aquel archivo que la portada seguía necesitando. */
.odo {
  display: inline-block;
  overflow: hidden;
  height: 1em;
  line-height: 1;
  white-space: pre;
}

.odo__reel {
  display: block;
  transition: transform 1s cubic-bezier(0.16, 0.9, 0.24, 1);
  will-change: transform;
}

.odo__reel > span {
  display: block;
  height: 1em;
  line-height: 1;
}

/* Giro terminado (la clase la pone odoRoll en home.js): en la ventanilla solo
   queda el dígito final. Así no puede asomar el borde del dígito de al lado —
   el alto de cada casilla se redondea a píxeles del aparato y en pantallas de
   mucha densidad se colaba un hilo del número vecino por encima. De paso suelta
   la capa de composición (will-change) que ya no hace falta. */
.odo.is-set .odo__reel {
  will-change: auto;
}

.odo.is-set .odo__reel > span {
  visibility: hidden;
}

.odo.is-set .odo__reel > span:last-child {
  visibility: visible;
}

/* ---------------------------------------------------------------------------
   Movimiento reducido: la portada no anima nada. Las transiciones de color se
   quedan (no son movimiento), pero los desplazamientos desaparecen.
   --------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {

  .pd-link,
  .pd-bar__buy {
    transition: none;
  }

  .pd-link:hover {
    gap: 0.3rem;
  }

  .pd-bar__buy:hover {
    transform: none;
  }
}

/* =============================================================================
   PASADA "SIN FONDOS" — 11-ago-2026
   Encargo del dueño, literal: «deja todo transparente», «quita los fondos»,
   «que sea más minimalista, elegante, que vaya con el aspecto de la página».

   La portada nació con las cajas del resto de la tienda: tarjetas con relleno,
   paneles con borde, franjas de color alterno. Sobre negro puro eso son
   rectángulos grises flotando, y cada uno le resta a lo único que tiene que
   brillar, que es el oro. Aquí se apagan TODOS esos fondos y lo que separa una
   cosa de otra pasa a ser el aire y, como mucho, una línea de un píxel.

   Todo va colgado de .pd-negro: el catálogo, la ficha de producto y
   el panel conservan sus cajas, que ahí sí hacen falta.
   ============================================================================= */

/* --- Titulares en letra NORMAL ---------------------------------------------
   11-ago-2026, segunda vuelta. Se probó el degradado de blanco a plomo con
   background-clip:text buscando el efecto de letra grabada en metal, y el
   dueño lo rechazó: «que se vean como letras normales».
   Tenía razón y además había un motivo técnico para no insistir — con el texto
   recortado sobre un fondo, el navegador deja de aplicarle el suavizado normal
   de subpíxel y los trazos finos salen sucios, que es justo lo que se veía.
   Los titulares vuelven a color sólido; el <em> conserva su oro. */
.pd-negro .sec-head h2,
.pd-negro .pd-cap__h2,
.pd-negro .s-productos h2:not(.pd-rotu__tab) {
  background: none;
  -webkit-background-clip: border-box;
  background-clip: border-box;
  -webkit-text-fill-color: currentColor;
  color: var(--ink);
}

.pd-negro .sec-head h2 em,
.pd-negro .pd-cap__h2 em,
.pd-negro .pd-cifra b i {
  -webkit-text-fill-color: var(--brand);
  color: var(--brand);
}

/* =============================================================================
   TITULARES CON LUSTRE (11-ago-2026)

   El dueño pidió «efecto glossy con sombreado» en el titular del hero y en los
   titulares de sección.

   NO SE USA background-clip:text, Y ESTA VEZ ESTÁ MEDIDO
   El bloque de arriba ya contaba que el degradado recortado se descartó porque
   «los trazos finos salen sucios». Aquí se intentó rescatarlo con el argumento
   de que la razón técnica había caducado: como `body.pd-negro` ya fuerza
   `-webkit-font-smoothing: antialiased` en toda la portada, no quedaría
   suavizado de subpíxel que perder.
   El argumento era FALSO, y se comprobó contando píxeles sobre la web ya
   publicada, apagando una declaración cada vez:

     titular en blanco sólido ......... 8.807 px de trazo pleno
     titular con degradado recortado .... 325 px  ← 27 veces menos
     quitando solo el filter ............ 324 px  (no era la sombra)

   O sea: el recorte adelgaza los glifos hasta dejarlos casi todo borde. Da
   igual el suavizado que tenga la página. La decisión original era correcta.

   EL BRILLO SE CONSIGUE CON SOMBRAS, NO CON DEGRADADO
   El relleno se queda blanco y sólido —trazo pleno, 252 de luminosidad— y todo
   el volumen lo ponen cuatro capas de `text-shadow`. Se ve glossy porque la
   letra tiene canto, peso y un halo cálido detrás, no porque esté pintada con
   un degradado.
   Y al haber relleno, `text-shadow` funciona con normalidad: no hace falta
   `filter: drop-shadow`, que solo era necesario para el texto transparente.
   --------------------------------------------------------------------------- */
/* El :not(.pd-rotu__tab) es del 13-ago-2026, cuando las pestañas de fila
   ("PRODUCTOS DESTACADOS", "MÁS LICENCIAS") pasaron de <h3> a <h2> para que el
   árbol de encabezados coincidiera con lo que se ve. Al hacerlo entraron en
   este selector y heredaron las cuatro sombras del titular: la pestaña dejaba
   de leerse como pieza de interfaz y competía con el <h1> del hero. El lustre
   es para los TITULARES, no para las etiquetas. */
.pd-negro .pd-rotulo,
.pd-negro .sec-head h2,
.pd-negro .pd-cap__h2,
.pd-negro .s-productos h2:not(.pd-rotu__tab) {
  /* RELLENO SÓLIDO Y BLANCO. Es lo único que garantiza el trazo entero. */
  color: #fff;
  -webkit-text-fill-color: #fff;
  /* Las cuatro sombras, de más cerca a más lejos. Cada una hace un trabajo y
     quitando cualquiera se nota:
       0 1px  → el canto de contacto: despega la letra del fondo
       0 2px  → un desenfoque corto que le da grosor al canto
       0 10px → la sombra proyectada, la que da peso y volumen
       0 0 34 → el halo de oro. Este es el que hace que se lea «glossy» y no
                solo «con sombra»: la letra parece iluminada por el mismo oro
                de la bóveda en vez de ser un blanco de oficina. */
  text-shadow:
    0 1px 0 oklch(0 0 0 / 0.62),
    0 2px 3px oklch(0 0 0 / 0.55),
    0 10px 24px oklch(0 0 0 / 0.70),
    0 0 34px oklch(0.72 0.17 91 / 0.30);
}

/* El <em> dorado conserva su oro: es el acento de la marca y no lleva el blanco
   del titular. La sombra sí la hereda, que es lo que se quiere. */
.pd-negro .sec-head h2 em,
.pd-negro .pd-cap__h2 em {
  color: var(--brand);
  -webkit-text-fill-color: var(--brand);
}

/* La bajada del hero: mismo lenguaje, la mitad de intensidad. A ese cuerpo una
   sombra tan marcada como la del titular la emborrona en vez de despegarla. */
.pd-negro .pd-rotulo span {
  color: oklch(0.86 0.008 265);
  -webkit-text-fill-color: oklch(0.86 0.008 265);
  text-shadow:
    0 1px 0 oklch(0 0 0 / 0.55),
    0 6px 16px oklch(0 0 0 / 0.6),
    0 0 22px oklch(0.72 0.17 91 / 0.16);
}

/* --- Fuera los fondos de sección ------------------------------------------- */
.pd-negro .section--alt,
.pd-negro .pd-cap--navy,
.pd-negro .pd-cap {
  background: transparent;
  border: 0;
}

/* --- Garantía: sin azulejos y sin iconos ------------------------------------
   Las tres promesas iban en tarjetas con relleno y cada una con su icono en un
   cuadradito. El dueño las quiere «como una experiencia»: ahora son tres
   columnas de texto separadas por una línea fina, sin caja y sin icono. Lo que
   las ordena es el espacio, no el marco. */
.pd-negro .pd-tile,
.pd-negro .pd-cap--navy .pd-tile {
  background: transparent;
  border: 0;
  box-shadow: none;
  padding-inline: 0;
}

.pd-negro .pd-tile__ic {
  display: none;
}

.pd-negro .pd-trio {
  gap: clamp(2rem, 5vw, 4rem);
}

/* La línea que separa columna de columna. Solo entre ellas —de ahí el :not
   sobre la primera— y solo cuando hay sitio de sobra: apiladas en el móvil una
   raya vertical no separa nada. */
@media (min-width: 860px) {
  .pd-negro .pd-trio > * + * {
    border-left: 1px solid oklch(1 0 0 / 0.07);
    padding-left: clamp(2rem, 4vw, 3.5rem);
  }
}

/* --- Cómo funciona y Cómo pagar: paneles sin relleno ------------------------
   Se conserva el CANTO (una línea al 8% de blanco) porque estas dos piezas son
   una pantalla simulada y una tarjeta de pago: sin ningún límite se
   desparramaban sobre el negro y dejaban de leerse como objetos. Lo que se va
   es el relleno gris, no la forma. */
.pd-negro .demo__stage,
.pd-negro .demo__app,
.pd-negro .demo__chrome,
.pd-negro .paypanel,
.pd-negro .paysec .card {
  background: transparent;
  box-shadow: none;
}

.pd-negro .demo__app,
.pd-negro .paypanel {
  border: 1px solid oklch(1 0 0 / 0.08);
  /* SIN backdrop-filter (11-ago-2026). Lo puse para dar sensación de cristal y
     era la causa de que el texto de estos dos paneles se viera BORROSO: un
     elemento con backdrop-filter se sube a una capa compuesta y su texto deja
     de dibujarse con suavizado de subpíxel. Encima aquí no pintaba nada —
     desenfocar un fondo negro liso no produce ningún efecto. */
}

.pd-negro .demo__chrome {
  border-bottom: 1px solid oklch(1 0 0 / 0.07);
}

/* --- Filtros de producto: pestañas, no botones ------------------------------
   «Todos los productos» y las categorías. En reposo son solo texto con un canto
   finísimo; la activa se rellena con un blanco al 8% en vez de con el oro: el
   oro está reservado para lo que se COMPRA (el botón, los precios), y gastarlo
   en un filtro le quita fuerza justo donde hace falta. */
.pd-filtros {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.5rem;
  /* 12-ago-2026: de clamp(2rem,4vw,3rem) a la mitad. Antes los filtros eran lo
     primero de la sección y ese aire los separaba del titular; ahora van entre
     la pestaña «Más licencias» y su rejilla, y con el margen viejo la pestaña
     parecía titular de los filtros en vez de los productos. */
  margin-bottom: clamp(1rem, 2vw, 1.5rem);
}

.pd-filtro {
  appearance: none;
  cursor: pointer;
  padding: 0.6rem 1.15rem;
  border-radius: var(--r-pill);
  border: 1px solid oklch(1 0 0 / 0.1);
  background: transparent;
  color: oklch(0.7 0 0 );
  font: inherit;
  font-size: 0.9rem;
  font-weight: 600;
  letter-spacing: -0.005em;
  transition: color var(--t), background-color var(--t), border-color var(--t);
}

.pd-filtro:hover {
  color: #fff;
  border-color: oklch(1 0 0 / 0.22);
}

.pd-filtro.is-on {
  background: oklch(1 0 0 / 0.08);
  border-color: oklch(1 0 0 / 0.26);
  color: #fff;
  box-shadow: inset 0 1px 0 oklch(1 0 0 / 0.22);
}

/* La rejilla usa la tarjeta del catálogo (SI.productCard) y, como el resto de
   la portada, sin relleno: solo el canto. */
.pd-negro .pd-rejilla .pcard,
.pd-negro .pd-rejilla .card {
  background: transparent;
  box-shadow: none;
  border: 1px solid oklch(1 0 0 / 0.08);
}

/* --- Tarjeta MÍNIMA de producto (portada) — YA NO SE USA ---------------------
   12-ago-2026: la rejilla pasó a .pd-item (ver «LA VITRINA ESTILO TIENDA DE
   JUEGO», más abajo). Esta se queda por si se quiere volver a la versión
   sobria: es la misma información, sin cabecera de color ni placa de precio.
   tarjetaMini() sigue en home.js, también sin llamar.

   11-ago-2026. Antes la rejilla usaba la tarjeta del catálogo: imagen, clave
   enmascarada, tres etiquetas y dos botones. Sobre negro y en rejilla eran
   ladrillos enormes y la sección se caía. Aquí manda lo contrario: cajas
   PEQUEÑAS, sin fondo, con el mismo canto al 8% de blanco que los filtros —
   logotipo, nombre y precio, nada más. Lo que hace falta para decidir si
   entras; el resto está en la ficha, a un clic. */
.pd-mini {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.55rem;
  padding: 1rem 1rem 1.1rem;
  border-radius: var(--r-lg);
  border: 1px solid oklch(1 0 0 / 0.08);
  background: transparent;
  text-decoration: none;
  transition: border-color var(--t), background-color var(--t), transform var(--t);
}

.pd-mini:hover {
  border-color: oklch(1 0 0 / 0.2);
  background: oklch(1 0 0 / 0.03);
  transform: translateY(-2px);
}

.pd-mini__ic {
  display: block;
  line-height: 0;
}

.pd-mini__t {
  /* Dos líneas como tope: "Adobe Creative Cloud" no cabe en una y cortado a
     "Adobe Creative Clo…" es justo el producto más caro del catálogo. */
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  font-size: 0.86rem;
  font-weight: 600;
  line-height: 1.3;
  color: oklch(0.92 0 0 );
}

.pd-mini__p {
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--brand);
  font-variant-numeric: tabular-nums;
}

/* =============================================================================
   LA VITRINA ESTILO TIENDA DE JUEGO — 12-ago-2026

   El dueño mandó una captura de la tienda de Rocket League: «toma este
   concepto, pero adáptalo al estilo que estamos manejando». Lo que se copia es
   el ARMAZÓN, no la paleta:

     · pestaña en diagonal como título de fila, con un riel que se pierde a la
       derecha y un dato al final;
     · dos banners anchos de destacados, con el dibujo a la izquierda y el
       nombre grande alineado a la derecha;
     · rejilla de tarjetas debajo, cada una con su cabecera, su dibujo y el
       precio en una placa con la esquina cortada.

   LO QUE NO SE COPIA, Y POR QUÉ:

   · Los colores. La referencia es azul cian con degradados saturados en cada
     tarjeta. Aquí el lienzo es negro y el único acento es el oro, así que el
     color lo ponen los propios logotipos de marca (Windows azul, Photoshop
     azul oscuro, Illustrator naranja…), que ya vienen con su fondo desde
     SI.brandGlyph. Es exactamente el mismo efecto que en la referencia —una
     rejilla que se ve variada— sin inventar una paleta nueva.

   · La cuenta atrás. En Rocket League el reloj es real: la tienda rota. Aquí
     no rota nada, así que un contador sería urgencia falsa —llegaría a cero y
     no pasaría nada—. En su sitio va un dato cierto (la entrega, y cuántas
     licencias se están viendo).

   · Las etiquetas de rareza de colores (CRIMSON, PINK…). Su equivalente honesto
     aquí es el TIPO de licencia, que ya está en los datos (`tag`: «Licencia
     permanente», «12 meses»), y va en la cápsula de contorno dorada que usa el
     resto de la portada.
   ============================================================================= */

/* --- La pestaña de cada fila --- */
.pd-rotu {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  margin: clamp(1.75rem, 3.5vw, 3rem) 0 clamp(0.9rem, 1.8vw, 1.4rem);
}

/* El corte en diagonal lo hace clip-path sobre el relleno; el canto dorado de
   la izquierda va con border-left porque un borde SÍ se recorta con la forma y
   así el bisel queda limpio en la punta. */
.pd-rotu__tab {
  margin: 0;
  padding: 0.48rem 2.3rem 0.48rem 1rem;
  clip-path: polygon(0 0, 100% 0, calc(100% - 1.25rem) 100%, 0 100%);
  background: linear-gradient(90deg,
    oklch(0.72 0.17 91 / 0.22),
    oklch(0.72 0.17 91 / 0.02));
  border-left: 2px solid var(--brand);
  font-family: var(--font-display);
  font-size: clamp(0.92rem, 1.5vw, 1.2rem);
  font-weight: 700;
  letter-spacing: 0.13em;
  line-height: 1.2;
  text-transform: uppercase;
  color: #fff;
  white-space: nowrap;
}

/* El riel que se desvanece: es lo que hace que la pestaña se lea como una
   pieza de interfaz y no como un titular suelto. */
.pd-rotu__riel {
  flex: 1 1 auto;
  min-width: 1rem;
  height: 1px;
  background: linear-gradient(90deg, oklch(1 0 0 / 0.16), oklch(1 0 0 / 0));
}

.pd-rotu__meta {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  flex: none;
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--brand);
  white-space: nowrap;
}

.pd-rotu__meta svg {
  width: 1rem;
  height: 1rem;
}

/* ============ ESTE RÓTULO DESCUADRABA TODA LA WEB EN EL MÓVIL ==============
   13-ago-2026. El dueño lo vio en su iPhone: «todo está puesto a la izquierda».
   Tenía razón y la causa estaba aquí, en tres líneas de esta misma hoja.

   La pestaña y el contador llevan los dos `white-space: nowrap`, y el contador
   además `flex: none`. Ninguno de los dos podía encoger. Medido en una pantalla
   de 390 px, dentro de una caja de 350:

       pestaña 291 + hueco 14 + riel 16 + hueco 14 + contador 183  =  518 px

   Se salía 168 px por la derecha. Y como la fila arranca 16 px a la izquierda
   —el desplazamiento con el que entra su animación—, el documento acababa
   midiendo 502 px de ancho.

   AHÍ ESTÁ EL DAÑO, Y NO ES UN DETALLE. La página se maqueta a 390 px pero el
   documento mide 502: todo el contenido queda pegado al borde izquierdo de un
   lienzo más ancho que la pantalla, con una franja muerta de 112 px a la
   derecha. No se descuadró un rótulo: se descuadró la web entera, en todas las
   secciones y en el pie. Por eso «se ve todo corrido».

   En pantalla estrecha el rótulo se parte en dos líneas y el riel desaparece:
   ese riel es un adorno que solo tiene sentido cuando sobra ancho, que es justo
   lo que aquí no pasa. */
@media (max-width: 560px) {
  .pd-rotu {
    flex-wrap: wrap;
    gap: 0.5rem 0.7rem;
  }

  .pd-rotu__tab {
    /* `min-width: 0` es obligatorio: sin él, un hijo de flex con nowrap se
       niega a bajar de su ancho natural por muy pequeña que sea la caja. */
    min-width: 0;
    max-width: 100%;
    font-size: 0.86rem;
    padding-right: 1.9rem;
  }

  .pd-rotu__riel { display: none; }

  .pd-rotu__meta {
    font-size: 0.7rem;
    flex: 0 0 auto;
  }
}

/* --- Los dos banners de destacados --- */
.pd-banners {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(0.7rem, 1.4vw, 1.1rem);
}

/* Uno debajo del otro en pantalla estrecha: a dos columnas, el nombre grande
   alineado a la derecha se parte en cuatro líneas y deja de leerse. */
@media (max-width: 760px) {
  .pd-banners { grid-template-columns: 1fr; }
}

/* --- LA CAJA DE IMAGEN (12-ago-2026) ----------------------------------------
   Pedido del dueño: «las cajas se ven vacías, que la foto ocupe todo», con la
   ficha de «Silo» de Apple TV delante: imagen a sangre y el texto DEBAJO, fuera
   del recuadro.

   La caja tiene proporción FIJA (16:9 en el banner, 1:1 en la tarjeta) con
   aspect-ratio, no con un alto en píxeles. Es lo que permite pedir las imágenes
   a una medida concreta y que encajen a cualquier ancho de pantalla sin recortes
   distintos en cada tamaño.

   Dentro conviven tres capas:
     1. el glifo de marca, centrado — respaldo permanente;
     2. la portada, en absoluto y cubriendo la caja entera;
     3. la etiqueta de tipo y la placa del precio, encima de todo.
   Si la portada no existe o falla, se ve el glifo y la tarjeta sigue entera.
   --------------------------------------------------------------------------- */
.pd-banner,
.pd-item {
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  text-decoration: none;
  transition: transform var(--t);
}

.pd-banner:hover,
.pd-item:hover {
  transform: translateY(-3px);
}

.pd-banner__caja,
.pd-item__caja {
  position: relative;
  display: block;
  overflow: hidden;
  border-radius: var(--r-lg);
  border: 1px solid oklch(1 0 0 / 0.1);
  /* El degradado solo se ve cuando NO hay portada: con imagen queda tapado.
     Existe para que la caja de respaldo no sea un rectángulo negro liso. */
  background:
    radial-gradient(70% 70% at 50% 45%, oklch(0.72 0.17 91 / 0.16), transparent 70%),
    linear-gradient(160deg, oklch(0.24 0 0 / 0.55), oklch(0 0 0 / 0));
  transition: border-color var(--t);
}

/* 3:2 EN EL BANNER, NO 16:9, Y LA RAZÓN NO ES ESTÉTICA.
   El dueño genera las portadas con ChatGPT, y ese generador solo entrega tres
   medidas: 1024×1024 (1:1), 1536×1024 (3:2) y 1024×1536 (2:3). No hay 16:9.
   Con la caja en 16:9 habría que recortar a mano cada imagen antes de subirla
   —un paso más, en una herramienta más, cada vez—. Con 3:2 lo que sale del
   generador entra tal cual.
   1:1 en la tarjeta por lo mismo: es la medida cuadrada nativa. */
.pd-banner__caja { aspect-ratio: 3 / 2; }
.pd-item__caja { aspect-ratio: 1 / 1; }

.pd-banner:hover .pd-banner__caja,
.pd-item:hover .pd-item__caja {
  border-color: oklch(0.72 0.17 91 / 0.45);
}

/* El glifo, centrado y por debajo de todo. */
.pd-banner__glifo,
.pd-item__glifo {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
}

/* La portada, cubriendo la caja. object-position al centro: las imágenes que
   se piden vienen con el motivo centrado, así que al recortar por los lados en
   pantallas estrechas nunca se pierde el sujeto. */
.pd-banner__img,
.pd-item__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

/* MODO RESPALDO: cuando no hay portada propia, la imagen es el render 3D del
   logotipo, que es CUADRADO (512×512). Recortarlo a 16:9 le comía un tercio por
   arriba y por abajo —el logo de Windows salía partido—, así que aquí se
   `contain` y se deja aire alrededor para que el degradado de la caja respire.
   En cuanto el producto tenga su portada propia, esta clase desaparece del
   marcado y vuelve el `cover` a sangre. */
.pd-banner__caja.es-logo .pd-banner__img,
.pd-item__caja.es-logo .pd-item__img {
  object-fit: contain;
}

.pd-banner__caja.es-logo .pd-banner__img { padding: 8%; }
.pd-item__caja.es-logo .pd-item__img { padding: 14%; }

/* Con imagen de respaldo el glifo sobra: se verían el logotipo 3D y el azulejo
   pequeño a la vez, uno encima del otro. El glifo solo tiene sentido cuando NO
   hay ninguna imagen, y entonces esta regla no encuentra ningún <img>. */
.pd-banner__caja:has(.pd-banner__img) .pd-banner__glifo,
.pd-item__caja:has(.pd-item__img) .pd-item__glifo {
  display: none;
}

/* La etiqueta de tipo, arriba a la izquierda y SOBRE la imagen: por eso lleva
   fondo propio y desenfoque, para leerse encima de cualquier portada. */
.pd-banner__tag,
.pd-item__tag {
  position: absolute;
  top: 0.55rem;
  left: 0.55rem;
  z-index: 2;
  padding: 0.14rem 0.55rem;
  border-radius: var(--r-pill);
  border: 1px solid oklch(0.72 0.17 91 / 0.45);
  background: oklch(0 0 0 / 0.55);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  font-size: 0.66rem;
  font-weight: 700;
  color: var(--brand);
}

.pd-item__tag {
  font-size: 0.6rem;
  padding: 0.1rem 0.45rem;
}

/* ===================== AGOTADO: SE VE, PERO SE VE APAGADO — 13-ago-2026 =====
   Pedido del dueño: «déjalos en la página para rellenar, pero como si
   estuvieran apagados, como si no hubiera stock y no se pudiera pagar».

   Tres señales a la vez, y las tres hacen falta:
     1 · el color se va      (grayscale) — se lee de un vistazo, sin leer nada
     2 · baja la intensidad  (opacity)   — pasa a segundo plano frente al resto
     3 · lo dice con letras  (el sello)  — el color solo no basta: quien no
         distingue bien los colores vería una tarjeta normal, un poco tenue.

   El precio SE QUEDA, pero en gris. Saber cuánto costará cuando vuelva es
   información útil; dejarlo en oro, al lado de los comprables, sería el único
   detalle que de verdad podría confundir.

   Y se apaga el levantar al pasar el ratón: ese gesto es una invitación, y aquí
   no hay a qué invitar. El enlace SIGUE funcionando —lleva a la ficha, donde ya
   se explica que no hay stock y el botón de pagar no existe—; lo que no hace es
   fingir que sí. */
/* OJO CON DÓNDE VA LA OPACIDAD. Lo natural sería atenuar la tarjeta entera
   (`.es-agotado { opacity: .62 }`), pero el sello vive DENTRO y se atenuaría con
   ella: quedaría medio borrado justo lo que hay que leer. Así que se apaga pieza
   por pieza —la imagen y el texto— y el sello se queda a plena intensidad. */
.pd-banner.es-agotado:hover,
.pd-item.es-agotado:hover {
  transform: none;
}

.pd-banner.es-agotado .pd-banner__img,
.pd-item.es-agotado .pd-item__img,
.pd-banner.es-agotado .pd-banner__glifo,
.pd-item.es-agotado .pd-item__glifo {
  filter: grayscale(0.95);
  opacity: 0.45;
}

.pd-banner.es-agotado .pd-banner__info,
.pd-item.es-agotado .pd-item__info {
  opacity: 0.6;
}

.pd-banner.es-agotado .pd-banner__tag,
.pd-item.es-agotado .pd-item__tag {
  opacity: 0.5;
}

.pd-banner.es-agotado:hover .pd-banner__caja,
.pd-item.es-agotado:hover .pd-item__caja {
  border-color: oklch(1 0 0 / 0.14);
}

/* El precio, en gris y sin el filo dorado de la placa. */
.pd-banner.es-agotado .pd-banner__p,
.pd-item.es-agotado .pd-item__p {
  color: var(--ink-muted);
  border-top-color: oklch(1 0 0 / 0.2);
}

/* El sello. Arriba a la DERECHA: la izquierda ya es de __tag. */
.pd-banner__seco,
.pd-item__seco {
  position: absolute;
  top: 0.55rem;
  right: 0.55rem;
  z-index: 3;
  padding: 0.14rem 0.55rem;
  border-radius: var(--r-pill);
  border: 1px solid oklch(1 0 0 / 0.28);
  background: oklch(0 0 0 / 0.72);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  /* En blanco pleno: el sello es lo ÚNICO que tiene que leerse bien de una
     tarjeta apagada, así que no se le baja el contraste con el resto. */
  color: oklch(1 0 0 / 0.92);
}

.pd-item__seco {
  font-size: 0.58rem;
  padding: 0.1rem 0.45rem;
}

/* La placa del precio: pegada a la esquina de la IMAGEN, con el canto izquierdo
   cortado en diagonal. Es la pieza que más «tienda de juego» hace del bloque, y
   la única que se conserva de la referencia de Rocket League ahora que el texto
   se fue fuera de la caja. Opaca a propósito: encima de una foto, un fondo
   translúcido deja el precio ilegible según la imagen que toque. */
.pd-banner__p,
.pd-item__p {
  position: absolute;
  right: 0;
  bottom: 0;
  z-index: 2;
  padding: 0.32rem 0.8rem 0.32rem 1.2rem;
  clip-path: polygon(0.8rem 0, 100% 0, 100% 100%, 0 100%);
  background: oklch(0.16 0.03 91 / 0.92);
  border-top: 1px solid oklch(0.72 0.17 91 / 0.45);
  font-weight: 700;
  color: var(--brand);
  font-variant-numeric: tabular-nums;
}

.pd-banner__p { font-size: clamp(0.88rem, 1.3vw, 1.05rem); }
.pd-item__p { font-size: 0.82rem; }

/* --- La información, FUERA de la caja --- */
.pd-banner__info,
.pd-item__info {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  padding-inline: 0.15rem;
  min-width: 0;
}

.pd-banner__n {
  font-family: var(--font-display);
  font-size: clamp(1.05rem, 1.9vw, 1.45rem);
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.02em;
  color: #fff;
}

/* La categoría, en versalitas separadas: es el «IMPORT ANIMATED DECAL» de la
   referencia, el renglón que dice QUÉ TIPO de cosa es. Una sola línea. */
.pd-banner__c,
.pd-item__c {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: oklch(0.66 0.012 265);
}

.pd-banner__c { font-size: clamp(0.6rem, 0.85vw, 0.7rem); }
.pd-item__c { font-size: 0.56rem; }

/* --- La rejilla del resto --- */
/* display:grid EXPLÍCITO. Esto lo traía .catalog-grid, que vive en catalog.css
   y la portada NO carga ese archivo: sin esta línea las tarjetas se apilaban a
   todo el ancho (1329px cada una). La clase se quitó del HTML el 12-ago-2026
   —estas tarjetas ya no son las del catálogo—, así que la línea es ahora la
   única que sostiene la rejilla. */
/* COLUMNAS FIJAS POR TRAMO, no auto-fill. Con auto-fill el navegador mete las
   que quepan —a 1440px salían 7— y las 6 tarjetas dejaban una huérfana sola en
   una segunda fila. Contando las columnas a mano, 6 productos caben SIEMPRE en
   filas completas: 6/6, 6/3 y 6/2. Es la misma cuenta que hace la referencia,
   que enseña justo seis y ni una más. */
.pd-negro .pd-rejilla {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(0.55rem, 1.1vw, 0.85rem);
}

@media (min-width: 700px) {
  .pd-negro .pd-rejilla { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (min-width: 1100px) {
  .pd-negro .pd-rejilla { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}

/* El nombre del producto, debajo de la caja. Dos líneas como tope: "Adobe
   Creative Cloud" no cabe en una, y cortado a "Adobe Creative Clo…" es justo el
   producto más caro del catálogo.
   El min-height reserva las DOS líneas aunque el nombre ocupe una: sin él, la
   tarjeta de "Canva Pro" quedaba más baja que la de al lado y la fila se veía
   desalineada por abajo. */
.pd-item__n {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  min-height: 2.5em;
  font-size: 0.82rem;
  font-weight: 700;
  line-height: 1.25;
  color: #fff;
}

/* (.pd-item__head y .pd-item__art se retiraron el 12-ago-2026: la cabecera de
   relleno y el hueco del dibujo desaparecieron cuando la imagen pasó a ocupar
   toda la caja y el texto se fue debajo. Ver «LA CAJA DE IMAGEN» más arriba.) */

/* --- El producto que sale al abrir la bóveda --------------------------------
   Vive DENTRO de la caja de la escena, pegado a la derecha: la puerta se abre
   hacia la izquierda (bisagra en su canto derecho, en vault3d.js) y deja libre
   ese lado. Nace oculto y entra deslizándose. */
.pd-vitrina {
  position: absolute;
  z-index: 4;
  right: 0;
  /* Centrada otra vez (11-ago-2026). El 34% compensaba que la bóveda vivía en
     la mitad de ARRIBA del lienzo, con el titular en partículas ocupando la de
     abajo. Desde que la bóveda está centrada en su caja, ese 34% dejaba la
     ficha del precio flotando por encima de la puerta. */
  top: 50%;
  width: min(20rem, 46%);
  translate: 0 -50%;
  padding: 1.35rem 1.4rem 1.2rem;
  text-align: left;
  border-radius: var(--r-lg);
  border: 1px solid oklch(1 0 0 / 0.1);
  background: oklch(0 0 0 / 0.55);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  box-shadow: inset 0 1px 0 oklch(1 0 0 / 0.16);
  opacity: 0;
  transform: translateX(1.5rem);
  transition: opacity 0.45s var(--ease-out), transform 0.45s var(--ease-out);
}

.pd-vitrina.is-on {
  opacity: 1;
  transform: translateX(0);
}

/* La imagen real del producto dentro de la ficha (13-ago-2026). Mismo tamaño y
   mismo redondeo que tenía el glifo al que sustituye: así la composición de la
   ficha no cambia según el producto traiga foto o no. `object-fit: cover` por
   si alguna imagen subida desde el panel no viene cuadrada — se recorta, no se
   deforma. */
.pd-vitrina__ic img {
  display: block;
  width: 46px;
  height: 46px;
  border-radius: 12px;
  object-fit: cover;
}

.pd-vitrina h3 {
  margin: 0.65rem 0 0.4rem;
  font-size: 1.08rem;
  font-weight: 700;
  color: #fff;
}

.pd-vitrina p {
  margin: 0;
  font-size: 0.86rem;
  line-height: 1.5;
  color: oklch(0.72 0 0 );
}

.pd-vitrina__pie {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-top: 1rem;
}

.pd-vitrina__pie b {
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--brand);
  font-variant-numeric: tabular-nums;
}

.pd-vitrina__cuenta {
  display: block;
  margin-top: 0.8rem;
  font-size: 0.7rem;
  letter-spacing: 0.06em;
  color: oklch(0.58 0 0 );
}

.pd-vitrina__x {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  display: grid;
  place-items: center;
  width: 1.9rem;
  height: 1.9rem;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: oklch(0.62 0 0 );
  cursor: pointer;
  transition: color var(--t), background-color var(--t);
}

.pd-vitrina__x:hover {
  color: #fff;
  background: oklch(1 0 0 / 0.08);
}

/* En el móvil la puerta ocupa casi todo el ancho y no queda hueco a un lado:
   el producto pasa a la parte de abajo, a todo lo ancho. */
@media (max-width: 760px) {
  .pd-vitrina {
    right: 0;
    left: 0;
    top: auto;
    bottom: 0;
    width: auto;
    translate: 0 0;
    transform: translateY(1.5rem);
  }

  .pd-vitrina.is-on {
    transform: translateY(0);
  }
}

/* --- UN SOLO BOTÓN EN TODA LA PORTADA ---------------------------------------
   11-ago-2026, decisión del dueño: todos los botones con el mismo aspecto que
   las pastillas de filtro de Productos —cápsula transparente, canto de un
   píxel, texto blanco—. El oro deja de usarse en botones y queda SOLO en los
   precios, que es donde ya estaba funcionando.

   Antes había dos familias mezcladas (oro sólido para lo principal, contorno
   para lo secundario) y sobre negro puro los rectángulos dorados eran lo
   único que se veía de la página.

   QUEDAN FUERA a propósito el carrito y el modal de compra: van sobre fondo
   claro, y un botón blanco de contorno ahí sería blanco sobre blanco. No es
   una cuestión de gusto, es que no se vería. */
.pd-negro .btn--primary,
.pd-negro .btn--secondary,
.pd-negro .btn--ghost,
.pd-negro .btn--soft {
  background: transparent;
  border: 1px solid oklch(1 0 0 / 0.12);
  color: oklch(0.94 0.006 265);
  border-radius: var(--r-pill);
  box-shadow: none;
  transition: color var(--t), background-color var(--t), border-color var(--t);
}

.pd-negro .btn--primary:hover,
.pd-negro .btn--secondary:hover,
.pd-negro .btn--ghost:hover,
.pd-negro .btn--soft:hover {
  background: oklch(1 0 0 / 0.07);
  border-color: oklch(1 0 0 / 0.28);
  color: #fff;
}

/* =============================================================================
   EL BOTÓN PRINCIPAL, EN PLATINO — 12-ago-2026

   Pedido del dueño: «hazlo gris como si fuera plata, tipo platinado glossy,
   igual al de iniciar sesión, como si hubiera un degradado entre el blanco y
   un gris».

   Sale de la cápsula de contorno de arriba y se convierte en metal. Los dos
   botones que señaló —«Ver productos» y «Iniciar sesión»— son la MISMA clase
   (.btn--primary), así que una sola regla los deja iguales, y de paso el resto
   de acciones principales de la portada.
   Secundario, ghost y soft NO cambian: siguen siendo cápsulas de contorno. Eso
   crea la jerarquía que antes no existía —todos los botones se veían igual—:
   ahora el metal es «la acción», y el contorno «lo demás».

   POR QUÉ ESTE DEGRADADO Y NO UNO SUAVE DE BLANCO A GRIS
   Un degradado liso de blanco a gris se lee como PAPEL GRIS, no como metal. Lo
   que convierte una superficie en metálica es el CORTE seco a media altura: el
   salto del 49% al 51% es la línea del horizonte reflejada en la pieza. Encima
   vuelve a aclarar hacia abajo (el rebote del suelo), que es lo que hace que se
   lea convexo. Es la misma razón que ya estaba anotada para --gloss-face en
   styles.css: «lo que hace que una superficie se lea como pulida no es el
   degradado, es el corte».

   El texto va en el negro de marca, no en gris: sobre la banda más oscura del
   metal (#9fa4ac) da 7,6:1, y sobre la más clara 20:1. Los dos pasan AA de
   sobra, que es lo que hay que garantizar cuando el fondo del botón cambia de
   luminosidad de arriba abajo.
   ============================================================================= */
.pd-negro .btn--primary {
  background:
    linear-gradient(180deg,
      #ffffff 0%,
      #f0f1f3 22%,
      #cdd0d5 49%,
      #a3a8b0 51%,
      #c4c8ce 78%,
      #f4f5f7 100%);
  border: 1px solid oklch(1 0 0 / 0.5);
  color: var(--on-brand);
  box-shadow:
    inset 0 1px 0 oklch(1 0 0 / 0.95),
    inset 0 -1px 0 oklch(0 0 0 / 0.28),
    0 8px 20px -10px oklch(0 0 0 / 0.9);
  text-shadow: 0 1px 0 oklch(1 0 0 / 0.45);
  /* background-image entra en la transición: los tres degradados (reposo,
     cursor encima y pulsado) tienen los MISMOS seis puntos y del mismo tipo, y
     con esa condición el navegador sabe interpolarlos. Si no coincidieran,
     saltaría de uno a otro de golpe. */
  transition: background-image var(--t), border-color var(--t),
              transform var(--t), box-shadow var(--t);
}

/* AL PASAR EL CURSOR: RESPLANDOR, Y EL METAL INTACTO.
   Pedido del dueño tras ver el primer intento: «cuando lo sombreo sale así, no
   me gusta; añade algo como un resplandor, en ambos botones».

   EL FALLO QUE HUBO AQUÍ, PARA QUE NO SE REPITA
   El bloque «UN SOLO BOTÓN EN TODA LA PORTADA», más arriba, agrupa el hover de
   primary/secondary/ghost/soft y les pone `background: oklch(1 0 0 / 0.07)`
   —un velo blanco sobre negro—. Mi primera versión de esta regla cambiaba
   `filter`, `box-shadow` y `color`, pero NO volvía a declarar `background`.
   Misma especificidad, propiedades distintas: cada declaración gana por su
   lado, así que al pasar el cursor el platino se sustituía por aquel velo y el
   texto, que es negro, quedaba negro sobre negro. Se veía el botón «apagado».
   Regla que se saca de esto: al sacar un botón de un grupo, hay que redeclarar
   TODAS las propiedades que el grupo toca, no solo las que se quieren cambiar.

   EL RESPLANDOR
   Dos capas de halo hacia fuera —una corta y blanca (el filo que se enciende) y
   otra ancha y cálida (la luz que se derrama sobre el negro)— más el metal un
   punto más claro. Va en `box-shadow` y no en `filter: drop-shadow` porque la
   cápsula tiene fondo: box-shadow sigue el borde redondeado exacto y no cuesta
   una capa de composición aparte. */
.pd-negro .btn--primary:hover {
  background:
    linear-gradient(180deg,
      #ffffff 0%,
      #f7f8f9 22%,
      #d9dce0 49%,
      #b2b7be 51%,
      #d2d6db 78%,
      #fafbfc 100%);
  border-color: oklch(1 0 0 / 0.75);
  color: var(--on-brand);
  box-shadow:
    inset 0 1px 0 oklch(1 0 0 / 1),
    inset 0 -1px 0 oklch(0 0 0 / 0.3),
    0 10px 26px -10px oklch(0 0 0 / 0.95),
    0 0 0 4px oklch(1 0 0 / 0.10),
    0 0 26px 2px oklch(0.85 0.06 91 / 0.38);
}

/* Al pulsar se hunde: el filo de luz se va arriba, entra una sombra interior y
   el resplandor se recoge. Sin esto el botón se siente una calcomanía. */
.pd-negro .btn--primary:active {
  background:
    linear-gradient(180deg,
      #eceef0 0%,
      #dfe1e4 22%,
      #bcc0c6 49%,
      #979ca4 51%,
      #b9bdc3 78%,
      #e6e8ea 100%);
  transform: translateY(1px);
  box-shadow:
    var(--gloss-press),
    inset 0 -1px 0 oklch(1 0 0 / 0.35),
    0 0 14px oklch(0.85 0.06 91 / 0.22);
}

/* El icono de la flecha hereda el color del texto: antes venía del oro y se
   quedaba dorado dentro de una cápsula blanca. Sobre el platino esto es lo que
   lo pone en negro en vez de dejarlo blanco e invisible. */
.pd-negro .btn svg {
  color: currentColor;
}

/* El carrito y el modal recuperan el botón de la casa (fondo claro). */
.pd-negro .drawer .btn--primary,
.pd-negro .modal .btn--primary,
.pd-negro .sheet .btn--primary {
  background: var(--brand-strong);
  border-color: transparent;
  color: var(--on-brand);
}

/* Los enlaces de texto de la portada, al mismo gris que los filtros. */
.pd-negro .pd-link {
  color: oklch(0.72 0.012 265);
}

.pd-negro .pd-link:hover {
  color: #fff;
}

/* --- TODOS LOS TITULARES, COMO EL DE "PRODUCTOS" ---------------------------
   11-ago-2026, cuarta vuelta. El dueño señaló el apartado de Productos: «la
   misma que ahí». Midiendo los dos titulares se vio que NO eran iguales:

     Productos  54.4px · 700 · interletrado -0.035em · interlínea 1.02
     Garantía   54.4px · 700 · interletrado NORMAL   · interlínea 1.18

   La diferencia la metí yo al «normalizar» el espaciado; y en Productos no se
   llegó a aplicar porque la regla de la casa —main > .section .sec-head h2—
   pesa más que la mía. O sea que el titular que al dueño le gusta es el
   CERRADO, y el que sobraba era el suelto.
   Aquí se iguala Garantía a los demás en vez de al revés. Un solo titular en
   toda la portada. */
.pd-negro {
  --pd-titular: clamp(1.9rem, 4.4vw, 3.4rem);
  --pd-display: clamp(2.2rem, 6vw, 4.5rem);
}

.pd-negro .pd-cap .pd-cap__h2 {
  font-size: var(--pd-titular);
  font-weight: 700;
  line-height: 1.02;
  letter-spacing: -0.035em;
}

/* Las cejas de sección («CATÁLOGO», «PROCESO», «MEDIOS DE PAGO») se retiran de
   la vista: el apartado de Productos, que es el modelo, no tiene ninguna, y en
   versálitas separadas a 0.22em eran el otro sitio donde el texto no parecía
   texto. Siguen en el HTML —son útiles para quien navegue con lector de
   pantalla—, solo dejan de pintarse. */
.pd-negro .sec-eyebrow,
.pd-negro .pd-cap__eyebrow {
  display: none;
}

/* =============================================================================
   POR QUÉ SE VEÍA BORROSO — 11-ago-2026
   El dueño lo describió exacto: «se ve borroso, no parece un texto normal».
   No era la fuente ni el tamaño ni el interletrado, que es lo que estuve
   cambiando cuatro veces. Eran tres ajustes de RENDERIZADO que styles.css
   aplica a todo el <body>:

   1. -webkit-font-smoothing: antialiased
      Fuerza suavizado en escala de grises en lugar del de subpíxel. Sobre
      fondo CLARO adelgaza un poco y queda fino; sobre fondo NEGRO, que es lo
      que es esta portada, adelgaza tanto que el texto se ve lavado y sin
      filo — literalmente borroso. Es el error clásico de los temas oscuros.

   2. text-rendering: optimizeLegibility
      Activa ligaduras y kerning extra. Junta pares de letras de formas que no
      corresponden al texto corriente.

   3. font-feature-settings: "ss01", "cv01", "ss03"
      Enciende los juegos estilísticos ALTERNATIVOS de Manrope: cambia el
      dibujo de varias letras por sus versiones de diseño. De ahí lo de «no
      parece un texto normal» — literalmente no son las letras normales de la
      fuente, son las alternativas.

   Los tres vuelven a su valor por defecto SOLO en la portada. El resto de la
   tienda, que va sobre blanco, se queda como estaba.
   ============================================================================= */
body.pd-negro {
  /* SUAVIZADO EN GRIS, no de subpíxel. Esta es la corrección de la corrección.

     El de subpíxel dibuja cada letra usando los tres puntos de color del
     píxel, así que los bordes salen con FLECOS rojos y azules. Sobre blanco
     no se notan; sobre negro, con letra blanca y grande, se ven como suciedad
     de color en el filo — que es exactamente lo que el dueño describió como
     «texturas feas». Yo lo puse en auto la vuelta anterior intentando quitar
     lo borroso, y cambié un problema por otro.

     En gris cada letra se dibuja en un solo tono: cero fleco de color, filo
     limpio. Lo que tenía de malo —que adelgaza el trazo y por eso se veía
     lavado— se compensa abajo subiendo el peso y usando blanco puro.

     Los otros dos ajustes SÍ se quedan como estaban: las ligaduras extra y
     sobre todo los juegos de letras alternativas eran un problema real y
     aparte. */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: auto;
  font-feature-settings: normal;
}

/* BLANCO PURO Y ALGO MÁS DE CUERPO.
   El sistema pinta los titulares con --ink, que en oscuro es oklch(0.98) con
   una pizca de azul: sobre negro se lee gris azulado, no blanco. Y en gris, el
   suavizado adelgaza el trazo. Blanco puro + un peso más = letra limpia y con
   cuerpo, que es lo que se pidió. */
.pd-negro h1,
.pd-negro h2,
.pd-negro h3,
.pd-negro .pd-cap__h2,
.pd-negro .sec-head h2,
.pd-negro .pd-cifra b,
.pd-negro .catalog-head h1 {
  color: #fff;
  -webkit-text-fill-color: #fff;
}

/* El texto corriente sube de gris apagado a un gris claro legible: en negro,
   un párrafo por debajo del 70% de luz se lee con esfuerzo. */
.pd-negro p,
.pd-negro li,
.pd-negro .pd-cap__p {
  color: oklch(0.82 0.008 265);
}

/* =============================================================================
   EL CATÁLOGO, CON EL MISMO LENGUAJE QUE LA PORTADA — 11-ago-2026
   Pedido del dueño: «todo el apartado de productos también, coherencia visual
   así como el home». La página ya hereda de arriba el lienzo negro, la letra,
   los titulares y las cápsulas de contorno; aquí solo van las piezas que son
   suyas y que traen fondo propio de cuando iba sobre blanco.

   La regla es la misma de toda la portada: nada de rellenos, solo el aire y,
   donde hace falta límite, un canto de un píxel al 8% de blanco.
   ============================================================================= */

/* Columna de filtros, barra de herramientas y estado vacío: sin caja. */
.pd-negro .filters,
.pd-negro .catalog-toolbar,
.pd-negro .filter-group,
.pd-negro .catalog-empty .card,
.pd-negro .active-tags .chip {
  background: transparent;
  box-shadow: none;
}

.pd-negro .filters,
.pd-negro .catalog-empty .card {
  border: 1px solid oklch(1 0 0 / 0.08);
}

.pd-negro .filter-group {
  border-bottom-color: oklch(1 0 0 / 0.07);
}

/* Campos del catálogo (buscar, ordenar, casillas). Un <input> con fondo claro
   sobre negro es lo que más canta de una página convertida a oscuro. */
.pd-negro .field,
.pd-negro .catalog-toolbar select,
.pd-negro .catalog-toolbar input,
.pd-negro .filters input[type="search"],
.pd-negro .filters select {
  background: transparent;
  border: 1px solid oklch(1 0 0 / 0.12);
  border-radius: var(--r-pill);
  color: oklch(0.94 0.006 265);
  box-shadow: none;
}

.pd-negro .field:focus,
.pd-negro .catalog-toolbar select:focus,
.pd-negro .catalog-toolbar input:focus,
.pd-negro .filters input[type="search"]:focus {
  border-color: oklch(1 0 0 / 0.3);
  outline: none;
}

/* Las opciones del desplegable las dibuja el sistema, no el CSS de la página:
   sin esto salen texto blanco sobre fondo blanco al desplegarlo. */
.pd-negro select option {
  background: #101418;
  color: #fff;
}

/* Etiquetas de filtro activo: la misma cápsula que los filtros de la portada. */
.pd-negro .active-tags .chip,
.pd-negro .chip {
  border: 1px solid oklch(1 0 0 / 0.12);
  border-radius: var(--r-pill);
  color: oklch(0.88 0.008 265);
}

/* La tarjeta de producto del catálogo. Aquí SÍ se conserva la tarjeta completa
   —con imagen, etiquetas y botón—: es la página donde se compra y el cliente
   necesita ver los datos. Lo que se va es el relleno, no la información. */
.pd-negro .lic-card,
.pd-negro .catalog-grid .card {
  background: transparent;
  border: 1px solid oklch(1 0 0 / 0.08);
  box-shadow: none;
}

.pd-negro .lic-card:hover {
  border-color: oklch(1 0 0 / 0.2);
  background: oklch(1 0 0 / 0.03);
}

/* Los titulares del catálogo, al mismo sitio que los de la portada. */
.pd-negro .catalog-head h1 {
  color: var(--ink);
  letter-spacing: -0.035em;
}

/* --- EL TITULAR DEL HERO ----------------------------------------------------
   11-ago-2026. Sustituye al texto que vault3d.js dibujaba con partículas dentro
   del lienzo. Los valores NO son inventados: son exactamente los del titular de
   «Productos», que es el que el dueño señaló como bueno —misma familia, mismo
   peso 700, mismo interletrado -0.035em, misma interlínea 1.02—. Lo único que
   cambia es el tamaño, un punto mayor porque es el encabezado de la página.

   El subtítulo va de segunda línea, en el gris de los párrafos y sin apretar:
   una frase larga con el interletrado del titular se lee peor, no mejor. */
.pd-rotulo {
  margin: clamp(1.5rem, 3.5vw, 2.5rem) 0 0;
  font-family: var(--font-display);
  font-size: clamp(2.1rem, 5vw, 3.9rem);
  font-weight: 700;
  line-height: 1.02;
  letter-spacing: -0.035em;
  color: #fff;
  text-wrap: balance;
}

.pd-rotulo span {
  display: block;
  margin-top: clamp(0.6rem, 1.4vw, 1rem);
  font-size: clamp(1rem, 0.95rem + 0.5vw, 1.35rem);
  font-weight: 400;
  line-height: 1.45;
  letter-spacing: normal;
  color: oklch(0.82 0.008 265);
}

/* --- BRILLO Y SOMBRA EN LOS TEXTOS BLANCOS ----------------------------------
   11-ago-2026. Cuatro capas de text-shadow, en este orden:

     1. filo de luz en el canto de ARRIBA (blanco al 42%, un píxel hacia
        arriba). Es lo que hace el bisel: la luz viene de arriba, así que el
        canto superior de la letra brilla;
     2. sombra pegada abajo, que le da el grosor;
     3. caída larga y difusa, que despega la letra del fondo;
     4. un halo blanquísimo alrededor — el reflejo.

   POR QUÉ CON text-shadow Y NO CON UN DEGRADADO. Ya se probó lo segundo (con
   background-clip:text) y fue justo lo que el dueño rechazó: al recortar el
   texto sobre un fondo, el navegador deja de dibujarlo con su suavizado normal
   y los trazos salen sucios. text-shadow no toca cómo se dibuja la letra —
   añade capas DETRÁS—, así que el filo se conserva intacto.

   No entra el texto gris de los párrafos: una sombra bajo un texto pequeño y
   de poco contraste solo lo emborrona. */
.pd-negro h1,
.pd-negro h2,
.pd-negro .pd-rotulo,
.pd-negro .pd-cap__h2,
.pd-negro .sec-head h2,
.pd-negro .pd-cifra b,
.pd-negro .catalog-head h1 {
  text-shadow:
    0 -1px 0 oklch(1 0 0 / 0.42),
    0 1px 1px oklch(0 0 0 / 0.6),
    0 18px 34px oklch(0 0 0 / 0.6),
    0 0 34px oklch(1 0 0 / 0.07);
}

/* El subtítulo del hero lleva la misma receta MUY rebajada: es texto pequeño y
   gris, y con la sombra entera se leería emborronado. */
.pd-negro .pd-rotulo span {
  text-shadow:
    0 1px 1px oklch(0 0 0 / 0.5),
    0 8px 20px oklch(0 0 0 / 0.4);
}
