/* ==========================================================================
   The Growth Loop Agency — styles.css
   Design tokens & component library per DESIGN.md
   ========================================================================== */

:root {
  /* Backgrounds */
  --bg: #0A0C0F;
  --surface: #14171C;
  --surface-alt: #191D23;
  --surface-hover: #20252C;

  /* Borders */
  --border: rgba(255,255,255,0.08);
  --border-hover: rgba(255,255,255,0.18);

  /* Text */
  --text: #F4F5F7;
  --text-secondary: #A6ACB6;
  --text-tertiary: #6B7280;

  /* Accent — morado de marca (heredado del sitio anterior) + cian como secundario */
  --accent: #8B5CF6;
  --accent-hover: #A177FF;
  --accent-2: #00CCFF;

  --bg-rgb: 10,12,15;
  --accent-rgb: 139,92,246;
  --accent-2-rgb: 0,204,255;

  --success: #4CE0C9;
  --error: #FF5C5C;
  --warning: #FFC93D;

  --container: 1280px;
  --container-narrow: 760px;
  --pad-inline: clamp(1.25rem, 5vw, 4rem);
  --section-pad: clamp(5rem, 10vw, 8rem);
  --radius: 20px;
}

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; overflow-x: clip; max-width: 100%; }
[id] { scroll-margin-top: 96px; }
body {
  background: var(--bg);
  color: var(--text);
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-size: 1.0625rem;
  line-height: 1.65;
  overflow-x: clip;
  max-width: 100%;
  -webkit-font-smoothing: antialiased;
}
img, svg { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
ul { list-style: none; }
button { font: inherit; background: none; border: none; cursor: pointer; color: inherit; }
h1, h2, h3, h4 { font-family: 'Heebo', sans-serif; color: var(--text); }

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

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

/* ---------- Layout ---------- */
.container {
  max-width: var(--container);
  margin: 0 auto;
  padding-inline: var(--pad-inline);
}
.container-narrow {
  max-width: var(--container-narrow);
  margin: 0 auto;
  padding-inline: var(--pad-inline);
}
.section { padding-block: var(--section-pad); position: relative; }
.section-alt { background: var(--surface-alt); }

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-family: 'Heebo', sans-serif;
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  border-bottom: 2px solid var(--accent);
  padding-bottom: 0.4rem;
  margin-bottom: 1.5rem;
}
.eyebrow.accent-2 { border-bottom-color: var(--accent-2); }
/* Variante sin la raya morada decorativa — para los eyebrows que SÍ se conservan como
   label tipográfico independiente (hero, "Han confiado en nosotros", "Partners
   tecnológicos") pero que ya no deben leerse como el primer nivel de un patrón
   microtítulo+raya+título repetido en cada sección. No se toca .eyebrow en sí (se usa
   en otras páginas del sitio) — solo se resta el recurso decorativo en esta variante. */
.eyebrow--plain { border-bottom: 0; padding-bottom: 0; }

h1 { font-size: clamp(2.75rem, 7vw, 6rem); font-weight: 800; line-height: 1.02; letter-spacing: -0.02em; }
h2 { font-size: clamp(2rem, 4vw, 3.25rem); font-weight: 700; line-height: 1.08; letter-spacing: -0.01em; }
h3 { font-size: clamp(1.25rem, 2vw, 1.75rem); font-weight: 700; line-height: 1.2; }

.lede { font-size: clamp(1.0625rem, 1.5vw, 1.25rem); color: var(--text-secondary); max-width: 640px; }
p { color: var(--text-secondary); }
.text-accent { color: var(--accent); }
.text-accent-2 { color: var(--accent-2); }

.glow-word {
  color: var(--accent);
  text-shadow: 0 0 40px rgba(var(--accent-rgb), 0.25);
}

/* ---------- Reveal / Motion ---------- */
.reveal {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity 0.7s cubic-bezier(0.16,1,0.3,1), transform 0.7s cubic-bezier(0.16,1,0.3,1);
}
.reveal.in-view { opacity: 1; transform: translateY(0); }

.stagger-reveal > * {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity 0.7s cubic-bezier(0.16,1,0.3,1), transform 0.7s cubic-bezier(0.16,1,0.3,1);
}
.stagger-reveal.in-view > * { opacity: 1; transform: translateY(0); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .reveal, .stagger-reveal > * { opacity: 1 !important; transform: none !important; }
  .hero-loop-path { stroke-dashoffset: 0 !important; }
  .marquee-track { animation: none !important; }
  .viz-strategy-dot, .viz-strategy-line, .viz-data-bar, .viz-exec-gear, .viz-exec-spark { animation: none !important; }
  .viz-data-bar { transform: scaleY(1) !important; }
  .whatsapp-float, .whatsapp-float::after { animation: none !important; }
  .hero-rotator-text::after { animation: none !important; opacity: 1; }
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.9rem 1.75rem;
  border-radius: 999px;
  font-family: 'Heebo', sans-serif;
  font-weight: 600;
  font-size: 0.9375rem;
  border: 1px solid transparent;
  cursor: pointer;
  transition: transform 0.2s ease, box-shadow 0.2s ease, background 0.2s ease, color 0.2s ease, border-color 0.2s ease;
  min-height: 44px;
  white-space: nowrap;
}
.btn-primary { background: var(--accent); color: #FFFFFF; }
.btn-primary:hover { background: var(--accent-hover); transform: translateY(-2px); box-shadow: 0 8px 24px rgba(var(--accent-rgb), 0.3); }
.btn-primary:active { transform: translateY(0) scale(0.97); box-shadow: none; }
.btn-primary:disabled { opacity: 0.4; cursor: not-allowed; transform: none; box-shadow: none; }

.btn-ghost { background: transparent; color: var(--text); border-color: var(--border); }
.btn-ghost:hover { border-color: var(--accent); color: var(--accent); background: rgba(var(--accent-rgb), 0.06); }

.btn-row { display: flex; flex-wrap: wrap; gap: 1rem; align-items: center; }

/* ---------- Links ---------- */
.link { position: relative; color: var(--text); }
.link::after {
  content: ''; position: absolute; bottom: -2px; left: 0; width: 0; height: 1px;
  background: var(--accent); transition: width 0.3s cubic-bezier(0.16,1,0.3,1);
}
.link:hover::after { width: 100%; }

/* ---------- Nav ---------- */
.nav {
  position: fixed; top: 0; left: 0; width: 100%; z-index: 100;
  padding: 1.25rem 0;
  background: transparent;
  border-bottom: 1px solid transparent;
  transition: background 0.3s ease, border-color 0.3s ease, padding 0.3s ease;
}
/* Sticky header COMPLETO al hacer scroll (patrón wardem.com): una única barra con fondo
   cubre todo el nav de una vez — logo, píldora y CTA quedan dentro del MISMO fondo, no
   como piezas sueltas con su propio recuadro cada una. Por eso .nav-pill neutraliza su
   propio fondo/borde en este estado: ya no hace falta, el fondo lo pone .nav.scrolled. */
.nav.scrolled {
  background: rgba(var(--bg-rgb), 0.9);
  backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
  border-bottom-color: var(--border);
  padding: 0.85rem 0;
}
.nav.scrolled .nav-pill {
  background: transparent; border-color: transparent;
  backdrop-filter: none; -webkit-backdrop-filter: none;
}
.nav-inner { display: flex; align-items: center; justify-content: space-between; gap: 2rem; }
.brand { display: flex; align-items: center; gap: 0.6rem; font-family: 'Heebo', sans-serif; font-weight: 700; font-size: 1.0625rem; color: var(--text); }
.brand-mark { width: 30px; height: 30px; flex-shrink: 0; }
.brand-mark .loop-o { transition: transform 0.6s cubic-bezier(0.34,1.56,0.64,1); transform-origin: center; }
.brand:hover .loop-o { transform: rotate(180deg); }

.nav-links { display: flex; align-items: center; gap: 1.5rem; }
.nav-links a { color: var(--text-secondary); font-weight: 500; font-size: 0.9375rem; transition: color 0.2s ease; }
.nav-links a:hover, .nav-links a[aria-current="page"] { color: var(--text); }
.nav-links a.btn-primary, .nav-links a.btn-primary:hover { color: #FFFFFF; }

/* ---------- Nav pill + desplegable de Servicios ----------
   Base = mobile: sin cápsula (fluye directo en el drawer de .nav-links) y el desplegable
   es un acordeón (max-height). El look de "píldora" flotante + panel flotante es un
   añadido SOLO de escritorio, en el media query de abajo (brief: clonar el patrón de
   nav de wardem.com). Nunca preventDefault en los <a> del panel — misma filosofía que
   el resto del nav: navegación 100% nativa. */
.nav-pill { display: contents; }
/* .nav-mobile-menu (información arquitectura propia de mobile: Servicios/Casos de éxito/
   Growth Strategy/Nosotros/Contacto + CTA de auditoría + email) solo existe visualmente
   en el breakpoint de teléfono (<=767px, ver más abajo) — oculto por defecto para que
   nunca aparezca apilado dentro del header en desktop/tablet. */
.nav-mobile-menu { display: none; }
/* Cabecera de #lead-form exclusiva de mobile (ver @media max-width:767px) — oculta por
   defecto para que desktop/tablet sigan mostrando el h3 de siempre sin duplicar mensaje. */
.lead-form-mobile-heading,
.lead-form-mobile-copy,
.lead-form-mobile-microcopy { display: none; }
.nav-dropdown { width: 100%; }
.nav-dropdown__trigger {
  display: flex; align-items: center; justify-content: space-between; gap: 0.4rem;
  width: 100%; background: none; border: none; padding: 0; margin: 0; cursor: pointer;
  color: var(--text-secondary); font-weight: 500; font-size: 0.9375rem; font-family: inherit; text-align: left;
  transition: color 0.2s ease;
}
.nav-dropdown__trigger:hover, .nav-dropdown__trigger.is-active { color: var(--text); }
.nav-dropdown__chevron { flex-shrink: 0; transition: transform 0.25s ease; }
.nav-dropdown.is-open .nav-dropdown__chevron { transform: rotate(180deg); }
.nav-dropdown__panel {
  max-height: 0; overflow: hidden;
  display: flex; flex-direction: column; gap: 0.15rem;
  transition: max-height 0.3s ease;
}
.nav-dropdown.is-open .nav-dropdown__panel { max-height: 420px; margin-top: 0.5rem; }
.nav-dropdown__panel a { display: block; padding: 0.45rem 0 0.45rem 0.6rem; font-size: 0.9rem; color: var(--text-tertiary); }
.nav-dropdown__panel a:hover { color: var(--text); }
.nav-dropdown__panel a[aria-current="page"] { color: var(--text); font-weight: 600; }

@media (min-width: 941px) {
  .nav-pill {
    display: flex; align-items: center; gap: 1.75rem;
    background: rgba(var(--bg-rgb), 0.72);
    border: 1px solid var(--border);
    border-radius: 999px;
    padding: 0.65rem 1.85rem;
    backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
  }
  .nav-dropdown { position: relative; width: auto; }
  .nav-dropdown__trigger { width: auto; }
  .nav-dropdown__panel {
    position: absolute; top: calc(100% + 20px); left: 50%;
    transform: translate(-50%, 8px);
    min-width: 230px; max-height: none; overflow: visible;
    background: var(--surface); border: 1px solid var(--border); border-radius: 16px;
    padding: 0.6rem; margin-top: 0;
    box-shadow: 0 24px 48px rgba(0, 0, 0, 0.4);
    opacity: 0; visibility: hidden; pointer-events: none;
    transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s;
    z-index: 120;
  }
  .nav-dropdown__panel a { padding: 0.65rem 0.9rem; border-radius: 10px; transition: background 0.15s ease, color 0.15s ease; }
  .nav-dropdown__panel a:hover { background: var(--surface-hover); }
  .nav-dropdown:hover .nav-dropdown__panel,
  .nav-dropdown:focus-within .nav-dropdown__panel,
  .nav-dropdown.is-open .nav-dropdown__panel {
    opacity: 1; visibility: visible; pointer-events: auto; transform: translate(-50%, 0);
  }
}
@media (prefers-reduced-motion: reduce) {
  .nav-dropdown__panel, .nav-dropdown__chevron { transition: none; }
}

.nav-toggle {
  display: none; width: 44px; height: 44px; align-items: center; justify-content: center;
  border: none; border-radius: 10px; background: transparent;
}
.nav-toggle span, .nav-toggle::before, .nav-toggle::after {
  content: ''; display: block; width: 18px; height: 2px; background: var(--text); position: relative; transition: all 0.25s ease;
}
.nav-toggle::before { position: absolute; transform: translateY(-6px); }
.nav-toggle::after { position: absolute; transform: translateY(6px); }
.nav-toggle[aria-expanded="true"] span { background: transparent; }
.nav-toggle[aria-expanded="true"]::before { transform: rotate(45deg); }
.nav-toggle[aria-expanded="true"]::after { transform: rotate(-45deg); }

/* CTA persistente en la barra mobile (copiloto de referencia: icono a la izquierda, logo
   centrado, CTA a la derecha) — distinto del .btn.btn-primary que vive dentro del drawer
   .nav-links; oculto en desktop, solo visible en el breakpoint mobile de abajo. */
.nav-mobile-cta { display: none; }

/* ---------- Hero ---------- */
.hero {
  position: relative;
  display: flex;
  align-items: center;
  min-height: clamp(600px, 94vh, 920px);
  padding-top: clamp(7rem, 12vw, 9rem);
  padding-bottom: clamp(3rem, 6vw, 5rem);
  background:
    radial-gradient(600px circle at var(--mx, 50%) var(--my, 30%), rgba(var(--accent-rgb), 0.08), transparent 60%),
    var(--bg);
  overflow: hidden;
}

/* El loop flota grande, mismo tamaño/escala de siempre (width/aspect-ratio intactos),
   desplazado hacia el centro-derecha para dejar sitio al copy ahora alineado a la
   izquierda — con object-fit:contain el propio vídeo es más "estrecho" que esta caja
   2:1, así que mover solo el object-position del <video> apenas desplazaba nada (el
   margen interno de letterbox es pequeño); desplazar la caja entera consigue el efecto
   real sin tocar su tamaño. left:50% pasa a 58% (en vez de translateX adicional) para
   mantener la lógica de centrado existente con un solo número que ajustar. */
.hero-video-bg {
  position: absolute;
  top: 50%;
  left: 67%;
  transform: translate(-50%, -50%);
  width: min(150vw, 1900px);
  aspect-ratio: 2 / 1;
  z-index: 0;
  pointer-events: none;
}
.hero-video {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: contain;
  /* La caja (.hero-video-bg) es más "ancha" (2:1) que el propio vídeo, así que con
     object-fit:contain sobra espacio lateral dentro de la caja — object-position desplaza
     el loop dentro de ESE margen sin tocar el tamaño ni la posición de la caja en sí
     (misma escala visual de siempre). 62% deja el cuerpo del loop en centro-derecha,
     detrás del hueco que libera el copy ahora alineado a la izquierda. */
  object-position: 62% center;
  mix-blend-mode: screen;
}
/* Scrim direccional: el copy vive ahora a la izquierda, así que el velo es más denso ahí
   y se aclara hacia la derecha para dejar respirar el loop — sustituye el velo radial
   centrado que servía al layout centrado anterior. Vive dentro de .hero-video-bg (que ya
   es position:absolute), así queda garantizado por debajo de .hero-content (z-index:2)
   sin depender de un z-index intermedio. */
.hero-video-bg::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(90deg, rgba(var(--bg-rgb), 0.86) 0%, rgba(var(--bg-rgb), 0.7) 30%, rgba(var(--bg-rgb), 0.32) 55%, rgba(var(--bg-rgb), 0.08) 78%, transparent 100%),
    linear-gradient(180deg, rgba(var(--bg-rgb), 0.5) 0%, transparent 22%, transparent 70%, rgba(var(--bg-rgb), 0.55) 100%);
}

/* .hero-content = posicionamiento respecto al viewport (full-width, NO usa .container —
   ese ancla a max-width:1280px + margin:auto, que es justo lo que empujaba el copy lejos
   del borde real). .hero-copy = ancho real del bloque editorial, contenido dentro. Esto
   permite hero full-bleed con un "rail" editorial estrecho, en vez de que todo el bloque
   quede atrapado dentro del ancho centrado que usan el resto de secciones (correcto ahí,
   no aquí). */
.hero-content {
  position: relative;
  z-index: 2;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  padding-left: clamp(48px, 4.6vw, 92px);
  padding-right: clamp(32px, 4vw, 72px);
}
.hero-copy {
  width: min(44vw, 680px);
  max-width: 680px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  text-align: left;
}
.hero-copy .eyebrow { margin-bottom: clamp(28px, 2.2vw, 38px); }
.hero-actions { justify-content: flex-start; margin-top: clamp(30px, 2.4vw, 38px); }

/* ---------- Hero title + subclaim + rotating headline ---------- */
.hero-title {
  /* Sin max-width propio: lo hereda de .hero-copy (min(44vw,680px)). El font-size debe
     dejar de crecer justo cuando .hero-copy alcanza su propio tope de 680px (~1545px de
     viewport) — si siguiera escalando por vw más allá de ese punto, la caja ya no crece
     pero la fuente sí, y "Connected Growth" volvería a partirse en 3 líneas. */
  font-size: clamp(3.3rem, 5vw, 4.8rem);
  line-height: 0.94;
  letter-spacing: -0.02em;
  color: var(--text);
  margin-bottom: clamp(28px, 2.2vw, 36px);
}
.hero-title span { display: block; }
.hero-title-accent { color: var(--accent); }

.hero-subclaim {
  margin-top: 0;
  margin-bottom: 0;
  font-size: clamp(1.25rem, 1.5vw, 1.5rem);
  line-height: 1.48;
  color: var(--text-secondary);
}
.hero-rotator-window {
  position: relative;
  display: block;
  width: 100%;
  /* overflow:hidden aquí era justo lo que podía recortar la frase si por lo que sea el
     ancho real del wrapper resultaba más estrecho que el texto (nowrap ya impide el
     envoltorio a una 2ª línea, pero un overflow:hidden seguía pudiendo recortar
     horizontalmente en el peor caso). overflow:visible: la frase nunca puede quedar
     invisible — como mucho se saldría un poco de su caja, nunca se corta. La altura fija
     de abajo sigue evitando el salto vertical entre frases sin necesitar overflow:hidden. */
  overflow: visible;
  height: 1.48em;
  line-height: 1.48;
}
.hero-rotator-text {
  display: inline-block;
  max-width: 100%;
  white-space: nowrap; /* sin esto, la frase podía envolver a una 2ª línea invisible
    dentro de la caja de 1 línea (height:1.48em + overflow:hidden del wrapper) y se veía
    cortada a mitad de palabra ("datos conec...") — nowrap la fuerza a una sola línea */
  color: var(--text);
}
/* Cursor de escritura: fino, morado de marca, parpadea durante todo el ciclo
   (escribiendo, en pausa y borrando) */
.hero-rotator-text::after {
  content: '';
  display: inline-block;
  width: 2px;
  height: 0.88em;
  margin-left: 0.08em;
  background: var(--accent);
  vertical-align: -0.05em;
  animation: heroCaretBlink 0.8s step-end infinite;
}
@keyframes heroCaretBlink {
  0%, 45% { opacity: 1; }
  46%, 100% { opacity: 0; }
}

/* ---------- Servicios: carrusel horizontal scroll-driven de slides editoriales negros
   (una sola fila, sin grid) — inspirado en el principio de "Nuestros Studios" de Globant
   GUT: fondo claro de sección + paneles negros con aire alrededor, nunca a pantalla
   completa. Composición editorial: cada card tiene su propia silueta (ancho, alto,
   ratio body/media, alineación vertical dentro del sticky) en vez de un sistema de dos
   tiers homogéneos — ver el bloque "silueta por card" más abajo. ---------- */
.services-intro { margin-bottom: 1.5rem; }
/* Con el eyebrow "Nuestros Servicios" retirado del HTML, el h2 pasa a ser el primer
   elemento — sin este margin quedaría pegado al lede (0 gap real, heredado del reset
   global), así que se añade aquí el respiro editorial título→subclaim. */
.services-intro h2 { margin-bottom: 1.5rem; }

/* Desktop (JS activa el modo "hijack" desde 1024px): .services-scroll-track es el spacer
   vertical que genera la distancia de scroll; .services-scroll-sticky se fija en pantalla
   mientras tanto; app.js mueve .services-carousel con translate3d según el progreso.
   align-items:center reparte el sobrante vertical arriba/abajo del slide — es lo que genera
   el aire de la referencia GUT en vez de que la card ocupe todo el sticky. */
.services-scroll-sticky {
  position: sticky;
  top: 96px;
  height: calc(100vh - 96px);
  height: calc(100svh - 96px); /* estable en mobile: no baila con la barra de direcciones */
  min-height: 460px;
  max-height: 820px;
  display: flex;
  align-items: center;
  overflow: hidden;
  touch-action: pan-y; /* el gesto sigue siendo scroll vertical nativo, nunca lo bloqueamos */
}
.services-carousel-wrap { width: 100%; overflow: hidden; }

/* Motor scroll-driven único para desktop/tablet/mobile (ver app.js). Por defecto (sin JS,
   o mientras JS no ha inicializado todavía) .services-carousel es un carrusel accesible con
   swipe/scroll horizontal nativo — el fallback exigido si JS falla. En cuanto
   initServicesHorizontalScroll() confirma que puede controlar el track, añade
   .is-hijacked y el propio JS pasa a mover el track con translate3d. app.js calcula el
   recorrido a partir de carousel.scrollWidth en tiempo real (ver initServicesHorizontalScroll
   en app.js) — cualquier cambio de anchos aquí se recalcula solo, sin tocar JS. */
#sistema .services-carousel {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  width: max-content;
  gap: clamp(26px, 2.2vw, 38px);
  padding-inline: var(--pad-inline);
  overflow-x: auto;
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
  scroll-padding-left: var(--pad-inline);
  scrollbar-width: none; -ms-overflow-style: none;
}
#sistema .services-carousel::-webkit-scrollbar { display: none; }
#sistema .services-carousel.is-hijacked {
  overflow-x: hidden;
  scroll-snap-type: none;
  will-change: transform;
}

