/* ==========================================================================
   LobotecAr — sistema visual
   Mundo: "La Traza". El circuito del logo es la estructura de la pagina.
   Manual de marca V2: negro real de fondo, un unico azul de acento, Russo One
   reservado al wordmark, Space Grotesk para todo lo demas.
   ========================================================================== */

/* --- Tipografias autohospedadas ------------------------------------------ */

@font-face {
  font-family: 'Russo One';
  src: url('assets/fonts/russo-one-latin.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Russo One';
  src: url('assets/fonts/russo-one-latin-ext.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Space Grotesk';
  src: url('assets/fonts/space-grotesk-latin.woff2') format('woff2');
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Space Grotesk';
  src: url('assets/fonts/space-grotesk-latin-ext.woff2') format('woff2');
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* --- Tokens --------------------------------------------------------------- */

:root {
  /* Los cuatro colores del manual, sin agregados. */
  --ink: #0A0D12;
  --azul: #2E6CE7;
  --blanco: #F4F6F8;
  --gris: #9AA6B8;

  /* Derivados del mismo azul: nucleo de neon y cobre apagado de la traza.
     No son colores nuevos, son estados del unico acento. */
  --azul-nucleo: #6FA0FF;
  --azul-frio: #1A2B4D;
  --azul-vivo: #4A82F0;

  /* Texto: el blanco titula, el intermedio lee, el gris etiqueta. */
  --texto: #F4F6F8;      /* 17.9:1 sobre ink */
  --texto-2: #C3CCD9;    /* 12.0:1 */
  --texto-3: #9AA6B8;    /*  7.9:1 */

  --panel: #10141B;
  --linea: rgba(154, 166, 184, .14);

  --e1: 4px;  --e2: 8px;  --e3: 12px; --e4: 16px; --e5: 24px;
  --e6: 32px; --e7: 48px; --e8: 64px; --e9: 96px; --e10: 128px;

  --h-cab: 72px;
  --ancho: 1240px;
  --margen: clamp(20px, 4vw, 48px);

  /* Canal reservado a la derecha para que la traza baje sin pisar contenido. */
  --canal: 76px;
  --riel-off: 8px;    /* del borde del contenedor al eje de la traza */
  --chaflan: 22px;

  --salida: cubic-bezier(.16, 1, .3, 1);
  --rapido: 160ms cubic-bezier(.3, .8, .4, 1);
}

@media (max-width: 899px) {
  :root { --h-cab: 60px; --canal: 44px; --riel-off: 6px; --chaflan: 16px; }
}

/* --- Base ----------------------------------------------------------------- */

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

html {
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--h-cab) + var(--e5));
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  position: relative;
  min-height: 100svh;
  background: var(--ink);
  color: var(--texto-2);
  font-family: 'Space Grotesk', ui-sans-serif, system-ui, sans-serif;
  font-size: clamp(1rem, .965rem + .18vw, 1.125rem);
  line-height: 1.6;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: clip;
}

h1, h2, h3 {
  margin: 0;
  color: var(--texto);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -.03em;
  text-wrap: balance;
}

p { margin: 0; }
/* El reset cubria solo ul: un ol conserva el padding-inline-start de 40px del
   navegador, asimetrico y solo del lado izquierdo. Era lo que corria los pasos
   respecto del titulo de su placa. */
ul, ol { margin: 0; padding: 0; list-style: none; }

img, svg { display: block; max-width: 100%; }
img { height: auto; }

a { color: var(--azul-nucleo); text-decoration-thickness: 1px; text-underline-offset: .22em; }

/* --- Superficies del navegador ------------------------------------------- */

::selection { background: var(--azul); color: #fff; }

:root {
  scrollbar-color: #22314f var(--ink);
  scrollbar-width: thin;
  caret-color: var(--azul-nucleo);
  accent-color: var(--azul);
}
::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: var(--ink); }
::-webkit-scrollbar-thumb {
  background: #22314f;
  border: 3px solid var(--ink);
  border-radius: 6px;
}
::-webkit-scrollbar-thumb:hover { background: #33456b; }

:focus-visible {
  outline: 2px solid var(--azul-nucleo);
  outline-offset: 3px;
  border-radius: 2px;
}

/* --- Utilidades ----------------------------------------------------------- */

.vo {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.saltar {
  position: fixed;
  top: var(--e3);
  left: var(--e3);
  z-index: 90;
  padding: 10px 18px;
  background: var(--azul);
  color: var(--ink);
  font-weight: 600;
  text-decoration: none;
  border-radius: 3px;
  transform: translateY(calc(-100% - var(--e5)));
  transition: transform var(--rapido);
}
.saltar:focus-visible { transform: none; }

.ico { width: 20px; height: 20px; flex: none; }

/* --- Botones -------------------------------------------------------------- */

.btn {
  --pad: 18px;
  --ico-comp: 30px; /* ancho del icono (20px) + gap (10px) */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  height: 44px;
  padding-inline: var(--pad);
  border: 0;
  border-radius: 3px;
  font: inherit;
  font-size: .9375rem;
  font-weight: 600;
  letter-spacing: -.01em;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background var(--rapido), color var(--rapido),
              box-shadow var(--rapido), transform var(--rapido);
}
.btn-grande { --pad: 26px; height: 54px; font-size: 1.0625rem; }

/* El icono empuja la etiqueta hacia el lado opuesto: compensamos ese lado con
   su ancho + gap para que quede centrado el texto, no el conjunto icono+texto. */
.btn:has(> .ico:first-child) { padding-right: calc(var(--pad) + var(--ico-comp)); }
.btn:has(> .ico:last-child)  { padding-left:  calc(var(--pad) + var(--ico-comp)); }

/* Tinta sobre azul: 5.0:1. El blanco sobre este azul queda en 4.4:1 y no pasa. */
.btn-primario {
  background: var(--azul);
  color: var(--ink);
  box-shadow: 0 10px 26px -14px rgba(46, 108, 231, .9);
}
.btn-primario:hover {
  background: var(--azul-vivo);
  box-shadow: 0 14px 34px -12px rgba(46, 108, 231, .95);
}
.btn-primario:active { transform: translateY(1px); }

.btn-fantasma {
  background: rgba(244, 246, 248, .035);
  color: var(--texto);
  box-shadow: inset 0 0 0 1px rgba(154, 166, 184, .26);
}
.btn-fantasma:hover {
  background: rgba(46, 108, 231, .12);
  color: var(--blanco);
  box-shadow: inset 0 0 0 1px rgba(46, 108, 231, .55);
}
.btn-fantasma:hover .ico { transform: translateX(3px); }
.btn-fantasma .ico { transition: transform var(--rapido); }
.btn-fantasma:active { transform: translateY(1px); }

.enlace-accion {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  color: var(--azul-nucleo);
  font-weight: 600;
  font-size: 1rem;
  text-decoration: none;
  padding-block: var(--e2);
}
.enlace-accion span {
  background-image: linear-gradient(currentColor, currentColor);
  background-size: 0% 1px;
  background-repeat: no-repeat;
  background-position: 0 100%;
  transition: background-size 260ms var(--salida);
}
.enlace-accion:hover span { background-size: 100% 1px; }
.enlace-accion .ico { width: 18px; height: 18px; transition: transform var(--rapido); }
.enlace-accion:hover .ico { transform: translateX(4px); }

/* --- Cabecera ------------------------------------------------------------- */

.cabecera {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 60;
  height: var(--h-cab);
  transition: background 220ms linear, box-shadow 220ms linear,
              backdrop-filter 220ms linear;
}
.cabecera.pegada {
  background: rgba(10, 13, 18, .78);
  backdrop-filter: blur(16px) saturate(140%);
  -webkit-backdrop-filter: blur(16px) saturate(140%);
  box-shadow: inset 0 -1px 0 rgba(46, 108, 231, .22);
}

.cabecera-int {
  max-width: var(--ancho);
  height: 100%;
  margin-inline: auto;
  padding-inline: var(--margen);
  display: flex;
  align-items: center;
  gap: var(--e5);
}

.marca {
  display: flex;
  align-items: center;
  gap: 11px;
  text-decoration: none;
  margin-right: auto;
}
.marca-icono { width: 34px; height: 34px; object-fit: contain; }
.marca-texto {
  font-family: 'Russo One', 'Space Grotesk', sans-serif;
  font-size: 1.28rem;
  line-height: 1;
  letter-spacing: .012em;
  color: var(--blanco);
  padding-top: 2px;
}
.marca-texto b { color: var(--azul); font-weight: inherit; }

.nav { display: flex; gap: var(--e5); }
.nav-a {
  position: relative;
  color: var(--texto-3);
  font-size: .9375rem;
  font-weight: 500;
  text-decoration: none;
  padding-block: 6px;
  transition: color var(--rapido);
}
.nav-a::after {
  content: '';
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 1px;
  background: var(--azul);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 300ms var(--salida);
}
.nav-a:hover { color: var(--blanco); }
.nav-a:hover::after { transform: scaleX(1); }
.nav-a[aria-current='true'] { color: var(--blanco); }
.nav-a[aria-current='true']::after { transform: scaleX(1); }

.hamburguesa {
  display: none;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  padding: 0;
  background: rgba(244, 246, 248, .04);
  color: var(--texto);
  border: 0;
  border-radius: 3px;
  box-shadow: inset 0 0 0 1px rgba(154, 166, 184, .22);
  cursor: pointer;
}
/* Tres trazos que se vuelven aspa. Antes eran dos SVG que se prendian y apagaban
   con display, o sea un corte seco; asi hay un solo objeto que se transforma.
   El grosor es el mismo 1.5 del set de iconos. */
.hamburguesa-trazos {
  position: relative;
  display: block;
  width: 18px;
  height: 14px;
}
.hamburguesa-trazos i {
  position: absolute;
  left: 0;
  width: 100%;
  height: 1.5px;
  background: currentColor;
  transition: transform 380ms var(--salida), opacity 160ms linear;
}
.hamburguesa-trazos i:nth-child(1) { top: 0; }
.hamburguesa-trazos i:nth-child(2) { top: 50%; margin-top: -.75px; }
.hamburguesa-trazos i:nth-child(3) { bottom: 0; }

/* El del medio se apaga primero y recien despues giran los otros dos: el aspa
   se arma en dos tiempos y no como un tironeo simultaneo. */
.hamburguesa[aria-expanded='true'] .hamburguesa-trazos i:nth-child(2) {
  opacity: 0;
  transform: scaleX(.4);
}
.hamburguesa[aria-expanded='true'] .hamburguesa-trazos i:nth-child(1) {
  transform: translateY(6.25px) rotate(45deg);
  transition-delay: 60ms;
}
.hamburguesa[aria-expanded='true'] .hamburguesa-trazos i:nth-child(3) {
  transform: translateY(-6.25px) rotate(-45deg);
  transition-delay: 60ms;
}
/* Al cerrar el orden se invierte: primero desgiran, despues vuelve el del medio. */
.hamburguesa .hamburguesa-trazos i:nth-child(2) { transition-delay: 220ms; }
.hamburguesa[aria-expanded='true'] .hamburguesa-trazos i:nth-child(2) { transition-delay: 0ms; }

.menu-movil {
  position: fixed;
  inset: var(--h-cab) 0 auto 0;
  z-index: 55;
  padding: var(--e5) var(--margen) var(--e7);
  background: rgba(10, 13, 18, .96);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  box-shadow: inset 0 -1px 0 rgba(46, 108, 231, .24);
}
.menu-movil[hidden] { display: none; }
/* Baja desde la cabecera en vez de aparecer de golpe. El JS saca [hidden] un
   cuadro antes de poner .abierto para que haya un estado desde el cual animar. */
.js .menu-movil {
  opacity: 0;
  transform: translateY(-10px);
  transition: opacity 240ms var(--salida), transform 240ms var(--salida);
}
.js .menu-movil.abierto { opacity: 1; transform: none; }
/* Los enlaces entran escalonados, el mismo gesto que .entra en el resto. */
.js .menu-movil.abierto nav a,
.js .menu-movil.abierto > .btn { animation: entra-menu 420ms var(--salida) backwards; }
.js .menu-movil.abierto nav a:nth-child(1) { animation-delay: 60ms; }
.js .menu-movil.abierto nav a:nth-child(2) { animation-delay: 105ms; }
.js .menu-movil.abierto nav a:nth-child(3) { animation-delay: 150ms; }
.js .menu-movil.abierto > .btn { animation-delay: 195ms; }
@keyframes entra-menu {
  from { opacity: 0; transform: translateY(10px); }
}
.menu-movil nav { display: grid; gap: 2px; margin-bottom: var(--e5); }
.menu-movil nav a {
  padding: 14px 0;
  color: var(--texto);
  font-size: 1.25rem;
  font-weight: 600;
  letter-spacing: -.02em;
  text-decoration: none;
  box-shadow: inset 0 -1px 0 var(--linea);
}
.menu-movil .btn { width: 100%; }

@media (max-width: 899px) {
  .nav, .btn-cabecera { display: none; }
  .hamburguesa { display: inline-flex; }
  .marca-icono { width: 30px; height: 30px; }
  .marca-texto { font-size: 1.12rem; }
}

/* --- La traza ------------------------------------------------------------- */

.traza-capa {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
}
.traza { overflow: visible; }

.traza-fria {
  fill: none;
  stroke: var(--azul-frio);
  stroke-width: 1.5;
  stroke-linejoin: round;
}
.traza-viva,
.traza-halo {
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: var(--largo, 0);
  stroke-dashoffset: calc(var(--largo, 0) * (1 - var(--avance, 0)));
}
.traza-viva { stroke: var(--azul-nucleo); stroke-width: 1.75; }
.traza-halo {
  stroke: var(--azul);
  stroke-width: 8;
  opacity: .34;
  filter: blur(7px);
}

.traza-pads .pad-anillo {
  fill: var(--ink);
  stroke: var(--azul-frio);
  stroke-width: 1.5;
  transition: stroke 420ms var(--salida);
}
.traza-pads .pad-nucleo {
  fill: var(--azul-frio);
  transition: fill 420ms var(--salida), filter 420ms var(--salida);
}
.traza-pads .pad-brazo {
  fill: none;
  stroke: var(--azul-frio);
  stroke-width: 1.5;
  stroke-dasharray: var(--brazo, 0);
  stroke-dashoffset: var(--brazo, 0);
  transition: stroke-dashoffset 620ms var(--salida), stroke 420ms var(--salida);
}
.traza-pads .nodo.vivo .pad-anillo { stroke: var(--azul); }
.traza-pads .nodo.vivo .pad-nucleo {
  fill: var(--azul-nucleo);
  filter: drop-shadow(0 0 5px rgba(46, 108, 231, .95));
}
.traza-pads .nodo.vivo .pad-brazo { stroke: var(--azul); stroke-dashoffset: 0; }

/* --- Envoltorio ----------------------------------------------------------- */

#contenido {
  position: relative;
  z-index: 1;
  max-width: var(--ancho);
  margin-inline: auto;
  padding-inline: var(--margen);
}

/* Guia invisible: su posicion en pantalla define el eje de la traza, de modo
   que el riel siempre queda atado al contenedor y no al borde de la ventana. */
.riel-guia {
  position: absolute;
  top: 0;
  right: calc(var(--margen) + var(--riel-off));
  width: 0;
  height: 1px;
  pointer-events: none;
}

/* --- Hero ----------------------------------------------------------------- */

.hero {
  display: flex;
  align-items: center;
  min-height: max(600px, calc(100svh - var(--h-cab)));
  padding-top: calc(var(--h-cab) + var(--e6));
  padding-bottom: var(--e8);
  padding-right: var(--canal);
}

.hero-int {
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(0, .8fr);
  align-items: center;
  gap: clamp(28px, 4.5vw, 72px);
  width: 100%;
}

.hero-titulo {
  font-size: clamp(2.125rem, 1.2rem + 3.1vw, 3.375rem);
  line-height: 1.02;
  letter-spacing: -.038em;
}
.hero-bajada {
  max-width: 46ch;
  margin-top: var(--e5);
  color: var(--texto-2);
  font-size: clamp(1.0625rem, 1rem + .35vw, 1.25rem);
  line-height: 1.55;
}

.hero-acciones {
  display: flex;
  flex-wrap: wrap;
  gap: var(--e3);
  margin-top: var(--e7);
}

/* Regla de base del hero: cruza las dos columnas y cierra el bloque. */
.hero-hechos {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  gap: var(--e2) clamp(20px, 3vw, 44px);
  margin-top: var(--e2);
  padding-top: var(--e5);
  color: var(--texto-3);
  font-size: .875rem;
  font-weight: 500;
  letter-spacing: .01em;
  box-shadow: inset 0 1px 0 var(--linea);
}
.hero-hechos li { display: flex; align-items: center; gap: 9px; }
.hero-hechos li::before {
  content: '';
  width: 5px;
  height: 5px;
  flex: none;
  background: var(--azul);
  box-shadow: 0 0 6px rgba(46, 108, 231, .85);
}

.hero-marca {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-self: end;
  width: 100%;
}
.hero-lobo {
  width: min(100%, 470px);
  height: auto;
}
.hero-wordmark {
  margin-top: calc(var(--e5) * -1);
  font-family: 'Russo One', 'Space Grotesk', sans-serif;
  font-size: clamp(1.75rem, .9rem + 2.5vw, 2.75rem);
  line-height: 1;
  letter-spacing: .01em;
  color: var(--blanco);
}
.hero-wordmark b { color: var(--azul); font-weight: inherit; }
.hero-lema {
  margin-top: var(--e3);
  color: var(--texto-3);
  font-size: clamp(.6875rem, .58rem + .3vw, .8125rem);
  font-weight: 500;
  letter-spacing: .28em;
  text-transform: uppercase;
  text-align: center;
}
.hero-lema span { color: var(--azul); }

@media (max-width: 999px) {
  .hero {
    padding-top: calc(var(--h-cab) + var(--e5));
    padding-bottom: var(--e7);
    min-height: 0;
  }
  .hero-int { grid-template-columns: 1fr; gap: var(--e6); }
  .hero-marca { order: -1; justify-self: start; align-items: flex-start; }
  .hero-lobo { width: min(62vw, 260px); }
  .hero-wordmark { margin-top: calc(var(--e4) * -1); }
  .hero-lema { text-align: left; }
  .hero-acciones { margin-top: var(--e6); }
  .hero-acciones .btn { width: 100%; }
  .hero-hechos { margin-top: var(--e5); }
  /* Mismo criterio que el hero: en pantalla angosta los CTA ocupan el ancho. */
  .cierre-acciones .btn { width: 100%; }
}

@media (max-width: 599px) {
  /* El lema entra en un renglon si se le suelta el tracking. */
  .hero-lema { letter-spacing: .15em; }
  /* Cuatro renglones limpios leen mejor que tres con viudas. */
  .hero-hechos { display: grid; grid-template-columns: 1fr; gap: var(--e3); }
}

/* --- Lineas de servicio --------------------------------------------------- */

/* Las dos lineas van apiladas, no en paralelo: nueve servicios contra tres no
   entran en dos columnas sin dejar media placa vacia, y apiladas cada linea
   toma el ancho completo y se gana su propio nodo sobre la traza. */
.servicios {
  display: grid;
  gap: clamp(20px, 2.6vw, 32px);
  padding-right: var(--canal);
  padding-bottom: var(--e9);
}

/* Bloque de una sola placa colgado de la traza: mismo canal reservado a la
   derecha que .servicios, sin la grilla de dos nodos. */
.bloque {
  padding-right: var(--canal);
  padding-bottom: var(--e9);
}

/* Placa de dos capas: el borde de 1px sobrevive al chaflan porque el contorno
   es un elemento y la superficie es otro, encajada un pixel adentro. */
.linea {
  position: relative;
  padding: 1px;
  background: linear-gradient(150deg,
      rgba(46, 108, 231, .55) 0%,
      rgba(46, 108, 231, .16) 34%,
      rgba(154, 166, 184, .13) 100%);
  clip-path: polygon(
    0 0,
    calc(100% - var(--chaflan)) 0,
    100% var(--chaflan),
    100% 100%,
    var(--chaflan) 100%,
    0 calc(100% - var(--chaflan)));
  transition: background 320ms var(--salida);
}
.linea:hover {
  background: linear-gradient(150deg,
      rgba(46, 108, 231, .9) 0%,
      rgba(46, 108, 231, .3) 34%,
      rgba(154, 166, 184, .16) 100%);
}
.linea-int {
  height: 100%;
  padding: clamp(24px, 3vw, 40px);
  background: rgba(16, 20, 27, .86);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  clip-path: polygon(
    0 0,
    calc(100% - var(--chaflan)) 0,
    100% var(--chaflan),
    100% 100%,
    var(--chaflan) 100%,
    0 calc(100% - var(--chaflan)));
}

/* El titulo despeja el chaflan superior derecho, que es por donde la traza
   entra a la placa. */
.linea-titulo {
  max-width: 24ch;
  padding-right: var(--chaflan);
  font-size: clamp(1.375rem, 1rem + 1.35vw, 1.875rem);
  line-height: 1.12;
  letter-spacing: -.028em;
}
/* Tope de medida en 90ch. El 68ch original cortaba el parrafo en 773px sobre
   990px disponibles y dejaba 217px muertos a la derecha. */
.linea-bajada {
  max-width: 90ch;
  margin-top: var(--e4);
  color: var(--texto-2);
}

/* Catalogo: una leyenda de componentes, no una grilla de tarjetas. Un glifo por
   servicio, todos en el azul de marca y con el mismo trazo. */
.catalogo {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(232px, 1fr));
  gap: var(--e5) clamp(20px, 2.4vw, 36px);
  margin-top: var(--e7);
  padding-top: var(--e6);
  box-shadow: inset 0 1px 0 var(--linea);
}
.catalogo li {
  display: flex;
  align-items: flex-start;
  gap: 14px;
}
.cat-ico {
  width: 22px;
  height: 22px;
  flex: none;
  margin-top: 2px;
  color: var(--azul);
}
.cat-txt { display: grid; gap: 3px; min-width: 0; }
.cat-nombre {
  color: var(--texto);
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.32;
  letter-spacing: -.012em;
  text-wrap: pretty;
}
.cat-cal {
  color: var(--texto-3);
  font-size: .8125rem;
  line-height: 1.4;
}

.linea .enlace-accion { margin-top: var(--e7); }

/* --- Alineacion del texto corrido ----------------------------------------- */

/* Solo las secciones marcadas con data-texto y solo su texto corrido: las
   etiquetas del catalogo quedan afuera a proposito porque viven en columnas de
   ~230px, donde justificar abre huecos enormes entre palabras.
   El partido de palabras se apoya en lang="es-AR" del <html>; sin ese atributo
   hyphens:auto no tiene diccionario y no corta nada. */
/* Bajadas: justificadas en todos los anchos. Miden 68ch en escritorio y 241px
   en celular, medida donde el partido de palabras alcanza para cerrar el
   renglon derecho sin abrir huecos. */
[data-texto="justificado"] .linea-bajada {
  text-align: justify;
  -webkit-hyphens: auto;
  hyphens: auto;
}

/* El detalle del paso se justifica en todos los anchos. Estuvo alineado a la
   izquierda en celular mientras su columna media 149px, porque ahi los espacios
   saltaban de 5.5px a 24px. Al sacarle al <ol> el relleno de 40px que le ponia
   el navegador, la columna paso a 189px y ese salto bajo a 7.8-16.2px, o sea
   dentro de lo que ya toleran las bajadas. */
[data-texto="justificado"] .paso-det {
  text-align: justify;
  -webkit-hyphens: auto;
  hyphens: auto;
}

/* --- Proceso -------------------------------------------------------------- */

/* Los pasos cuelgan de una hairline vertical: el mismo gesto de la traza, en
   chico y adentro de la placa. */
.pasos {
  display: grid;
  gap: var(--e6);
  margin-top: var(--e7);
  padding-top: var(--e6);
  box-shadow: inset 0 1px 0 var(--linea);
}
.paso {
  /* El numero manda en la fila, asi que su medida define tambien el ancho de
     la columna y donde arranca la hairline: una sola fuente de verdad. */
  --n-tam: clamp(1.75rem, 1.1rem + 2.2vw, 2.75rem);
  --n-col: calc(var(--n-tam) * 1.35);
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: clamp(14px, 1.6vw, 22px);
}
/* El tramo de hairline que une un paso con el siguiente. El ultimo no lo lleva
   para que la serie termine en el paso y no en una linea al vacio. Arranca
   debajo del numero y centrada en su columna. */
.paso:not(:last-child)::before {
  content: "";
  position: absolute;
  top: calc(var(--n-tam) + 12px);
  left: calc(var(--n-col) / 2);
  width: 1px;
  height: calc(100% + var(--e6) - var(--n-tam) - 12px);
  background: var(--linea);
}
/* Sin fondo propio: antes llevaba un --panel opaco para tapar la hairline, pero
   la linea arranca debajo del numero y nunca lo cruzo. Lo unico que hacia era
   dibujar un rectangulo plano sobre una placa translucida con blur detras, y
   ese parche desparejo era la mitad del problema de nitidez. */
.paso-n {
  flex: none;
  width: var(--n-col);
  color: var(--azul);
  font-size: var(--n-tam);
  font-weight: 700;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.02em;
}
/* flex:1 y no el 0 1 auto por defecto: como item flexible sin crecimiento, la
   columna de texto se dimensionaba a su contenido y dejaba ~200px muertos a la
   derecha del paso. El min-width:0 la deja encoger por debajo del contenido. */
.paso-txt { display: grid; flex: 1; gap: var(--e1); min-width: 0; }
.paso-nombre {
  color: var(--texto);
  font-size: 1.0625rem;
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -.014em;
}
.paso-det {
  max-width: 90ch;
  color: var(--texto-2);
  font-size: .9375rem;
  line-height: 1.5;
  text-wrap: pretty;
}

/* --- Trabajos ------------------------------------------------------------- */

/* La galeria no va adentro de una placa: despues de tres placas seguidas, las
   fotos sobre el negro cortan el ritmo y aguantan el peso solas. */
.bloque-titulo {
  font-size: clamp(1.375rem, 1rem + 1.35vw, 1.875rem);
  line-height: 1.12;
  letter-spacing: -.028em;
}
.bloque-bajada {
  max-width: 90ch;
  margin-top: var(--e4);
  color: var(--texto-2);
}
.galeria-grupo { margin-top: var(--e7); }
.galeria-cat {
  color: var(--texto-3);
  font-size: .8125rem;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
}
.galeria {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(212px, 1fr));
  gap: clamp(10px, 1.2vw, 16px);
  margin-top: var(--e4);
}
/* La foto es una placa mas: mismo chaflan, mismo hairline. El fondo queda
   visible si el archivo todavia no esta, y el alt se lee sobre el. */
