/*==============================================================
  DaIA — main3.css
  Rediseño v2.0 · sin dependencias (ni Bootstrap, ni AOS, ni Swiper)

  Índice
    01. Tokens
    02. Reset
    03. Layout (wrap, section, grid)
    04. Tipografía
    05. Botones y enlaces
    06. Iconos
    07. Header y navegación
    08. Hero
    09. Ventanas de video (lazy)
    10. Stats / contadores
    11. Diagnóstico (orbes clickeables)
    12. Ejes de dolor
    13. Productos (showcase)
    14. Shells de demo (Fase B)
    14b. Soluciones por industria
    15. Servicios
    16. Método
    17. Casos y testimonios (carrusel)
    18. Equipo
    19. FAQ
    20. Contacto y formulario
    21. Footer
    22. Modal
    23. Flotantes (WhatsApp, scroll-top)
    24. Página interior (política de privacidad)
    25. Animaciones de entrada y reduced-motion
    26. Manufactura — Command Center (landing de conversión)
    27. Manufactura — capa de movimiento (fondo, cursor, gráficos)
    28. Enterprise — Command Center (landing de conversión)
    29. Enterprise — capa de superficie (puntero y scroll)
    30. Enterprise — sectores, validación social y cuestionario
    31. Enterprise — Footer
    32. Enterprise — Galería de tutoriales en video
    33. Aviso de Privacidad — marcador de datos pendientes
    34. Enterprise — franja de sistemas del bloque de solución
    35. Enterprise — cierre orientado a conversión
    36. Enterprise — botón de WhatsApp
    37. Enterprise — formulario de un solo paso
==============================================================*/


/*--------------------------------------------------------------
# 01. Tokens
--------------------------------------------------------------*/
:root {
  /* Marca */
  --bg:           #070708;
  --bg-alt:       #0a0a0c;
  --surface:      #131317;
  --surface-2:    #1f1f23;
  --line:         rgba(255, 255, 255, .09);
  --line-strong:  rgba(255, 255, 255, .18);

  --accent:       #575AFF;          /* violeta DaIA */
  --accent-hi:    #7A7CFF;
  --accent-soft:  rgba(87, 90, 255, .14);
  --accent-2:     #22D3EE;          /* cyan heredado de los orbes */
  --accent-2-soft: rgba(34, 211, 238, .12);

  --heading:      #ffffff;
  --text:         rgba(255, 255, 255, .74);
  --text-dim:     rgba(255, 255, 255, .48);
  --on-accent:    #ffffff;

  /* Tipografía */
  --font-head: "Montserrat", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-body: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;

  --step--1: clamp(.8rem,  .77rem + .15vw,  .875rem);
  --step-0:  clamp(.95rem, .91rem + .2vw,   1.05rem);
  --step-1:  clamp(1.1rem, 1.03rem + .35vw, 1.3rem);
  --step-2:  clamp(1.35rem, 1.2rem + .7vw,  1.75rem);
  --step-3:  clamp(1.7rem, 1.45rem + 1.2vw, 2.4rem);
  --step-4:  clamp(2.1rem, 1.7rem + 2vw,    3.4rem);
  --step-5:  clamp(2.5rem, 1.9rem + 3vw,    4.5rem);

  /* Espaciado — escala 4/8 */
  --sp-1: .25rem;  --sp-2: .5rem;   --sp-3: .75rem;  --sp-4: 1rem;
  --sp-5: 1.5rem;  --sp-6: 2rem;    --sp-7: 2.5rem;  --sp-8: 3rem;
  --sp-9: 4rem;    --sp-10: 5rem;   --sp-11: 6.5rem; --sp-12: 8rem;

  /* Geometría y movimiento */
  --radius:    12px;
  --radius-lg: 20px;
  --radius-pill: 999px;
  --wrap:      1200px;
  --wrap-pad:  clamp(1rem, 4vw, 2.5rem);

  --dur:  .3s;
  --dur-slow: .6s;
  --ease: cubic-bezier(.4, 0, .2, 1);

  --shadow:    0 1px 2px rgba(0, 0, 0, .4), 0 8px 24px rgba(0, 0, 0, .3);
  --shadow-lg: 0 24px 64px rgba(0, 0, 0, .55);

  --header-h: 76px;

  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + 1rem);
  color-scheme: dark;
}

/* Superficie alterna, para intercalar secciones sin cambiar el markup */
.section--alt {
  --bg: var(--bg-alt);
  --surface: #17171c;
  background: var(--bg);
}


/*--------------------------------------------------------------
# 02. Reset
--------------------------------------------------------------*/
*, *::before, *::after { box-sizing: border-box; }

* { margin: 0; }

/* `clip` y no `hidden`: hidden convierte al elemento en contenedor de scroll
   y rompe el position:sticky del header. clip solo recorta.
   Necesario porque el panel de nav off-canvas vive desplazado fuera de pantalla. */
html {
  -webkit-text-size-adjust: 100%;
  overflow-x: clip;
}

body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: var(--step-0);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;
}

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

input, button, textarea, select { font: inherit; color: inherit; }

button { background: none; border: 0; cursor: pointer; }

ul, ol { list-style: none; padding: 0; }

a { color: var(--accent); text-decoration: none; transition: color var(--dur) var(--ease); }
a:hover { color: var(--accent-hi); }

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

/* Salto al contenido, para lectores de pantalla y teclado */
.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 999;
  padding: var(--sp-3) var(--sp-5);
  background: var(--accent);
  color: var(--on-accent);
  border-radius: 0 0 var(--radius) 0;
}
.skip-link:focus { left: 0; color: var(--on-accent); }

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}


/*--------------------------------------------------------------
# 03. Layout
--------------------------------------------------------------*/
.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--wrap-pad);
}
.wrap--narrow { max-width: 860px; }

.section {
  padding-block: clamp(3.5rem, 8vw, var(--sp-12));
  position: relative;
}

/* Grid genérica: se controla con --cols y --gap desde el componente */
.grid {
  display: grid;
  gap: var(--gap, var(--sp-5));
  grid-template-columns: repeat(var(--cols, 1), minmax(0, 1fr));
}
@media (min-width: 700px)  { .grid { grid-template-columns: repeat(var(--cols-md, var(--cols, 1)), minmax(0, 1fr)); } }
@media (min-width: 1000px) { .grid { grid-template-columns: repeat(var(--cols-lg, var(--cols-md, var(--cols, 1))), minmax(0, 1fr)); } }

/* Encabezado de sección */
.section-head {
  max-width: 760px;
  margin-bottom: var(--sp-9);
}
.section-head--center { margin-inline: auto; text-align: center; }

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-family: var(--font-body);
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--accent-hi);
  margin-bottom: var(--sp-4);
}
.eyebrow::before {
  content: "";
  width: 24px;
  height: 1px;
  background: currentColor;
  opacity: .6;
}
.section-head--center .eyebrow::before { display: none; }

.section-head p {
  margin-top: var(--sp-4);
  font-size: var(--step-1);
  color: var(--text-dim);
  max-width: 62ch;
}
.section-head--center p { margin-inline: auto; }

/* Ritmo vertical para bloques de texto sueltos que no viven en .section-head */
.flow > * + * { margin-top: var(--sp-4); }
.flow > .eyebrow + * { margin-top: var(--sp-2); }
.flow > * + .btn,
.flow > * + .diagnostico__hint { margin-top: var(--sp-6); }


/*--------------------------------------------------------------
# 04. Tipografía
--------------------------------------------------------------*/
h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-head);
  color: var(--heading);
  line-height: 1.15;
  font-weight: 700;
  letter-spacing: -.02em;
  text-wrap: balance;
}

h1 { font-size: var(--step-5); }
h2 { font-size: var(--step-4); }
h3 { font-size: var(--step-2); }
h4 { font-size: var(--step-1); }

p { text-wrap: pretty; }

strong { color: var(--heading); font-weight: 600; }

.lead {
  font-size: var(--step-1);
  color: var(--text);
  max-width: 60ch;
}


/*--------------------------------------------------------------
# 05. Botones
--------------------------------------------------------------*/
.btn {
  --btn-bg: transparent;
  --btn-fg: var(--heading);
  --btn-bd: var(--line-strong);

  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
  padding: .8rem 1.5rem;
  border: 1px solid var(--btn-bd);
  border-radius: var(--radius-pill);
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-family: var(--font-body);
  font-size: var(--step-0);
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
  cursor: pointer;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease),
              color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.btn:hover { transform: translateY(-2px); color: var(--btn-fg); }
.btn:active { transform: translateY(0); }

.btn--primary {
  --btn-bg: var(--accent);
  --btn-bd: var(--accent);
  --btn-fg: var(--on-accent);
}
.btn--primary:hover { --btn-bg: var(--accent-hi); --btn-bd: var(--accent-hi); }

.btn--ghost:hover { --btn-bg: rgba(255, 255, 255, .06); --btn-bd: var(--line-strong); }

.btn--soft {
  --btn-bg: var(--accent-soft);
  --btn-bd: transparent;
  --btn-fg: var(--accent-hi);
}
.btn--soft:hover { --btn-bg: rgba(87, 90, 255, .22); }

.btn--sm { padding: .5rem 1rem; font-size: var(--step--1); gap: var(--sp-2); }
.btn--block { width: 100%; justify-content: center; }

/* Flecha circular — el gesto de CTA que se repite en toda la página */
.btn__arrow {
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 1px solid currentColor;
  flex-shrink: 0;
  transition: transform var(--dur) var(--ease);
}
.btn__arrow svg { width: 11px; height: 11px; }
.btn:hover .btn__arrow { transform: translateX(3px); }

/* Enlace de texto con flecha */
.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-weight: 600;
  color: var(--accent-hi);
}
.link-arrow svg { width: 14px; height: 14px; transition: transform var(--dur) var(--ease); }
.link-arrow:hover svg { transform: translateX(4px); }


/*--------------------------------------------------------------
# 06. Iconos
--------------------------------------------------------------*/
.icon {
  /* inline-block y no el display:block del reset: así un icono suelto dentro
     de un título o un párrafo no se cae a su propia línea. En contenedores
     flex o grid el navegador lo blockifica igual, así que no cambia nada ahí. */
  display: inline-block;
  vertical-align: middle;
  width: 1em;
  height: 1em;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex-shrink: 0;
}
.icon--fill { fill: currentColor; stroke: none; }

/* Caja de icono, reutilizada en dolores, servicios, método y contacto */
.icon-box {
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  border-radius: var(--radius);
  background: var(--accent-soft);
  color: var(--accent-hi);
  font-size: 24px;
  flex-shrink: 0;
}


/*--------------------------------------------------------------
# 07. Header y navegación
--------------------------------------------------------------*/
.header {
  position: sticky;
  top: 0;
  z-index: 100;
  height: var(--header-h);
  display: flex;
  align-items: center;
  border-bottom: 1px solid transparent;
  transition: border-color var(--dur) var(--ease);
}

/* El tinte y el desenfoque van en un pseudo-elemento y NO en .header.

   El motivo no es cosmetico: un elemento con backdrop-filter distinto
   de none se convierte en bloque contenedor de sus descendientes
   position:fixed. El panel de navegacion mobile (.nav) es fixed y vive
   dentro del header, asi que se anclaba al header en lugar del
   viewport: con inset de var(--header-h) sobre una caja de 76px de
   alto, la altura resuelta daba 0 y del panel solo quedaban los 80px
   de su propio padding. Los enlaces caian fuera y el overflow-y los
   recortaba: el menu se abria mostrando un solo item.

   Con el filtro en ::before, .header vuelve a ser un elemento comun y
   .nav se ancla al viewport. El aspecto no cambia: el mismo tinte y el
   mismo blur, pintados en la misma posicion. */
.header::before {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(7, 7, 8, .72);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  transition: background var(--dur) var(--ease);
  pointer-events: none;
}
/* Por encima de la capa de desenfoque. position:relative no crea
   bloque contenedor para fixed, asi que .nav sigue anclado al
   viewport. */
.header__inner { position: relative; z-index: 1; }

body.is-scrolled .header { border-bottom-color: var(--line); }
body.is-scrolled .header::before { background: rgba(7, 7, 8, .92); }

.header__inner {
  display: flex;
  align-items: center;
  gap: var(--sp-5);
}

.header__logo { margin-right: auto; display: flex; align-items: center; }
.header__logo img { height: 38px; width: auto; }

.nav__list {
  display: flex;
  align-items: center;
  gap: var(--sp-6);
}
.nav__list a {
  position: relative;
  color: var(--text);
  font-size: var(--step--1);
  font-weight: 500;
  letter-spacing: .01em;
  padding-block: var(--sp-2);
}
.nav__list a::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 2px;
  border-radius: 2px;
  background: var(--accent);
  transform: scaleX(0);
  transition: transform var(--dur) var(--ease);
}
.nav__list a:hover,
.nav__list a.is-active { color: var(--heading); }
.nav__list a.is-active::after { transform: scaleX(1); }

.header__cta { flex-shrink: 0; }

/* El CTA dentro del panel solo existe en mobile: en desktop está el del header */
.nav__cta { display: none; }

.nav__toggle {
  display: none;
  width: 44px;
  height: 44px;
  place-items: center;
  color: var(--heading);
  font-size: 26px;
  border-radius: var(--radius);
}

@media (max-width: 980px) {
  .nav__toggle { display: grid; order: 3; }
  .header__cta { display: none; }

  .nav {
    position: fixed;
    inset: var(--header-h) 0 0 auto;
    width: min(340px, 86vw);
    padding: var(--sp-7) var(--sp-6);
    background: var(--bg-alt);
    border-left: 1px solid var(--line);
    transform: translateX(100%);
    transition: transform var(--dur) var(--ease);
    overflow-y: auto;
  }
  body.nav-open .nav { transform: translateX(0); }

  .nav__list {
    flex-direction: column;
    align-items: stretch;
    gap: var(--sp-1);
  }
  .nav__list a {
    display: block;
    padding: var(--sp-4) var(--sp-2);
    font-size: var(--step-1);
    border-bottom: 1px solid var(--line);
  }
  .nav__list a::after { display: none; }
  .nav__list a.is-active { color: var(--accent-hi); }

  .nav__cta { display: flex; margin-top: var(--sp-6); }

  /* Velo detrás del panel */
  body.nav-open::after {
    content: "";
    position: fixed;
    inset: var(--header-h) 0 0 0;
    background: rgba(0, 0, 0, .6);
    z-index: 99;
  }
  body.nav-open { overflow: hidden; }
}

/* Redes en el header, solo desktop */
.header__social { display: flex; gap: var(--sp-3); }
.header__social a {
  display: grid;
  place-items: center;
  width: 34px; height: 34px;
  border-radius: 50%;
  border: 1px solid var(--line);
  color: var(--text-dim);
  font-size: 15px;
}
.header__social a:hover { color: var(--heading); border-color: var(--accent); }
@media (max-width: 1180px) { .header__social { display: none; } }


/*--------------------------------------------------------------
# 08. Hero
--------------------------------------------------------------*/
.hero {
  position: relative;
  padding-block: clamp(3rem, 7vw, var(--sp-11)) clamp(3rem, 6vw, var(--sp-10));
  overflow: hidden;
}
.hero::before {
  content: "";
  position: absolute;
  top: -20%; left: 50%;
  width: min(1100px, 130vw);
  aspect-ratio: 1;
  transform: translateX(-50%);
  background: radial-gradient(circle, var(--accent-soft) 0%, transparent 62%);
  pointer-events: none;
}

.hero__inner {
  position: relative;
  display: grid;
  gap: var(--sp-9);
  align-items: center;
}
@media (min-width: 1000px) {
  .hero__inner { grid-template-columns: minmax(0, 6fr) minmax(0, 5fr); gap: var(--sp-8); }
}

.hero__badge {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: .4rem .9rem .4rem .5rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--surface);
  font-size: var(--step--1);
  color: var(--text);
  margin-bottom: var(--sp-5);
}
.hero__badge b { color: var(--heading); font-weight: 600; }
.hero__badge-dot {
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--accent-2);
  box-shadow: 0 0 0 4px var(--accent-2-soft);
  margin-left: var(--sp-2);
}

.hero h1 { margin-bottom: var(--sp-5); }
.hero h1 em {
  font-style: normal;
  color: var(--accent-hi);
}

.hero__lead {
  font-size: var(--step-1);
  color: var(--text);
  max-width: 54ch;
  margin-bottom: var(--sp-7);
}

.hero__ctas {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  margin-bottom: var(--sp-7);
}

/* Accesos a los subdominios: Automatizar, Ser Partner, Influencer IA, Showcase */
.hero__links {
  padding-top: var(--sp-6);
  border-top: 1px solid var(--line);
}
.hero__links-label {
  display: block;
  margin-bottom: var(--sp-3);
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--text-dim);
}
.hero__links-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
}
.hero__links-row .icon { font-size: 16px; color: var(--accent-hi); }


/*--------------------------------------------------------------
# 09. Ventanas de video (lazy)
--------------------------------------------------------------*/
.video-frame {
  position: relative;
  aspect-ratio: 16 / 10;
  border-radius: var(--radius-lg);
  border: 1px solid var(--line);
  background:
    linear-gradient(135deg, rgba(87, 90, 255, .1), transparent 55%),
    var(--surface);
  overflow: hidden;
  box-shadow: var(--shadow-lg);
}

.video-frame__poster {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  opacity: .5;
}

.video-frame__body {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: var(--sp-4);
  padding: var(--sp-6);
  text-align: center;
}

.video-frame__play {
  position: relative; /* ancla el anillo del ::before */
  display: grid;
  place-items: center;
  width: 68px; height: 68px;
  border-radius: 50%;
  border: 1px solid var(--line-strong);
  background: rgba(10, 10, 12, .6);
  backdrop-filter: blur(6px);
  color: var(--heading);
  font-size: 26px;
  transition: transform var(--dur) var(--ease), background var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}
.video-frame__play::before {
  content: "";
  position: absolute;
  width: 68px; height: 68px;
  border-radius: 50%;
  border: 1px solid var(--accent);
  animation: video-ping 2.6s var(--ease) infinite;
}
@keyframes video-ping {
  0%   { transform: scale(1);   opacity: .7; }
  100% { transform: scale(1.9); opacity: 0;  }
}
.video-frame__play:hover {
  transform: scale(1.08);
  background: var(--accent);
  border-color: var(--accent);
}

.video-frame__label {
  font-family: var(--font-head);
  font-weight: 600;
  color: var(--heading);
  font-size: var(--step-0);
}
.video-frame__note {
  font-size: var(--step--1);
  color: var(--text-dim);
}

/* Estado sin video cargado todavía */
.video-frame[data-state="pending"] .video-frame__play {
  cursor: not-allowed;
  opacity: .55;
}
.video-frame[data-state="pending"] .video-frame__play::before { animation: none; }

/* Una vez inyectado el video real */
.video-frame__media {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  border: 0;
  object-fit: cover;
}


/*--------------------------------------------------------------
# 10. Stats / contadores
--------------------------------------------------------------*/
.stats {
  display: grid;
  gap: var(--sp-5);
  grid-template-columns: repeat(2, minmax(0, 1fr));
  margin-top: var(--sp-10);
  padding-top: var(--sp-8);
  border-top: 1px solid var(--line);
}
@media (min-width: 800px) { .stats { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.stat__value {
  font-family: var(--font-head);
  font-size: var(--step-4);
  font-weight: 700;
  color: var(--heading);
  line-height: 1;
  letter-spacing: -.03em;
}
.stat__value span { color: var(--accent-hi); }

.stat__label {
  margin-top: var(--sp-2);
  font-size: var(--step--1);
  color: var(--text-dim);
}


/*--------------------------------------------------------------
# 11. Diagnóstico — orbes clickeables
  Se conserva el efecto orbital heredado, pero cada orbe es un
  <button> que abre el modal de diagnóstico.
--------------------------------------------------------------*/
.diagnostico {
  position: relative;
  overflow: hidden;
  background: var(--bg-alt);
}

.diagnostico__inner {
  display: grid;
  gap: var(--sp-9);
  align-items: center;
}
/* El anillo exterior mide 510px + el radio de los orbes: la columna izquierda
   necesita ~570px o los orbes se montan sobre el texto de la derecha. */
@media (min-width: 1000px) {
  .diagnostico__inner {
    grid-template-columns: minmax(0, 6fr) minmax(0, 5fr);
    gap: var(--sp-10);
  }
}

.orbit {
  position: relative;
  display: grid;
  place-items: center;
  min-height: 540px;
}
.orbit::before {
  content: "";
  position: absolute;
  width: 700px; height: 700px;
  max-width: 130vw;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(34, 211, 238, .06) 0%, transparent 68%);
  pointer-events: none;
}

.orbit__stage {
  position: relative;
  width: 540px;
  height: 540px;
}

/* Pulsos concéntricos */
.orbit__pulse {
  position: absolute;
  top: 50%; left: 50%;
  width: 120px; height: 120px;
  border-radius: 50%;
  border: 1px solid rgba(34, 211, 238, .45);
  transform: translate(-50%, -50%) scale(.5);
  animation: orbit-pulse 4s ease-out infinite;
  pointer-events: none;
}
.orbit__pulse:nth-child(2) { animation-delay: -1.33s; }
.orbit__pulse:nth-child(3) { animation-delay: -2.66s; }

@keyframes orbit-pulse {
  0%   { transform: translate(-50%, -50%) scale(.5);  opacity: .7; }
  100% { transform: translate(-50%, -50%) scale(3.2); opacity: 0;  }
}

/* Centro */
.orbit__center {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  z-index: 20;
  display: grid;
  place-items: center;
  pointer-events: none;
}
.orbit__glow {
  position: absolute;
  width: 140px; height: 140px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(34, 211, 238, .18) 0%, transparent 70%);
  animation: orbit-breathe 3s ease-in-out infinite;
}
@keyframes orbit-breathe {
  0%, 100% { transform: scale(1);   opacity: .7; }
  50%      { transform: scale(1.4); opacity: 1;  }
}