/* Slide/panel: lienzo negro único (media + copy dentro del mismo bloque, sin card SaaS) */
#sistema .service-card {
  position: relative;
  flex: 0 0 auto;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  text-decoration: none;
  background: #050505;
  color: #fff;
  border: 0;
  border-radius: 3px;
  scroll-snap-align: start;
  transition: box-shadow 0.3s ease;

  /* Sistema único de spacing interno del copy — heredado por .service-body y sus hijos en
     las seis cards, sin excepción por variante (media-top/bottom/side). La silueta (ancho,
     alto, ratio body/media) sí varía card a card — ver más abajo — pero el colchón interior
     del copy usa siempre estos mismos tokens. */
  --service-pad-x: clamp(34px, 2.6vw, 44px);
  --service-pad-y: clamp(32px, 2.4vw, 42px);
  --service-gap-title: 15px;
  --service-gap-copy: 13px;
  --service-gap-cta: clamp(28px, 2vw, 34px);
}

/* Familias de layout: el DOM siempre es MEDIA seguido de BODY; flex-direction decide el
   orden visual. media-top = tal cual (media arriba, body abajo); media-bottom invierte
   visualmente con column-reverse; media-side pone copy a la izquierda (64%) y media a la
   derecha (36%) con row-reverse. El tamaño real de cada card vive en el bloque "silueta por
   card" de más abajo — aquí solo se define la familia estructural. */
#sistema .service-card--media-top { flex-direction: column; align-items: stretch; }
#sistema .service-card--media-bottom { flex-direction: column-reverse; align-items: stretch; }
#sistema .service-card--media-side {
  flex-direction: row-reverse;
  align-items: stretch;
}
#sistema .service-card--media-side.service-card--media-left { flex-direction: row; }
#sistema .service-card--media-side .service-body { flex: 0 0 64%; height: 100%; }
#sistema .service-card--media-side .service-media { flex: 0 0 36%; height: 100%; }
/* IA Operativa reparte algo más de ancho a su vídeo 9:16 (38% en vez del 36% genérico) para
   acercarse más a su ratio nativo y reducir el crop lateral. */
#sistema .service-card--ai .service-body { flex-basis: 62%; }
#sistema .service-card--ai .service-media { flex-basis: 38%; }

#sistema .service-body {
  position: relative;
  z-index: 2;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  min-width: 0;
  min-height: 0;
  padding: var(--service-pad-y) var(--service-pad-x);
  background: #050505;
  overflow: visible;
}

#sistema .service-body h3 {
  flex: 0 0 auto;
  color: #fff;
  font-size: clamp(2.4rem, 2.7vw, 3.2rem);
  font-weight: 800;
  line-height: .98;
  letter-spacing: -.045em;
  text-wrap: balance; /* evita ríos de una sola palabra en títulos de 2 líneas (CRM, IA) */
  overflow-wrap: normal;
  word-break: normal;
  margin: 0 0 var(--service-gap-title);
}
#sistema .service-claim {
  flex: 0 0 auto;
  color: #fff;
  font-size: clamp(1.18rem, 1.3vw, 1.45rem);
  font-weight: 500;
  line-height: 1.28;
  letter-spacing: -.012em;
  max-width: 31ch;
  margin: 0 0 var(--service-gap-copy);
}
#sistema .service-description {
  flex: 0 0 auto;
  color: rgba(255, 255, 255, .70);
  font-size: clamp(.98rem, 1.02vw, 1.08rem);
  font-weight: 400;
  line-height: 1.5;
  max-width: 45ch;
  overflow: visible;
  margin: 0;
}
/* El CTA vuelve al flujo natural del contenido: margin-top fijo (no auto) marca el gap
   mínimo/real frente a la descripción. Con margin-top:auto anterior, cualquier card con
   copy corto y una altura de card generosa (Growth Strategy, Advertising) empujaba el CTA
   hasta el borde inferior, dejando un hueco negro sin función entre descripción y CTA. El
   sobrante de altura (si lo hay) ahora queda DESPUÉS del CTA — igual de silencioso
   visualmente, pero ya no rompe la lectura del copy. */
#sistema .service-more {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  gap: 10px;
  flex: 0 0 auto;
  margin-top: var(--service-gap-cta);
  padding-top: 0;
  padding-bottom: 8px;
  font-family: 'Heebo', sans-serif;
  font-weight: 650;
  font-size: .92rem;
  line-height: 1.15;
  color: #F4F5F7;
  white-space: nowrap;
  border-bottom: 1px solid rgba(255, 255, 255, .32);
  width: fit-content;
  opacity: 1;
  visibility: visible;
  position: static;
  transition: color 0.3s ease, border-color 0.3s ease;
}
#sistema .service-more svg { width: 16px; height: 16px; flex: 0 0 auto; transition: transform 180ms ease; }
#sistema .service-card:hover .service-more { color: var(--accent); border-color: var(--accent); }
#sistema .service-card:hover .service-more svg { transform: translateX(4px); }

/* Visual protagonista, full-bleed dentro de su área — sin márgenes ni caja propia. */
#sistema .service-media { position: relative; min-width: 0; min-height: 0; overflow: hidden; background: #111; }
#sistema .service-media img,
#sistema .service-media video {
  width: 100%; height: 100%; object-fit: cover; display: block;
  animation: serviceKenBurns 18s ease-in-out infinite alternate;
  transition: filter 0.4s ease;
}
#sistema .service-card:hover .service-media img,
#sistema .service-card:hover .service-media video { filter: brightness(1.08) saturate(1.1); }
/* Growth Strategy: el cohete termina su recorrido arriba a la derecha — ancla el
   crop de object-fit:cover hacia arriba para no cortarle la punta. */
#sistema .service-motion--growth-strategy { object-position: center top; }
@keyframes serviceKenBurns {
  from { transform: scale(1) translate(0, 0); }
  to   { transform: scale(1.12) translate(-1.5%, -1%); }
}

/* ---------- Silueta por card: cada una de las 6 tiene su propio ancho/alto — el vídeo NO
   crece proporcionalmente con la card, el espacio extra va a body/padding/CTA. El objetivo
   nth-child(N) sigue el orden real del DOM en index.html (Growth, Advertising, Martech,
   CRM, SEO, IA) — es estructural, no decorativo, así que es seguro anclarse a él aquí. ---------- */

/* 01 · Growth Strategy — horizontal, media arriba, la más ancha del tier alto. Altura
   recortada respecto a Desarrollo 1 (620-660 → 535-590) ahora que el copy compactado ya no
   necesita tanto colchón — media ~50% / body ~50%, sin margin-top:auto en el CTA. */
#sistema .services-carousel > .service-card:nth-child(1) {
  width: clamp(610px, 42vw, 700px);
  min-height: clamp(535px, 38vw, 590px);
  height: auto;
  align-self: center;
}
#sistema .services-carousel > .service-card:nth-child(1) .service-media {
  height: clamp(265px, 19vw, 295px);
  flex: 0 0 auto;
}
#sistema .services-carousel > .service-card:nth-child(1) .service-body {
  min-height: clamp(265px, 18vw, 290px);
  flex: 1 0 auto;
}

/* 02 · Advertising — media lateral, muy ancha y cinematográfica, la más baja del tier
   panorámico junto a IA. body/media ya estaban en 64/36 (dentro del target 61-65/35-39). */
#sistema .services-carousel > .service-card:nth-child(2) {
  width: clamp(680px, 46vw, 780px);
  height: clamp(470px, 33vw, 520px);
  align-self: center;
}

/* 03 · Martech — la más estrecha/vertical del set, media abajo. */
#sistema .services-carousel > .service-card:nth-child(3) {
  width: clamp(520px, 35vw, 590px);
  min-height: clamp(555px, 39vw, 610px);
  height: auto;
  align-self: flex-start;
}
#sistema .services-carousel > .service-card:nth-child(3) .service-body {
  min-height: clamp(275px, 18.5vw, 300px);
  flex: 0 0 auto;
}
#sistema .services-carousel > .service-card:nth-child(3) .service-media {
  height: clamp(265px, 19vw, 305px);
  flex: 0 0 auto;
}

/* 04 · CRM & Automation — media arriba, algo más vertical que Growth; body ligeramente más
   dominante que Growth (differencia deliberada de silueta, no una copia). */
#sistema .services-carousel > .service-card:nth-child(4) {
  width: clamp(565px, 39vw, 640px);
  min-height: clamp(545px, 39vw, 600px);
  height: auto;
  align-self: center;
}
#sistema .services-carousel > .service-card:nth-child(4) .service-media {
  height: clamp(260px, 18vw, 290px);
  flex: 0 0 auto;
}
#sistema .services-carousel > .service-card:nth-child(4) .service-body {
  min-height: clamp(280px, 19vw, 310px);
  flex: 1 0 auto;
}

/* 05 · SEO & Content — media abajo (sin cambiar), algo más compacta que Martech. */
#sistema .services-carousel > .service-card:nth-child(5) {
  width: clamp(535px, 36vw, 610px);
  min-height: clamp(520px, 37vw, 575px);
  height: auto;
  align-self: flex-end;
}
#sistema .services-carousel > .service-card:nth-child(5) .service-body {
  min-height: clamp(255px, 17.5vw, 285px);
  flex: 0 0 auto;
}
#sistema .services-carousel > .service-card:nth-child(5) .service-media {
  height: clamp(250px, 18vw, 285px);
  flex: 0 0 auto;
}

/* 06 · IA Operativa — media lateral, ancha y la más baja de las seis, cerrando el recorrido
   volviendo a abrir horizontalmente. body/media ya estaban en 62/38 (target 60-63/37-40). */
#sistema .services-carousel > .service-card:nth-child(6) {
  width: clamp(640px, 44vw, 730px);
  height: clamp(455px, 32vw, 505px);
  align-self: center;
}

/* Guarda de altura corta en desktop (portátiles 13"-14", ventanas maximizadas en monitores
   panorámicos de poca altura): reducir la MEDIA primero, nunca el body — el body es donde
   vive el criterio de seguridad del copy (título/descr./CTA con aire). */
@media (min-width: 1101px) and (max-height: 820px) {
  #sistema .service-card {
    --service-pad-x: 32px;
    --service-pad-y: 30px;
  }
  #sistema .services-carousel > .service-card:nth-child(1) .service-media { height: 260px; }
  #sistema .services-carousel > .service-card:nth-child(1) .service-body { min-height: 300px; }
  #sistema .services-carousel > .service-card:nth-child(4) .service-media { height: 265px; }
  #sistema .services-carousel > .service-card:nth-child(4) .service-body { min-height: 310px; }
  #sistema .services-carousel > .service-card:nth-child(3) .service-media { height: 270px; }
  #sistema .services-carousel > .service-card:nth-child(5) .service-media { height: 270px; }
}

/* Tablet (<=1100px): mismo sistema de siluetas, solo se reduce el colchón interior y el
   ancho de cada card pasa a ser relativo al viewport (mantiene la variedad, no las iguala).
   Las alturas (min-height/height) del bloque de siluetas de arriba no están condicionadas a
   ningún min-width, así que ya se contraen solas vía sus propios clamp() — no hace falta
   repetirlas aquí. Growth/Martech/CRM/SEO ya usan height:auto (nunca comprimen); Advertising
   e IA sí tenían height fija en desktop y se liberan a auto en cuanto la familia --media-side
   pasa a columna (ver breakpoint siguiente), para que nunca corten contenido al apilarse. */
@media (max-width: 1100px) {
  #sistema .service-card {
    --service-pad-x: clamp(28px, 3.5vw, 34px);
    --service-pad-y: clamp(27px, 3.4vw, 33px);
  }
  #sistema .service-body h3 { font-size: clamp(2.15rem, 4vw, 2.7rem); }
  #sistema .service-claim { font-size: clamp(1.12rem, 2vw, 1.24rem); }
  #sistema .service-description { font-size: clamp(.96rem, 1.6vw, 1rem); }
  #sistema .services-carousel > .service-card:nth-child(1) { width: clamp(460px, 74vw, 640px); }
  #sistema .services-carousel > .service-card:nth-child(2) { width: clamp(480px, 78vw, 660px); }
  #sistema .services-carousel > .service-card:nth-child(3) { width: clamp(440px, 70vw, 600px); }
  #sistema .services-carousel > .service-card:nth-child(4) { width: clamp(460px, 74vw, 640px); }
  #sistema .services-carousel > .service-card:nth-child(5) { width: clamp(450px, 72vw, 620px); }
  #sistema .services-carousel > .service-card:nth-child(6) { width: clamp(480px, 78vw, 660px); }
}

/* Breakpoint side → stack (<=900px): Advertising/IA dejan de caber cómodas en formato
   panorámico lado a lado — pasan a media arriba + body abajo (mismo DOM, solo cambia
   flex-direction). height pasa a auto para que, apiladas en columna, el body nunca quede
   corto de sitio por heredar la altura fija que tenían en fila. */
@media (max-width: 900px) {
  #sistema .service-card--media-side {
    flex-direction: column;
    height: auto;
  }
  #sistema .service-card--media-side .service-media {
    width: 100%;
    height: clamp(210px, 34vw, 280px);
    flex: 0 0 auto;
  }
  #sistema .service-card--media-side .service-body {
    width: 100%;
    height: auto;
    flex: 0 0 auto;
  }
}

/* Mobile (<=767px): el motor scroll-driven sigue horizontal (ver app.js) — NUNCA lista
   vertical. !important es deliberado: neutraliza en bloque los width/height específicos por
   nth-child de desktop (más específicos que una clase simple) sin tener que repetir los seis
   selectores nth-child aquí uno a uno. */
