/* ===== Encabezado fijo ===== */
header {
  position: fixed;
  top: 0;
  z-index: 1000;
  width: 100%;
  border-bottom: 1px solid transparent;
  background: transparent;
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  transition: background 500ms ease, border-color 500ms ease;
}

header.desplazado {
  border-bottom-color: rgb(255 255 255 / 12%);
  background: rgb(0 0 0 / 88%);

  /* Un backdrop-filter en una barra fija obliga a recomponer todo lo que queda
     detrás en cada cuadro del scroll, y es de lo más caro en móvil. Ya
     desplazado el fondo es negro al 88%, así que el desenfoque no llega a
     notarse: se quita y se recupera la fluidez. Arriba del todo, sobre el
     video, sí se conserva. */
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

html {
  scroll-padding-top: 78px;
}

.barra {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 32px;
  padding: 18px 0;
}

.marca img {
  width: auto;
  height: 38px;
  transition: transform 300ms ease;
}

.marca:hover img {
  transform: scale(1.03);
}

nav {
  display: flex;
  gap: 36px;
}

nav a {
  color: var(--texto-suave);
  font-size: 0.8rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  transition: color 300ms ease, transform 300ms ease;
}

nav a:hover,
nav a.activo {
  transform: translateY(-1px);
  color: #fff;
}

.boton-barra {
  padding: 13px 24px;
  border: 0;
  box-shadow: 0 4px 14px rgb(225 29 42 / 30%);
  white-space: nowrap;
}

/* Botón hamburguesa (solo móvil) */
.boton-menu {
  display: none;
  width: 44px;
  height: 40px;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  padding: 0 10px;
  border: 1px solid rgb(255 255 255 / 18%);
  border-radius: 3px;
  background: rgb(255 255 255 / 5%);
  cursor: pointer;
}

.boton-menu span {
  display: block;
  height: 2px;
  border-radius: 2px;
  background: #fff;
  transition: transform 260ms ease, opacity 200ms ease;
}

.boton-menu[aria-expanded="true"] span:nth-child(1) {
  transform: translateY(7px) rotate(45deg);
}

.boton-menu[aria-expanded="true"] span:nth-child(2) {
  opacity: 0;
}

.boton-menu[aria-expanded="true"] span:nth-child(3) {
  transform: translateY(-7px) rotate(-45deg);
}

/* ===== Portada ===== */
.portada {
  position: relative;
  display: flex;
  min-height: 100svh;
  align-items: center;
  overflow: hidden;
  padding: 76px 0 24px;
  background: #000;
}

/* Viñeta oscura: da contraste al texto sin tapar el video.
   Son dos capas en un mismo pseudo-elemento (una sola capa de composición, no
   cuesta más que la de antes). La lineal oscurece la columna izquierda, que es
   donde va el texto y donde el video tiene los monitores encendidos; se apaga
   antes del 75% para no ensuciar la parte derecha del encuadre. La radial que
   ya estaba baja de intensidad porque ahora no trabaja sola.

   El 66% de arranque salió de medir sobre cuadros del propio video: deja el
   fondo bajo el texto en 49/255 de percentil 95, o sea 11.8:1 de contraste
   contra el texto blanco, cuando el mínimo exigible es 4.5:1. Antes estaba en
   88%, que daba 14.5:1 (margen que no hacía falta) a cambio de aplastar el muro
   de monitores casi a negro justo donde es más interesante. */
.portada::after {
  position: absolute;
  inset: 0;
  z-index: 2;
  background:
    linear-gradient(100deg, rgb(0 0 0 / 66%) 0%, rgb(0 0 0 / 42%) 38%, rgb(0 0 0 / 10%) 62%, transparent 78%),
    radial-gradient(90% 90% at 30% 50%, rgb(0 0 0 / 40%) 0%, rgb(0 0 0 / 24%) 55%, rgb(0 0 0 / 10%) 100%);
  content: "";
  pointer-events: none;
}

.portada video {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  filter: brightness(0.95) contrast(1.05);
  object-fit: cover;
  pointer-events: none;
}

.niebla {
  position: absolute;
  z-index: 1;
  inset: -15%;
  overflow: hidden;
  opacity: 0.35;
  pointer-events: none;
}

.nube {
  position: absolute;
  border-radius: 50%;
  filter: blur(55px);
  will-change: transform, opacity;
}

.nube-1 {
  top: -10%;
  left: -5%;
  width: 950px;
  height: 950px;
  background: radial-gradient(circle, rgb(255 255 255 / 22%) 0%, rgb(225 29 42 / 28%) 35%, rgb(10 10 15 / 75%) 65%, transparent 80%);
}

.nube-2 {
  bottom: -10%;
  left: 15%;
  width: 1050px;
  height: 1050px;
  background: radial-gradient(circle, rgb(0 0 0 / 95%) 0%, rgb(15 15 22 / 85%) 50%, transparent 80%);
}

.nube-3 {
  top: 10%;
  left: 30%;
  width: 850px;
  height: 850px;
  background: radial-gradient(circle, rgb(59 130 246 / 22%) 0%, rgb(10 10 15 / 65%) 55%, transparent 75%);
}

.contenido-portada {
  position: relative;
  z-index: 3;
  /* Desplazamiento del bloque respecto al centro de la portada. Era de 50px,
     pero con los botones el contenido creció y se salía del primer pantallazo
     en portátiles; centrado cabe completo. Es el único número a mover si se
     quiere más arriba o más abajo. */
  top: 0;
}

.contenido-portada h1 {
  /* 780px deja el titular en tres renglones en escritorio. `balance` reparte
     las palabras entre ellos para que no quede uno con dos palabras sueltas;
     donde no esté soportado simplemente se ignora y parte por ancho. */
  max-width: 780px;
  margin: 0;
  font-size: clamp(2.1rem, 3.8vw, 3.5rem);
  font-weight: 700;
  line-height: 1.06;
  text-wrap: balance;
}

.contenido-portada h1 span {
  background: linear-gradient(135deg, #e11d2a, #ff4d5a);
  -webkit-background-clip: text;
  background-clip: text;
  color: var(--rojo);
  -webkit-text-fill-color: transparent;
}

.entrada-portada {
  max-width: 580px;
  margin: 16px 0 0;
  color: #c2c7d0;
  font-size: 1rem;
  line-height: 1.68;
}

/* La acción principal de toda la página. Antes el único botón vivía en el
   encabezado y la portada no ofrecía ningún camino. */
.acciones-portada {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin-top: 30px;
}

/* Métricas de portada (propuesta 4).
   Rejilla de cuatro columnas en vez de flex: con `flex-wrap` la cuarta métrica
   se caía sola a un segundo renglón y arrastraba un separador huérfano. */
.metricas-portada {
  display: grid;
  max-width: 760px;
  /* Anclado arriba, no centrado: en pantallas angostas hay etiquetas que se
     parten en dos renglones y, centradas, las cifras de una misma fila
     quedaban a distinta altura. */
  align-items: start;
  justify-content: start;
  grid-template-columns: repeat(4, auto);
  margin-top: 30px;
  padding-top: 20px;
  border-top: 1px solid rgb(255 255 255 / 14%);
}

.metrica {
  padding: 0 22px;
  border-left: 1px solid rgb(255 255 255 / 15%);
}

.metrica:first-child {
  padding-left: 0;
  border-left: 0;
}

.cifra {
  display: block;
  font-family: var(--titulos);
  font-size: 1.65rem;
  font-weight: 700;
  /* Ancho fijo por dígito: evita que la cifra se mueva mientras cuenta */
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

.cifra.rojo {
  color: var(--rojo);
  text-shadow: 0 0 12px rgb(225 29 42 / 40%);
}

.cifra.azul {
  color: var(--azul);
  text-shadow: 0 0 12px rgb(59 130 246 / 40%);
}

.detalle {
  display: block;
  margin-top: 2px;
  color: var(--texto-suave);
  font-family: var(--mono);
  font-size: 0.62rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

/* ===== Franja de clientes ===== */
.clientes {
  overflow: hidden;
  /* 40 + los 6 de relleno del visor = los 46 de siempre. */
  padding: 40px 0;
  border-top: 1px solid rgb(255 255 255 / 8%);
  border-bottom: 1px solid rgb(255 255 255 / 8%);
  background: #000;
}

.cuadricula-clientes {
  display: grid;
  align-items: center;
  gap: 48px;
  grid-template-columns: minmax(0, 220px) 1fr;
}

.titulo-clientes {
  margin: 0;
  color: #5c626e;
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.2em;
  line-height: 1.7;
  text-transform: uppercase;
}

.titulo-clientes span {
  color: var(--rojo);
}

/* El difuminado de los bordes se hacía con mask-image. Una máscara obliga al
   navegador a rehacer un pase de composición fuera de pantalla en cada cuadro
   mientras la pista se desplaza por debajo, y eso trababa el scroll en móvil
   justo al pasar por esta franja. Como el fondo de .clientes es negro sólido,
   dos degradados hacia ese mismo negro dan el mismo resultado a la vista y solo
   cuestan dos capas superpuestas. */
/* El visor mide justo lo que mide un logotipo, así que al agrandarse con el
   :hover se salía por arriba y por abajo y `overflow: hidden` le rebanaba el
   borde: en los logotipos redondos el corte se veía como un círculo aplanado.
   Este relleno le deja el margen que necesita el zoom (52px * 1.06 = 55.1,
   o sea 1.6px por lado) y se descuenta del relleno de .clientes para que la
   franja siga midiendo lo mismo. `overflow` no se puede abrir solo en vertical:
   en cuanto un eje es visible el otro pasa a auto y aparecería una barra. */
.visor-logos {
  position: relative;
  padding: 6px 0;
  overflow: hidden;
}

.visor-logos::before,
.visor-logos::after {
  position: absolute;
  z-index: 1;
  top: 0;
  width: 8%;
  height: 100%;
  content: "";
  pointer-events: none;
}

.visor-logos::before {
  left: 0;
  background: linear-gradient(90deg, #000, transparent);
}

.visor-logos::after {
  right: 0;
  background: linear-gradient(270deg, #000, transparent);
}

.pista-logos {
  --separacion-logos: 80px;
  --altura-logo: 52px;
  display: flex;
  width: max-content;
  /* Con la igualación óptica de más abajo ya casi ningún logotipo mide los
     --altura-logo completos, así que sin este mínimo la pista se encogería hasta
     su pieza más alta y las dos franjas dejarían de medir lo mismo: la de
     partners, que no tiene ningún escudo a tamaño completo, quedaba 7px más baja
     que la de clientes. Fijado el alto, los logotipos se centran dentro. */
  min-height: var(--altura-logo);
  align-items: center;
  gap: var(--separacion-logos);
  /* Capa propia: el navegador rasteriza la tira una sola vez (con los filtros
     de los logotipos ya aplicados) y después solo la desliza. La duración va
     con el largo de la pista: son 15 logotipos por vuelta y a 6s cada uno se
     mantiene la velocidad de desplazamiento que tenía con cinco. */
  animation: desplazar-logos 90s linear infinite;
  will-change: transform;
}

/* La franja de partners lleva doce logotipos en vez de quince: con los mismos
   6s por logotipo, la vuelta dura 72s y la tira se desplaza a la misma
   velocidad que la de clientes. */
.pista-partners {
  animation-duration: 72s;
}

.pista-logos.detenida,
.pista-logos.pestana-oculta {
  animation-play-state: paused;
}

.pista-logos img {
  width: auto;
  height: calc(var(--altura-logo) * var(--escala-optica, 1));
  filter: grayscale(1) brightness(2.2);
  object-fit: contain;
  opacity: 0.55;
  transition: opacity 400ms ease, filter 400ms ease, transform 400ms ease;
}

/* ===== Igualación óptica de los logotipos =====
   Los 27 archivos están recortados al contenido y miden todos 104px de alto, así
   que darles la misma altura CSS los deja del mismo tamaño de caja pero no del
   mismo tamaño aparente: un escudo redondo ocupa esos 52px con toda su forma,
   mientras que un logotipo de una sola línea de texto los ocupa con la altura de
   las letras. Medida la superficie de tinta de cada archivo (píxeles opacos,
   escalados al tamaño de dibujo), los partners salían a 60 de media y los
   clientes a 38: por eso la segunda franja se veía bastante más grande que la
   primera aunque las dos usaran la misma regla. Después de la corrección las dos
   medianas quedan en 38.

   --escala-optica corrige eso: es 52 * 38 / (tinta del logotipo), o sea el factor
   que iguala la superficie de tinta de cada pieza a la del cliente promedio.
   Queda acotado entre 0.58 y 1 para que ningún logotipo se salga de la franja ni
   se quede tan bajo que se pierda: los que ya estaban por debajo de la media
   (escudos pequeños como Irapuato o Fragaria) se quedan en 1 y los muy anchos
   (Avigilon, Genetec, Pelco, Cambium) tocan el suelo de 0.58. El valor es un
   factor y no una altura fija para que el corte de móvil, que solo cambia
   --altura-logo, siga funcionando sin repetir estos números. */
.logo-guanajuato,
.logo-procter-gamble {
  --escala-optica: 0.82;
}

.logo-c5i {
  --escala-optica: 0.86;
}

.logo-holiday-inn {
  --escala-optica: 0.71;
}

.logo-aloft {
  --escala-optica: 0.97;
}

.logo-gigante-verde {
  --escala-optica: 0.77;
}

.logo-pagobus {
  --escala-optica: 0.72;
}

.logo-axis {
  --escala-optica: 0.70;
}

.logo-avigilon,
.logo-genetec,
.logo-pelco,
.logo-cambium {
  --escala-optica: 0.58;
}

.logo-hanwha {
  --escala-optica: 0.85;
}

.logo-unv {
  --escala-optica: 0.87;
}

.logo-flir {
  --escala-optica: 0.69;
}

.logo-notifier {
  --escala-optica: 0.79;
}

.logo-ciscou {
  --escala-optica: 0.61;
}

.logo-astra {
  --escala-optica: 0.82;
}

.logo-lightera {
  --escala-optica: 0.80;
}

/* Al pasar por encima, el logotipo recupera su color y se agranda un poco.
   Se llegó a restringir a dispositivos con ratón por sospecha de que el :hover
   accidental del dedo trababa el scroll aquí. Medida la grabación cuadro a
   cuadro, el culpable resultó ser otro (arrancar y detener el video de la
   portada), así que el efecto vuelve a estar activo en todos los dispositivos. */
.pista-logos img:hover,
.pista-logos img:focus-visible {
  transform: scale(1.06);
  filter: none;
  opacity: 1;
}


/* El recorrido avanza medio ancho de la pista más medio hueco: así el primer
   logotipo de la copia queda exactamente donde arrancó el original y el ciclo
   se reinicia sin salto visible. */
@keyframes desplazar-logos {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(calc(-50% - var(--separacion-logos) / 2));
  }
}

@media (max-width: 1100px) {
  nav {
    gap: 22px;
  }

  nav a {
    font-size: 0.72rem;
  }
}

@media (max-width: 900px) {
  /* El backdrop-filter del header se quita en cuanto se hace scroll (arriba,
     header.desplazado), pero justo al inicio, sobre el video, sigue activo a
     propósito para el efecto de vidrio. En móvil eso cae exactamente en la
     franja donde ya se recortaron otros filtros por el mismo motivo, así que
     se apaga también aquí y el header arranca con fondo sólido. */
  header {
    background: rgb(0 0 0 / 55%);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }

  /* Mismo razonamiento que el zoom y las nubes: recalcular brightness/contrast
     sobre cada fotograma decodificado del video es un costo continuo que no
     depende del scroll, y en una pantalla de teléfono el ajuste de color casi
     no se nota. Se quita para dejarle más margen a la GPU en esa franja. */
  .portada video {
    filter: none;
  }

  .portada {
    min-height: auto;
    padding: 95px 0 40px;
  }

  /* En pantallas pequeñas la portada ya no sobra espacio: sin desplazamiento */
  .contenido-portada {
    top: 0;
  }

  .contenido-portada h1 {
    font-size: clamp(1.8rem, 6.8vw, 3.1rem);
  }

  /* Va por clase y no por `.contenido-portada > p`, para no arrastrar a
     cualquier otro párrafo que se agregue después al bloque de portada. */
  .entrada-portada {
    font-size: 0.95rem;
  }

  /* Aquí el texto ocupa todo el ancho, así que el degradado deja de venir del
     lado izquierdo y pasa a ser de arriba abajo. */
  .portada::after {
    background:
      linear-gradient(180deg, rgb(0 0 0 / 78%) 0%, rgb(0 0 0 / 55%) 45%, rgb(0 0 0 / 72%) 100%),
      radial-gradient(90% 90% at 50% 50%, rgb(0 0 0 / 30%) 0%, rgb(0 0 0 / 15%) 100%);
  }

  .boton-menu {
    display: flex;
    order: 3;
  }

  .boton-barra {
    display: none;
  }

  nav {
    position: absolute;
    top: 100%;
    right: 0;
    left: 0;
    display: grid;
    max-height: 0;
    overflow: hidden;
    gap: 0;
    border-bottom: 1px solid transparent;
    background: rgb(0 0 0 / 96%);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    transition: max-height 320ms ease, border-color 320ms ease;
  }

  nav.abierto {
    max-height: 420px;
    border-bottom-color: rgb(255 255 255 / 10%);
  }

  nav a {
    padding: 16px 24px;
    border-top: 1px solid rgb(255 255 255 / 7%);
    font-size: 0.78rem;
  }

  .cuadricula-clientes {
    gap: 26px;
    grid-template-columns: 1fr;
    text-align: center;
  }
}

/* Las cuatro columnas dejan de caber antes que el resto del bloque, así que
   pasan a 2x2 en su propio corte. */
@media (max-width: 780px) {
  .metricas-portada {
    max-width: 420px;
    grid-template-columns: repeat(2, 1fr);
    row-gap: 22px;
  }

  .metrica:nth-child(odd) {
    padding-left: 0;
    border-left: 0;
  }
}

@media (max-width: 600px) {
  .acciones-portada .boton {
    flex: 1 1 100%;
  }

  .cifra {
    font-size: 1.4rem;
  }

  .pista-logos {
    --separacion-logos: 52px;
    --altura-logo: 42px;
  }
}

/* ===== Alivio de pintado en pantallas pequeñas =====
   Al pasar de la portada a la franja de clientes y a pólizas se juntan cuatro
   trabajos pesados que en el resto de la página nunca coinciden: las tres nubes
   desenfocadas, el video escalándose, el carrusel desplazándose y el fondo de
   pólizas repintándose. En un móvil eso no cabe en el presupuesto de un cuadro
   y el scroll da tirones justo en esa banda.

   Las nubes ya son degradados radiales suaves, así que el desenfoque de 55px
   sobre ellos es casi redundante: bajarlo conserva el aspecto y cuesta una
   fracción, porque el coste del blur crece con el cuadrado del radio.

   El acercamiento del video y el movimiento de las nubes se desactivan también
   aquí, pero esas reglas viven en animaciones.css, que se carga después y
   mandaría sobre esta.

   La segunda condición cubre el "modo computadora" del navegador móvil, que
   declara un ancho de unos 980px: sin ella el teléfono se quedaría renderizando
   la versión completa de escritorio con su propio hardware. */
@media (max-width: 900px), (hover: none) and (pointer: coarse) {
  .nube {
    filter: blur(18px);
  }
}

/* ===== Portada en ventana ancha pero vertical =====
   Es el caso del "modo computadora" de un navegador móvil: declara unos 980px
   de ancho pero la pantalla sigue siendo vertical, así que 100svh estiraba la
   portada por encima de 2000px y el texto quedaba flotando en medio de un mar
   de video vacío. La altura pasa a depender del ancho, que es lo que da una
   proporción razonable, sin superar nunca la pantalla.

   Un monitor de escritorio es apaisado y jamás cumple max-aspect-ratio: 1/1,
   de modo que ahí no cambia absolutamente nada. */
@media (min-width: 901px) and (max-aspect-ratio: 1 / 1) {
  .portada {
    min-height: min(100svh, 68vw);
  }

  /* Con la portada ya compacta, el desplazamiento hacia abajo del bloque de
     texto deja de hacer falta y lo descentraría. */
  .contenido-portada {
    top: 0;
  }
}