.foto {
  position: relative;
  /* <figure> trae margin: 1em 40px del navegador; sin esto la foto nunca llena
     su celda y el marco cuadrado sale rectangular. */
  margin: 0;
  /* Cuadrado: las fotos vienen mezcladas, verticales de celular y apaisadas.
     Un marco 4:3 le comeria casi la mitad del alto a las verticales. */
  aspect-ratio: 1 / 1;
  overflow: hidden;
  background: var(--panel);
  box-shadow: inset 0 0 0 1px var(--linea);
  clip-path: polygon(
    0 0,
    calc(100% - var(--chaflan)) 0,
    100% var(--chaflan),
    100% 100%,
    var(--chaflan) 100%,
    0 calc(100% - var(--chaflan)));
}
.foto img {
  position: relative;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 420ms var(--salida);
}
/* Slot vacio en vez de imagen rota mientras la foto no este subida: los
   pseudo-elementos de un <img> solo se pintan cuando la carga falla, asi que
   esto desaparece solo en cuanto el archivo existe. */
.foto img::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--panel);
}
.foto:hover img { transform: scale(1.03); }

/* --- Carrusel ------------------------------------------------------------- */

/* Scroll-snap nativo: el swipe en celular y el arrastre de trackpad ya vienen
   dados por el navegador, sin librerias ni JS de gesto. El JS solo marca cual
   quedo en el centro y sincroniza los puntos. */