@media (max-width: 767px) {
  #sistema .services-carousel { gap: 20px; }
  #sistema .service-card {
    width: 88vw !important;
    height: auto !important;
    min-height: 0 !important;
    --service-pad-x: clamp(24px, 6vw, 28px);
    --service-pad-y: clamp(24px, 6vw, 28px);
    --service-gap-title: 11px;
    --service-gap-copy: 9px;
    --service-gap-cta: 24px;
    align-self: center;
  }
  #sistema .service-body h3 { font-size: clamp(1.9rem, 8.2vw, 2.3rem); line-height: 1.05; }
  #sistema .service-claim { font-size: clamp(1.02rem, 4.4vw, 1.15rem); line-height: 1.22; max-width: none; }
  #sistema .service-description { font-size: clamp(.92rem, 3.6vw, .98rem); line-height: 1.45; max-width: none; }
  #sistema .service-more { font-size: 0.9rem; margin-top: var(--service-gap-cta); padding-top: 0; }

  #sistema .service-card--media-top .service-body { min-height: 0 !important; height: auto !important; }
  #sistema .service-card--media-bottom .service-body { min-height: 0 !important; height: auto !important; }

  /* Diferencia sutil también en mobile — no clones absolutos del ancho ni de la media,
     aunque el contraste se suaviza respecto a desktop. Los seis nth-child ganan sobre la
     regla !important genérica de arriba por especificidad (mismo mecanismo ya usado en el
     resto del sistema de siluetas) y sobre las reglas de familia --media-top/bottom/side. */
  #sistema .services-carousel > .service-card:nth-child(1) { width: 88vw !important; }
  #sistema .services-carousel > .service-card:nth-child(1) .service-media { height: clamp(210px, 52vw, 225px) !important; }
  #sistema .services-carousel > .service-card:nth-child(2) { width: 90vw !important; }
  #sistema .services-carousel > .service-card:nth-child(2) .service-media { height: clamp(195px, 52vw, 215px) !important; }
  #sistema .services-carousel > .service-card:nth-child(3) { width: 85vw !important; }
  #sistema .services-carousel > .service-card:nth-child(3) .service-media { height: clamp(205px, 52vw, 220px) !important; }
  #sistema .services-carousel > .service-card:nth-child(4) { width: 88vw !important; }
  #sistema .services-carousel > .service-card:nth-child(4) .service-media { height: clamp(205px, 52vw, 220px) !important; }
  #sistema .services-carousel > .service-card:nth-child(5) { width: 86vw !important; }
  #sistema .services-carousel > .service-card:nth-child(5) .service-media { height: clamp(195px, 52vw, 215px) !important; }
  #sistema .services-carousel > .service-card:nth-child(6) { width: 90vw !important; }
  #sistema .services-carousel > .service-card:nth-child(6) .service-media { height: clamp(190px, 52vw, 210px) !important; }

  /* Causa real del "hueco" antes de la 1ª card y después de la 6ª: .services-scroll-sticky
     (arriba, ~línea 471) usa align-items:center dentro de una caja de casi toda la altura
     del viewport (100svh-96px, hasta 820px) — deliberado en desktop (comentario "aire de
     la referencia GUT"), pero en mobile la card (~500-580px de alto real: media ~210px +
     body con texto/padding) queda flotando con ~150-190px de vacío arriba Y abajo dentro
     de esa caja alta, TODO el tiempo que dura el scroll horizontal 01→06 — no es un fallo
     de la fórmula de app.js (progress llega a 1 exactamente cuando se agota el track,
     verificado leyendo measure()/layout()/render(): no dependen de la altura del sticky,
     solo de scrollWidth/clientWidth), es puramente este centrado vertical sumado a una
     caja más alta de lo que la card necesita. Dos cambios, no uno: top corregido a la
     altura real del header mobile (era 96px, el de desktop, dejando ~28px de más antes de
     enganchar el sticky) y la propia altura de la caja recortada a un techo mucho menor
     (640px cubre con margen la card más alta real, ~580px, sin arriesgarse a recortarla
     con el overflow:hidden del sticky) — así queda mucho menos sobrante que repartir, y
     con align-items:flex-start ese resto mínimo se queda abajo de forma predecible en vez
     de partirse arriba/abajo y empujar la card hacia el centro de la pantalla. */
  #sistema .services-scroll-sticky {
    top: var(--mobile-nav-height, 68px);
    height: calc(100svh - var(--mobile-nav-height, 68px));
    min-height: 460px;
    max-height: 640px;
    align-items: flex-start;
    padding-top: 28px;
  }
}

/* El vídeo 16:9 de SEO & Content depende de reconocer persona + smartphone + tarjetas de
   contenido — mismo criterio de ventana panorámica que Martech/CRM, pero un poco menos
   agresivo (1.9:1 en vez de 2:1) para conservar más rostro/gesto en el crop vertical.
   .service-card--seo no necesita reglas propias: .service-card--media-bottom ya resuelve el
   layout (column-reverse → copy visualmente arriba, media abajo, con el media primero en
   el DOM, igual que Martech/CRM) y se mantiene como hook por si hiciera falta más adelante. */
@media (min-width: 641px) {
  .service-card--media-bottom .service-media--seo {
    flex: 0 0 auto;
    height: auto;
    aspect-ratio: 1.9 / 1;
  }
}

/* #sistema hereda .section { padding-block: var(--section-pad) } (80-128px) como su PROPIO
   padding-bottom — eso se sumaba al padding-block del CTA de abajo (antes 56-96px por lado)
   y era la causa real del hueco de ~450-550px, no un min-height (nunca existió uno aquí).
   .services-end-cta pasa a ser la única fuente de spacing en el cierre de Servicios. */
.services-section { padding-bottom: 0; }

/* Cierre editorial de Servicios (principio GUT: capabilities → CTA independiente → siguiente
   sección) — vive fuera de .services-scroll-track, así que el flujo normal del documento ya
   lo posiciona después de que termine la fase sticky/horizontal; no necesita JS ni detección
   de progreso. height:auto implícito (no hay min-height/height fijado) + padding-top/bottom
   asimétrico (ligeramente más aire arriba, hacia las cards, que abajo hacia Metodología). */
.services-end-cta {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  padding-top: clamp(80px, 6vw, 100px);
  padding-bottom: clamp(70px, 5.5vw, 92px);
}
@media (max-width: 1023px) {
  .services-end-cta { padding-block: clamp(58px, 7vw, 75px); }
}
@media (max-width: 640px) {
  .services-end-cta {
    padding-top: clamp(45px, 12vw, 65px);
    padding-bottom: clamp(40px, 11vw, 60px);
  }
}
.services-end-cta__link {
  display: inline-flex;
  align-items: center;
  gap: clamp(0.75rem, 1.5vw, 1.25rem);
  padding-block: 0.4rem; /* asegura un tap target >=44px en mobile junto al line-height */
  text-decoration: none;
  font-family: 'Heebo', sans-serif;
  font-weight: 700;
  font-size: clamp(1.75rem, 2.3vw, 2.625rem);
  color: var(--text);
  border-bottom: 2px solid var(--border);
  transition: color 0.2s ease, border-color 0.2s ease;
}
.services-end-cta__link svg {
  width: clamp(28px, 2.3vw, 40px);
  height: clamp(28px, 2.3vw, 40px);
  color: var(--accent);
  flex-shrink: 0;
  transition: transform 0.2s ease;
}
.services-end-cta__link:hover,
.services-end-cta__link:focus-visible {
  color: var(--accent);
  border-color: var(--accent);
}
.services-end-cta__link:hover svg,
.services-end-cta__link:focus-visible svg {
  transform: translateX(6px);
}
@media (prefers-reduced-motion: reduce) {
  .services-end-cta__link svg { transition: none; }
  .services-end-cta__link:hover svg,
  .services-end-cta__link:focus-visible svg { transform: none; }
}

/* ---------- Cards ---------- */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 2rem;
  position: relative;
  overflow: hidden;
  transition: border-color 0.3s ease, transform 0.3s ease, background 0.3s ease;
}
.card:hover { border-color: var(--border-hover); background: var(--surface-hover); transform: translateY(-4px); }

.card-spotlight::before {
  content: ''; position: absolute; inset: 0;
  background: radial-gradient(320px circle at var(--mx, 50%) var(--my, 50%), rgba(var(--accent-rgb), 0.10), transparent 70%);
  opacity: 0; transition: opacity 0.3s ease; pointer-events: none;
}
.card-spotlight:hover::before { opacity: 1; }
.card > * { position: relative; z-index: 1; }

.card-icon {
  width: 44px; height: 44px; border-radius: 12px;
  background: rgba(var(--accent-rgb), 0.1);
  display: flex; align-items: center; justify-content: center;
  margin-bottom: 1.5rem;
}
.card-icon svg { width: 22px; height: 22px; stroke: var(--accent); }
.pillar-data .card-icon { background: rgba(var(--accent-2-rgb), 0.1); }
.pillar-data .card-icon svg { stroke: var(--accent-2); }
.card h3 { margin-bottom: 0.75rem; }

/* ---------- Tags ---------- */
.tag {
  display: inline-flex; align-items: center; padding: 0.35rem 0.85rem; border-radius: 999px;
  border: 1px solid var(--border); background: var(--surface); color: var(--text-tertiary);
  font-size: 0.75rem; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase;
}
.tag-accent { border-color: rgba(var(--accent-rgb), 0.4); color: var(--accent); background: rgba(var(--accent-rgb), 0.08); }


/* ---------- Stats row ---------- */
.stats-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 2rem; margin-top: 3rem; }
.stat-block { border-top: 1px solid var(--border); padding-top: 1.5rem; }
.stat-number { font-family: 'Heebo', sans-serif; font-weight: 800; font-size: clamp(2.5rem, 5vw, 4.5rem); color: var(--text); font-variant-numeric: tabular-nums; }
.stat-label { color: var(--text-tertiary); font-size: 0.875rem; margin-top: 0.5rem; }

/* ---------- Operadores preview (home) ---------- */
.operators-section {
  position: relative;
  overflow: hidden;
  overflow-x: clip;
  padding-block: clamp(80px, 7vw, 110px);
}
/* Negro premium exacto del sistema (mismo --bg de root) — no gris lavado, no .section-alt
   (--surface-alt es un carbón más claro, pensado para paneles, no para "negro real"). */
