/* ============================================================
   GERPRO — Subsitios de servicio.
   Mismo lenguaje visual del cubo (vidrio holografico, hairlines
   menta, HUD en esquinas, display Archivo) pero con el color de
   cada servicio inyectado en --c desde PHP. Requiere tokens.css.
   ============================================================ */

/* --c y --c2 los pone el template en el <body>; estos son el respaldo. */
body{ --c:var(--teal); --c2:var(--menta); }

/* Cada subsitio tiene su propio _ds/*-design-system, con su propia escala de
   radios — distinta entre si y de la del home (gerpro-design-system). El
   template pone data-servicio en el body (page-servicio.php); cada bloque
   solo pisa los pasos que de verdad difieren del valor por defecto de
   tokens.css (xs4/sm6/md8/lg12/xl20), no la escala completa. */
body[data-servicio="mafp"]{
  /* _ds/mafp-design-system/tokens/spacing.css */
  --radius-xs:3px; --radius-sm:5px; --radius-xl:18px;
}
body[data-servicio="datamax"]{
  /* _ds/datamax-design-system/tokens/spacing.css */
  --radius-xs:3px; --radius-sm:5px; --radius-xl:16px;
}
body[data-servicio="forecast"]{
  /* _ds/forecast-design-system/tokens/spacing.css — escala mas corta (sin
     paso xs ni xl propios): su "lg" es el radio grande de la marca, hace
     de --radius-xl aqui. */
  --radius-sm:4px; --radius-xl:16px;
}
body[data-servicio="ingemax"]{
  /* _ds/ingemax-design-system/tokens/shape.css */
  --radius-md:10px; --radius-lg:16px; --radius-xl:24px;
}
body[data-servicio="crewcore"]{
  /* _ds/crew-core-design-system/tokens/radius.css (--cc-radius-*) */
  --radius-xs:3px; --radius-sm:5px; --radius-lg:14px; --radius-xl:22px;
}
body[data-servicio="leanbuilt"]{
  /* _ds/lean-built-design-system/tokens/spacing.css — "la geometria del
     hexagono/cubo favorece esquinas chicas y nitidas" segun su propio
     comentario de origen. */
  --radius-xs:3px; --radius-sm:5px; --radius-xl:16px;
}

/* ---------- Fondo vivo ----------
   tokens.css pone la base (dos radiales fijos + degrade) igual en el home y
   aqui; lo que hace sentir "vivo" al home encima de eso son las auras que
   derivan lento (#heroFx en ecosistema.css). El resto de ese motor — piso en
   perspectiva, barrido de luz, red neuronal en canvas — es apropiado para
   una sola pantalla de impacto, pero en un subsitio de scroll largo, con
   texto real que leer, seria ruido compitiendo por atencion y presupuesto
   de fotograma en toda la pagina. Se porta solo la pieza barata: dos auras
   con el color propio del servicio (--c/--c2, no un lila generico), asi el
   fondo respira igual que el home sin pelearse con la lectura. */
.sub-fx{ position:fixed; inset:0; z-index:-1; overflow:hidden; pointer-events:none; }
.sub-fx::before, .sub-fx::after{
  content:''; position:absolute; border-radius:50%; will-change:transform;
}
.sub-fx::before{
  width:min(64vw, 760px); aspect-ratio:1; left:-16vw; top:-22vh;
  background:radial-gradient(circle, color-mix(in srgb, var(--c) 38%, transparent) 0%, transparent 68%);
  animation:sub-aura-a 32s ease-in-out infinite alternate;
}
.sub-fx::after{
  width:min(54vw, 660px); aspect-ratio:1; right:-14vw; bottom:-22vh;
  background:radial-gradient(circle, color-mix(in srgb, var(--c2) 32%, transparent) 0%, transparent 66%);
  animation:sub-aura-b 38s ease-in-out infinite alternate;
}
@keyframes sub-aura-a{ from{ transform:translate3d(0,0,0) scale(1); } to{ transform:translate3d(5vw,4vh,0) scale(1.14); } }
@keyframes sub-aura-b{ from{ transform:translate3d(0,0,0) scale(1.06); } to{ transform:translate3d(-5vw,-4vh,0) scale(.92); } }
@media (prefers-reduced-motion: reduce){
  .sub-fx::before, .sub-fx::after{ animation:none; }
}

/* ---------- Cabecera ---------- */
.sub-header{
  position:fixed; top:0; left:0; right:0; z-index:60;
  display:flex; align-items:center; justify-content:space-between;
  gap:24px; padding:16px clamp(18px, 4vw, 54px);
  background:rgba(20,23,51,.72);
  backdrop-filter:blur(16px) saturate(1.4); -webkit-backdrop-filter:blur(16px) saturate(1.4);
  border-bottom:1px solid var(--hair);
}
.sub-header .hlogo{ height:30px; display:block; }
/* El logo respira con un brillo tenue del color propio del servicio —mismo
   lenguaje que .glogo, el nucleo del cubo en el home— y crece un poco al
   pasar el mouse. El header dejaba de sentirse estatico con esto. */
.sub-header .logo{ display:inline-block; transition:transform .3s ease; }
.sub-header .logo:hover{ transform:scale(1.06); }
.sub-header .hlogo{ animation:header-logo-pulse 4.4s ease-in-out infinite; }
@keyframes header-logo-pulse{
  0%, 100%{ filter:drop-shadow(0 0 0 transparent); }
  50%{ filter:drop-shadow(0 0 12px color-mix(in srgb, var(--c) 60%, transparent)); }
}
@media (prefers-reduced-motion: reduce){
  .sub-header .hlogo{ animation:none; }
}
.sub-header nav{ display:flex; align-items:center; gap:clamp(14px, 2.4vw, 30px); }
/* :not(.btn) es imprescindible. Sin el, esta regla gana en especificidad
   (0,1,2) al `.btn-1` (0,1,0) y le impone al CTA de la cabecera el color de
   texto claro y una opacidad del 62%: el boton queda lavado e ilegible. */
.sub-header nav a:not(.btn){
  font-size:13px; font-weight:500; color:var(--ink); text-decoration:none;
  opacity:.62; transition:opacity .2s;
}
.sub-header nav a:not(.btn):hover{ opacity:1; }
/* En Gerpro IA² y Gerpro X esta cabecera convive con ecosistema.css, que trae
   su propio `nav a{text-transform:uppercase; letter-spacing:.14em}` (pensado
   para el nav del home). Ninguna regla de arriba lo neutraliza — ni siquiera
   el `.btn-1`, que tampoco fija estas dos propiedades — asi que en esas dos
   paginas el nav entero y el CTA se veian en mayusculas y mas separados que
   en el resto de subsitios: mismo tamaño de fuente, pero mas "grande" a la
   vista. Sin :not(.btn): las dos propiedades no chocan con el color/opacidad
   que el comentario de arriba protege.*/
.sub-header nav a{ text-transform:none; letter-spacing:normal; }
.sub-header .volver{ display:inline-flex; align-items:center; gap:7px; }
@media (max-width:860px){
  .sub-header nav a.opt{ display:none; }
}

/* ---------- Menu movil (hamburguesa) ----------
   El logo trae el wordmark completo ("Impulsamos Empresas Rentables") en el
   mismo SVG, con una proporcion muy ancha (1080x135, 8:1): a los 30px de
   alto de escritorio, en movil ocupa ~240px y no deja sitio para el resto
   del nav (Productos, el CTA). En vez de ir comprimiendo cada elemento para
   que quepan todos en una sola fila, el nav completo se convierte en un
   panel desplegable — mismo lenguaje visual que el panel de Productos
   (.prod-m), asi que no se ve como un componente distinto. */
/* El boton en si (.sub-burger) vive en nav.css: lo comparte esta cabecera
   y la del home. Aqui solo queda a que ancho aparece (mas abajo). */

@media (max-width:760px){
  .sub-header{ padding:14px clamp(16px, 4vw, 24px); gap:14px; }
  .sub-header .hlogo{ height:24px; }
  .sub-burger{ display:inline-flex; }

  /* Con el hamburguesa como unico control visible, el nav pasa de fila a
     panel: mismo posicionamiento fijo, ancho y sombra que .prod-m para que
     luzca como el mismo sistema de componentes. [hidden] lo saca del arbol
     de accesibilidad cuando esta cerrado (lo pone/quita nav.js). */
  .sub-header nav{
    position:fixed; top:64px; right:12px; left:auto;
    width:min(300px, calc(100vw - 24px));
    flex-direction:column; align-items:stretch; gap:2px;
    padding:10px; border-radius:16px;
    /* Mismo tratamiento de profundidad que .prod-m/.card en vez del navy
       plano de antes — este panel SI puede usar --c/--surf-b/--surf-c sin
       fallback, a diferencia de nav.css: subsitio.css es lo unico que carga
       esta pagina y ya los define arriba (--c por servicio, --surf-* fijos). */
    border:1px solid color-mix(in srgb, var(--c) 48%, var(--hair));
    background:linear-gradient(155deg, color-mix(in srgb, var(--c) 34%, var(--surf-a)), var(--surf-c) 60%);
    backdrop-filter:blur(18px) saturate(1.7); -webkit-backdrop-filter:blur(18px) saturate(1.7);
    box-shadow:0 8px 20px rgba(3,5,16,.5),
      0 30px 70px -18px color-mix(in srgb, var(--c) 50%, transparent),
      inset 0 0 30px color-mix(in srgb, var(--c) 14%, transparent),
      inset 0 1px 0 rgba(255,255,255,.18);
  }
  .sub-header nav[hidden]{ display:none; }
  /* El panel tiene sitio de sobra: "Eventos" y "Gerpro IA²" vuelven a verse
     (la regla de arriba los oculta desde 860px cuando el nav era una sola
     fila apretada; en el panel movil eso ya no aplica). */
  .sub-header nav a.opt{ display:block; }
  .sub-header nav a:not(.btn){
    padding:11px 12px; border-radius:11px; opacity:1;
  }
  .sub-header nav a:not(.btn):hover{ background:rgba(127,192,183,.10); }
  .sub-header .volver{ gap:10px; }
  .sub-header .prod{ display:block; }
  .sub-header .prod-t{
    width:100%; padding:11px 12px; justify-content:space-between;
    font-size:13px; letter-spacing:normal; text-transform:none; opacity:1;
  }
  /* Dentro del panel movil el submenu de Productos se abre debajo, en el
     flujo normal — .prod-m ya es position:fixed a partir de 960px (ver
     nav.css), asi que sigue anclandose al viewport y no se corta contra el
     borde de este panel aunque quede anidado. */
  .sub-header .btn{ margin-top:8px; justify-content:center; }
  @media (prefers-reduced-motion: no-preference){
    .sub-header nav{
      transform-origin:top right;
      opacity:0; transform:translateY(-8px) scale(.96);
      transition:opacity .18s var(--ease-out), transform .18s var(--ease-out);
    }
    .sub-header nav[data-open]{ opacity:1; transform:translateY(0) scale(1); }
  }
}
@media (max-width:560px){
  .sub-header .hlogo{ height:19px; }
  .sub-header{ padding:12px 14px; gap:10px; }
  .sub-header nav{ top:57px; }
}

/* ---------- Contenedor ---------- */
.wrap{ width:min(1120px, 92vw); margin-inline:auto; }
.sub main{ padding-top:78px; }
section.blk{ padding:clamp(56px, 9vh, 104px) 0; }

/* ---------- Tipografia ---------- */
.eyebrow{
  font-size:12px; font-weight:600; letter-spacing:.32em; text-transform:uppercase;
  color:var(--c); margin-bottom:14px;
}
h1.big{
  font-family:var(--display); font-weight:800;
  font-size:clamp(34px, 5.6vw, 68px); line-height:1.03; letter-spacing:-.02em;
  color:#fff; max-width:19ch;
}
h2.big{
  font-family:var(--display); font-weight:800;
  font-size:clamp(26px, 3.4vw, 44px); line-height:1.1; letter-spacing:-.018em;
  color:#fff; max-width:22ch;
}
h3.mid{
  font-family:var(--display); font-weight:700;
  font-size:clamp(19px, 1.7vw, 24px); line-height:1.18; color:#fff;
}
p.lead{ font-size:clamp(16px, 1.32vw, 19px); line-height:1.62; color:var(--ink-dim); max-width:62ch; }
p.body{ font-size:15.5px; line-height:1.65; color:var(--ink-dim); max-width:66ch; }
.mt{ margin-top:18px; } .mt2{ margin-top:30px; } .mt3{ margin-top:46px; }
/* .fases, .faq y ul.bul traen su propio margin-top:8px (pensado para
   cuando van pegados a un p.eyebrow/lead sin titulo grande encima) que
   choca con el ".mt2"/".mt" que el markup les agrega a proposito debajo
   de un h2.big — misma especificidad en .fases/.faq (gana el que esta
   mas abajo en el archivo, que es el propio componente) y mayor
   especificidad en ul.bul (elemento+clase le gana siempre a la clase
   suelta). El resultado real en pantalla era 8px en los cinco subsitios
   que usan ".fases mt2"/".faq mt2"/"ul.bul mt(2)", no los 30px/18px que
   el markup pedia — el titulo se veia pegado a la lista de abajo. */
.fases.mt2, .faq.mt2{ margin-top:30px; }
ul.bul.mt{ margin-top:18px; }
ul.bul.mt2{ margin-top:30px; }

/* ---------- Hero ---------- */
.sub-hero{
  position:relative; padding:clamp(64px, 13vh, 132px) 0 clamp(46px, 8vh, 84px);
  overflow:hidden;
}
.sub-hero::before{
  content:''; position:absolute; z-index:-1;
  width:760px; height:760px; right:-190px; top:-290px; border-radius:50%;
  background:radial-gradient(circle, color-mix(in srgb, var(--c) 26%, transparent), transparent 66%);
  filter:blur(46px); pointer-events:none;
}
/* 52px se veia chico comparado con .mlogo (el logo de los modulos, ya a
   72px) y sobre todo en los logos casi cuadrados como el de CrewCore
   (icono + "CREW CORE" apilado): el texto quedaba minusculo. Misma altura
   que .mlogo para que los seis servicios y los cinco modulos se sientan del
   mismo tamaño en el hero. */
.sub-hero .slogo{ height:72px; max-width:100%; object-fit:contain; object-position:left center; display:block; margin-bottom:26px; }
.hero-ctas{ display:flex; flex-wrap:wrap; gap:13px; margin-top:32px; }

/* ---------- Botones ---------- */
.btn{
  display:inline-flex; align-items:center; gap:10px;
  padding:13px 24px; border-radius:var(--radius-pill); border:1px solid transparent;
  font-size:14px; font-weight:600; text-decoration:none; cursor:pointer;
  transition:transform .2s var(--ease-out), box-shadow .2s var(--ease-out),
    background .2s var(--ease-out), border-color .2s var(--ease-out);
}
.btn:hover{ transform:translateY(-2px); }
.btn-1{
  background:var(--c); color:#0B0E22;
  box-shadow:0 8px 30px color-mix(in srgb, var(--c) 40%, transparent);
}
.btn-1:hover{ box-shadow:0 12px 40px color-mix(in srgb, var(--c) 58%, transparent); }
/* Halo difuminado del boton primario quitado a pedido de Juan, en todas
   partes menos Contacto (esa la esta editando el aparte, no se toca aqui). */