.carrusel {
  --card: 340px;
  /* El techo lo pone el riel en celular: por encima de 1.31 la central no entra
     en el ancho visible. 1.22 marca bien el foco y deja aire en los dos anchos. */
  --escala: 1.22;
  /* Cruce lento y parejo. --salida arranca demasiado rapido para un disolvido:
     sirve para entradas, no para un cambio de foco. */
  --disolver: cubic-bezier(.22, .61, .36, 1);
  display: flex;
  grid-template-columns: none;   /* anula la grilla de .galeria */
  gap: clamp(12px, 1.4vw, 20px);
  /* Centra la primera y la ultima: sin este relleno, los extremos nunca llegan
     al centro del riel y el snap queda corrido. */
  padding-inline: max(0px, calc(50% - var(--card) / 2));
  /* overflow-x: auto vuelve el eje vertical recortable, y la escala de la foto
     activa no ocupa lugar en el layout: sin este aire, la central se corta
     contra el borde. Se calcula sobre el marco mas alto (4:5 de CCTV) y se le
     suma el radio del halo. */
  padding-block: calc((var(--escala) - 1) / 2 * var(--card) * 1.25 + 14px);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  /* Los puntos son el indicador; la barra nativa solo ensuciaria el riel. */
  scrollbar-width: none;
}
.carrusel::-webkit-scrollbar { display: none; }
.carrusel:focus-visible { outline: 2px solid var(--azul); outline-offset: 6px; }