.operators-section--dark { background: #0A0C0F; }
.operators-section--dark .operators-stat { border-left-color: rgba(255, 255, 255, .12); }
.operators-section--dark .operators-stat-label { color: rgba(255, 255, 255, .58); }
/* Textura editorial casi imperceptible — dos manchas radiales muy suaves, nada de imagen
   pesada. Evocan vagamente tejido/flujo sin competir con el contenido ni con la foto. */
.operators-section::before,
.operators-section::after {
  content: '';
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
  z-index: 0;
  filter: blur(70px);
}
.operators-section::before {
  width: 55vw; height: 55vw;
  top: -22%; left: -18%;
  background: radial-gradient(circle, rgba(var(--accent-rgb), 0.06), transparent 72%);
}
.operators-section::after {
  width: 45vw; height: 45vw;
  bottom: -20%; right: -12%;
  background: radial-gradient(circle, rgba(var(--accent-rgb), 0.045), transparent 72%);
}
/* Full-width por diseño (NO .container): igual que el hero, .operators-shell controla su
   propio padding-inline directamente en vez de heredar max-width:var(--container) +
   margin:auto — eso es lo que mantenía el copy lejos del borde real y de paso acortaba el
   espacio disponible para el loop. .container global queda intacto para el resto del sitio. */
.operators-shell {
  position: relative;
  z-index: 1;
  width: 100%;
  display: grid;
  /* Antes 52%/48%, luego 47.7%/52.3% para el loop de infinito. El Growth Core pide todavía
     más presencia (~43%/57%, dentro del 42-45% / 55-58% del brief) — el copy conserva un
     suelo de 400px para no comprimirse nunca, la visual uno de 750px para que el objeto
     tenga sitio real donde crecer sin invadir el copy. */
  grid-template-columns: minmax(400px, 0.86fr) minmax(750px, 1.14fr);
  align-items: center;
  gap: clamp(32px, 5vw, 72px);
  padding-left: clamp(48px, 5vw, 96px);
  padding-right: clamp(32px, 4vw, 72px);
}
.operators-copy { max-width: 700px; justify-self: start; }

.operators-title {
  /* .container tiene max-width:var(--container) (1280px), así que la columna izquierda deja
     de crecer a partir de ese viewport — si el font-size siguiera escalando por vw más allá
     de 1280px, "Los operadores que" volvería a partirse en dos líneas en pantallas grandes.
     El techo del clamp (3rem) se alcanza justo en 1280px y se queda plano de ahí en adelante. */
  font-size: clamp(2.5rem, 3.75vw, 3rem);
  line-height: 1.05;
  letter-spacing: -0.02em;
  margin-bottom: 1.5rem;
}
.operators-title span { display: block; }
.operators-title em {
  font-family: Georgia, "Times New Roman", serif;
  font-style: italic;
  font-weight: 400;
}
.operators-lede { margin-bottom: clamp(1.5rem, 2.4vw, 2rem); max-width: 600px; }

.operators-stats {
  display: flex;
  flex-wrap: nowrap;
  gap: clamp(1rem, 1.8vw, 1.75rem);
  margin-bottom: clamp(2rem, 3vw, 2.5rem);
}
.operators-stat { flex: 1 1 0; min-width: 0; padding-left: clamp(1rem, 1.8vw, 1.75rem); border-left: 1px solid var(--border); }
.operators-stat:first-child { padding-left: 0; border-left: none; }
.operators-stat-num {
  font-family: 'Heebo', sans-serif;
  font-weight: 800;
  font-size: clamp(2.8rem, 3.5vw, 4rem);
  line-height: 1;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}
.operators-stat-label { color: var(--text-tertiary); font-size: 0.875rem; margin-top: 0.5rem; max-width: 18ch; }

.operators-actions { margin-bottom: clamp(2.5rem, 4vw, 3.5rem); }
.operators-actions .btn svg { width: 16px; height: 16px; }
.btn-light-outline { background: #FFFFFF; color: var(--text); border-color: var(--border); }
.btn-light-outline:hover { border-color: var(--accent); color: var(--accent); background: #FFFFFF; }
/* Sobre el Equipo dark, .btn-light-outline heredaría texto casi blanco sobre su propio
   fondo blanco hardcodeado (invisible) — el resto de páginas que sí usan esta clase sobre
   fondo claro no se tocan; el fix vive scoped al modifier de esta sección. */
.operators-section--dark .btn-light-outline { background: transparent; color: #fff; border-color: rgba(255, 255, 255, .35); }
.operators-section--dark .btn-light-outline:hover { border-color: var(--accent); color: var(--accent); background: transparent; }

/* Base (fallback foto, sin modifier dark): tarjeta con foto, comportamiento previo intacto
   para cualquier otro uso futuro de estas clases fuera de #operadores-preview. */
.operators-visual {
  position: relative;
  border-radius: 28px;
  overflow: hidden;
  height: clamp(650px, 55vw, 760px);
  box-shadow: 0 30px 70px rgba(var(--accent-rgb), 0.10);
}
.operators-visual__photo { display: block; width: 100%; height: 100%; }
.operators-visual img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: center; }
.operators-visual-media { display: none; }

/* ---------- Equipo dark: Adaptive Growth Core, sin frame, en todos los breakpoints ----------
   assets/team/operators-growth-core.webm es VP9 + yuva420p con ALPHA REAL (generado a partir
   de Banner-operadores-nuevo_opcionA.mp4: reencuadrado para excluir la marca del generador y
   eliminar espacio muerto, luego colorkey del fondo blanco del source — ver informe de la
   tarea). Sustituye al símbolo de infinito anterior; mismo mecanismo de transparencia real,
   sin bordes que difuminar, sin negro que igualar. La foto de equipo (.operators-visual__photo)
   sigue retirada del DOM de home; ese markup base se conserva en la hoja de estilos como
   fallback reutilizable fuera de esta sección. */
.operators-section--dark .operators-visual {
  position: relative;
  display: flex;
  align-items: center;
  /* flex-end (no center): el visual debe pegar hacia el borde interior de su columna — el
     propio translateX negativo de .operators-visual-media es lo que luego lo trae "respirando"
     hacia el copy en vez de quedarse pegado al borde derecho del viewport. */
  justify-content: flex-end;
  height: auto;
  min-height: 0;
  max-width: none;
  border-radius: 0;
  overflow: visible;
  box-shadow: none;
  background: transparent;
}
.operators-section--dark .operators-visual-media {
  display: grid;
  place-items: center;
  position: relative;
  /* Ni max-width:100% ni flex-shrink (default:1 en el padre flex) a propósito: el brief
     permite que el visual desborde su propia celda de grid (nunca el documento — eso ya lo
     garantiza overflow-x:clip en .operators-section) para que domine el lado derecho.
     Coeficiente vw + translateX medidos con Playwright contra el borde real de
     .operators-copy en cada ancho para no invadir nunca el texto — "si el grid aprieta,
     ajustar el visual, nunca comprimir el copy". aspect-ratio 1600/1316 (≈1.216:1): el
     crop final del Growth Core no es 2:1 como el loop de infinito anterior — más alto en
     proporción a su ancho, así que el mismo ancho en px se traduce en un objeto bastante
     más alto que antes; ver ajustes de tamaño/posición vertical más abajo. */
  width: clamp(760px, 50vw, 950px);
  max-width: none;
  flex-shrink: 0;
  aspect-ratio: 1600 / 1316;
  overflow: visible;
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  filter: none;
  transform: translateX(-8px);
}
.operators-visual-poster,
.operators-section--dark .operators-visual-video {
  grid-area: 1 / 1;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  pointer-events: none;
  user-select: none;
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  filter: none;
  /* --operators-optical-x por defecto en 0% (no-op en desktop, que ya tiene su propio
     translateX(-8px) intencionado en .operators-visual-media más arriba, pensado para el
     layout asimétrico flex-end). Se define solo en mobile (ver @media abajo), y como
     poster y vídeo comparten esta MISMA regla, comparten el mismo transform exacto — no
     puede haber un salto de posición entre poster y vídeo. */
  transform: translateX(var(--operators-optical-x, 0%));
}
/* Crossfade poster → vídeo real: el poster arranca opaco (primer paint correcto, sin salto,
   sin negro) y el vídeo arranca invisible. initLazyVideoSource() (app.js) añade .is-ready al
   wrapper en el evento canplay del vídeo — recién entonces hay un frame real que mostrar y se
   invierte la opacidad. 220ms: dentro del rango 200-300ms que pide el brief, evita tanto el
   corte brusco como una transición perceptible como "carga". */
.operators-visual-poster {
  opacity: 1;
  transition: opacity 220ms ease-out;
}
.operators-section--dark .operators-visual-video {
  opacity: 0;
  transition: opacity 220ms ease-out;
}
.operators-visual-media.is-ready .operators-visual-poster { opacity: 0; }
.operators-section--dark .operators-visual-media.is-ready .operators-visual-video { opacity: 1; }

@media (max-width: 1024px) {
  /* Layout apilado (copy arriba, loop abajo) desde aquí hacia abajo — flex-end/translateX
     eran para "acercar el loop al copy" dentro de una fila de 2 columnas; en una columna
     apilada no hay fila que acercar, así que vuelve a un centrado simple y sin desplazar. */
  .operators-section--dark .operators-visual { justify-content: center; }
  .operators-section--dark .operators-visual-media { width: clamp(560px, 62vw, 680px); transform: none; }
}

@media (max-width: 767px) {
  /* Centrado defensivo explícito: .operators-visual ya hereda justify-content:center del
     breakpoint de 1024px y .operators-visual-media ya no lleva transform (también
     heredado), pero se fija aquí también de forma local para que el centrado en <=767px
     no dependa silenciosamente de una regla de otro breakpoint que alguien podría tocar
     más adelante sin darse cuenta del efecto en mobile. */
  .operators-section--dark .operators-visual {
    justify-content: center;
    width: 100%;
  }
  /* Optical center del Growth Core: medido con Python/PIL directamente sobre los assets
     reales (operators-growth-core-poster.webp y un frame de operators-growth-core.webm),
     no estimado a ojo. Bounding box del contenido no-blanco contra el canvas 1600×1316:
     el poster tiene su masa visual centrada en +10.8% del ancho respecto al centro del
     canvas, el frame de vídeo en +11.9% — prácticamente el mismo offset en ambos (ver
     informe), lo que confirma que un único valor compartido es correcto. -11% (redondeo
     del promedio) es el translateX que devuelve esa masa al centro real. Este offset ya
     está "horneado" en el propio archivo (el objeto no está centrado dentro de su propio
     canvas) — por eso ni margin:auto ni justify-content:center por sí solos podían
     arreglarlo: ambos centran la CAJA, no el objeto dentro de ella. */
  .operators-section--dark .operators-visual-media {
    width: min(92vw, 460px);
    margin-inline: auto;
    transform: none;
    --operators-optical-x: -11%;
  }
}

@media (max-width: 1024px) {
  /* Antes el corte estaba en 1023px mientras que el loop pasaba a su tamaño "tablet" en
     1024px — a 1024px exactos la grid seguía siendo de 2 columnas (columna visual real
     ~360-400px) pero el loop ya pedía 614px, así que se recortaba contra el borde de
     .operators-section (overflow-x:clip) y se montaba encima de las stats. Alineando este
     breakpoint con el del loop, a 1024px ya está todo apilado en una sola columna con sitio
     de sobra para el tamaño grande sin invadir el copy. */
  .operators-shell { grid-template-columns: 1fr; gap: clamp(40px, 6vw, 56px); padding-left: clamp(32px, 4vw, 48px); padding-right: clamp(24px, 3vw, 40px); }
  .operators-copy { max-width: none; }
  .operators-visual { height: clamp(420px, 52vw, 560px); }
  .operators-section { padding-block: clamp(75px, 8vw, 100px); }
}

@media (max-width: 640px) {
  .operators-section { padding-block: clamp(60px, 12vw, 80px); }
  .operators-title { font-size: clamp(2.4rem, 9vw, 3rem); }
  .operators-shell { padding-left: clamp(20px, 5vw, 24px); padding-right: clamp(20px, 5vw, 24px); }
  /* .operators-copy se "desenvuelve" para poder intercalar el loop entre las CTAs y el
     final de la sección (orden mobile pedido: título → copy → stats → CTAs → LOOP) sin
     romper la agrupación de dos columnas en desktop/tablet. */
  .operators-shell { display: flex; flex-direction: column; align-items: stretch; }
  .operators-copy { display: contents; }
  .operators-title { order: 2; }
  .operators-lede { order: 3; }
  .operators-stats { order: 4; }
  .operators-actions { order: 5; margin-bottom: 16px; }
  /* margin-bottom:0: el aire final antes de que la sección termine ya lo da
     .operators-section{padding-block} de este mismo breakpoint — sumar un margin propio aquí
     disparaba el hueco muy por encima del 48-72px que pide el brief para después del loop. */
  .operators-visual { order: 6; height: auto; margin-bottom: 0; }
  .operators-stats { justify-content: space-between; gap: 1rem; }
  .operators-stat { padding-left: 1rem; flex: 1 1 0; }
  /* Antes clamp(1.9rem,8vw,2.4rem) rendía ~30-32px en los anchos reales (bajo el target
     38-44px) y la label a 0.8125rem=13px quedaba por debajo del piso legible de 14px. */
  .operators-stat-num { font-size: clamp(2.375rem, 9vw, 2.75rem); }
  .operators-stat-label { font-size: 14px; line-height: 1.35; max-width: none; }

  .operators-actions { flex-direction: column; align-items: stretch; }
  .operators-actions .btn { width: 100%; }
}

/* ---------- SCALE (home, 3 casos de éxito) ----------
   Reconstruido en HTML/CSS a partir del mockup aprobado (no es una imagen de fondo).
   .section-light ya redefine --text/--border/--surface para tema claro; aquí solo se
   sobreescribe `background` con el gradiente propio — mismo mecanismo que el resto del
   sitio usa para alternar dark/light entre secciones. */
.scale-section {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding: clamp(88px, 8vw, 150px) 0 clamp(88px, 8vw, 140px);
  background:
    radial-gradient(circle at 68% 4%, rgba(139, 92, 246, .08), transparent 34%),
    radial-gradient(circle at 10% 28%, rgba(124, 58, 237, .045), transparent 30%),
    #f8f7fb;
}
.scale-background {
  position: absolute;
  z-index: 0;
  top: -7%;
  left: 8%;
  width: min(70vw, 1050px);
  aspect-ratio: 2 / 1;
  background: url("assets/scale/scale-loop-bg.svg") center / contain no-repeat;
  opacity: .09;
  pointer-events: none;
}
.scale-inner { position: relative; z-index: 1; }

.scale-header {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  width: min(58%, 850px);
  margin-left: auto;
  margin-bottom: clamp(54px, 5vw, 82px);
  text-align: right;
}
/* Peso real más alto de Heebo (900, cargado explícitamente vía <link> de Google Fonts en
   el <head>) — nunca sintetizado por el navegador. Sin línea/underline: prohibido por el
   mockup aprobado. */
.scale-title {
  margin: 0;
  color: #08090b;
  font-family: 'Heebo', sans-serif;
  font-size: clamp(6rem, 10vw, 11rem);
  font-weight: 900;
  line-height: .8;
  letter-spacing: -.065em;
}
.scale-subclaim {
  max-width: 720px;
  margin: clamp(26px, 2vw, 34px) 0 0;
  color: rgba(20, 22, 30, .76);
  font-size: clamp(1.12rem, 1.45vw, 1.52rem);
  line-height: 1.42;
}

.scale-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(20px, 1.8vw, 30px);
}
.scale-case { min-width: 0; }
.scale-case__link {
  display: flex;
  flex-direction: column;
  height: 100%;
  overflow: hidden;
  color: inherit;
  text-decoration: none;
  background: transparent;
  border: 1px solid rgba(20, 20, 25, .08);
  border-radius: 10px;
}
.scale-case__media { aspect-ratio: 16 / 9; margin: 0; overflow: hidden; }
.scale-case__media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 320ms cubic-bezier(.2, .7, .2, 1);
}

/* Simplificado: sin métricas — image → cliente → categoría → descripción → CTA.
   El hover es de COLOR, no de movimiento: .scale-case__body pasa de blanco a negro
   (mismo --bg oscuro del sistema) y los textos cambian de tono en el mismo tiempo.
   flex:1 + .scale-case__more{margin-top:auto} mantiene el CTA anclado abajo en las
   tres cards por igual, ahora bastante más compactas al no tener bloque de métricas. */
.scale-case__body {
  display: flex;
  flex: 1;
  flex-direction: column;
  padding: clamp(24px, 2vw, 32px);
  background: #fff;
  transition: background-color 240ms ease;
}
.scale-case__title {
  margin: 0;
  color: #090a0d;
  font-family: 'Heebo', sans-serif;
  font-size: clamp(1.35rem, 1.5vw, 1.65rem);
  font-weight: 800;
  line-height: 1.08;
  letter-spacing: -.025em;
  transition: color 240ms ease;
}
.scale-case__category {
  margin: 8px 0 0;
  color: var(--accent);
  font-size: .92rem;
  font-weight: 600;
  transition: color 240ms ease;
}
.scale-case__description {
  margin: 14px 0 0;
  color: rgba(20, 22, 30, .66);
  line-height: 1.48;
  transition: color 240ms ease;
}

.scale-case__more {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  gap: 9px;
  margin-top: auto;
  padding-top: 26px;
  color: var(--accent);
  font-weight: 650;
  transition: color 240ms ease;
}
.scale-case__more svg { width: 17px; height: 17px; transition: transform 180ms ease; }
.scale-case__link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Estado dark también accesible por teclado — no depende exclusivamente de :hover. */
.scale-case__link:focus-visible .scale-case__body,
.scale-case__link:hover .scale-case__body { background: #0A0C0F; }
.scale-case__link:focus-visible .scale-case__title,
.scale-case__link:hover .scale-case__title { color: #fff; }
.scale-case__link:focus-visible .scale-case__description,
.scale-case__link:hover .scale-case__description { color: rgba(255, 255, 255, .68); }
.scale-case__link:focus-visible .scale-case__category,
.scale-case__link:hover .scale-case__category { color: #9B6BFF; }
.scale-case__link:focus-visible .scale-case__more,
.scale-case__link:hover .scale-case__more { color: #fff; }
/* Zoom de imagen y hover de color solo en dispositivos con hover real (mouse) — en
   touch la card se queda en blanco de forma permanente, sin simular :hover con JS;
   el tap simplemente navega. */
@media (hover: hover) and (pointer: fine) {
  .scale-case__link:hover .scale-case__media img { transform: scale(1.025); }
}

.scale-actions { display: flex; justify-content: center; margin-top: clamp(42px, 4vw, 64px); }
/* El SVG del CTA ("Ver más") no tenía tamaño propio en ningún breakpoint — un <svg> con
   solo viewBox y sin width/height/CSS cae al tamaño intrínseco por defecto del user-agent
   (bastante mayor que el texto que acompaña), de ahí que se percibiera "enorme". Mismo
   patrón que ya usan .operators-actions .btn svg / .scale-case__more svg en este archivo. */
.scale-actions .btn svg { width: 18px; height: 18px; flex-shrink: 0; }

@media (max-width: 1100px) {
  .scale-header { width: 76%; }
  .scale-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* SURA (3er caso) no hace span:2 a lo bruto — quedaría desproporcionada frente a las
     otras dos; se centra con un ancho contenido, como recomienda el brief tras QA. */
  .scale-case:nth-child(3) { grid-column: 1 / -1; max-width: 70%; margin-inline: auto; }
}

@media (max-width: 767px) {
  /* padding-bottom bajado de 84px a 56px: con Technology Partners oculto en mobile,
     Scale ahora conecta directo con #contacto — 84px (pensado para cuando entre medias
     había toda la franja de partners) se sentía como una franja clara de más antes del
     salto a oscuro. 56px cae dentro del target 48-64px "CTA bottom → fin de sección". */
  .scale-section { padding: 76px 0 56px; }
  .scale-header { width: 100%; align-items: flex-end; margin-bottom: 44px; text-align: right; }
  .scale-title { font-size: clamp(4.5rem, 23vw, 6.8rem); letter-spacing: -.055em; }
  .scale-subclaim { max-width: 95%; font-size: 1.04rem; }
  .scale-grid { grid-template-columns: 1fr; gap: 24px; }
  .scale-case:nth-child(3) { max-width: 100%; }
  /* .btn{width:100%} (regla genérica de mobile) convertía este CTA secundario en una
     tarjeta a todo lo ancho — aquí se le da su propio tamaño compacto, sin afectar a
     ningún otro .btn del sitio. */
  .scale-actions .btn {
    width: auto;
    min-width: 180px;
    min-height: 56px;
    padding: 0 24px;
    display: inline-flex;
    align-items: center;
    justify-content: space-between;
    gap: 28px;
  }
  .scale-actions .btn svg { width: 28px; height: 28px; }
}

/* ---------- Bento (Casos de éxito) ---------- */
.grid-casos { display: grid; grid-template-columns: repeat(6, 1fr); gap: 1.25rem; margin-top: 3rem; }
.grid-casos .case-featured { grid-column: span 4; }
.grid-casos .case-standard { grid-column: span 2; }
.case-card { display: flex; flex-direction: column; gap: 1rem; min-height: 100%; }
.case-head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
.case-metrics { display: flex; gap: 2rem; margin-top: auto; padding-top: 1rem; }
.case-metric-num { font-family: 'Heebo', sans-serif; font-weight: 800; font-size: 1.75rem; color: var(--accent); }
.case-metric-label { color: var(--text-tertiary); font-size: 0.75rem; margin-top: 0.2rem; }

/* ---------- Team grid (Operadores) ---------- */
.grid-operadores { display: grid; grid-template-columns: repeat(6, 1fr); gap: 1.5rem; margin-top: 3rem; }
/* Rejilla de 6 columnas con tarjetas de span 2: el ancho de cada tarjeta es exactamente
   el mismo que con repeat(3, 1fr) —((W-5g)/6)*2+g equivale a (W-2g)/3—, pero permite
   centrar las dos últimas de una fila de cinco en vez de dejarlas pegadas a la izquierda. */
.grid-operadores > * { grid-column: span 2; }
.grid-operadores > :nth-child(4):nth-last-child(2) { grid-column: 2 / span 2; }
.grid-operadores > :nth-child(5):nth-last-child(1) { grid-column: 4 / span 2; }
.operador-avatar {
  width: 64px; height: 64px; border-radius: 16px;
  background: var(--surface-alt); border: 1px solid var(--border);
  display: flex; align-items: center; justify-content: center;
  font-family: 'Heebo', sans-serif; font-weight: 800; font-size: 1.25rem; color: var(--accent);
  margin-bottom: 1.5rem;
}
.operador-role { color: var(--text-tertiary); font-size: 0.875rem; margin-top: 0.15rem; margin-bottom: 1rem; }

/* ---------- Operador card (expandable <details>) ---------- */
.operador-card { padding: 0; }
.operador-card summary {
  cursor: pointer; list-style: none; padding: 2rem; display: block;
}
.operador-card summary::-webkit-details-marker { display: none; }
.operador-card summary::marker { content: ''; }
.operador-toggle {
  display: inline-flex; align-items: center; gap: 0.5rem;
  color: var(--accent); font-family: 'Heebo', sans-serif; font-weight: 600; font-size: 0.875rem;
  margin-top: 0.25rem;
}
.operador-toggle svg { width: 16px; height: 16px; transition: transform 0.3s ease; }
.operador-card[open] .operador-toggle svg { transform: rotate(180deg); }
.operador-card[open] .operador-toggle .toggle-label-closed { display: none; }
.operador-toggle .toggle-label-open { display: none; }
.operador-card[open] .operador-toggle .toggle-label-open { display: inline; }

.operador-expand {
  padding: 0 2rem 2rem;
  border-top: 1px solid var(--border);
  margin-top: 0.5rem; padding-top: 1.5rem;
  animation: expandFade 0.35s ease;
}
@keyframes expandFade { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: translateY(0); } }
.operador-expand p { margin-bottom: 1rem; }
.operador-skills { display: flex; flex-wrap: wrap; gap: 0.5rem; }

/* ---------- Service subpages: checklist + process ---------- */
.check-list { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem 2rem; margin-top: 2.5rem; }
.check-list li { display: flex; gap: 0.75rem; align-items: flex-start; color: var(--text-secondary); }
.check-list li svg { flex-shrink: 0; width: 20px; height: 20px; stroke: var(--accent); margin-top: 0.15rem; }

.process-steps { margin-top: 2.5rem; }
.process-step { display: flex; gap: 1.75rem; padding: 1.75rem 0; border-top: 1px solid var(--border); }
.process-step:last-child { border-bottom: 1px solid var(--border); }
.process-step-num { font-family: 'Heebo', sans-serif; font-weight: 800; font-size: 1.5rem; color: var(--text-tertiary); flex-shrink: 0; width: 50px; }
.process-step-title { font-family: 'Heebo', sans-serif; font-weight: 700; font-size: 1.125rem; margin-bottom: 0.4rem; color: var(--text); }
.process-step-desc { color: var(--text-secondary); }

.related-cases { display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; margin-top: 2.5rem; }
.service-hero { padding-bottom: 2rem; }
.service-breadcrumb { color: var(--text-tertiary); font-size: 0.875rem; margin-bottom: 1.5rem; }
.service-breadcrumb a { color: var(--text-tertiary); transition: color 0.2s ease; }
.service-breadcrumb a:hover { color: var(--accent); }

/* ---------- Quote block ---------- */
.quote-block {
  border-left: 3px solid var(--accent);
  padding-left: 2rem;
  margin: 3rem 0;
}
.quote-block p { font-size: 1.25rem; color: var(--text); font-family: 'Heebo', sans-serif; font-weight: 500; }

/* ---------- Legal / Privacy page ---------- */
.legal-section { margin-bottom: 2.5rem; }
.legal-section h2 { font-size: 1.375rem; margin-bottom: 0.9rem; }
.legal-section p, .legal-section li { color: var(--text-secondary); margin-bottom: 0.75rem; }
.legal-section li { padding-left: 1.25rem; position: relative; }
.legal-section li::before { content: '—'; position: absolute; left: 0; color: var(--accent); }
.legal-toc { border: 1px solid var(--border); border-radius: var(--radius); padding: 1.5rem 2rem; margin-bottom: 3rem; background: var(--surface); }
.legal-toc a { display: block; padding: 0.4rem 0; color: var(--text-secondary); }
.legal-toc a:hover { color: var(--accent); }

.legal-table-wrap { overflow-x: auto; margin-bottom: 1.5rem; }
.legal-table { width: 100%; border-collapse: collapse; font-size: .875rem; }
.legal-table th, .legal-table td { text-align: left; padding: .65rem .9rem; border-bottom: 1px solid var(--border); vertical-align: top; }
.legal-table th { color: var(--text); font-family: 'Heebo', sans-serif; font-weight: 700; font-size: .8125rem; white-space: nowrap; }
.legal-table td { color: var(--text-secondary); }

/* ---------- Final CTA ---------- */
.cta-final { text-align: center; }
.cta-final .btn-row { justify-content: center; margin-top: 2rem; }
.cta-final-note { margin-top: 1.5rem; color: var(--text-tertiary); font-size: 0.875rem; }

/* ---------- Footer ---------- */
.footer { border-top: 1px solid var(--border); padding-block: 4rem 2.5rem; background: var(--surface-alt); }
.footer-grid { display: grid; grid-template-columns: 1.2fr 1fr 1fr 1fr 1fr; gap: 2rem; }
.footer-brand { display: flex; align-items: center; gap: 0.6rem; font-family: 'Heebo', sans-serif; font-weight: 700; margin-bottom: 1rem; }
.footer-brand svg { width: 26px; height: 26px; }
.footer-mark { transition: transform 0.6s cubic-bezier(0.34,1.56,0.64,1); transform-origin: center; }
.footer-mark.spun { transform: rotate(360deg); }
.footer-tagline { color: var(--text-tertiary); font-size: 0.9375rem; max-width: 280px; }
.footer-col h4 { font-size: 0.8125rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-tertiary); margin-bottom: 1rem; font-weight: 600; }
.footer-col a { display: block; color: var(--text-secondary); font-size: 0.9375rem; margin-bottom: 0.65rem; transition: color 0.2s ease; }
.footer-col a:hover { color: var(--accent); }
/* "Gestionar cookies" es una ACCIÓN (reabre el modal de preferencias), no una
   navegación — <button> real, mismo aspecto que los links del footer. */
.footer-col button { display: block; width: auto; text-align: left; color: var(--text-secondary); font-size: 0.9375rem; margin-bottom: 0.65rem; transition: color 0.2s ease; cursor: pointer; }
.footer-col button:hover { color: var(--accent); }
.footer-bottom {
  display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 1rem;
  margin-top: 3.5rem; padding-top: 1.75rem; border-top: 1px solid var(--border);
  color: var(--text-tertiary); font-size: 0.8125rem;
}
.footer-easter-egg {
  opacity: 0; transform: translateY(6px);
  transition: opacity 0.5s ease, transform 0.5s ease;
  color: var(--accent); font-size: 0.8125rem; margin-top: 0.5rem;
}
.footer-easter-egg.show { opacity: 1; transform: translateY(0); }

/* Bloque social — deliberadamente ligero: un solo perfil hoy (LinkedIn), así que NO es
   una columna más de .footer-grid (rompería el balance 1.2fr/1fr×4) sino un bloque
   pequeño debajo del tagline/easter-egg, dentro de la misma columna de marca.
   .footer-socials en flex por diseño: añadir más perfiles en el futuro (Instagram,
   YouTube, X) es solo añadir otro <a class="footer-social-link">, sin tocar layout. */
.footer-social-label {
  margin-top: 1.25rem;
  font-size: 0.8125rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-tertiary);
  font-weight: 600;
}
.footer-socials { display: flex; flex-wrap: wrap; gap: 0.75rem; margin-top: 0.75rem; }
.footer-social-link {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  color: var(--text-secondary);
  font-size: 0.875rem;
  font-weight: 500;
  transition: color 0.2s ease, transform 0.2s ease;
}
.footer-social-link svg { width: 18px; height: 18px; flex-shrink: 0; }
.footer-social-link:hover { color: var(--accent); transform: translateY(-1px); }

/* ---------- Floating WhatsApp button ---------- */
.whatsapp-float {
  position: fixed; right: 1.5rem; bottom: 1.5rem; z-index: 90;
  width: 60px; height: 60px; border-radius: 50%;
  background: #25D366; color: #fff;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 8px 24px rgba(0,0,0,0.35);
  transition: transform 0.25s ease, box-shadow 0.25s ease, opacity 0.2s ease;
}
/* El pulso vive en un ::after compuesto (transform + opacity) en vez de animar box-shadow.
   Animar box-shadow repinta el botón en cada frame durante toda la sesión — es una de las
   dos animaciones que PageSpeed marca como no compuestas. El anillo original iba de
   spread 0 a spread 10px sobre un círculo de 60px, es decir de radio 30 a 40: exactamente
   un scale(1) -> scale(1.3333). Y como rgba(37,211,102) ES el verde del propio botón, un
   círculo relleno detrás se ve idéntico a un anillo: la parte que cae sobre el botón es
   verde sobre el mismo verde (invisible) y solo asoma el borde que se expande. */
.whatsapp-float::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: #25D366;
  z-index: -1;
  pointer-events: none;
  animation: whatsappPulse 2.8s ease-in-out infinite;
}
.whatsapp-float svg { width: 30px; height: 30px; }
.whatsapp-float:hover { transform: translateY(-3px) scale(1.05); box-shadow: 0 12px 32px rgba(0,0,0,0.4); }
.whatsapp-float:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
@keyframes whatsappPulse {
  0%, 100% { transform: scale(1); opacity: 0.4; }
  50% { transform: scale(1.3333); opacity: 0; }
}

/* ---------- Partners marquee ----------
   Logos sueltos (sin cards), blancos/monocromos, flotando sobre el mismo fondo oscuro
   del hero para que hero + social proof se lean como una sola apertura visual. */
/* Trust strip compacta: label + logos en una sola fila horizontal en desktop, para que
   ocupe lo mínimo entre Hero y Servicios (~130-160px de alto, no un capítulo aparte). */
.marquee-section {
  background: var(--bg);
  display: flex;
  align-items: center;
  gap: clamp(1.5rem, 4vw, 3rem);
  padding-block: clamp(2.25rem, 3.6vw, 2.75rem);
  padding-left: var(--pad-inline);
}
.marquee-label { flex-shrink: 0; margin: 0; white-space: nowrap; }
.marquee-viewport { flex: 1; min-width: 0; overflow: hidden; position: relative; mask-image: linear-gradient(90deg, transparent, black 8%, black 92%, transparent); -webkit-mask-image: linear-gradient(90deg, transparent, black 8%, black 92%, transparent); }
/* Duración escalada de 38s a 50.67s (×8/6) al pasar de 6 a 8 logos por mitad — el
   recorrido físico (translateX(-50%)) crece con el contenido, así que sin este ajuste el
   marquee se percibiría acelerado. Mismo linear infinite, mismo mecanismo. */
.marquee-track { display: flex; align-items: center; gap: clamp(2.75rem, 7vw, 5.5rem); width: max-content; animation: marqueeScroll 50.67s linear infinite; }
.marquee-track:hover { animation-play-state: paused; }
@keyframes marqueeScroll { from { transform: translateX(0); } to { transform: translateX(-50%); } }
.marquee-item {
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  height: clamp(30px, 3.4vw, 42px);
}
.marquee-item img {
  width: auto;
  max-width: 100%;
  height: 100%;
  object-fit: contain;
  filter: grayscale(1) brightness(0) invert(1);
  opacity: 0.7;
  transition: opacity 0.3s ease;
}
.marquee-item:hover img { opacity: 1; }

/* ---------- Partners tecnológicos (home, segunda trust strip) ----------
   Reutiliza el motor del marquee superior al 100% (.marquee-viewport, .marquee-track,
   @keyframes marqueeScroll, mask-image, reduced-motion) — cero JS nuevo, cero keyframes
   nuevas. Los únicos overrides son los que exige el brief: fondo claro (en vez del oscuro
   del marquee superior), slot de logo fijo con object-fit:contain (los 5 assets ya vienen
   normalizados a canvas 600×300, así que una única regla .partner-tech-logo basta — sin
   modifiers por marca), sin el filtro blanco/grayscale del marquee superior (aquí se piden
   colores oficiales), y sentido de giro opuesto reutilizando la MISMA keyframe existente
   vía animation-direction:reverse.

   El label ("Partners tecnológicos") ya NO vive dentro de este bloque — ahora es un
   header propio (.technology-partners-header) fuera de .marquee-section--technology, así
   que esta franja se dedica solo a logos (ver .technology-partners-block más abajo). */
.technology-partners-block { background: #fff; }
.technology-partners-header { padding-top: clamp(32px, 4vw, 48px); padding-bottom: clamp(18px, 2vw, 26px); }
#technology-partners-title { margin-bottom: 0; }
.marquee-section--technology {
  background: #fff;
  padding-block: clamp(26px, 3vw, 34px) clamp(30px, 3.4vw, 38px);
}
/* Duración calculada, no copiada: a 1440px el marquee superior recorre ~1645px (8 items +
   8 gaps a clamp máx. 88px) en 50.67s ≈ 32.5px/s. Esta franja recorre ~1296px (5 slots a
   clamp máx. 230px + 5 gaps a clamp máx. 68px) — a la misma velocidad, 1296/32.5 ≈ 40s,
   dentro del rango 30-40s que pide el brief. */
.marquee-track--technology {
  gap: clamp(34px, 4vw, 68px);
  animation-duration: 40s;
  animation-direction: reverse;
}
.marquee-item--technology {
  width: clamp(180px, 14vw, 230px);
  height: clamp(76px, 6vw, 96px);
}
#technology-partners .partner-tech-logo {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: center;
  max-width: none;
  max-height: none;
  filter: none;
  opacity: 1;
}
/* Hooks .partner-tech-logo--google/--meta/--hubspot/--klaviyo/--shopify: existen en el
   HTML (en vez de nth-child) para poder ajustar un partner puntual sin tocar los demás.
   Sin valores propios por ahora: los 5 assets ya se recortaron a su bounding box real
   +10% de margen (Google/HubSpot tenían solo 38% de relleno horizontal en su canvas
   original de 600×300 frente al 80% de Klaviyo — medido con PIL, no a ojo). Tras el
   recorte los 5 rellenan ~83% de su propio canvas de forma consistente, así que la MISMA
   caja + object-fit:contain + centrado ya reparte el peso visual con equilibrio, sin
   necesitar max-height distinto por partner. Si en el futuro alguno necesita un ajuste
   fino puntual, este es el selector — nunca nth-child. */

@media (max-width: 900px) {
  .marquee-track--technology { gap: clamp(28px, 4vw, 48px); }
}

/* ---------- Decisión UX final: Partners tecnológicos NO aparece en mobile ----------
   Se oculta el WRAPPER completo (.technology-partners-block), no solo el track — así no
   queda ni el header/label, ni paddings, ni una altura residual reservada. Con
   display:none el elemento no genera caja (0×0, sin margin collapse raro alrededor) y dos
   efectos colaterales quedan resueltos gratis, sin JS ni lógica extra: (1) las <img
   loading="lazy"> de dentro nunca se descargan, porque un elemento display:none no tiene
   layout box con el que el navegador pueda decidir "está cerca del viewport"; (2) app.js
   no tiene ninguna lógica sobre .marquee-track--technology (confirmado por grep, es
   animación 100% CSS), así que no hay nada que proteger de un contenedor a 0px de ancho.
   Tablet (>900px, ver el bloque de arriba) y desktop conservan la sección exactamente
   como estaba — este display:none vive solo aquí, en <=767px. */
@media (max-width: 767px) {
  .technology-partners-block { display: none; }
}

/* ---------- Services marquee (violeta, transición Form → Footer) ----------
   Reutiliza el mismo motor que el marquee de arriba (.marquee-viewport, .marquee-track,
   @keyframes marqueeScroll, mask-image, reduced-motion) — cero JS/librerías nuevas, solo
   un modifier de tema + su propia velocidad (el contenido es texto, no logos, así que no
   comparte proporciones con --technology). El gradiente violeta anima muy sutil (posición,
   no tamaño ni blur) para dar sensación de energía sin caer en neón/glow exagerado. */
.marquee-section--services {
  padding-left: 0; padding-block: 14px; /* con el font-size/line-height de .marquee-item--services
    esto da ~50-56px de alto total, dentro del target 48-56px */
  position: relative;
  overflow: hidden;
  background: #4C1D95; /* color de arranque del gradiente: si el ::before no pintara
    (sin soporte, o durante un repaint), la franja nunca queda transparente */
}
/* El gradiente animado se mueve por transform en un ::before, no por background-position.
   Animar background-position obliga a repintar la franja entera en cada frame durante toda
   la sesión — es la segunda animación que PageSpeed marca como no compuesta.
   Equivalencia exacta: background-size:300% 300% pintaba el gradiente en una caja de 3w×3h
   y background-position 0%->100% lo desplazaba 2 anchos hacia la izquierda. Aquí el ::before
   ES esa caja de 3w×3h (top:-100% la centra igual que la posición vertical 50%), así que el
   ángulo de 120deg se calcula sobre la misma geometría, y translateX(-66.6667%) de su propio
   ancho equivale a esos mismos 2 anchos de la sección. Posicionado en absoluto a propósito:
   .marquee-section es flex y un ::before en flujo se convertiría en flex item. */
.marquee-section--services::before {
  content: '';
  position: absolute;
  top: -100%;
  left: 0;
  width: 300%;
  height: 300%;
  background: linear-gradient(120deg, #4C1D95, var(--accent), var(--accent-hover), var(--accent));
  animation: marqueeGradientShift 14s ease-in-out infinite;
  pointer-events: none;
}
.marquee-section--services > * { position: relative; } /* por encima del gradiente */
@keyframes marqueeGradientShift {
  0%, 100% { transform: translateX(0); }
  50% { transform: translateX(-66.6667%); }
}
.marquee-track--services { gap: 0; animation-duration: 26s; }
.marquee-item--services {
  text-transform: uppercase;
  font-weight: 600;
  font-size: clamp(1.125rem, 2vw, 1.375rem);
  color: #FFFFFF;
  white-space: nowrap;
  padding-inline: 0.6rem;
  text-shadow: 0 0 14px rgba(255, 255, 255, 0.22); /* soft inner glow, no bloom */
}
.marquee-sep { color: rgba(255, 255, 255, 0.5); padding-inline: 0.4rem; font-weight: 400; }
/* prefers-reduced-motion ya congela esta animación (y la del track) vía la regla global
   *,::before,::after{animation-duration:0.01ms!important} — no hace falta repetirla aquí. */

/* ---------- Section light (Globant-style white block) ---------- */
.section-light {
  --bg: #F3F4F1;
  --surface: #FFFFFF;
  --surface-alt: #ECEEEA;
  --surface-hover: #FFFFFF;
  --border: rgba(10,12,15,0.1);
  --border-hover: rgba(10,12,15,0.22);
  --text: #0A0C0F;
  --text-secondary: #4B5563;
  --text-tertiary: #6B7280;
  background: var(--bg);
  color: var(--text);
}
.section-light .card { box-shadow: 0 2px 12px rgba(10,12,15,0.05); }
.section-light .card:hover { box-shadow: 0 16px 32px rgba(10,12,15,0.09); }


.viz-strategy-dot { animation: vizTravel 3.5s ease-in-out infinite; }
@keyframes vizTravel {
  0%   { transform: translate(4px, 70px); }
  25%  { transform: translate(50px, 22px); }
  50%  { transform: translate(96px, 70px); }
  75%  { transform: translate(140px, 108px); }
  100% { transform: translate(4px, 70px); }
}
.viz-strategy-line { stroke-dasharray: 6 6; animation: vizDash 2s linear infinite; }
@keyframes vizDash { to { stroke-dashoffset: -24; } }

.viz-data-bar { transform-origin: bottom; animation: vizGrow 2.4s ease-in-out infinite; }
.viz-data-bar:nth-child(1) { animation-delay: 0s; }
.viz-data-bar:nth-child(2) { animation-delay: 0.2s; }
.viz-data-bar:nth-child(3) { animation-delay: 0.4s; }
.viz-data-bar:nth-child(4) { animation-delay: 0.6s; }
@keyframes vizGrow { 0%, 100% { transform: scaleY(0.55); } 50% { transform: scaleY(1); } }

.viz-exec-gear { transform-origin: center; transform-box: fill-box; animation: vizSpin 6s linear infinite; }
.viz-exec-spark { animation: vizSpark 1.8s ease-in-out infinite; transform-origin: center; transform-box: fill-box; }
@keyframes vizSpin { to { transform: rotate(360deg); } }
@keyframes vizSpark { 0%, 100% { opacity: 0.3; transform: scale(0.8); } 50% { opacity: 1; transform: scale(1.15); } }

/* ---------- Team photo card (Operadores) ---------- */
.operador-photo-wrap {
  aspect-ratio: 4 / 4.5; border-radius: 16px; overflow: hidden; margin-bottom: 1.5rem;
  background: var(--surface-alt); border: 1px solid var(--border);
  position: relative;
}
.operador-photo-wrap img {
  width: 100%; height: 100%; object-fit: cover; object-position: center top;
  filter: grayscale(1) contrast(1.05);
  transition: transform 0.5s cubic-bezier(0.16,1,0.3,1), filter 0.4s ease;
}
.card:hover .operador-photo-wrap img { transform: scale(1.05); filter: grayscale(0.4) contrast(1.05); }
.operador-photo-wrap::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(180deg, transparent 60%, rgba(var(--bg-rgb), 0.6) 100%);
  pointer-events: none;
}

/* ---------- Lead capture form ---------- */
/* Con el eyebrow ("Empecemos" en Home, "Tu turno" en Casos de Éxito) retirado del HTML
   en las dos páginas que comparten #contacto, el h2 pasa a ser el primer elemento —
   este margin sustituye el respiro que antes daba el eyebrow, sin dejarlo pegado al
   lede (0 gap real, heredado del reset global). Selector por ID: afecta a ambas
   páginas por diseño (misma estructura, mismo ajuste). */
#contacto h2 { margin-bottom: 1.5rem; }
.contact-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 4rem; align-items: start; text-align: left; }
.contact-steps { list-style: none; margin-top: 2rem; display: flex; flex-direction: column; gap: 1.5rem; }
.contact-steps li { display: flex; gap: 1rem; align-items: flex-start; }
.contact-step-num {
  flex-shrink: 0; width: 32px; height: 32px; border-radius: 10px;
  background: rgba(var(--accent-rgb), 0.1); border: 1px solid rgba(var(--accent-rgb), 0.3);
  color: var(--accent); font-family: 'Heebo', sans-serif; font-weight: 700; font-size: 0.875rem;
  display: flex; align-items: center; justify-content: center;
}
.contact-step-title { font-weight: 600; color: var(--text); margin-bottom: 0.2rem; }
.contact-step-desc { color: var(--text-secondary); font-size: 0.9375rem; }