@property --orbit-angle {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: false;
}
.orbit__ring-glow {
  position: absolute;
  width: 114px; height: 114px;
  border-radius: 50%;
  border: 2px solid transparent;
  background:
    linear-gradient(var(--bg-alt), var(--bg-alt)) padding-box,
    conic-gradient(from var(--orbit-angle), var(--accent-2) 0%, transparent 40%,
                   var(--accent-2) 80%, transparent 100%) border-box;
  box-shadow: 0 0 24px rgba(34, 211, 238, .45), inset 0 0 16px rgba(34, 211, 238, .08);
  animation: orbit-spin 7s linear infinite;
}
@keyframes orbit-spin { to { --orbit-angle: 360deg; } }

/* Sin soporte de @property el gradiente cónico no anima: borde plano */
@supports not (background: conic-gradient(from var(--orbit-angle), red, blue)) {
  .orbit__ring-glow {
    border: 2px solid var(--accent-2);
    background: var(--bg-alt);
    animation: none;
  }
}

.orbit__logo {
  position: relative;
  z-index: 21;
  width: 62px; height: 62px;
  object-fit: contain;
}

/* Anillos.
   pointer-events:none es obligatorio: el anillo externo mide 510px y, al ser
   un div posterior en el DOM, tapaba por completo los 6 orbes del anillo
   interno y los volvía imposibles de clickear con el mouse. */
.orbit__ring {
  position: absolute;
  top: 50%; left: 50%;
  border-radius: 50%;
  border: 1px solid rgba(34, 211, 238, .09);
  pointer-events: none;
}
.orbit__ring--inner { width: 310px; height: 310px; margin: -155px; }
.orbit__ring--outer { width: 510px; height: 510px; margin: -255px; }

/* Cada orbe: ahora es un botón real */
.orb {
  position: absolute;
  top: 50%; left: 50%;
  width: 52px; height: 52px;
  margin: -26px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: rgba(5, 5, 8, .85);
  border: 1.5px solid rgba(34, 211, 238, .6);
  box-shadow: 0 0 14px rgba(34, 211, 238, .34), inset 0 0 10px rgba(34, 211, 238, .08);
  color: var(--accent-2);
  font-size: 20px;
  cursor: pointer;
  pointer-events: auto; /* el anillo contenedor los desactiva */
  transition: box-shadow var(--dur) var(--ease), border-color var(--dur) var(--ease),
              color var(--dur) var(--ease);
}
.orb:hover,
.orb:focus-visible {
  border-color: var(--accent-2);
  color: #fff;
  box-shadow: 0 0 30px rgba(34, 211, 238, .95), inset 0 0 14px rgba(34, 211, 238, .25);
  z-index: 30;
}

/* ---- Micro-interacciones ----
   El transform del orbe está tomado por la animación orbital, así que el
   movimiento se hace sobre el glifo y sobre dos pseudo-elementos. */

/* Latido de reposo: escalonado por --i, para que se lean como clickeables */
.orb::before {
  content: "";
  position: absolute;
  inset: -1px;
  border-radius: 50%;
  border: 1px solid currentColor;
  opacity: 0;
  animation: orb-idle 3.4s var(--ease) infinite;
  animation-delay: calc(var(--i, 0) * -.45s);
  pointer-events: none;
}
@keyframes orb-idle {
  0%, 70%, 100% { opacity: 0; }
  35%           { opacity: .45; }
}

/* Anillo que se abre al pasar por encima */
.orb::after {
  content: "";
  position: absolute;
  inset: -5px;
  border-radius: 50%;
  border: 1px solid currentColor;
  opacity: 0;
  transform: scale(.82);
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
  pointer-events: none;
}
.orb:hover::after,
.orb:focus-visible::after { opacity: .55; transform: scale(1); }

/* El glifo crece al pasar y se hunde al apretar */
.orb .icon {
  position: relative;
  z-index: 1;
  transition: transform var(--dur) var(--ease);
}
.orb:hover .icon,
.orb:focus-visible .icon { transform: scale(1.18); }
.orb:active .icon { transform: scale(.88); }

/* Al abrir su modal el orbe queda marcado hasta que el usuario siga navegando */
.orb.is-open {
  border-color: var(--accent-2);
  color: #fff;
  box-shadow: 0 0 30px rgba(34, 211, 238, .8);
}
.orb--ai.is-open {
  border-color: var(--accent-hi);
  box-shadow: 0 0 30px rgba(87, 90, 255, .8);
}

/* Los motores de IA se distinguen en violeta de los canales en cyan */
.orb--ai {
  border-color: var(--accent);
  color: var(--accent-hi);
  box-shadow: 0 0 16px rgba(87, 90, 255, .45), inset 0 0 10px rgba(87, 90, 255, .1);
}
.orb--ai:hover,
.orb--ai:focus-visible {
  border-color: var(--accent-hi);
  color: #fff;
  box-shadow: 0 0 32px rgba(87, 90, 255, .95), inset 0 0 14px rgba(87, 90, 255, .28);
}

.orbit__ring--inner .orb {
  animation: orbit-cw 22s linear infinite;
  animation-delay: calc(var(--i, 0) * -22s / var(--n, 6));
}
.orbit__ring--outer .orb {
  animation: orbit-ccw 38s linear infinite;
  animation-delay: calc(var(--i, 0) * -38s / var(--n, 10));
}

@keyframes orbit-cw {
  from { transform: rotate(0deg)   translateY(-155px) rotate(0deg);    }
  to   { transform: rotate(360deg) translateY(-155px) rotate(-360deg); }
}
@keyframes orbit-ccw {
  from { transform: rotate(0deg)    translateY(-255px) rotate(0deg);   }
  to   { transform: rotate(-360deg) translateY(-255px) rotate(360deg); }
}

/* Pausa al pasar el mouse o al navegar con teclado: hace clickeable el orbe.
   Se usa :focus-visible y NO :focus-within: al cerrar el modal el foco vuelve
   al orbe que lo abrió (correcto para accesibilidad), y con :focus-within eso
   dejaba la órbita congelada para siempre. */
.orbit__stage:hover .orb,
.orbit__stage:has(.orb:focus-visible) .orb { animation-play-state: paused; }

/* Etiqueta flotante del orbe */
.orb__tip {
  position: absolute;
  bottom: calc(100% + 10px);
  left: 50%;
  transform: translateX(-50%);
  padding: .3rem .7rem;
  border-radius: var(--radius-pill);
  background: var(--surface-2);
  border: 1px solid var(--line);
  color: var(--heading);
  font-size: .72rem;
  font-weight: 600;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur) var(--ease);
}
.orb:hover .orb__tip,
.orb:focus-visible .orb__tip { opacity: 1; }

@media (max-width: 1240px) { .orbit__stage { transform: scale(.86); } .orbit { min-height: 500px; } }
@media (max-width: 1100px) { .orbit__stage { transform: scale(.8);  } .orbit { min-height: 460px; } }
@media (max-width: 560px)  { .orbit__stage { transform: scale(.56); } .orbit { min-height: 340px; } }

/* Texto de la sección */
.diagnostico__hint {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
  margin-top: var(--sp-6);
  padding: var(--sp-3) var(--sp-5);
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius);
  font-size: var(--step--1);
  color: var(--text-dim);
}
.diagnostico__hint .icon { color: var(--accent-2); font-size: 18px; }


/*--------------------------------------------------------------
# 11b. Stack — franja infinita de herramientas
  El track contiene la lista dos veces; la animación lo mueve
  -50%, así el punto de reinicio coincide exactamente y el loop
  no tiene costura.
--------------------------------------------------------------*/
.stack {
  padding-block: var(--sp-9);
  border-block: 1px solid var(--line);
  background: var(--bg);
  overflow: hidden;
}

.stack__title {
  text-align: center;
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin-bottom: var(--sp-6);
}

.stack__note {
  margin-top: var(--sp-6);
  text-align: center;
  font-size: var(--step--1);
  color: var(--text-dim);
}

.marquee {
  overflow: hidden;
  /* Difumina los bordes para que las fichas entren y salgan sin cortarse */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
}
.marquee + .marquee { margin-top: var(--sp-4); }

.marquee__track {
  display: flex;
  width: max-content;
  gap: var(--sp-4);
  padding-block: var(--sp-1);
  animation: marquee 46s linear infinite;
}
.marquee--reverse .marquee__track {
  animation-duration: 58s;
  animation-direction: reverse;
}

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

/* Pausa al pasar el mouse: deja leer los nombres */
.marquee:hover .marquee__track { animation-play-state: paused; }

.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
  flex-shrink: 0;
  padding: .6rem 1.15rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--surface);
  color: var(--text);
  font-size: var(--step--1);
  font-weight: 600;
  white-space: nowrap;
  transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.chip:hover { border-color: var(--accent); color: var(--heading); }
.chip .icon { font-size: 19px; color: var(--accent-hi); }

/* Sin animación: la franja pasa a ser una grilla estática legible */
@media (prefers-reduced-motion: reduce) {
  .marquee { -webkit-mask-image: none; mask-image: none; }
  .marquee__track {
    animation: none;
    flex-wrap: wrap;
    width: 100%;
    justify-content: center;
    padding-inline: var(--wrap-pad);
  }
  /* La copia duplicada solo existe para el loop: sin animación, sobra */
  .marquee__track .chip[aria-hidden="true"] { display: none; }
}


/*--------------------------------------------------------------
# 12. Ejes de dolor
--------------------------------------------------------------*/
.pain-card {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  padding: var(--sp-6);
  height: 100%;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--surface);
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease),
              transform var(--dur) var(--ease);
}
.pain-card:hover {
  border-color: var(--accent);
  background: var(--surface-2);
  transform: translateY(-4px);
}
.pain-card h3 { font-size: var(--step-1); }
.pain-card p { font-size: var(--step-0); color: var(--text-dim); flex-grow: 1; }
.pain-card .link-arrow { font-size: var(--step--1); }


/*--------------------------------------------------------------
# 13. Productos (showcase)
  Layout de Adrián: izquierda = dolor, derecha = producto,
  abajo a la derecha = ventana de video.
--------------------------------------------------------------*/
.products { display: grid; gap: clamp(3rem, 7vw, var(--sp-11)); }

.product {
  display: grid;
  gap: var(--sp-6);
  padding-top: clamp(2rem, 5vw, var(--sp-9));
  border-top: 1px solid var(--line);
}
.product:first-child { border-top: 0; padding-top: 0; }

@media (min-width: 1000px) {
  .product {
    grid-template-columns: repeat(12, minmax(0, 1fr));
    column-gap: var(--sp-7);
    row-gap: var(--sp-8);
    align-items: start;
  }
  .product__pain     { grid-column: 1 / 6;  }
  .product__solution { grid-column: 6 / 13; }
  .product__demo     { grid-column: 1 / 9;  }
  .product__video    { grid-column: 9 / 13; align-self: end; }
}

/* Columna izquierda: el dolor */
.product__pain {
  position: relative;
  padding-left: var(--sp-6);
  border-left: 2px solid var(--accent);
}
.product__index {
  display: block;
  font-family: var(--font-head);
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: .12em;
  color: var(--accent-hi);
  margin-bottom: var(--sp-3);
}
.product__pain-title {
  font-size: var(--step-2);
  color: var(--heading);
  margin-bottom: var(--sp-4);
}
.product__pain p { color: var(--text-dim); }

.product__pain-tag {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  margin-top: var(--sp-5);
  padding: .3rem .8rem;
  border-radius: var(--radius-pill);
  background: var(--accent-soft);
  color: var(--accent-hi);
  font-size: var(--step--1);
  font-weight: 600;
}

/* Columna derecha: el producto */
.product__name {
  font-size: var(--step-3);
  margin-bottom: var(--sp-4);
}
.product__desc { color: var(--text); margin-bottom: var(--sp-6); max-width: 56ch; }

.product__features {
  display: grid;
  gap: var(--sp-4);
  margin-bottom: var(--sp-6);
}
@media (min-width: 640px) { .product__features { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.product__features li {
  display: flex;
  gap: var(--sp-3);
  align-items: flex-start;
  font-size: var(--step-0);
  color: var(--text);
}
.product__features .icon {
  color: var(--accent-2);
  font-size: 18px;
  margin-top: .25em;
}

.product__ctas { display: flex; flex-wrap: wrap; gap: var(--sp-3); }


/*--------------------------------------------------------------
# 14. Shells de demo (Fase B)
  Cada [data-demo] queda como marco estático. main3.js monta el
  demo interactivo si hay uno registrado con ese nombre.
--------------------------------------------------------------*/
.demo {
  position: relative;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background:
    linear-gradient(180deg, rgba(255, 255, 255, .03), transparent 40%),
    var(--surface);
  overflow: hidden;
  min-height: 320px;
}

/* Barra superior tipo ventana de aplicación */
.demo__chrome {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-5);
  border-bottom: 1px solid var(--line);
  background: rgba(0, 0, 0, .25);
}
.demo__dots { display: flex; gap: 6px; }
.demo__dots span {
  width: 10px; height: 10px;
  border-radius: 50%;
  background: var(--line-strong);
}
.demo__title {
  font-size: var(--step--1);
  font-weight: 600;
  color: var(--text-dim);
  font-family: var(--font-body);
}
.demo__badge {
  margin-left: auto;
  padding: .15rem .6rem;
  border-radius: var(--radius-pill);
  background: var(--accent-2-soft);
  color: var(--accent-2);
  font-size: .7rem;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
}

.demo__body {
  display: grid;
  place-content: center;
  justify-items: center;
  gap: var(--sp-4);
  padding: var(--sp-9) var(--sp-6);
  text-align: center;
  min-height: 260px;
}
.demo__body .icon-box { background: rgba(255, 255, 255, .04); color: var(--text-dim); }
.demo__body p { color: var(--text-dim); font-size: var(--step--1); max-width: 40ch; }

/* Esqueleto animado, para que el shell no se lea como un error */
.demo__skeleton {
  display: grid;
  gap: var(--sp-3);
  width: min(360px, 100%);
}
.demo__skeleton span {
  height: 10px;
  border-radius: var(--radius-pill);
  background: linear-gradient(90deg,
    rgba(255, 255, 255, .04) 0%,
    rgba(255, 255, 255, .09) 50%,
    rgba(255, 255, 255, .04) 100%);
  background-size: 200% 100%;
  animation: demo-shimmer 1.8s linear infinite;
}
.demo__skeleton span:nth-child(2) { width: 78%; animation-delay: .15s; }
.demo__skeleton span:nth-child(3) { width: 56%; animation-delay: .3s;  }

@keyframes demo-shimmer {
  from { background-position: 200% 0; }
  to   { background-position: -200% 0; }
}


/*--------------------------------------------------------------
# 14b. Soluciones por industria
  Los 5 productos ensamblados en verticales reales (Axia,
  Farmacia.AI, aegle). Cada tarjeta lleva su ventana de video.
--------------------------------------------------------------*/
.vertical {
  display: flex;
  flex-direction: column;
  height: 100%;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--surface);
  overflow: hidden;
  transition: border-color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.vertical:hover { border-color: var(--accent); transform: translateY(-4px); }

/* La ventana de video se integra al borde superior de la tarjeta */
.vertical__video {
  border: 0;
  border-bottom: 1px solid var(--line);
  border-radius: 0;
  box-shadow: none;
  aspect-ratio: 16 / 9;
  flex-shrink: 0;
}
.vertical__video .video-frame__play { width: 54px; height: 54px; font-size: 20px; }
.vertical__video .video-frame__play::before { width: 54px; height: 54px; }
.vertical__video .video-frame__body { gap: var(--sp-3); padding: var(--sp-5); }

.vertical__body {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  padding: var(--sp-6);
  flex-grow: 1;
}

.vertical__industry {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  align-self: flex-start;
  padding: .25rem .7rem;
  border-radius: var(--radius-pill);
  background: var(--accent-soft);
  color: var(--accent-hi);
  font-size: var(--step--1);
  font-weight: 600;
}
.vertical__industry .icon { font-size: 15px; }

.vertical h3 { font-size: var(--step-2); }
.vertical > .vertical__body > p { color: var(--text-dim); font-size: var(--step-0); }

.vertical__features {
  display: grid;
  gap: var(--sp-2);
  margin-block: var(--sp-2);
  flex-grow: 1;
}
.vertical__features li {
  display: flex;
  gap: var(--sp-3);
  align-items: flex-start;
  font-size: var(--step--1);
  color: var(--text);
}
.vertical__features .icon {
  color: var(--accent-2);
  font-size: 15px;
  margin-top: .3em;
}


/*--------------------------------------------------------------
# 15. Servicios
  Sección separada de producto, como pide el brief.
--------------------------------------------------------------*/
.service-card {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  height: 100%;
  padding: var(--sp-6);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--surface);
  transition: border-color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.service-card:hover { border-color: var(--line-strong); transform: translateY(-4px); }
.service-card h3 { font-size: var(--step-1); }
.service-card p { color: var(--text-dim); font-size: var(--step-0); flex-grow: 1; }

.service-card__num {
  font-family: var(--font-head);
  font-size: var(--step--1);
  font-weight: 700;
  color: var(--text-dim);
  letter-spacing: .1em;
}

/* Aclaración producto vs servicio */
.split-note {
  display: grid;
  gap: var(--sp-5);
  padding: var(--sp-6);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--accent-soft);
  margin-bottom: var(--sp-8);
}
@media (min-width: 800px) { .split-note { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* El icono va al costado en su caja, como en el resto de las tarjetas.
   Suelto dentro del <h4> caía en su propia línea (el reset hace svg
   display:block) y quedaba flotando sin relación con el título. */
.split-note__item { display: flex; gap: var(--sp-4); align-items: flex-start; }
.split-note__item .icon-box { width: 44px; height: 44px; font-size: 21px; background: rgba(255, 255, 255, .06); }
.split-note h4 { font-size: var(--step-1); margin-bottom: var(--sp-2); }
.split-note p { font-size: var(--step-0); color: var(--text); }


/*--------------------------------------------------------------
# 16. Método
--------------------------------------------------------------*/
.steps { counter-reset: step; }

.step {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  height: 100%;
  padding: var(--sp-6);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--surface);
}
.step__num {
  font-family: var(--font-head);
  font-size: var(--step-3);
  font-weight: 700;
  color: var(--accent);
  line-height: 1;
  opacity: .7;
}
.step h3 { font-size: var(--step-1); }
.step p { font-size: var(--step-0); color: var(--text-dim); }
.step__free {
  align-self: flex-start;
  padding: .2rem .7rem;
  border-radius: var(--radius-pill);
  background: var(--accent-2-soft);
  color: var(--accent-2);
  font-size: var(--step--1);
  font-weight: 600;
}


/*--------------------------------------------------------------
# 17. Casos y testimonios
--------------------------------------------------------------*/
.case-card {
  display: flex;
  flex-direction: column;
  height: 100%;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--surface);
  overflow: hidden;
  transition: border-color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.case-card:hover { border-color: var(--accent); transform: translateY(-4px); }

.case-card__media {
  position: relative;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  background: var(--surface-2);
  flex-shrink: 0; /* la media nunca se comprime aunque la tarjeta estire */
}
.case-card__media img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform var(--dur-slow) var(--ease);
}
.case-card:hover .case-card__media img { transform: scale(1.05); }