.carrusel > li {
  position: relative;   /* para que la activa pueda pisar a las vecinas */
  flex: 0 0 var(--card);
  scroll-snap-align: center;
  opacity: .38;
  transform: scale(.9);
  /* Las dos caras del cruce declaran la MISMA lista de funciones de filtro. Si
     una dijera solo blur() y la otra solo drop-shadow(), el navegador no puede
     interpolar entre listas distintas y el cambio saltaria de golpe. */
  filter: blur(3px) drop-shadow(0 0 0 rgba(46, 108, 231, 0));
  transition: opacity 420ms var(--disolver), transform 420ms var(--disolver),
              filter 420ms var(--disolver);
}
/* La foto en foco se enciende igual que un pad de la traza: el mismo azul y el
   mismo halo que usa .nodo.vivo, para que se lea como un tramo mas del circuito
   y no como un efecto aparte. */
.carrusel > li.activa {
  z-index: 1;
  opacity: 1;
  /* Por encima de 1, no en 1: contra vecinas en .9 el salto tiene que leerse
     de un vistazo, y la central es la que manda en la fila. */
  transform: scale(var(--escala));
  filter: blur(0px) drop-shadow(0 0 12px rgba(46, 108, 231, .42));
}
.carrusel .foto { box-shadow: inset 0 0 0 1px var(--azul-frio); }
.carrusel > li.activa .foto { box-shadow: inset 0 0 0 1px var(--azul); }

