/* ==========================================================================
   NovaSales — Sistema de diseño
   Tokens exactos según 01_scaffolding.md. Patrones visuales (radios,
   sombras, densidad, scroll-reveal) tomados de referencia_visual.html,
   que es la fuente de verdad visual (mockup del Home aprobado por el cliente).
   ========================================================================== */

:root{
  --ink:#0B1533;
  --navy:#101F52;
  --cyan:#00BAB4;
  --coral:#FC4236;
  --verde-whatsapp:#00AE54;
  --azul-telegram:#229ED9;
  --naranja:#FC782A; /* Prompt 17: definido pero sin uso — era el acento de Real Estate
    en las tarjetas de industria, unificadas a --cyan. No se borra por si se reusa. */
  --paper:#F6F8FB;
  --line:#E5E9F1;
  --muted:#7C849E;
  --body:#434B66;

  --r:56px;        /* radio de paneles oscuros, en desktop */
  --r-mobile:30px;  /* mismo token, media query <980px */

  --display:'Manrope',sans-serif;
  --text:'Inter',sans-serif;
  --wrap:1180px;

  /* ritmo vertical del hero interior (Prompt 9, Parte 3) — no existía una
     escala de espaciado en el proyecto, se crean estos 3 tokens puntuales.
     Documentados también en content.es.json _meta.convenciones_tecnicas. */
  --hero-gap-sm:22px;   /* H1 → bajada (mediano) */
  --hero-gap-lg:40px;   /* bajada → CTA (grande, > gap-sm): el CTA se despega del párrafo */
  --hero-i-pad-bottom:80px; /* CTA → borde inferior de la banda oscura, en heros interiores */
}

*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth;overflow-x:hidden}
body{font-family:var(--text);color:var(--body);background:var(--paper);-webkit-font-smoothing:antialiased;line-height:1.65}
.wrap{max-width:var(--wrap);margin:0 auto;padding:0 24px}
h1,h2,h3,h4{font-family:var(--display);color:var(--navy);line-height:1.18;letter-spacing:-0.018em;font-weight:700}
/* Prompt 19 — viudas en el texto de cuerpo del Home (ej. la cita del bloque
   Híbrido rompía dejando una "A" sola en su línea). text-wrap:pretty evita esto
   pidiéndole al navegador que reparta mejor la última línea del párrafo; balance
   (H1/H2, sin tocar acá) es para títulos, no para prosa. Regla amplia sobre los
   contenedores de texto en vez de una por componente, scopeada a .home (wrapper
   propio de home.html) para no afectar .card/.acard/.split en otras páginas que
   reusan las mismas clases. .card-note y .ideal ("Ideal para:") son <div>, no
   <p>/<li> — quedaban fuera del selector original, se agregan acá. */
.home p,.home li,.home .closing,.home .card-note,.home .ideal{text-wrap:pretty}
/* Prompt 19 (ronda 2) — balance en H1/H2 del Home: no estaba puesto (corrección
   sobre lo asumido en la ronda anterior de este mismo prompt). .hero es clase
   exclusiva del header del Home (no la reusa .hero-interior/.hero-center de las
   páginas internas), así que no hace falta el wrapper .home para scopearla. */
.hero h1,.home h2{text-wrap:balance}
a{text-decoration:none;color:inherit}
img{max-width:100%;display:block}

.eyebrow{font-family:var(--text);font-size:11.5px;letter-spacing:.15em;text-transform:uppercase;color:var(--cyan);font-weight:600;display:block;margin-bottom:18px}