.case-card__tag {
  position: absolute;
  top: var(--sp-4); left: var(--sp-4);
  padding: .25rem .7rem;
  border-radius: var(--radius-pill);
  background: rgba(7, 7, 8, .82);
  backdrop-filter: blur(6px);
  border: 1px solid var(--line);
  font-size: .72rem;
  font-weight: 600;
  color: var(--heading);
}

.case-card__body {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  padding: var(--sp-5);
  flex-grow: 1;
}
.case-card__body h3 { font-size: var(--step-1); }
.case-card__body p { font-size: var(--step-0); color: var(--text-dim); flex-grow: 1; }

.case-card__metric {
  font-family: var(--font-head);
  font-size: var(--step-2);
  font-weight: 700;
  color: var(--accent-hi);
  line-height: 1;
}
.case-card__metric small {
  display: block;
  font-family: var(--font-body);
  font-size: var(--step--1);
  font-weight: 400;
  color: var(--text-dim);
  margin-top: var(--sp-1);
}

/* Carrusel — reemplaza a Swiper con scroll-snap nativo */
/* CTA de cierre de sección */
.section-cta {
  display: flex;
  justify-content: center;
  margin-top: var(--sp-8);
}

/* Testimonios */
.quote {
  display: flex;
  flex-direction: column;
  gap: var(--sp-5);
  height: 100%;
  padding: var(--sp-6);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--surface);
}
.quote__text { color: var(--text); flex-grow: 1; }
.quote__text::before {
  content: "\201C";
  display: block;
  font-family: var(--font-head);
  font-size: 3rem;
  line-height: .6;
  color: var(--accent);
  margin-bottom: var(--sp-3);
}
.quote__stars { display: flex; gap: 2px; color: #F5B301; font-size: 15px; }

.quote__author { display: flex; align-items: center; gap: var(--sp-3); }
.quote__author img {
  width: 46px; height: 46px;
  border-radius: 50%;
  object-fit: cover;
  border: 1px solid var(--line);
}
.quote__author h4 { font-size: var(--step-0); }
.quote__author span { font-size: var(--step--1); color: var(--text-dim); }

/* Franja de logos de clientes */
.logos {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--sp-4) var(--sp-7);
  padding-block: var(--sp-7);
  border-block: 1px solid var(--line);
}
.logos span {
  font-family: var(--font-head);
  font-size: var(--step-0);
  font-weight: 600;
  color: var(--text-dim);
  letter-spacing: -.01em;
  transition: color var(--dur) var(--ease);
}
.logos span:hover { color: var(--heading); }


/*--------------------------------------------------------------
# 18. Equipo
--------------------------------------------------------------*/
.member {
  display: flex;
  flex-direction: column;
  height: 100%;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--surface);
  overflow: hidden;
  transition: border-color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.member:hover { border-color: var(--accent); transform: translateY(-4px); }

.member__photo {
  aspect-ratio: 1;
  overflow: hidden;
  background: var(--surface-2);
}
.member__photo img {
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: center top;
  filter: grayscale(1);
  transition: filter var(--dur-slow) var(--ease), transform var(--dur-slow) var(--ease);
}
.member:hover .member__photo img { filter: grayscale(0); transform: scale(1.04); }

.member__body { padding: var(--sp-5); }
.member__body h3 { font-size: var(--step-0); }
.member__role {
  display: block;
  margin-top: var(--sp-1);
  font-size: var(--step--1);
  color: var(--accent-hi);
  font-weight: 600;
}
.member__body p {
  margin-top: var(--sp-3);
  font-size: var(--step--1);
  color: var(--text-dim);
}


/*--------------------------------------------------------------
# 19. FAQ
--------------------------------------------------------------*/
.faq { display: grid; gap: var(--sp-3); }

.faq__item {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  overflow: hidden;
  transition: border-color var(--dur) var(--ease);
}
.faq__item:has(.faq__q[aria-expanded="true"]) { border-color: var(--accent); }

.faq__q {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  width: 100%;
  padding: var(--sp-5);
  text-align: left;
  font-family: var(--font-head);
  font-size: var(--step-1);
  font-weight: 600;
  color: var(--heading);
  line-height: 1.35;
}
.faq__q .icon { color: var(--accent); font-size: 20px; }
.faq__q-text { flex-grow: 1; }

.faq__chevron {
  transition: transform var(--dur) var(--ease);
  color: var(--text-dim);
  font-size: 18px;
}
.faq__q[aria-expanded="true"] .faq__chevron { transform: rotate(180deg); color: var(--accent); }

.faq__a {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--dur) var(--ease);
}
.faq__a > div { overflow: hidden; }
.faq__item.is-open .faq__a { grid-template-rows: 1fr; }

.faq__a p {
  padding: 0 var(--sp-5) var(--sp-5) calc(var(--sp-5) + 20px + var(--sp-4));
  color: var(--text-dim);
}


/*--------------------------------------------------------------
# 20. Contacto y formulario
--------------------------------------------------------------*/
.contact__grid {
  display: grid;
  gap: var(--sp-7);
}
@media (min-width: 980px) {
  .contact__grid { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); }
}

.info-card {
  display: flex;
  gap: var(--sp-4);
  padding: var(--sp-5);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
}
.info-card h4 { font-size: var(--step-0); margin-bottom: var(--sp-1); }
.info-card p, .info-card a { font-size: var(--step--1); color: var(--text-dim); }
.info-card a:hover { color: var(--accent-hi); }

.contact__cards { display: grid; gap: var(--sp-4); }

.form {
  display: grid;
  gap: var(--sp-4);
  padding: var(--sp-6);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--surface);
}
@media (min-width: 620px) {
  .form { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .field--full, .form__foot, .form__status { grid-column: 1 / -1; }
}

.field { display: grid; gap: var(--sp-2); }
.field label {
  font-size: var(--step--1);
  font-weight: 600;
  color: var(--text);
}
.field input,
.field textarea {
  width: 100%;
  padding: .8rem 1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--heading);
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.field input::placeholder,
.field textarea::placeholder { color: var(--text-dim); }
.field input:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--surface-2);
}
.field textarea { resize: vertical; min-height: 140px; }

.form__status {
  display: none;
  padding: var(--sp-4);
  border-radius: var(--radius);
  font-size: var(--step--1);
  font-weight: 600;
}
.form__status[data-state="loading"] { display: block; background: var(--surface-2); color: var(--text); }
.form__status[data-state="error"]   { display: block; background: rgba(223, 21, 41, .14); color: #FF8B96; border: 1px solid rgba(223, 21, 41, .4); }
.form__status[data-state="ok"]      { display: block; background: rgba(5, 150, 82, .14);  color: #4ADE80; border: 1px solid rgba(5, 150, 82, .4); }

.map {
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
  aspect-ratio: 16 / 7;
  margin-bottom: var(--sp-5);
}
.map iframe { width: 100%; height: 100%; border: 0; }

.social-row { display: flex; gap: var(--sp-3); }
.social-row a {
  display: grid;
  place-items: center;
  width: 42px; height: 42px;
  border-radius: 50%;
  border: 1px solid var(--line);
  color: var(--text-dim);
  font-size: 17px;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease),
              background var(--dur) var(--ease);
}
.social-row a:hover { color: var(--heading); border-color: var(--accent); background: var(--accent-soft); }


/*--------------------------------------------------------------
# 21. Footer
--------------------------------------------------------------*/
.footer {
  padding-block: var(--sp-9) var(--sp-6);
  border-top: 1px solid var(--line);
  background: var(--bg-alt);
}

.footer__grid {
  display: grid;
  gap: var(--sp-7);
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  margin-bottom: var(--sp-8);
}

.footer h4 {
  font-size: var(--step-0);
  margin-bottom: var(--sp-4);
}
.footer p, .footer li, .footer a { font-size: var(--step--1); color: var(--text-dim); }
.footer a:hover { color: var(--accent-hi); }
.footer li + li { margin-top: var(--sp-2); }

.footer__bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  padding-top: var(--sp-6);
  border-top: 1px solid var(--line);
  font-size: var(--step--1);
  color: var(--text-dim);
}

.kommo-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
  padding: .4rem .9rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  color: var(--text-dim);
}
.kommo-badge:hover { border-color: var(--line-strong); color: var(--heading); }
/* El logo de Kommo es un wordmark 132×28: se respeta esa proporción
   o el texto queda aplastado. En espacios chicos se usa #i-kommo. */
.kommo-badge img {
  width: 76px;
  height: auto;
  aspect-ratio: 132 / 28;
  object-fit: contain;
  filter: brightness(0) invert(1);
  opacity: .85;
}


/*--------------------------------------------------------------
# 22. Modal (diagnóstico y video)
--------------------------------------------------------------*/
.modal {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  place-items: center;
  padding: var(--sp-5);
  background: rgba(3, 3, 5, .82);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--dur) var(--ease), visibility var(--dur) var(--ease);
}
.modal.is-open { opacity: 1; visibility: visible; }

.modal__panel {
  position: relative; /* ancla el botón de cerrar */
  width: min(620px, 100%);
  max-height: min(85vh, 760px);
  overflow-y: auto;
  padding: var(--sp-7);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg);
  background: var(--surface);
  box-shadow: var(--shadow-lg);
  transform: translateY(16px) scale(.98);
  transition: transform var(--dur) var(--ease);
}
.modal.is-open .modal__panel { transform: translateY(0) scale(1); }
.modal--wide .modal__panel { width: min(960px, 100%); padding: var(--sp-5); }

.modal__close {
  position: absolute;
  top: var(--sp-5); right: var(--sp-5);
  display: grid;
  place-items: center;
  width: 40px; height: 40px;
  border-radius: 50%;
  border: 1px solid var(--line);
  color: var(--heading);
  font-size: 20px;
  background: var(--surface);
}
.modal__close:hover { background: var(--surface-2); border-color: var(--line-strong); }

.modal__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--accent-hi);
  margin-bottom: var(--sp-3);
}
.modal__title { font-size: var(--step-2); margin-bottom: var(--sp-3); }
.modal__lead { color: var(--text-dim); margin-bottom: var(--sp-6); }

/* Preguntas de diagnóstico */
.diag__q {
  font-family: var(--font-head);
  font-weight: 600;
  color: var(--heading);
  margin-bottom: var(--sp-4);
}
.diag__options { display: grid; gap: var(--sp-3); margin-bottom: var(--sp-5); }

.diag__option {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  width: 100%;
  padding: var(--sp-4) var(--sp-5);
  text-align: left;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--text);
  font-size: var(--step-0);
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease),
              color var(--dur) var(--ease);
}
.diag__option:hover {
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--heading);
}
.diag__option .icon { color: var(--accent-hi); }

.diag__progress {
  display: flex;
  gap: var(--sp-2);
  margin-bottom: var(--sp-6);
}
.diag__progress span {
  height: 3px;
  flex: 1;
  border-radius: var(--radius-pill);
  background: var(--line);
  transition: background var(--dur) var(--ease);
}
.diag__progress span.is-done { background: var(--accent); }

/* Resultado del diagnóstico */
.diag__result {
  padding: var(--sp-6);
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  background: var(--accent-soft);
  margin-bottom: var(--sp-5);
}
.diag__result h4 { font-size: var(--step-1); margin-bottom: var(--sp-2); }
.diag__result p { color: var(--text); font-size: var(--step-0); }

.diag__actions { display: flex; flex-wrap: wrap; gap: var(--sp-3); }

/* Modal de integración (los logos que orbitan) */
.tool__head {
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  margin-bottom: var(--sp-5);
  padding-right: var(--sp-9); /* deja lugar al botón de cerrar */
}
.tool__head .modal__eyebrow { margin-bottom: var(--sp-1); }
.tool__head .modal__title { margin-bottom: 0; }

.tool__mark {
  display: grid;
  place-items: center;
  width: 64px; height: 64px;
  flex-shrink: 0;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: var(--bg);
  color: var(--accent-hi);
}
.tool__glyph { font-size: 32px; }

.tool__uses {
  display: grid;
  gap: var(--sp-3);
  margin-bottom: var(--sp-6);
}
.tool__uses li {
  display: flex;
  gap: var(--sp-3);
  align-items: flex-start;
  font-size: var(--step-0);
  color: var(--text);
}
.tool__uses .icon { color: var(--accent-2); font-size: 17px; margin-top: .3em; flex-shrink: 0; }


/*--------------------------------------------------------------
# 23. Flotantes
--------------------------------------------------------------*/
.wa-float {
  position: fixed;
  right: 20px; bottom: 20px;
  z-index: 90;
  display: grid;
  place-items: center;
  width: 56px; height: 56px;
  border-radius: 50%;
  background: #25D366;
  color: #fff;
  box-shadow: 0 8px 24px rgba(37, 211, 102, .38);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.wa-float:hover {
  transform: scale(1.08);
  color: #fff;
  box-shadow: 0 12px 32px rgba(37, 211, 102, .55);
}
.wa-float svg { width: 28px; height: 28px; fill: currentColor; stroke: none; }

.wa-float__tip {
  position: absolute;
  right: calc(100% + 12px);
  white-space: nowrap;
  padding: .4rem .8rem;
  border-radius: var(--radius);
  background: var(--surface-2);
  border: 1px solid var(--line);
  color: var(--heading);
  font-size: var(--step--1);
  font-weight: 600;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur) var(--ease);
}
.wa-float:hover .wa-float__tip { opacity: 1; }

.scroll-top {
  position: fixed;
  right: 20px; bottom: 88px;
  z-index: 90;
  display: grid;
  place-items: center;
  width: 44px; height: 44px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--on-accent);
  font-size: 20px;
  opacity: 0;
  visibility: hidden;
  transform: translateY(8px);
  transition: opacity var(--dur) var(--ease), visibility var(--dur) var(--ease),
              transform var(--dur) var(--ease);
}
.scroll-top.is-visible { opacity: 1; visibility: visible; transform: translateY(0); }
.scroll-top:hover { background: var(--accent-hi); color: var(--on-accent); }


/*--------------------------------------------------------------
# 24. Página interior (política de privacidad)
--------------------------------------------------------------*/
.page-head {
  padding-block: var(--sp-9) var(--sp-7);
  border-bottom: 1px solid var(--line);
  background: var(--bg-alt);
}
.breadcrumb {
  display: flex;
  gap: var(--sp-2);
  font-size: var(--step--1);
  color: var(--text-dim);
  margin-top: var(--sp-4);
}

.prose { max-width: 74ch; }
.prose h2 {
  font-size: var(--step-2);
  margin-top: var(--sp-8);
  margin-bottom: var(--sp-4);
}
.prose h2:first-child { margin-top: 0; }
.prose h3 {
  font-size: var(--step-1);
  margin-top: var(--sp-6);
  margin-bottom: var(--sp-3);
}
.prose p, .prose li { margin-bottom: var(--sp-4); }
.prose ul { list-style: disc; padding-left: 1.4rem; margin-bottom: var(--sp-5); }
.prose li { margin-bottom: var(--sp-2); }
.prose li::marker { color: var(--accent); }


/*--------------------------------------------------------------
# 25. Animaciones de entrada y reduced-motion
  Reemplaza a AOS: main3.js agrega .is-in vía IntersectionObserver.
--------------------------------------------------------------*/
[data-reveal] {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity var(--dur-slow) var(--ease), transform var(--dur-slow) var(--ease);
  transition-delay: var(--reveal-delay, 0ms);
}
[data-reveal].is-in { opacity: 1; transform: none; }

[data-reveal="zoom"]  { transform: scale(.94); }
[data-reveal="left"]  { transform: translateX(-24px); }
[data-reveal="right"] { transform: translateX(24px); }

/* Si el usuario no tiene JS, nunca se agrega .is-in: el contenido debe verse igual */
.no-js [data-reveal] { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  [data-reveal] { opacity: 1; transform: none; }
  .orb, .orbit__pulse, .orbit__glow, .orbit__ring-glow { animation: none !important; }
  .orb::before { animation: none !important; opacity: 0; }
  .video-frame__play::before { animation: none !important; }
  .demo__skeleton span { animation: none !important; }
}

/* Impresión */
@media print {
  .header, .nav, .wa-float, .scroll-top, .modal, .demo { display: none !important; }
  body { background: #fff; color: #000; }
}


/*--------------------------------------------------------------
# 26. Manufactura — Command Center (landing de conversión)

  Todo lo de acá abajo es aditivo: no pisa ninguna regla de las
  secciones 01–25. La landing de manufactura reutiliza .btn,
  .icon-box, .section-head, .pain-card, .form, .field, .header,
  .footer y .video-frame tal cual están definidos arriba.

  Regla de acentos de esta landing:
    --accent   (violeta) → marca, CTAs, navegación
    --accent-2 (cyan)    → datos, dashboards, métricas de mejora
    --danger   (rojo)    → SOLO el diagnóstico del dolor
--------------------------------------------------------------*/

/* --- 26.1 Tokens ------------------------------------------- */
:root {
  --danger:      #DF1529;
  --danger-hi:   #FF8B96;          /* el rojo puro sobre fondo oscuro no llega a AA */
  --danger-soft: rgba(223, 21, 41, .12);
}

/* Números como material tipográfico: mismo tratamiento en toda la página */
.num {
  font-family: var(--font-head);
  font-weight: 700;
  line-height: 1;
  letter-spacing: -.03em;
  font-variant-numeric: tabular-nums;
}


/* Logo de marca + bajada de línea de producto. El alto lo fija
   .header__logo img (sección 07); acá solo va el sufijo. */
.logo-sub {
  margin-left: var(--sp-3);
  padding-left: var(--sp-3);
  border-left: 1px solid var(--line-strong);
  font-family: var(--font-head);
  font-weight: 600;
  font-size: var(--step--1);
  letter-spacing: .04em;
  color: var(--text-dim);
  white-space: nowrap;
}
@media (max-width: 420px) { .logo-sub { display: none; } }


/* --- 26.1b Diagrama del hero -------------------------------- */
/* Placeholder honesto mientras no está la foto del operador: muestra la
   arquitectura real (tres orígenes → un centro), no un mockup decorativo. */
.hero-diagram {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.hero-diagram text {
  font-family: var(--font-body);
  font-size: 15px;
  fill: var(--text);
}
.hero-diagram__node rect {
  fill: rgba(255, 255, 255, .03);
  stroke: var(--line-strong);
}
.hero-diagram__node text {
  font-family: var(--font-head);
  font-weight: 700;
  letter-spacing: .1em;
  text-anchor: middle;
  fill: var(--heading);
}
.hero-diagram__core rect { fill: rgba(19, 19, 23, .9); stroke: var(--accent-2); stroke-opacity: .5; }
.hero-diagram__core-kicker {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .18em;
  fill: #22D3EE;
}
.hero-diagram__core-num {
  font-family: var(--font-head);
  font-size: 34px;
  font-weight: 700;
  fill: var(--heading);
}
.hero-diagram__core-sub { font-size: 12px; fill: var(--text-dim); }
.hero-diagram__bar-bg  { fill: rgba(255, 255, 255, .1); stroke: none; }
.hero-diagram__bar-val { fill: #22D3EE; stroke: none; }

/* Coincide con el viewBox del diagrama (640×338): el SVG llena el marco
   sin bandas arriba y abajo. Si se reemplaza por la foto del operador,
   este valor vuelve al 16/10 de .video-frame. */
.hero .video-frame { aspect-ratio: 640 / 338; }

@media (max-width: 620px) {
  /* Como inline-flex, al no entrar en una línea el badge parte en dos
     columnas y "Integración / nativa" queda apilado contra el resto del
     texto. Como bloque, fluye como una frase normal. */
  .hero__badge { display: block; }
  .hero__badge-dot { display: inline-block; vertical-align: middle; }
}


/* --- 26.2 Barra de confianza -------------------------------- */
.trust-bar {
  padding-block: var(--sp-8);
  border-block: 1px solid var(--line);
  background: var(--bg);
}

/* Alineado a la izquierda y no centrado: el bloque de filas arranca en el
   eje del label, y un título centrado sobre él se lee fuera de registro. */
.trust-bar__title {
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin-bottom: var(--sp-7);
}

/* Estática a propósito: es información de confianza, no un elemento
   de movimiento. El carrusel infinito vive en #11b Stack.

   Un grupo por fila y no tres columnas: ERP tiene cinco sistemas y CRM
   dos, así que en columnas siempre queda una corta y otra en tres filas.
   En filas, el ancho sobrante es del grupo que lo necesita. */
/* 860px = label (150) + gap (40) + los cinco sistemas de ERP, que es la
   fila más larga. Así ERP llena el ancho exacto y los otros dos grupos
   quedan alineados contra el mismo eje izquierdo. */
.trust-rows,
.trust-bar__title {
  max-width: 860px;
  margin-inline: auto;
}

.trust-row {
  display: grid;
  gap: var(--sp-4);
  align-items: center;
}
@media (min-width: 760px) {
  /* 168px: lo que mide "DATOS DE PLANTA" en versalitas espaciadas. Con
     menos, ese label cae a dos líneas y desentona con ERP y CRM. */
  .trust-row { grid-template-columns: 168px minmax(0, 1fr); gap: var(--sp-6); }
}
.trust-row + .trust-row {
  margin-top: var(--sp-6);
  padding-top: var(--sp-6);
  border-top: 1px solid var(--line);
}

.trust-row__label {
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--text-dim);
}

.trust-items {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-5);
}

/* Placa + nombre. La placa iguala el peso visual de logos que de origen
   tienen formas y densidades muy distintas: sin ella, el óvalo de Oracle
   y las cuatro barras de Power BI no se leen como la misma familia. */
.trust-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-3);
  width: 104px;
  text-align: center;
}