/* Flechas y puntos comparten renglon: las flechas mueven, los puntos ubican. */
.carrusel-nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--e3);
  margin-top: var(--e5);
}

/* Mismo par de estados que el filo de la foto activa y que un pad de la traza:
   azul frio en reposo, azul pleno con halo cuando se enciende. */
/* Mismo chaflan de 45 grados que las placas y las fotos: el boton es una pieza
   mas de la placa, no un control generico pegado encima. */
.flecha {
  --ch-b: 9px;
  position: relative;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  flex: none;
  padding: 0;
  border: 0;
  background: none;
  color: var(--texto-3);
  cursor: pointer;
  clip-path: polygon(
    0 0,
    calc(100% - var(--ch-b)) 0,
    100% var(--ch-b),
    100% 100%,
    var(--ch-b) 100%,
    0 calc(100% - var(--ch-b)));
  transition: color var(--rapido), filter var(--rapido);
}
/* El marco va como sombra interior porque el clip-path recorta cualquier borde. */
.flecha::before {
  content: "";
  position: absolute;
  inset: 0;
  box-shadow: inset 0 0 0 1px var(--azul-frio);
  transition: box-shadow var(--rapido);
}
/* Nodo de circuito, igual que un pad de la traza: anillo hueco, sin relleno.
   Va arriba a la izquierda porque el chaflan corta las esquinas superior
   derecha e inferior izquierda, y ahi el clip-path se lo comeria. */