body.no-glow-cta .btn-1, body.no-glow-cta .btn-1:hover{ box-shadow:none; }
.btn-2{ background:transparent; color:var(--ink); border-color:var(--hair); }
.btn-2:hover{ border-color:var(--c); color:#fff; }

/* Feedback de presion. Ningun boton del sitio confirmaba el clic mas alla
   del cambio de cursor; :active gana por especificidad sobre el :hover de
   arriba mientras el puntero sigue encima al soltar. */
.btn:active{ transform:scale(.97); }

/* ---------- Bloque de pregunta canonica ----------
   Sin caja: nada de fondo, borde ni radio propios — el texto se apoya
   directo en el fondo de la seccion, a todo el ancho de .wrap (como el
   resto de titulos/parrafos sueltos de la pagina, no encogido en una
   columna angosta). Su unica ancla visual es el filo vertical de ::before
   (3px, color del servicio: el UNICO naranja de todo el bloque). */
.pregunta{
  position:relative;
  padding-left:36px;
}
.pregunta::before{
  content:''; position:absolute; top:4px; bottom:4px; left:0;
  width:3px; background:var(--c);
}
.pregunta .eyebrow{ letter-spacing:.14em; color:var(--ink-dim); margin-bottom:8px; }
.pregunta q, .pregunta .q{
  display:block; quotes:none;
  font-family:var(--display); font-weight:800;
  font-size:clamp(22px, 2.9vw, 36px); line-height:1.15; color:#fff; letter-spacing:-.01em;
  /* El soporte real de hanging-punctuation es minimo (Safari) y no cubre
     "¿" (no es Ps/Pi en Unicode) — el indent negativo es lo que de verdad
     saca el "¿" fuera del margen en todos los navegadores; el ::first-line
     de arriba queda solo como mejora progresiva donde el navegador la sume. */
  hanging-punctuation:first;
  text-indent:-.42em;
}
.pregunta .q::before, .pregunta .q::after{ content:none; }
.pregunta p.body{ max-width:none; color:var(--ink); margin-top:34px; }
/* Esquinas HUD del componente generico (.hud-box .hud) apagadas solo aqui:
   .hud-box lo comparte con .error-404, que si las conserva. */
.pregunta .hud{ display:none; }
@media (max-width:640px){
  /* Movil: sin espacio para el hueco del "¿" colgado sin chocar con el
     filo — se simplifica. */
  .pregunta{ padding-left:22px; }
  .pregunta .q{ text-indent:0; }
}
/* p.lead hijo directo de .wrap (sin columna hermana con imagen/panel al
   lado, a diferencia del hero o de .split-head): con el limite base de
   62ch (linea 217) el parrafo queda embutido a la izquierda con un hueco
   enorme a la derecha, mientras el h2.big de arriba si ocupa todo el
   ancho. Mismo patron que .pregunta p.body / .dato p.lead / .wrap-legal
   p.body / .wrap:has(> .otros) p.body. */
.wrap > p.lead{ max-width:none; }
/* h2.big cuando queda solo, sin columna hermana que lo angoste (hijo
   directo de .wrap, o dentro de .pregunta que ocupa el ancho completo):
   los 22ch de la regla base estan pensados para titulos cortos que
   conviven con una imagen/columna al lado (hero-grid, split-head, card).
   Un titulo largo ahi se parte en 3-4 lineas todas cortas y deja un
   hueco enorme a la derecha — mismo sintoma que p.body mas arriba, aqui
   se sube el limite en vez de quitarlo del todo para no perder el corte
   editorial en 2 lineas de los titulos cortos. */
.wrap > h2.big,
.pregunta > h2.big{ max-width:34ch; }

/* Esquinas HUD, iguales a las caras del cubo */
.hud-box{ position:relative; }
.hud-box .hud{ position:absolute; width:16px; height:16px; border:0 solid var(--c); opacity:.9; }
.hud-box .hud.tl{ top:9px; left:9px;    border-top-width:2px; border-left-width:2px; }
.hud-box .hud.tr{ top:9px; right:9px;   border-top-width:2px; border-right-width:2px; }
.hud-box .hud.bl{ bottom:9px; left:9px;  border-bottom-width:2px; border-left-width:2px; }
.hud-box .hud.br{ bottom:9px; right:9px; border-bottom-width:2px; border-right-width:2px; }

/* Enfoque al revelarse: las 4 esquinas parten abiertas hacia afuera (como el
   diafragma de una camara) y cierran sobre la caja cuando esta cruza el
   observer — mismo disparador que .rv (subsitio.js le agrega .in), pero con
   su propia transicion en vez de heredar el fade generico del resto del
   sitio. Siempre que .hud-box vaya con .rv en el HTML (los 16 usos actuales
   lo hacen: "pregunta hud-box rv"). --hx/--hy fijan la direccion de cada
   esquina; el resto de la transicion es identica para las 4. */
.hud-box.rv .hud{
  opacity:0; transform:translate(var(--hx,0), var(--hy,0)) scale(1.4);
  transition:opacity 420ms var(--ease-out), transform 420ms var(--ease-out);
}
.hud-box.rv .hud.tl{ --hx:-11px; --hy:-11px; }
.hud-box.rv .hud.tr{ --hx:11px;  --hy:-11px; }
.hud-box.rv .hud.bl{ --hx:-11px; --hy:11px; }
.hud-box.rv .hud.br{ --hx:11px;  --hy:11px; }
.hud-box.rv.in .hud{ opacity:.9; transform:translate(0,0) scale(1); }
@media (prefers-reduced-motion: reduce){
  .hud-box.rv .hud{ opacity:.9; transform:none; transition:none; }
}

/* ---------- Visual del hero (tarjeta-respuesta) ----------
   El hero traia solo texto: eyebrow + h1 + lead + CTAs, sin nada que lo
   acompañe. La primera version porto el SVG mini-dashboard del home
   (front-page.php, ".sec.svc .vis .card") tal cual — pero un dashboard
   generico flotando junto al titular no demuestra nada: es decoracion.

   CrewCore (2026-09-02) es el banco de pruebas de una version que SI
   demuestra el producto: la tarjeta ya no es una "captura de pantalla", es
   una pregunta real respondida en vivo — la promesa literal de la pagina
   ("pregunte, no navegue") puesta a funcionar en el propio hero. Estructura
   fija, reutilizable con el SVG propio de cada servicio (MAFP: flujo de
   caja; DataMAX: tablero de indicadores; Forecast: proyeccion de
   escenarios; LeanBuilt: ciclo Lean):
     .hv-query   — la pregunta, en mono, como si se acabara de escribir
     .hv-answer  — el SVG (la respuesta), con el dato que responde resaltado
     .hv-source  — de donde sale la cifra, no una leyenda decorativa

   Reemplaza la leyenda en mayusculas con puntos medios que traia el SVG
   original (EDT · COMITÉS · HITOS...): esa leyenda no decia nada que el
   grafico no dijera ya, y era puro adorno tipografico.

   IngeMAX (la suite) no sigue este patron: su ".hero-visual" es la
   cuadricula de modulos enlazable (".mods-mini", tambien del home), porque
   ahi el hero no responde una pregunta — enlaza a los cinco modulos. Sus
   estilos siguen abajo, sin tocar.

   ecosistema.css (donde vive el SVG original) no se carga en los subsitios
   — trae toda la coreografia de scroll del cubo, que no aplica aqui. */
.hero-visual{
  background:rgba(255,255,255,.045);
  border:1px solid rgba(255,255,255,.13);
  border-radius:var(--radius-lg); padding:16px;
  box-shadow:0 22px 60px rgba(0,0,0,.4), inset 0 0 40px rgba(127,192,183,.04);
  backdrop-filter:blur(8px); -webkit-backdrop-filter:blur(8px);
}
.hero-visual svg{ display:block; width:100%; height:auto; border-radius:8px; }

.hv-query{
  display:flex; align-items:baseline; gap:8px;
  padding:2px 4px 14px;
  font-family:var(--mono); font-size:12.5px; line-height:1.4;
  color:var(--ink);
}
.hv-caret{ color:var(--c); font-weight:700; }
.hv-answer{
  border-top:1px solid rgba(255,255,255,.1);
  border-bottom:1px solid rgba(255,255,255,.1);
  padding:14px 0;
}
.hv-source{
  display:flex; align-items:center; gap:8px;
  padding:14px 4px 2px;
  font-family:var(--mono); font-size:10.5px; letter-spacing:.02em;
  color:var(--ink-dim);
}
.hv-dot{
  flex:none; width:6px; height:6px; border-radius:50%;
  background:var(--c);
  box-shadow:0 0 0 3px color-mix(in srgb, var(--c) 25%, transparent);
}

/* Cuadricula de modulos de IngeMAX (misma marca que .mods-mini en
   ecosistema.css): cada ficha es un enlace real a gerpro_modulo_url(). */
.hero-visual .mods-mini{ display:grid; grid-template-columns:repeat(3, 1fr); gap:10px; }
.hero-visual .mods-mini .mm{
  display:flex; align-items:center; justify-content:center;
  min-height:76px; padding:12px 14px;
  border-radius:10px; text-decoration:none;
  border:1px solid color-mix(in srgb, var(--pc) 38%, transparent);
  background:linear-gradient(155deg,
    color-mix(in srgb, var(--pc) 16%, transparent), rgba(41,46,89,.20));
  transition:border-color .25s, background .25s, transform .25s;
}
.hero-visual .mods-mini .mm:hover{
  border-color:var(--pc);
  background:linear-gradient(155deg,
    color-mix(in srgb, var(--pc) 30%, transparent), rgba(41,46,89,.26));
  transform:translateY(-2px);
}
.hero-visual .mods-mini img.mm-logo{
  max-width:100%; max-height:46px; width:auto; height:auto;
  object-fit:contain; display:block;
}
/* .mlogo-txt generico (mas abajo en este archivo) esta pensado para el logo
   GRANDE del propio hero de un modulo (30px, alineado a la izquierda): a esa
   escala no cabe en una ficha de 76px de alto. Esta version, mas especifica,
   gana por selector y recupera el tamaño compacto original del home. */
.hero-visual .mods-mini .mlogo-txt{
  display:flex; flex-direction:column; align-items:center; gap:1px;
  line-height:1.05; text-align:center; margin-bottom:0;
}
.hero-visual .mods-mini .mlogo-txt b{ font-size:13px; letter-spacing:.01em; }
.hero-visual .mods-mini .mlogo-txt span{ font-size:8.5px; letter-spacing:.14em; }
.hero-visual .mods-mini .mm-foot{
  grid-column:1 / -1; margin-top:4px;
  font-size:8.5px; letter-spacing:.1em; text-transform:uppercase;
  color:var(--ink-dim); opacity:.5; white-space:nowrap;
}
@media (max-width:560px){
  .hero-visual .mods-mini{ grid-template-columns:repeat(2, 1fr); }
}

/* Dos columnas en escritorio (texto + panel), una sola en movil con el
   panel debajo del texto: es un complemento del hero, no debe competir con
   el titular ni empujarlo fuera de la vista inicial. */
.hero-grid{
  display:grid; grid-template-columns:minmax(0, 1fr) minmax(280px, 380px);
  gap:clamp(30px, 5vw, 64px); align-items:center;
}
.hero-grid .hero-copy{ min-width:0; }
@media (max-width:920px){
  .hero-grid{ grid-template-columns:1fr; }
  .hero-grid .hero-visual{ max-width:460px; }
  .hero-grid .demo.dchat{ max-width:460px; margin-inline:auto; }
}

/* ---------- Entrada del hero ----------
   Probado primero solo en CrewCore (banco de pruebas), ahora universal a
   los 11 subsitios — ver [[hero-visual-subsitios]]. El hero no tenia
   NINGUNA entrada: todo aparecia de golpe con la carga.

   Secuencia unica orquestada, no efectos sueltos: el texto entra en
   cascada y, mientras tanto, la tarjeta-respuesta "escribe" su propia
   respuesta — los elementos del SVG (barras, curva, nodos — segun el
   grafico propio de cada servicio) se revelan en el orden de la
   narrativa, terminando en el dato que responde la pregunta del hero.
   Las clases genericas .hv-bar-1..4 / .hv-hito / .hv-hoy son reutilizables
   por cualquier SVG; si un grafico necesita otra forma de revelado
   (curva, nodos de un embudo), se agrega su propio bloque mas abajo.

   2026-09-11 (Juan: "que las animaciones de todos los heroes tambien
   fueran en bucle... termine, espere unos 3 segundos y vuelva a empezar"):
   primer intento le puso el loop a TODO (texto + tarjeta + grafico) con un
   ciclo largo compartido (--hero-cycle, ver mas abajo). Juan lo corrigio en
   la misma sesion: el texto (y la tarjeta como caja) reapareciendo cada
   pocos segundos "se siente como un bug" — solo el GRAFICO (lo que dibuja
   .hv-answer: barras, curva, nodos) debe repetirse. Vuelto a como era:
   .hero-in (texto + .hero-visual como caja) corre UNA sola vez al cargar,
   sin iteration-count — la tarjeta aparece y se queda quieta para siempre.
   Solo lo de ADENTRO de .hv-answer (mas abajo: hv-bar-in, hv-bar-v-in,
   hv-fade-in, hv-curve-in, hv-node-in) sigue en bucle con --hero-cycle: la
   tarjeta ya visible "redibuja" su respuesta cada ~4.3s, como un tablero
   que se refresca — eso SI lee como una demostracion a proposito, no como
   texto que parpadea. Las fichas de IngeMAX (.mods-mini .mm, sin SVG
   propio) tambien se revirtieron a una sola vez: son enlaces reales a los
   modulos, y una ficha clickeable que desaparece y vuelve cada pocos
   segundos se sentia todavia mas a bug que el texto. */
.sub-hero .hero-copy > .slogo,
.sub-hero .hero-copy > .eyebrow,
.sub-hero .hero-copy > h1.big,
.sub-hero .hero-copy > p.lead,
.sub-hero .hero-copy > .hero-ctas,
.sub-hero .hero-visual{
  animation:hero-in 620ms var(--ease-out) both;
}
.sub-hero .hero-copy > .eyebrow{ animation-delay:70ms; }
.sub-hero .hero-copy > h1.big{ animation-delay:130ms; }
.sub-hero .hero-copy > p.lead{ animation-delay:210ms; }
.sub-hero .hero-copy > .hero-ctas{ animation-delay:280ms; }
.sub-hero .hero-visual{ animation-delay:190ms; }
@keyframes hero-in{
  from{ opacity:0; transform:translateY(14px); }
  to{ opacity:1; transform:none; }
}

/* Solo lo de ADENTRO de la tarjeta (.hv-answer: barras, curva, nodos) se
   repite — ver la nota de arriba. Los keyframes de aqui abajo son de UNA
   sola pasada otra vez (2026-09-11, segunda vuelta — Juan: "la primera vez
   se siente bien... cuando se repite se siente raro, como que no todos los
   elementos desaparecen o titilan"): un primer intento hizo esto en CSS
   puro con un ciclo largo compartido + infinite, pero cada pieza tiene su
   propio animation-delay (520-980ms) — y para animaciones infinitas ese
   delay SOLO corre antes de la primera vuelta, no se repite en las
   siguientes. Resultado real: cada pieza terminaba reiniciandose en un
   instante distinto (desplazado por su propio delay, para siempre), asi
   que en cualquier repeticion habia piezas ya ocultas y redibujandose
   mezcladas con piezas que aun mostraban el dibujo de la vuelta anterior —
   exactamente el "titileo" que describio Juan. El reinicio SINCRONIZADO de
   todas las piezas a la vez ahora lo hace subsitio.js (buscar "Grafico del
   hero"): fuerza animation:none + reflow + animation:'' sobre todas al
   mismo tiempo, asi que cada vuelta usa estos mismos keyframes de una sola
   pasada y se ve identica a la primera. */
.hv-answer .hv-bar{
  transform-box:fill-box; transform-origin:0% 50%;
  animation:hv-bar-in 420ms var(--ease-out) both;
}
@keyframes hv-bar-in{ from{ transform:scaleX(0); } to{ transform:scaleX(1); } }

/* Variante vertical (DataMAX, Talento: barras verticales) — mismo truco,
   crece desde su propia base. */
.hv-answer .hv-bar-v{
  transform-box:fill-box; transform-origin:50% 100%;
  animation:hv-bar-v-in 420ms var(--ease-out) both;
}
@keyframes hv-bar-v-in{ from{ transform:scaleY(0); } to{ transform:scaleY(1); } }

.hv-answer .hv-hito{
  opacity:0; animation:hv-fade-in 260ms var(--ease-out) 840ms both;
}
.hv-answer .hv-hoy{
  opacity:0; animation:hv-fade-in 260ms var(--ease-out) 980ms both;
}
@keyframes hv-fade-in{ from{ opacity:0; } to{ opacity:1; } }

/* Grafico de curva (MAFP: flujo de caja; Forecast: proyeccion de
   escenarios) en vez de barras: se revela de izquierda a derecha con
   clip-path — la curva "se traza" en el mismo tiempo en que las barras se
   dibujan en CrewCore, para que ambos lenguajes de grafico entren con el
   mismo ritmo narrativo. */
.hv-answer .hv-curve{
  clip-path:inset(0 100% 0 0);
  animation:hv-curve-in 640ms var(--ease-out) 520ms both;
}
@keyframes hv-curve-in{ to{ clip-path:inset(0 0 0 0); } }

/* Nodos de un diagrama (LeanBuilt: ciclo Planear/Ejecutar/Mejorar; util
   para cualquier grafico de pasos o embudo futuro) — entran uno a uno con
   fundido + escala, timing puesto por las mismas clases .hv-bar-1..4. */
.hv-answer .hv-node{
  transform-box:fill-box; transform-origin:50% 50%;
  opacity:0; transform:scale(.92);
  animation:hv-node-in 380ms var(--ease-out) both;
}
@keyframes hv-node-in{ to{ opacity:1; transform:scale(1); } }

/* El retardo escalonado va SIEMPRE despues de .hv-bar/.hv-bar-v/.hv-node:
   las tres fijan la propiedad "animation" completa (shorthand), que
   resetea animation-delay a 0 aunque no lo mencionen explicitamente. Con
   igual especificidad (dos clases), gana la regla que aparece MAS ABAJO en
   el archivo — así que si esto se declarara antes de esas tres, quedaría
   pisado y las barras/nodos entrarían todos a la vez en vez de en cascada.
   Bug real que paso exactamente asi en LeanBuilt, Comercial, Financiera,
   Documental, DataMAX y Talento — ver [[hero-visual-subsitios]]. Sirve
   para cualquiera de las tres variantes por igual: solo pisa el delay. */
.hv-answer .hv-bar-1{ animation-delay:520ms; }
.hv-answer .hv-bar-2{ animation-delay:580ms; }
.hv-answer .hv-bar-3{ animation-delay:640ms; }
.hv-answer .hv-bar-4{ animation-delay:700ms; }
.hv-answer .hv-bar-5{ animation-delay:760ms; }
.hv-answer .hv-bar-6{ animation-delay:820ms; }

/* IngeMAX (la suite) no responde una pregunta en el hero — enlaza a los
   cinco modulos — asi que no lleva .hv-query/.hv-answer. Las fichas
   entran en cascada igual que el resto de la tarjeta, para que no se
   sienta menos "viva" que las demas por no tener SVG propio. Una sola vez
   (hv-node-in-once, NO hv-node-in): son enlaces reales — ver la nota de
   "Entrada del hero" mas arriba sobre por que estas fichas no se repiten
   aunque el grafico de las demas paginas si. */
.hero-visual .mods-mini .mm{
  opacity:0; transform:scale(.94);
  animation:hv-node-in-once 380ms var(--ease-out) both;
}
@keyframes hv-node-in-once{ to{ opacity:1; transform:scale(1); } }
.hero-visual .mods-mini .mm:nth-child(1){ animation-delay:520ms; }
.hero-visual .mods-mini .mm:nth-child(2){ animation-delay:570ms; }
.hero-visual .mods-mini .mm:nth-child(3){ animation-delay:620ms; }
.hero-visual .mods-mini .mm:nth-child(4){ animation-delay:670ms; }
.hero-visual .mods-mini .mm:nth-child(5){ animation-delay:720ms; }
@media (prefers-reduced-motion:reduce){
  .hero-visual .mods-mini .mm{ animation:none; opacity:1; transform:none; }
}

@media (prefers-reduced-motion:reduce){
  .sub-hero .hero-copy > .slogo,
  .sub-hero .hero-copy > .eyebrow,
  .sub-hero .hero-copy > h1.big,
  .sub-hero .hero-copy > p.lead,
  .sub-hero .hero-copy > .hero-ctas,
  .sub-hero .hero-visual{
    animation:hv-fade-in 200ms ease both; animation-delay:0ms !important;
  }
  .hv-answer .hv-bar,
  .hv-answer .hv-bar-v{
    animation:none; transform:none;
  }
  .hv-answer .hv-curve{
    animation:none; clip-path:none;
  }
  .hv-answer .hv-node{
    animation:none; opacity:1; transform:none;
  }
  .hv-answer .hv-hito,
  .hv-answer .hv-hoy{
    animation:none; opacity:1;
  }
}

/* ---------- Rejillas y tarjetas ---------- */
.grid{ display:grid; gap:18px; }
.g2{ grid-template-columns:repeat(2, 1fr); }
.g3{ grid-template-columns:repeat(3, 1fr); }
@media (max-width:900px){ .g2, .g3{ grid-template-columns:1fr; } }

/* ---------- Pilares con mini-dashboard SVG (DataMAX, seccion "El
   producto") ----------
   Portado de gerprolatam.com/datamax/ ("Tres formas de ver la verdad de su
   negocio" — Juan, 2026-09-11), en vez de las antiguas "cuatro líneas
   contratables" de texto plano. .pilar extiende .card (mismo hover/spotlight
   del resto del tema) y solo agrega el visual SVG + el remate de bullets.

   Las animaciones de las barras y la curva REUTILIZAN hv-bar-v-in y
   hv-curve-in (@keyframes definidos arriba, en "Visual del hero") en vez de
   duplicarlos: mismo lenguaje de movimiento en todo el subsitio. La unica
   diferencia es el disparador — aqui no corren solas al cargar (la seccion
   vive fuera del viewport inicial), sino cuando el observer generico de
   .rv agrega .in al hacer scroll (igual que .hud-box.rv.in mas arriba). */
.pilar-grid{ align-items:stretch; }
.pilar{ display:flex; flex-direction:column; }
.pilar-tag{
  display:inline-block; margin-bottom:14px;
  font-family:var(--mono); font-size:10.5px; font-weight:700;
  letter-spacing:.14em; text-transform:uppercase; color:var(--c);
}
.pilar-visual{
  border-radius:var(--radius-lg); overflow:hidden; margin-bottom:18px;
  border:1px solid var(--hair);
}
.pilar-visual svg{ display:block; width:100%; height:auto; }
/* Tarjeta "Infografías": el SVG lleva fondo blanco propio (imita un PDF),
   asi que el marco oscuro del resto de visuales se ve como un borde muerto
   encima del blanco — un hairline mas suave en vez del generico var(--hair). */
.pilar-visual--light{ border-color:rgba(11,14,34,.08); }
.pilar h3.mid{ margin-bottom:8px; }
/* margin-top:auto empuja el remate de bullets al fondo de la tarjeta aunque
   los parrafos de las tres columnas tengan largos distintos, para que las
   tres lineas terminen alineadas. */
.pilar .bul{ margin-top:auto; padding-top:14px; border-top:1px solid var(--hair); }
.pilar .bul li{ font-size:13.5px; padding-left:22px; }
.pilar .bul li::before{ width:6px; height:6px; box-shadow:none; }
.pilar-featured{
  border-color:color-mix(in srgb, var(--c) 46%, var(--hair));
  background:linear-gradient(160deg, color-mix(in srgb, var(--c) 20%, var(--surf-a)), var(--surf-b) 60%, var(--surf-c));
}

.pilar.rv.in .pv-bar-v{
  transform-box:fill-box; transform-origin:50% 100%;
  animation:hv-bar-v-in 420ms var(--ease-out) both;
}
.pilar.rv.in .pv-bars .pv-bar-v:nth-child(2){ animation-delay:.08s; }
.pilar.rv.in .pv-bars .pv-bar-v:nth-child(3){ animation-delay:.16s; }
.pilar.rv.in .pv-bars .pv-bar-v:nth-child(4){ animation-delay:.24s; }
.pilar.rv.in .pv-bars .pv-bar-v:nth-child(5){ animation-delay:.32s; }
.pilar.rv.in .pv-bars .pv-bar-v:nth-child(6){ animation-delay:.40s; }
.pilar.rv.in .pv-bars .pv-bar-v:nth-child(7){ animation-delay:.48s; }
.pilar.rv.in .pv-bars .pv-bar-v:nth-child(8){ animation-delay:.56s; }
.pilar.rv.in .pv-curve{
  clip-path:inset(0 100% 0 0);
  animation:hv-curve-in 640ms var(--ease-out) .6s both;
}
.pilar.rv.in .pv-donut{
  stroke-dasharray:0 200;
  animation:pv-donut-in 1.2s .3s var(--ease-out) forwards;
}
@keyframes pv-donut-in{ to{ stroke-dasharray:120 163; } }

/* Tarjeta "Agente IA": las 3 burbujas (pregunta, respuesta, CTA) entran una
   a una en vez de aparecer de golpe con el resto de la tarjeta — el mismo
   truco fill-box que .pv-bar-v, pero fundido + deslizado en vez de crecer.
   Los 3 puntos de abajo son un "..." decorativo, no un indicador de
   escritura por mensaje (no hay burbuja de "escribiendo" en este mockup en
   miniatura): laten en bucle sin parar apenas la tarjeta se revela, sin
   depender del reinicio de subsitio.js — a diferencia de las burbujas, no
   es un dibujo de una sola pasada que haya que "rebobinar". */
.pilar.rv.in .pv-bubble{
  transform-box:fill-box; transform-origin:50% 50%;
  animation:pv-bubble-in 420ms var(--ease-out) both;
}
.pilar.rv.in .pv-bubbles .pv-bubble:nth-child(2){ animation-delay:.5s; }
.pilar.rv.in .pv-bubbles .pv-bubble:nth-child(3){ animation-delay:1s; }
@keyframes pv-bubble-in{ from{ opacity:0; transform:translateY(6px); } to{ opacity:1; transform:none; } }

/* transform-box:fill-box es obligatorio aqui, no cosmetico: sin el, el
   scale() de cada punto se aplica relativo al origen del viewBox ENTERO del
   SVG (110,80) en vez del centro del propio circulo — cada punto "viaja"
   hacia/desde ese origen lejano al latir en vez de crecer en su propio
   sitio (Juan: "los puntos bajan mucho", "quedo como raro"). Mismo truco que
   .pv-bar-v/.pv-bubble mas arriba, se me olvido aqui la primera vez. */
.pilar.rv.in .pv-dot{
  transform-box:fill-box; transform-origin:50% 50%;
  animation:pv-dot-pulse 1.1s ease-in-out infinite;
}
.pilar.rv.in .pv-dots .pv-dot:nth-child(2){ animation-delay:.15s; }
.pilar.rv.in .pv-dots .pv-dot:nth-child(3){ animation-delay:.3s; }
@keyframes pv-dot-pulse{
  0%, 60%, 100%{ opacity:.35; transform:scale(.85); }
  30%{ opacity:1; transform:scale(1); }
}

@media (prefers-reduced-motion:reduce){
  .pilar .pv-bar-v{ animation:none; transform:none; }
  .pilar .pv-curve{ animation:none; clip-path:none; }
  .pilar .pv-donut{ animation:none; stroke-dasharray:120 163; }
  .pilar .pv-bubble{ animation:none; opacity:1; transform:none; }
  .pilar .pv-dot{ animation:none; opacity:.7; }
}

/* #equipo tiene 5 tarjetas: con grid puro la ultima fila (2) queda pegada a
   la izquierda y sobra un hueco a la derecha. Flex con wrap centra esa fila
   sobrante sin afectar los demas .g3 del sitio. */
#equipo .grid.g3{ display:flex; flex-wrap:wrap; justify-content:center; }
#equipo .grid.g3 > .card{ flex:0 1 calc((100% - 36px) / 3); }
@media (max-width:900px){ #equipo .grid.g3 > .card{ flex:0 1 100%; } }

/* Cascada al revelar: las 5 tarjetas cruzan el umbral del IntersectionObserver
   casi al mismo tiempo (misma posicion de scroll), asi que sin esto entraban
   todas de golpe. transition-delay sobre la propia .rv basta, sin tocar JS. */
#equipo .grid.g3 > .card:nth-child(1){ transition-delay:0ms; }
#equipo .grid.g3 > .card:nth-child(2){ transition-delay:60ms; }
#equipo .grid.g3 > .card:nth-child(3){ transition-delay:120ms; }
#equipo .grid.g3 > .card:nth-child(4){ transition-delay:60ms; }
#equipo .grid.g3 > .card:nth-child(5){ transition-delay:120ms; }

.card{
  position:relative; padding:26px; border-radius:var(--radius-xl);
  border:1px solid var(--hair);
  background:linear-gradient(155deg, rgba(127,192,183,.07), rgba(41,46,89,.14) 60%, rgba(255,255,255,.02));
  backdrop-filter:blur(8px); -webkit-backdrop-filter:blur(8px);
  transition:border-color .25s var(--ease-out), transform .25s var(--ease-out),
    box-shadow .25s var(--ease-out);
}
.card:hover{
  border-color:color-mix(in srgb, var(--c) 62%, transparent);
  transform:translateY(-3px);
  box-shadow:0 16px 44px rgba(11,14,34,.45);
}
/* Insignia de icono: mismo lenguaje de --c que .card .ideal (color de marca
   sobre fondo tenue), para que lea como parte del mismo sistema y no como
   un icono generico pegado encima. Tambien bajo .mod (Project Tracking en
   Gestion de Obra, ver gestion-de-obra.php): a esas 3 tarjetas les faltaba
   por completo un elemento visual, .mod solo trae icono cuando el modulo
   es un logo (<img>, suite IngeMAX en ingemax.php). */
.card .icn, .mod .icn{
  display:flex; align-items:center; justify-content:center;
  width:44px; height:44px; margin-bottom:16px;
  border-radius:var(--radius-lg); color:var(--c);
  background:color-mix(in srgb, var(--c) 14%, transparent);
  border:1px solid color-mix(in srgb, var(--c) 32%, transparent);
}
.card .icn svg, .mod .icn svg{ width:22px; height:22px; }
/* Height mucho mayor que el resto de usos de .card: estos son los tres
   logos de la familia MAFP (Logo_MAFP_PRO/MACRO/MRLP), lockups verticales
   de proporcion ~1.5:1 — nada que ver con el wordmark horizontal ancho de
   otros .slogo. A 40px se veian como un timbre postal perdido en la
   tarjeta. Unico uso de .card .slogo en todo el sitio (parts/servicios/
   mafp.php, seccion #familia): subirlo aqui no afecta ninguna otra pagina. */
.card .slogo{ height:clamp(72px, 9vw, 104px); object-fit:contain; object-position:left center; display:block; margin-bottom:18px; }
.card .ideal{
  display:inline-block; margin-top:14px; padding:5px 12px; border-radius:var(--radius-pill);
  font-size:11.5px; font-weight:600; letter-spacing:.04em;
  color:var(--c); border:1px solid color-mix(in srgb, var(--c) 42%, transparent);
  background:color-mix(in srgb, var(--c) 10%, transparent);
}

/* ---------- Lista de beneficios ---------- */
ul.bul{ list-style:none; display:grid; gap:15px; margin-top:8px; }
ul.bul li{
  position:relative; padding-left:30px;
  font-size:15.5px; line-height:1.6; color:var(--ink-dim); max-width:72ch;
}
ul.bul li::before{
  content:''; position:absolute; left:4px; top:.62em;
  width:9px; height:9px; border-radius:50%;
  background:var(--c); box-shadow:0 0 10px var(--c);
}
ul.bul li b, ul.bul li strong{ color:var(--ink); font-weight:600; }

/* ---------- Bloque de demostracion conversacional ---------- */
.demo{
  border-radius:var(--radius-xl); border:1px solid var(--hair); overflow:hidden;
  background:rgba(11,14,34,.52);
}
.demo .demo-h{
  display:flex; align-items:center; gap:9px;
  padding:13px 20px; border-bottom:1px solid var(--hair);
  background:rgba(41,46,89,.32);
  font-family:var(--mono); font-size:11.5px; letter-spacing:.12em;
  text-transform:uppercase; color:var(--ink-dim);
}
.demo .dot{ width:9px; height:9px; border-radius:50%; background:var(--c); box-shadow:0 0 9px var(--c); }
.demo .demo-b{ padding:26px clamp(20px, 3vw, 34px); }
.demo .pregunta-user{
  font-size:clamp(16px, 1.6vw, 20px); line-height:1.55; color:#fff;
  padding-left:18px; border-left:3px solid var(--c);
}
.demo .respuesta{ margin-top:22px; font-size:15px; line-height:1.65; color:var(--ink-dim); }
.demo .remate{
  margin-top:24px; padding-top:20px; border-top:1px solid var(--hair);
  font-family:var(--display); font-weight:700; font-size:17px; color:#fff;
}
.demo .remate b{ color:var(--c); }

/* Mismo remate, pero fuera de .demo: LeanBuilt (#lino) lo usa en la columna
   de texto de un .hero-grid, junto al chat de Lino en vez de dentro de la
   caja de chat. Mismos valores que ".demo .remate" para que el cierre en
   negrita se vea igual en cualquiera de los dos contextos. */
.hero-copy .remate{
  margin-top:24px; padding-top:20px; border-top:1px solid var(--hair);
  font-family:var(--display); font-weight:700; font-size:17px; color:#fff;
}
.hero-copy .remate b{ color:var(--c); }

/* ---------- .demo, variante multi-turno con tabla (DataMAX) ----------
   El .demo de arriba es una sola pregunta-respuesta (MAFP, LeanBuilt). Esta
   variante (.dchat, sobre el mismo .demo/.demo-h/.demo-b) es un mockup de
   varios turnos con un header de "app de chat" (avatar + nombre + estado) y
   una tabla con badges de riesgo dentro de la respuesta — de
   gerprolatam.com/datamax/, adaptado. Es SOLO ilustrativo (datos de
   ejemplo, sin backend real como el chat de #introGate en el home): el
   input de abajo no envia nada, por eso el bloque completo lleva
   aria-hidden en el markup. */
.demo-h.chat{ justify-content:space-between; }
.demo-avatar{
  flex:none; width:30px; height:30px; display:flex; align-items:center; justify-content:center;
  border-radius:50%; font-family:var(--display); font-weight:700; font-size:11px;
  color:var(--c); background:color-mix(in srgb, var(--c) 18%, transparent);
  border:1px solid color-mix(in srgb, var(--c) 40%, transparent);
}
.demo-who{ flex:1; display:flex; flex-direction:column; gap:2px; min-width:0; }
.demo-who b{
  font-family:var(--display); font-size:12.5px; letter-spacing:0; text-transform:none;
  color:var(--ink); font-weight:600;
}
.demo-status{
  display:flex; align-items:center; gap:6px;
  font-family:var(--mono); font-size:10px; letter-spacing:.06em; text-transform:none;
  color:var(--ink-dim);
}
.demo-status .dot.online{ width:6px; height:6px; background:var(--verde); box-shadow:0 0 6px var(--verde); }
.demo-refresh{
  flex:none; display:flex; align-items:center; justify-content:center;
  width:26px; height:26px; border-radius:50%; color:var(--ink-dim);
  border:1px solid var(--hair);
}
.demo-b.chat{ padding:18px clamp(16px, 2.6vw, 24px); display:flex; flex-direction:column; gap:16px; }

/* Alto FIJO, no minimo: la tarjeta debe caber igual con el hilo vacio que
   con la conversacion completa (Juan: "el contenido de abajo se desplaza
   porque la seccion crece... debe poder contener tanto el chat inicial
   como el finalizado sin aumentar o disminuir su altura"). 520px es el alto
   real de la conversacion completa (medido con Chrome headless, guion
   actual) mas margen — cabe sin scroll desde 320px de ancho (501px medidos)
   hasta desktop (461px); overflow-y es solo una red de seguridad si algun
   dia el guion crece o el texto ocupa mas lineas de las medidas. Los
   mensajes se apilan desde arriba (comportamiento por defecto de flex-start
   en columna): el espacio vacio queda siempre abajo, nunca empujando el
   input ni lo que sigue en la pagina. */
.dchat-thread{
  display:flex; flex-direction:column; gap:12px;
  height:520px; overflow-y:auto; overflow-x:hidden;
}
.dchat-msg{
  max-width:88%; padding:10px 14px; border-radius:14px;
  font-size:13px; line-height:1.55;
  transition:opacity .38s ease, transform .38s cubic-bezier(.22,1,.36,1);
}
.dchat-msg.user{
  align-self:flex-end; border-bottom-right-radius:4px;
  color:#fff; background:color-mix(in srgb, var(--c) 55%, #1a1030);
}
.dchat-msg.agent{
  align-self:flex-start; border-bottom-left-radius:4px;
  color:var(--ink-dim); background:rgba(255,255,255,.045); border:1px solid var(--hair);
}
.dchat-msg.agent p{ margin:0; }
.dchat-msg.agent b{ color:var(--ink); }

/* Estados que solo existen mientras subsitio.js reproduce el guion (ver
   "Mockup de chat" mas abajo en ese archivo) — .pend/.show nunca aparecen en
   el markup estatico, asi que sin JS (o con prefers-reduced-motion, que
   desactiva la reproduccion) los mensajes se quedan visibles tal cual estan
   escritos, sin depender de que nada los revele. */
.dchat-msg.pend{ opacity:0; transform:translateY(8px); }
.dchat-msg.show{ opacity:1; transform:none; }

/* Indicador de "escribiendo" — mismos tres puntos que respiran (opacity +
   escala) del chat real del home (.ig-dots/@keyframes ig-dot-pulse en
   ecosistema.css), portados aqui porque ecosistema.css no se carga en
   subsitios. Color con --c en vez del fucsia de IA: cada subsitio hereda su
   propio acento. */
.dchat-dots{ display:inline-flex; align-items:center; gap:5px; padding:2px 2px; }
.dchat-dots i{
  width:6px; height:6px; border-radius:50%; background:var(--c);
  animation:dchat-dot-pulse 1.1s ease-in-out infinite;
}
.dchat-dots i:nth-child(2){ animation-delay:.15s; }
.dchat-dots i:nth-child(3){ animation-delay:.3s; }
@keyframes dchat-dot-pulse{
  0%, 60%, 100%{ opacity:.35; transform:scale(.85); }
  30%{ opacity:1; transform:scale(1); }
}
@media (prefers-reduced-motion: reduce){
  .dchat-dots i{ animation:none; opacity:.85; }
}

.dchat-table{ width:100%; border-collapse:collapse; margin-top:10px; font-size:11.5px; }
.dchat-table th{
  text-align:left; padding:0 8px 6px 0; font-family:var(--mono); font-size:9.5px;
  letter-spacing:.08em; text-transform:uppercase; color:var(--ink-dim); font-weight:500;
  border-bottom:1px solid var(--hair);
}
.dchat-table td{ padding:7px 8px 7px 0; color:var(--ink); border-bottom:1px solid var(--hair); }
.dchat-table tr:last-child td{ border-bottom:none; }
/* Las filas se leen una a una en vez de aparecer en bloque, activado por
   .dchat-msg.agent.show (ver subsitio.js, "Mockup de chat"). Igual que el
   resto del sitio con .rv/.in, esto depende de que ese JS corra: con
   reduced-motion se salta la animacion pero SIEMPRE agrega .show de una
   (misma regla que .rv), asi que solo un visitante sin JS del todo se queda
   sin ver la tabla — el mismo limite que ya acepta el resto del theme. */
.dchat-table tr{ opacity:0; transition:opacity .4s ease; }
.dchat-msg.agent.show .dchat-table tr{ opacity:1; }
.dchat-table tr:nth-child(1){ transition-delay:.05s; }
.dchat-table tr:nth-child(2){ transition-delay:.16s; }
.dchat-table tr:nth-child(3){ transition-delay:.27s; }
.dchat-table tr:nth-child(4){ transition-delay:.38s; }
@media (prefers-reduced-motion: reduce){
  .dchat-table tr{ opacity:1; transition:none; }
}
.dchat-badge{
  display:inline-block; padding:2px 9px; border-radius:var(--radius-pill);
  font-weight:700; font-size:10.5px; color:var(--bc);
  border:1px solid color-mix(in srgb, var(--bc) 42%, transparent);
  background:color-mix(in srgb, var(--bc) 16%, transparent);
}

.dchat-inputbar{
  display:flex; align-items:center; justify-content:space-between; gap:10px;
  padding:10px 8px 10px 16px; border-radius:var(--radius-pill);
  border:1px solid var(--hair); background:rgba(255,255,255,.03);
  font-size:12.5px; color:var(--ink-dim);
}
.dchat-send{
  flex:none; width:28px; height:28px; display:flex; align-items:center; justify-content:center;
  border-radius:50%; color:#fff; background:var(--c);
}

#agente-dm .big em{ font-style:normal; color:var(--c); }

@media (max-width:600px){
  .dchat-table{ font-size:10.5px; }
  .dchat-table th:nth-child(2), .dchat-table td:nth-child(2){ display:none; }
}

/* ---------- "El ejemplo que lo dice todo" (MAFP) ----------
   Reemplaza la tarjeta-chat (header con punto "en linea" + burbuja) por el
   mismo lenguaje sin caja que ya usa .pregunta: barra de acento a la
   izquierda en vez de HUD/fondo, porque un punto de estado decorativo y una
   ventana de chat no aportan nada aqui (no es un producto de chat, es una
   cita de ejemplo). Texto literal de la seccion 7.1 sin cambios; solo se
   redistribuye en una columna para la pregunta y otra para la respuesta,
   con la misma proporcion 1.15fr/.85fr que .split-head unas secciones mas
   abajo, para no repetir tres veces seguidas el bloque de una sola columna
   de .pregunta. Clases propias (no toca .demo/.demo-h/.demo-b: esas las
   comparte el chat real de DataMAX mas arriba). */
.caso{
  display:grid; grid-template-columns:minmax(0, 1.15fr) minmax(0, .85fr);
  gap:clamp(28px, 4vw, 56px);
  align-items:start;
}
.caso-q{ position:relative; padding-left:22px; }
.caso-q::before{
  content:''; position:absolute; top:4px; bottom:4px; left:0;
  width:3px; background:var(--c);
}
.caso-quote{
  font-family:var(--display); font-weight:600;
  font-size:clamp(17px, 1.55vw, 21px); line-height:1.6; color:#fff;
}
.caso-role{ margin-top:16px; font-size:12.5px; color:var(--ink-dim); }
.caso-answer{ font-size:15.5px; line-height:1.7; color:var(--ink-dim); }
.caso-remate{
  margin-top:22px; padding-top:20px; border-top:1px solid var(--hair);
  font-family:var(--display); font-weight:700; font-size:16.5px; color:#fff;
}
.caso-remate b{ color:var(--c); }
@media (max-width:760px){
  .caso{ grid-template-columns:1fr; gap:28px; }
  .caso-q{ padding-left:18px; }
}

/* ---------- Ejemplos por rol y fase ---------- */
.fases{ display:grid; gap:12px; margin-top:8px; }
.fase{
  display:grid; grid-template-columns:minmax(150px, 200px) 1fr; gap:20px;
  align-items:baseline; padding:17px 20px; border-radius:var(--radius-lg);
  border:1px solid var(--hair); background:rgba(41,46,89,.20);
}
.fase .rol{
  font-family:var(--mono); font-size:11.5px; letter-spacing:.08em;
  text-transform:uppercase; color:var(--c);
}
.fase .q{ font-size:15.5px; line-height:1.55; color:var(--ink); }
@media (max-width:760px){ .fase{ grid-template-columns:1fr; gap:7px; } }

/* ---------- Franja de logos de clientes (carrusel infinito) ----------
   Mismo mecanismo que ".marquee"/".marquee-track" del home
   (front-page.php + ecosistema.css, seccion Clientes): el contenido esta
   DUPLICADO dos veces en ".logos-set" y la animacion mueve translateX(-50%)
   — como el track mide el doble del contenido real, al llegar a -50% queda
   exactamente donde empezo el segundo set y el loop no salta. Portado a
   subsitio.css (ecosistema.css no se carga en subsitios) con su propio
   nombre de clase, sin depender de "#aiSections". */
.logos-strip{
  margin-top:34px; overflow:hidden;
  mask-image:linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  -webkit-mask-image:linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.logos-track{ display:flex; width:max-content; animation:logos-scroll 30s linear infinite; }
.logos-strip:hover .logos-track{ animation-play-state:paused; }
.logos-set{
  display:flex; flex:none; align-items:center;
  gap:clamp(20px, 3.4vw, 46px); padding-inline-end:clamp(20px, 3.4vw, 46px);
}
.logos-track img{
  height:34px; width:auto; object-fit:contain; flex:none;
  opacity:.5; filter:grayscale(1) brightness(1.7);
  transition:opacity .25s, filter .25s;
}
.logos-track img:hover{ opacity:.95; filter:grayscale(0) brightness(1); }
@keyframes logos-scroll{ to{ transform:translateX(-50%); } }
@media (prefers-reduced-motion: reduce){
  .logos-strip{ overflow:visible; mask-image:none; -webkit-mask-image:none; }
  .logos-track{ animation:none; width:100%; }
  /* flex-wrap necesita un ancho concreto contra el cual envolver: sin este
     width:100%, ".logos-set" queda con flex-basis:auto (hereda "flex:none"
     de arriba) y crece al ancho de su contenido en vez de romper linea. */
  .logos-set{ flex:none; width:100%; flex-wrap:wrap; justify-content:center; padding-inline-end:0; }
  .logos-set[aria-hidden="true"]{ display:none; }
}

/* ---------- Video ---------- */
.video-wrap{
  position:relative; border-radius:var(--radius-xl); overflow:hidden;
  border:1px solid var(--hair); background:#0B0E22;
  aspect-ratio:16 / 9;
}
.video-wrap iframe{ position:absolute; inset:0; width:100%; height:100%; border:0; }
/* Fachada: no cargamos YouTube hasta que el usuario pulse play. Evita el
   tercero bloqueante en la carga inicial y las cookies antes del consentimiento. */
.video-wrap .facade{
  position:absolute; inset:0; width:100%; height:100%; padding:0; border:0;
  display:flex; align-items:center; justify-content:center;
  background:linear-gradient(155deg, rgba(25,148,164,.16), rgba(41,46,89,.5));
  cursor:pointer;
}
.video-wrap .facade img{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover; opacity:.55; }
.video-wrap .facade .play{
  position:relative; width:74px; height:74px; border-radius:50%;
  background:var(--c); color:#0B0E22;
  display:flex; align-items:center; justify-content:center;
  font-size:24px; padding-left:5px;
  box-shadow:0 10px 40px color-mix(in srgb, var(--c) 50%, transparent);
  transition:transform .25s;
}
.video-wrap .facade:hover .play{ transform:scale(1.09); }

/* .gana-grid: companero de ul.bul en "Lo que su empresa gana". La lista
   trae max-width:72ch (legibilidad) y en pantallas anchas dejaba un hueco
   vacio a la derecha dentro de .wrap — se llena con la propia captura de
   producto (.shot, ya definida mas abajo con su resplandor ambiental y su
   entrada .rv), no con un widget decorativo inventado. */
.gana-grid{ align-items:center; }
.gana-grid .bul{ margin-top:0; }

/* ---------- Captura de producto ---------- */
.shot{
  position:relative; border-radius:var(--radius-xl); overflow:hidden;
  border:1px solid var(--hair); background:rgba(11,14,34,.4);
  box-shadow:0 26px 70px rgba(11,14,34,.5);
}
.shot img{ display:block; width:100%; height:auto; }
.shot figcaption{
  padding:14px 20px; border-top:1px solid var(--hair);
  font-size:13px; color:var(--ink-dim); background:rgba(41,46,89,.28);
}

/* ---------- Modulos con icono (suite IngeMAX) ----------
   Cada tarjeta es un <a> al subsitio del modulo (antes era un <div> sin
   destino): de ahi display:block y el reset de color/subrayado, que un
   <div> no necesitaba. */
.mods{ display:grid; grid-template-columns:repeat(3, 1fr); gap:18px; }
@media (max-width:900px){ .mods{ grid-template-columns:repeat(2, 1fr); } }
@media (max-width:560px){ .mods{ grid-template-columns:1fr; } }
.mod{
  position:relative;
  display:block; padding:24px; border-radius:var(--radius-xl); border:1px solid var(--hair);
  background:linear-gradient(155deg, rgba(127,192,183,.06), rgba(41,46,89,.16) 60%);
  text-decoration:none; color:inherit;
  transition:border-color .25s, transform .25s;
}
.mod:hover{ border-color:color-mix(in srgb, var(--c) 55%, transparent); transform:translateY(-3px); }
/* Lockups horizontales anchos (~2,3:1), no iconos cuadrados: forzarlos a un
   cuadro de 46x46 con object-fit:contain los encogia a ~19px de alto -el
   texto quedaba ilegible. Alto fijo y ancho libre, como el resto de los
   logos del sitio. */
.mod img{ height:44px; width:auto; max-width:100%; object-fit:contain; object-position:left center; margin-bottom:16px; display:block; }
.mod h3{ font-family:var(--display); font-weight:700; font-size:17px; color:#fff; margin-bottom:8px; }
.mod p{ font-size:14.5px; line-height:1.58; color:var(--ink-dim); }

/* ---------- Contraste antes / ahora ---------- */
.vs{ display:grid; grid-template-columns:1fr auto 1fr; gap:22px; align-items:stretch; }
@media (max-width:860px){
  .vs{ grid-template-columns:1fr; }
  /* Sin justify-self:center, .flecha ocupa el ancho completo de la celda
     (460px en un iPhone de gama media) aunque la flecha solo mida ~26px: al
     rotarla, ese rectangulo ancho-y-bajo gira sobre su propio centro y se
     convierte en uno angosto-y-altisimo (460px de alto), que se mete por
     encima y por debajo de la fila y tapa texto de las dos tarjetas. Al
     encogerla a su contenido antes de rotar, el giro no tiene de donde
     sacar esos 460px. */
  .vs .flecha{ justify-self:center; transform:rotate(90deg); }
}
.vs .col{
  position:relative;
  padding:26px; border-radius:var(--radius-xl); border:1px solid var(--hair);
  background:rgba(41,46,89,.18);
}
.vs .col.ahora{
  border-color:color-mix(in srgb, var(--c) 52%, transparent);
  background:linear-gradient(155deg, color-mix(in srgb, var(--c) 13%, transparent), rgba(41,46,89,.2));
}
.vs .col h3{ font-family:var(--display); font-weight:700; font-size:18px; color:#fff; margin-bottom:14px; }
.vs .col.ahora h3{ color:var(--c); }
.vs .flecha{ align-self:center; font-size:26px; color:var(--c); }
.vs .paso{ font-size:14.5px; line-height:1.6; color:var(--ink-dim); padding:9px 0; border-bottom:1px dashed var(--hair); }
.vs .paso:last-child{ border-bottom:0; }
.vs-eje{
  margin-top:18px; text-align:center; font-size:14px; color:var(--ink-dim);
}
.vs-eje b{ color:var(--c); }

/* ---------- Escalera de niveles ---------- */
.escalera{ display:grid; gap:12px; counter-reset:nv -1; }
.nivel{
  display:grid; grid-template-columns:auto 1fr; gap:20px; align-items:start;
  padding:20px 24px; border-radius:var(--radius-lg);
  border:1px solid var(--hair); background:rgba(41,46,89,.18);
}
.nivel .lv{
  font-family:var(--display); font-weight:800; font-size:15px;
  color:var(--c); white-space:nowrap;
}
.nivel h3{ font-family:var(--display); font-weight:700; font-size:17px; color:#fff; margin-bottom:6px; }
.nivel p{ font-size:14.5px; line-height:1.58; color:var(--ink-dim); }
@media (max-width:640px){ .nivel{ grid-template-columns:1fr; gap:8px; } }

/* ---------- Cifra de respaldo ---------- */
.dato{
  display:grid; grid-template-columns:auto 1fr; gap:26px; align-items:center;
  padding:30px clamp(22px, 3.4vw, 40px); border-radius:var(--radius-xl);
  border:1px solid color-mix(in srgb, var(--c) 34%, transparent);
  background:linear-gradient(120deg, color-mix(in srgb, var(--c) 14%, transparent), transparent 62%);
}
.dato .n{
  font-family:var(--display); font-weight:800;
  font-size:clamp(46px, 6.6vw, 82px); line-height:.9; color:var(--c);
  text-shadow:0 0 34px color-mix(in srgb, var(--c) 52%, transparent);
  font-variant-numeric:tabular-nums; /* el ancho no debe saltar mientras subsitio.js cuenta */
}
.dato p.lead{ max-width:none; }
@media (max-width:640px){ .dato{ grid-template-columns:1fr; gap:12px; } }

/* ---------- Filosofia: diagrama del ciclo (Forecast, "Nuestra filosofia") ----------
   Sustituye las tres tarjetas planas por un diagrama triangulo + orbita —a pedido
   de Juan, la seccion se sentia "muy tranqui"— inspirado en el diagrama Concepto/
   Metodo/Software de gerprolatam.com/forecast pero con el lenguaje visual propio
   del subsitio: var(--c) (coral de Forecast), hairline punteado, y el isotipo real
   de forecast-dark.svg en el centro (mismos dos <path> del logo, solo reescalados
   con translate+scale, ver forecast.php). La rotacion del anillo es continua y
   lenta (48s): mas suave que el .orbit del cubo que Juan pidio detener del todo
   (ecosistema.css:166), pero aqui se justifica porque representa un ciclo real
   (1 Concepto -> 2 Metodo -> 3 Software), no decoracion de fondo; aun asi respeta
   prefers-reduced-motion como el resto del tema. Los subsitios no cargan
   ecosistema.js, asi que ?lowfx no aplica en esta pagina. */
.filo-grid{
  display:grid; grid-template-columns:minmax(220px, 320px) minmax(auto, 460px);
  gap:clamp(28px, 5vw, 64px); align-items:center;
  justify-content:center; max-width:900px; margin-inline:auto;
}
@media (max-width:900px){
  .filo-grid{ grid-template-columns:1fr; justify-items:center; }
}
.fc-filo-visual svg{ display:block; width:100%; height:auto; max-width:320px; }
.fc-filo-orbit{
  transform-box:view-box; transform-origin:150px 150px;
  animation:fc-filo-spin 48s linear infinite;
}
@keyframes fc-filo-spin{ to{ transform:rotate(360deg); } }
.fc-filo-badge{
  filter:drop-shadow(0 4px 10px color-mix(in srgb, var(--c) 55%, transparent));
}
@media (prefers-reduced-motion:reduce){
  .fc-filo-orbit{ animation:none; }
}
.fc-filo-list{ display:grid; gap:26px; }
.fc-filo-item{ display:flex; gap:18px; align-items:flex-start; }
.fc-filo-num{
  flex:none; width:34px; height:34px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  font-family:var(--display); font-weight:800; font-size:14px; color:#fff;
  background:var(--c);
  box-shadow:0 6px 16px color-mix(in srgb, var(--c) 45%, transparent);
}

/* ---------- Principio destacado ---------- */
.principio{
  text-align:center; padding:clamp(38px, 6vw, 66px) 0;
}
.principio .frase{
  font-family:var(--display); font-weight:800;
  font-size:clamp(25px, 3.6vw, 46px); line-height:1.12; color:#fff; letter-spacing:-.018em;
}
.principio .frase em{ font-style:normal; color:var(--c); }

/* ---------- FAQ ---------- */
.faq{ display:grid; gap:12px; margin-top:8px; }
.faq details{
  border:1px solid var(--hair); border-radius:var(--radius-lg);
  background:rgba(41,46,89,.20); overflow:hidden;
  transition:border-color .25s;
}
.faq details[open]{ border-color:color-mix(in srgb, var(--c) 50%, transparent); }
.faq summary{
  list-style:none; cursor:pointer; padding:19px 22px;
  font-size:16px; font-weight:600; color:#fff;
  display:flex; align-items:center; justify-content:space-between; gap:18px;
}
.faq summary::-webkit-details-marker{ display:none; }
.faq summary::after{
  content:'+'; flex:none; font-size:21px; font-weight:400; color:var(--c);
  transition:transform .25s;
}
.faq details[open] summary::after{ transform:rotate(45deg); }
.faq .ans{ padding:0 22px 20px; font-size:15px; line-height:1.65; color:var(--ink-dim); }

/* Apertura/cierre animados. <details> nativo no se puede animar con solo
   CSS (el contenido pasa a display:none de golpe al cerrar): subsitio.js
   mide la altura y anima con la Web Animations API, y overflow:hidden
   evita que el texto se desborde mientras la altura esta en un valor
   intermedio. */
.faq .ans{ overflow:hidden; }

/* ---------- Profundidad ----------
   Probado primero solo en CrewCore, ahora universal — ver
   [[hero-visual-subsitios]].
   v1 de esto (sombra tintada de un solo tono, muy sutil) resultó
   imperceptible: Juan la vio "prácticamente igual". El problema no era la
   sombra, era que el RELLENO de cada superficie (.vs .col,
   .card, .fase, .faq details, .otros a) sigue casi del mismo tono que el
   fondo de la página (10-20% de opacidad sobre un fondo ya oscuro, que
   además tiene sus propios degradados de color moviendose detras via
   .sub-fx) — la tarjeta deja ver tanto del fondo que se funde con él
   ópticamente, y ninguna sombra por fuerte que sea arregla eso. v2 (sombra
   e --hair mas fuertes) tampoco alcanzó: seguía viéndose "igual". v3 va a
   la causa real y sube la opacidad del relleno a un nivel casi solido
   (75-90%, no 35-40%) para que cada bloque se lea como un panel aparte,
   no como una ventana semitransparente al mismo fondo; pinta el BORDE con
   el color del servicio en reposo (ya no el --hair genérico, igual en
   todo el sitio), y usa sombra en dos capas — una oscura y ceñida (peso
   real) más un halo de color mucho más grande y notorio. */
body{
  /* Tonos de superficie propios — mas claros que el fondo de pagina
     (--indigo-night/--deep2) para que cada bloque lea como un panel
     encima, no como una ventana semitransparente al mismo fondo.
     v3 uso #242849/#1C2044/#171A3A: medidos con pixeles reales de la
     captura, salieron CASI IGUALES al fondo (28,38,67 vs 26,30,61) — de
     ahi que se siguiera viendo "igual". v4 sube el salto de claridad de
     verdad (~2x mas claro que el fondo, no ~1.1x). Nacio probado solo en
     CrewCore, ahora universal — ver [[hero-visual-subsitios]]. */
  --surf-a:#3A4079; --surf-b:#2E3468; --surf-c:#262C56;
}
.vs .col{
  border-color:color-mix(in srgb, var(--c) 34%, var(--hair));
  background:linear-gradient(155deg, color-mix(in srgb, var(--c) 12%, var(--surf-b)), var(--surf-c));
  backdrop-filter:blur(12px) saturate(1.25); -webkit-backdrop-filter:blur(12px) saturate(1.25);
  box-shadow:0 6px 14px rgba(3,5,16,.45),
    inset 0 1px 0 rgba(255,255,255,.12);
  transition:border-color .25s, box-shadow .25s, transform .25s, background .25s;
}
.vs .col:hover{
  transform:translateY(-4px);
  border-color:color-mix(in srgb, var(--c) 48%, var(--hair));
  box-shadow:0 8px 18px rgba(3,5,16,.5),
    inset 0 1px 0 rgba(255,255,255,.16);
}
.vs .col.ahora{
  border-color:color-mix(in srgb, var(--c) 62%, transparent);
  background:linear-gradient(155deg, color-mix(in srgb, var(--c) 30%, var(--surf-a)), var(--surf-b));
  box-shadow:0 6px 14px rgba(3,5,16,.45),
    inset 0 1px 0 rgba(255,255,255,.18);
}
.card{
  border-color:color-mix(in srgb, var(--c) 36%, var(--hair));
  background:linear-gradient(155deg, color-mix(in srgb, var(--c) 22%, var(--surf-a)), var(--surf-b) 55%, var(--surf-c));
  box-shadow:0 6px 16px rgba(3,5,16,.45),
    inset 0 1px 0 rgba(255,255,255,.14);
}
.card:hover{
  border-color:color-mix(in srgb, var(--c) 70%, transparent);
  box-shadow:0 8px 20px rgba(3,5,16,.5),
    inset 0 1px 0 rgba(255,255,255,.18);
}
.faq details{
  border-color:color-mix(in srgb, var(--c) 30%, var(--hair));
  background:linear-gradient(155deg, color-mix(in srgb, var(--c) 14%, var(--surf-b)), var(--surf-c));
  backdrop-filter:blur(12px) saturate(1.2); -webkit-backdrop-filter:blur(12px) saturate(1.2);
  box-shadow:0 5px 14px rgba(3,5,16,.4),
    inset 0 1px 0 rgba(255,255,255,.1);
  transition:border-color .25s, box-shadow .25s;
}
.faq details[open]{
  border-color:color-mix(in srgb, var(--c) 58%, transparent);
  box-shadow:0 6px 16px rgba(3,5,16,.45),
    inset 0 1px 0 rgba(255,255,255,.14);
}

/* .fase ("Qué puede pedirle") eran cinco filas identicas sin sombra, sin
   hover, sin nada que las distinga entre si — la version mas plana y mas
   estatica de la pagina, justo el sitio que menos deberia parecerlo: son
   las preguntas de ejemplo, el mismo lenguaje que la tarjeta-respuesta del
   hero. Filo de color a la izquierda, mas grueso que en la v1 (4px, con su
   propio resplandor) para que se note sin pasar el mouse; relleno con mas
   cuerpo y elevacion + respuesta clara al hover. */
.fase{
  position:relative; overflow:hidden;
  border-color:color-mix(in srgb, var(--c) 30%, var(--hair));
  background:linear-gradient(155deg, color-mix(in srgb, var(--c) 16%, var(--surf-b)), var(--surf-c));
  backdrop-filter:blur(10px) saturate(1.2); -webkit-backdrop-filter:blur(10px) saturate(1.2);
  box-shadow:0 5px 12px rgba(3,5,16,.4),
    inset 0 1px 0 rgba(255,255,255,.08);
  transition:border-color .25s, box-shadow .25s, transform .25s, background .25s;
}
.fase::before{
  content:''; position:absolute; inset:0 auto 0 0; width:4px;
  background:var(--c); box-shadow:0 0 16px 1px var(--c);
}
.fase:hover{
  border-color:color-mix(in srgb, var(--c) 60%, transparent);
  background:linear-gradient(155deg, color-mix(in srgb, var(--c) 26%, var(--surf-a)), var(--surf-b));
  transform:translateX(5px);
  box-shadow:0 6px 16px rgba(3,5,16,.45),
    inset 0 1px 0 rgba(255,255,255,.12);
}

/* .shot (captura de producto): una foto plana pegada sobre el fondo. Un
   resplandor ambiental detras, bien presente — mismo recurso que
   .sub-hero::before, pero contenido a la propia figura — la separa del
   fondo en vez de dejarla flotando sin contexto de luz. */
.shot{ position:relative; }
.shot::before{
  content:''; position:absolute; z-index:-1; inset:-14%;
  background:radial-gradient(ellipse at center,
    color-mix(in srgb, var(--c) 34%, transparent) 0%, transparent 68%);
  filter:blur(50px); pointer-events:none;
}
.shot{
  border-color:color-mix(in srgb, var(--c) 30%, var(--hair));
  box-shadow:0 8px 20px rgba(3,5,16,.55),
    inset 0 1px 0 rgba(255,255,255,.12);
}

/* .otros (franja de otros negocios GerPro, cierre de pagina): usa el color
   de CADA servicio enlazado (--oc), no el de CrewCore — coherente con que
   cada ficha lleva a un sitio distinto. */
.otros a{
  border-color:color-mix(in srgb, var(--oc) 34%, var(--hair));
  background:linear-gradient(155deg, color-mix(in srgb, var(--oc) 18%, var(--surf-b)), var(--surf-c));
  backdrop-filter:blur(10px) saturate(1.2); -webkit-backdrop-filter:blur(10px) saturate(1.2);
  box-shadow:0 5px 12px rgba(3,5,16,.4),
    inset 0 1px 0 rgba(255,255,255,.1);
}
.otros a:hover{
  border-color:color-mix(in srgb, var(--oc) 65%, transparent);
  box-shadow:0 6px 16px rgba(3,5,16,.45),
    inset 0 1px 0 rgba(255,255,255,.14);
}

/* Grano — una textura por debajo del umbral consciente para que el fondo
   oscuro deje de leerse como un vector perfectamente liso. Ruido SVG
   generado (feTurbulence), no una imagen: cero peso de red, cero
   dependencia externa. mix-blend-mode:overlay para que tome el tono de lo
   que tiene debajo en vez de pintar gris parejo encima. */
body::after{
  content:''; position:fixed; inset:0; z-index:2;
  pointer-events:none; opacity:.06; mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ---------- CTA de cierre ---------- */
.cierre{
  position:relative; text-align:center; overflow:hidden;
  padding:clamp(56px, 9vw, 96px) clamp(22px, 4vw, 54px);
  border-radius:var(--radius-xl); border:1px solid var(--hair);
  background:linear-gradient(160deg,
    color-mix(in srgb, var(--c) 18%, transparent),
    rgba(41,46,89,.28) 62%, rgba(255,255,255,.02));
}
.cierre::before{
  content:''; position:absolute; z-index:-1;
  width:620px; height:620px; left:50%; top:-260px; margin-left:-310px; border-radius:50%;
  background:radial-gradient(circle, color-mix(in srgb, var(--c) 30%, transparent), transparent 68%);
  filter:blur(50px);
}
.cierre .hero-ctas{ justify-content:center; }

/* ---------- Navegacion entre servicios ---------- */
/* sub-otros.php / sub-otros-modulos.php: el parrafo de intro va solo,
   sin columna hermana que use el resto de .wrap (a diferencia de la
   mayoria de .blk p.body, que conviven con una imagen o un panel al
   lado) — el limite de 66ch (p.body en linea 209) lo deja apretado a la
   izquierda con hueco a la derecha. Mismo patron que .pregunta p.body /
   .wrap-legal p.body mas arriba. */
.wrap:has(> .otros) p.body{ max-width:none; }
.otros{ display:grid; grid-template-columns:repeat(5, 1fr); gap:12px; margin-top:22px; }
@media (max-width:900px){ .otros{ grid-template-columns:repeat(2, 1fr); } }
.otros a{
  position:relative;
  display:flex; flex-direction:column; gap:12px; justify-content:center; align-items:center;
  padding:22px 18px; border-radius:var(--radius-lg); text-decoration:none; text-align:center;
  border:1px solid var(--hair); background:rgba(41,46,89,.20);
  transition:border-color .25s, transform .25s, background .25s;
}
.otros a:hover{ border-color:var(--oc); transform:translateY(-3px); background:rgba(41,46,89,.34); }
/* El 404 lista los seis servicios (no hay "actual" que excluir, a diferencia
   de sub-otros.php, que siempre deja cinco y llena las cinco columnas de
   arriba). Tres columnas reparten 3+3; auto-fit no sirve aqui porque a los
   1120px de .wrap caben cinco columnas de 200px y deja la sexta tarjeta sola
   igual que antes. */
.otros.seis{ grid-template-columns:repeat(3, 1fr); }
@media (max-width:900px){ .otros.seis{ grid-template-columns:repeat(2, 1fr); } }
@media (max-width:560px){ .otros.seis{ grid-template-columns:1fr; } }
.otros .ar{
  font-size:10.5px; font-weight:600; letter-spacing:.2em; text-transform:uppercase;
  color:var(--oc);
}
/* El logo ya es el wordmark de cada marca (ya no hay .nm en texto blanco
   repitiendo el nombre), asi que puede crecer bastante mas que antes.
   Misma logica de antes: una sola altura pareja no se ve pareja (cada marca
   trae su propio viewBox), asi que se afina por marca via data-servicio
   para que el ancho renderizado quede parejo a ojo. */
.otros-logo{ height:34px; max-width:100%; width:auto; object-fit:contain; }
.otros a[data-servicio="mafp"]     .otros-logo{ height:44px; }
.otros a[data-servicio="ingemax"]  .otros-logo{ height:19px; }
.otros a[data-servicio="crewcore"] .otros-logo{ height:50px; }
.otros a[data-servicio="leanbuilt"] .otros-logo{ height:31px; }
.otros a[data-servicio="forecast"] .otros-logo{ height:24px; }
/* ---------- Entrada de cada tarjeta al revelarse ----------
   subsitio.js ya observa .rv con IntersectionObserver y agrega .in al
   cruzar el umbral — se reusa ese mecanismo (no un observer aparte) y se le
   suma el mismo lenguaje que igTemaIn del home (blur+scale+translateY),
   para que el sitio entero se sienta como una sola coreografia. La entrada
   anima translate/scale (propiedades DISTINTAS de transform), no transform:
   el hover de arriba ya usa transform (translateY(-3px) a .25s) y si la
   entrada compartiera esa misma propiedad, una de las dos listas de
   transition reemplazaria a la otra en vez de sumarse (el hover se volvia
   instantaneo, o la entrada heredaba una duracion de .25s, muy brusca para
   un desenfoque). translate/scale corren en paralelo a transform sin pisarlo. */
.otros a.rv{
  --rv-delay:0ms;
  opacity:0; translate:0 24px; scale:.93; filter:blur(7px);
  transition:border-color .25s, transform .25s, background .25s,
    opacity .6s var(--ease-out) var(--rv-delay),
    translate .6s var(--ease-out) var(--rv-delay),
    scale .6s var(--ease-out) var(--rv-delay),
    filter .6s var(--ease-out) var(--rv-delay);
}
.otros a.rv.in{ opacity:1; translate:0 0; scale:1; filter:blur(0); }
/* Las 5 (o 6) tarjetas cruzan el umbral casi al mismo tiempo (misma posicion
   de scroll): sin desfase entrarian todas de golpe, igual que #equipo mas
   arriba. Custom property, no transition-delay directo — asi el desfase
   solo le llega a las 4 propiedades de la entrada, sin retrasar tambien el
   hover (transition-delay reemplaza la lista entera si se declara aparte). */
.otros a:nth-child(1){ --rv-delay:0ms; }
.otros a:nth-child(2){ --rv-delay:70ms; }
.otros a:nth-child(3){ --rv-delay:140ms; }
.otros a:nth-child(4){ --rv-delay:210ms; }
.otros a:nth-child(5){ --rv-delay:280ms; }
.otros a:nth-child(6){ --rv-delay:350ms; }
@media (prefers-reduced-motion: reduce){
  .otros a.rv{
    opacity:1; translate:0 0; scale:1; filter:none;
    transition:border-color .25s, transform .25s, background .25s;
  }
}

/* ---------- Error 404 ----------
   Misma cara del cubo, sin arista: el glow queda centrado (no en la esquina
   como en el hero de servicio) y el numero usa el degrade ambar-menta de
   marca, con un glitch sutil que insinua "señal perdida" sin payasadas. */
.error-404{ text-align:center; }
.error-404::before{
  left:50%; right:auto; top:-320px; margin-left:-380px;
  width:760px; height:760px;
}
.error-404 .num-wrap{ position:relative; display:inline-block; margin:14px auto 4px; }
.error-404 .num{
  position:relative; display:block;
  font-family:var(--display); font-weight:800;
  font-size:clamp(108px, 20vw, 236px); line-height:.86; letter-spacing:-.03em;
  background:linear-gradient(135deg, var(--c), var(--c2));
  -webkit-background-clip:text; background-clip:text; color:transparent;
  filter:drop-shadow(0 0 46px color-mix(in srgb, var(--c) 42%, transparent));
}
.error-404 .num::before,
.error-404 .num::after{
  content:attr(data-text); position:absolute; inset:0;
  background:linear-gradient(135deg, var(--c), var(--c2));
  -webkit-background-clip:text; background-clip:text; color:transparent;
}
.error-404 .num::before{ clip-path:inset(0 0 55% 0); animation:gp-glitch-a 5.4s infinite steps(1); }
.error-404 .num::after{ clip-path:inset(55% 0 0 0); animation:gp-glitch-b 5.4s infinite steps(1); }
@keyframes gp-glitch-a{
  0%, 84%, 100%{ transform:translate(0,0); opacity:0; }
  85%{ transform:translate(5px,-2px); opacity:.65; }
  87%{ transform:translate(-4px,1px); opacity:.5; }
  89%{ transform:translate(0,0); opacity:0; }
}
@keyframes gp-glitch-b{
  0%, 88%, 100%{ transform:translate(0,0); opacity:0; }
  89%{ transform:translate(-5px,2px); opacity:.6; }
  91%{ transform:translate(4px,-1px); opacity:.45; }
  93%{ transform:translate(0,0); opacity:0; }
}
.error-404 .lead{ margin-inline:auto; }
.error-404 .hero-ctas{ justify-content:center; }

/* Orbes de fondo: mismo truco de profundidad que .sub-hero::before pero en
   tres puntos y con deriva propia, para que la escena no se sienta estatica
   sin caer en ruido visual (blur alto, opacidad baja, sin bordes duros). */
.error-404 .orb{
  position:absolute; z-index:-1; border-radius:50%; filter:blur(54px);
  opacity:.4; pointer-events:none;
  animation:gp-orb-float 10s ease-in-out infinite;
}
.error-404 .orb.o1{ width:230px; height:230px; top:4%;  left:5%;  background:var(--teal); }
.error-404 .orb.o2{ width:170px; height:170px; bottom:8%; right:9%; background:var(--menta); animation-delay:-3.3s; }
.error-404 .orb.o3{ width:130px; height:130px; top:46%; right:3%; background:var(--ambar); animation-delay:-6.6s; }
@keyframes gp-orb-float{
  0%, 100%{ transform:translate(0, 0); }
  50%{ transform:translate(10px, -26px); }
}

/* El numeral flota apenas, como si tambien estuviera "buscando senal". */
.error-404 .num-wrap{ animation:gp-num-float 6.4s ease-in-out infinite; }
@keyframes gp-num-float{
  0%, 100%{ transform:translateY(0); }
  50%{ transform:translateY(-10px); }
}

/* Las esquinas HUD del cubo laten en vez de quedar fijas: refuerza la idea
   de "escaneando, sin senal" sin agregar mas elementos a la escena. */
.error-404.hud-box .hud{ animation:gp-hud-pulse 3.4s ease-in-out infinite; }
@keyframes gp-hud-pulse{ 0%, 100%{ opacity:.9; } 50%{ opacity:.32; } }

@media (prefers-reduced-motion: reduce){
  .error-404 .num::before, .error-404 .num::after{ animation:none; opacity:0; }
  .error-404 .orb, .error-404 .num-wrap, .error-404.hud-box .hud{ animation:none; }
}

/* ---------- Pie ----------
   El pie compartido (parts/site-footer.php) trae su propio CSS en
   tokens.css (.site-footer): es el mismo componente que usa el home, asi
   que no hay reglas propias que mantener aqui. */
.site-footer{ margin-top:clamp(50px, 8vh, 90px); }

/* ---------- Formulario de contacto (Zoho, HTML/CSS embed) ----------
   Markup exportado de "Conoce a GERPRO" (Zoho Forms, formulario
   GERPROLATAM) sin su hoja de estilos original — esa venia pensada para
   fondo claro y reescribia body/img/a/ul de forma global, asi que no se
   copia tal cual: se reescribe aqui con los tokens de marca, scopeado bajo
   .contacto-form para que no se filtre a otras paginas. Los nombres de
   campo (name=, checktype=, value= de los <option>) si se dejan identicos
   a los del export: eso es lo que Zoho espera para asociar cada respuesta
   al campo correcto. El export tambien traia un bloque "BMI Calculator"
   (Weight/Height) sobrante de una plantilla de ejemplo — no tiene nada que
   ver con captar un lead B2B y no es obligatorio en Zoho, asi que se
   quito por completo en el HTML de page-contacto.php sin afectar el envio. */
.contacto-form{ margin-top:8px; }

/* El formulario quedaba "perdido" en la pagina: solo texto plano sobre el
   fondo, sin nada que lo distinga como la pieza central de la seccion. Se
   mete en la misma tarjeta que ya usan el resto de cards del sitio (.card),
   con mas padding porque este contenido es mucho mas grande que una tarjeta
   tipica (persona, familia MAFP, etc). */
.contacto-form.card{ padding:clamp(28px, 4vw, 44px); }
.cf-grid{
  display:grid; grid-template-columns:repeat(2, 1fr); gap:22px 26px;
}
@media (max-width:720px){ .cf-grid{ grid-template-columns:1fr; } }

.cf-field{ display:flex; flex-direction:column; }
.cf-label{ font-size:13.5px; font-weight:600; color:var(--ink); margin-bottom:8px; }
.cf-req{ color:var(--rojo); font-style:normal; margin-left:2px; }

.cf-field input[type="text"], .cf-select{
  width:100%; height:46px; padding:0 14px;
  background:rgba(11,14,34,.4); color:var(--ink);
  border:1px solid var(--hair); border-radius:var(--radius-md);
  font-family:var(--body); font-size:14.5px;
  transition:border-color .2s var(--ease-out), box-shadow .2s var(--ease-out);
}
.cf-field input[type="text"]::placeholder{ color:var(--ink-dim); }
.cf-field input[type="text"]:hover, .cf-select:hover{
  border-color:color-mix(in srgb, var(--c) 40%, var(--hair));
}
.cf-field input[type="text"]:focus, .cf-select:focus{
  outline:none; border-color:var(--c);
  box-shadow:0 0 0 3px color-mix(in srgb, var(--c) 22%, transparent);
}

/* Select nativo: no se puede restylear la lista desplegable en todos los
   navegadores, pero si la caja cerrada y su flecha (svg inline en vez de
   la del sistema, que siempre sale blanca y no calza con el fondo oscuro). */
.cf-select{
  appearance:none; -webkit-appearance:none;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%237FC0B7' stroke-width='2'%3E%3Cpath d='M6 8l4 4 4-4'/%3E%3C/svg%3E");
  background-repeat:no-repeat; background-position:right 12px center; background-size:16px;
  padding-right:36px; cursor:pointer;
}
.cf-select option{ background:var(--indigo-night); color:var(--ink); }

.cf-split-row{ display:flex; gap:14px; }
.cf-sub{ flex:1; display:flex; flex-direction:column; }
.cf-sub label{ font-size:11.5px; color:var(--ink-dim); margin-top:6px; }
.cf-split-row--phone .cf-sub--code{ flex:0 0 92px; }

/* display:none -> block era instantaneo: el mensaje de error aparecia de
   golpe, sin relacion visual con el campo que acaba de fallar. .is-visible
   (contacto-form.js la pone/quita, ya no toca style.display a mano) anima
   la entrada con @starting-style — bloqueado tras la validacion, asi que
   nunca corre mas de una vez por intento. */
.cf-error{ display:none; margin-top:7px; font-size:12.5px; color:var(--rojo); }
.cf-error.is-visible{
  display:block; opacity:1; transform:translateY(0);
  transition:opacity 160ms var(--ease-out), transform 160ms var(--ease-out);
  transition-behavior:allow-discrete;
}
@starting-style{
  .cf-error.is-visible{ opacity:0; transform:translateY(-4px); }
}
@media (prefers-reduced-motion: reduce){
  .cf-error.is-visible{ transition:opacity 120ms ease; }
  @starting-style{ .cf-error.is-visible{ transform:none; } }
}

/* ---------- Formulario en dos pasos ----------
   Antes eran 8 campos en una sola pantalla; separar datos personales
   (paso 1) de los datos de la empresa (paso 2) reduce la friccion de
   llenado — el visitante ve una tarea corta primero, no un formulario
   largo completo. contacto-form.js valida cada paso por separado antes de
   dejar avanzar (zf_CheckFields) y vuelve a validar todo al enviar
   (zf_ValidateAndSubmit), asi que un campo del paso 1 no puede quedar
   vacio aunque el paso ya no este visible. */
.cf-steps{
  display:flex; align-items:center; gap:12px; margin-bottom:28px;
}
.cf-step-dot{
  display:flex; align-items:center; gap:9px;
  font-size:12.5px; font-weight:600; color:var(--ink-dim); letter-spacing:.01em;
  transition:color .2s var(--ease-out);
}
.cf-step-n{
  display:flex; align-items:center; justify-content:center; flex:none;
  width:23px; height:23px; border-radius:50%;
  border:1px solid var(--hair); font-size:11.5px; color:var(--ink-dim);
  transition:background .2s var(--ease-out), border-color .2s var(--ease-out),
    color .2s var(--ease-out), transform .2s var(--ease-out);
}
.cf-step-dot.is-active{ color:#fff; }
.cf-step-dot.is-active .cf-step-n{ background:var(--c); border-color:var(--c); color:#0B0E22; transform:scale(1.08); }

/* La linea entre los dos pasos era un hairline fijo, sin indicar avance. El
   relleno usa scaleX (no width, para quedarse en transform/opacity — ver
   "Solo animar transform y opacity") y :has() lee el estado real del dot 2
   en vez de que contacto-form.js tenga que marcar el contenedor aparte. */
.cf-step-line{ position:relative; flex:1; height:1px; background:var(--hair); max-width:70px; overflow:hidden; }
.cf-step-line::after{
  content:''; position:absolute; inset:0; transform-origin:left;
  background:var(--c); transform:scaleX(0);
  transition:transform 260ms var(--ease-in-out);
}
.cf-steps:has(.cf-step-dot[data-step-dot="2"].is-active) .cf-step-line::after{ transform:scaleX(1); }
@media (prefers-reduced-motion: reduce){
  .cf-step-n{ transition:background .2s var(--ease-out), border-color .2s var(--ease-out), color .2s var(--ease-out); }
  .cf-step-dot.is-active .cf-step-n{ transform:none; }
  .cf-step-line::after{ transition:none; }
}
@media (max-width:520px){ .cf-step-dot span:not(.cf-step-n){ display:none; } }

/* Cambiar de paso era un corte seco: [hidden] de golpe, y el contenido de
   abajo (el equipo comercial) saltaba de posicion sin transicion — "elementos
   que aparecen o desaparecen sin transicion se sienten rotos". zf_GoToStep()
   anima opacity+transform (nunca otra cosa, por rendimiento) en dos fases
   CSS-transition (no keyframes, para que un clic doble en Continuar/Atras
   pueda interrumpir/retomar en vez de reiniciar desde cero): sale mas rapido
   de lo que entra (150ms vs 200ms — la salida debe sentirse inmediata, la
   entrada puede tomarse un poco mas) y en la direccion real del avance:
   hacia el paso 2 sale/entra por la izquierda, hacia el paso 1 por la
   derecha, igual que cualquier flujo de pasos consistente. */
.cf-step{ transition:opacity 200ms var(--ease-out), transform 200ms var(--ease-out); }
.cf-step.cf-step--exit{ transition-duration:150ms; }
@media (prefers-reduced-motion: reduce){
  .cf-step{ transition:opacity 120ms ease; }
}

.cf-nav{ display:flex; align-items:center; gap:14px; margin-top:34px; }
.cf-nav--end{ justify-content:space-between; }

/* ---------- CTA del formulario (Continuar / Enviar) ----------
   En esta pagina .btn-1 quedo sin box-shadow (ver override de "halo
   difuminado" mas abajo): bien para un CTA secundario, pero el que empuja
   a avanzar de paso o a enviar quedaba plano. Se probaron dos extras que
   Juan pidio quitar despues de verlos: una sombra solida sin blur (efecto
   "boton 3D" que se hunde al presionar, "esta horrible") y padding/tamano de
   fuente mas grandes que el resto de botones ("quedo muy alto"). Lo que
   queda es el mismo tamano que cualquier .btn del sitio — el degradado del
   color de marca es la unica diferencia. No usan .btn-1 (llevan su propia
   clase .cf-cta) para no heredar el override de "halo difuminado" de mas
   abajo. */
.cf-cta{
  justify-content:center;
  background:linear-gradient(135deg, var(--c), color-mix(in srgb, var(--c) 70%, #fff));
  color:#0B0E22;
}
.cf-arrow{ display:inline-block; transition:transform .2s var(--ease-out); }
.cf-cta:hover .cf-arrow{ transform:translateX(4px); }
@media (max-width:520px){ .cf-cta{ width:100%; } }

/* Las flechas de texto (↓ ← →) que trae el resto del sitio en los .btn
   dependen de que fuente esta activa: en el body font, el glifo de flecha
   sale delgado y chico junto a un label en negrita — casi invisible, que es
   justo lo que reportaron aqui. .btn-arrow es un SVG con el mismo stroke
   que los iconos de gerpro_icono_contacto(): tamaño y grosor fijos, no
   depende de la fuente. */
.btn-arrow{ width:15px; height:15px; flex:none; }

.cf-hint{ margin-top:14px; font-size:13px; color:var(--ink-dim); }

/* ---------- Reveal al entrar en pantalla ---------- */
.rv{ opacity:0; transform:translateY(22px); transition:opacity .7s ease, transform .7s cubic-bezier(.22,1,.36,1); }
.rv.in{ opacity:1; transform:none; }
@media (prefers-reduced-motion: reduce){
  .rv{ opacity:1; transform:none; transition:none; }
  .btn:hover, .card:hover, .otros a:hover{ transform:none; }
  .persona:hover .persona-photo img, .persona-datos a:hover{ transform:none; }
}

/* ---------- Spotlight en tarjetas ----------
   .card, .mod, .vs .col y .otros a compartian el mismo hover generico
   (translateY(-3px), que sigue ahi): esto suma un halo que sigue al cursor
   de verdad (subsitio.js actualiza --mx/--my por delegacion, sin listener
   por tarjeta). Gateado tras hover:hover y pointer:fine (en tactil el
   hover se dispara al primer toque y el halo quedaria clavado en ese
   punto) y tras prefers-reduced-motion:no-preference (una mancha de color
   seguiendo el cursor cuenta como movimiento, no solo opacidad). */
@media (hover:hover) and (pointer:fine) and (prefers-reduced-motion: no-preference){
  .card::after, .mod::after, .vs .col::after, .otros a::after{
    content:''; position:absolute; inset:0; border-radius:inherit; pointer-events:none;
    background:radial-gradient(220px circle at var(--mx,50%) var(--my,50%),
      color-mix(in srgb, var(--c) 22%, transparent), transparent 70%);
    opacity:0; transition:opacity .3s var(--ease-out);
  }
  .otros a::after{
    background:radial-gradient(220px circle at var(--mx,50%) var(--my,50%),
      color-mix(in srgb, var(--oc) 26%, transparent), transparent 70%);
  }
  .card:hover::after, .mod:hover::after, .vs .col:hover::after, .otros a:hover::after{ opacity:1; }
}

/* ---------- Lockup del modulo sin logo propio ----------
   Gestion del Talento es el unico modulo que todavia no tiene PNG oficial.
   gerpro_modulo_logo() cae a este bloque tipografico, de la misma familia.
   En cuanto exista assets/servicios/modulos/gt.png, esto deja de usarse solo. */
.mlogo-txt{
  display:flex; flex-direction:column; align-items:flex-start; gap:2px;
  line-height:1.05; margin-bottom:26px;
}
.mlogo-txt b{
  font-family:var(--display); font-weight:800;
  font-size:30px; letter-spacing:-.01em; color:#fff;
}
.mlogo-txt span{
  font-size:12px; font-weight:600; letter-spacing:.22em; text-transform:uppercase;
  color:var(--pc, var(--c));
}

/* Los logos de modulo son PNG y bastante mas compactos que los SVG de servicio
   (1,6:1 frente a los apaisados), asi que a la altura del hero de servicio se
   veian pequenos. Se les da altura propia, con tope de ancho para el de GT, que
   viene en 3,2:1 y si no dominaria el hero. */
.sub-hero .mlogo{
  height:auto; max-height:72px; max-width:min(240px, 62vw);
  width:auto; object-fit:contain; object-position:left center;
  display:block; margin-bottom:26px;
}

/* ---------- Eventos ----------
   Cartel vertical (los originales son 4:5) a la izquierda y el texto a la
   derecha. Cada evento trae su propio acento en --ec, que pone el markup. */
.eventos{ display:grid; gap:clamp(14px, 2vw, 22px); }
.evento{
  display:grid; grid-template-columns:clamp(180px, 24vw, 260px) minmax(0,1fr);
  gap:clamp(18px, 3vw, 34px);
  padding:clamp(18px, 2.4vw, 26px);
  border-radius:var(--radius-xl);
  border:1px solid var(--hair);
  background:linear-gradient(155deg, rgba(127,192,183,.06), rgba(41,46,89,.16) 60%);
  transition:border-color .25s, transform .25s, box-shadow .25s;
}
.evento:hover{
  border-color:color-mix(in srgb, var(--ec) 58%, transparent);
  transform:translateY(-3px);
  box-shadow:0 18px 48px rgba(11,14,34,.45);
}
.ev-cartel{
  border-radius:var(--radius-lg); overflow:hidden; align-self:start;
  border:1px solid var(--hair); background:rgba(11,14,34,.4);
  aspect-ratio:4 / 5;
}
.ev-cartel img{ display:block; width:100%; height:100%; object-fit:cover; }

.ev-tipo{
  font-family:var(--mono); font-size:11.5px; letter-spacing:.2em;
  text-transform:uppercase; color:var(--ec); margin-bottom:6px;
}
.ev-publico{
  font-size:12.5px; letter-spacing:.02em; color:var(--ink-dim);
  opacity:.85; margin-bottom:14px;
}
.evento h3{
  font-family:var(--display); font-weight:800;
  font-size:clamp(20px, 2.4vw, 30px); line-height:1.12; color:#fff;
  letter-spacing:-.015em;
}
.ev-bajada{
  font-family:var(--display); font-weight:600; font-size:clamp(15px,1.5vw,18px);
  color:var(--ec); margin-top:8px;
}
.ev-cuerpo{ font-size:14.5px; line-height:1.62; color:var(--ink-dim); margin-top:14px; max-width:70ch; }
.ev-cuando{
  display:flex; flex-wrap:wrap; gap:10px 14px; margin-top:18px;
  padding-top:16px; border-top:1px solid var(--hair);
}
.ev-cuando span{
  font-family:var(--mono); font-size:12px; letter-spacing:.08em;
  color:var(--ink); padding:6px 13px; border-radius:var(--radius-pill);
  border:1px solid color-mix(in srgb, var(--ec) 40%, transparent);
  background:color-mix(in srgb, var(--ec) 10%, transparent);
}

@media (max-width:760px){
  .evento{ grid-template-columns:1fr; }
  .ev-cartel{ max-width:260px; }
}

/* ---------- Contacto ----------
   Tarjetas de persona (equipo comercial) y testimonios. Las fotos del
   equipo traen de fondo el isotipo "G" de marca sobre blanco (asset
   original de gerprolatam.com/contacto/): en vez de perseguir un recorte
   que lo elimine del todo -las cuatro fotos tienen encuadres distintos y
   nunca calza igual-, se trata como una insignia circular a proposito: zoom
   parejo + anillo solido del color de marca, para que el trozo de fondo que
   asome dentro del circulo lea como parte del marco y no como el fondo
   blanco de la foto original. Sin box-shadow: el halo difuminado alrededor
   del anillo se veia como un borde borroso, no como parte del marco. */
.persona{ text-align:center; padding:30px 22px; }
.persona-photo{
  width:132px; height:132px; margin:0 auto 18px; border-radius:50%;
  overflow:hidden; border:2px solid color-mix(in srgb, var(--c) 55%, transparent);
}
.persona-photo img{
  width:100%; height:100%; object-fit:cover; display:block;
  transform:scale(1.32); object-position:44% 18%;
  transition:transform .5s var(--ease-out);
}
@media (hover:hover) and (pointer:fine){
  .persona:hover .persona-photo img{ transform:scale(1.42); }
}
.persona-pais{
  display:inline-block; margin-bottom:10px; padding:4px 12px; border-radius:var(--radius-pill);
  font-size:10.5px; font-weight:600; letter-spacing:.14em; text-transform:uppercase;
  color:var(--c); border:1px solid color-mix(in srgb, var(--c) 42%, transparent);
  background:color-mix(in srgb, var(--c) 10%, transparent);
}
.persona h3{ font-family:var(--display); font-weight:700; font-size:19px; color:#fff; }
.persona .rol{ font-size:13.5px; color:var(--ink-dim); margin-top:4px; line-height:1.4; }
.persona-datos{ display:grid; gap:10px; margin-top:20px; text-align:center; }
.persona-datos a, .persona-datos .hora{
  display:flex; align-items:center; justify-content:center; gap:9px;
  font-size:13.5px; color:var(--ink-dim); text-decoration:none; line-height:1.3;
  transition:color .2s var(--ease-out), transform .2s var(--ease-out);
}
.persona-datos a:hover{ color:var(--c); }
@media (hover:hover) and (pointer:fine){
  .persona-datos a:hover{ transform:translateX(3px); }
}
.persona-datos svg{ width:16px; height:16px; flex:none; color:var(--c); }

.testi{
  display:flex; gap:16px; align-items:flex-start;
  padding:26px; border-radius:var(--radius-xl); border:1px solid var(--hair);
  background:linear-gradient(155deg, rgba(127,192,183,.06), rgba(41,46,89,.16) 60%);
}
.testi:nth-child(2){ transition-delay:70ms; }
.testi-av{
  width:46px; height:46px; border-radius:50%; flex:none; overflow:hidden;
  border:1px solid var(--hair);
}
.testi-av img{ width:100%; height:100%; object-fit:cover; display:block; }
.testi p.q{
  font-size:15px; line-height:1.62; color:var(--ink);
}
.testi p.q::before{ content:'“'; color:var(--c); }
.testi p.q::after{ content:'”'; color:var(--c); }
.testi .quien{ margin-top:12px; font-size:13px; color:var(--ink-dim); }
.testi .quien b{ color:#fff; font-weight:600; }

/* Pidieron quitar el halo difuminado de los botones y las tarjetas
   puntualmente en esta pagina (el resto de subsitios sigue igual). .btn-1
   y .card son clases compartidas por todo el sitio, asi que el override va
   scopeado a .page-contacto (ver body_class() en page-contacto.php) en vez
   de tocar la regla base. Tres focos del mismo halo, cada uno con su propio
   selector:
   1) .card::after — el "spotlight" que sigue el cursor (ver comentario
      "Spotlight en tarjetas" mas arriba), disparado por :hover.
   2) .card:hover (linea ~582) — sombra difusa al pasar el mouse.
   3) .card BASE (linea ~936, una segunda definicion de .card mas abajo en
      el archivo que le agrega glow de color(var(--c)) incluso SIN hover —
      esta es la que quedaba visible en reposo con la foto de cada persona,
      la que de verdad reportaron: el hover ya estaba resuelto, el reposo
      no. Pisa :hover tambien porque esa segunda definicion trae su propio
      .card:hover con otro glow (linea ~943). */
.page-contacto .btn-1,
.page-contacto .btn-1:hover{ box-shadow:none; }
.page-contacto .card,
.page-contacto .card:hover{ box-shadow:none; }

/* Aviso de privacidad: el cuerpo legal es solo texto corrido, sin la
   columna visual (imagen/tarjeta) que en el resto de subsitios ocupa la
   mitad derecha de .wrap (1120px). Con el limite de p.body/ul.bul li
   (66-72ch, pensado para convivir con esa columna) el texto quedaba
   pegado a la izquierda con un vacio enorme a la derecha; angostar el
   wrap entero solo lo hacia ver embutido. Se quita el limite de ancho
   del texto (mismo patron que .pregunta p.body / .dato p.lead mas
   arriba) para que ocupe todo el ancho de .wrap, sin tocar la regla
   base de p.body/ul.bul li usada en el resto del sitio. */
.wrap-legal p.body,
.wrap-legal ul.bul li{ max-width:none; }
.page-contacto .card::after{ content:none; }

/* ---------- "De tres escenarios al espacio completo" (MAFP) ----------
   Rediseno pedido por Juan (mockup compartido 2026-09-14): titular partido
   en 2 columnas (eyebrow+h2 vs. lead) y las 3 tarjetas de texto plano
   cambian a formato cifra (etiqueta numerada + icono, numero grande,
   descripcion al pie). Reusa .card/.pilar-tag/.pilar-featured/.icn — el
   mismo lenguaje que las tarjetas de DataMAX y "La licencia incluye" — en
   vez de inventar clases nuevas donde ya existian. */
.split-head{
  display:grid; grid-template-columns:minmax(0, 1.15fr) minmax(0, .85fr);
  gap:clamp(28px, 5vw, 56px); align-items:start;
}
.split-head .lead{ margin-top:0; padding-top:4px; max-width:none; }
@media (max-width:820px){
  .split-head{ grid-template-columns:1fr; gap:16px; }
}
.eyebrow.eyebrow-dash{ display:flex; align-items:center; gap:10px; }
.eyebrow.eyebrow-dash::before{
  content:''; flex:none; width:22px; height:2px; border-radius:2px; background:var(--c);
}
.split-head h2.big em{ font-style:normal; color:var(--c); }

.cambio{ display:flex; flex-direction:column; }
.cambio-head{ display:flex; align-items:center; justify-content:space-between; gap:12px; margin-bottom:22px; }
.cambio .icn{ margin-bottom:0; width:32px; height:32px; flex:none; }
.cambio .icn svg{ width:17px; height:17px; }
.cambio-stat{
  font-family:var(--display); font-weight:800;
  font-size:clamp(27px, 2.7vw, 34px); line-height:1.05; color:var(--c);
}
.cambio-cap{
  display:block; margin-top:6px;
  font-size:11px; font-weight:600; letter-spacing:.1em; text-transform:uppercase;
  color:var(--ink-dim); opacity:.75;
}
.cambio-desc{
  margin-top:auto; padding-top:16px;
  border-top:1px solid var(--hair);
}

/* ---------- Tarjeta de trazabilidad tipo "linea de tiempo" (.gd-track) ----------
   Nacio en IngeMAX GD ("El alcance / Conectado con las areas que producen
   los documentos": un acta con su linea radicado -> indexado -> aprobado ->
   notificacion) pero el patron es generico y se reusa en otros modulos con
   su propio contenido (p.ej. GT, "Cuatro efectos sobre la administracion de
   personal": novedades -> calculo -> contabilizacion -> nomina electronica).
   Reusa el mismo patron que el .demo.dchat de DataMAX (tarjeta de producto
   dentro de .hero-grid, aria-hidden porque es solo ilustrativo — el texto
   real y accesible sigue siendo el .hero-copy) y .dchat-badge para el pill
   de estado. */
.gdt-h{ justify-content:space-between; }
.gdt-doc-icn{
  flex:none; width:34px; height:34px; display:flex; align-items:center; justify-content:center;
  border-radius:var(--radius-md); color:var(--c);
  background:color-mix(in srgb, var(--c) 16%, transparent);
  border:1px solid color-mix(in srgb, var(--c) 34%, transparent);
}
.gdt-doc-icn svg{ width:17px; height:17px; }

.gdt-b{ padding:22px clamp(18px, 3vw, 30px) 6px; }
.gdt-item{ position:relative; display:flex; gap:14px; padding-bottom:22px; }
.gdt-item:last-child{ padding-bottom:4px; }
/* Linea que conecta cada paso con el siguiente: un segmento por item (no
   una sola linea detras de todos) para poder "dibujarla" en cascada con
   el resto de la entrada, igual que .pv-curve en los pilares de DataMAX.
   Elemento real (no ::before) porque necesita adentro un hijo real, el
   punto que viaja (.gdt-dot): un pseudo-elemento no puede tener hijos. Al
   quedar dentro del propio segmento, el punto escala solo a lo alto real
   de CADA tramo (el alto de un item varia segun cuanto texto entre en
   .gdt-txt), sin coordenadas fijas que se desalinearan en movil. */
.gdt-line{
  position:absolute; left:15px; top:34px; bottom:0;
  width:1px; background:var(--hair);
}
.gdt-item:last-child .gdt-line{ display:none; }
.gdt-dot{
  position:absolute; left:50%; top:0; width:7px; height:7px; margin-left:-3.5px;
  border-radius:50%; background:var(--c);
  box-shadow:0 0 8px var(--c), 0 0 3px #fff; opacity:0;
}
.gdt-icn{
  position:relative; z-index:1; flex:none;
  width:32px; height:32px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  color:var(--bc); background:color-mix(in srgb, var(--bc) 22%, transparent);
  border:1px solid color-mix(in srgb, var(--bc) 48%, transparent);
}
.gdt-icn svg{ width:15px; height:15px; }
.gdt-txt{ display:flex; flex-direction:column; gap:2px; padding-top:4px; }
.gdt-txt b{ font-family:var(--display); font-weight:700; font-size:14.5px; color:#fff; }
.gdt-txt span{ font-size:12.5px; color:var(--ink-dim); }
.gdt-txt time{
  margin-top:2px; font-family:var(--mono); font-size:10.5px; letter-spacing:.03em;
  color:var(--ink-dim); opacity:.6;
}

.gdt-foot{
  display:flex; align-items:center; gap:12px;
  padding:15px clamp(18px, 3vw, 30px); border-top:1px solid var(--hair);
  background:rgba(41,46,89,.22);
}
.gdt-avatars{ display:flex; }
.gdt-av{
  width:24px; height:24px; margin-left:-8px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  font-family:var(--display); font-weight:700; font-size:9.5px; color:#fff;
  background:var(--bc); border:2px solid rgba(11,14,34,.75);
}
.gdt-avatars .gdt-av:first-child{ margin-left:0; }
.gdt-note{
  font-family:var(--mono); font-size:10px; letter-spacing:.1em; text-transform:uppercase;
  color:var(--ink-dim); opacity:.75;
}

/* Entrada escalonada disparada por el observer generico .rv/.in (mismo
   lenguaje que .pilar.rv.in .pv-bar-v en DataMAX): cada paso aparece y la
   linea hacia el siguiente se "dibuja" antes de que aparezca el que sigue. */
.gd-track.rv.in .gdt-item{ animation:gdt-item-in .5s var(--ease-out) both; }
.gd-track.rv.in .gdt-item:nth-child(1){ animation-delay:.05s; }
.gd-track.rv.in .gdt-item:nth-child(2){ animation-delay:.22s; }
.gd-track.rv.in .gdt-item:nth-child(3){ animation-delay:.39s; }
.gd-track.rv.in .gdt-item:nth-child(4){ animation-delay:.56s; }
@keyframes gdt-item-in{ from{ opacity:0; transform:translateY(10px); } to{ opacity:1; transform:none; } }
.gd-track.rv.in .gdt-line{ animation:gdt-line-in .4s linear both; }
.gd-track.rv.in .gdt-item:nth-child(1) .gdt-line{ animation-delay:.26s; }
.gd-track.rv.in .gdt-item:nth-child(2) .gdt-line{ animation-delay:.43s; }
.gd-track.rv.in .gdt-item:nth-child(3) .gdt-line{ animation-delay:.60s; }
@keyframes gdt-line-in{ from{ clip-path:inset(0 0 100% 0); } to{ clip-path:inset(0 0 0% 0); } }
.gd-track.rv.in .gdt-foot{ animation:gdt-item-in .5s var(--ease-out) .68s both; }

/* Punto que viaja de Radicado a Notificacion, en relevo (un tramo, un
   punto): cada .gdt-dot solo esta activo dentro de su ventana del ciclo
   compartido de 2.7s (0-0.5s, 0.5-1s, 1-1.5s) y el resto del tiempo queda
   invisible — de lejos se lee como un unico punto recorriendo toda la
   linea y haciendo una pausa antes de repetir, sin curvas comunes entre
   pasos de distinto alto (el pausa real de cada tramo depende del alto
   real de ESE item, no de un numero fijo). Arranca despues de que termino
   de dibujarse la cascada inicial (1.3s) para no competir con ella. */
.gd-track.rv.in .gdt-item:nth-child(1) .gdt-dot{ animation:gdt-dot-1 2.7s 1.3s linear infinite; }
.gd-track.rv.in .gdt-item:nth-child(2) .gdt-dot{ animation:gdt-dot-2 2.7s 1.3s linear infinite; }
.gd-track.rv.in .gdt-item:nth-child(3) .gdt-dot{ animation:gdt-dot-3 2.7s 1.3s linear infinite; }
@keyframes gdt-dot-1{
  0%{ opacity:0; top:0; }
  1%{ opacity:1; }
  17%{ opacity:1; top:100%; }
  18.5%{ opacity:0; }
  100%{ opacity:0; }
}
@keyframes gdt-dot-2{
  0%, 18.5%{ opacity:0; top:0; }
  19.5%{ opacity:1; }
  35.5%{ opacity:1; top:100%; }
  37%{ opacity:0; }
  100%{ opacity:0; }
}
@keyframes gdt-dot-3{
  0%, 37%{ opacity:0; top:0; }
  38%{ opacity:1; }
  54%{ opacity:1; top:100%; }
  55.5%{ opacity:0; }
  100%{ opacity:0; }
}
@media (prefers-reduced-motion:reduce){
  .gd-track .gdt-item, .gd-track .gdt-line, .gd-track .gdt-foot{ animation:none; opacity:1; clip-path:none; }
  .gd-track .gdt-dot{ display:none; }
}