.lead-form {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  padding: clamp(1.75rem, 3vw, 2.5rem);
}
/* .nav mide ~96.5px en top de página / ~85.6px con .nav.scrolled (medido, no estimado) —
   112px cubre ambos estados con margen de aire antes del h3 del formulario. */
#lead-form { scroll-margin-top: 112px; }
.lead-form h3 { margin-bottom: 1.75rem; }
.lead-form h3 .text-accent { font-weight: 800; }
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 1.25rem; }
.form-field { margin-bottom: 1.25rem; }
.form-field label {
  display: block; font-family: 'Heebo', sans-serif; font-size: 0.75rem; font-weight: 600;
  letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-tertiary); margin-bottom: 0.5rem;
}
.form-field input, .form-field select {
  width: 100%; padding: 0.85rem 1rem; border-radius: 12px;
  background: var(--surface-alt); border: 1px solid var(--border); color: var(--text);
  font-family: 'Inter', sans-serif; font-size: 0.9375rem; min-height: 48px;
  transition: border-color 0.2s ease, background 0.2s ease;
  appearance: none; -webkit-appearance: none;
}
.form-field select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23A6ACB6' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 1rem center; padding-right: 2.5rem;
}
.form-field input::placeholder { color: var(--text-tertiary); }
.form-field input:focus, .form-field select:focus { outline: none; border-color: var(--accent); background: var(--surface); }
.form-field input:focus-visible, .form-field select:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.form-check { display: flex; align-items: flex-start; gap: 0.75rem; margin-bottom: 1rem; }
.form-check input[type="checkbox"] {
  flex-shrink: 0; width: 20px; height: 20px; margin-top: 0.15rem;
  accent-color: var(--accent); cursor: pointer;
}
.form-check label { color: var(--text-secondary); font-size: 0.875rem; line-height: 1.5; cursor: pointer; }