.trust-item__mark {
  display: grid;
  place-items: center;
  width: 64px;
  height: 64px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--heading);
  font-size: 34px;
  opacity: .6;
  filter: grayscale(1);
  transition: opacity var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.trust-item:hover .trust-item__mark {
  opacity: 1;
  border-color: var(--line-strong);
}
/* A 34px un stroke de 1.75 se ve endeble: el glifo tiene que sostener
   la placa, no flotar adentro. */
.trust-item__mark .icon { stroke-width: 1.6; }

/* Cuando lleguen los SVG oficiales entran acá y heredan la misma placa */
.trust-item__mark img {
  width: 38px;
  height: 38px;
  object-fit: contain;
}

/* Dos líneas reservadas: "SAP Business One" ocupa dos y "Oracle" una,
   y sin el alto mínimo la fila se desalinea entera. */
.trust-item__name {
  min-height: calc(2 * 1.3em);
  font-size: var(--step--1);
  font-weight: 600;
  line-height: 1.3;
  color: var(--text-dim);
  transition: color var(--dur) var(--ease);
}
.trust-item:hover .trust-item__name { color: var(--text); }


/* --- 26.3 Diagnóstico del dolor ----------------------------- */
/* El ícono en rojo solo acá: marca "esto te cuesta plata", no "esto instalamos" */
.pain-card--alert .icon-box {
  background: var(--danger-soft);
  color: var(--danger-hi);
}
.pain-card--alert:hover { border-color: var(--danger); }

/* Dos de los tres títulos ocupan dos líneas y uno una sola: sin el alto
   mínimo, los párrafos arrancan a tres alturas distintas y las tarjetas
   se leen como componentes diferentes en vez de como una serie. */
.pain-card--alert h3 { min-height: calc(2 * 1.15em); }

/* Métrica destacada full-width: el argumento financiero de la sección */
.metric-hero {
  display: grid;
  gap: var(--sp-5);
  align-items: center;
  margin-bottom: var(--sp-8);
  padding: clamp(1.5rem, 4vw, var(--sp-8));
  border: 1px solid var(--line);
  border-left: 3px solid var(--danger);
  border-radius: var(--radius-lg);
  background:
    linear-gradient(100deg, var(--danger-soft), transparent 45%),
    var(--surface);
}
@media (min-width: 900px) {
  .metric-hero { grid-template-columns: auto minmax(0, 1fr); column-gap: var(--sp-8); }
}

.metric-hero__num {
  font-size: var(--step-5);
  color: var(--accent-2);
  white-space: nowrap;
}
.metric-hero__num small {
  display: block;
  margin-top: var(--sp-2);
  font-family: var(--font-body);
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--text-dim);
}

.metric-hero__text {
  font-size: var(--step-2);
  font-family: var(--font-head);
  font-weight: 600;
  color: var(--heading);
  line-height: 1.25;
  text-wrap: balance;
}
.metric-hero__source {
  margin-top: var(--sp-4);
  font-size: var(--step--1);
  color: var(--text-dim);
}


/* --- 26.4 Bento de dashboards ------------------------------- */
/* Mobile: una columna, y las dos tarjetas grandes primero. El orden
   sigue el impacto financiero (OEE e inventario), no la grilla. */
.dash-bento {
  display: grid;
  gap: var(--sp-5);
  grid-template-areas:
    "oee"
    "inv"
    "pipeline"
    "scorecard";
}
@media (min-width: 780px) {
  .dash-bento {
    grid-template-columns: 3fr 2fr;
    grid-template-areas:
      "oee pipeline"
      "inv scorecard";
  }
}
.dash-card--oee       { grid-area: oee; }
.dash-card--inv       { grid-area: inv; }
.dash-card--pipeline  { grid-area: pipeline; }
.dash-card--scorecard { grid-area: scorecard; }

.dash-card {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  padding: var(--sp-6);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background:
    linear-gradient(180deg, rgba(255, 255, 255, .025), transparent 40%),
    var(--surface);
  transition: border-color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
/* Mismo gesto que .pain-card pero con el acento de datos, no el de alerta */
.dash-card:hover { border-color: var(--accent-2); transform: translateY(-4px); }

/* Las dos grandes cargan los dos dolores más caros: se les da más aire
   y un título un escalón mayor, no solo más ancho de grilla. */
@media (min-width: 780px) {
  .dash-card--lg { padding: var(--sp-7); }
  .dash-card--lg h3 { font-size: var(--step-2); }
  .dash-card--lg .icon-box { width: 52px; height: 52px; font-size: 24px; }
}

.dash-card__head { display: flex; align-items: flex-start; gap: var(--sp-4); }
.dash-card .icon-box {
  width: 42px; height: 42px;
  font-size: 20px;
  background: var(--accent-2-soft);
  color: var(--accent-2);
}
.dash-card__eyebrow {
  display: block;
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--accent-2);
  margin-bottom: var(--sp-2);
}
.dash-card h3 { font-size: var(--step-1); }
.dash-card__desc { font-size: var(--step-0); color: var(--text-dim); }

/* El visual va abajo y absorbe el alto sobrante: las dos tarjetas de
   cada fila terminan alineadas aunque el texto mida distinto. */
.dash-card__visual {
  margin-top: auto;
  padding-top: var(--sp-5);
  border-top: 1px solid var(--line);
}

/* Los tableros no son capturas: se manipulan. Esta franja es lo que
   separa "te mandamos un reporte" de "entrás y filtrás vos". */
.dash-dynamic {
  display: grid;
  gap: var(--sp-4) var(--sp-5);
  align-items: center;
  margin-top: var(--sp-5);
  padding: var(--sp-5) var(--sp-6);
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent-2);
  border-radius: var(--radius-lg);
  background:
    linear-gradient(100deg, var(--accent-2-soft), transparent 42%),
    var(--surface);
}
@media (min-width: 900px) {
  .dash-dynamic { grid-template-columns: auto minmax(0, 1fr) auto; }
}

.dash-dynamic .icon-box {
  background: var(--accent-2-soft);
  color: var(--accent-2);
}

.dash-dynamic__text {
  font-size: var(--step-0);
  color: var(--text);
}
.dash-dynamic__text strong { color: var(--heading); }

.dash-dynamic__chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2) var(--sp-4);
}
.dash-dynamic__chips li {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--step--1);
  font-weight: 600;
  color: var(--text-dim);
  white-space: nowrap;
}
.dash-dynamic__chips .icon { font-size: 16px; color: var(--accent-2); }

.dash-note {
  margin-top: var(--sp-6);
  font-size: var(--step--1);
  color: var(--text-dim);
  text-align: center;
}

/* Visual 1 — OEE: una barra partida en tres segmentos reales */
.oee { display: grid; gap: var(--sp-4); }
.oee__total {
  display: flex;
  align-items: baseline;
  gap: var(--sp-3);
}
.oee__total .num { font-size: var(--step-3); color: var(--accent-2); }
.oee__total span { font-size: var(--step--1); color: var(--text-dim); }

/* El gap tiene que ser generoso: con 3px los labels de dos segmentos
   contiguos se tocan y se leen como una sola frase. */
.oee__bar { display: flex; gap: var(--sp-4); }
/* En pantallas chicas ni con gap alcanza: tres segmentos de ~130px no
   entran "Disponibilidad" + "91.4%". Se apilan uno por fila. */
@media (max-width: 640px) {
  .oee__bar { flex-direction: column; gap: var(--sp-3); }
}
.oee__seg { flex: 1; min-width: 0; }
.oee__track {
  height: 10px;
  border-radius: 3px;
  background: rgba(255, 255, 255, .07);
  overflow: hidden;
}
.oee__fill {
  height: 100%;
  width: var(--pct, 0%);
  border-radius: 3px;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
}
/* El segmento que arrastra el OEE hacia abajo se lee distinto */
.oee__seg--low .oee__fill { background: linear-gradient(90deg, var(--danger), var(--danger-hi)); }

.oee__meta {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--sp-2);
  margin-top: var(--sp-2);
}
.oee__label { font-size: var(--step--1); color: var(--text-dim); }
.oee__val   { font-size: var(--step--1); color: var(--heading); font-variant-numeric: tabular-nums; }
.oee__seg--low .oee__val { color: var(--danger-hi); }

/* Visual 2 — DIO: gauge semicircular + alerta de stock */
.gauge { display: flex; align-items: center; gap: var(--sp-6); flex-wrap: wrap; }
.gauge__chart { width: 170px; flex-shrink: 0; }
.gauge__chart svg { width: 100%; height: auto; display: block; }
.gauge__arc-bg  { stroke: rgba(255, 255, 255, .08); }
.gauge__arc-val { stroke: var(--accent-2); }
/* En px de usuario y no con --step-*: el SVG ya se escala solo, y un
   clamp en rem dentro del viewBox se vuelve impredecible. */
.gauge__num { font-size: 30px; fill: var(--heading); }

.gauge__scale {
  display: flex;
  justify-content: space-between;
  padding-inline: 6px;
  font-size: var(--step--1);
  color: var(--text-dim);
}
.gauge__caption {
  margin-top: var(--sp-1);
  text-align: center;
  font-size: var(--step--1);
  color: var(--text-dim);
}

.gauge__side { display: grid; gap: var(--sp-3); min-width: 0; }
.gauge__target { font-size: var(--step--1); color: var(--text-dim); }
.gauge__target b { color: var(--heading); }

.alert-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: .35rem .75rem;
  border: 1px solid rgba(223, 21, 41, .35);
  border-radius: var(--radius-pill);
  background: var(--danger-soft);
  color: var(--danger-hi);
  font-size: var(--step--1);
  font-weight: 600;
  line-height: 1.3;
}
.alert-badge .icon { font-size: 15px; }

/* Visual 3 — Pipeline: capacidad de planta vs. compromiso comercial */
.caps { display: grid; gap: var(--sp-3); }
.caps__plot {
  display: flex;
  align-items: flex-end;
  gap: var(--sp-4);
  height: 92px;
}
.caps__month { flex: 1; display: flex; align-items: flex-end; gap: 3px; height: 100%; }
.caps__bar {
  flex: 1;
  height: var(--h, 50%);
  border-radius: 3px 3px 0 0;
  background: rgba(255, 255, 255, .14);
}
.caps__bar--load { background: var(--accent-2); }
/* Compromiso por encima de la capacidad instalada: eso es una promesa que no se cumple */
.caps__bar--over { background: var(--danger); }

.caps__axis {
  display: flex;
  gap: var(--sp-4);
  padding-top: var(--sp-2);
  border-top: 1px solid var(--line);
}
.caps__axis span { flex: 1; text-align: center; font-size: var(--step--1); color: var(--text-dim); }

.legend { display: flex; flex-wrap: wrap; gap: var(--sp-4); font-size: var(--step--1); color: var(--text-dim); }
.legend span { display: inline-flex; align-items: center; gap: var(--sp-2); }
.legend i {
  width: 10px; height: 10px;
  border-radius: 2px;
  background: var(--swatch, var(--text-dim));
}

/* Visual 4 — Balanced scorecard: 3 KPIs en línea */
.kpi-row {
  display: grid;
  gap: var(--sp-4);
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
.kpi__val {
  font-size: var(--step-1);
  color: var(--heading);
  white-space: nowrap;
}
.kpi__val small { font-size: .55em; color: var(--text-dim); font-weight: 600; }
.kpi__label {
  margin-top: var(--sp-1);
  font-size: var(--step--1);
  color: var(--text-dim);
}
.kpi__delta { font-size: var(--step--1); font-weight: 600; color: var(--accent-2); }
.kpi__delta--down { color: var(--danger-hi); }


/* --- 26.5 ROI y testimonios --------------------------------- */
/* Las tres tarjetas tienen que leerse como una sola familia: número en una
   línea, label en dos, cita abajo. Sin las alturas mínimas, "50% → 90%"
   parte a dos líneas y "precisión de inventario" ocupa una sola, y las tres
   citas arrancan a alturas distintas — se lee como tres componentes. */
.roi-stat {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  height: 100%;
  padding: var(--sp-6);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--surface);
  transition: border-color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.roi-stat:hover { border-color: var(--accent-2); transform: translateY(-4px); }

.roi-stat__num {
  font-family: var(--font-head);
  font-size: var(--step-3);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -.03em;
  color: var(--accent-2);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.roi-stat__label {
  min-height: calc(2 * 1.5em);      /* dos líneas: alinea el arranque de las citas */
  font-size: var(--step-0);
  font-weight: 600;
  line-height: 1.5;
  color: var(--heading);
}
.roi-stat__quote {
  padding-top: var(--sp-3);
  border-top: 1px solid var(--line);
  font-size: var(--step-0);
  color: var(--text-dim);
  font-style: italic;
  flex-grow: 1;
}

.roi-disclaimer {
  margin-top: var(--sp-7);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--line);
  font-size: var(--step--1);
  color: var(--text-dim);
  max-width: 70ch;
}


/* --- 26.6 Cierre — CTA único de WhatsApp -------------------- */
/* Reemplaza al stepper de 3 pasos: un solo destino, sin campos, sin
   validación y sin estado de envío que mantener. La calificación
   (cargo, ERP, cuello de botella) pasa a la conversación. */
.cta-panel {
  max-width: 780px;
  margin-inline: auto;
  padding: clamp(2rem, 5vw, var(--sp-9)) clamp(1.5rem, 4vw, var(--sp-8));
  text-align: center;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background:
    radial-gradient(ellipse at 50% 0%, var(--accent-soft), transparent 62%),
    var(--surface);
}
.cta-panel .eyebrow { margin-bottom: var(--sp-4); }
.cta-panel .eyebrow::before { display: none; }
.cta-panel h2 { margin-bottom: var(--sp-5); }

.cta-panel__lead {
  margin-inline: auto;
  margin-bottom: var(--sp-7);
  color: var(--text);
}

.cta-panel__note {
  margin-top: var(--sp-4);
  font-size: var(--step--1);
  color: var(--text-dim);
}

/* El CTA es el elemento más grande de la sección: si empata en peso con
   el H2, el usuario duda entre seguir leyendo y actuar. */
.btn--lg { padding: 1.05rem 2rem; font-size: var(--step-1); }
.wa-cta .icon { font-size: 22px; }

.cta-facts { margin-top: var(--sp-8); }
.cta-facts .info-card { height: 100%; padding: var(--sp-5) var(--sp-5) var(--sp-6); }
/* Mismo criterio que en .pain-card--alert: "60 minutos, con tu equipo de
   planta" ocupa dos líneas y los otros dos títulos una. */
.cta-facts .info-card h4 { min-height: calc(2 * 1.15em); }


/* --- 26.7 Footer de cumplimiento ---------------------------- */
/* (la capa de movimiento vive en la sección 27, al final del archivo) */
.compliance-block {
  display: grid;
  gap: var(--sp-5);
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  margin-bottom: var(--sp-8);
  padding-bottom: var(--sp-8);
  border-bottom: 1px solid var(--line);
}
.compliance-item { display: flex; gap: var(--sp-4); align-items: flex-start; }
.compliance-item .icon-box { width: 40px; height: 40px; font-size: 19px; }
.compliance-item h4 { font-size: var(--step-0); margin-bottom: var(--sp-1); }
.compliance-item p  { font-size: var(--step--1); color: var(--text-dim); }

.footer__grid a .icon {
  font-size: 15px;
  margin-right: var(--sp-2);
  vertical-align: -.15em;
  color: var(--accent-hi);
}


/*--------------------------------------------------------------
# 27. Manufactura — capa de movimiento

  Regla de la sección: el movimiento tiene que hacer un trabajo.
  Nada gira ni rebota "para verse moderno". Cada efecto de acá
  cumple una de tres funciones:

    orientar   — dónde estoy (progreso de scroll, grid del fondo)
    responder  — el sitio registra lo que hago (spotlight de cursor)
    explicar   — el dato se construye a la vista (barras, contadores)

  Todo se apaga con prefers-reduced-motion y nada depende de JS
  para que el contenido sea legible: sin JS, los gráficos se
  muestran en su estado final.
--------------------------------------------------------------*/

/* --- 27.1 Fondo del hero: grid + auroras --------------------- */
/* Las líneas dan escala y profundidad al fondo plano; la máscara
   radial las apaga hacia los bordes para que no se lean como tabla. */
.hero__bg {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
}

.hero__grid {
  position: absolute;
  inset: -1px;
  background-image:
    linear-gradient(to right,  rgba(255, 255, 255, .04) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(255, 255, 255, .04) 1px, transparent 1px);
  background-size: 68px 68px;
  -webkit-mask-image: radial-gradient(ellipse 75% 65% at 50% 25%, #000 20%, transparent 72%);
          mask-image: radial-gradient(ellipse 75% 65% at 50% 25%, #000 20%, transparent 72%);
}

/* Dos manchas de color en deriva muy lenta (28s y 34s). A esa
   velocidad no se percibe el movimiento: se percibe que el fondo
   "respira" y no está congelado. */
.hero__aurora {
  position: absolute;
  width: min(760px, 90vw);
  aspect-ratio: 1;
  border-radius: 50%;
  filter: blur(10px);
  opacity: .5;
}
.hero__aurora--1 {
  top: -28%; left: 8%;
  background: radial-gradient(circle, var(--accent-soft) 0%, transparent 62%);
  animation: aurora-a 28s var(--ease) infinite alternate;
}
.hero__aurora--2 {
  top: 6%; right: -14%;
  width: min(560px, 70vw);
  background: radial-gradient(circle, var(--accent-2-soft) 0%, transparent 62%);
  animation: aurora-b 34s var(--ease) infinite alternate;
}
@keyframes aurora-a {
  from { transform: translate3d(0, 0, 0)          scale(1);    }
  to   { transform: translate3d(6%, 5%, 0)        scale(1.14); }
}
@keyframes aurora-b {
  from { transform: translate3d(0, 0, 0)          scale(1.08); }
  to   { transform: translate3d(-8%, 7%, 0)       scale(.92);  }
}

/* Halo que sigue al cursor. Las coordenadas las escribe el JS en
   --mx/--my; sin JS queda en su posición inicial y es inofensivo. */
.hero__halo {
  position: absolute;
  inset: 0;
  background: radial-gradient(420px circle at var(--mx, 70%) var(--my, 30%),
              rgba(122, 124, 255, .10), transparent 65%);
  opacity: 0;
  transition: opacity var(--dur-slow) var(--ease);
}
.hero:hover .hero__halo { opacity: 1; }

/* El contenido del hero va por encima de todas las capas de fondo */
.hero__inner { z-index: 1; }


/* --- 27.2 Grano ---------------------------------------------- */
/* Rompe el banding de los degradados grandes sobre fondo casi negro,
   que es donde más se nota. Es textura, no debe leerse como ruido. */
.grain {
  position: fixed;
  inset: 0;
  z-index: 9999;
  pointer-events: none;
  opacity: .028;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}


/* --- 27.3 Progreso de scroll --------------------------------- */
/* Dos píxeles al pie del header: en una landing larga es la única
   pista de cuánto falta, y no ocupa espacio de layout. */
.scroll-progress {
  position: absolute;
  left: 0; right: 0; bottom: -1px;
  height: 2px;
  transform: scaleX(var(--progress, 0));
  transform-origin: left;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  opacity: 0;
  transition: opacity var(--dur) var(--ease);
}
body.is-scrolled .scroll-progress { opacity: 1; }


/* --- 27.4 Spotlight de cursor en tarjetas -------------------- */
/* El patrón de Attio/Vercel: la luz nace donde está el puntero, no
   en el centro de la tarjeta. Es lo que hace que el hover se sienta
   "físico" en vez de un cambio de estado binario.
   z-index -1 + isolation: la luz queda sobre el fondo de la tarjeta
   pero por debajo de su contenido. */
.spot { position: relative; isolation: isolate; }
.spot::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: radial-gradient(300px circle at var(--mx, 50%) var(--my, 50%),
              rgba(255, 255, 255, .07), transparent 68%);
  opacity: 0;
  transition: opacity var(--dur) var(--ease);
}
.spot:hover::after { opacity: 1; }

/* En el diagnóstico la luz es del color de la alerta, no blanca:
   el hover no puede contradecir lo que dice la sección. */
.pain-card--alert.spot::after {
  background: radial-gradient(300px circle at var(--mx, 50%) var(--my, 50%),
              rgba(223, 21, 41, .17), transparent 68%);
}
.dash-card.spot::after,
.roi-stat.spot::after {
  background: radial-gradient(320px circle at var(--mx, 50%) var(--my, 50%),
              rgba(34, 211, 238, .12), transparent 68%);
}


/* --- 27.5 Los gráficos se dibujan al entrar en pantalla ------ */
/* Ver cómo se llena la barra explica que es una medición, no un
   adorno. Se dibuja una sola vez, al primer scroll que la cruza.
   Las reglas cuelgan de html:not(.no-js): sin JS el gráfico ya está
   en su valor final y no hay nada que animar. */
html:not(.no-js) [data-chart] .oee__fill {
  width: 0;
  transition: width 1.1s var(--ease) var(--delay, 0ms);
}
html:not(.no-js) [data-chart].is-drawn .oee__fill { width: var(--pct); }

html:not(.no-js) [data-chart] .caps__bar {
  height: 0;
  transition: height .9s var(--ease) var(--delay, 0ms);
}
html:not(.no-js) [data-chart].is-drawn .caps__bar { height: var(--h); }

html:not(.no-js) [data-chart] .gauge__arc-val {
  stroke-dashoffset: 194.8;                   /* arco completo = vacío */
  transition: stroke-dashoffset 1.3s var(--ease);
}
html:not(.no-js) [data-chart].is-drawn .gauge__arc-val { stroke-dashoffset: 60.6; }

/* La alerta de stock entra después del gauge: primero el dato, después
   la consecuencia. Invertido, la alerta se lee antes que su causa. */
html:not(.no-js) [data-chart] .alert-badge {
  opacity: 0;
  transform: translateY(6px);
  transition: opacity var(--dur-slow) var(--ease) .6s,
              transform var(--dur-slow) var(--ease) .6s;
}
html:not(.no-js) [data-chart].is-drawn .alert-badge { opacity: 1; transform: none; }


/* --- 27.6 Micro-estados -------------------------------------- */
/* Las placas de sistemas se levantan apenas: confirma que la franja
   es contenido vivo y no una imagen. */
.trust-item__mark { transform: translateY(0); }
.trust-item:hover .trust-item__mark { transform: translateY(-3px); }
.trust-item__mark { transition: opacity var(--dur) var(--ease),
                                border-color var(--dur) var(--ease),
                                transform var(--dur) var(--ease); }

/* Brillo que cruza el CTA principal al pasar por encima. Una sola
   pasada, sin loop: un botón que titila solo se lee como banner. */
.wa-cta { position: relative; overflow: hidden; }
.wa-cta::after {
  content: "";
  position: absolute;
  top: 0; bottom: 0;
  left: -60%;
  width: 45%;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, .22), transparent);
  transform: skewX(-18deg);
  transition: left .75s var(--ease);
}
.wa-cta:hover::after { left: 115%; }