.flecha::after {
  content: "";
  position: absolute;
  left: 7px;
  top: 7px;
  width: 5px;
  height: 5px;
  border: 1px solid var(--azul-frio);
  border-radius: 50%;
  transition: border-color var(--rapido), box-shadow var(--rapido);
}
.flecha .ico { position: relative; z-index: 1; }
.flecha:first-child .ico { transform: rotate(180deg); }

.flecha:hover,
.flecha:focus-visible {
  color: var(--blanco);
  filter: drop-shadow(0 0 8px rgba(46, 108, 231, .5));
}
.flecha:hover::before,
.flecha:focus-visible::before { box-shadow: inset 0 0 0 1px var(--azul); }
.flecha:hover::after,
.flecha:focus-visible::after {
  border-color: var(--azul-nucleo);
  box-shadow: 0 0 6px rgba(46, 108, 231, .9);
}

/* Barrido: una banda de luz cruza el boton una sola vez al entrar el foco. Es
   un pulso, no un brillo que se queda dando vueltas. */
.flecha .barrido {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}
.flecha .barrido::before {
  content: "";
  position: absolute;
  top: 0;
  left: -60%;
  width: 45%;
  height: 100%;
  background: linear-gradient(100deg,
      transparent 0%,
      rgba(111, 160, 255, .5) 50%,
      transparent 100%);
  transform: skewX(-18deg);
}
.flecha:hover .barrido::before,
.flecha:focus-visible .barrido::before { animation: barrido 620ms var(--salida); }
@keyframes barrido {
  from { left: -60%; }
  to   { left: 130%; }
}
.flecha:active { transform: translateY(1px); }