.form-submit { width: 100%; justify-content: center; margin-top: 0.5rem; }
.form-status { margin-top: 1rem; font-size: 0.875rem; color: var(--accent); text-align: center; }
.form-status[hidden] { display: none; }
.form-note { margin-top: 1rem; font-size: 0.8125rem; color: var(--text-tertiary); text-align: center; }

/* ---------- Responsive ---------- */
@media (max-width: 1024px) {
  .footer-grid { grid-template-columns: 1fr 1fr; }
  .contact-grid { grid-template-columns: 1fr; gap: 2.5rem; }
}

@media (max-width: 900px) {
  .hero-video-bg { width: min(190vw, 1100px); }
  .hero-content { padding-left: clamp(32px, 4vw, 48px); padding-right: clamp(24px, 3vw, 40px); }
  .hero-copy { width: min(65vw, 620px); }
  .marquee-section { padding-block: clamp(2.75rem, 5.6vw, 3.25rem); gap: 1.5rem; }
  .marquee-item { height: clamp(26px, 3.8vw, 32px); }
  .marquee-track { gap: clamp(2rem, 5vw, 3rem); }
  .grid-operadores { grid-template-columns: repeat(2, 1fr); }
  .grid-operadores > *,
  .grid-operadores > :nth-child(4):nth-last-child(2),
  .grid-operadores > :nth-child(5):nth-last-child(1) { grid-column: auto / span 1; }
  .check-list, .related-cases { grid-template-columns: 1fr; }

/* Móvil: una sola columna. Va después del bloque de 900px a propósito: con la misma
   especificidad, gana la última regla, así que declararla antes la anulaba. */
@media (max-width: 640px) {
  .grid-operadores { grid-template-columns: 1fr; }
}
  .process-step { gap: 1.25rem; }
  .grid-casos { grid-template-columns: 1fr; }
  .grid-casos .case-featured, .grid-casos .case-standard { grid-column: span 1; }
  .stats-row { grid-template-columns: 1fr; gap: 1.5rem; }
}

@media (max-width: 940px) {
  /* Barra mobile/tablet de 3 zonas (patrón copilot.agency, solo UX — no branding/colores):
     toggle a la izquierda, logo VERDADERAMENTE centrado respecto al viewport (por eso
     1fr/auto/1fr y no auto/1fr/auto: con columnas laterales iguales, el brand queda
     centrado aunque toggle y CTA tengan anchos distintos), CTA a la derecha. .nav-links
     es position:fixed, así que queda fuera de este grid (no ocupa columna) y sigue siendo
     el drawer de siempre. Este bloque es la base compartida tablet+mobile; el breakpoint
     de 767px de abajo la compacta más para phones. */
  .nav-inner {
    position: relative;
    display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 0.5rem;
    padding-inline: clamp(0.875rem, 4vw, 1.25rem);
  }
  /* Centrado del brand por position:absolute, no por grid: el grid (1fr/auto/1fr) ya
     centraba la CAJA del brand respecto al viewport correctamente, pero el bug reportado
     persistía — así que en vez de seguir iterando sobre el mecanismo de grid, se sustituye
     por el método más robusto posible: el brand sale del flujo del grid por completo y se
     centra en los DOS ejes directamente contra .nav-inner (ya position:relative arriba),
     sin depender de cómo el grid calcule su fila/columna. Con esto los anchos distintos de
     toggle y CTA no pueden afectar el centrado horizontal, y el centrado vertical deja de
     depender de que .nav-inner tenga la altura "correcta" en cada estado (abierto/cerrado/
     scrolled) — siempre es 50%/50% de la propia barra. */
  .brand {
    position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
    display: inline-flex; align-items: center; justify-content: center;
    margin: 0; gap: 0.4rem; min-width: 0;
    font-size: clamp(0.8125rem, 3.6vw, 0.9375rem); white-space: nowrap;
  }
  .brand-mark { width: 26px; height: 26px; }
  .nav-links { position: fixed; top: 0; right: 0; height: 100vh; width: min(320px, 80vw);
    background: var(--surface); border-left: 1px solid var(--border);
    flex-direction: column; align-items: flex-start; justify-content: center;
    padding: 2rem; gap: 1.75rem;
    transform: translateX(100%); transition: transform 0.3s cubic-bezier(0.16,1,0.3,1);
  }
  .nav-links[data-open="true"] { transform: translateX(0); }
  .nav-links a { font-size: 1.0625rem; }
  .nav-links .btn { width: 100%; }
  .nav-dropdown__trigger { font-size: 1.0625rem; }
  .nav-toggle { display: flex; grid-column: 1; justify-self: start; }
  .nav-mobile-cta {
    grid-column: 3; justify-self: end; display: inline-flex; align-items: center; justify-content: center;
    padding: 0.4rem 0.8rem; border-radius: 999px; background: var(--accent); color: #FFFFFF;
    font-family: 'Heebo', sans-serif; font-weight: 600; font-size: clamp(0.75rem, 3.2vw, 0.8125rem);
    white-space: nowrap; transition: background 0.2s ease;
  }
  .nav-mobile-cta:hover, .nav-mobile-cta:focus-visible { background: var(--accent-hover); }
}

/* ---------- Mobile phones (<=767px): header compacto de 68px + hero pegado al header +
   drawer sin centrado vertical. Todo lo de arriba (940px) sigue aplicando como base
   (tablet 768-940 se queda con esa versión intermedia, sin esta compactación extra —
   brief: "no aplicar ciegamente mobile CSS a iPad"); esto solo AJUSTA valores puntuales
   para el rango de teléfono real. Una sola fuente de verdad por propiedad, sin reglas
   pisándose: cada selector de aquí abajo gana por especificidad de breakpoint (767<940),
   no por duplicar el mismo selector varias veces. */