/* El punto del badge del hero late como un indicador de "en vivo" */
.hero__badge-dot { animation: live-dot 2.4s var(--ease) infinite; }
@keyframes live-dot {
  0%, 100% { box-shadow: 0 0 0 4px var(--accent-2-soft); }
  50%      { box-shadow: 0 0 0 7px rgba(34, 211, 238, .04); }
}

/* Los números tabulares no deben saltar de ancho mientras cuentan */
[data-count-to] { font-variant-numeric: tabular-nums; }


/* --- 27.7 Reduced motion ------------------------------------- */
/* La sección 25 ya reduce duraciones a .01ms. Acá se apaga lo que
   además es continuo o innecesario, y se fija el estado final. */
@media (prefers-reduced-motion: reduce) {
  .hero__aurora { animation: none !important; }
  .hero__halo { display: none; }
  .hero__badge-dot { animation: none !important; }
  .wa-cta::after { display: none; }
  .spot::after { display: none; }
  .grain { display: none; }

  html:not(.no-js) [data-chart] .oee__fill { width: var(--pct); }
  html:not(.no-js) [data-chart] .caps__bar { height: var(--h); }
  html:not(.no-js) [data-chart] .gauge__arc-val { stroke-dashoffset: 60.6; }
  html:not(.no-js) [data-chart] .alert-badge { opacity: 1; transform: none; }
}


/*--------------------------------------------------------------
# 28. Enterprise — Command Center (landing de conversión)

  Aditivo sobre 01–27: no pisa ninguna regla anterior. Reutiliza
  los tokens y componentes de la landing de Manufactura (§26) y su
  capa de movimiento (§27) — --danger, .num, .metric-hero,
  .pain-card--alert, .dash-card, .kpi-row, .gauge, .caps,
  .alert-badge, .roi-stat, .compliance-block, .spot,
  .scroll-progress, .grain — sin redeclarar nada de eso.

  Va numerada 28 y no 27 como decía la spec: la 27 ya está ocupada
  por la capa de movimiento de Manufactura, y sobrescribirla rompe
  esa landing. Ambas conviven en este mismo archivo.

  Regla de acentos (idéntica a §26):
    --accent   violeta → marca, CTAs, navegación, arquitectura
    --accent-2 cyan    → datos, dashboards, métricas de mejora
    --danger   rojo    → SOLO el diagnóstico del dolor (§2)

  Movimiento: la única animación continua de la página es la línea
  de flujo del hero (28.2). Todo lo demás entra una vez con
  [data-reveal] / [data-chart] y queda quieto.
--------------------------------------------------------------*/

/* --- 28.1 Marca ---------------------------------------------- */
/* El wordmark es assets/img/LogoConNombre.png (254x92). El alto se lo
   fija .header__logo img (§07) y el ancho sale del aspect-ratio, así
   que en el header no hace falta nada.

   En el footer sí: logo + separador + "Command Center" en una línea
   miden 266px y la columna de la grilla da 250, y como .logo-sub va
   con white-space:nowrap el bloque se sale. Apilado entra holgado, y
   ahí el separador vertical ya no tiene contra qué separar. */
.footer .header__logo {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sp-2);
}
.footer .logo-sub {
  margin-left: 0;
  padding-left: 0;
  border-left: 0;
}

/* Desde 981px el nav ya es horizontal, pero hasta ~1120 no hay ancho para
   logo + bajada + cuatro ítems + CTA: la suma da 966px contra 944 de
   contenido, y como .logo-sub va con nowrap el sobrante se desborda del
   logo. La bajada es lo prescindible — el wordmark ya identifica la marca.
   Scopeado a .ent: Manufactura tiene otro menú y otro punto de quiebre. */
@media (min-width: 981px) and (max-width: 1120px) {
  .ent .logo-sub { display: none; }
}


/* --- 28.2 Hero ----------------------------------------------- */
/* El H1 de esta landing tiene 86 caracteres contra los ~45 del de
   Manufactura: en --step-5 ocupa seis líneas y empuja el diagrama
   fuera de la primera pantalla. Un escalón menos lo deja en cuatro.
   Va scopeado a .hero--enterprise y no a .hero: ambas landings
   comparten este archivo. */
.hero--enterprise h1 { font-size: var(--step-4); }

/* Líneas de flujo */
/* Tres orígenes de datos convergiendo en el Command Center. Es la
   única animación en loop de la página: comunica que el flujo es
   continuo, que es justo lo que vende la sección. Lenta (7s) y a
   opacidad baja para que no compita con el H1. */
.hero__flow-line {
  stroke: var(--accent-2);
  stroke-width: 1.5;
  fill: none;
  stroke-dasharray: 6 10;
  animation: flow-dash 7s linear infinite;
  /* Desfasadas entre sí: tres líneas en fase se leen como una sola
     barra que se desplaza, no como tres flujos independientes. */
  animation-delay: calc(var(--i, 0) * -2.3s);
  opacity: .55;
}
@keyframes flow-dash { to { stroke-dashoffset: -160; } }

/* Los puntos de conexión no se animan: marcan dónde empieza y
   dónde termina cada flujo, y tienen que estar quietos para eso. */
.hero-diagram__dot { fill: var(--accent-2); stroke: none; }
.hero-diagram__divider { stroke: var(--line); stroke-width: 1; }

/* Sub-línea de cada origen. Selector con el elemento adentro para
   ganarle en especificidad a `.hero-diagram__node text` (§26.1b),
   que fuerza fuente de titular y letter-spacing amplio. */
.hero-diagram__node text.hero-diagram__node-sub {
  font-family: var(--font-body);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: .02em;
  fill: var(--text-dim);
}
.hero-diagram__row-label { font-size: 12px; fill: var(--text-dim); }
.hero-diagram__row-val {
  font-size: 11px;
  fill: var(--text);
  font-variant-numeric: tabular-nums;
}

.hero__visual-note {
  margin-top: var(--sp-4);
  font-size: var(--step--1);
  color: var(--text-dim);
  text-align: center;
}


/* --- 28.3 Diagrama de arquitectura de 4 etapas --------------- */
/* Cuatro columnas solo a partir de 980px: a 780px cada etapa queda
   en ~170px y los títulos de dos palabras parten a tres líneas. */
/* Las cuatro columnas recién a 1080px. A 980 cada etapa queda en 161px de
   contenido y "Almacenamiento" —una sola palabra, sin punto de corte— mide
   174 en --step-1: el título se sale de la tarjeta. A 1080 hay 184. */
.flow-diagram {
  display: grid;
  gap: var(--sp-5);
  grid-template-columns: minmax(0, 1fr);
}
@media (min-width: 620px)  { .flow-diagram { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1080px) { .flow-diagram { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.flow-step {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  padding: var(--sp-5);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--surface);
  transition: border-color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.flow-step:hover { border-color: var(--accent); transform: translateY(-4px); }

.flow-step .icon-box { width: 44px; height: 44px; font-size: 21px; }
.flow-step__num {
  font-family: var(--font-head);
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--accent-hi);
}
/* "Almacenamiento centralizado" y "Modelado semántico" ocupan dos líneas
   y las otras dos una: sin el alto mínimo los párrafos arrancan a
   alturas distintas y las cuatro etapas dejan de leerse como una serie.
   Mismo criterio que .pain-card--alert h3 (§26.3). */
.flow-step h3 { font-size: var(--step-1); min-height: calc(2 * 1.15em); }
.flow-step p { font-size: var(--step--1); color: var(--text-dim); flex-grow: 1; }
.flow-step__sys {
  font-size: var(--step--1);
  font-weight: 600;
  color: var(--text);
  padding-top: var(--sp-3);
  border-top: 1px solid var(--line);
}

/* Conector: vive dentro del gap de la grilla, por eso mide exactamente
   --sp-5. Se dibuja de izquierda a derecha cuando la etapa entra en
   pantalla, encadenado al mismo --reveal-delay escalonado de las
   tarjetas: la línea sigue al bloque, no al revés.

   Es un <span> real y no un pseudo-elemento porque .flow-step ya tiene
   los dos ocupados: ::after por .spot (§27.4) y ::before por .edge
   (§29.2). Compartir pseudo con .spot ya rompió esto una vez — el
   `left: 0` de su `inset` ganaba sobre el `right` negativo del conector
   y la línea aparecía pegada al borde izquierdo de su propia tarjeta. */
.flow-step__link {
  position: absolute;
  top: 50%;
  right: calc(-1 * var(--sp-5));
  width: var(--sp-5);
  /* 2px con el degradado de acento y no 1px en --line-strong: a 1px pesa
     menos que el borde de las propias tarjetas y deja de leerse como el
     flujo que las une, que es todo su trabajo. */
  height: 2px;
  margin-top: -1px;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  opacity: .7;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-slow) var(--ease) var(--reveal-delay, 0ms);
  display: none;
}
/* Mismo umbral que las cuatro columnas: en la grilla de dos, el conector
   de la etapa 2 apuntaría al borde derecho de la fila y no a la etapa 3. */
@media (min-width: 1080px) {
  .flow-step:not(:last-child) .flow-step__link { display: block; }
}
.flow-step.is-in .flow-step__link { transform: scaleX(1); }
.no-js .flow-step__link { transform: scaleX(1); }


/* --- 28.4 Tabs de paneles por rol ---------------------------- */
.role-tabs__nav {
  display: flex;
  gap: var(--sp-2);
  margin-bottom: var(--sp-6);
  flex-wrap: wrap;
}
.role-tabs__btn {
  padding: .6rem 1.2rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  color: var(--text-dim);
  font-size: var(--step--1);
  font-weight: 600;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease),
              background var(--dur) var(--ease);
}
.role-tabs__btn:hover { color: var(--text); border-color: var(--line-strong); }
.role-tabs__btn.is-active {
  color: var(--heading);
  border-color: var(--accent);
  background: var(--accent-soft);
}
.role-tabs__btn small {
  display: block;
  font-size: .85em;
  font-weight: 500;
  color: var(--text-dim);
}
.role-tabs__btn.is-active small { color: var(--accent-hi); }

/* Dos clases y no una: `display` no es animable, así que el JS
   primero monta el panel (.is-mounted) y recién en el frame
   siguiente lo enciende (.is-active). Con una sola clase el fade
   nunca se ve porque el elemento pasa de none a su estado final
   en el mismo frame. */
.role-tabs__panel { display: none; }
.role-tabs__panel.is-mounted {
  display: block;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity .2s var(--ease), transform .2s var(--ease);
}
.role-tabs__panel.is-active { opacity: 1; transform: none; }
/* Sin JS no hay tabs: se muestran los tres paneles uno debajo del
   otro. Es más largo, pero no se pierde contenido. */
.no-js .role-tabs__panel { display: block; opacity: 1; transform: none; }
.no-js .role-tabs__nav { display: none; }

.role-panel__lead {
  margin-bottom: var(--sp-6);
  font-size: var(--step-1);
  color: var(--text);
  max-width: 62ch;
}
.role-panel__lead strong { color: var(--heading); }

/* La tarjeta que abre cada panel ocupa el ancho completo: es el
   KPI que define el rol, no uno más de la grilla. */
.dash-card--wide { grid-column: 1 / -1; }


/* --- 28.5 Medidor genérico de los paneles -------------------- */
/* Mismo lenguaje visual que .oee__bar (§26.4) pero sin su semántica
   de tres segmentos: acá cada fila es una métrica independiente. */
.meter { display: grid; gap: var(--sp-4); }
.meter__meta {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--sp-2);
  margin-bottom: var(--sp-2);
}
.meter__label { font-size: var(--step--1); color: var(--text-dim); }
.meter__val {
  font-size: var(--step--1);
  color: var(--heading);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.meter__track {
  height: 8px;
  border-radius: 3px;
  background: rgba(255, 255, 255, .07);
  overflow: hidden;
}
/* display:block explícito: el relleno es un <span> y como inline no
   toma ni ancho ni alto — la barra queda vacía. .oee__fill (§26.4) no
   lo necesita porque su contenedor es flex y lo blockifica solo. */
.meter__fill {
  display: block;
  height: 100%;
  width: var(--pct, 0%);
  border-radius: 3px;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
}
/* La fila que rompe el objetivo se lee distinto, igual criterio que
   .oee__seg--low: el color dice "acá está el problema". */
.meter__row--warn .meter__fill { background: linear-gradient(90deg, var(--danger), var(--danger-hi)); }
.meter__row--warn .meter__val  { color: var(--danger-hi); }
.meter__row--muted .meter__fill { background: rgba(255, 255, 255, .16); }

/* Los medidores se dibujan al entrar en pantalla, igual que los
   gráficos de §27.5, y con el mismo enganche [data-chart]. */
html:not(.no-js) [data-chart] .meter__fill {
  width: 0;
  transition: width 1.1s var(--ease) var(--delay, 0ms);
}
html:not(.no-js) [data-chart].is-drawn .meter__fill { width: var(--pct); }

/* .kpi-row (§26.4) es de tres columnas fijas; algunos paneles
   muestran solo dos KPIs y con tres columnas queda un hueco. */
.kpi-row--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }


/* --- 28.6 Resultados ----------------------------------------- */
/* Reemplaza a .roi-stat__quote: acá no hay testimonios nominales
   que citar, así que la tercera línea es contexto del dato y no
   una cita. Mismo alto y mismo separador para que las tres
   tarjetas sigan leyéndose como una serie. */
.roi-stat__note {
  padding-top: var(--sp-3);
  border-top: 1px solid var(--line);
  font-size: var(--step--1);
  color: var(--text-dim);
  flex-grow: 1;
}

/* "Semanas → horas" no es un número: en --step-3 mide ~315px y con el
   white-space:nowrap de .roi-stat__num se sale de la tarjeta. Baja un
   escalón, pero conserva el alto de una línea de --step-3 para que las
   tres tarjetas sigan arrancando el label a la misma altura. */
/* Solo cuando las tres tarjetas están en fila: ahí el label más largo de
   esta landing ("...ERP y sistemas de almacén (WMS)") ocupa tres líneas,
   una más de lo que reserva .roi-stat__label (§26.5), y sin subirlo la
   línea divisoria de esa tarjeta cae más abajo que la de las otras dos.
   Apiladas, cada label entra en una sola línea y el mínimo sería un hueco. */
@media (min-width: 1000px) {
  .roi-grid .roi-stat__label { min-height: calc(3 * 1.5em); }
}
/* Apiladas a ancho completo cada label entra en una sola línea, y tanto
   este mínimo como el de §26.5 se leen como un hueco entre el label y la
   nota. El mínimo solo tiene sentido cuando hay tres tarjetas en fila. */
@media (max-width: 999.98px) {
  .roi-grid .roi-stat__label { min-height: 0; }
}

.roi-stat__num--text {
  display: flex;
  align-items: center;
  min-height: calc(var(--step-3) * 1.1);
  white-space: normal;
  font-size: var(--step-2);
  letter-spacing: -.02em;
}


/* --- 28.7 Cierre — CTA único de WhatsApp --------------------- */
/* No hay estilos propios: el panel de cierre reutiliza tal cual
   .cta-panel, .cta-panel__lead, .cta-panel__note, .btn--lg, .wa-cta
   y .cta-facts de §26.6, el brillo de .wa-cta::after de §27.6 y el
   flotante .wa-float de §23. El stepper de tres pasos que vivía acá
   se eliminó junto con su CSS (campos, select, tarjetas de opción y
   mensajes de error): un solo destino, sin campos y sin estado de
   envío que mantener. */


/* --- 28.8 Reduced motion ------------------------------------- */
/* La sección 25 ya lleva todas las duraciones a .01ms. Acá se apaga
   lo que además es continuo, y se fija el estado final de lo que
   depende de una clase que el JS podría no llegar a poner. */
@media (prefers-reduced-motion: reduce) {
  .hero__flow-line { animation: none !important; }

  .flow-step__link { transform: scaleX(1); }
  html:not(.no-js) [data-chart] .meter__fill { width: var(--pct); }

  .role-tabs__panel.is-mounted { opacity: 1; transform: none; }
}


/*--------------------------------------------------------------
# 29. Enterprise — capa de superficie (puntero y scroll)

  Todo lo de acá cuelga de `body.ent`, o de clases nuevas que solo
  usa esta landing: main3.css lo comparten Manufactura y el sitio,
  y ninguna regla de esta sección puede filtrarse a esos.

  Criterio, después de mirar qué hace hoy la referencia del rubro
  (Linear, Vercel, Stripe, Attio): el movimiento premium de 2026 no
  es "más animación", es superficie que responde. Tres familias:

    responder al puntero  — el borde y el relleno se encienden donde
                            está el cursor (29.2, 29.3, 29.4)
    responder al scroll   — el fondo se mueve a otra velocidad que
                            el contenido (29.5), en CSS nativo
    orientar              — lo que ya hace la 27 (progreso, grano)

  Lo que deliberadamente NO se hace: cursor personalizado. Es la
  técnica que más se pide y la que la referencia abandonó — rompe
  magnificadores, inversión de color y ajustes de puntero del
  sistema, y esta pieza apunta a compras enterprise donde WCAG 2.1
  AA suele ser requisito de contrato. El efecto "premium" que se le
  atribuye lo da la superficie reactiva, no el puntero dibujado.

  Todo se apaga con prefers-reduced-motion y nada es necesario para
  leer la página: son capas sobre contenido que ya funciona.
--------------------------------------------------------------*/