/* ---------- NAV ---------- */
.nav{position:sticky;top:0;z-index:60;background:var(--ink);border-bottom:1px solid rgba(255,255,255,.07);transition:box-shadow .3s}
.nav.stuck{box-shadow:0 6px 28px -10px rgba(0,0,0,.6)}
.nav-in{max-width:var(--wrap);margin:0 auto;padding:0 24px;height:76px;display:flex;align-items:center;gap:38px}
.nav-logo{font-family:var(--display);font-weight:800;font-size:19px;color:#fff;letter-spacing:-0.02em}
.nav-logo img{height:36px;display:block}
.nav-logo svg{height:19px;width:auto;display:block}
.nav-links{display:flex;gap:27px;align-items:center;margin-left:auto}
.nav-links>li{position:relative;list-style:none}
.nav-links a{font-size:14.5px;color:#C6CDE4;font-weight:500;position:relative;padding:7px 0;transition:color .18s;display:inline-block}
.nav-links a:hover{color:#fff}
.nav-links a::after{content:"";position:absolute;left:0;bottom:0;width:0;height:2px;border-radius:2px;background:var(--cyan);transition:width .24s}
.nav-links a:hover::after{width:100%}
/* Estado activo (03g): mismo ::after del hover, pero sin transition — si hereda la
   animación de entrada del hover, se ve "dibujándose" al cargar la página. */
.nav-links a.is-active::after{width:100%;transition:none}
.has-sub{position:relative;padding-right:14px}
.has-sub::after{content:"";position:absolute;right:0;top:14px;width:5px;height:5px;border-right:1.5px solid #7C87A8;border-bottom:1.5px solid #7C87A8;transform:rotate(45deg)}
.submenu{position:absolute;top:calc(100% + 14px);left:-16px;min-width:220px;background:var(--navy);border:1px solid rgba(255,255,255,.08);
  border-radius:14px;padding:8px;box-shadow:0 24px 48px -20px rgba(0,0,0,.55);opacity:0;visibility:hidden;transform:translateY(6px);transition:.2s}
.nav-item:hover .submenu{opacity:1;visibility:visible;transform:none}
.submenu a{display:block;padding:10px 14px;border-radius:9px;font-size:14px;color:#C6CDE4}
.submenu a:hover{background:rgba(0,186,180,.1);color:#fff}
.submenu a::after{display:none}
/* Estado activo dentro del dropdown: mismo highlight que ya tiene el hover del submenú
   (no hay ::after acá, así que no aplica la regla de arriba) — mismo color, mismo fondo. */
.submenu a.is-active{background:rgba(0,186,180,.1);color:#fff}
/* header de categoría dentro del submenú (ej. "RETAIL" en Industrias) — no clickeable,
   mismo tratamiento tipográfico que otros headers chicos del sitio (.astep/.eyebrow). */
.submenu-head{display:block;padding:10px 14px 4px;font-size:10.5px;letter-spacing:.1em;text-transform:uppercase;font-weight:700;color:#7C87A8}
.nav-right{display:flex;gap:13px;align-items:center;margin-left:12px}
.lang{font-size:12.5px;font-weight:600;color:#9BA4C4;border:1px solid rgba(255,255,255,.15);padding:7px 12px;border-radius:9px;letter-spacing:.05em;cursor:pointer;background:none}
.signin{font-size:14px;color:#fff;font-weight:600;border:1px solid rgba(255,255,255,.22);padding:9px 19px;border-radius:10px;transition:.2s}
.signin:hover{background:rgba(0,186,180,.12);border-color:var(--cyan)}

/* ---------- NAV MOBILE ---------- */
/* Botón hamburguesa: oculto por defecto (desktop), visible solo bajo 900px
   (regla en el @media de más abajo, junto al resto de los ajustes mobile).
   Tres líneas via spans, mismo criterio visual simple que el resto del sitio
   (sin SVG ni ícono de librería). */
.nav-burger{display:none;flex-direction:column;justify-content:center;gap:5px;width:34px;height:34px;padding:0;border:none;background:none;cursor:pointer}
.nav-burger-line{display:block;width:20px;height:2px;border-radius:2px;background:#fff}
/* Capa a pantalla completa con la navegación mobile. Mismo fondo que el resto
   del sistema oscuro (--ink), con scroll interno propio por si el listado no
   entra en la altura de la pantalla (Industrias trae 6 sub-links). Oculta por
   defecto vía [hidden] (atributo HTML, no clase) + la clase .is-open la
   muestra — main.js alterna las dos cosas a la vez. */
.nav-mobile{position:fixed;inset:0;z-index:100;background:var(--ink);overflow-y:auto;padding:24px}
.nav-mobile[hidden]{display:none}
.nav-mobile-head{display:flex;justify-content:flex-end}
.nav-mobile-close{display:flex;align-items:center;justify-content:center;width:34px;height:34px;padding:0;border:none;background:none;cursor:pointer;position:relative}
.nav-mobile-close-line{position:absolute;width:20px;height:2px;border-radius:2px;background:#fff}
.nav-mobile-close-line:first-child{transform:rotate(45deg)}
.nav-mobile-close-line:last-child{transform:rotate(-45deg)}
.nav-mobile-list{list-style:none;margin:12px 0 0;display:flex;flex-direction:column;gap:6px}
.nav-mobile-item{border-bottom:1px solid rgba(255,255,255,.08);padding:14px 0}
.nav-mobile-item>a{display:block;font-size:19px;font-weight:600;color:#fff}
.nav-mobile-item>a.is-active{color:var(--cyan)}
/* Canales/Industrias: título de grupo sin link (no hay acordeón, según diseño
   decidido) seguido de sus sub-links siempre visibles. */
.nav-mobile-group{display:block;font-size:19px;font-weight:600;color:#fff}
.nav-mobile-group.is-active{color:var(--cyan)}
.nav-mobile-sub{display:flex;flex-direction:column;gap:2px;margin-top:10px}
.nav-mobile-sub a{font-size:15px;color:#C6CDE4;padding:8px 0 8px 14px}
.nav-mobile-sub a.is-active{color:var(--cyan)}
/* Bloqueo de scroll del body mientras el panel está abierto (clase aplicada
   por main.js sobre <body>, no sobre .nav-mobile). */
body.nav-mobile-open{overflow:hidden}

/* ---------- HERO ---------- */
.hero{background:var(--ink);position:relative;overflow:hidden;padding:86px 0 92px}
.hero::before{content:"";position:absolute;inset:0;
  background-image:linear-gradient(rgba(0,186,180,.05) 1px,transparent 1px),linear-gradient(90deg,rgba(0,186,180,.05) 1px,transparent 1px);
  background-size:60px 60px;
  -webkit-mask-image:radial-gradient(ellipse 78% 62% at 28% 42%,#000 18%,transparent 76%);
  mask-image:radial-gradient(ellipse 78% 62% at 28% 42%,#000 18%,transparent 76%)}
.hero::after{content:"";position:absolute;width:800px;height:800px;right:-240px;top:-280px;border-radius:50%;
  background:radial-gradient(circle,rgba(0,186,180,.19),transparent 63%);pointer-events:none}
.hero-in{position:relative;z-index:2;display:grid;grid-template-columns:1.03fr .97fr;gap:58px;align-items:center}
.hero h1{color:#fff;font-size:clamp(33px,4.1vw,52px);font-weight:800;letter-spacing:-0.028em;line-height:1.13}
.hero h1 em{font-style:normal;color:var(--cyan)}
.hero-lead{color:#B3BBD6;font-size:18.5px;margin-top:var(--hero-gap-sm);max-width:520px}
.hero-lead strong{color:#fff;font-weight:600}
.hero-sub{color:#98A1C0;font-size:16px;margin-top:16px;max-width:520px}
.hero-sub strong{color:#DDE3F5;font-weight:600}
.hero-list{list-style:none;margin:28px 0 34px;display:flex;flex-direction:column;gap:13px}
.hero-list li{color:#C6CDE4;font-size:15.5px;display:flex;gap:12px;align-items:flex-start}
.tick{flex:0 0 19px;height:19px;margin-top:3px;border-radius:7px;background:rgba(0,186,180,.15);position:relative}
.tick::after{content:"";position:absolute;left:6.5px;top:4px;width:4px;height:8px;border-right:2px solid var(--tc,var(--cyan));border-bottom:2px solid var(--tc,var(--cyan));transform:rotate(42deg)}
.cta-row{display:flex;gap:13px;flex-wrap:wrap;align-items:center}
.btn{font-family:var(--text);font-size:15px;font-weight:600;padding:15px 28px;border-radius:12px;display:inline-block;transition:.22s;border:none;cursor:pointer}
.btn-primary{background:var(--coral);color:#fff;box-shadow:0 8px 26px -9px rgba(252,66,54,.55)}
.btn-primary:hover{background:#e6392d;transform:translateY(-2px);box-shadow:0 15px 32px -9px rgba(252,66,54,.6)}
.btn-ghost{color:#fff;border:1px solid rgba(255,255,255,.24);background:transparent}
.btn-ghost:hover{border-color:var(--cyan);background:rgba(0,186,180,.09)}
.btn-dark{background:var(--navy);color:#fff}
.btn-dark:hover{background:#16295F;transform:translateY(-2px)}

/* ---------- demo widget (WhatsApp / Telegram / SMS) ---------- */
/* Segmented control (Prompt 6, Parte 5): un solo contenedor con borde, sin
   gaps entre segmentos, indicador deslizante posicionado por JS (moveIndicator
   en js/main.js) sobre el botón activo. El color activo es siempre cyan —
   el canal ya se identifica por el logo del pie (.cap-logo), no por color de pestaña. */
.chan-tabs{position:relative;display:flex;background:rgba(255,255,255,.055);
  border:1px solid rgba(255,255,255,.10);border-radius:12px;padding:4px;margin-bottom:15px;isolation:isolate}
.chan-tabs-indicator{position:absolute;top:4px;left:0;height:calc(100% - 8px);width:0;
  background:var(--cyan);border-radius:8px;z-index:0;
  transition:transform .22s cubic-bezier(.2,.8,.3,1),width .22s cubic-bezier(.2,.8,.3,1)}
@media (prefers-reduced-motion:reduce){.chan-tabs-indicator{transition:none}}
.chan-tab{position:relative;z-index:1;flex:1;font-family:var(--text);font-size:12.5px;letter-spacing:.03em;
  color:#98A1C0;background:none;border:none;padding:9px 15px;border-radius:8px;cursor:pointer;
  transition:color .2s;font-weight:600;text-align:center}
.chan-tab:hover{color:#fff}
.chan-tab.on{color:#07142E}
.chan-tab:focus-visible{outline:2px solid #fff;outline-offset:2px}
/* Prompt 23 (Parte 3) — alto subido de 462 a 540px: es un valor único y
   compartido por las 3 pestañas del Home Y por el widget fijo de las páginas
   de canal (mismo componente, .phone-body sigue con overflow:auto de red de
   seguridad) — así que la conversación de Real Estate no puede necesitar una
   altura propia sin romper la regla de "el panel no salta al cambiar de
   pestaña". El resto de las conversaciones (Retail/Emprendedores) quedan con
   más aire abajo, ya resuelto por .fill-bottom (Prompt 10) cuando terminan de
   renderizarse antes de llenar el panel. Estimado sin poder medir en browser:
   revisar sobre todo en 390px, ver reporte.
   Prompt 24 (Parte 4) — Real Estate pasó de 6 a 8 mensajes con 2 imágenes a
   100% de ancho (antes 1 mensaje con 2 imágenes a 50%). Se mantiene en 540px
   sin seguir agrandando (el prompt pide no crecer más de lo que el hero
   tolera): mi estimación a mano de texto+imágenes en 390px da un total mayor
   al espacio disponible en este alto — ver aviso explícito en el reporte,
   no lo resolví agrandando el panel a ciegas. .phone-body conserva su
   overflow-y:auto como red de seguridad si hiciera falta scroll ahí. */
.phone{background:#13204A;border:1px solid rgba(255,255,255,.1);border-radius:22px;overflow:hidden;
  box-shadow:0 40px 84px -34px rgba(0,0,0,.72);height:540px;display:flex;flex-direction:column}
/* Prompt 22 (Parte 2) — panel translúcido solo en el Home: el widget se comparte
   con whatsapp.html/telegram.html/sms.html vía .demo-fixed, ahí se apoya sobre
   fondo claro (--paper) y un panel con blanco al 4,5% quedaría invisible. .demo
   envuelve el widget únicamente en el hero del Home (home.html), así que scopear
   por ahí deja las páginas de canal intactas sin necesidad de tocarlas. */
.demo .phone{background:rgba(255,255,255,.045);border-color:rgba(255,255,255,.10)}
.demo .phone-bar{background:none;border-bottom-color:rgba(255,255,255,.09)}
.phone-bar{padding:14px 18px;display:flex;align-items:center;gap:11px;border-bottom:1px solid rgba(255,255,255,.08);background:rgba(255,255,255,.03)}
.avatar{width:35px;height:35px;border-radius:11px;background:var(--accent,var(--cyan));display:flex;align-items:center;justify-content:center;
  font-family:var(--display);font-weight:800;font-size:13px;color:#0B1533;flex:0 0 35px}
.phone-name{color:#fff;font-size:14px;font-weight:700;font-family:var(--display);line-height:1.3}
.phone-meta{font-size:11.5px;color:var(--accent,var(--cyan));font-weight:500}
/* Alineación del panel (Prompt 10, Parte 4): por defecto los mensajes crecen
   desde arriba (flex-start) — con flex-end quedaba un hueco grande arriba
   mientras la secuencia todavía estaba llenando el panel, justo cuando el
   visitante está mirando. El anclaje al fondo (.fill-bottom) se agrega por JS
   solo cuando la conversación terminó de renderizarse y es más corta que el
   panel (hoy, típicamente SMS). */
.phone-body{flex:1;min-height:0;padding:18px;overflow-y:auto;overflow-x:hidden;display:flex;flex-direction:column;justify-content:flex-start;gap:11px;scrollbar-width:thin}
.phone-body.fill-bottom{justify-content:flex-end}
.phone-body::-webkit-scrollbar{width:4px}
.phone-body::-webkit-scrollbar-thumb{background:rgba(255,255,255,.13);border-radius:4px}
.msg{max-width:82%;padding:11px 15px;border-radius:16px;font-size:13.6px;line-height:1.55;animation:msgIn .32s ease-out both}
/* Ajuste post-Prompt 24: burbuja con imagen a ancho FIJO (88% del área de
   mensajes, no fit-content) — sin esto, un texto corto como "Sí, te los
   paso." encoge la burbuja y arrastra la imagen con ella, dejando las dos
   imágenes de anchos distintos entre sí. width (no max-width) fuerza el
   mismo ancho en las dos sin importar el largo del texto que acompañan. */
.msg.has-img{width:88%;max-width:88%}
.msg.agent{background:rgba(255,255,255,.07);color:#DCE2F4;border:1px solid rgba(255,255,255,.07);border-bottom-left-radius:6px;align-self:flex-start}
/* Prompt 22 (Parte 2) — burbujas del agente un poco más presentes en el Home
   (mismo criterio de scope que .demo .phone arriba). El texto (#DCE2F4) no
   se toca: .085 sigue leyéndose cómodo, no hizo falta subir el color. */
.demo .msg.agent{background:rgba(255,255,255,.085)}
/* Prompt 24/25 — un mensaje puede traer 1 imagen a ancho completo (Real
   Estate) o varias en fila (Emprendedores: 2). La cantidad de columnas la
   fija JS por mensaje (grid-template-columns inline, según imagenes.length),
   no una clase por conversación — así un tercer caso (3+ imágenes) entra sin
   tocar CSS. Con 1 sola imagen, "1 columna" da el mismo resultado que el
   ancho completo de antes.
   aspect-ratio también lo fija JS, por imagen, a partir de las dimensiones
   reales del archivo (leídas por build.py vía Pillow, no hardcodeadas) —
   reserva el espacio antes de cargar sin importar cuántas columnas tenga esa
   imagen, y evita que object-fit:cover recorte de más si el ancho de columna
   no coincide con el ancho natural del archivo. */
.msg-imgs{display:grid;gap:7px;margin-top:8px}
/* Placeholder de carga por imagen: reusa el mismo componente de puntitos
   que .typing (mismo keyframe bl, más abajo). .img-ph no fija tamaño propio:
   el <img> ya reserva el espacio vía aspect-ratio (ver JS), así que los
   puntitos quedan centrados sobre ese hueco mientras la imagen sigue en
   opacity:0; al llegar el evento load/error se agrega .loaded, que hace
   fade-in a la imagen y esconde los puntitos, sin salto de layout. Se aplica
   igual con 1 imagen o con varias: cada una tiene su propio .img-ph. */
.img-ph{position:relative;border-radius:8px;overflow:hidden}
.msg-imgs img{width:100%;height:auto;border-radius:8px;display:block;object-fit:cover;opacity:0;transition:opacity .25s ease-out}
.img-ph.loaded img{opacity:1}
.img-ph-dots{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;gap:4px;background:rgba(255,255,255,.05)}
.img-ph.loaded .img-ph-dots{display:none}
.img-ph-dots i{width:6px;height:6px;border-radius:50%;background:#7C87A8;animation:bl 1.3s infinite}
/* Prompt 25 — texto después de las imágenes, dentro de la misma burbuja
   (ej. el precio debajo de las dos fotos de Emprendedores). Mismo gap que
   .msg-imgs para que la separación se vea pareja arriba y abajo de la grilla. */
.msg-text-after{margin-top:8px}
.img-ph-dots i:nth-child(2){animation-delay:.18s}
.img-ph-dots i:nth-child(3){animation-delay:.36s}
.msg.user{background:var(--accent,var(--cyan));color:#07142E;font-weight:500;border-bottom-right-radius:6px;align-self:flex-end}
.msg.sys{align-self:center;max-width:92%;background:rgba(0,186,180,.09);border:1px dashed rgba(0,186,180,.38);color:var(--cyan);
  font-size:11.5px;font-weight:600;text-align:center;border-radius:10px;padding:9px 13px}
.msg b{font-weight:700;color:#fff}
.msg.user b{color:#07142E}
/* Fade de cada mensaje (reemplaza el pop anterior): opacidad 0→1 y
   desplazamiento de 8px abajo a su posición, .32s ease-out — coincide con
   FADE_DURATION en js/main.js (no hay enlace programático entre los dos
   valores, es una duración replicada a mano en ambos archivos). La imagen,
   al ser hija de .msg, entra con la misma animación que la burbuja: no
   necesita su propio keyframe. */
@keyframes msgIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
.typing{align-self:flex-start;background:rgba(255,255,255,.07);border-radius:16px;border-bottom-left-radius:6px;padding:13px 16px;display:flex;gap:4px}
.typing i{width:6px;height:6px;border-radius:50%;background:#7C87A8;animation:bl 1.3s infinite}
.typing i:nth-child(2){animation-delay:.18s}.typing i:nth-child(3){animation-delay:.36s}
@keyframes bl{0%,60%,100%{opacity:.3}30%{opacity:1}}
/* Logo de canal en el pie (Prompt 6, Parte 6): isotipo real de WhatsApp/Telegram
   (sin recolorear) + ícono genérico de SMS, mismo tamaño de caja base. WhatsApp
   se compensa a 18px (mismo criterio que .chan-logo-whatsapp más arriba) porque
   su viewBox recortado no es cuadrado como el de Telegram/SMS y a 16px queda
   con menos peso óptico. */
.demo-cap{font-size:12px;color:#767F9E;margin-top:14px;display:flex;align-items:center;justify-content:center;gap:7px}
.cap-logo{width:16px;height:16px;flex:0 0 16px;object-fit:contain}
.cap-logo-wa{width:18px;height:18px;flex-basis:18px}

/* ---------- THESIS (sección propia, no comparte panel con el hero) ----------
   Fondo blanco: crea contraste fuerte con el hero oscuro que la precede y
   contraste suave con --paper de "Canales" que la sigue.
   Prompt 14 — pasa a 2 columnas: izquierda el argumento (sin cambios),
   derecha 3 puntos que preparan el módulo de agentes de abajo, sin nombrarlos.
   Prompt 15 (Parte 3) — padding bajado de 80px a 64px, en línea con .sec-tight
   (ver SECTIONS más abajo): con el bloque lleno de contenido, el ritmo de 92px
   entre secciones del Home se leía como casi una pantalla de blanco. */
/* Prompt 21 (Parte 1) — padding vertical subido de 64 a 132px: con el H2 en la
   escala nueva (.thesis-h2, mucho más grande), el ritmo de 64px quedaba
   apretado arriba y abajo. */
.thesis{background:#fff;padding:132px 0}
/* Prompt 21 (Parte 1) — salto de escala ÚNICO del sitio: clase dedicada
   (.thesis-h2, no una regla .thesis h2 ni un h1,h2{} general) para que quede
   auditable que este tamaño no se usa en ningún otro título. text-wrap:balance
   se mantiene, heredado de .home h2 (Prompt 19) — acá no se pisa esa propiedad. */
.thesis-h2{font-size:clamp(40px,5.2vw,68px);line-height:1.02;letter-spacing:-0.035em;font-weight:800;max-width:860px}
.thesis-h2 em{font-style:normal;color:var(--cyan)}
.thesis p{color:var(--muted);font-size:17.5px;margin-top:20px;max-width:660px}
/* Prompt 15 (Parte 4) — align-items:center (antes "start"): la columna
   izquierda termina antes que la lista de 3 ítems de la derecha y quedaba
   media columna vacía abajo. Centrada verticalmente respecto de la altura
   real de la fila (que sigue definida por la lista, la más alta), en vez de
   pegada arriba. */
.thesis-grid{display:grid;grid-template-columns:1.15fr 1fr;gap:56px;align-items:center}
.thesis-list{list-style:none;display:flex;flex-direction:column;gap:34px}
/* acento cyan a la izquierda — mismo patrón que .split .closing (línea 443):
   liviano a propósito, sin fondo/borde/radio — el bloque de canales que sigue
   ya usa tarjetas, dos seguidos aplanaban la página (Prompt 14). */
.thesis-item{padding-left:20px;border-left:3px solid var(--cyan)}
.thesis-item h3{font-size:16.5px;font-weight:800;color:var(--navy);letter-spacing:-0.01em}
.thesis-item p{margin-top:6px;max-width:100%;color:var(--muted);font-size:14.6px;line-height:1.55}
/* reveal escalonado — mismo .rv/.rv.in del sitio, solo se suma transition-delay
   por ítem (prefers-reduced-motion ya fuerza transition:none!important en .rv,
   así que el delay queda sin efecto ahí — no rompe la preferencia de accesibilidad). */
.thesis-item:nth-child(2){transition-delay:.1s}
.thesis-item:nth-child(3){transition-delay:.2s}

/* ---------- PANELES OSCUROS ----------
   Regla no negociable: cuando una sección oscura se apoya sobre una clara,
   el radio --r va en las DOS esquinas del borde de contacto, nunca en una sola. */
.dark-top{border-bottom-left-radius:var(--r);border-bottom-right-radius:var(--r);overflow:hidden;position:relative;isolation:isolate}
.dark-top::after{content:"";position:absolute;left:0;right:0;bottom:0;height:220px;pointer-events:none;z-index:3;
  background:radial-gradient(ellipse 70% 100% at 50% 100%,rgba(0,186,180,.13),transparent 70%);
  border-bottom-left-radius:var(--r);border-bottom-right-radius:var(--r)}
.dark-bottom{border-top-left-radius:var(--r);border-top-right-radius:var(--r);overflow:hidden;position:relative;isolation:isolate}
.dark-mid{border-radius:var(--r);overflow:hidden;position:relative;isolation:isolate}

/* ---------- SECTIONS ---------- */
.sec{padding:92px 0;background:#fff}
/* Prompt 15 (Parte 3) — modificador, no toca .sec: .sec es compartida por TODAS
   las páginas del sitio (canal, industria, agentes, planes, contacto...) y el
   alcance de este prompt es solo Home. Bajado de 92px a 64px, mismo valor que
   .thesis, para que el ritmo entre secciones del Home sea consistente y no se
   lea como "casi una pantalla de blanco" entre bloques ya llenos de contenido.
   Se aplica sumando esta clase a los <section class="sec"> del Home únicamente. */
.sec-tight{padding:64px 0}
/* Checkout en Agentes (Prompt 41): tarjeta corta (.agente-detalle.soon) con
   mucho aire abajo por el padding-bottom:92px genérico de .sec. Solo
   padding-bottom, no toca .sec ni .sec-tight — el resto de la página sigue
   en 92px arriba/abajo. */
.sec-bottom-tight{padding-bottom:40px}
.sec-paper{background:var(--paper)}
.sec-head{max-width:700px;margin-bottom:50px}
.sec-head h2{font-size:clamp(27px,3.2vw,39px);font-weight:800;letter-spacing:-0.025em}
/* Industrias del Home: título largo ("Industrias donde NovaSales aplica Agentes AI")
   rompía a 2 líneas por el max-width:700px genérico de .sec-head, aunque sobraba
   ancho en la sección. Scoped a esta sección — el resto de .sec-head sigue en 700px. */
.sec-head-wide{max-width:100%}
/* Derivación en Agentes (Prompt 41): el margin-bottom:50px genérico de
   .sec-head, comparado contra el gap:14px entre bullets de .derivacion-list,
   se leía como un salto. Modificador propio, no toca .sec-head base
   (compartida por todas las páginas). */
.sec-head-tight{margin-bottom:24px}
.sec-head p{margin-top:17px;font-size:17.5px;color:var(--muted)}
/* Cita de fuente (Prompt 8, Parte 1) — texto chico bajo el párrafo, mismo --muted
   pero más chico y sin el margin-top grande de .sec-head p, para leerse como nota
   al pie de esa afirmación puntual, no como continuación del párrafo. */
.sec-head p.fuente{margin-top:6px;font-size:12.5px;color:var(--muted)}

/* cards */
.grid-2{display:grid;grid-template-columns:repeat(2,1fr);gap:22px}
.grid-3{display:grid;grid-template-columns:repeat(3,1fr);gap:22px}
/* Prompt 19 — gap reducido de 20 a 16px: en 4 columnas los 3 gaps entre tarjetas
   pesan más que en las grillas de 3, y sumado al padding interno de .acard (ver
   más abajo) le gana ancho de texto a las tarjetas sin tocar el contenedor
   (.wrap ya es el mismo compartido por canales e industrias, no había margen
   lateral de más ahí para reducir). */
.grid-4{display:grid;grid-template-columns:repeat(4,1fr);gap:16px}
/* grid de industrias (03e) — ahora son 6 activas: 3 columnas x 2 filas, ya que 6 no
   divide parejo en 4 ni queda prolijo en 5. */
.grid-ind{display:grid;grid-template-columns:repeat(3,1fr);gap:20px}
.card{background:#fff;border:1px solid var(--line);border-radius:18px;padding:30px 27px;transition:.25s}
.card:hover{transform:translateY(-4px);border-color:var(--c,var(--cyan));box-shadow:0 22px 46px -24px rgba(16,31,82,.28)}
.card-rule{width:36px;height:3px;border-radius:3px;background:var(--c,var(--cyan));margin-bottom:20px}
.card h3{font-size:20px;margin-bottom:11px}
.card p{font-size:15px;color:var(--muted)}
.card .tag{font-size:11px;letter-spacing:.11em;text-transform:uppercase;color:var(--c,var(--cyan));display:block;margin-bottom:12px;font-weight:600}
.card-note{margin-top:18px;padding-top:16px;border-top:1px solid var(--line);font-size:13.4px;color:#6E7899}
.card-note b{color:var(--navy);font-weight:600}
.card .more{margin-top:16px;display:block;font-size:12.5px;color:var(--c,var(--cyan));font-weight:600}
.card .more::after{content:" →"}

/* pasos */
.steps{display:grid;grid-template-columns:repeat(4,1fr);gap:20px}
.step{background:#fff;border:1px solid var(--line);border-radius:18px;padding:28px 24px;transition:.25s;position:relative}
.step:hover{transform:translateY(-4px);box-shadow:0 22px 46px -24px rgba(16,31,82,.26);border-color:var(--cyan)}
.step-n{width:34px;height:34px;border-radius:11px;background:rgba(0,186,180,.11);color:var(--cyan);font-family:var(--display);
  font-weight:800;font-size:14px;display:flex;align-items:center;justify-content:center;margin-bottom:18px}
.step h3{font-size:17.5px;margin-bottom:10px;line-height:1.3}
.step p{font-size:14.4px;color:var(--muted)}

/* agentes */
/* Prompt 19 — padding lateral de 22 a 18px: gana ancho de texto adentro de la
   tarjeta (ver .grid-4 arriba). Vertical sin cambios. */
.acard{background:#fff;border:1px solid var(--line);border-radius:18px;padding:26px 18px;transition:.25s;display:flex;flex-direction:column;position:relative}
.acard:hover{transform:translateY(-4px);border-color:var(--cyan);box-shadow:0 22px 46px -24px rgba(16,31,82,.28)}
.acard h3{font-size:19px;margin-bottom:8px;line-height:1.25}
.acard .adesc{font-size:14.2px;color:var(--muted);margin-bottom:18px;line-height:1.55}
.acard ul{list-style:none;margin:0;display:flex;flex-direction:column;gap:10px;flex:1}
.acard li{color:var(--body);font-size:13.8px;padding-left:17px;position:relative}
.acard li::before{content:"";position:absolute;left:0;top:9px;width:6px;height:6px;border-radius:50%;background:var(--cyan)}
.acard .ideal{margin-top:22px;padding-top:16px;border-top:1px solid var(--line);font-size:13.2px;color:#6E7899;line-height:1.6}
.acard .ideal b{color:var(--navy);font-weight:600}
.acard .more{margin-top:14px;font-size:12.5px;color:var(--cyan);font-weight:600}
.acard .more::after{content:" →"}
.astep{display:inline-block;font-size:10.5px;letter-spacing:.12em;text-transform:uppercase;font-weight:700;color:var(--cyan);
  background:rgba(0,186,180,.1);padding:5px 10px;border-radius:7px;margin-bottom:14px}
/* Prompt 19 — el badge estaba position:absolute superpuesto al eyebrow (a cualquier
   ancho de tarjeta en el que el eyebrow no dejaba libre el hueco de la esquina
   superior derecha, tapaba texto: "04 · CIERRA Y C[OBRA]"). Pasa al flujo normal,
   en su propia línea debajo del eyebrow — así conviven a cualquier ancho de tarjeta
   sin depender de que el texto del eyebrow sea corto. */
.acard .badge{display:block;width:max-content;font-size:10px;letter-spacing:.08em;text-transform:uppercase;font-weight:700;
  color:#8A6B00;background:#FFF0C2;border:1px solid #F2D98A;padding:4px 9px;border-radius:20px;margin-bottom:14px}
.acard.soon{background:#FBFCFE;border-style:dashed}
.acard.soon .astep{color:#8A6B00;background:rgba(242,217,138,.28)}
.acard.soon li::before{background:#C9A227}

/* Escalera de compromiso (03h): mismo cyan en los 4 agentes, pero con intensidad
   progresiva en el chip de escalón — más sutil en 01, más saturado en 03 — para que
   el orden se lea sin recurrir a un color distinto por agente. El 04 (Checkout,
   .soon) no entra en esta progresión: mantiene su propio tratamiento de estado. */
.acard:nth-child(1) .astep{background:rgba(0,186,180,.08)}
.acard:nth-child(2) .astep{background:rgba(0,186,180,.16)}
.acard:nth-child(3) .astep{background:rgba(0,186,180,.26)}

/* agentes.html — la fila de 4 es el elemento central de la página (ya no hay tabla
   comparativa): más padding interno y más aire entre bullets que la versión del Home. */
.agentes-grid .acard{padding:34px 28px}
.agentes-grid .acard ul{gap:15px}

/* Prompt 21 (Parte 2) — módulo de agentes del Home invertido a banda oscura.
   Clase dedicada .agentes-dark (no se toca .sec/.sec-paper, compartidas por
   todo el sitio, ni .acard/.astep base, compartidas con agentes.html en fondo
   claro — ver nota de scope más abajo). Fondo + textura calcados de .hero
   (grilla sutil enmascarada + resplandor radial): mismos valores, ningún
   tratamiento nuevo. */
.agentes-dark{background:var(--ink);position:relative;overflow:hidden;isolation:isolate}
.agentes-dark::before{content:"";position:absolute;inset:0;
  background-image:linear-gradient(rgba(0,186,180,.05) 1px,transparent 1px),linear-gradient(90deg,rgba(0,186,180,.05) 1px,transparent 1px);
  background-size:60px 60px;
  -webkit-mask-image:radial-gradient(ellipse 78% 62% at 28% 42%,#000 18%,transparent 76%);
  mask-image:radial-gradient(ellipse 78% 62% at 28% 42%,#000 18%,transparent 76%)}
.agentes-dark::after{content:"";position:absolute;width:800px;height:800px;right:-240px;top:-280px;border-radius:50%;
  background:radial-gradient(circle,rgba(0,186,180,.19),transparent 63%);pointer-events:none}
.agentes-dark .wrap{position:relative;z-index:2}
.agentes-dark .sec-head h2{color:#fff}
.agentes-dark .sec-head p{color:#98A1C0}
/* tarjetas translúcidas — el fondo de la banda tiene que transparentarse detrás,
   por eso no van sólidas. */
.agentes-dark .acard{background:rgba(255,255,255,.045);border-color:rgba(255,255,255,.10)}
.agentes-dark .acard h3{color:#fff}
.agentes-dark .acard .adesc{color:#93A0BE}
.agentes-dark .acard li{color:#C4CDE2}
.agentes-dark .acard .ideal{border-top-color:rgba(255,255,255,.10);color:#8F9BB8}
.agentes-dark .acard .ideal b{color:#fff}
/* chip del eyebrow — mismo cyan, fondo un poco más presente que en claro (.15
   en vez de .1) para que no se pierda contra el ink. Pisa la progresión de
   intensidad por tarjeta (Prompt 15/16) con la misma especificidad: acá los
   3 chips van parejos, la progresión es un recurso pensado para fondo claro. */
.agentes-dark .acard:nth-child(1) .astep,
.agentes-dark .acard:nth-child(2) .astep,
.agentes-dark .acard:nth-child(3) .astep{background:rgba(0,186,180,.15)}
/* Checkout (.soon) — mismo tratamiento diferenciado, en ámbar sobre fondo oscuro. */
.agentes-dark .acard.soon{background:rgba(240,196,90,.05);border-color:rgba(240,196,90,.42)}
.agentes-dark .acard.soon .astep{color:#F0C45A;background:rgba(240,196,90,.16)}
.agentes-dark .acard.soon li::before{background:#F0C45A}

/* agentes.html (Prompt 34b) — comparativa en tarjetas. Alineación por
   grid-template-rows:subgrid: .comp-grid define 4 filas (head/objetivo/
   mensajes/medida) x 4 columnas (una por tarjeta); cada .comp-card ocupa
   las 4 filas de su columna y hace subgrid, así toma el alto real de cada
   fila (el máximo entre las 4 tarjetas) sin min-height fijo. En mobile
   (1 columna) el subgrid de filas ya no aporta nada — se cae a bloque
   normal, altura de cada tarjeta según su propio contenido.
   Divisorias: una sola línea bajo el nombre (.comp-card-head), el resto de
   los campos se separa con espacio (margin-top en .comp-row), no con reglas.
   Estética coherente con .card/.acard del resto del sitio, pero clase propia:
   no se reusan sus reglas para no atar esta grilla a cambios ahí. */
.comp-grid{display:grid;grid-template-columns:repeat(4,1fr);grid-template-rows:repeat(4,auto);gap:20px}
.comp-card{grid-row:1 / span 4;display:grid;grid-template-rows:subgrid;background:#fff;border-radius:18px;padding:24px 22px;
  box-shadow:0 1px 2px rgba(16,31,82,.04),0 18px 40px -12px rgba(16,31,82,.16)}
/* delay escalonado de 60ms por tarjeta, mismo patrón que .tone-card (línea
   ~861) y .thesis-item (línea ~284): transition-delay por nth-child como
   longhand suelto, sin repetir el shorthand transition de .rv — así no lo
   pisa. prefers-reduced-motion ya fuerza transition:none!important más abajo. */
.comp-card:nth-child(2){transition-delay:.06s}
.comp-card:nth-child(3){transition-delay:.12s}
.comp-card:nth-child(4){transition-delay:.18s}
/* Hover: selector con más clases que .rv (incluye .in) para que el shorthand
   transition de acá gane por especificidad mientras dura el :hover, igual
   que .ui-shot.rv-shot.in:hover (línea ~1030) — al salir del hover, .rv
   vuelve a mandar y la transición de salida usa su propia duración. Cortado
   por debajo de 768px junto con hover:hover. */
@media(hover:hover) and (min-width:768px){
  .comp-card.rv.in:hover{transform:translateY(-4px);
    box-shadow:0 4px 10px rgba(16,31,82,.06),0 26px 52px -14px rgba(16,31,82,.24),inset 0 2px 0 0 var(--cyan);
    transition:transform .2s cubic-bezier(.2,.7,.3,1),box-shadow .2s cubic-bezier(.2,.7,.3,1)}
}
.comp-card-head{display:flex;align-items:center;flex-wrap:wrap;gap:8px;border-bottom:1px solid var(--line);padding-bottom:14px;align-content:start}
.comp-card-head h3{font-size:18px;line-height:1.25}
.comp-card-badge{display:block;width:max-content;font-size:9.5px;letter-spacing:.08em;text-transform:uppercase;font-weight:700;
  color:#8A6B00;background:#FFF0C2;border:1px solid #F2D98A;padding:3px 8px;border-radius:20px}
.comp-row{margin-top:14px;align-self:start}
.comp-row span{display:block;font-size:11px;letter-spacing:.06em;text-transform:uppercase;font-weight:700;color:var(--muted);margin-bottom:6px}
.comp-row p{font-family:var(--display);font-weight:600;font-size:19px;color:var(--navy);line-height:1.3}
.comp-row-empty span{opacity:.5}
.comp-card-soon{background:#FBFCFE;border:1px dashed var(--line)}
@media(max-width:900px){
  .comp-grid{grid-template-columns:repeat(2,1fr);grid-template-rows:none}
  .comp-card{grid-row:auto;display:block}
}
@media(max-width:560px){
  .comp-grid{grid-template-columns:1fr}
}

/* agentes.html (Prompt 35b/38/39) — detalle por agente en dos columnas, reusando
   .platform-split/-rev de Plataforma pero con su propia proporción: acá el
   texto pesa más que la ilustración (3fr/2fr), al revés que en Plataforma,
   así que se pisa grid-template-columns para las dos variantes scopeado a
   .agente-detalle (no toca el significado de .platform-split/-rev ahí).
   Columna izquierda: .agente-detalle-texto (texto + ficha Trabaja sobre/
   Entrega al pie, dos campos lado a lado como antes del Prompt 35). Columna
   derecha: .agente-visual con la ilustración SVG del agente (Prompt 38) —
   sin borde/fondo propio porque el SVG ya trae fondo transparente; escala
   al ancho de la columna con un max-width para no crecer de más en
   pantallas anchas, centrada en las dos direcciones dentro de su columna.
   Canales sale de acá: los logos ya están en el nav y van al módulo final
   (Prompt 37), no se repiten en cada ficha.
   Alternancia texto-izquierda/derecha (no solo proporción, como en
   Plataforma): en .platform-split-rev el order de .agente-detalle-texto y
   .agente-visual se invierte — como el grid-template-columns de la variante
   rev también queda invertido (2fr/3fr en vez de 3fr/2fr), el texto sigue
   siendo siempre la columna más ancha, cambie de lado o no. Ese order se
   resetea abajo de 900px (mismo breakpoint donde .platform-split colapsa a
   una columna) para que la ilustración quede siempre debajo del texto en
   mobile, no arriba. */
.agente-detalle-badge{display:block;width:max-content;font-size:10px;letter-spacing:.08em;text-transform:uppercase;font-weight:700;
  color:#8A6B00;background:#FFF0C2;border:1px solid #F2D98A;padding:4px 9px;border-radius:20px;margin-bottom:14px}
.agente-detalle-contexto{font-size:15.2px;color:var(--body);line-height:1.7;margin-bottom:26px}
.agente-detalle-puntos{list-style:none;margin:0;display:flex;flex-direction:column;gap:12px}
.agente-detalle-puntos li{color:var(--body);font-size:14.4px;font-weight:600;line-height:1.55;padding-left:18px;position:relative}
.agente-detalle-puntos li::before{content:"";position:absolute;left:0;top:9px;width:6px;height:6px;border-radius:50%;background:var(--cyan)}
.agente-detalle-meta{display:flex;flex-wrap:wrap;gap:24px;padding-top:20px;margin-top:24px;border-top:1px solid var(--line)}
.agente-detalle-meta>div{flex:1;min-width:200px}
.agente-detalle-meta span{display:block;font-size:11.5px;letter-spacing:.06em;text-transform:uppercase;font-weight:700;color:var(--muted);margin-bottom:6px}
.agente-detalle-meta p{font-size:13.8px;color:var(--body);line-height:1.5}
.agente-detalle-integraciones{font-size:13.4px;color:var(--muted);margin-top:20px}
.agente-detalle.platform-split{grid-template-columns:3fr 2fr}
.agente-detalle.platform-split-rev{grid-template-columns:2fr 3fr}
.agente-visual{align-self:stretch;display:flex;align-items:center;justify-content:center}
.agente-visual-img{display:block;width:100%;max-width:420px;height:auto;margin:0 auto}
.agente-detalle.platform-split-rev .agente-detalle-texto{order:2}
.agente-detalle.platform-split-rev .agente-visual{order:1}
@media(max-width:900px){
  .agente-detalle.platform-split-rev .agente-detalle-texto,
  .agente-detalle.platform-split-rev .agente-visual{order:0}
}
/* #consultivo en banda oscura (Prompt 36) — mismo patrón translúcido que
   .agentes-dark .acard (ver arriba): texto/rótulos invertidos, la ficha
   Trabaja sobre/Entrega pasa de línea separadora a caja translúcida
   (fondo rgba(255,255,255,.045), borde rgba(255,255,255,.10), igual que
   las tarjetas). .sec-head h2/p ya se invierten solos (regla genérica de
   .agentes-dark). El punto cyan de los bullets no se toca, ya lee bien
   sobre fondo oscuro. */
.agentes-dark .agente-detalle-contexto{color:#93A0BE}
.agentes-dark .agente-detalle-puntos li{color:#C4CDE2}
.agentes-dark .agente-detalle-meta{background:rgba(255,255,255,.045);border:1px solid rgba(255,255,255,.10);
  border-radius:14px;padding:20px 22px}
.agentes-dark .agente-detalle-meta span{color:#8F9BB8}
.agentes-dark .agente-detalle-meta p{color:#C4CDE2}
/* Checkout (soon) no tiene ficha ni visual: el texto ocupa las dos columnas
   del grid. Mismo tratamiento dashed/ámbar que .acard.soon, aplicado al
   contenedor split completo. */
.agente-detalle.soon{background:#FBFCFE;border:1px dashed var(--line);border-radius:20px;padding:32px 30px}
.agente-detalle.soon .agente-detalle-texto{grid-column:1/-1;max-width:760px;order:0}

/* derivación — lista simple, mismo patrón de punto cyan que .legal-list. */
.derivacion-list{list-style:none;margin:0;display:flex;flex-direction:column;gap:14px;max-width:760px}
.derivacion-list li{font-size:14.6px;color:var(--body);line-height:1.6;padding-left:18px;position:relative}
.derivacion-list li::before{content:"";position:absolute;left:0;top:9px;width:6px;height:6px;border-radius:50%;background:var(--cyan)}

/* ícono de plataforma por canal (Ajuste 2, 03c) — mismo componente visual que .card-icon,
   coloreado con el acento tokenizado de cada canal via --c inline. Se ubica en las cards
   de "Por qué [canal]", no en el hero. */
.chan-icon{width:42px;height:42px;border-radius:13px;background:var(--c-soft,rgba(0,186,180,.13));
  border:1px solid var(--c,var(--cyan));display:flex;align-items:center;justify-content:center;margin-bottom:20px}
.chan-icon::after{content:"";width:16px;height:16px;border-radius:5px;background:var(--c,var(--cyan))}
/* Ícono real por ítem (WhatsApp "por qué", item.icono/item.logo): se descartó reusar
   .seg-icon/.seg-icon-glyph (bullets del DEMO FIJO) porque es un círculo de 46px con
   spacing por gap de flex, pensado para una lista apilada — acá el slot ya existente es
   el cuadrado de 42px de .chan-icon con margin-bottom, misma forma/tamaño que ya resuelve
   .card-icon-real/.card-icon-glyph en Plataforma para el mismo tipo de swap (cuadrado
   decorativo -> ícono real). Se replica esa técnica ya establecida en vez de forzar el
   componente de otra sección. El color sigue saliendo de --c, la misma variable que ya
   trae .chan-icon por canal — no hace falta ninguna variable nueva para el verde de
   WhatsApp, ya es su acento (#00AE54, content/es.json). */
.chan-icon-real::after{content:none}
.chan-icon-glyph{width:26px;height:26px;display:block;color:var(--c,var(--cyan))}
.chan-icon-glyph svg{width:100%;height:100%;display:block}
/* item.logo (caso Meta): mismo contenedor .chan-icon (fondo/borde tintados, 42px), pero
   sin recolorear el logo — va en sus colores originales (gradiente propio, sin
   currentColor), por eso <img> en vez de svg_inline(). 22px de ancho (más chico que los
   26px del glyph de línea): el logo de Meta es una marca sólida/con relleno, no un trazo
   fino de 2px como los íconos Tabler, así que al mismo tamaño se lee más pesado —se achica
   un poco para que las tres tarjetas queden parejas. Ajuste estimado sin verificación
   visual (sandbox de preview bloqueado en esta carpeta). height:auto conserva el aspect
   ratio real del archivo (287.59x191 de viewBox) a partir del width/height del <img>. */
.chan-icon-logo::after{content:none}
.chan-icon-logo-img{width:22px;height:auto;display:block}

/* logo/isotipo por canal (WhatsApp/Telegram/SMS, los tres con su propio asset) —
   usado en las cards de Home ("Un agente, tres canales") y en el hero de cada
   página de canal individual. Distinto de .chan-icon (que sigue siendo el ícono
   decorativo genérico de las cards "Por qué [canal]", sin tocar). */
.chan-logo{display:block;width:42px;height:42px;margin-bottom:20px;border-radius:13px;object-fit:contain}
.chan-logo-hero{margin-bottom:0}
/* el isotipo de WhatsApp (assets/logos/whatsapp-3.svg) traía ~46% de margen vacío
   dentro de su propio viewBox — se recortó el viewBox del SVG para que el dibujo
   ocupe casi todo el canvas (igual que Telegram). Queda un leve ajuste de tamaño
   acá porque su forma final no es perfectamente cuadrada (tiene "colita" de globo
   de chat), a diferencia del círculo 1:1 de Telegram. */
.chan-logo-whatsapp{width:46px;height:46px}
.chan-logo-hero.chan-logo-whatsapp{width:50px;height:50px}
/* logo + eyebrow en una sola línea, en el hero de cada página de canal (Ajuste logos v2) */
.hero-brand{display:flex;align-items:center;gap:10px;margin-bottom:14px}
.hero-brand .eyebrow{margin:0}

/* páginas de industria (template genérico) — párrafo de problema, sin card, solo tipografía */
.problema-body{max-width:760px}
.problema-body .problema-lead{font-family:var(--display);font-weight:700;font-size:19px;color:var(--navy);margin-bottom:14px}
.problema-body p{font-size:16px;color:var(--body);line-height:1.6}

/* banner de "cobertura" (esquema Retail, 03e) — mismo tratamiento que .split .closing:
   una línea, sin card ni sección grande. */
.cobertura-lead{font-family:var(--display);font-weight:700;font-size:19px;color:var(--navy);
  max-width:760px;padding-left:18px;border-left:3px solid var(--cyan)}

/* nota de roadmap (Checkout "próximamente") en el cierre de industria_pymes — mismo tono
   ámbar que ya usa el badge/borde punteado de la card de Agente de Checkout en agentes.html,
   pero como nota breve de 1-2 líneas, no una sección grande.
   Hoy sin uso: la clave checkout_nota se eliminó de Emprendedores. Se conservan porque
   el bloque sigue disponible por dato para cualquier industria. */
.roadmap-note{max-width:560px;margin:26px auto 0;padding:14px 18px;border:1px dashed rgba(242,217,138,.4);
  border-radius:12px;background:rgba(255,255,255,.03);color:#C9B37A;font-size:13.6px;line-height:1.6}
.roadmap-badge{display:inline-block;font-size:10px;letter-spacing:.08em;text-transform:uppercase;font-weight:700;
  color:#8A6B00;background:#FFF0C2;border:1px solid #F2D98A;padding:4px 9px;border-radius:20px;margin-right:10px;vertical-align:middle}

/* ---------- Planes (prompt 04) ---------- */
/* card de plan — mismo lenguaje visual que .card (borde/radio/hover), con badge
   "Recomendado" reusando el mismo tratamiento cyan de .astep en vez de inventar uno. */
.plan-card{background:#fff;border:1px solid var(--line);border-radius:18px;padding:30px 27px;transition:.25s;position:relative}
.plan-card:hover{transform:translateY(-4px);border-color:var(--cyan);box-shadow:0 22px 46px -24px rgba(16,31,82,.28)}
.plan-card.recommended{border-color:var(--cyan);box-shadow:0 22px 46px -24px rgba(0,186,180,.35)}
.plan-badge{display:inline-block;font-size:10.5px;letter-spacing:.12em;text-transform:uppercase;font-weight:700;color:var(--cyan);
  background:rgba(0,186,180,.1);padding:5px 10px;border-radius:7px;margin-bottom:14px}
.plan-card h3{font-size:20px;margin-bottom:9px}
.plan-head{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:9px}
.plan-head h3{margin-bottom:0}
.plan-head .plan-badge{margin-bottom:0}
.plan-desc{font-size:14.2px;color:var(--muted);margin-bottom:18px;line-height:1.55}
.plan-card ul{list-style:none;margin:0;display:flex;flex-direction:column;gap:10px}
.plan-card li{color:var(--body);font-size:13.8px;padding-left:17px;position:relative}
.plan-card li::before{content:"";position:absolute;left:0;top:9px;width:6px;height:6px;border-radius:50%;background:var(--cyan)}

/* tabla comparativa — mismo tratamiento que .compare (borde/radio/overflow), pero a
   4 columnas (feature + 3 planes) y con celda tick/dash en vez de texto. Filas
   ordenadas en el JSON para que "lea todo incluido" primero. */
.ptable{display:grid;grid-template-columns:1.4fr 1fr 1fr 1fr;border:1px solid var(--line);border-radius:18px;overflow:hidden;background:#fff}
.ptable-head{padding:16px 20px;font-family:var(--display);font-weight:800;font-size:14px;letter-spacing:-0.01em;background:var(--paper);color:var(--navy)}
.ptable-head.ptable-feature{background:#fff}
.ptable-cell{padding:14px 20px;font-size:13.8px;color:var(--body);border-top:1px solid var(--line);display:flex;align-items:center}
.ptable-cell.ptable-feature{color:var(--navy);font-weight:600;justify-content:flex-start}
.ptable-cell:not(.ptable-feature){justify-content:center;text-align:center}
.ptable .dash{color:var(--muted);font-weight:600}

/* FAQ — acordeón nativo <details>/<summary>, sin JS. Mismo borde/radio que .card. */
.faq-list{display:flex;flex-direction:column;gap:12px;max-width:820px}
.faq-item{background:#fff;border:1px solid var(--line);border-radius:14px;padding:6px 22px;transition:border-color .2s}
.faq-item[open]{border-color:var(--cyan)}
.faq-item summary{padding:16px 0;font-family:var(--display);font-weight:700;font-size:15.5px;color:var(--navy);cursor:pointer;list-style:none}
.faq-item summary::-webkit-details-marker{display:none}
.faq-item summary::after{content:"+";float:right;color:var(--cyan);font-size:20px;font-weight:600}
.faq-item[open] summary::after{content:"−"}
.faq-item p{padding:0 0 18px;font-size:14.6px;color:var(--muted);line-height:1.6}

/* ---------- Contacto (prompt 04, ajustes Prompt 11 y 12) ---------- */
/* bloque WhatsApp — Prompt 12: deja de ser panel oscuro (esa instrucción del
   Prompt 11 estaba equivocada). Pasa a ser contenido normal sobre la sección
   clara que lo envuelve (.sec, fondo blanco) — sin fondo, radio ni overflow
   propios; solo tipografía centrada, mismo criterio de color que .sec-head. */
.wa-panel{text-align:center}
.wa-panel h2{color:var(--navy);font-size:clamp(24px,2.8vw,32px);font-weight:800;letter-spacing:-0.025em;margin-bottom:14px}
.wa-panel p{color:var(--muted);font-size:16.5px;max-width:520px;margin:0 auto 28px}
.wa-panel .cta-row{justify-content:center}
/* único lugar del sitio donde el CTA primario es verde en vez de coral — acá el verde
   ES el contexto (mismo criterio que --verde-whatsapp en el resto del sitio). El
   box-shadow verde se mantiene sobre fondo claro: es una sombra de elevación
   estándar (mismo color que el botón), no el patrón de grilla del hero que sí
   se sacó — no se ve sucio sobre blanco/paper. */
.btn-whatsapp{font-family:var(--text);font-size:15px;font-weight:600;padding:15px 28px;border-radius:12px;display:inline-flex;
  align-items:center;gap:10px;transition:.22s;border:none;cursor:pointer;background:var(--verde-whatsapp);color:#fff;box-shadow:0 8px 26px -9px rgba(0,174,84,.45)}
.btn-whatsapp:hover{background:#009449;transform:translateY(-2px);box-shadow:0 15px 32px -9px rgba(0,174,84,.5)}
/* logo de WhatsApp inline en el botón (Prompt 12, Parte 2): el mask-image del
   Prompt 11 no renderizaba. Se pega el SVG inline con fill="currentColor" en
   el path (ver contacto.html), así hereda el color del texto del botón sin
   depender de soporte de máscaras CSS.
   display:block saca el <svg> del flujo de línea de texto (por defecto es
   inline y queda sujeto al line-height del botón), evitando que se desalinee
   o se vea recortado por la caja de línea dentro del inline-flex. */
.btn-whatsapp-logo{width:22px;height:22px;flex:0 0 22px;display:block}

/* ---------- Privacidad (prompt 04) ---------- */
/* página sobria, tipográfica: sin paneles oscuros, columna angosta, índice sticky. */
.legal-wrap{max-width:820px}
.legal-header{padding-bottom:0}
.legal-header h1{font-size:clamp(28px,3.4vw,40px)}
.legal-vigencia{font-size:13.5px;color:var(--muted);margin-top:14px}
.legal-intro{font-size:16.5px;color:var(--body);margin-top:22px;line-height:1.65}
.legal-layout{display:grid;grid-template-columns:220px 1fr;gap:56px;align-items:start;max-width:1040px}
.legal-index{position:sticky;top:96px;display:flex;flex-direction:column;gap:2px}
.legal-index a{font-size:13px;color:var(--muted);padding:8px 0;line-height:1.4;border-left:2px solid transparent;padding-left:14px}
.legal-index a:hover{color:var(--navy);border-left-color:var(--cyan)}
.legal-content{max-width:720px}
.legal-section{padding:28px 0;border-top:1px solid var(--line)}
.legal-section:first-child{border-top:none;padding-top:0}
.legal-section h2{font-size:19.5px;margin-bottom:14px}
.legal-section p{font-size:15px;color:var(--body);line-height:1.7;margin-bottom:12px}
.legal-section p:last-child{margin-bottom:0}
.legal-list{list-style:none;margin:0 0 12px;display:flex;flex-direction:column;gap:10px}
.legal-list li{font-size:15px;color:var(--body);line-height:1.7;padding-left:18px;position:relative}
.legal-list li::before{content:"";position:absolute;left:0;top:9px;width:6px;height:6px;border-radius:50%;background:var(--cyan)}

/* industrias — Prompt 17: acento unificado a --cyan (antes var(--c), inline por
   industria: verde en Retail Tradicional, naranja en Real Estate, rojo en
   Automotriz — competía con la regla base del sitio, donde cyan es el acento
   dominante y verde/azul están reservados a WhatsApp/Telegram). */
.ind{background:#fff;border:1px solid var(--line);border-radius:18px;padding:26px 23px;transition:.25s;display:flex;flex-direction:column;height:100%}
.ind:hover{transform:translateY(-4px);border-color:var(--cyan);box-shadow:0 22px 46px -24px rgba(16,31,82,.26)}
/* Contenedor de imagen — ratio fijo 3:2, radio consistente con el sistema de paneles.
   Sin foto: fallback visible en --paper con el nombre (nunca se ve "roto"). Con foto:
   duotono cyan/navy vía mix-blend-mode — capa de color sobre la imagen (no sobre el
   archivo), conserva la luminosidad de la foto para que siga siendo legible y no un
   bloque de color plano. .no-duo (mockups de UI, no fotografía) desactiva la capa. */
.ind-ph{aspect-ratio:3/2;border-radius:13px;margin-bottom:20px;overflow:hidden;position:relative;background:var(--paper)}
.ind-ph-fallback{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;text-align:center;padding:0 14px;
  font-size:11px;color:var(--cyan);letter-spacing:.09em;text-transform:uppercase;border:1px dashed var(--cyan);border-radius:13px;font-weight:600}
.ind-ph img{width:100%;height:100%;object-fit:cover;display:block}
.ind-ph.has-img::after{content:"";position:absolute;inset:0;background:linear-gradient(160deg,var(--navy),var(--cyan));
  mix-blend-mode:color;opacity:.88;transition:.25s}
.ind:hover .ind-ph.has-img::after{opacity:.7}
.ind-ph.has-img.no-duo::after{display:none}
.ind h3{font-size:18px;margin-bottom:9px}
.ind p{font-size:14.4px;color:var(--muted);flex:1}
.ind .more{margin-top:18px;font-size:12.5px;color:var(--cyan);font-weight:600}
.ind .more::after{content:" →"}

/* split (bloque híbrido) */
.split{display:grid;grid-template-columns:1fr 1fr;gap:62px;align-items:center}
.split-ph{height:350px;border-radius:20px;background:linear-gradient(140deg,rgba(0,186,180,.1),rgba(252,66,54,.06));border:1px dashed var(--line);
  display:flex;align-items:center;justify-content:center;font-size:11.5px;color:var(--muted);letter-spacing:.09em;text-transform:uppercase;font-weight:600}

/* Contenedor de imagen del bloque Híbrido — mismo patrón que .ind-ph (ratio fijo,
   object-fit cover, fallback en --paper, duotono listo vía has-img/no-duo) para que la
   foto final entre sin rehacer el bloque. Sin imagen todavía: el asset evaluado
   (vendedores_real2.png) fue descartado — ver nota en content/es.json. */
.media-ph{aspect-ratio:3/2;border-radius:20px;overflow:hidden;position:relative;background:var(--paper);
  display:flex;align-items:center;justify-content:center;text-align:center;padding:0 24px;
  font-size:11.5px;color:var(--muted);letter-spacing:.09em;text-transform:uppercase;font-weight:600;border:1px dashed var(--line)}
.media-ph img{width:100%;height:100%;object-fit:cover;display:block}
.media-ph.has-img{border:none}
.media-ph.has-img::after{content:"";position:absolute;inset:0;background:linear-gradient(160deg,var(--navy),var(--cyan));
  mix-blend-mode:color;opacity:.88}
.media-ph.has-img.no-duo::after{display:none}
/* SVG animado del bloque Híbrido (Prompt 18) — inyectado inline, no <img>, así que
   .media-ph img no le aplica. viewBox 3:2 igual que el contenedor: con width:100%
   y height:auto llena el espacio sin recorte ni deformación. */
.media-ph svg{width:100%;height:auto;display:block}
.split h2{font-size:clamp(25px,3vw,36px);margin-bottom:20px;font-weight:800;letter-spacing:-0.025em}
.split .kicker{font-size:19px;color:var(--navy);font-weight:700;font-family:var(--display);margin-bottom:18px}
.split p{font-size:16.5px;color:var(--muted);margin-bottom:15px}
.split p strong{color:var(--navy);font-weight:600}
.split .closing{font-size:17.5px;color:var(--navy);font-weight:600;margin-top:22px;padding-left:18px;border-left:3px solid var(--cyan)}

/* bloque híbrido de industria (retail-tradicional / retail-farmaceutico) — jerarquía
   propia, scopeada a .hibrido-industria para no tocar el bloque gemelo del Home,
   que comparte .wrap.split pero no lleva esta clase. H2 sube al escalón de
   .sec-head h2 (línea 313) y usa text-wrap:balance, mismo tratamiento que .home h2
   (línea 55). "Ambos." abre el párrafo de texto como continuación del flujo
   (antes kicker en línea propia, .split .kicker línea 747; después dentro del H2):
   sin font-size propio, hereda el tamaño de .split p por estar dentro de ese
   párrafo; conserva el cyan y el peso 700 que ya tenía, distinguiéndose del resto
   del párrafo (.split p, color muted, sin negrita). */
.hibrido-industria h2{font-size:clamp(27px,3.2vw,39px);text-wrap:balance}
.hibrido-industria-respuesta{color:var(--cyan);font-weight:700}

/* apertura (conversion) de las dos páginas de retail — scopeada a .conversion-retail
   (agregada cuando p.archivo es retail-tradicional.html o retail-farmaceutico.html,
   ver industria.html) para no tocar el conversion de Real Estate, que comparte
   .sec-head/.sec-head p. El texto sube al escalón "lead" ya usado para este mismo
   rol en .cobertura-lead/.problema-lead/.attach-lead (19px/700/var(--display)/navy)
   — antes de migrar a este esquema, este mismo texto ya usaba ese tratamiento como
   .cobertura-lead (línea 605). El padding-bottom lo da sec-bottom-tight (línea 310,
   ya usado en agentes.html #checkout), no una regla nueva. */
.conversion-retail .sec-head p{font-family:var(--display);font-weight:700;font-size:19px;color:var(--navy)}

/* módulo "cómo actúa la AI" (por ahora solo retail farmacéutico, vía
   p.ia_proceso is defined) — dos columnas de primer nivel: .ia-proceso-col
   (paso 1 + paso 2 apilados, agrupados desde el propio Jinja) y el paso 3
   como hijo directo de .ia-proceso-shots. Antes la ubicación salía de
   nth-child sobre una grilla plana de tres ítems; al ser el paso 3 más alto
   que el paso 1, el paso 2 heredaba la fila 2 del grid completo (la altura
   del paso 3) y quedaba descolgado en vez de pegado al paso 1. Con el
   wrapper propio cada columna crece según su propio contenido.
   align-items:start + min-width:0 en los hijos (mismo patrón que
   .platform-split>*, línea 1268): ninguna columna se estira para igualar
   alturas. El gap interno de .ia-proceso-col (18px) reusa la misma
   separación que ya hay entre un rótulo y su imagen (.eyebrow, línea 59,
   margin-bottom:18px), no el gap de 22px entre columnas ni el espaciado de
   sección. Rótulo reusa .eyebrow, ya probado sobre fondo claro en el
   sec-head de Plataforma. Mismo componente .ui-shot/.ui-shot-parallax que
   Plataforma (línea 1280, js/main.js:58, ya preparado para cualquier
   cantidad de .ui-shot-parallax en la página). En mobile (línea ~1320) la
   grilla pasa a una columna: el orden visual ya queda 1, 2, 3 porque
   .ia-proceso-col (con paso 1 arriba de paso 2) sigue siendo el primer hijo
   del grid y el paso 3 el segundo — no hace falta la propiedad order. */
.ia-proceso-shots{display:grid;grid-template-columns:repeat(2,1fr);gap:22px;align-items:start}
.ia-proceso-shots>*{min-width:0}
.ia-proceso-col{display:flex;flex-direction:column;gap:18px}

/* hero de página interna (Plataforma y sucesivas — sin grid de demo, Prompt 9).
   .hero-in.single ya NO tiene max-width propio: antes lo tenía (760px) y, al
   estar centrado por el margin:0 auto que le da .wrap en el mismo elemento,
   el hero quedaba centrado en la página mientras el contenido de abajo (.wrap
   liso) arranca al gutter izquierdo — de ahí el desalineado. Ahora el wrapper
   ocupa el ancho completo del .wrap (1180px, mismo gutter que el resto) y el
   ancho de lectura cómodo vive en .hero-text, alineado a la izquierda. */
.hero-in.single{grid-template-columns:1fr}
.hero-in.single .hero-lead,.hero-in.single .hero-sub{max-width:100%}
.hero-text{max-width:800px}

/* hero interior — unifica lo que antes era .hero-compact (agrandado a todas
   las páginas interiores, no solo canal.html: la altura mínima y el ritmo
   vertical deben ser consistentes entre Plataforma/Agentes/Canales/Industrias/
   Planes/Contacto). flex+align-items centra el bloque de texto dentro de la
   banda cuando min-height fuerza más alto que el contenido (Parte 4 y 5). */
.hero-interior{padding:72px 0 var(--hero-i-pad-bottom);min-height:420px;display:flex;align-items:center}
.hero-interior .cta-row{margin-top:var(--hero-gap-lg)}
.hero-interior h1{text-wrap:balance}
/* eyebrow "camino" de las 6 páginas de Industria (Prompt 13) — mismo tratamiento
   tipográfico que .eyebrow (cyan, versalitas, tracking), solo se agrega nowrap:
   es una sola línea corta tipo "Industrias · Retail Farmacéutico" y a 390px
   nunca se acerca al ancho del gutter, pero se fuerza para que nunca rompa. */
.hero-interior .eyebrow{white-space:nowrap}

/* Contacto (Prompt 11) — EXCEPCIÓN DELIBERADA al alineado a la izquierda de
   los heros interiores de arriba (Prompt 9). Contacto es una página focal de
   una sola acción, no de contenido, así que su hero se centra horizontalmente
   en vez de alinearse al gutter. No copiar este patrón a otras páginas.
   Pierde también el min-height fijo de los demás heros interiores: sin
   bullets ni CTA en este hero, ese mínimo dejaba un vacío grande debajo de
   la bajada; acá el alto lo define el contenido + padding simétrico. */
.hero-center{text-align:center;min-height:0;padding:80px 0}
.hero-center .hero-text{margin:0 auto}
/* Prompt 12, Parte 3 — la bajada de Contacto (única con hero-center) rompía
   dejando "Sí: es" colgado solo en su línea. text-wrap:pretty no alcanzaba
   por sí solo porque .hero-in.single .hero-lead queda sin max-width (100%);
   acá, centrada, un ancho de lectura más angosto reparte mejor las líneas. */
.hero-center .hero-lead{max-width:620px;margin-left:auto;margin-right:auto;text-wrap:pretty}

/* Prompt 12, Parte 4 — "Qué esperar" es la única sec-head centrada del sitio,
   scopeada a Contacto vía .sec-head-center (no se toca .sec-head en general:
   el resto de las secciones del sitio sigue alineada a la izquierda). */
.sec-head-center{margin-left:auto;margin-right:auto;text-align:center}

/* demo fijo de canal (WhatsApp/Telegram/SMS) — mismo componente .phone del Home,
   sin pestañas, centrado en su propia sección. */
.demo-fixed{max-width:380px;margin:0 auto}

/* demo-wa/demo-tg (Paso 2/3, generalizado a Telegram) — sección propia del DEMO
   FIJO en whatsapp.html/telegram.html, scopeada por canal_id en canal.html: no
   afecta a Home (.demo) ni a SMS (sigue con .demo-fixed desnudo, sin clase de
   canal). Reglas agrupadas por selector (.demo-wa X, .demo-tg X) en vez de
   duplicar el bloque entero: es el mismo layout para los dos canales, solo
   cambia el color (ver los dos bloques de color al final, sí separados por
   canal). Los nombres de clase en el HTML (demo-wa-, demo-tg-) no se unifican
   porque canal.html ya los emite así por dato (demo_key, ver build.py) y
   cambiarlos alteraría el output ya publicado de whatsapp.html. Ancho del
   encabezado angostado a 680px en vez de los 700px genéricos de .sec-head —
   tope propio de este bloque, no toca la regla base (Paso 3b: ya no se centra
   con .sec-head-center, ver más abajo). */
.demo-wa .sec-head,.demo-tg .sec-head,.demo-sms .sec-head{max-width:680px}

/* demo-wa/demo-tg — Paso 3b, dos columnas. Reusa .platform-split (Plataforma/
   Agentes) en vez de inventar un grid propio. Proporción 3fr/2fr (texto más
   ancho que teléfono): mismo valor que .agente-detalle.platform-split, ya
   usado en el sitio para el caso "el texto pesa más que la columna angosta".
   min-width:0 de los hijos ya lo cubre la regla base .platform-split>*; el
   colapso a una columna en mobile (900px) también es el de la regla base, sin
   necesidad de resetear order acá (ver comentario en canal.html). align-items:
   start (pisa el align-items:center de la base .platform-split): misma
   corrección ya aplicada en .agente-detalle.platform-split-rev, para que las
   dos columnas arranquen alineadas arriba en vez de centradas verticalmente
   entre sí. */
.demo-wa-split.platform-split,.demo-tg-split.platform-split,.demo-sms-split.platform-split{grid-template-columns:3fr 2fr;align-items:start}

/* Bullets del demo-wa-text/demo-tg-text (Paso 4, generalizado a Telegram en el
   Paso 5 de Telegram): reutiliza .seg-item/.seg-icon/.seg-icon-glyph de
   bloque_seguridad.html (icono inline vía svg_inline(), ver canal.html) en vez
   de crear un componente nuevo — es el único bullet-con-ícono del sitio que ya
   inyecta un SVG distinto por ítem. .demo-wa-bullets/.demo-tg-bullets
   reemplazan a .seguridad como contenedor: lista apilada en vez de grid de 3
   tarjetas. El override de .seg-item le saca el chrome de tarjeta (fondo/
   borde/padding) de su uso original y lo pone en fila (icono a la izquierda,
   texto a la derecha) en vez de columna — scopeado a estas dos clases para no
   tocar el .seg-item que sigue usando Plataforma/bloque_seguridad tal cual.
   Paso 5 (5 bullets en vez de 4): gap bajado de 20px a 16px para compensar el
   ítem extra sin engordar demasiado el alto total de la columna respecto del
   teléfono (align-items:start ya evita cualquier recorte real — es solo
   ajuste de proporción visual entre las dos columnas).
   margin-bottom (Paso 7, epígrafe movido a la columna derecha): antes el
   epígrafe cerraba la columna de texto con su propio alto + margin-top; al
   sacarlo, el último bullet pasó a ser el último elemento de la columna sin
   ningún cierre — en mobile (bajo 900px, .platform-split se apila a 1
   columna) quedaba pegado contra el teléfono que le sigue debajo. 32px
   restaura un cierre de magnitud similar al que daba el epígrafe.
   gap subido de 16px a 24px (SMS, Paso 3 de su tratamiento visual): a 16px los
   bullets quedaban muy pegados entre sí. Valor único, ya que las tres páginas
   comparten este selector — sube igual en WhatsApp (5 bullets) y Telegram (5
   bullets), no solo en SMS (4). Estimado a partir de las métricas de CSS
   (font-size/line-height de cada bloque, sin render real: el preview server
   no arranca en este sandbox), la columna de texto queda igual por debajo del
   alto fijo del teléfono (650px, ver más abajo) en las tres páginas — no hizo
   falta compensar nada. */
.demo-wa-bullets,.demo-tg-bullets,.demo-sms-bullets{list-style:none;display:flex;flex-direction:column;gap:24px;margin:28px 0 32px}
.demo-wa-bullets .seg-item,.demo-tg-bullets .seg-item,.demo-sms-bullets .seg-item{flex-direction:row;align-items:flex-start;background:none;border:none;padding:0;gap:14px}
/* Bugfix: .seg-icon/.seg-icon-glyph nunca tuvieron color por canal (a diferencia
   de .chan-icon, que sí usa --c/--c-soft) — heredaban el cyan hardcodeado de su
   uso original en bloque_seguridad.html. Override de color scopeado acá, sin
   tocar la regla base que sigue sirviendo a Plataforma/bloque_seguridad. */
.demo-wa-bullets .seg-icon{background:rgba(0,174,84,.13);border-color:rgba(0,174,84,.28)}
.demo-wa-bullets .seg-icon-glyph{color:var(--verde-whatsapp)}
.demo-tg-bullets .seg-icon{background:rgba(34,158,217,.13);border-color:rgba(34,158,217,.28)}
.demo-tg-bullets .seg-icon-glyph{color:var(--azul-telegram)}
.demo-sms-bullets .seg-icon{background:rgba(252,120,42,.13);border-color:rgba(252,120,42,.28)}
.demo-sms-bullets .seg-icon-glyph{color:var(--naranja)}

/* demo-wa/demo-tg — Paso 3, tratamiento visual compartido. Todo anidado bajo
   .demo-wa/.demo-tg, nada en la raíz: no toca .sec-paper/.phone/.msg/etc. de
   base, así que Home (.demo) y SMS (.demo-fixed desnudo, sin clase de canal)
   quedan exactamente igual. */
.demo-wa .phone-body,.demo-tg .phone-body,.demo-sms .phone-body{background:#fff}
/* Burbujas del agente sobre fondo claro: --paper/--line (mismos tokens que el
   resto del sitio para "papel" sobre blanco) y texto oscuro con --body, el
   mismo tono que usa el copy de cuerpo en el resto de la página (no --navy,
   que es de headings). border-color en vez de reescribir el shorthand: la
   base ya pone border:1px solid rgba(255,255,255,.07), acá solo cambia el color. */
.demo-wa .msg.agent,.demo-tg .msg.agent,.demo-sms .msg.agent{background:var(--paper);border-color:var(--line);color:var(--body)}
/* Cabecera del teléfono a --ink sólido (pedido explícito), en vez del
   fondo translúcido que hereda de la base (pensado para el panel oscuro). */
.demo-wa .phone-bar,.demo-tg .phone-bar,.demo-sms .phone-bar{background:var(--ink)}
/* Ancho del teléfono (Paso 3b): ya no tiene un tope propio en px, se ajusta a
   la columna que le da .demo-wa-split/.demo-tg-split — pisa el max-width:380px/
   margin:0 auto de la regla base .demo-fixed (pensada para quedar centrada y
   angosta fuera de un grid), acá el ancho y la posición los define la columna. */
.demo-wa .demo-fixed,.demo-tg .demo-fixed,.demo-sms .demo-fixed{max-width:none;margin:0}
/* Alto del teléfono (Paso 3d): revertido de 560px a 650px, dentro del rango
   600-700px original — 560px no dio el resultado esperado en verificación
   visual directa. align-items:start y el margen del epígrafe (arriba) no se
   tocan, quedaron validados. */
.demo-wa .phone,.demo-tg .phone,.demo-sms .phone{height:650px}

/* Único punto donde WhatsApp y Telegram difieren de verdad: el color. Patrón
   de fondo tileable (mismo SVG en estructura, solo cambia el stroke) y el
   color del mensaje "sistema", que necesita bajarse de luminosidad para leerse
   sobre blanco con contraste AA (4.5:1) — el acento puro de cada canal no
   alcanza ese mínimo. SMS se suma al mismo patrón (patron-demo-sms.svg,
   mismo trazo, stroke en naranja). */
.demo-wa{background:#fff url("../assets/canales/patron-demo-wa.svg") repeat;background-size:120px 120px}
.demo-tg{background:#fff url("../assets/canales/patron-demo-tg.svg") repeat;background-size:120px 120px}
.demo-sms{background:#fff url("../assets/canales/patron-demo-sms.svg") repeat;background-size:120px 120px}
/* .msg.sys en cyan puro (#00BAB4) sobre blanco da ~2.4:1 de contraste, por
   debajo del mínimo AA. #007A76 es el mismo cyan bajado de luminosidad
   (~5.2:1 sobre blanco) — sigue siendo "cyan", solo más oscuro para leerse acá.
   Mismo criterio para Telegram: #16688E es --azul-telegram (#229ED9) con la
   misma proporción de oscurecimiento aplicada a cada canal RGB (~65% del
   valor original), dando ~6.2:1 de contraste — no verificado visualmente,
   solo calculado. Mismo criterio para SMS: #A54F1C es --naranja (#FC782A) con
   la misma proporción de oscurecimiento (~65.6%), dando ~5.6:1 de contraste. */
.demo-wa .msg.sys{color:#007A76}
.demo-tg .msg.sys{color:#16688E}
.demo-sms .msg.sys{color:#A54F1C}
/* Bugfix: background/border-color de .msg.sys quedaron sin migrar en el Paso
   4/6 (solo se overrideó color, arriba) — la regla base sigue en cyan puro
   (rgba(0,186,180,...)). Acá van al azul de Telegram, mismos alphas que la
   base (.09 fondo / .38 borde), sin bajar la luminosidad: a esa opacidad el
   contraste no es un problema de texto, así que no aplica el mismo criterio
   de oscurecimiento usado para color. Scopeado a .demo-tg (no se toca
   .demo-wa, que queda igual que antes de este commit). SMS sigue el mismo
   criterio que Telegram desde el arranque (naranja puro a esos alphas). */
.demo-tg .msg.sys{background:rgba(34,158,217,.09);border-color:rgba(34,158,217,.38)}
.demo-sms .msg.sys{background:rgba(252,120,42,.09);border-color:rgba(252,120,42,.38)}

/* demo-industria — banda oscura del módulo de demo en páginas de Industria
   (real-estate/retail-farmaceutico/emprendedores). Misma estructura de grid
   que .demo-wa/.demo-tg/.demo-sms, pero el teléfono NO lleva los overrides a
   blanco de esos tres: acá el fondo de sección es oscuro, así que .phone/
   .msg.agent/.msg.sys quedan en su tratamiento BASE (el mismo que ya usa el
   widget del Home dentro de .demo, pensado desde el origen para fondo
   oscuro) — nada que tocar ahí.
   Fondo: grilla enmascarada + resplandor radial calcados de .hero (mismos
   valores que ya reusa .agentes-dark para banda oscura de sección, más abajo
   en este archivo). El patrón patron-demo-wa.svg va como capa aparte a
   opacidad .04 en .wrap::before (pseudo-elemento propio: el de
   .demo-industria ya está ocupado por la grilla y el resplandor), encima de
   esas dos capas y detrás del contenido real (z-index:2 en .wrap, mismo
   criterio que .agentes-dark .wrap). */
.demo-industria{background:var(--ink);position:relative;overflow:hidden;isolation:isolate}
.demo-industria::before{content:"";position:absolute;inset:0;
  background-image:linear-gradient(rgba(0,186,180,.05) 1px,transparent 1px),linear-gradient(90deg,rgba(0,186,180,.05) 1px,transparent 1px);
  background-size:60px 60px;
  -webkit-mask-image:radial-gradient(ellipse 78% 62% at 28% 42%,#000 18%,transparent 76%);
  mask-image:radial-gradient(ellipse 78% 62% at 28% 42%,#000 18%,transparent 76%)}
.demo-industria::after{content:"";position:absolute;width:800px;height:800px;right:-240px;top:-280px;border-radius:50%;
  background:radial-gradient(circle,rgba(0,186,180,.19),transparent 63%);pointer-events:none}
.demo-industria .wrap{position:relative;z-index:2}
.demo-industria .wrap::before{content:"";position:absolute;inset:0;pointer-events:none;
  background:url("../assets/canales/patron-demo-wa.svg") repeat;background-size:120px 120px;opacity:.04}
.demo-industria .sec-head h2{color:#fff}
.demo-industria .sec-head p{color:#98A1C0}

/* Contorno del teléfono — el borde base de .phone (rgba(255,255,255,.1)) no
   alcanza contraste contra el fondo de .demo-industria; se sube solo el
   border-color acá, mismo patrón scopeado que .demo .phone (línea 164). */
.demo-industria .phone{border-color:rgba(255,255,255,.32)}

/* Layout split — mismos valores de grid que .demo-wa-split (3fr/2fr,
   columnas alineadas arriba). min-width:0 de los hijos ya lo cubre la regla
   base .platform-split>*, y el colapso a 1 columna en mobile (900px) es el
   mismo de .platform-split — sin order que resetear ahí: el texto ya es el
   primero en el DOM, igual que en .demo-wa-split (ver comentario en
   canal.html). .demo-fixed pierde su tope de 380px para ocupar la columna
   completa, mismo criterio que .demo-wa .demo-fixed. */
.demo-industria-split.platform-split{grid-template-columns:3fr 2fr;align-items:start}
.demo-industria .demo-fixed{max-width:none;margin:0}

/* Bullets — misma estructura que .demo-wa-bullets (lista de .seg-item sin
   chrome de tarjeta), con el patrón de translucidez del sistema para fondo
   oscuro (rgba(255,255,255,.045)/.10, el mismo que .agentes-dark .acard) en
   vez del verde claro que usa .demo-wa-bullets .seg-icon. */
.demo-industria-bullets{list-style:none;display:flex;flex-direction:column;gap:24px;margin:28px 0 32px}
.demo-industria-bullets .seg-item{flex-direction:row;align-items:flex-start;background:none;border:none;padding:0;gap:14px}
.demo-industria-bullets .seg-item h3{color:#fff}
.demo-industria-bullets .seg-item p{color:#C4CDE2}
.demo-industria-bullets .seg-icon{background:rgba(255,255,255,.045);border-color:rgba(255,255,255,.32)}
.demo-industria-bullets .seg-icon-glyph{color:var(--verde-whatsapp)}

/* Burbujas del cliente en verde WhatsApp — explícito acá (no depende de que
   build.py fuerce el canal a whatsapp en render_industria, commit aparte). */
.demo-industria .msg.user{background:var(--verde-whatsapp)}

/* headline corto entre bloques — panel oscuro intermedio, respiro de color a mitad de página */
.headline{background:var(--navy);padding:74px 0;text-align:center;position:relative}
.headline::before{content:"";position:absolute;width:600px;height:400px;left:50%;top:50%;transform:translate(-50%,-50%);
  background:radial-gradient(ellipse,rgba(0,186,180,.18),transparent 70%);pointer-events:none}
.headline .wrap{position:relative;z-index:2}
.headline h2{color:#fff;font-size:clamp(24px,3vw,34px);max-width:820px;margin:0 auto;font-weight:800;letter-spacing:-0.025em}

/* checklist de items con ícono, sobre fondo claro (surtido inteligente) — ícono con más presencia */
.check-list{list-style:none;display:flex;flex-direction:column;gap:20px;margin:24px 0}
.check-list li{display:flex;gap:16px;align-items:flex-start}
.check-tick{flex:0 0 30px;height:30px;margin-top:1px;border-radius:10px;background:rgba(0,186,180,.14);border:1px solid rgba(0,186,180,.22);position:relative}
.check-tick::after{content:"";position:absolute;left:10px;top:8px;width:7px;height:12px;border-right:2.5px solid var(--cyan);border-bottom:2.5px solid var(--cyan);transform:rotate(42deg)}
.check-list h4{font-size:15.5px;color:var(--navy);margin-bottom:4px;font-family:var(--display);font-weight:700}
.check-list p{font-size:14px;color:var(--muted);margin:0}

/* variante de grid de 3 columnas (flujo de Plataforma) */
.steps-3{grid-template-columns:repeat(3,1fr)}
/* números del flujo Detecta/Propone/Cierra — círculo cyan sólido, número en blanco */
.steps-3 .step-n{background:var(--cyan);color:#fff;border-radius:50%}

/* ícono de acento para cards (CRM / Características / Beneficios en Plataforma) —
   reemplaza la rayita fina por un ícono con fondo cyan tenue, más presencia */
.card-icon{width:42px;height:42px;border-radius:13px;background:rgba(0,186,180,.13);border:1px solid rgba(0,186,180,.22);
  display:flex;align-items:center;justify-content:center;margin-bottom:20px}
.card-icon::after{content:"";width:16px;height:16px;border-radius:5px;background:var(--cyan)}
/* .card-icon-real — "Por qué NovaSales" en Plataforma: el cuadrado ::after
   (placeholder verde) se apaga y en su lugar entra un ícono real de Tabler,
   inyectado inline vía svg_inline() (mismo helper que hibrido-base-animado.svg
   en el Home) en vez de <img>/mask-image: los Tabler ya traen
   stroke="currentColor", así que con el SVG inline en el DOM el color sale
   solo de heredar color de .card-icon-glyph — sin enmascarar nada.
   El contenedor (.card-icon, fondo cyan tenue + radio) no se toca, solo lo
   de adentro. */
.card-icon-real::after{content:none}
.card-icon-glyph{width:26px;height:26px;display:block;color:var(--cyan)}
.card-icon-glyph svg{width:100%;height:100%;display:block}

/* Prompt 27 (Parte 2) — "Cómo aprende" en Plataforma: tres puntos sin caja,
   sin borde, solo título en navy + texto en muted separados por aire. A
   propósito distinto de .card (con borde) y de .thesis-item (con línea
   vertical cyan) — el prompt pide variar el ritmo entre los tres bloques
   nuevos de la página. */
.plain-points{align-items:start}
.plain-point h3{font-size:16.5px;font-weight:800;color:var(--navy);letter-spacing:-0.01em}
.plain-point p{margin-top:8px;color:var(--muted);font-size:14.6px;line-height:1.55}
.plain-close{margin-top:36px;font-size:15.5px;color:var(--body);max-width:760px}
/* .attach-* — reemplaza a la línea huérfana de .plain-close en "Cómo aprende"
   (Plataforma): intro con peso propio + fila de adjuntos con ícono. La intro
   reusa el patrón ya establecido para "línea más grande que el cuerpo, más
   chica que un H2" (.problema-lead/.cobertura-lead: 19px/700/--display/
   --navy), no un tamaño nuevo. Los ítems van pelados (sin .card ni borde)
   para no competir con las tarjetas de "Por qué NovaSales", la sección
   siguiente. Íconos inline vía svg_inline(), mismo criterio que
   .card-icon-glyph. */
.attach-block{margin-top:36px}
.attach-lead{font-family:var(--display);font-weight:700;font-size:19px;color:var(--navy)}
/* grid de 4 columnas iguales (1fr): cada ítem arranca en un punto regular
   del ancho, acompañando la grilla de 3 columnas de arriba, en vez de
   agruparse a la izquierda (flex) o flotar suelto (columnas "auto"). */
.attach-list{list-style:none;display:grid;grid-template-columns:repeat(4,1fr);column-gap:40px;row-gap:16px;margin-top:20px}
.attach-item{display:flex;align-items:center;gap:10px}
.attach-icon{width:26px;height:26px;flex:none;display:block;color:var(--cyan)}
.attach-icon svg{width:100%;height:100%;display:block}
.attach-label{font-size:14.6px;color:var(--body)}
@media(max-width:900px){
  .attach-list{display:grid;grid-template-columns:1fr 1fr;column-gap:20px;row-gap:16px}
}

/* Prompt 27 (Parte 3) — "Configuración": reusa .thesis-list/.thesis-item tal
   cual (línea vertical cyan a la izquierda, ya usada en "El problema real"
   del Home) en vez de crear un componente nuevo. .config-list solo ajusta el
   gap: 5 ítems cortos necesitan menos aire vertical que los 3 del Home.
   ADDENDUM (.tone-panel): con align-items:start, .config-list arranca en el
   mismo borde superior que .tone-panel — pero .tone-panel tiene encima la
   etiqueta "Estilo de comunicación" (línea de 12px + margin-bottom:12px)
   antes de la primera tarjeta. margin-top empareja ese alto para que el
   primer bullet ("Idioma") quede a la misma altura que la primera tarjeta,
   no que la etiqueta. */
.config-list{gap:22px;margin-top:32px}

/* Addendum prompt 30 — Configuración pasa a banda oscura (.agentes-dark,
   reusada del Home). .thesis-item trae colores pensados para fondo claro
   (--navy/--muted): mismos overrides de texto que ya usa .agentes-dark para
   .acard/.sec-head, mismo gris #98A1C0. */
.agentes-dark .thesis-item h3{color:#fff}
.agentes-dark .thesis-item p{color:#98A1C0}
/* .tone-panel — reemplaza a la captura "estilo de agente" en Configuración:
   componente nativo armado desde p.configuracion.tono_panel (texto
   seleccionable/accesible/traducible, la imagen quedaba fija en español).
   Vive en la misma columna de .platform-split-rev donde antes iba
   .ui-shot-parallax, así que no toca el grid. Fondo propio (no hereda de
   .agentes-dark) porque necesita distinguirse de la banda como una "pantalla"
   aparte, con su propia grilla sutil (::before, líneas cada 44px) — mismo
   patrón de grid de fondo que .hero/.agentes-dark, pero blanco muy tenue en
   vez de cyan, porque acá no compite con contenido cyan propio (el check de
   la tarjeta seleccionada). */
/* padding-top en 0 (antes 28px): con align-items:start ya alineado, la
   etiqueta "Estilo de comunicación" quedaba empujada 28px por debajo del
   borde superior del panel, y detrás de ella la primera tarjeta bajaba más
   todavía — un renglón entero (etiqueta) de diferencia contra "Idioma", el
   primer bullet de la columna derecha, que arranca pegado al borde superior
   de su columna (sin padding propio). Sin padding-top, la etiqueta sube al
   borde del panel y la primera tarjeta ocupa el lugar donde antes estaba
   el aire vacío. */
.tone-panel{position:relative;background:#0B1533;border-radius:20px;padding:0 26px 28px;overflow:hidden}
.tone-panel::before{content:"";position:absolute;inset:0;pointer-events:none;z-index:0;
  background-image:linear-gradient(rgba(255,255,255,.028) 1px,transparent 1px),linear-gradient(90deg,rgba(255,255,255,.028) 1px,transparent 1px);
  background-size:44px 44px}
.tone-panel>*{position:relative;z-index:1}
/* sin encabezado propio (título/bajada): en la app es el paso 2 de un flujo
   que en el sitio no existe como tal. La etiqueta queda como única línea
   antes de las tarjetas, sin margin-top porque ahora es el primer elemento
   del panel (el aire de arriba ya lo da el padding de .tone-panel). */
.tone-panel-label{display:block;margin:0 0 12px;font-size:12px;color:#98A1C0}
.tone-panel-asterisk{color:var(--coral);margin-right:4px}
/* una sola columna, tarjetas apiladas a ancho completo — sin scroll ni
   overflow propio, la altura del panel la da el contenido. */
.tone-grid{display:flex;flex-direction:column;gap:12px}
.tone-card{position:relative;display:flex;align-items:flex-start;gap:12px;padding:14px 16px;
  border-radius:12px;background:rgba(255,255,255,.045);border:1px solid rgba(255,255,255,.10)}
/* .rv reusa el observer compartido (js/main.js) para el toggle de .in; acá
   se pisa opacity/transform/transition de la base .rv (14px en vez de 22px,
   easing distinto) por especificidad de dos clases — mismo criterio que
   .ui-shot.rv-shot. El hover de fondo/borde entra en la MISMA lista de
   transition (no en una regla aparte) porque una segunda declaración del
   shorthand "transition" pisaría por completo a esta, no se mezclan. */
.tone-card.rv{opacity:0;transform:translateY(14px);
  transition:opacity .7s cubic-bezier(.16,1,.3,1),transform .7s cubic-bezier(.16,1,.3,1),background .3s,border-color .3s}
.tone-card.rv.in{opacity:1;transform:none}
/* delay escalonado de 60ms por tarjeta, mismo patrón que .thesis-item
   (línea ~284): transition-delay por nth-child, sin tocar el observer.
   prefers-reduced-motion ya fuerza transition:none!important más abajo,
   así que el delay queda sin efecto ahí. */
.tone-card:nth-child(2){transition-delay:.06s}
.tone-card:nth-child(3){transition-delay:.12s}
.tone-card:nth-child(4){transition-delay:.18s}
.tone-card:nth-child(5){transition-delay:.24s}
.tone-icon{flex:none;width:20px;height:20px;margin-top:2px;display:block;color:var(--cyan)}
.tone-icon svg{width:100%;height:100%;display:block}
.tone-copy h4{font-size:14px;font-weight:700;color:#fff}
.tone-copy p{margin-top:3px;font-size:13px;color:#98A1C0;line-height:1.5}
.tone-card.tone-card-sel{background:rgba(0,186,180,.10);border-color:rgba(0,186,180,.45)}
.tone-card-sel .tone-copy p{color:#C3CBE0}
.tone-check{position:absolute;top:14px;right:16px;width:17px;height:17px;display:block;color:var(--cyan)}
.tone-check svg{width:100%;height:100%;display:block}
@media(hover:hover){
  .tone-card:not(.tone-card-sel):hover{background:rgba(255,255,255,.075);border-color:rgba(255,255,255,.18)}
}
@media(max-width:900px){
  .tone-panel{padding:22px 20px}
}
/* .agentes-dark-wide — modificador exclusivo de Plataforma (Configuración),
   NO toca .agentes-dark base (compartida con Home). La sección de Plataforma
   es más baja y más ancha que la del Home (padding 92px vs sec-tight 64px,
   platform-split-rev con imagen marcando el alto de fila en vez de un
   grid-4 de tarjetas), así que el mismo resplandor fijo de 800px cubre
   menos proporción. Se escala el ::after a ~1100px y se sube a top:-180px
   para que la cobertura relativa quede pareja a la del Home. La grilla
   (::before) y su opacidad no se tocan.
   ADDENDUM — la elipse del mask-image (::before) también recortaba de más:
   78% 62% está pensada para una sección alta (Home); en una más baja el
   mismo 62% de alto es muchos menos píxeles reales, así que la grilla se
   lee más apagada/chica. Se agranda a 92% 108% en el mismo centro (28% 42%)
   — el eje vertical crece más porque es el que pierde superficie real al
   bajar la altura de la sección; el horizontal casi no cambia porque el
   ancho del ::before (full-bleed de la sección) es similar en ambas
   páginas. Placeholder para ajuste fino: no se pudo confirmar por preview
   (sandbox sin acceso a esta carpeta); si sigue leyéndose recortada, el
   siguiente paso es agrandar más el % vertical antes de tocar el mask del
   ::before de otra forma. */
.agentes-dark-wide::after{width:1100px;height:1100px;top:-180px}
.agentes-dark-wide::before{
  -webkit-mask-image:radial-gradient(ellipse 92% 108% at 28% 42%,#000 18%,transparent 76%);
  mask-image:radial-gradient(ellipse 92% 108% at 28% 42%,#000 18%,transparent 76%)}
/* .ui-shot-dark — variante de .ui-shot para banda oscura: la sombra suave
   pensada para fondo claro se pierde sobre --ink, así que pasa a borde claro
   translúcido + sombra más profunda y difusa. El marco sigue blanco (#fff,
   heredado de .ui-shot): la captura es una UI clara y tiene que leerse como
   tal, aunque esté rodeada de oscuro. Sombra más profunda (dos capas) +
   inset superior que simula luz pegando arriba del marco. */
.ui-shot.ui-shot-dark{border:1px solid rgba(255,255,255,.14);
  box-shadow:0 40px 80px -24px rgba(0,0,0,.65),0 8px 24px -12px rgba(0,0,0,.4),inset 0 1px 0 rgba(255,255,255,.55)}
@media(hover:hover){
  .ui-shot.ui-shot-dark.rv-shot.in:hover{box-shadow:0 30px 60px -20px rgba(0,0,0,.6)}
}
/* halo detrás de la captura en la banda oscura — solo .agentes-dark, no toca
   .ui-shot-parallax del bloque abm (fondo claro). ::before ancla a este
   contenedor (position:relative), no a .ui-shot, para no interferir con el
   parallax/hover que ya mueven .ui-shot-parallax y .ui-shot por separado.
   z-index:-1 lo manda detrás del <figure> DENTRO del stacking context local
   de .ui-shot-parallax — no compite con .agentes-dark::before/::after: esos
   quedan por debajo de todo este subárbol porque .agentes-dark .wrap ya
   tiene su propio z-index:2 (stacking context aparte, por isolation:isolate
   en .agentes-dark). */
.agentes-dark .ui-shot-parallax{position:relative}
.agentes-dark .ui-shot-parallax::before{content:"";position:absolute;inset:-60px;z-index:-1;
  background:radial-gradient(ellipse at 50% 45%,rgba(0,186,180,.20),transparent 68%);
  filter:blur(48px);pointer-events:none}

/* Prompt 27 (Parte 7) — franja "Construido sobre": logos en gris (--muted),
   pasan a su color de marca en hover. Sin borde, sin caja, sin fondo. */
/* Logos oficiales, multicolor, sin filtro — franja en --paper (no funcionan
   sobre panel oscuro). Ver content.plataforma.construido_sobre. */
.built-on{padding-top:0;background:var(--paper)}
.built-on-eyebrow{display:block;text-align:center;margin-bottom:34px}
.built-on-row{display:flex;align-items:center;justify-content:center;flex-wrap:wrap;gap:48px}
.built-on-logo{display:block;width:auto}

/* comparación — modelo humano vs modelo híbrido AI, 2 columnas + filas */
.compare{display:grid;grid-template-columns:1fr 1fr;border:1px solid var(--line);border-radius:18px;overflow:hidden;background:#fff}
.compare-head{padding:19px 26px;font-family:var(--display);font-weight:800;font-size:15.5px;letter-spacing:-0.01em}
.compare-old{background:#EEF0F6;color:var(--muted)}
.compare-new{background:var(--cyan);color:#07142E}
.compare-cell{padding:17px 26px;font-size:14.6px;border-top:1px solid var(--line)}
.compare-old-cell{color:var(--muted)}
.compare-new-cell{color:var(--navy);font-weight:600;background:rgba(0,186,180,.05)}

/* seguridad — ícono en círculo cyan por ítem, más peso visual (confianza institucional) */
.seguridad{display:grid;grid-template-columns:repeat(3,1fr);gap:24px}
.seg-item{display:flex;flex-direction:column;align-items:flex-start;gap:16px;background:#fff;border:1px solid var(--line);border-radius:16px;padding:26px 24px}
.seg-icon{flex:0 0 46px;width:46px;height:46px;border-radius:50%;background:rgba(0,186,180,.13);border:1px solid rgba(0,186,180,.28);
  display:flex;align-items:center;justify-content:center}
.seg-icon-glyph{width:26px;height:26px;display:block;color:var(--cyan)}
.seg-icon-glyph svg{width:100%;height:100%;display:block}
.seg-item h3{font-size:15.5px;margin-bottom:5px}
.seg-item p{font-size:13.8px;color:var(--muted)}

/* final CTA */
.final{background:var(--ink);padding:88px 0 96px;text-align:center;position:relative;overflow:hidden}
.final::before{content:"";position:absolute;width:920px;height:540px;left:50%;top:50%;transform:translate(-50%,-50%);
  background:radial-gradient(ellipse,rgba(0,186,180,.15),transparent 68%)}
.final-in{position:relative;z-index:2}
.final h2{color:#fff;font-size:clamp(28px,3.5vw,43px);max-width:720px;margin:0 auto 20px;font-weight:800;letter-spacing:-0.028em}
.final p{color:#98A1C0;font-size:17.5px;max-width:540px;margin:0 auto 34px}
.final .cta-row{justify-content:center}

/* footer */
.foot{background:var(--ink);padding:52px 0 30px;color:#8891AE}
.foot-in{display:flex;justify-content:space-between;gap:40px;flex-wrap:wrap;padding-bottom:28px;border-bottom:1px solid rgba(255,255,255,.07)}
.foot-brand{font-family:var(--display);font-weight:800;color:#fff;font-size:18px;margin-bottom:10px}
.foot-brand svg{height:18px;width:auto;display:block}
.foot-tagline{font-size:13.5px;max-width:260px}
.foot-links{display:flex;gap:34px;flex-wrap:wrap}
.foot-col h4{font-family:var(--text);font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:#5E688A;font-weight:600;margin-bottom:14px}
.foot-col a{display:block;font-size:13.8px;color:#AAB2CC;margin-bottom:10px;transition:.18s}
.foot-col a:hover{color:#fff}
.foot-social{display:flex;gap:12px}
.foot-social a{width:36px;height:36px;border-radius:10px;border:1px solid rgba(255,255,255,.14);display:flex;align-items:center;justify-content:center;font-size:12px;color:#AAB2CC;transition:.2s}
.foot-social a:hover{border-color:var(--cyan);color:#fff}
.foot-bottom{padding-top:22px;text-align:center;font-size:12px;color:#5E688A}

/* scroll reveal */
.rv{opacity:0;transform:translateY(22px);transition:opacity .7s cubic-bezier(.2,.7,.3,1),transform .7s cubic-bezier(.2,.7,.3,1)}
.rv.in{opacity:1;transform:none}

/* .platform-split — Prompt 30: contenedor de grid para los bloques "abm" y
   "configuracion" de Plataforma. 40/60 por defecto (texto/imagen, abm).
   .platform-split-rev invierte a 60/40 (imagen/lista, configuracion — el
   sec-head de configuracion quedó afuera del grid, a todo ancho, así que acá
   no hace falta reordenar nada: el DOM ya va imagen→lista en los dos casos).
   min-width:0 en los hijos: por defecto un ítem de grid tiene min-width:auto,
   así que el ancho intrínseco de la imagen (1140/1080px) fuerza el track a
   desbordar la columna en vez de encogerse. */
.platform-split{display:grid;grid-template-columns:2fr 3fr;gap:64px;align-items:center}
.platform-split>*{min-width:0}
/* .tone-panel (caja con padding propio) vs .config-list (lista sin caja):
   con align-items:center heredado, la columna más corta queda centrada en
   la fila y arranca más abajo que la más alta — acá se pisa a start para
   que las dos columnas empiecen a la misma altura. Solo en -rev: el bloque
   abm (imagen + sec-head) sigue centrado, no tiene este problema. */
.platform-split-rev{grid-template-columns:56fr 44fr;align-items:start}
.platform-split .sec-head{margin-bottom:0}
@media(max-width:900px){
  .platform-split,.platform-split-rev,
  .agente-detalle.platform-split,.agente-detalle.platform-split-rev,
  .demo-wa-split.platform-split,.demo-tg-split.platform-split,.demo-sms-split.platform-split,
  .demo-industria-split.platform-split{grid-template-columns:1fr;gap:32px}
}

/* .ui-shot — captura de producto (Prompt 29: bloques "abm" y "configuracion"
   de Plataforma). El parallax (js/main.js) mueve .ui-shot-parallax (el
   wrapper); la entrada (.rv-shot) y el hover mueven .ui-shot (la figura de
   adentro) — separados en dos elementos para que sus transform no se pisen.
   Prompt 30: sin max-width propio, el ancho lo define la columna de
   .platform-split. */
.ui-shot-parallax{width:100%;margin:0}
.ui-shot{display:block;width:100%;background:#fff;border:1px solid var(--line);border-radius:20px;overflow:hidden;
  box-shadow:0 1px 2px rgba(16,31,82,.04),0 18px 40px -12px rgba(16,31,82,.16)}
.ui-shot img{width:100%;height:auto;display:block}
.ui-shot.rv-shot{opacity:0;transform:translateY(24px) scale(.985);
  transition:opacity .9s cubic-bezier(.16,1,.3,1),transform .9s cubic-bezier(.16,1,.3,1)}
.ui-shot.rv-shot.in{opacity:1;transform:none}
@media(hover:hover){
  .ui-shot.rv-shot.in:hover{transform:translateY(-4px);
    box-shadow:0 4px 10px rgba(16,31,82,.06),0 24px 48px -12px rgba(16,31,82,.22);
    transition:transform .4s cubic-bezier(.2,.7,.3,1),box-shadow .4s cubic-bezier(.2,.7,.3,1)}
}
@media(max-width:767px){
  /* Prompt 29: por debajo de 768px se desactiva el parallax (ver js/main.js);
     este reset cubre el caso de resize sin nuevo scroll, para que no quede
     un translateY colgado de la última lectura en desktop. */
  .ui-shot-parallax{transform:none!important}
}

@media(max-width:900px){
  :root{--r:var(--r-mobile)}
  .hero-in,.split,.thesis-grid{grid-template-columns:1fr;gap:44px}
  .grid-2,.grid-3,.grid-4,.grid-ind,.steps,.steps-3,.seguridad{grid-template-columns:1fr}
  /* una sola columna: .ia-proceso-col (paso 1 + paso 2, ya apilados por su
     propio flex-direction:column) y el paso 3 quedan uno debajo del otro en
     su orden natural del DOM (1, 2, 3), sin necesidad de la propiedad
     order. */
  .ia-proceso-shots{grid-template-columns:1fr}
  .nav-links{display:none}
  .nav-burger{display:flex}
  .sec{padding:68px 0}
  /* hero interior en mobile (Prompt 9, Parte 6): sin altura mínima (el
     contenido define el alto) y ritmo/padding reducidos — el aire grande de
     desktop come demasiada pantalla en 390px. */
  .hero-interior{min-height:0;padding:56px 0 60px}
  .hero-interior .cta-row{margin-top:28px}
  .split-ph{height:220px}
  .foot-in{flex-direction:column}
  .compare-head,.compare-cell{padding:14px 16px;font-size:13.5px}
  .ptable{grid-template-columns:1.3fr 1fr 1fr 1fr}
  .ptable-head,.ptable-cell{padding:10px 8px;font-size:11.5px}
  .legal-layout{grid-template-columns:1fr}
  .legal-index{position:static;flex-direction:row;flex-wrap:wrap;gap:8px 16px;margin-bottom:36px}
  .legal-index a{padding:4px 0;border-left:none}
  /* Cinco logos: un grid fijo de 2 columnas fuerza 3 filas desparejas (2/2/1).
     Se mantiene el flex-wrap del desktop y solo se reduce el gap, para que
     el acomodo a dos filas dependa del ancho disponible de cada logo. */
  .built-on-row{gap:28px}
}
@media(prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}.rv{opacity:1;transform:none}
  .ui-shot.rv-shot{opacity:1;transform:none}
  .ui-shot-parallax{transform:none}
  .ui-shot.rv-shot.in:hover{transform:none}
  .tone-card.rv{opacity:1;transform:none}
}

/* .estructura-falta — SOLO desarrollo local, con DEBUG_ESTRUCTURA=True en
   build.py (ver constante cerca del tope del archivo). Marca visualmente,
   en las páginas de Industria, qué sección no tiene contenido en el JSON.
   No se publica: con DEBUG_ESTRUCTURA=False el build no genera este markup. */
.estructura-falta{border:2px dashed #E2352F;background:#FFF6E9;color:#8A2A25;
  text-transform:uppercase;letter-spacing:.08em;font-weight:700;font-size:13px;
  padding:32px 24px;margin:24px auto;max-width:var(--wrap);text-align:center;border-radius:12px}