@media (max-width: 767px) {
  :root { --mobile-nav-height: 68px; }

  /* Header: altura fija de 68px en vez de padding vertical (que era la causa real de que
     el header midiera ~96px) + safe-area para notch/dynamic island. */
  .nav, .nav.scrolled { padding-block: 0; padding-top: env(safe-area-inset-top, 0px); }
  .nav-inner { min-height: var(--mobile-nav-height); padding-inline: 16px; gap: 0.5rem; }

  /* z-index:2 en las 3 zonas del header: quedan SIEMPRE por encima del drawer (z-index:1
     de abajo), así que cuando el menú abre, la barra [hamburger/brand/CTA] no desaparece
     ni se tapa — sigue siendo la misma barra, solo cambia lo que hay debajo. Esto es lo
     que permite reusar un único header en vez de duplicar uno para el estado abierto.
     CRÍTICO: .brand NO puede llevar position:relative aquí — ese era exactamente el bug.
     .brand ya es position:absolute (bloque de 940px, arriba) para centrarse en los dos
     ejes contra .nav-inner; esta regla, escrita en una vuelta anterior SOLO para el
     z-index, pisaba silenciosamente ese absolute con relative (misma especificidad,
     .brand aparece más tarde en el archivo → gana) y convertía left:50%/top:50%/
     transform:translate(-50%,-50%) en un desplazamiento RELATIVO a su posición normal en
     el grid en vez de un centrado absoluto — eso es lo que se veía como "el brand salta a
     una segunda fila". z-index no necesita position:relative aquí porque position:absolute
     ya establece contexto de apilamiento por sí solo. */
  .nav-toggle, .nav-mobile-cta { position: relative; z-index: 2; }
  .brand { z-index: 2; }
  .nav-toggle span, .nav-toggle::before, .nav-toggle::after { width: 24px; }

  /* Causa real de que el brand se viera "demasiado arriba": Heebo tiene métricas
     verticales muy generosas (pensadas para convivir con hebreo) y el body hereda
     line-height:1.65 — ese interlineado alto desplaza ópticamente el glyph dentro de su
     propia caja de línea aunque .nav-inner ya centre el bloque entero con align-items:
     center. line-height:1 en el propio .brand corta esa caja para que abrace el texto de
     verdad, sin tocar el font-size ya aprobado. .brand-mark no necesita el mismo ajuste:
     al ser hijo directo de un flex container, el spec ya lo "blockifica" (sin fantasma de
     descendente tipo elemento-inline). */
  .brand { font-size: clamp(14px, 3.6vw, 16px); font-weight: 700; line-height: 1; gap: 6px; margin: 0; }
  .brand-mark { width: 20px; height: 20px; }

  .nav-mobile-cta { height: 40px; padding-inline: clamp(12px, 4vw, 18px); font-size: clamp(12px, 3.2vw, 15px); }

  /* ===== Drawer: fullscreen real (100vw/100dvh), no franja de la Home detrás. Ya no
     necesita border-left (eso era el look "sidebar" que había que quitar) ni el flex-gap
     genérico (el ritmo ahora lo da el padding-block + divisor de cada fila). ===== */
  .nav-links {
    width: 100vw;
    height: 100dvh;
    border-left: none;
    justify-content: flex-start;
    padding-top: calc(var(--mobile-nav-height) + env(safe-area-inset-top, 0px) + 20px);
    padding-inline: 24px;
    padding-bottom: max(24px, calc(env(safe-area-inset-bottom, 0px) + 16px));
    gap: 0;
    z-index: 1;
    overflow-y: auto; /* red de seguridad: con el accordion de Servicios abierto en un
      iPhone SE (568px de alto) el contenido puede superar el viewport — nunca debe cortarse */
    /* El scroll del drawer no se propaga al documento de detrás: sin esto, al llegar al
       final de la lista el gesto seguía "empujando" la página (scroll chaining), que es
       justo la sensación de fondo en movimiento que hay que eliminar. Complementa —no
       sustituye— al scroll lock del body que hace app.js. */
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    opacity: 0;
    transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.3s ease;
  }
  .nav-links[data-open="true"] { opacity: 1; }

  /* .nav-pill (Servicios▾/Operadores/Casos de éxito/Insights, el orden y naming de
     desktop/tablet) deja de ser lo que se ve en mobile: la información arquitectura
     final de mobile es distinta (orden propio, "Nosotros" en vez de "Operadores",
     Growth Strategy como item principal, Contacto, sin Insights) y vive en su propio
     bloque, .nav-mobile-menu, añadido como hermano de .nav-pill dentro de .nav-links —
     no se reordena/relabela el mismo DOM porque eso rompería desktop/tablet, que deben
     seguir mostrando exactamente lo de siempre. El botón "Hablemos" grande de dentro del
     drawer tampoco se repite aquí (ya está arriba, en el header) — solo se oculta. */
  .nav-pill,
  .nav-links > .btn.btn-primary { display: none; }
  .nav-mobile-menu { display: contents; }

  /* Navegación principal: escala editorial (32-42px fluido), cada fila con su propio
     padding-block (área táctil real, no solo line-height) + divisor. :not(.btn) excluye
     la CTA de auditoría (su propio estilo va más abajo, sin divisor) y :not(.nav-mobile-
     email) excluye el email secundario — ambos son <a> hijos directos de .nav-mobile-menu
     también, pero no deben heredar la escala/divisor de la navegación principal. */
  .nav-mobile-menu > a:not(.btn):not(.nav-mobile-email),
  .nav-dropdown { width: 100%; border-bottom: 1px solid rgba(255, 255, 255, 0.55); }
  .nav-mobile-menu > a:not(.btn):not(.nav-mobile-email),
  .nav-dropdown__trigger {
    font-size: clamp(2rem, 9vw, 2.625rem); /* 32-42px */
    font-weight: 500;
    line-height: 1.1;
    color: var(--text); /* #F4F5F7: navegación principal en blanco casi puro, no el gris
      secundario que usaba antes — a esta escala editorial necesita el contraste alto */
  }
  /* padding-block va en el <a>/<button> real, no en el <div class="nav-dropdown"> que lo
     envuelve — así el área táctil de "Servicios" es la fila entera, igual que las demás,
     y no solo la línea de texto (el wrapper solo aporta el ancho:100% y el divisor). */
  .nav-mobile-menu > a:not(.btn):not(.nav-mobile-email) { padding-block: 26px; }
  .nav-dropdown__trigger { padding-block: 26px; gap: 1rem; }
  .nav-dropdown__chevron { width: 22px; height: 22px; }

  /* Submenu: un nivel visual por debajo del principal a propósito (18-21px, color
     secundario) — si usara el mismo tamaño de arriba dejaría de leerse como jerarquía. */
  .nav-dropdown__panel { padding-left: 14px; gap: 0.375rem; margin-top: 0; }
  .nav-dropdown.is-open .nav-dropdown__panel { margin-top: 0.85rem; }
  .nav-dropdown__panel a {
    font-size: clamp(1.125rem, 4vw, 1.3125rem); /* 18-21px */
    font-weight: 400;
    color: var(--text-secondary); /* #A6ACB6, no el --text-tertiary más apagado de base */
    padding-block: 0.4rem;
    padding-left: 0;
  }

  /* CTA del drawer ("Solicita tu auditoría gratuita"): grande y en el flujo normal
     (nunca margin-top:auto empujándolo al fondo del 100dvh — eso es justo lo que volvía a
     crear una zona vacía enorme). Ya NO es "Hablemos" (ese vive en el header, arriba, y
     con esta CTA de alta intención comercial no tiene sentido repetirlo dos veces). */
  .nav-links .btn {
    width: 100%;
    height: 64px;
    padding-block: 0;
    padding-inline: 24px; /* mismos gutters que el resto de la navegación */
    font-size: 1.25rem; /* 20px, dentro de 18-21px */
    margin-top: 40px;
    white-space: normal; /* en 320px puede partirse en 2 líneas, nunca truncarse */
    line-height: 1.15;
  }

  /* Email corporativo: contacto secundario bajo la CTA, jerarquía deliberadamente menor
     (no debe competir con la CTA de auditoría ni con los links principales). */
  .nav-mobile-email {
    display: block;
    width: 100%;
    text-align: center;
    margin-top: 24px;
    font-size: 15px;
    font-weight: 400;
    color: rgba(255, 255, 255, 0.65);
  }

  /* Backdrop: capa de seguridad adicional durante la animación de entrada/salida (el
     drawer ya es 100vw así que en reposo no queda franja que oscurecer, pero durante los
     ~300ms de transform sí puede asomar un resquicio). app.js añade/quita .menu-open en
     <body> al abrir/cerrar. z-index:99, justo debajo de .nav (100). */
  body.menu-open::before {
    content: ''; position: fixed; inset: 0; z-index: 99;
    background: rgba(0, 0, 0, 0.55);
  }
  body.menu-open .whatsapp-float,
  body.menu-open .cookie-fab { opacity: 0; visibility: hidden; pointer-events: none; transition: opacity 0.2s ease; }

  /* Hero: el hueco enorme no era el padding-top en sí, era combinarlo con
     align-items:center dentro de una caja de hasta 760px — el copy se centraba muy por
     debajo del header en vez de empezar justo tras él. flex-start + una caja más baja
     resuelve ambas causas a la vez. Sin cambios respecto a la pasada anterior: aquí solo
     se toca el posicionamiento del loop (ver abajo), no el espaciado ya corregido. */
  /* min-height era la causa real del hueco entre Contáctanos y "Han confiado en
     nosotros": con align-items:flex-start el copy ya arranca pegado al header, así que
     cualquier alto forzado de más (antes clamp(420px,58vh,560px), ~75px por encima de lo
     que el copy real ocupa en 390px) se queda como aire DESPUÉS del CTA, no antes. El
     vídeo es decorativo (position:absolute, no participa en el alto del flujo), así que
     quitar min-height no le quita sitio — el Hero termina exactamente cuando termina su
     contenido + este padding-bottom. */
  .hero {
    align-items: flex-start;
    padding-top: calc(var(--mobile-nav-height) + env(safe-area-inset-top, 0px) + 20px);
    padding-bottom: 2.5rem;
    min-height: 0;
  }
  /* Loop desplazado a la derecha: la causa real es que .hero-video-bg hereda left:67% del
     desktop (ahí tiene sentido, deja sitio al copy en la columna angosta de la izquierda),
     y en mobile nadie lo devolvía a 50%. Verificado con frames reales del vídeo
     (assets/hero/loop-hero.mp4, 1280x640 = exactamente 2:1 igual que la caja): el símbolo
     ya está centrado dentro del propio archivo, así que NO hace falta tocar
     object-position con un focal point custom (sería inerte de todos modos: al coincidir
     el aspect-ratio de la caja con el del vídeo, contain no genera espacio lateral que
     object-position pueda desplazar) — con volver el wrapper a 50% es suficiente. */
  .hero-video-bg { width: min(240vw, 720px); left: 50%; }
  .hero-video { object-position: 50% center; }
  .hero-content { padding-left: clamp(18px, 5vw, 20px); padding-right: clamp(20px, 5vw, 24px); }
  .hero-copy { width: 100%; max-width: 100%; }
  .hero-title { font-size: clamp(2.5rem, 9vw, 3.4rem); }

  /* ===== Trust strip (primera prueba social, justo debajo del Hero): modifier propio,
     no se toca .marquee-section genérico (eso afectaría también a --technology y
     --services). Fila horizontal (label + track), NO columna — el track sigue
     atravesando el viewport como pide el brief, solo se comprime el padding vertical y se
     alinea el label al mismo gutter que el Hero. ===== */
  .marquee-section--trust {
    padding-top: 28px;
    padding-bottom: 32px;
    padding-left: 0;
    gap: 20px;
  }
  .marquee-section--trust .marquee-label {
    text-align: left;
    margin-inline: 0;
    padding-left: clamp(18px, 5vw, 20px); /* mismo eje que .hero-content */
    font-size: 14px;
  }

  /* ===== Contacto: el formulario pasa a ser el "hero de conversión" — pero SOLO en las 2
     páginas donde ese bloque introductorio era relleno genérico repetido (Home tenía
     además los 3 pasos). Auditoría SEO (skill senior-technical-seo-content-architecture):
     esta regla vivía como ".contact-grid > div { display:none }" SIN scope — ocultaba
     también el H2/lede de Operadores y los 6 servicio-*.html, que NUNCA tuvieron los 3
     pasos y cuyo H2 es copy único por página ("¿Tu inversión en medios está comprando
     crecimiento?", etc.) — contenido real, no genérico, que además queda REEMPLAZADO por
     nada en mobile: una regresión de "mobile-first indexing" real, no solo visual (Google
     indexa la versión mobile; ese copy quedaba invisible para el crawl mobile). Ahora la
     clase .contact-intro--compact (solo en index.html y casos_exito.html) es lo único que
     se oculta; los otros 7 conservan su H2/lede propios en mobile, apilados sobre el
     formulario en flujo normal (grid-template-columns:1fr ya los pone en una columna). */
  /* gap real (no 0): en index/casos_exito da igual (el único hijo visible es el form, sin
     hermano con el que dejar hueco), pero en los otros 7 el H2/lede ahora SÍ se ve encima
     del form y necesita separación propia. */
  .contact-grid { grid-template-columns: 1fr; gap: 36px; }
  .contact-grid > .contact-intro--compact { display: none; }
  .lead-form { padding: 0; background: transparent; border: none; }

  /* Ajuste puntual pedido en esta vuelta ("auditar también el inicio de #contacto, no
     asumir que su padding actual sigue funcionando" al desaparecer Partners de por medio
     en mobile) — reduce SOLO el padding-top de la sección (heredaba el genérico de
     .section, ~80px) para que el H2 "Cuéntanos dónde..." entre con más fuerza justo
     después de Scale. No toca el <form> ni su padding-bottom (transición hacia el
     marquee violeta), que no se ha tocado en esta iteración. Solo afecta a index.html y
     casos_exito.html (las únicas 2 páginas con id="contacto" real). */
  #contacto { padding-top: 48px; }

  /* Inputs: 16px+ obligatorio (si no, Safari hace zoom automático al enfocar) — la base
     usaba 0.9375rem=15px, por debajo del umbral. Resto de valores dentro del target de
     "campo grande, táctil, editorial" pedido. */
  .form-field input, .form-field select {
    min-height: 64px;
    padding: 20px 22px;
    border-radius: 22px;
    font-size: 16px;
  }
  .form-row { grid-template-columns: 1fr; gap: 0.85rem; }
  .form-field { margin-bottom: 0.85rem; }
  /* 112px (base) está calibrado para el header alto de desktop/tablet; el header mobile
     ahora mide 68px + safe-area, así que un salto directo a #contacto/#lead-form dejaba
     más aire del necesario antes del H2. */
  #lead-form { scroll-margin-top: calc(var(--mobile-nav-height) + env(safe-area-inset-top, 0px) + 16px); }

  /* Cabecera editorial nueva SOLO para mobile (Home y Casos de éxito, las dos páginas que
     comparten el h3 "El loop de tu crecimiento empieza aquí" que sustituye): el h3 de
     siempre se oculta aquí y sigue intacto en desktop/tablet; lo nuevo es exclusivo de
     este breakpoint, no un rename del mismo elemento. */
  .lead-form > h3 { display: none; }
  .lead-form-mobile-heading {
    display: block;
    font-size: clamp(34px, 9vw, 46px);
    font-weight: 700;
    line-height: 1.05;
    text-align: left;
    margin: 0 0 14px;
  }
  .lead-form-mobile-copy {
    display: block;
    font-size: 19px;
    line-height: 1.45;
    color: var(--text-secondary);
    margin: 0 0 18px;
  }
  .lead-form-mobile-microcopy {
    display: block;
    font-size: 16px;
    font-weight: 600;
    margin: 0 0 24px;
  }

  /* ===== Footer: reduce drásticamente el scroll de cierre. Inicio/Operadores/Casos de
     éxito y los 6 Servicios ya viven en el drawer (Servicios/Casos de éxito/Growth
     Strategy/Nosotros/Contacto) — repetirlos aquí sería la misma información dos veces en
     la misma visita. El símbolo del loop pasa a ser el cierre de marca dominante en vez
     de un icono pequeño junto al texto. ===== */
  .footer { padding-block: 2.5rem 2rem; }
  .footer-grid { grid-template-columns: 1fr; gap: 2rem; text-align: center; }
  .footer-grid > div:nth-child(3) { display: none; }
  /* nth-child(2) ("Navegación") NO se oculta entero: Insights es la ÚNICA página del
     sitio cuyo enlace en mobile vivía solo aquí y en el drawer — y el drawer la quitó a
     propósito (decisión UX explícita de otra vuelta). Ocultar toda la columna dejaba
     blog.html sin NINGÚN link visible en mobile desde 12 de las 20 páginas (auditado con
     lxml: 0 enlaces "mobile-visible" a blog.html en Home, Casos, Operadores, las 6
     páginas de servicio y las legales — solo sobrevivían en los propios artículos). Eso
     es justo lo que la skill de SEO advierte en "Mobile-First SEO": no quitar enlaces
     internos solo por limpieza si de verdad son la única vía de acceso. Se ocultan
     Inicio/Operadores/Casos de éxito (sí redundantes, ya están en el drawer) y se
     mantiene Insights. */
  .footer-grid > div:nth-child(2) a[href="index.html"],
  .footer-grid > div:nth-child(2) a[href="operadores.html"],
  .footer-grid > div:nth-child(2) a[href="casos_exito.html"] { display: none; }

  .footer-brand { flex-direction: column; justify-content: center; gap: 16px; margin-bottom: 0; font-size: 26px; }
  .footer-brand svg { width: 96px; height: 96px; }
  .footer-tagline, .footer-easter-egg, .footer-social-label { display: none; }
  .footer-socials { justify-content: center; margin-top: 8px; }
  .footer-social-link {
    width: 56px; height: 56px; justify-content: center;
    border: 1px solid var(--border); border-radius: 50%;
  }
  .footer-social-link span { display: none; } /* icon-only en mobile, texto sigue accesible por aria-label */
  .footer-social-link svg { width: 24px; height: 24px; }

  .footer-col { text-align: center; }
  .footer-col h4 { display: none; }
  .footer-col a[href^="https://wa.me"] { display: none; } /* WhatsApp ya está en el drawer y en el float */
  .footer-col button { text-align: center; margin-inline: auto; }

  .footer-bottom {
    flex-direction: column; align-items: center; text-align: center; gap: 4px;
    margin-top: 2rem; padding-top: 1.5rem;
  }
  .footer-bottom > span:last-child { display: none; } /* "España · Colombia · Ecuador": desktop lo conserva */
}

@media (max-width: 640px) {
  .card { padding: 1.5rem; }
  .btn { width: 100%; }
  .btn-row { flex-direction: column; align-items: stretch; }
  .case-metrics { gap: 1.25rem; }
  /* Bajo 640px: label y logos apilados (no caben cómodos en una fila), sección aun así compacta */
  .marquee-section { flex-direction: column; align-items: stretch; gap: 0.85rem; padding-block: clamp(1.25rem, 4vw, 1.75rem); padding-left: 0; }
  .marquee-label { text-align: center; margin-inline: auto; white-space: normal; }
  .marquee-item { height: 24px; }
  .marquee-track { gap: clamp(1.75rem, 8vw, 2.5rem); }
  .whatsapp-float { width: 52px; height: 52px; right: 18px; bottom: calc(18px + env(safe-area-inset-bottom, 0px)); }
  .whatsapp-float svg { width: 26px; height: 26px; }
}

/* ==========================================================================
   servicio-growth-strategy.html — namespace .growth-service-* para evitar
   regresiones en el resto del sitio. Reutiliza tokens/componentes globales
   (--accent, .section-light, .section-alt, .btn, .lede, .eyebrow, .card,
   .process-steps, .reveal, .stagger-reveal, .lead-form) allí donde ya
   resuelven el diseño; solo se define CSS nuevo para el hero full-bleed y
   los accordions editoriales de "Qué trabajamos".
   Arquitectura de 6 bloques (hero + 5 secciones): las antiguas "Antes de
   escalar" y "Del roadmap a la ejecución" se eliminaron como secciones
   independientes — sus ideas viven ahora dentro de la intro de "Qué
   trabajamos" y del tercer accordion, respectivamente.
   ========================================================================== */