/* --- 29.1 Tokens de la capa ---------------------------------- */
.ent {
  --edge-size: 260px;          /* radio del halo que recorre el borde */
  --tilt: 4deg;                /* inclinación máxima del panel del hero */
}


/* --- 29.2 Borde reactivo al puntero -------------------------- */
/* El gesto de Linear/Vercel: no es la tarjeta la que se ilumina,
   es su borde, y solo en el tramo que tiene el cursor al lado.
   Comunica que la superficie es sensible sin mover nada de sitio.

   Cómo funciona: un anillo de 1px hecho con dos máscaras — una al
   content-box y otra a toda la caja — restadas entre sí. Lo que
   queda visible es exclusivamente el marco, y ahí se pinta un
   radial-gradient centrado en --mx/--my, que escribe el JS.

   Va en ::before porque ::after ya es de .spot (27.4). Los dos
   trabajan juntos: .spot da el relleno tenue, .edge el filo. */
@supports ((-webkit-mask-composite: xor) or (mask-composite: exclude)) {
  .edge { position: relative; isolation: isolate; }

  .edge::before {
    content: "";
    position: absolute;
    /* inset:0 y no -1px: el anillo se apoya sobre el borde de 1px que
       ya tiene la tarjeta, en vez de dibujar un segundo contorno. */
    inset: 0;
    z-index: -1;
    border-radius: inherit;
    padding: 1px;
    background: radial-gradient(var(--edge-size, 260px) circle at var(--mx, 50%) var(--my, 50%),
                var(--edge-color, var(--accent)) 0%, transparent 62%);
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
            mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
            mask-composite: exclude;
    opacity: 0;
    transition: opacity var(--dur) var(--ease);
    pointer-events: none;
  }
  .edge:hover::before,
  .edge:focus-within::before { opacity: 1; }
}

/* El borde no puede contradecir lo que dice la sección: rojo donde se
   habla del costo del problema, cian donde se habla de los datos. */
.metric-hero.edge,
.pain-card--alert.edge { --edge-color: var(--danger); }

.dash-card.edge,
.roi-stat.edge,
.dash-dynamic.edge { --edge-color: var(--accent-2); }


/* --- 29.3 Brillo del CTA bajo el cursor ---------------------- */
/* El botón primario es el único elemento de la página que persigue
   al puntero por dentro. Es deliberado: marca cuál es la acción. */
.ent .btn--sheen {
  position: relative;
  isolation: isolate;
  overflow: hidden;
}
.ent .btn--sheen::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: radial-gradient(120px circle at var(--mx, 50%) var(--my, 50%),
              rgba(255, 255, 255, .28), transparent 66%);
  opacity: 0;
  transition: opacity var(--dur) var(--ease);
  pointer-events: none;
}
.ent .btn--sheen:hover::before,
.ent .btn--sheen:focus-visible::before { opacity: 1; }


/* --- 29.4 Inclinación del panel del hero --------------------- */
/* El diagrama se inclina hacia el cursor. Cuatro grados como máximo:
   por encima de eso deja de leerse como profundidad y se lee como un
   truco. El giro va en .video-frame y no en .hero__visual porque ese
   ya tiene el transform de [data-reveal="zoom"]; en el mismo elemento
   una cosa pisaría a la otra.

   --ptx/--pty los escribe el JS sin unidad (-0.5 a 0.5) justamente
   para poder multiplicarlos por un ángulo: --mx/--my son porcentajes
   y calc(62% * 1deg) no es una operación válida. */
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .ent .hero__visual { perspective: 1400px; }
  .ent .hero__visual .video-frame {
    transform:
      rotateX(calc(var(--pty, 0) * var(--tilt) * -1))
      rotateY(calc(var(--ptx, 0) * var(--tilt)));
    transition: transform .45s var(--ease);
  }
}


/* --- 29.5 Paralaje y salida del hero (scroll nativo) --------- */
/* animation-timeline es CSS puro: corre en el hilo de composición,
   no en el principal, así que no compite con el scroll ni suma un
   listener más. Va detrás de @supports porque en un navegador sin
   soporte simplemente no hay paralaje, y la página no lo necesita. */
@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
    /* La grilla del fondo se desplaza menos que el contenido: es lo
       que da la sensación de que el hero tiene profundidad. */
    .ent .hero__grid {
      animation: ent-parallax linear both;
      animation-timeline: scroll(root block);
      animation-range: 0 100vh;
    }
    @keyframes ent-parallax { to { transform: translateY(12%); } }

    /* El hero se apaga al salir en vez de cortarse contra el borde de
       la pantalla. No baja de .3: si desaparece del todo, los dos CTA
       se vuelven invisibles justo cuando el usuario todavía puede
       volver a ellos.

       Solo desde 1000px, que es donde .hero__inner pasa a dos columnas
       (§08) y entra entero en una pantalla. Apilado, el hero mide dos
       viewports largos: el rango 25vh–85vh terminaba de apagarlo con
       el diagrama y la franja "Se conecta a" todavía en pantalla, y
       toda la mitad inferior del hero se leía gris. Ese era el bug de
       "secciones oscuras en responsive".

       El alto mínimo va con el ancho: en 1000px de ancho y 500 de alto
       (una tablet apaisada) el hero tampoco entra. */
    @media (min-width: 1000px) and (min-height: 680px) {
      .ent .hero__inner {
        animation: ent-hero-out linear both;
        animation-timeline: scroll(root block);
        /* Arranca a 45vh y no a 25: a 25 el apagado empieza antes de
           que el H1 llegue al borde superior. */
        animation-range: 45vh 100vh;
      }
      @keyframes ent-hero-out { to { opacity: .34; } }
    }
  }
}


/* --- 29.6 Micro-estados ------------------------------------- */
/* La regla del eyebrow se dibuja al entrar la sección, con el mismo
   observer que ya revela el bloque: la línea sigue al título. */
.ent [data-reveal] .eyebrow::before {
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-slow) var(--ease) .12s;
}
.ent [data-reveal].is-in .eyebrow::before { transform: scaleX(1); }
.no-js .ent [data-reveal] .eyebrow::before { transform: none; }

/* Las pestañas de rol se levantan como el resto de las superficies
   clickeables de la página. */
.ent .role-tabs__btn {
  transition: color var(--dur) var(--ease),
              border-color var(--dur) var(--ease),
              background var(--dur) var(--ease),
              transform var(--dur) var(--ease);
}
.ent .role-tabs__btn:hover { transform: translateY(-2px); }


/* --- 29.7 Reduced motion ------------------------------------ */
/* La 25 ya lleva las duraciones a .01ms; acá se apaga lo que además
   depende del puntero o del scroll y no aporta información. */
@media (prefers-reduced-motion: reduce) {
  .edge::before { display: none; }
  .ent .btn--sheen::before { display: none; }
  .ent .hero__aurora { animation: none !important; }
  .ent [data-reveal] .eyebrow::before { transform: none; }
  .ent .role-tabs__btn:hover { transform: none; }
}


/*--------------------------------------------------------------
# 30. Enterprise — sectores, validación social y cuestionario

  Tercer bloque de la landing unificada. Igual que la 28 y la 29,
  todo cuelga de `.ent` o de clases nuevas: main3.css lo comparten
  el sitio y la landing de Manufactura, y ninguna regla de acá
  puede filtrarse a esos.

  Las tres piezas responden a lo mismo — la decisión de compra la
  toma un comité, no una persona:

    sectores (30.1)     filtran. Una foto del sector real hace que
                        el visitante se reconozca en dos segundos,
                        y que el que no es del rubro se vaya solo.
    validación (30.2)   autoriza. Nadie firma una integración sobre
                        su ERP productivo sin ver que ya se hizo.
    cuestionario (30.3) califica. Fricción intencional: el dato de
                        ERP y de obstáculo vale más que el volumen.
--------------------------------------------------------------*/

/* --- 30.1 Franja de sectores --------------------------------- */
/* Foto real y no ilustración: el objetivo es que un director de
   planta se reconozca en la imagen. La capa oscura no es decorativa,
   es lo que deja legible el texto sobre cualquier foto sin tener
   que retocar las fotos una por una. */
.sector-grid {
  display: grid;
  gap: var(--sp-4);
  grid-template-columns: minmax(0, 1fr);
}
@media (min-width: 620px)  { .sector-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1000px) { .sector-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.sector-card {
  position: relative;
  display: block;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--surface);
  /* 4/5 y no cuadrado: las cuatro fotos son de gente trabajando y el
     retrato vertical las corta mejor que el cuadrado, que siempre
     deja media máquina afuera. En mobile se achata para no comerse
     cuatro pantallas enteras. */
  aspect-ratio: 4 / 5;
  transition: border-color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
@media (max-width: 619.98px) { .sector-card { aspect-ratio: 16 / 10; } }

.sector-card:hover { border-color: var(--accent-2); transform: translateY(-4px); }

.sector-card__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Desaturada y oscurecida: la página es casi negra y una foto a
     color pleno se lee como un banner pegado encima. Al hover
     recupera color — confirma que la tarjeta está viva. */
  filter: grayscale(.55) brightness(.72) contrast(1.05);
  transform: scale(1.02);
  transition: filter var(--dur-slow) var(--ease), transform var(--dur-slow) var(--ease);
}
.sector-card:hover .sector-card__img {
  filter: grayscale(0) brightness(.86) contrast(1);
  transform: scale(1.06);
}

/* Tres paradas y no una: con un solo degradado desde abajo, el
   kicker de arriba queda sobre la parte clara de la foto. */
.sector-card__veil {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg,
              rgba(7, 7, 8, .72) 0%, rgba(7, 7, 8, .12) 38%, rgba(7, 7, 8, .92) 100%);
  pointer-events: none;
}

.sector-card__body {
  position: absolute;
  inset: auto 0 0 0;
  padding: var(--sp-5);
}
.sector-card__kicker {
  display: block;
  margin-bottom: var(--sp-2);
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--accent-2);
}
.sector-card__title {
  font-size: var(--step-1);
  margin-bottom: var(--sp-2);
}
.sector-card__desc {
  font-size: var(--step--1);
  color: rgba(255, 255, 255, .78);
}


/* --- 30.2 Validación social ---------------------------------- */
/* Dos bloques distintos y no uno: la experiencia responde "¿saben
   hacer esto?" y los casos "¿le funcionó a alguien como yo?".
   Mezclados en una sola tarjeta ninguna de las dos queda contestada. */
.exp-block {
  display: grid;
  gap: var(--sp-7);
  align-items: center;
  margin-bottom: var(--sp-9);
}
@media (min-width: 900px) {
  .exp-block { grid-template-columns: minmax(0, 6fr) minmax(0, 5fr); gap: var(--sp-9); }
}

.exp-block__lead {
  font-size: var(--step-1);
  color: var(--text-dim);
  margin-bottom: var(--sp-7);
  max-width: 56ch;
}

.exp-stats {
  display: grid;
  gap: var(--sp-5);
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
.exp-stat {
  padding-left: var(--sp-4);
  border-left: 2px solid var(--accent);
}
.exp-stat__num {
  font-family: var(--font-head);
  font-size: var(--step-3);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -.03em;
  color: var(--heading);
  font-variant-numeric: tabular-nums;
}
.exp-stat__label {
  margin-top: var(--sp-1);
  font-size: var(--step--1);
  color: var(--text-dim);
}

.exp-figure {
  position: relative;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  aspect-ratio: 4 / 3;
  box-shadow: var(--shadow-lg);
}
.exp-figure img {
  width: 100%; height: 100%;
  object-fit: cover;
  filter: grayscale(.35) brightness(.8);
}
/* Tinte de marca sobre la foto: la ata al resto de la paleta en vez
   de que se lea como una imagen pegada de otro sitio. */
.exp-figure::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(140deg, rgba(87, 90, 255, .22), transparent 55%, rgba(7, 7, 8, .5));
  pointer-events: none;
}

/* Tarjetas de caso. Sin foto de persona a propósito mientras las
   citas sean de referencia y no de un cliente identificable: una
   cara inventada al lado de una cita convierte un caso de referencia
   en un testimonio falso. Cuando haya clientes con autorización
   escrita, la placa de iniciales se reemplaza por <img> con la misma
   clase y el mismo tamaño, y no hay que tocar nada más. */
.testi-grid {
  display: grid;
  gap: var(--sp-5);
  grid-template-columns: minmax(0, 1fr);
}
@media (min-width: 760px)  { .testi-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1060px) { .testi-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.testi-card {
  display: flex;
  flex-direction: column;
  gap: var(--sp-5);
  height: 100%;
  padding: var(--sp-6);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background:
    linear-gradient(180deg, rgba(255, 255, 255, .025), transparent 40%),
    var(--surface);
  transition: border-color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.testi-card:hover { border-color: var(--accent); transform: translateY(-4px); }

/* La comilla es tipográfica y grande: marca que lo que sigue es voz
   de otro y no copy de la marca, sin necesidad de itálicas. */
.testi-card__mark {
  font-family: var(--font-head);
  font-size: 2.6rem;
  font-weight: 700;
  line-height: .6;
  color: var(--accent);
  opacity: .5;
}
.testi-card__quote {
  font-size: var(--step-1);
  line-height: 1.5;
  color: var(--heading);
  flex-grow: 1;
  text-wrap: pretty;
}
.testi-card__who {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--line);
}
.testi-card__avatar {
  display: grid;
  place-items: center;
  width: 44px; height: 44px;
  border-radius: 50%;
  border: 1px solid var(--line-strong);
  background: var(--accent-soft);
  color: var(--accent-hi);
  font-family: var(--font-head);
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: .04em;
  object-fit: cover;
  flex-shrink: 0;
}
.testi-card__role {
  font-size: var(--step--1);
  font-weight: 700;
  color: var(--heading);
  line-height: 1.35;
}
.testi-card__org {
  font-size: var(--step--1);
  color: var(--text-dim);
  line-height: 1.35;
}
/* El número del caso: es lo único de la tarjeta que se lee de lejos,
   y es lo que hace que la cita valga como prueba y no como opinión. */
.testi-card__metric {
  display: inline-flex;
  align-items: baseline;
  gap: var(--sp-2);
  align-self: flex-start;
  padding: .3rem .7rem;
  border: 1px solid rgba(34, 211, 238, .3);
  border-radius: var(--radius-pill);
  background: var(--accent-2-soft);
  font-size: var(--step--1);
  color: var(--text-dim);
}
.testi-card__metric b {
  font-family: var(--font-head);
  font-weight: 700;
  color: var(--accent-2);
  font-variant-numeric: tabular-nums;
}

.testi-note {
  margin-top: var(--sp-7);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--line);
  font-size: var(--step--1);
  color: var(--text-dim);
  max-width: 70ch;
}


/* Cuatro tarjetas de resultado en fila y no tres (§28.6): cada una
   baja a ~250px de contenido, y "50% → 90%" en --step-3 con el
   white-space:nowrap de .roi-stat__num se sale de la tarjeta. Un
   escalón menos entra con margen, y la variante de texto lo sigue
   para que las cuatro arranquen el label a la misma altura. */
@media (min-width: 1000px) {
  .roi-grid--4 .roi-stat__num { font-size: var(--step-2); }
  .roi-grid--4 .roi-stat__num--text {
    font-size: var(--step-1);
    min-height: calc(var(--step-2) * 1.1);
  }
}


/* --- 30.3 Cuestionario de calificación ----------------------- */
/* Stepper de tres pasos y no un formulario largo: la primera
   pantalla pide dos campos, y eso decide si el visitante arranca.
   El resto de la fricción llega cuando ya empezó a completar.

   Todo el estado vive en clases (.is-active, .is-done, .has-error):
   el JS no escribe estilos inline, así que el formulario se puede
   depurar mirando el DOM. */
.qform-panel {
  max-width: 780px;
  margin-inline: auto;
  padding: clamp(1.5rem, 4vw, var(--sp-8));
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background:
    radial-gradient(ellipse at 50% 0%, var(--accent-soft), transparent 60%),
    var(--surface);
}

/* Barra de pasos. Los tres siempre visibles: saber cuánto falta es
   lo que sostiene el abandono en el paso 2. */
.qsteps {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-bottom: var(--sp-7);
}
.qstep {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-width: 0;
}
.qstep__num {
  display: grid;
  place-items: center;
  width: 30px; height: 30px;
  border-radius: 50%;
  border: 1px solid var(--line-strong);
  color: var(--text-dim);
  font-family: var(--font-head);
  font-size: var(--step--1);
  font-weight: 700;
  flex-shrink: 0;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease),
              color var(--dur) var(--ease);
}
.qstep__label {
  font-size: var(--step--1);
  font-weight: 600;
  color: var(--text-dim);
  white-space: nowrap;
  transition: color var(--dur) var(--ease);
}
/* Debajo de 620px los tres labels no entran: quedan los círculos, y
   el título del paso activo ya está en el <h3> del panel. */
@media (max-width: 619.98px) { .qstep__label { display: none; } }

.qstep.is-active .qstep__num {
  border-color: var(--accent);
  background: var(--accent);
  color: var(--on-accent);
}
.qstep.is-active .qstep__label { color: var(--heading); }
.qstep.is-done .qstep__num {
  border-color: var(--accent-2);
  background: var(--accent-2-soft);
  color: var(--accent-2);
}
.qstep.is-done .qstep__label { color: var(--text); }
.qstep__num .icon { font-size: 15px; }

.qsteps__line {
  flex: 1;
  height: 1px;
  min-width: var(--sp-3);
  background: var(--line-strong);
}

/* Los paneles se montan y encienden con el mismo par de clases que
   .role-tabs__panel (§28.4) y por la misma razón: display no es
   animable. Una sola firma de transición para todo lo que cambia de
   paso o de pestaña en la página. */
.qpanel { display: none; }
.qpanel.is-mounted {
  display: grid;
  gap: var(--sp-5);
  opacity: 0;
  transform: translateY(8px);
  transition: opacity .2s var(--ease), transform .2s var(--ease);
}
.qpanel.is-active { opacity: 1; transform: none; }
/* Sin JS no hay stepper: se muestran los tres pasos uno debajo del
   otro y el <form> sigue siendo enviable. */
.no-js .qpanel { display: grid; gap: var(--sp-5); opacity: 1; transform: none; }
.no-js .qsteps, .no-js .qform__nav { display: none; }

.qpanel__head h3 { font-size: var(--step-2); margin-bottom: var(--sp-2); }
.qpanel__head p  { font-size: var(--step--1); color: var(--text-dim); }

.qgrid { display: grid; gap: var(--sp-4); }
@media (min-width: 620px) {
  .qgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .qgrid .field--full { grid-column: 1 / -1; }
}

/* El <select> no lo cubre .field (§20): ahí solo hay input y textarea.
   La flecha va como background porque appearance:none se lleva puesta
   la nativa, y sin flecha el campo se lee como un input de texto. */
.field select {
  width: 100%;
  padding: .8rem 2.4rem .8rem 1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background-color: var(--bg);
  color: var(--heading);
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-opacity='.55' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right .9rem center;
  background-size: 18px;
  transition: border-color var(--dur) var(--ease), background-color var(--dur) var(--ease);
}
.field select:focus {
  outline: none;
  border-color: var(--accent);
  background-color: var(--surface-2);
}
/* El desplegable nativo hereda el fondo del sistema, que en Windows es
   blanco: sin esto las opciones salen en blanco sobre blanco. */
.field select option { background: var(--surface-2); color: var(--heading); }

.field__hint { font-size: var(--step--1); color: var(--text-dim); }

/* Error inline y no un resumen arriba: el usuario tiene que ver cuál
   de los campos lo frenó sin volver a leer todo el paso. */
.field__error {
  display: none;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--step--1);
  font-weight: 600;
  color: var(--danger-hi);
}
.field__error .icon { font-size: 15px; }
.field.has-error .field__error { display: flex; }
.field.has-error input,
.field.has-error select { border-color: var(--danger); }

/* Paso 3 — el obstáculo. Tarjetas y no checkboxes: es el dato de
   mayor valor comercial de todo el formulario y tiene que pesar
   visualmente más que un cuadradito de 16px. */