/* Puntos: posicion, no navegacion pesada. La tira cede y envuelve antes que
   empujar la pagina a lo ancho, por si alguna categoria crece en fotos. */
.puntos {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--e2);
  min-width: 0;
}
.punto {
  width: 22px;
  height: 22px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  display: grid;
  place-items: center;
}
.punto::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--azul-frio);
  transition: background var(--rapido), transform var(--rapido);
}
.punto[aria-current="true"]::before {
  background: var(--azul);
  transform: scale(1.34);
}
.punto:hover::before { background: var(--azul-vivo); }
.punto:focus-visible { outline: 2px solid var(--azul); outline-offset: 2px; }

/* En celular la card se calcula desde el ancho real disponible en vez de un %:
   el relleno de centrado tambien es porcentual y las dos medidas resuelven
   contra bases distintas, asi que compuestas dan una foto mucho mas chica de la
   pedida. El 0.76 deja asomando la siguiente, que es lo que avisa que desliza. */
@media (max-width: 599px) {
  .carrusel {
    --card: calc((100vw - 2 * var(--margen) - var(--canal)) * .76);
  }
  /* Con los circulos de 42px, siete puntos a medida de escritorio no entran en
     el renglon y el ultimo cae solo a una segunda fila. Se achica el area de
     toque del punto, no el punto: en celular se navega con el circulo y el
     deslizamiento, y el punto es indicador. */
  .carrusel-nav { gap: var(--e2); }
  .flecha { width: 38px; height: 38px; }
  .puntos { gap: var(--e1); }
  .punto { width: 18px; }
}

/* Las dos ultimas de CCTV son piezas de campana con el texto pegado al borde
   (abajo en una, arriba en la otra): recortarlas se lo comeria. Entran enteras
   y el marco las acompana con una relacion mas alta que el cuadrado. */
.galeria-cctv { grid-template-columns: repeat(auto-fill, minmax(232px, 1fr)); }
.galeria-cctv .foto { aspect-ratio: 4 / 5; }
.foto-pieza img { object-fit: contain; }
.foto-pieza:hover img { transform: none; }

/* --- Cierre --------------------------------------------------------------- */

.cierre-acciones {
  display: flex;
  flex-wrap: wrap;
  gap: var(--e3);
  margin-top: var(--e7);
}

/* --- Datos de contacto ---------------------------------------------------- */

.contacto-datos { margin-top: var(--e7); }
.contacto-datos a {
  color: inherit;
  text-decoration: none;
  box-shadow: inset 0 -1px 0 rgba(46, 108, 231, .5);
  transition: color var(--rapido), box-shadow var(--rapido);
}
.contacto-datos a:hover {
  color: var(--azul-nucleo);
  box-shadow: inset 0 -1px 0 var(--azul-nucleo);
}

/* --- Pie ------------------------------------------------------------------ */

/* Cierre, no seccion: no cuelga de la traza, no lleva placa ni chaflan y no
   suma ninguna pieza que no este ya en el sistema. Solo hairlines y el mismo
   negro de siempre. */
.pie {
  position: relative;
  z-index: 1;
  /* Sin margen propio: el ultimo .bloque ya cierra con --e9 de padding y
     sumarle otro tanto abre un hueco que se lee como error. */
  padding-block: var(--e7) var(--e6);
  box-shadow: inset 0 1px 0 var(--linea);
}
.pie-int,
.pie-legal {
  max-width: var(--ancho);
  margin-inline: auto;
  padding-inline: var(--margen);
}
/* Una sola columna centrada: el pie cierra en el eje de la pagina y no arma
   una grilla propia que compita con la de las secciones. */
.pie-int { text-align: center; }
/* .marca es flex y trae margin-right:auto para empujar el nav en la cabecera;
   aca no hay nada que empujar. */