/* ---------- Ritmo de color + padding vertical compacto por sección ---------- */
.growth-service-capabilities { --bg: #FFFFFF; background: var(--bg); }
.growth-service-results { --bg: #FAFAF8; background: var(--bg); }
.growth-service-faq-section { --bg: #F6F6F4; background: var(--bg); }
.growth-service-contact { --bg: #FFFFFF; background: var(--bg); }

.growth-service-capabilities,
.growth-service-process,
.growth-service-results,
.growth-service-faq-section,
.growth-service-contact {
  padding-block: clamp(72px, 8vw, 110px);
}
@media (max-width: 1023px) {
  .growth-service-capabilities,
  .growth-service-process,
  .growth-service-results,
  .growth-service-faq-section,
  .growth-service-contact {
    padding-block: clamp(64px, 7vw, 88px);
  }
}
@media (max-width: 640px) {
  .growth-service-capabilities,
  .growth-service-process,
  .growth-service-results,
  .growth-service-faq-section,
  .growth-service-contact {
    padding-block: clamp(52px, 10vw, 72px);
  }
}

/* ---------- Hero: full-bleed, vídeo de fondo 100vw + overlay + copy encima ---------- */
.growth-service-hero {
  position: relative;
  width: 100%;
  margin-top: 96px; /* despeja el navbar fijo (misma medida que [id]{scroll-margin-top:96px} sitewide) */
  min-height: clamp(560px, 80dvh, 860px);
  display: flex;
  align-items: center;
  overflow: hidden;
  background: #08090C;
}
.growth-service-hero__media {
  position: absolute;
  inset: 0;
}
.growth-service-hero__video {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
  object-position: 55% center; /* Growth Strategy: estratega hacia la derecha */
}
/* CRM & Automation: composición centrada (operador a la izquierda, sistema centrado) —
   único ajuste que necesita el hero compartido para este vídeo concreto. */
.growth-service-hero--crm .growth-service-hero__video { object-position: center center; }
/* Advertising: composición centrada (persona + smartphone + experiencia digital) —
   único ajuste que necesita el hero compartido para este vídeo concreto. */
.growth-service-hero--advertising .growth-service-hero__video { object-position: center center; }
/* Martech: composición centrada en desktop (operador + red de datos completa); en mobile
   se desplaza hacia el centro-derecha para conservar la convergencia de datos/violeta
   aunque parte del operador quede recortado — único ajuste para este vídeo. */
.growth-service-hero--martech .growth-service-hero__video { object-position: center center; }
/* SEO & Content: encuadre desplazado hacia el centro-derecha en desktop, donde vive el
   protagonista + smartphone + ecosistema de contenido; la izquierda queda más despejada
   para el copy. En mobile se ajusta unos puntos más para conservar el smartphone en el
   recorte lateral — único ajuste para este vídeo. */
.growth-service-hero--seo .growth-service-hero__video { object-position: center center; }
/* IA Operativa: composición centrada en desktop (robot + entorno Miami completos); en
   mobile se desplaza hacia el centro-derecha para priorizar el robot y la señal violeta
   sobre el fondo urbano recortado — único ajuste para este vídeo. */
.growth-service-hero--ai .growth-service-hero__video { object-position: center center; }
/* Operadores: operador + loop violeta en centro-derecha, pared oscura despejada a la
   izquierda para el copy — único ajuste para este vídeo. */
.growth-service-hero--operators .growth-service-hero__video { object-position: center center; }
.growth-service-hero__overlay {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(90deg, rgba(5,6,9,.88) 0%, rgba(5,6,9,.66) 38%, rgba(5,6,9,.22) 70%, rgba(5,6,9,.12) 100%),
    linear-gradient(180deg, rgba(5,6,9,.32) 0%, transparent 22%, transparent 72%, rgba(5,6,9,.42) 100%);
}
.growth-service-hero__content {
  position: relative;
  z-index: 1;
  max-width: 720px;
  padding-block: clamp(48px, 8vh, 96px);
}
.growth-service-hero__title {
  font-size: clamp(2.5rem, 6vw, 4.5rem);
  margin-bottom: 1.25rem;
}
.growth-service-hero__subclaim {
  font-size: clamp(1.0625rem, 1.5vw, 1.25rem);
  color: var(--text-secondary);
  max-width: 660px;
  line-height: 1.5;
  margin-bottom: 2rem;
}
/* Operadores: rail editorial estrecho en vez de .container (max-width:1280px+margin:auto,
   que empuja el copy muy lejos del borde real en desktop ancho). Mismo principio que
   .hero-content/.hero-copy de la home — aquí sin usar esas clases (evita heredar
   propiedades pensadas para el hero del loop) y scoped solo a este hero via el modifier,
   así que el resto de service pages siguen usando .container tal cual. */
.growth-service-hero--operators .growth-service-hero__content {
  max-width: none;
  width: 100%;
  padding-left: clamp(48px, 4.6vw, 92px);
  padding-right: clamp(32px, 4vw, 72px);
}
.growth-service-hero__copy { width: min(44vw, 650px); max-width: 650px; }
/* Split de línea determinista para "Growth Partners" / "End-to-End" — evita el corte feo
   a mitad de palabra ("End-to-" / "End") que dejaba el ajuste de línea natural. */
.growth-service-hero--operators .growth-service-hero__title .glow-word { display: block; }
@media (max-width: 1023px) {
  .growth-service-hero { min-height: clamp(520px, 74dvh, 820px); }
}
@media (max-width: 640px) {
  .growth-service-hero { min-height: clamp(480px, 70dvh, 680px); margin-top: 88px; }
  .growth-service-hero__video { object-position: 62% center; }
  .growth-service-hero--martech .growth-service-hero__video { object-position: 62% center; }
  .growth-service-hero--seo .growth-service-hero__video { object-position: 55% center; }
  .growth-service-hero--ai .growth-service-hero__video { object-position: 58% center; }
  .growth-service-hero--operators .growth-service-hero__video { object-position: 65% center; }
  .growth-service-hero__overlay {
    background:
      linear-gradient(180deg, rgba(5,6,9,.5) 0%, rgba(5,6,9,.4) 30%, rgba(5,6,9,.55) 70%, rgba(5,6,9,.82) 100%),
      linear-gradient(90deg, rgba(5,6,9,.55) 0%, rgba(5,6,9,.15) 100%);
  }
  .growth-service-hero__subclaim { max-width: none; }
  .growth-service-hero--operators .growth-service-hero__content {
    padding-left: clamp(20px, 5.5vw, 24px);
    padding-right: clamp(20px, 5.5vw, 24px);
  }
  .growth-service-hero__copy { width: 100%; max-width: none; }
}

/* ---------- Qué trabajamos: 3 grandes apartados editoriales ---------- */
.growth-service-capabilities-list { margin-top: clamp(2.5rem, 5vw, 3.5rem); }
.growth-service-capability {
  border-top: 1px solid var(--border);
  transition: background 0.2s ease;
}
.growth-service-capability:last-child { border-bottom: 1px solid var(--border); }
.growth-service-capability:hover { background: rgba(10,12,15,0.02); }
.growth-service-capability summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  padding: clamp(1.75rem, 3vw, 2.75rem) 0;
}
.growth-service-capability summary::-webkit-details-marker { display: none; }
.growth-service-capability summary::marker { content: ''; }
.growth-service-capability__head {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 2vw, 1.75rem);
  min-width: 0;
}
.growth-service-capability__icon {
  flex-shrink: 0;
  width: clamp(32px, 2.6vw, 42px);
  height: clamp(32px, 2.6vw, 42px);
  color: var(--text);
  transition: color 0.2s ease, transform 0.2s ease;
}
.growth-service-capability:hover .growth-service-capability__icon,
.growth-service-capability[open] .growth-service-capability__icon {
  color: var(--accent);
  transform: translateX(4px);
}
.growth-service-capability__title {
  font-family: 'Heebo', sans-serif;
  font-weight: 700;
  font-size: clamp(1.375rem, 2.6vw, 2rem);
  color: var(--text);
  transition: transform 0.2s ease;
}
.growth-service-capability:hover .growth-service-capability__title,
.growth-service-capability[open] .growth-service-capability__title {
  transform: translateX(4px);
}
.growth-service-capability__plus {
  position: relative;
  flex-shrink: 0;
  width: clamp(56px, 6vw, 84px);
  height: clamp(56px, 6vw, 84px);
  border-radius: 50%;
  border: 1px solid var(--border);
  transition: border-color 0.2s ease, transform 0.22s ease;
}
.growth-service-capability__plus::before,
.growth-service-capability__plus::after {
  content: '';
  position: absolute;
  top: 50%; left: 50%;
  background: var(--text);
  transition: background 0.2s ease, transform 0.22s ease;
}
.growth-service-capability__plus::before { width: 32%; height: 1.5px; transform: translate(-50%, -50%); }
.growth-service-capability__plus::after { width: 1.5px; height: 32%; transform: translate(-50%, -50%); }
.growth-service-capability:hover .growth-service-capability__plus,
.growth-service-capability[open] .growth-service-capability__plus {
  border-color: var(--accent);
}
.growth-service-capability:hover .growth-service-capability__plus::before,
.growth-service-capability:hover .growth-service-capability__plus::after,
.growth-service-capability[open] .growth-service-capability__plus::before,
.growth-service-capability[open] .growth-service-capability__plus::after {
  background: var(--accent);
}
.growth-service-capability[open] .growth-service-capability__plus::after { transform: translate(-50%, -50%) rotate(90deg); opacity: 0; }
.growth-service-capability[open] .growth-service-capability__plus::before { transform: translate(-50%, -50%) rotate(180deg); }
@media (prefers-reduced-motion: reduce) {
  .growth-service-capability__icon,
  .growth-service-capability__title,
  .growth-service-capability__plus,
  .growth-service-capability__plus::before,
  .growth-service-capability__plus::after { transition: none; }
}

.growth-service-capability__content {
  padding: 0 0 clamp(1.75rem, 3vw, 2.5rem);
  opacity: 0;
  transform: translateY(-6px);
  transition: opacity 0.22s ease, transform 0.22s ease;
}
.growth-service-capability[open] .growth-service-capability__content {
  opacity: 1;
  transform: translateY(0);
}
@media (prefers-reduced-motion: reduce) {
  .growth-service-capability__content { transition: none; }
}
.growth-service-capability__claim {
  color: var(--text-secondary);
  font-size: clamp(1rem, 1.3vw, 1.1875rem);
  max-width: 68ch;
  margin: 0 0 1.75rem;
}
.growth-service-capability__label {
  display: block;
  font-family: 'Heebo', sans-serif;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  margin-bottom: 1rem;
}
.growth-service-capability__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.6rem 1.5rem;
}
.growth-service-capability__grid li {
  color: var(--text-secondary);
  font-size: 0.9375rem;
  padding-left: 1.1rem;
  position: relative;
}
.growth-service-capability__grid li::before {
  content: '';
  position: absolute;
  left: 0; top: 0.55em;
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--accent);
}
.growth-service-capability__players {
  margin-top: 2rem;
  padding-top: 1.75rem;
  border-top: 1px solid var(--border);
}
.growth-service-capability__players-label {
  display: block;
  font-family: 'Heebo', sans-serif;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 0.6rem;
}
.growth-service-capability__players p { color: var(--text-secondary); margin: 0 0 1rem; max-width: 60ch; }
.growth-service-capability__links { display: flex; flex-wrap: wrap; gap: 0.6rem; }
.growth-service-capability__links a {
  display: inline-flex;
  align-items: center;
  padding: 0.4rem 0.9rem;
  border-radius: 999px;
  border: 1px solid var(--border);
  color: var(--text);
  font-size: 0.875rem;
  font-weight: 500;
  text-decoration: none;
  transition: border-color 0.2s ease, color 0.2s ease;
}
.growth-service-capability__links a:hover { border-color: var(--accent); color: var(--accent); }
@media (max-width: 640px) {
  .growth-service-capability__grid { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 480px) {
  .growth-service-capability__title { font-size: clamp(1.125rem, 5vw, 1.375rem); }
  .growth-service-capability__plus { width: 52px; height: 52px; }
  .growth-service-capability__icon { width: 26px; height: 26px; }
  .growth-service-capability__grid { grid-template-columns: 1fr; }
}

/* ---------- Cómo trabajamos: compacto, reutiliza .process-steps/.process-step ---------- */
.growth-service-process__grid {
  display: grid;
  grid-template-columns: minmax(0, 0.75fr) minmax(0, 1.4fr);
  gap: clamp(2.5rem, 5vw, 5rem);
  align-items: start;
}
.growth-service-steps { margin-top: 0; }
.growth-service-steps .process-step { padding: 0.85rem 0; }
.growth-service-steps .process-step-desc { line-height: 1.45; }
.growth-service-process { padding-block: clamp(56px, 6vw, 80px); }
.growth-service-steps__output {
  margin-top: 0.6rem;
  font-size: 0.875rem;
  color: var(--text);
}
.growth-service-steps__output span {
  font-family: 'Heebo', sans-serif;
  font-weight: 700;
  font-size: 0.6875rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--accent);
  margin-right: 0.4rem;
}
@media (max-width: 1023px) {
  .growth-service-process__grid { grid-template-columns: 1fr; gap: 2rem; }
}

/* ---------- Accordions FAQ (compactos, sin icono/plus grande) ---------- */
.growth-service-faq { margin-top: clamp(2rem, 4vw, 3rem); }
.growth-service-accordion {
  border-top: 1px solid var(--border);
}
.growth-service-accordion:last-child { border-bottom: 1px solid var(--border); }
.growth-service-accordion summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  padding: clamp(1.1rem, 1.8vw, 1.5rem) 0;
  min-height: 48px;
}
.growth-service-accordion summary::-webkit-details-marker { display: none; }
.growth-service-accordion summary::marker { content: ''; }
.growth-service-accordion__title {
  font-family: 'Heebo', sans-serif;
  font-weight: 700;
  font-size: clamp(1rem, 1.4vw, 1.125rem);
  color: var(--text);
}
.growth-service-accordion__icon {
  position: relative;
  flex-shrink: 0;
  width: 22px;
  height: 22px;
}
.growth-service-accordion__icon::before,
.growth-service-accordion__icon::after {
  content: '';
  position: absolute;
  top: 50%; left: 50%;
  background: var(--text);
  transition: transform 0.22s ease;
}
.growth-service-accordion__icon::before { width: 14px; height: 1.5px; transform: translate(-50%, -50%); }
.growth-service-accordion__icon::after { width: 1.5px; height: 14px; transform: translate(-50%, -50%); }
.growth-service-accordion[open] .growth-service-accordion__icon::after { transform: translate(-50%, -50%) rotate(90deg); opacity: 0; }
.growth-service-accordion[open] .growth-service-accordion__icon::before { transform: translate(-50%, -50%) rotate(180deg); }
@media (prefers-reduced-motion: reduce) {
  .growth-service-accordion__icon::before,
  .growth-service-accordion__icon::after { transition: none; }
}
.growth-service-accordion__content { padding: 0 0 clamp(1.25rem, 2vw, 1.5rem); }
.growth-service-accordion__content p { color: var(--text-secondary); margin: 0; max-width: 68ch; }

/* ==========================================================================
   Cookie consent — banner + modal de preferencias (cookie-consent.js)
   Compartido por TODAS las páginas (script cargado sitewide). Construido con los
   mismos tokens/componentes que el resto del sitio (--bg/--surface/--accent/--border,
   .btn/.btn-primary/.btn-ghost) — cero paleta nueva.
   ========================================================================== */
/* Botón flotante "Configurar cookies" (sticky, bottom-izquierda). Simétrico a
   .whatsapp-float (bottom-derecha, 60px, z-index:90): mismo tamaño y offset en el lado
   opuesto, para que ambos flotantes convivan sin pisarse. Se queda SIEMPRE visible,
   independiente del estado del banner — que lo tapa mientras está abierto (z-index:300)
   y lo vuelve a dejar ver al cerrarse — como puerta de entrada permanente a
   "Gestionar cookies" (brief: mismo patrón que copilot.agency). */
.cookie-fab {
  position: fixed; left: 1.5rem; bottom: 1.5rem; z-index: 90;
  width: 60px; height: 60px; border-radius: 50%;
  background: var(--surface); border: 1px solid var(--border);
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 8px 24px rgba(0,0,0,0.35);
  transition: transform 0.25s ease, box-shadow 0.25s ease, opacity 0.2s ease;
}
.cookie-fab svg { width: 28px; height: 28px; }
.cookie-fab:hover { transform: translateY(-3px) scale(1.05); box-shadow: 0 12px 32px rgba(0,0,0,0.4); }
.cookie-fab:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* CRO: con #contacto visible (ver initContactFloatHide en app.js) los floats se apagan —
   dos rutas de salida flotando encima de un formulario de alta intención compiten con el
   submit. Global (no solo mobile): el mismo principio aplica en desktop. */
body.contact-in-view .whatsapp-float,
body.contact-in-view .cookie-fab {
  opacity: 0;
  pointer-events: none;
  transform: translateY(10px);
}

/* bottom-IZQUIERDA a propósito: .whatsapp-float vive fijo en bottom-right (z-index:90,
   60px) — un banner también anclado a la derecha lo taparía/colisionaría en mobile. */
.cookie-banner {
  position: fixed;
  left: clamp(16px, 3vw, 28px);
  right: clamp(16px, 3vw, 28px);
  bottom: clamp(16px, 3vw, 28px);
  z-index: 300;
  max-width: 560px;
  margin-right: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 16px;
  box-shadow: 0 24px 64px rgba(0, 0, 0, .38);
  padding: clamp(22px, 2.6vw, 30px);
  transform: translateY(calc(100% + 32px));
  opacity: 0;
  transition: transform .45s cubic-bezier(.16, 1, .3, 1), opacity .45s ease;
}
.cookie-banner.is-visible { transform: translateY(0); opacity: 1; }
.cookie-banner__title {
  font-family: 'Heebo', sans-serif;
  font-size: .8125rem;
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: .6rem;
}
.cookie-banner__text { font-size: .9375rem; line-height: 1.55; color: var(--text-secondary); margin-bottom: .35rem; }
.cookie-banner__links { display: flex; flex-wrap: wrap; gap: .3rem 1rem; margin-bottom: 1.25rem; }
.cookie-banner__links a { font-size: .8125rem; color: var(--text-tertiary); text-decoration: underline; text-underline-offset: 2px; }
.cookie-banner__links a:hover { color: var(--text); }
.cookie-banner__actions { display: flex; flex-wrap: wrap; gap: .75rem; }
.cookie-banner__actions .btn { flex: 1 1 auto; justify-content: center; padding: .7rem 1.1rem; font-size: .9rem; }

/* La ventana de preferencias se abre ANCLADA junto al .cookie-fab (bottom-izquierda),
   no como diálogo centrado con fondo oscurecido — mismo patrón que copilot.agency: un
   panel que crece desde la esquina del botón, sin tapar el resto de la página. El
   overlay sigue cubriendo todo el viewport (transparente) solo para capturar el click
   "fuera" que cierra el panel — la lógica de cierre en cookie-consent.js no cambia. */
.cookie-modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 310;
  display: flex;
  align-items: flex-end;
  justify-content: flex-start;
  padding: 0;
  opacity: 0;
  pointer-events: none;
  transition: opacity .3s ease;
}
.cookie-modal-overlay.is-visible { opacity: 1; pointer-events: auto; }
.cookie-modal {
  margin: 1.5rem;
  margin-bottom: calc(1.5rem + 60px + 14px); /* deja hueco justo encima del .cookie-fab (60px + su offset de 1.5rem) */
  width: min(100%, 400px);
  max-height: min(75vh, 620px);
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 20px;
  padding: clamp(22px, 2.6vw, 30px);
  box-shadow: 0 24px 64px rgba(0, 0, 0, .38);
  transform-origin: bottom left;
  transform: translateY(12px) scale(.92);
  transition: transform .3s cubic-bezier(.16, 1, .3, 1);
}
.cookie-modal-overlay.is-visible .cookie-modal { transform: translateY(0) scale(1); }
.cookie-modal__head { display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem; margin-bottom: 1.5rem; }
.cookie-modal__title { font-family: 'Heebo', sans-serif; font-size: clamp(1.25rem, 2vw, 1.5rem); font-weight: 800; }
.cookie-modal__close {
  flex-shrink: 0;
  width: 32px; height: 32px;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  color: var(--text-secondary);
  transition: background .2s ease, color .2s ease;
}
.cookie-modal__close:hover { background: var(--surface-hover); color: var(--text); }
.cookie-modal__intro { font-size: .9375rem; line-height: 1.55; color: var(--text-secondary); margin-bottom: 1.75rem; }
.cookie-category { border-top: 1px solid var(--border); padding-block: 1.25rem; }
.cookie-category:last-of-type { border-bottom: 1px solid var(--border); }
.cookie-category__row { display: flex; align-items: center; justify-content: space-between; gap: 1rem; margin-bottom: .4rem; }
.cookie-category__name { font-family: 'Heebo', sans-serif; font-weight: 700; font-size: .9375rem; }
.cookie-category__desc { font-size: .8125rem; line-height: 1.5; color: var(--text-tertiary); max-width: 42ch; }
.cookie-category__always { font-size: .75rem; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--text-tertiary); }

/* Toggle switch — checkbox nativo, solo re-skinado (accesible por teclado sin JS extra) */
.cookie-toggle { position: relative; flex-shrink: 0; width: 42px; height: 24px; }
.cookie-toggle input {
  position: absolute; inset: 0; margin: 0; opacity: 0; cursor: pointer;
}
.cookie-toggle input:disabled { cursor: not-allowed; }
.cookie-toggle__track {
  position: absolute; inset: 0;
  background: var(--surface-hover);
  border: 1px solid var(--border);
  border-radius: 999px;
  transition: background .2s ease, border-color .2s ease;
}
.cookie-toggle__track::before {
  content: '';
  position: absolute;
  top: 2px; left: 2px;
  width: 18px; height: 18px;
  border-radius: 50%;
  background: var(--text-secondary);
  transition: transform .2s ease, background .2s ease;
}
.cookie-toggle input:checked ~ .cookie-toggle__track { background: rgba(var(--accent-rgb), .3); border-color: var(--accent); }
.cookie-toggle input:checked ~ .cookie-toggle__track::before { transform: translateX(18px); background: var(--accent); }
.cookie-toggle input:disabled ~ .cookie-toggle__track { opacity: .6; }
.cookie-toggle input:focus-visible ~ .cookie-toggle__track { outline: 2px solid var(--accent); outline-offset: 2px; }

.cookie-modal__actions { display: flex; flex-wrap: wrap; gap: .75rem; margin-top: 1.75rem; }
.cookie-modal__actions .btn { flex: 1 1 auto; justify-content: center; }

@media (prefers-reduced-motion: reduce) {
  .cookie-banner, .cookie-modal-overlay, .cookie-modal, .cookie-toggle__track, .cookie-toggle__track::before {
    transition: none;
  }
}
@media (max-width: 640px) {
  .cookie-banner { left: 12px; right: 12px; bottom: 12px; max-width: none; }
  .cookie-banner__actions .btn { flex-basis: 100%; }
  .cookie-fab { width: 52px; height: 52px; left: 18px; bottom: calc(18px + env(safe-area-inset-bottom, 0px)); }
  .cookie-modal { margin: 12px; margin-bottom: calc(1rem + 52px + 12px); width: calc(100% - 24px); max-height: min(70vh, 560px); }
}