/* El grupo va en un <fieldset> para que el <legend> le dé nombre
   accesible al conjunto de checkboxes. La contra es que el navegador
   le pone borde y padding propios, y el recuadro se lee como una
   tarjeta más que compite con las seis opciones de adentro. */
.qform-panel fieldset { border: 0; padding: 0; margin: 0; min-width: 0; }

.opt-grid {
  display: grid;
  gap: var(--sp-3);
  grid-template-columns: minmax(0, 1fr);
}
@media (min-width: 620px) { .opt-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.opt-card {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  padding: var(--sp-4);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg);
  cursor: pointer;
  font-size: var(--step--1);
  color: var(--text);
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease),
              color var(--dur) var(--ease);
}
.opt-card:hover { border-color: var(--line-strong); color: var(--heading); }

/* El input real sigue en el DOM y recibe foco: se lo saca de la vista
   con opacidad y no con display:none, que lo haría no enfocable. */
.opt-card input,
.consent input {
  position: absolute;
  opacity: 0;
  width: 1px; height: 1px;
}
.opt-card__box {
  display: grid;
  place-items: center;
  width: 20px; height: 20px;
  margin-top: 2px;
  border: 1px solid var(--line-strong);
  border-radius: 5px;
  color: transparent;
  flex-shrink: 0;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease),
              color var(--dur) var(--ease);
}
.opt-card__box .icon { font-size: 13px; stroke-width: 3; }

/* La clase .is-checked la pone el JS. Va primero para que la regla
   con :has() gane cuando el navegador la soporta, y sea el único
   camino cuando no (Firefox < 121). */
.opt-card.is-checked {
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--heading);
}
.opt-card.is-checked .opt-card__box {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
}
.opt-card:has(input:checked) {
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--heading);
}
.opt-card:has(input:checked) .opt-card__box {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
}
.opt-card:has(input:focus-visible) { outline: 2px solid var(--accent-2); outline-offset: 2px; }

/* Consentimiento: mismo patrón que .opt-card pero sin caja de tarjeta,
   porque no es una opción de venta sino un requisito legal. */
.consent {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  font-size: var(--step--1);
  color: var(--text-dim);
  cursor: pointer;
}
.consent a { text-decoration: underline; text-underline-offset: 3px; }
.consent .opt-card__box { margin-top: 1px; }
.consent.is-checked .opt-card__box,
.consent:has(input:checked) .opt-card__box {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
}
.consent.has-error .opt-card__box { border-color: var(--danger); }

.qform__nav {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  margin-top: var(--sp-6);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--line);
}
/* El botón de avanzar siempre a la derecha, aunque en el paso 1 no
   exista el de volver: si se corre de lugar entre pasos, el usuario
   tiene que buscarlo cada vez. */
.qform__next { margin-left: auto; }
@media (max-width: 519.98px) {
  .qform__nav { flex-direction: column-reverse; align-items: stretch; }
  .qform__next { margin-left: 0; }
  .qform__nav .btn { justify-content: center; }
}

.qform__alt {
  margin-top: var(--sp-6);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--line);
  text-align: center;
  font-size: var(--step--1);
  color: var(--text-dim);
}
.qform__alt .btn { margin-top: var(--sp-4); }

/* Estados de envío. Misma paleta que .form__status (§20) pero con su
   propio bloque: este formulario no vive dentro de .form. */
.qform__status {
  display: none;
  align-items: center;
  gap: var(--sp-3);
  margin-top: var(--sp-5);
  padding: var(--sp-4);
  border-radius: var(--radius);
  font-size: var(--step--1);
  font-weight: 600;
}
.qform__status[data-state="loading"] { display: flex; background: var(--surface-2); color: var(--text); }
.qform__status[data-state="error"]   { display: flex; background: var(--danger-soft); color: var(--danger-hi); border: 1px solid rgba(223, 21, 41, .4); }
.qform__status[data-state="ok"]      { display: flex; background: rgba(5, 150, 82, .14); color: #4ADE80; border: 1px solid rgba(5, 150, 82, .4); }

/* Pantalla de gracias: reemplaza al formulario entero cuando el envío
   sale bien. Dejar los campos completados en pantalla invita a mandar
   el mismo lead dos veces. */
.qform-done { display: none; text-align: center; }
.qform-done.is-visible { display: block; }
.qform-done__icon {
  display: grid;
  place-items: center;
  width: 64px; height: 64px;
  margin: 0 auto var(--sp-5);
  border-radius: 50%;
  background: rgba(5, 150, 82, .14);
  border: 1px solid rgba(5, 150, 82, .4);
  color: #4ADE80;
  font-size: 30px;
}
.qform-done h3 { font-size: var(--step-3); margin-bottom: var(--sp-4); }
.qform-done p { color: var(--text-dim); max-width: 52ch; margin-inline: auto; }
.qform-done .btn { margin-top: var(--sp-6); }


/* Trampa de bots. Fuera del flujo con posición absoluta y no con
   display:none ni visibility:hidden: los scripts de spam saltean los
   campos ocultos por esas dos vías, pero completan los que siguen
   presentes en el layout.

   OJO: estas mismas declaraciones están repetidas en el atributo
   style= del div en el HTML, y la duplicación es deliberada. Un campo
   trampa que se vuelve visible es peor que no tenerlo — el visitante
   ve un campo que le pide no completarlo y desconfía del formulario
   entero. No puede depender de que esta hoja cargue: pasó con una
   versión cacheada de main3.css y el campo quedó a la vista arriba
   del título del paso 1. */
.qf-hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}


/* --- 30.3b Ajuste fino del cuestionario ---------------------- */
/* Correcciones y pulido sobre 30.3. Va aparte y no editado arriba
   para que se lea qué se cambió y por qué. Nada de acá toca la
   estructura del formulario ni el payload: es solo presentación. */

/* BUG DE LAYOUT (el de la captura). .qgrid es una grilla de dos
   columnas y sus ítems estiran al alto de la fila; .field es a su vez
   una grilla de filas `auto`, que con align-content por defecto
   (stretch) reparte el alto sobrante entre sus filas. Resultado: al
   aparecer el mensaje de error en "Correo corporativo", la columna
   creció, y el <input> de "Nombre y apellido" —que comparte fila— se
   estiró hasta el alto del vecino y quedó como una caja gigante.

   Con align-items:start las columnas dejan de estirarse, y el
   align-content:start protege el caso de que una .field quede alta
   por otro motivo. */
.qgrid { align-items: start; }
.qform-panel .field { align-content: start; }

/* Autocompletado de Chrome. La UA pinta el fondo del input con un
   color propio que ninguna regla de background puede sobrescribir —
   por eso el campo autocompletado se veía gris claro sobre un
   formulario oscuro. El box-shadow interior sí se dibuja encima, y
   es la única vía para recuperar el fondo del tema. */
.qform-panel input:-webkit-autofill,
.qform-panel input:-webkit-autofill:hover,
.qform-panel select:-webkit-autofill {
  -webkit-text-fill-color: var(--heading);
  -webkit-box-shadow: inset 0 0 0 100px var(--bg);
  caret-color: var(--heading);
  /* La transición larguísima es el truco conocido para que el color
     de fondo de la UA no llegue nunca a aplicarse. */
  transition: background-color 9999s ease-out 0s;
}
.qform-panel input:-webkit-autofill:focus {
  -webkit-box-shadow: inset 0 0 0 100px var(--surface-2);
}

/* Barra de pasos: el tramo de línea que sigue a un paso completado se
   pinta con el acento. Es CSS puro — .qstep.is-done ya existe y el
   conector es su hermano inmediato, así que no hace falta que el JS
   marque nada nuevo. */
.qsteps__line {
  background: var(--line-strong);
  transition: background var(--dur-slow) var(--ease);
}
.qstep.is-done + .qsteps__line { background: var(--accent-2); }

/* El círculo activo respira: un halo del color de marca en vez de un
   relleno plano. Marca dónde está parado el usuario sin agregar peso. */
.qstep.is-active .qstep__num { box-shadow: 0 0 0 4px var(--accent-soft); }
.qstep.is-done .qstep__num { box-shadow: none; }

/* Campos. Más alto de golpe (44px reales de área táctil), foco con
   anillo en vez de solo cambio de borde, y placeholder más apagado
   para que no compita con el valor escrito. */
.qform-panel .field label {
  font-size: var(--step--1);
  font-weight: 600;
  color: var(--text);
  letter-spacing: .01em;
}
.qform-panel .field input,
.qform-panel .field select {
  padding-block: .78rem;
  border-radius: 10px;
  background-color: var(--bg);
  transition: border-color var(--dur) var(--ease), background-color var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease);
}
.qform-panel .field input::placeholder { color: rgba(255, 255, 255, .32); }
.qform-panel .field input:hover:not(:focus),
.qform-panel .field select:hover:not(:focus) { border-color: var(--line-strong); }
.qform-panel .field input:focus,
.qform-panel .field select:focus {
  border-color: var(--accent);
  background-color: var(--surface-2);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

/* Error: baja el peso y sube el aire. En bold y a tamaño pleno se
   leía como una reprimenda; el trabajo del mensaje es explicar qué
   corregir, no gritar. El fade evita que aparezca de golpe. */
.field__error {
  align-items: flex-start;
  margin-top: var(--sp-1);
  font-weight: 500;
  line-height: 1.45;
  color: var(--danger-hi);
}
.field__error .icon { margin-top: .18em; }
.field.has-error .field__error,
.consent.has-error .field__error { animation: qf-error-in var(--dur) var(--ease) both; }
@keyframes qf-error-in {
  from { opacity: 0; transform: translateY(-3px); }
  to   { opacity: 1; transform: none; }
}
.field.has-error input,
.field.has-error select { box-shadow: 0 0 0 3px var(--danger-soft); }

/* El validador enfoca el primer campo inválido, y el :focus de arriba
   —más específico— le pisaba el rojo y lo pintaba de violeta: el campo
   que acababa de fallar se veía igual que uno recién seleccionado.
   El estado de error manda por encima del foco. */
.qform-panel .field.has-error input:focus,
.qform-panel .field.has-error select:focus {
  border-color: var(--danger);
  box-shadow: 0 0 0 3px var(--danger-soft);
}

/* Tarjetas de obstáculo: más aire, y la marcada se levanta apenas.
   Es la pantalla donde el usuario tiene que elegir, así que el estado
   seleccionado tiene que verse de un vistazo. */
.opt-card {
  padding: var(--sp-4) var(--sp-4) var(--sp-4) var(--sp-3);
  border-radius: 10px;
  line-height: 1.45;
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease),
              color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.opt-card:hover { transform: translateY(-2px); }
.opt-card.is-checked,
.opt-card:has(input:checked) { box-shadow: inset 0 0 0 1px var(--accent); }
.opt-card__box { border-radius: 6px; }

.consent { line-height: 1.5; }

/* Pie del formulario: el botón principal manda, el de volver se
   retira. Antes competían por tener el mismo peso. */
.qform__nav { margin-top: var(--sp-7); }
.qform__back { color: var(--text-dim); border-color: var(--line); }
.qform__back:hover { color: var(--heading); }

@media (prefers-reduced-motion: reduce) {
  .field.has-error .field__error,
  .consent.has-error .field__error { animation: none; }
  .opt-card:hover { transform: none; }
}


/* El atributo `hidden` lo aplica la hoja del navegador, y cualquier
   `display` de la hoja de autor le gana por orden de cascada: .btn es
   inline-flex y .qsteps es flex, así que los botones y la barra de
   pasos que el JS oculta al llegar al último paso seguían viéndose.
   Esto devuelve al atributo el comportamiento que promete. */
.qform-panel [hidden] { display: none !important; }


/* --- 30.4 Ajustes de mobile ---------------------------------- */
/* Los dos flotantes se apoyan sobre el contenido, y a 56+44px tapaban
   media línea de titular en pantallas de 360. Se achican y se juntan
   al borde: siguen a un pulgar de distancia y dejan de competir con
   el texto. */
@media (max-width: 600px) {
  .wa-float { width: 50px; height: 50px; right: 14px; bottom: 14px; }
  .wa-float svg { width: 25px; height: 25px; }
  /* Sin tip: en táctil no hay hover que lo dispare, solo suma ancho */
  .wa-float__tip { display: none; }
  .scroll-top { width: 40px; height: 40px; right: 14px; bottom: 74px; font-size: 18px; }
}

/* La franja de sistemas tiene tres filas de placas de 104px: en 360px
   entran tres por fila y el bloque mide media pantalla. Placas más
   chicas, que es como se lee en vertical. */
@media (max-width: 619.98px) {
  .trust-items { gap: var(--sp-4); }
  .trust-item { width: 78px; }
  .trust-item__mark { width: 52px; height: 52px; font-size: 27px; }
}

/* .role-tabs__nav es flex-wrap: con cuatro pestañas y una bajada cada
   una, en mobile quedaban cuatro filas y la primera tarjeta del panel
   arrancaba fuera de pantalla. Con scroll horizontal las cuatro se
   leen en una línea y se entiende que hay más a la derecha. */
@media (max-width: 780px) {
  .ent .role-tabs__nav {
    flex-wrap: nowrap;
    overflow-x: auto;
    scroll-snap-type: x proximity;
    /* El padding compensa el translateY(-2px) del hover y el outline
       de foco, que si no quedan recortados por el overflow. */
    padding-block: 4px;
    margin-inline: calc(-1 * var(--wrap-pad));
    padding-inline: var(--wrap-pad);
    scrollbar-width: none;
  }
  .ent .role-tabs__nav::-webkit-scrollbar { display: none; }
  .ent .role-tabs__btn { flex-shrink: 0; scroll-snap-align: start; }
}


/* --- 30.5 Panel de prueba (solo desarrollo) ------------------ */
/* No se envía nunca en producción: el JS solo inyecta este panel si
   la URL trae ?debug=1 / #debug, o si la página se abrió desde
   localhost o file://. En un dominio real, sin el parámetro, este
   bloque de CSS queda inerte — no hay markup que lo use.

   Existe porque probar el webhook obliga a completar tres pasos de
   formulario por cada intento, y en modo test n8n acepta una sola
   llamada por clic en "Execute workflow": el ciclo de prueba se
   vuelve impracticable a mano. */
.devbar {
  position: fixed;
  left: 14px; bottom: 14px;
  z-index: 95;
  width: min(340px, calc(100vw - 28px));
  padding: var(--sp-4);
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  background: rgba(10, 10, 12, .96);
  backdrop-filter: blur(8px);
  box-shadow: var(--shadow-lg);
  font-size: var(--step--1);
}
.devbar__title {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-bottom: var(--sp-3);
  font-family: var(--font-head);
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  font-size: .7rem;
  color: var(--accent-hi);
}
.devbar__close { margin-left: auto; color: var(--text-dim); font-size: 18px; line-height: 1; }
.devbar__close:hover { color: var(--heading); }

.devbar__row { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.devbar button[data-dev] {
  padding: .45rem .8rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-pill);
  color: var(--text);
  font-size: var(--step--1);
  font-weight: 600;
  transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease),
              background var(--dur) var(--ease);
}
.devbar button[data-dev]:hover { border-color: var(--accent); color: var(--heading); background: var(--accent-soft); }

/* La salida del probe: es lo que reemplaza a leer la respuesta de
   curl en una terminal, así que tiene que mostrar el cuerpo del
   error de n8n completo y ser seleccionable para copiarlo. */
.devbar__out {
  display: none;
  max-height: 190px;
  margin-top: var(--sp-3);
  padding: var(--sp-3);
  overflow: auto;
  border-radius: 6px;
  background: #000;
  border: 1px solid var(--line);
  color: var(--text);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 11px;
  line-height: 1.5;
  white-space: pre-wrap;
  word-break: break-word;
  user-select: text;
}
.devbar__out.is-visible { display: block; }
.devbar__out b { color: #4ADE80; }
.devbar__out i { color: var(--danger-hi); font-style: normal; }


/* --- 30.6 Reduced motion ------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .sector-card__img { transition: none; transform: none; }
  .sector-card:hover .sector-card__img { transform: none; }
  .sector-card:hover, .testi-card:hover { transform: none; }
  .qpanel.is-mounted { opacity: 1; transform: none; }
}


/*--------------------------------------------------------------
# 31. Enterprise — Footer

  Rediseño del pie. Todo cuelga de `.ent`: main3.css lo comparten el
  sitio y la landing de Manufactura, y el footer de esos dos no se
  toca.

  Qué estaba mal en el anterior. La grilla era
  `repeat(auto-fit, minmax(220px, 1fr))`, o sea cuatro columnas de
  ancho idéntico. Con eso, la bajada de marca partía en cinco líneas
  dentro de 250px mientras las dos listas de enlaces dejaban medio
  ancho vacío, y los tres datos de contacto —que son el único camino
  de conversión que queda al final de la página— pesaban exactamente
  lo mismo que un ítem de navegación.

  Qué cambia:
    · anchos por función y no iguales (1.6 / 1 / 1 / 1.3)
    · títulos de columna en versalitas chicas, para que el contenido
      pese más que sus etiquetas
    · los canales de contacto pasan a placa + etiqueta + valor
    · un CTA real en la columna de contacto
    · bloque de gobernanza en tarjetas
--------------------------------------------------------------*/

/* Filo de luz sobre el borde superior: el mismo gesto que la barra de
   progreso del header, y separa el pie del cuerpo sin una línea dura
   más en una página que ya tiene muchas. */
.ent .footer {
  position: relative;
  padding-block: var(--sp-10) var(--sp-6);
}
.ent .footer::before {
  content: "";
  position: absolute;
  top: -1px; left: 0; right: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--accent), var(--accent-2), transparent);
  opacity: .5;
}

/* --- 31.1 Gobernanza en tarjetas ----------------------------- */
/* Sueltos sobre el fondo, los tres ítems se leían como notas al pie.
   En tarjeta se leen como lo que son: requisitos que el área de TI
   del cliente va a querer verificar. */
.ent .compliance-block {
  gap: var(--sp-4);
  margin-bottom: var(--sp-9);
  padding-bottom: var(--sp-9);
}
.ent .compliance-item {
  padding: var(--sp-5);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--surface);
  transition: border-color var(--dur) var(--ease);
}
.ent .compliance-item:hover { border-color: var(--line-strong); }
.ent .compliance-item .icon-box {
  background: var(--accent-2-soft);
  color: var(--accent-2);
}

/* --- 31.2 Grilla --------------------------------------------- */
.ent .footer__grid {
  display: grid;
  gap: var(--sp-8) var(--sp-7);
  grid-template-columns: minmax(0, 1fr);
  margin-bottom: var(--sp-8);
}
/* En dos columnas la marca ocupa la fila entera: su párrafo mide más
   que cualquiera de las listas y, encajonado en media fila, vuelve al
   problema que este rediseño viene a resolver. */
@media (min-width: 620px) {
  .ent .footer__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ent .footer__brand { grid-column: 1 / -1; max-width: 62ch; }
}
@media (min-width: 980px) {
  .ent .footer__grid {
    grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1.3fr);
    gap: var(--sp-7);
  }
  .ent .footer__brand { grid-column: auto; max-width: none; }
}

/* --- 31.3 Columna de marca ----------------------------------- */
/* §28.1 apila el logo y su bajada en el footer porque en la grilla
   vieja la columna daba 250px y "DaIA | Command Center" mide 266. En
   la nueva, esta columna pasa de 300px desde 980, así que vuelve a
   entrar en línea con su separador — que es como se ve en el header. */
@media (min-width: 980px) {
  .ent .footer__brand .header__logo { flex-direction: row; align-items: center; }
  .ent .footer__brand .logo-sub {
    margin-left: var(--sp-3);
    padding-left: var(--sp-3);
    border-left: 1px solid var(--line-strong);
  }
}
.ent .footer__brand .header__logo { margin-bottom: var(--sp-5); }
.ent .footer__blurb {
  font-size: var(--step--1);
  color: var(--text-dim);
  max-width: 46ch;
}

/* --- 31.4 Títulos y listas ----------------------------------- */
/* Versalitas chicas en vez de un h4 a tamaño de cuerpo: el título de
   una columna es una etiqueta, no contenido, y compitiendo en tamaño
   con sus propios enlaces hacía que las cuatro columnas se leyeran
   como cuatro bloques de texto. */
.ent .footer h4 {
  margin-bottom: var(--sp-5);
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--text-dim);
}