.pie-int .marca {
  justify-content: center;
  margin-right: 0;
}

/* Mismo tratamiento que el lema del hero: versalita espaciada, gris, con el
   segundo tramo en azul. */
.pie-lema {
  margin-top: var(--e3);
  color: var(--texto-3);
  font-size: .6875rem;
  font-weight: 500;
  letter-spacing: .22em;
  text-transform: uppercase;
}
.pie-lema span { color: var(--azul); }

.pie-redes {
  display: flex;
  justify-content: center;
  gap: var(--e3);
  margin-top: var(--e5);
}
.pie-redes a {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 3px;
  color: var(--texto-3);
  box-shadow: inset 0 0 0 1px var(--azul-frio);
  transition: color var(--rapido), box-shadow var(--rapido);
}
.pie-redes a:hover,
.pie-redes a:focus-visible {
  color: var(--blanco);
  box-shadow: inset 0 0 0 1px var(--azul);
}

/* La hairline va como sombra interior, el mismo recurso que usa .catalogo. */
.pie-legal {
  margin-top: var(--e7);
  padding-top: var(--e6);
  color: var(--texto-3);
  font-size: .8125rem;
  text-align: center;
  box-shadow: inset 0 1px 0 var(--linea);
}
/* La firma va un escalon mas abajo en jerarquia: mas chica y en el gris apagado,
   nunca en el azul de acento, que en este sistema significa accion. */
.pie-credito {
  margin-top: var(--e2);
  color: var(--gris);
  font-size: .75rem;
}
.pie-credito a {
  color: inherit;
  text-decoration: none;
  box-shadow: inset 0 -1px 0 rgba(154, 166, 184, .4);
  transition: color var(--rapido), box-shadow var(--rapido);
}
.pie-credito a:hover {
  color: var(--texto-2);
  box-shadow: inset 0 -1px 0 var(--texto-2);
}

/* El flotante de WhatsApp vive en la esquina inferior derecha, justo donde
   termina el copyright. Se le reserva el alto del boton mas su separacion para
   que el texto legal nunca quede debajo. */
@media (max-width: 899px) {
  .pie { padding-bottom: calc(56px + var(--e5) + var(--e6) + env(safe-area-inset-bottom, 0px)); }
}

/* --- WhatsApp flotante (solo celular) ------------------------------------- */

/* No existe boton de subir al tope en el sitio, asi que la esquina inferior
   derecha esta libre y no hay que negociar el lugar con nadie. */
.wa-flota {
  position: fixed;
  right: var(--margen);
  /* safe-area: en iPhone la barra de gestos se come el borde inferior. */
  bottom: calc(var(--e5) + env(safe-area-inset-bottom, 0px));
  z-index: 60;
  display: none;
  place-items: center;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: var(--azul);
  color: var(--ink);
  box-shadow: 0 10px 26px -10px rgba(0, 0, 0, .8);
  transition: opacity 260ms var(--salida), transform 260ms var(--salida);
}
.wa-flota .ico { width: 26px; height: 26px; }

/* Aparece recien cuando el hero salio de pantalla. Mientras el hero se ve, su
   propio boton de WhatsApp esta a la vista y el flotante solo taparia el CTA
   secundario. El JS pone .visible; sin JS queda siempre visible. */
.js .wa-flota {
  opacity: 0;
  transform: scale(.8);
  pointer-events: none;
}
.js .wa-flota.visible {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}
/* Con el menu abierto se va: no compite con la navegacion. */
.js .wa-flota.oculta { opacity: 0; transform: scale(.8); pointer-events: none; }
.wa-flota:active { transform: scale(.94); }

/* El anillo respira aparte del boton: late cada 2.6s y descansa el resto. Un
   glow permanente a full termina siendo ruido y se deja de ver.
   El tramo animado sube a 28% para que el destello siga durando ~0.73s: si se
   dejaba en 12%, acortar el ciclo tambien aceleraba el destello y pasaba a
   leerse como un parpadeo nervioso en vez de una respiracion. */
.wa-flota::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  box-shadow: 0 0 0 0 rgba(46, 108, 231, .55);
  animation: latido-wa 2.6s var(--salida) 1.2s infinite;
}
@keyframes latido-wa {
  0%      { box-shadow: 0 0 0 0 rgba(46, 108, 231, .55); }
  28%     { box-shadow: 0 0 0 14px rgba(46, 108, 231, 0); }
  100%    { box-shadow: 0 0 0 0 rgba(46, 108, 231, 0); }
}

@media (max-width: 899px) {
  .wa-flota { display: grid; }
}

/* --- Movimiento ----------------------------------------------------------- */

/* El contenido es visible por defecto: la entrada solo existe si hay JS. */
.js .entra { opacity: 0; transform: translateY(12px); }
.js .entra.dentro {
  opacity: 1;
  transform: none;
  transition: opacity 700ms var(--salida) var(--retraso, 0ms),
              transform 700ms var(--salida) var(--retraso, 0ms);
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    transition-duration: .001ms !important;
  }
  .js .entra { opacity: 1; transform: none; }
  .traza-viva, .traza-halo { stroke-dashoffset: 0; }
  .traza-pads .pad-brazo { stroke-dashoffset: 0; }
  /* El salto del carrusel es instantaneo y las fotos de al lado no se achican:
     el foco queda solo en el borde azul, sin escala, blur ni desvanecido. */
  .carrusel { scroll-behavior: auto; }
  .carrusel > li { opacity: 1; transform: none; filter: none; }
}