.ent .footer__links li + li { margin-top: 0; }
.ent .footer__links a {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding-block: var(--sp-2);
  font-size: var(--step--1);
  color: var(--text-dim);
  transition: color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
/* El desplazamiento al pasar por encima confirma que la línea es un
   enlace: en una lista sin viñetas ni subrayado, el color solo no
   alcanza para que se lea como clickeable. */
.ent .footer__links a:hover { color: var(--heading); transform: translateX(3px); }
.ent .footer__links .icon { color: var(--accent-hi); font-size: 16px; margin-right: 0; }
.ent .footer__links--tech a { font-variant-numeric: tabular-nums; }

/* --- 31.5 Contacto ------------------------------------------- */
.ent .footer__contact { display: grid; gap: var(--sp-3); }
.ent .footer__contact li + li { margin-top: 0; }
.ent .footer__contact a {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-2);
  margin-inline: calc(-1 * var(--sp-2));
  border-radius: var(--radius);
  transition: background var(--dur) var(--ease);
}
.ent .footer__contact a:hover { background: rgba(255, 255, 255, .04); }

.ent .footer__chip {
  display: grid;
  place-items: center;
  width: 36px; height: 36px;
  flex-shrink: 0;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--surface);
  color: var(--accent-hi);
  font-size: 17px;
  transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease),
              background var(--dur) var(--ease);
}
.ent .footer__contact a:hover .footer__chip {
  border-color: var(--accent);
  background: var(--accent-soft);
}
/* El verde de WhatsApp y no el violeta de marca: es el color con el
   que la gente reconoce el canal, y acá el objetivo es que se note. */
.ent .footer__chip--wa { color: #25D366; }
.ent .footer__contact a:hover .footer__chip--wa {
  border-color: rgba(37, 211, 102, .5);
  background: rgba(37, 211, 102, .12);
}

.ent .footer__meta { display: grid; gap: 1px; min-width: 0; }
.ent .footer__meta-label {
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--text-dim);
}
.ent .footer__meta-val {
  font-size: var(--step--1);
  color: var(--text);
  overflow-wrap: anywhere;
  transition: color var(--dur) var(--ease);
}
.ent .footer__contact a:hover .footer__meta-val { color: var(--heading); }

/* Última oportunidad de conversión de la página: quien llegó hasta acá
   leyó todo y no hizo clic en nada. */
.ent .footer__cta { margin-top: var(--sp-6); }

/* --- 31.6 Pie ------------------------------------------------ */
.ent .footer__bottom {
  padding-top: var(--sp-6);
  font-size: var(--step--1);
  color: var(--text-dim);
}
/* A la derecha en pantallas anchas y debajo en angostas: apilado, el
   `justify-content: space-between` de §21 dejaba las dos líneas
   pegadas al borde izquierdo sin separación entre sí. */
@media (max-width: 619.98px) {
  .ent .footer__bottom { flex-direction: column; align-items: flex-start; gap: var(--sp-2); }
}
.ent .footer__bottom-note { opacity: .8; }

@media (prefers-reduced-motion: reduce) {
  .ent .footer__links a:hover { transform: none; }
}


/*--------------------------------------------------------------
# 32. Enterprise — Galería de tutoriales en video

  Sección de mayor peso visual de la página, y a propósito: son las
  únicas piezas donde el producto se ve funcionando, y el pedido fue
  que resalte. Se destaca con superficie y escala —marco grande,
  resplandor de fondo, riel de miniaturas— y no con movimiento: un
  bloque que se mueve al lado de un video compite con el video.

  Todo cuelga de `.ent` o de clases nuevas (.vidsec, .vgal, .vthumb):
  main3.css lo comparten el sitio y la landing de Manufactura.

  Decisiones de layout que dependen del material real:

  · Los cuatro videos son 1280x684 (1.871:1, más ancho que 16:9). El
    marco usa exactamente esa proporción, así que ninguno se recorta
    ni queda con bandas del navegador. Si algún día se reemplazan por
    videos 16:9, hay un solo número que cambiar: --vgal-ar.

  · El marco va en negro puro. Tres de los cuatro videos traen barras
    negras incrustadas de ~50px; sobre un marco negro no se leen como
    un defecto del reproductor.

  · Las flechas viven en el margen exterior del marco desde 1080px, y
    recién por debajo se superponen al video. Encima del video tapan
    la zona donde estos tutoriales muestran el cursor y los menús
    laterales de la aplicación.
--------------------------------------------------------------*/

.vidsec {
  --vgal-ar: 1280 / 684;      /* proporción real de los cuatro videos */
  position: relative;
  overflow: hidden;           /* contiene el resplandor */
}

/* Resplandor detrás del marco: es lo que hace que la sección se lea
   como el centro de la página sin necesidad de cambiar el fondo ni
   agregar un borde. Decorativo puro, por eso es un <span> vacío. */
.vidsec__glow {
  position: absolute;
  top: 12%;
  left: 50%;
  width: min(1180px, 130vw);
  aspect-ratio: 1;
  transform: translateX(-50%);
  background:
    radial-gradient(circle, var(--accent-soft) 0%, transparent 58%),
    radial-gradient(circle at 60% 40%, var(--accent-2-soft) 0%, transparent 46%);
  pointer-events: none;
  z-index: 0;
}
.vidsec .wrap { position: relative; z-index: 1; }


/* --- 32.1 Escenario ------------------------------------------ */
.vgal { display: grid; gap: var(--sp-5); }

.vgal__stage {
  position: relative;
  display: grid;
  align-items: center;
  grid-template-columns: minmax(0, 1fr);
}
/* Tres columnas desde 1080: flecha | marco | flecha. El marco toma el
   ancho que sobra, así que no hay que calcularle nada. */
@media (min-width: 1080px) {
  .vgal__stage {
    grid-template-columns: auto minmax(0, 1fr) auto;
    gap: var(--sp-4);
  }
}

.vgal__frame {
  position: relative;
  aspect-ratio: var(--vgal-ar);
  overflow: hidden;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg);
  /* Negro puro y no var(--surface): las barras incrustadas de tres de
     los videos tienen que fundirse con el marco. */
  background: #000;
  box-shadow: var(--shadow-lg), 0 0 0 1px rgba(87, 90, 255, .18);
}

.vgal__video {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: contain;
}


/* --- 32.2 Cubierta y botón de reproducción ------------------- */
/* El <video> con preload="none" no descarga nada, pero tampoco pinta
   su póster de forma consistente entre navegadores. La cubierta es
   una imagen real encima: se controla el encuadre, el velo y el
   botón, y se puede volver a mostrar cuando el video termina. */
.vgal__cover {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  cursor: pointer;
  transition: opacity var(--dur) var(--ease), visibility var(--dur) var(--ease);
}
.vgal__cover.is-gone { opacity: 0; visibility: hidden; }

.vgal__cover-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
}
/* Oscurece el fotograma para que el botón y su texto tengan contraste
   sobre cualquiera de los cuatro pósters, que son tableros claros. */
.vgal__cover-veil {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg, rgba(7, 7, 8, .34) 0%, rgba(7, 7, 8, .62) 100%),
    radial-gradient(60% 60% at 50% 50%, rgba(7, 7, 8, .3), transparent 70%);
}

.vgal__play {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--sp-4);
  max-width: min(92%, 520px);
  padding: var(--sp-3) var(--sp-5) var(--sp-3) var(--sp-3);
  border: 1px solid rgba(255, 255, 255, .16);
  border-radius: var(--radius-pill);
  background: rgba(10, 10, 12, .58);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  text-align: left;
  transition: transform var(--dur) var(--ease), border-color var(--dur) var(--ease),
              background var(--dur) var(--ease);
}
.vgal__cover:hover .vgal__play {
  transform: translateY(-2px);
  border-color: var(--accent);
  background: rgba(10, 10, 12, .72);
}

.vgal__play-ring {
  display: grid;
  place-items: center;
  width: 52px; height: 52px;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--accent);
  color: var(--on-accent);
  font-size: 20px;
  transition: background var(--dur) var(--ease);
}
.vgal__cover:hover .vgal__play-ring { background: var(--accent-hi); }
/* El glifo es un triángulo: centrado óptico, no geométrico */
.vgal__play-ring .icon { margin-left: 2px; }

.vgal__play-txt { display: grid; gap: 2px; min-width: 0; }
.vgal__play-kicker {
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--accent-2);
}
.vgal__play-title {
  font-family: var(--font-head);
  font-size: var(--step-1);
  font-weight: 700;
  line-height: 1.2;
  color: var(--heading);
}


/* Colisión con las flechas. Por debajo de 1080px las flechas se
   superponen al marco (32.3), y la píldora al 92% del ancho les pasa
   por debajo: el chevron quedaba encima del título.

   Dos respuestas según el espacio real:
   · hasta 640px la píldora pierde el texto y queda solo el círculo. No
     se pierde información: el nombre del tutorial ya está en la
     miniatura activa del riel y en la descripción, justo debajo.
   · entre 641 y 1079 hay lugar para el texto, pero se le reserva el
     ancho de las dos flechas más su margen. */
@media (max-width: 1079.98px) {
  .vgal__play { max-width: calc(100% - 140px); }
}
@media (max-width: 640px) {
  .vgal__play {
    max-width: none;
    gap: 0;
    padding: var(--sp-2);
    border-radius: 50%;
  }
  .vgal__play-txt { display: none; }
}


/* --- 32.3 Flechas ------------------------------------------- */
.vgal__arrow {
  display: grid;
  place-items: center;
  width: 48px; height: 48px;
  border: 1px solid var(--line-strong);
  border-radius: 50%;
  background: rgba(10, 10, 12, .72);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  color: var(--heading);
  font-size: 22px;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease),
              transform var(--dur) var(--ease), opacity var(--dur) var(--ease);
}
.vgal__arrow:hover { background: var(--accent); border-color: var(--accent); }
.vgal__arrow--prev:hover { transform: translateX(-2px); }
.vgal__arrow--next:hover { transform: translateX(2px); }

/* Debajo de 1080 no hay margen exterior donde ponerlas: se superponen
   al marco, centradas en vertical y pegadas a los bordes. */
@media (max-width: 1079.98px) {
  .vgal__arrow {
    position: absolute;
    top: 50%;
    z-index: 2;
    transform: translateY(-50%);
    width: 42px; height: 42px;
    font-size: 19px;
  }
  .vgal__arrow--prev { left: var(--sp-3); }
  .vgal__arrow--next { right: var(--sp-3); }
  .vgal__arrow--prev:hover, .vgal__arrow--next:hover { transform: translateY(-50%); }

  /* Mientras el video se está reproduciendo las flechas se apagan:
     encima de los controles nativos son un blanco falso, y en táctil
     el usuario intenta usar la barra de progreso y cambia de video. */
  .vgal.is-playing .vgal__arrow { opacity: 0; pointer-events: none; }
}


/* Pista de pantalla completa. Solo por debajo de 700px, que es el
   umbral donde el JS pide fullscreen al reproducir: en desktop el
   marco ya mide casi 1000px y la frase sobra. */
.vgal__hint { display: none; }
@media (max-width: 700px) {
  .vgal__hint {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    margin-top: var(--sp-1);
    font-size: var(--step--1);
    color: var(--text-dim);
  }
  .vgal__hint .icon { color: var(--accent-2); font-size: 13px; flex-shrink: 0; }
}


/* --- 32.4 Barra de contador y descripción ------------------- */
.vgal__bar {
  display: grid;
  gap: var(--sp-3);
  align-items: start;
}
@media (min-width: 760px) {
  .vgal__bar { grid-template-columns: auto minmax(0, 1fr); gap: var(--sp-6); }
}

.vgal__count {
  display: flex;
  align-items: baseline;
  gap: var(--sp-2);
  font-family: var(--font-head);
  font-weight: 700;
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.vgal__count b { font-size: var(--step-3); color: var(--accent-2); }
.vgal__count span { font-size: var(--step-1); color: var(--text-dim); }

.vgal__desc {
  font-size: var(--step-0);
  color: var(--text-dim);
  max-width: 68ch;
}


/* --- 32.5 Riel de miniaturas -------------------------------- */
.vgal__rail {
  display: grid;
  gap: var(--sp-3);
  grid-template-columns: repeat(2, minmax(0, 1fr));
  margin-top: var(--sp-3);
}
@media (min-width: 900px) { .vgal__rail { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
/* En 360px dos columnas dejan la miniatura en 150px y el nombre en tres
   líneas. Una sola columna, en fila horizontal, se lee mejor. */
@media (max-width: 519.98px) { .vgal__rail { grid-template-columns: minmax(0, 1fr); } }

.vthumb {
  display: grid;
  gap: var(--sp-3);
  width: 100%;
  padding: var(--sp-3);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  text-align: left;
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease),
              transform var(--dur) var(--ease);
}
@media (max-width: 519.98px) {
  .vthumb { grid-template-columns: 108px minmax(0, 1fr); align-items: center; }
}
.vthumb:hover { border-color: var(--line-strong); transform: translateY(-2px); }

.vthumb.is-active {
  border-color: var(--accent);
  background: var(--accent-soft);
}
.vthumb.is-active .vthumb__num { background: var(--accent); color: var(--on-accent); }
.vthumb.is-active .vthumb__name { color: var(--heading); }
.vthumb.is-active .vthumb__shot img { filter: none; }

.vthumb__shot {
  position: relative;
  display: block;
  overflow: hidden;
  border-radius: 8px;
  background: #000;
  aspect-ratio: var(--vgal-ar);
}
.vthumb__shot img {
  width: 100%; height: 100%;
  object-fit: cover;
  /* Las inactivas atenuadas: deja claro cuál se está viendo sin
     necesidad de un borde más grueso. */
  filter: grayscale(.4) brightness(.62);
  transition: filter var(--dur) var(--ease);
}
.vthumb:hover .vthumb__shot img { filter: grayscale(0) brightness(.85); }

/* Glifo de reproducción sobre la miniatura: sin él, las cuatro placas
   se leen como capturas y no como videos. */
.vthumb__glyph {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  color: #fff;
  font-size: 20px;
  text-shadow: 0 2px 8px rgba(0, 0, 0, .6);
  opacity: .78;
  transition: opacity var(--dur) var(--ease);
}
.vthumb:hover .vthumb__glyph, .vthumb.is-active .vthumb__glyph { opacity: 1; }

.vthumb__meta {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-width: 0;
}
.vthumb__num {
  display: grid;
  place-items: center;
  width: 26px; height: 26px;
  flex-shrink: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, .07);
  color: var(--text-dim);
  font-family: var(--font-head);
  font-size: .7rem;
  font-weight: 700;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.vthumb__name {
  font-size: var(--step--1);
  font-weight: 600;
  line-height: 1.35;
  color: var(--text-dim);
  transition: color var(--dur) var(--ease);
}


/* --- 32.6 Reduced motion ------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  .vgal__cover:hover .vgal__play,
  .vthumb:hover,
  .vgal__arrow:hover { transform: none; }
  .vgal__arrow--prev:hover, .vgal__arrow--next:hover { transform: none; }
}

/*--------------------------------------------------------------
# 33. Aviso de Privacidad — marcador de datos pendientes

  Resalta en pantalla los tres datos que solo puede completar el
  cliente: razon social, domicilio fiscal y RFC. Se ve, y molesta a
  proposito: un aviso de privacidad publicado con marcadores es
  incomodo, pero uno publicado con una razon social inventada es un
  problema legal. Al completarlos se borra la clase y listo.
--------------------------------------------------------------*/
.dato-pendiente {
  display: inline;
  padding: .1em .45em;
  border: 1px dashed var(--danger);
  border-radius: 6px;
  background: var(--danger-soft);
  color: var(--danger-hi);
  font-weight: 600;
  font-size: .92em;
}

/* El pie del aviso no necesita el separador del footer general */
.prose code {
  padding: .12em .4em;
  border-radius: 4px;
  background: rgba(255, 255, 255, .07);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: .9em;
  color: var(--accent-2);
}


/*--------------------------------------------------------------
# 34. Enterprise — franja de sistemas del bloque de solución
--------------------------------------------------------------*/
/* .dash-dynamic (§26.4) reparte icono | texto | chips en tres
   columnas, y funciona cuando los chips son de dos palabras
   ("Línea y turno", "Excel y PDF"). Acá los chips son listas de
   sistemas —SAP · Dynamics · Oracle · Odoo— y se llevan el ancho:
   el párrafo quedaba exprimido en 230px y siete líneas.

   Con este modificador el texto toma el ancho que le corresponde y
   los chips bajan a su propia fila, alineados bajo el texto y no
   bajo el icono. */
@media (min-width: 900px) {
  .dash-dynamic--sistemas { grid-template-columns: auto minmax(0, 1fr); }
  .dash-dynamic--sistemas .dash-dynamic__chips { grid-column: 2; }
}

/*--------------------------------------------------------------
# 35. Enterprise — cierre orientado a conversión

  El bloque de demostración se reordenó siguiendo cómo decide una
  persona, no cómo se describe un producto:

    gancho        el titular pregunta, no afirma
    seguridad     las tres objeciones de TI, ANTES de pedir datos
    formulario
    qué sigue     quita la incertidumbre de lo que viene después

  La tranquilidad ya existía en la página, pero estaba debajo del
  formulario: la leía quien ya se había convencido.
--------------------------------------------------------------*/

/* Línea que entrega el formulario. Centrada y con más aire que un
   párrafo normal: es la última frase antes de pedir datos. */
.demo-intro {
  max-width: 62ch;
  margin: 0 auto var(--sp-7);
  text-align: center;
  font-size: var(--step-0);
  color: var(--text-dim);
}
.demo-intro strong { color: var(--text); }
.demo-intro a { text-decoration: underline; text-underline-offset: 3px; }

/* CTA de dos líneas: el beneficio arriba, la acción concreta abajo.
   El botón es inline-flex, así que las dos líneas necesitan su propio
   contenedor en grid o se acomodan una al lado de la otra. */
.btn__lines { display: grid; gap: 2px; text-align: left; }
.btn__main { font-weight: 700; line-height: 1.2; }
.btn__sub {
  font-size: .72em;
  font-weight: 500;
  line-height: 1.2;
  opacity: .78;
}
/* Apilado en móvil el botón ocupa todo el ancho y el texto a la
   izquierda queda descolgado del centro óptico. */
@media (max-width: 519.98px) {
  .btn__lines { text-align: center; justify-items: center; }
}

/* Pasos numerados. Reutiliza .info-card y solo cambia el contenido de
   la caja de icono por un número, con la tipografía de titulares para
   que se lea como una secuencia y no como tres viñetas sueltas. */
.pasos { margin-top: var(--sp-9); }
.pasos__titulo {
  margin-bottom: var(--sp-5);
  text-align: center;
  font-family: var(--font-head);
  font-size: var(--step-1);
  font-weight: 700;
  color: var(--heading);
}
.pasos ol { counter-reset: none; }
.pasos .info-card { height: 100%; padding: var(--sp-5) var(--sp-5) var(--sp-6); }
.pasos .info-card h4 { min-height: calc(2 * 1.15em); }
.icon-box--num {
  font-family: var(--font-head);
  font-size: var(--step-2);
  font-weight: 700;
  line-height: 1;
  color: var(--accent-hi);
}

/*--------------------------------------------------------------
# 36. Enterprise — botón de WhatsApp
--------------------------------------------------------------*/
/* .btn ya resuelve fondo, borde y texto con variables, así que el
   modificador es solo cambiar los tres valores. El verde es el de
   la marca WhatsApp (#25D366), el mismo del flotante de §23. */
.btn--wa {
  --btn-bg: #25D366;
  --btn-bd: #25D366;
  --btn-fg: #ffffff;
}
.btn--wa:hover { --btn-bg: #1FBE58; --btn-bd: #1FBE58; }

/* .wa-cta pone el glifo en 22px, que es correcto para el CTA grande
   del cierre pero desproporcionado dentro de un .btn--sm del header. */
.btn--sm.wa-cta .icon { font-size: 17px; }

/*--------------------------------------------------------------
# 37. Enterprise — formulario de un solo paso
--------------------------------------------------------------*/
/* Sin barra de pasos ni botones de navegación: el pie del formulario
   es un único botón a ancho completo. .qform__next ya no existe, así
   que el margin-left:auto de §30.3 no aplica. */
.qform__nav .btn--block { justify-content: center; }

/* Aviso simplificado bajo el botón. Reemplaza a la casilla de
   consentimiento: con el aviso a la vista, el art. 8 de la LFPDPPP
   admite consentimiento tácito para datos no sensibles. Va discreto
   pero legible — no es letra chica escondida. */
.qform__consent {
  margin-top: var(--sp-4);
  text-align: center;
  font-size: var(--step--1);
  line-height: 1.5;
  color: var(--text-dim);
}
.qform__consent a {
  color: var(--text);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.qform__consent a:hover { color: var(--heading); }