/* ==== variables.css ==== */
/* ============================================================
   ZAIWEBS — Design tokens
   Editá solo este archivo para cambiar colores, tipografía y espaciado.
   ============================================================ */

:root {
  /* Marca */
  --c-primary:        #0A2540;  /* Azul profundo — headers, títulos, footer */
  --c-primary-800:    #123253;
  --c-primary-600:    #1B4570;
  --c-accent:         #00B8D4;  /* Cian — SOLO como fondo (botones) o sobre fondo oscuro. 2.38:1 sobre blanco: no usar como color de texto sobre claro. */
  --c-accent-ink:     #007A8C;  /* Cian oscuro — texto e íconos sobre fondos CLAROS. 5.05:1 sobre blanco */
  --c-accent-hover:   #007A8C;  /* Antes #0096AD: con texto blanco daba 3.52:1 y no cumplía AA */
  --c-accent-soft:    #E6F8FB;  /* Fondos de badges y destacados */

  /* Neutros */
  --c-bg:             #FFFFFF;
  --c-bg-alt:         #E9EFF5;  /* Alternancia de secciones. Antes #F5F8FB: 1.07 contra blanco,
                                    casi invisible. Este da 1.16 y el texto muted sigue en 4.73.
                                    No oscurecer más allá de #E4EBF2: ahí el muted cae a 4.56 */
  --c-bg-dark:        #071B2F;  /* Footer y bloques CTA oscuros */
  --c-text:           #142838;
  --c-text-muted:     #5A6B7D;
  --c-text-invert:    #EAF2F8;
  --c-border:         #DFE7EE;

  /* Semánticos */
  --c-success:        #16A34A;
  --c-error:           #DC2626;

  /* Logo — crema cálido, NO es blanco puro. No usar #FFFFFF. */
  --c-logo-cream:      #FFFAF1;

  /* WhatsApp */
  --c-whatsapp:        #25D366;

  /* Tipografía */
  --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --fs-hero:   clamp(2.25rem, 5vw + 0.5rem, 4rem);
  --fs-h2:     clamp(1.75rem, 3vw + 0.5rem, 2.75rem);
  --fs-h3:     clamp(1.25rem, 1.5vw + 0.5rem, 1.5rem);
  --fs-body:   clamp(1rem, 0.4vw + 0.9rem, 1.125rem);
  --fs-small:  0.9375rem;
  --lh-tight:  1.15;
  --lh-body:   1.65;

  /* Espaciado (escala 4px) */
  --sp-1: 0.25rem;  --sp-2: 0.5rem;   --sp-3: 0.75rem;
  --sp-4: 1rem;     --sp-5: 1.25rem;  --sp-6: 1.5rem;
  --sp-8: 2rem;     --sp-10: 2.5rem;  --sp-12: 3rem;
  --sp-16: 4rem;    --sp-24: 6rem;
  /* --sp-5 y --sp-10 faltaban y se venían usando con valor de respaldo
     (var(--sp-5, 1.25rem)). Funcionaba, pero el día que alguien escribía
     var(--sp-5) sin respaldo la declaración entera se caía en silencio y la
     propiedad volvía a cero. Definirlas cuesta dos líneas y saca la trampa. */
  /* Bajado de clamp(4rem, 8vw, 7rem). Eran 112px arriba y 112 abajo: entre
     dos secciones daba 224px seguidos de nada, y el cambio de tono caía
     justo en el medio de ese vacío, así que se leía como una raya en vez de
     como un cambio de sección. */
  --section-y: clamp(3rem, 5.2vw, 5rem);

  /* Layout */
  --container: 1200px;
  --container-narrow: 800px;
  --radius:    10px;
  --radius-lg: 16px;

  /* Sombras — sutiles, corporativas */
  --shadow-sm: 0 1px 3px rgba(10, 37, 64, 0.06);
  --shadow-md: 0 4px 16px rgba(10, 37, 64, 0.08);
  --shadow-lg: 0 12px 32px rgba(10, 37, 64, 0.12);

  --transition: 200ms cubic-bezier(0.4, 0, 0.2, 1);

  /* Header */
  --header-h: 76px;
  --header-h-mobile: 64px;
}

/* ==== base.css ==== */
/* ============================================================
   ZAIWEBS — Reset + estilos globales + utilidades
   ============================================================ */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

body {
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--c-text);
  background: var(--c-bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

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

a { color: inherit; text-decoration: none; }

ul, ol { list-style: none; }

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

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

h1, h2, h3, h4 {
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: var(--lh-tight);
  color: var(--c-primary);
}

h1 { font-size: var(--fs-hero); }
h2 { font-size: var(--fs-h2); }
h3 { font-size: var(--fs-h3); }

p { max-width: 65ch; }

/* Un párrafo con max-width dentro de un contenedor centrado queda pegado a la
   izquierda: se centra el TEXTO pero no la CAJA, y se ve corrido unos 40px
   respecto del título y los botones. Acá se centra también la caja. */
.text-center p,
.section-head--center p,
.cta-final__inner p,
.acciones-centradas {
  margin-inline: auto;
}

/* Envoltorio para un botón suelto centrado bajo una grilla.
   Sin max-width, si no hereda los 65ch y queda descentrado. */
.acciones-centradas {
  max-width: none;
  text-align: center;
  margin-top: var(--sp-8);
}

/* Foco visible en todos los interactivos */
:focus-visible {
  outline: 2px solid var(--c-accent);
  outline-offset: 2px;
  border-radius: 4px;
}

/* ============ Utilidades ============ */

.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--sp-6);
}

.container-narrow {
  width: 100%;
  max-width: var(--container-narrow);
  margin-inline: auto;
  padding-inline: var(--sp-6);
}

.section {
  padding-block: var(--section-y);
}

.section-alt {
  background: var(--c-bg-alt);
  /* Filete al ras: marca dónde empieza y termina la banda
     sin tener que oscurecer más el fondo. */
  border-block: 1px solid var(--c-border);
}

.section-dark {
  background: var(--c-bg-dark);
  color: var(--c-text-invert);
}

.section-dark h1, .section-dark h2, .section-dark h3 {
  color: var(--c-text-invert);
}

.section-head {
  max-width: var(--container-narrow);
  margin-bottom: var(--sp-12);
}

.section-head--center {
  margin-inline: auto;
  text-align: center;
}

.eyebrow {
  display: inline-block;
  font-size: var(--fs-small);
  font-weight: 600;
  color: var(--c-accent-hover);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  margin-bottom: var(--sp-3);
}

.lede {
  font-size: var(--fs-body);
  color: var(--c-text-muted);
  margin-top: var(--sp-4);
}

.section-dark .lede {
  color: var(--c-text-invert);
  opacity: 0.85;
}

.text-muted { color: var(--c-text-muted); }
.text-center { text-align: center; }

.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;
}

/* Saltar al contenido */
.skip-link {
  position: absolute;
  top: -100%;
  left: var(--sp-4);
  background: var(--c-accent);
  color: var(--c-primary);
  font-weight: 600;
  padding: var(--sp-3) var(--sp-6);
  border-radius: var(--radius);
  z-index: 1000;
  transition: top var(--transition);
}

.skip-link:focus {
  top: var(--sp-4);
}

main { display: block; }

/* Reveal en scroll — visible por defecto, JS agrega .reveal-init y luego .is-visible */
.reveal-init {
  opacity: 0;
  transform: translateY(20px);
}

.reveal-init.is-visible {
  opacity: 1;
  transform: translateY(0);
  transition: opacity 500ms cubic-bezier(0.4, 0, 0.2, 1), transform 500ms cubic-bezier(0.4, 0, 0.2, 1);
}

@media (prefers-reduced-motion: reduce) {
  .reveal-init,
  .reveal-init.is-visible {
    opacity: 1;
    transform: none;
    transition: none;
    animation: none;
  }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ---- Volanta ----
   El renglón chico en versalitas que va ARRIBA del <h2>. Sirve para nombrar
   de qué habla la sección sin gastar el título en eso.

   Va como <p> y no como <h3>: si fuera un encabezado, un lector de pantalla
   anunciaría un nivel de título antes del h2 y el esquema de la página
   quedaría al revés. Es una etiqueta, no una jerarquía. */
.volanta {
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--c-accent-ink);
  margin-bottom: var(--sp-3);
}

/* En una cabecera centrada el <p> hereda max-width 65ch y, sin margen
   automático, la CAJA queda a la izquierda aunque el texto esté centrado.
   Es el mismo tropiezo que ya apareció cuatro veces en este proyecto. */
.section-head--center .volanta { margin-inline: auto; }

/* Separación entre los bloques internos de una sección larga (Estudio).
   Antes iba como style="margin-top: var(--sp-24)" repetido en el HTML. */
/* Sin título visible arriba, el bloque puede acercarse: los 64px de antes
   compensaban el aire que dejaba ese renglón suelto. */
.estudio-bloque { margin-top: var(--sp-12); }

/* Los <h4> de tarjeta no tienen que verse más chicos que un <h3> solo por
   bajar un nivel: el cambio fue de jerarquía para los lectores de pantalla,
   no de tamaño. Sin esto las tarjetas se achicaban al corregir el HTML. */
.card h4,
.process-step h4 {
  font-size: 1.0625rem;
  margin-bottom: var(--sp-2);
}

/* ==== components.css ==== */
/* ============================================================
   ZAIWEBS — Header, footer, botones, cards, componentes compartidos
   ============================================================ */

/* ============ Botones ============ */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  padding: 0.875rem 1.75rem;
  border-radius: var(--radius);
  font-weight: 600;
  font-size: var(--fs-body);
  line-height: 1;
  min-height: 44px;
  transition: background var(--transition), color var(--transition), border-color var(--transition), transform var(--transition), box-shadow var(--transition);
  border: 1.5px solid transparent;
  white-space: nowrap;
}

.btn-primary {
  background: var(--c-accent);
  color: var(--c-primary);
}

/* Los :hover de botones van solo con mouse. En un celular el hover queda
   pegado después del toque: el botón quedaba levantado y con otro color
   hasta tocar otra cosa, como si siguiera apretado. */
@media (hover: hover) and (pointer: fine) {
  .btn-primary:hover {
    background: var(--c-accent-hover);
    color: #fff;
    transform: translateY(-2px);
    box-shadow: var(--shadow-md);
  }

  .btn-secondary:hover {
    background: var(--c-primary);
    color: #fff;
  }
}

/* Al apretar, el botón se achica un pelo: es la confirmación de que la
   página escuchó el toque, antes de que se abra WhatsApp. Va para mouse y
   para dedo. 160 ms con salida rápida: más lento se siente pegajoso. */
.btn:active {
  transform: scale(0.97);
  transition-duration: 160ms;
  transition-timing-function: cubic-bezier(0.23, 1, 0.32, 1);
}

.btn-secondary {
  background: transparent;
  border-color: var(--c-primary);
  color: var(--c-primary);
}

.section-dark .btn-secondary {
  border-color: var(--c-text-invert);
  color: var(--c-text-invert);
}

@media (hover: hover) and (pointer: fine) {
  .section-dark .btn-secondary:hover {
    background: var(--c-text-invert);
    color: var(--c-primary);
  }
}

.btn-ghost {
  padding: 0.5rem 0;
  color: var(--c-primary);
  font-weight: 600;
  position: relative;
  min-height: auto;
}

.btn-ghost::after {
  content: '';
  position: absolute;
  left: 0; bottom: -2px;
  width: 100%;
  height: 2px;
  background: var(--c-accent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--transition);
}

.btn-ghost:hover::after { transform: scaleX(1); }

.section-dark .btn-ghost { color: var(--c-text-invert); }

.btn-block { width: 100%; }

.btn-lg {
  padding: 1.125rem 2.25rem;
  font-size: 1.0625rem;
}

.btn svg { width: 1.25em; height: 1.25em; flex-shrink: 0; }

/* ============ Header ============ */

.site-header {
  position: sticky;
  top: 0;
  z-index: 900;
  background: var(--c-bg);
  height: var(--header-h-mobile);
  display: flex;
  align-items: center;
  transition: box-shadow var(--transition);
}

@media (min-width: 900px) {
  .site-header { height: var(--header-h); }
}

.site-header.is-scrolled {
  box-shadow: var(--shadow-sm);
}

.site-header__inner {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--sp-6);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-6);
}

.site-header__logo {
  display: flex;
  align-items: center;
  flex-shrink: 0;
}

.site-header__logo img {
  height: 28px;
  width: 148px;
}

@media (min-width: 900px) {
  .site-header__logo img {
    height: 34px;
    width: 180px;
  }
}

.site-nav {
  display: none;
}

@media (min-width: 900px) {
  /* Grilla de tres columnas con los costados iguales: así el nav queda
     centrado en la PÁGINA. Con flex + margin auto se centraba en el
     espacio sobrante, y como el logo (180px) es más ancho que el bloque
     de acciones (144px), quedaba 18px corrido a la derecha. */
  .site-header__inner {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
  }

  .site-header__actions { justify-self: end; }

  .site-nav {
    display: flex;
    align-items: center;
    gap: var(--sp-8);
    margin-inline: 0;
  }
}

/* Entre 900 y 1023px el nav es tan ancho que la columna del logo no entra
   en su mitad y empuja: las columnas laterales dejan de ser iguales y el
   menú se corre. Con menos separación entra y la simetría se mantiene. */
@media (min-width: 900px) and (max-width: 1023px) {
  /* Con el enlace "IA" la nav tiene seis entradas: a 24px de separación
     la columna del logo ya no entraba a 900px. A 20px vuelve a entrar. */
  .site-nav { gap: var(--sp-5); }
}

@media (min-width: 900px) {

  .site-nav__link {
    font-weight: 500;
    color: var(--c-text);
    padding-block: var(--sp-2);
    position: relative;
    transition: color var(--transition);
  }

  .site-nav__link::after {
    content: '';
    position: absolute;
    left: 0; bottom: 0;
    width: 100%;
    height: 2px;
    background: var(--c-accent);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform var(--transition);
  }

  .site-nav__link:hover { color: var(--c-primary); }
  .site-nav__link:hover::after { transform: scaleX(1); }

  .site-nav__link.is-active {
    color: var(--c-primary);
    font-weight: 600;
  }

  .site-nav__link.is-active::after { transform: scaleX(1); }
}

.site-header__actions {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  flex-shrink: 0;
}

/* Selector de idioma — maqueta lista para pt-BR, oculto hasta el lanzamiento */
.lang-switch {
  position: relative;
}

.lang-switch__btn {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  font-weight: 600;
  font-size: var(--fs-small);
  color: var(--c-text-muted);
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--radius);
  transition: background var(--transition), color var(--transition);
}

.lang-switch__btn:hover {
  background: var(--c-bg-alt);
  color: var(--c-primary);
}

.lang-switch__btn svg {
  width: 14px; height: 14px;
  transition: transform var(--transition);
}

.lang-switch__menu {
  position: absolute;
  top: calc(100% + var(--sp-2));
  right: 0;
  background: var(--c-bg);
  border: 1px solid var(--c-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md);
  min-width: 120px;
  padding: var(--sp-2);
  display: none;
}

.lang-switch__menu a {
  display: block;
  padding: var(--sp-2) var(--sp-3);
  border-radius: 6px;
  font-size: var(--fs-small);
  font-weight: 500;
}

.lang-switch__menu a:hover { background: var(--c-bg-alt); }

.site-header__actions .btn {
  display: none;
}

@media (min-width: 640px) {
  .site-header__actions .btn {
    display: inline-flex;
  }
}

/* ============ Menú móvil (hamburguesa) ============ */

.menu-toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  flex-shrink: 0;
}

@media (min-width: 900px) {
  .menu-toggle { display: none; }
}

.menu-toggle__icon {
  position: relative;
  width: 22px;
  height: 16px;
}

.menu-toggle__icon span {
  position: absolute;
  left: 0;
  width: 100%;
  height: 2px;
  background: var(--c-primary);
  border-radius: 2px;
  transition: transform var(--transition), opacity var(--transition), top var(--transition);
}

.menu-toggle__icon span:nth-child(1) { top: 0; }
.menu-toggle__icon span:nth-child(2) { top: 7px; }
.menu-toggle__icon span:nth-child(3) { top: 14px; }

.menu-toggle[aria-expanded="true"] .menu-toggle__icon span:nth-child(1) {
  top: 7px;
  transform: rotate(45deg);
}
.menu-toggle[aria-expanded="true"] .menu-toggle__icon span:nth-child(2) {
  opacity: 0;
}
.menu-toggle[aria-expanded="true"] .menu-toggle__icon span:nth-child(3) {
  top: 7px;
  transform: rotate(-45deg);
}

.mobile-menu {
  position: fixed;
  inset: 0;
  z-index: 950;
  background: var(--c-bg);
  display: flex;
  flex-direction: column;
  padding: var(--sp-6);
  transform: translateY(-100%);
  opacity: 0;
  visibility: hidden;
  transition: transform var(--transition), opacity var(--transition), visibility 0s linear var(--transition);
}

.mobile-menu.is-open {
  transform: translateY(0);
  opacity: 1;
  visibility: visible;
  transition: transform var(--transition), opacity var(--transition), visibility 0s;
}

@media (min-width: 900px) {
  .mobile-menu { display: none; }
}

.mobile-menu__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: var(--header-h-mobile);
}

.mobile-menu__top img {
  height: 28px;
  width: 148px;
}

.mobile-menu__close {
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.mobile-menu__close svg {
  width: 22px; height: 22px;
}

.mobile-menu__nav {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  margin-top: var(--sp-8);
}

.mobile-menu__nav a {
  font-size: 1.5rem;
  font-weight: 600;
  color: var(--c-primary);
  padding: var(--sp-3) 0;
  border-bottom: 1px solid var(--c-border);
}

.mobile-menu__nav a.is-active { color: var(--c-accent-hover); }

/* :not([hidden]) no sobra: `display: flex` le gana al atributo hidden, así
   que el selector de idioma aparecía en el menú móvil aunque estuviera
   marcado como oculto — un selector con un solo idioma disponible. En
   escritorio no pasaba porque ahí la regla no fuerza display. */
.mobile-menu__lang:not([hidden]) {
  display: flex;
  gap: var(--sp-3);
  margin-top: var(--sp-6);
}

.mobile-menu__lang a {
  font-weight: 600;
  font-size: var(--fs-small);
  color: var(--c-text-muted);
  padding: var(--sp-2) var(--sp-4);
  border: 1px solid var(--c-border);
  border-radius: var(--radius);
}

.mobile-menu__cta {
  margin-top: auto;
  padding-top: var(--sp-8);
}

body.menu-open { overflow: hidden; }

/* ============ Cards ============ */

.card {
  background: var(--c-bg);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-lg);
  padding: var(--sp-8);
  transition: transform var(--transition), box-shadow var(--transition);
}

@media (hover: hover) and (pointer: fine) {
  .card:hover {
    transform: translateY(-4px);
    box-shadow: var(--shadow-md);
  }
}

.card__icon {
  width: 48px;
  height: 48px;
  color: var(--c-accent-ink);
  margin-bottom: var(--sp-4);
}

.card__icon svg {
  width: 100%;
  height: 100%;
  stroke: var(--c-accent-ink);
  fill: none;
  stroke-width: 2;
}

.card h3 { margin-bottom: var(--sp-3); }

.card p { color: var(--c-text-muted); }

/* ============ Badges ============ */

.badge {
  display: inline-block;
  font-size: var(--fs-small);
  font-weight: 600;
  padding: var(--sp-1) var(--sp-3);
  border-radius: 999px;
  background: var(--c-accent-soft);
  color: var(--c-primary-800);
}

/* Franja "Próximamente" */




/* ============ Footer ============ */

.site-footer {
  background: var(--c-bg-dark);
  color: var(--c-text-invert);
  padding-block: var(--sp-16) var(--sp-8);
}

.site-footer__grid {
  display: grid;
  gap: var(--sp-12);
  grid-template-columns: 1fr;
}

@media (min-width: 640px) {
  .site-footer__grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 1000px) {
  .site-footer__grid {
    /* Cada columna mide lo que mide su contenido y el sobrante se reparte
       en partes iguales entre las cuatro. Con tracks de 1fr todas medían lo
       mismo pero su contenido no, y quedaban huecos muy desparejos —sobre
       todo entre EMPRESA y CONTACTO, que son las de texto más corto. */
    grid-template-columns: repeat(4, auto);
    justify-content: space-between;
    column-gap: var(--sp-12);
  }
}

.site-footer__brand img {
  height: 30px;
  width: 159px;
  margin-bottom: var(--sp-4);
}

.site-footer__tagline {
  max-width: 32ch;   /* sin esto la columna de marca se estira y desarma el reparto */
  color: var(--c-text-invert);
  opacity: 0.75;
  max-width: 32ch;
}

.site-footer__social {
  display: flex;
  gap: var(--sp-3);
  margin-top: var(--sp-6);
}

.site-footer__social a {
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid rgba(234, 242, 248, 0.2);
  border-radius: 50%;
  transition: background var(--transition), border-color var(--transition);
}

.site-footer__social a:hover {
  background: var(--c-accent);
  border-color: var(--c-accent);
}

.site-footer__social svg {
  width: 18px; height: 18px;
  fill: var(--c-text-invert);
}

.site-footer__heading {
  font-size: var(--fs-small);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--c-text-invert);
  opacity: 0.6;
  margin-bottom: var(--sp-4);
}

.site-footer__list {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}

.site-footer__list a,
.site-footer__list span {
  color: var(--c-text-invert);
  opacity: 0.85;
  transition: opacity var(--transition);
}

.site-footer__list a:hover { opacity: 1; color: var(--c-accent); }

.site-footer__bottom {
  margin-top: var(--sp-16);
  padding-top: var(--sp-8);
  border-top: 1px solid rgba(234, 242, 248, 0.12);
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  font-size: var(--fs-small);
  color: var(--c-text-invert);
  opacity: 0.6;
}

@media (min-width: 700px) {
  .site-footer__bottom {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
  }
}

.site-footer__legal {
  display: flex;
  gap: var(--sp-6);
}

.site-footer__legal a:hover { opacity: 1; color: var(--c-accent); }

/* ============ Botón flotante de WhatsApp ============ */

.whatsapp-float {
  position: fixed;
  right: var(--sp-6);
  bottom: var(--sp-6);
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: var(--c-whatsapp);
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: var(--shadow-lg);
  z-index: 800;
  opacity: 0;
  transform: scale(0.8);
  /* Escondido también para el mouse y el dedo: desde el 27/09 se oculta
     sobre Contacto y el pie, y un botón invisible pero tocable se comía los
     toques a los enlaces de abajo. visibility espera a que termine el
     desvanecido para no cortarlo de golpe. */
  visibility: hidden;
  pointer-events: none;
  transition: opacity 300ms ease, transform 300ms ease, background var(--transition), visibility 0s linear 300ms;
}

.whatsapp-float.is-visible {
  opacity: 1;
  transform: scale(1);
  visibility: visible;
  pointer-events: auto;
  transition-delay: 0s;
}

@media (hover: hover) and (pointer: fine) {
  .whatsapp-float:hover {
    background: #1EBE57;
  }
}

.whatsapp-float svg {
  width: 28px; height: 28px;
  fill: #fff;
}

/* En el celular el botón es solo el círculo con el ícono: la pantalla es
   angosta y una píldora con texto tapa media línea de lo que se está
   leyendo. En pantalla grande sobra lugar y el texto ayuda, así que ahí
   sí se despliega. */
.whatsapp-float__texto { display: none; }

@media (min-width: 900px) {
  .whatsapp-float {
    width: auto;
    height: auto;
    min-height: 56px;
    padding-inline: var(--sp-4) var(--sp-5);
    gap: var(--sp-2);
    border-radius: 999px;
  }

  .whatsapp-float__texto {
    display: inline;
    color: #fff;
    font-weight: 600;
    font-size: 0.9375rem;
    line-height: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .whatsapp-float { transition: opacity 1ms; }
}

/* ============ Proceso (pasos numerados) ============ */

.process-grid {
  display: grid;
  gap: var(--sp-8);
  grid-template-columns: 1fr;
}

@media (min-width: 900px) {
  .process-grid {
    grid-template-columns: repeat(4, 1fr);
    gap: var(--sp-6);
  }
}

.process-step__number {
  font-size: 2.5rem;
  font-weight: 700;
  color: var(--c-accent-ink);
  line-height: 1;
  margin-bottom: var(--sp-3);
}

.process-step h3 { margin-bottom: var(--sp-2); }
.process-step p { color: var(--c-text-muted); }

/* ============ Lista con check ============ */

.check-list {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
}

.check-list li {
  display: flex;
  gap: var(--sp-3);
  align-items: flex-start;
}

.check-list svg {
  width: 22px; height: 22px;
  flex-shrink: 0;
  margin-top: 2px;
  color: var(--c-success);
  stroke: var(--c-success);
  fill: none;
  stroke-width: 2.5;
}

/* ============ FAQ (details/summary) ============ */

.faq-item {
  border-bottom: 1px solid var(--c-border);
}

.faq-item summary {
  padding: var(--sp-6) 0;
  font-weight: 600;
  font-size: 1.0625rem;
  color: var(--c-primary);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  list-style: none;
}

.faq-item summary::-webkit-details-marker { display: none; }

.faq-item summary::after {
  content: '+';
  font-size: 1.5rem;
  font-weight: 400;
  color: var(--c-accent-ink);
  flex-shrink: 0;
  transition: transform var(--transition);
}

.faq-item[open] summary::after {
  transform: rotate(45deg);
}

.faq-item p {
  padding-bottom: var(--sp-6);
  color: var(--c-text-muted);
}

/* ============ Trust bar (Home) ============
   Tres datos duros. El número manda, la etiqueta explica.
   Nada de adjetivos: si no es verificable, no va acá. */

.trust-bar {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-8);
  text-align: center;
}

@media (min-width: 760px) {
  .trust-bar {
    /* auto-fit: sirve igual con 2 o con 3 ítems, sin tocar el CSS */
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: var(--sp-4);
    align-items: stretch;   /* mismas alturas => divisorias parejas */
    max-width: 760px;
    margin-inline: auto;
  }

  .trust-bar__item + .trust-bar__item {
    border-left: 1px solid var(--c-border);
  }
}

.trust-bar__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  gap: var(--sp-2);
  padding-inline: var(--sp-6);
}

.trust-bar__value {
  font-size: clamp(2.5rem, 4vw, 3.25rem);
  font-weight: 700;
  line-height: 1;
  color: var(--c-primary);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.03em;
}

.trust-bar__label {
  max-width: 26ch;
  margin-inline: auto;
  font-size: var(--fs-small);
  line-height: 1.45;
  color: var(--c-text-muted);
  text-wrap: balance;
}

/* ============================================================
   Testimonios — citas reales de clientes.
   Solo texto verificable: nombre del cliente y proyecto.
   ============================================================ */

.testimonios-grid {
  display: grid;
  gap: var(--sp-6);
  grid-template-columns: 1fr;
}

@media (min-width: 700px) {
  .testimonios-grid { grid-template-columns: repeat(2, 1fr); }
}

.testimonio {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  background: var(--c-bg);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-lg);
  padding: var(--sp-8);
}

.testimonio__cita {
  margin: 0;
  font-size: 1.0625rem;
  line-height: var(--lh-body);
  color: var(--c-text);
}

.testimonio__cita::before { content: '\201C'; }
.testimonio__cita::after  { content: '\201D'; }

.testimonio__pie {
  display: flex;
  align-items: baseline;
  gap: var(--sp-3);
  margin-top: auto;
  padding-top: var(--sp-4);
  border-top: 1px solid var(--c-border);
  flex-wrap: wrap;
}

.testimonio__cliente {
  font-weight: 600;
  color: var(--c-primary);
  font-size: var(--fs-small);
}

.testimonio__rubro {
  font-size: 0.8125rem;
  color: var(--c-text-muted);
}

/* ==== pages.css ==== */
/* ============================================================
   ZAIWEBS — Estilos específicos por página
   ============================================================ */

/* ============ Hero (Home) ============ */

.hero {
  padding-block: var(--sp-16) var(--section-y);
}

.hero__inner {
  display: grid;
  gap: var(--sp-12);
  align-items: center;
}

@media (min-width: 900px) {
  .hero__inner {
    grid-template-columns: 1.1fr 0.9fr;
  }
}

.hero__title { margin-bottom: var(--sp-6); }

.hero__lede {
  font-size: 1.125rem;
  color: var(--c-text-muted);
  margin-bottom: var(--sp-8);
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-4);
}

.hero__visual {
  display: none;
}

@media (min-width: 900px) {
  .hero__visual {
    display: block;
  }
}

/* ============ Grid de servicios (Home) ============ */

.services-grid {
  display: grid;
  gap: var(--sp-6);
  grid-template-columns: 1fr;
}

@media (min-width: 640px) {
  .services-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 1000px) {
  .services-grid { grid-template-columns: repeat(4, 1fr); }
}

/* ============ Por qué elegirnos (Home) ============ */

.why-grid {
  display: grid;
  gap: var(--sp-8);
  grid-template-columns: 1fr;
}

@media (min-width: 700px) {
  .why-grid { grid-template-columns: repeat(2, 1fr); }
}

.why-item {
  display: flex;
  gap: var(--sp-4);
}

.why-item__icon {
  width: 44px;
  height: 44px;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--c-accent-soft);
  display: flex;
  align-items: center;
  justify-content: center;
}

.why-item__icon svg {
  width: 22px; height: 22px;
  stroke: var(--c-accent-hover);
  fill: none;
  stroke-width: 2.5;
}

.why-item h3 { margin-bottom: var(--sp-2); font-size: 1.125rem; }
.why-item p { color: var(--c-text-muted); }

/* ============ Portfolio preview (Home) ============ */

.portfolio-preview-grid {
  display: grid;
  gap: var(--sp-6);
  grid-template-columns: 1fr;
}

@media (min-width: 700px) {
  .portfolio-preview-grid { grid-template-columns: repeat(3, 1fr); }
}

/* ============ CTA final ============ */

.cta-final {
  text-align: center;
}

.cta-final__inner {
  max-width: var(--container-narrow);
  margin-inline: auto;
  text-align: center;
}

.cta-final h2 { margin-bottom: var(--sp-4); }

.cta-final__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--sp-4);
  margin-top: var(--sp-8);
}

.cta-final__email {
  margin-top: var(--sp-6);
  color: var(--c-text-invert);
  opacity: 0.75;
}

.cta-final__email a { color: var(--c-accent); font-weight: 600; }

/* ============ Servicios — bloques alternados ============ */

.service-block {
  display: grid;
  gap: var(--sp-8);
  align-items: center;
}

.service-block + .service-block {
  margin-top: var(--sp-24);
}

@media (min-width: 900px) {
  .service-block {
    grid-template-columns: 1fr 1fr;
    gap: var(--sp-16);
  }

  .service-block--reverse .service-block__visual {
    order: 2;
  }
}

.service-block__visual {
  background: var(--c-bg-alt);
  border-radius: var(--radius-lg);
  aspect-ratio: 4 / 3;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.service-block__visual svg {
  width: 55%;
  height: 55%;
  stroke: var(--c-accent-ink);
  fill: none;
  stroke-width: 1.5;
}

.service-block__intro {
  color: var(--c-text-muted);
  margin-block: var(--sp-4) var(--sp-6);
}

.service-block__meta {
  margin-block: var(--sp-6);
  font-size: var(--fs-small);
}

.service-block__meta strong {
  color: var(--c-primary);
}

.service-block h2 { margin-bottom: var(--sp-2); }

/* ============ Portfolio ============ */

.portfolio-filters {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  margin-bottom: var(--sp-12);
}

.filter-chip {
  padding: var(--sp-2) var(--sp-6);
  border: 1.5px solid var(--c-border);
  border-radius: 999px;
  font-weight: 600;
  font-size: var(--fs-small);
  color: var(--c-text-muted);
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  transition: background var(--transition), border-color var(--transition), color var(--transition);
}

.filter-chip:hover {
  border-color: var(--c-accent);
  color: var(--c-primary);
}

.filter-chip[aria-pressed="true"] {
  background: var(--c-primary);
  border-color: var(--c-primary);
  color: #fff;
}

.portfolio-grid {
  display: grid;
  gap: var(--sp-8);
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
}

.portfolio-card {
  border: 1px solid var(--c-border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--c-bg);
  max-width: 460px;
  transition: transform var(--transition), box-shadow var(--transition);
  display: flex;
  flex-direction: column;
}

/* Solo con mouse: en un celular el :hover queda pegado después del toque y
   la tarjeta se quedaba levantada hasta tocar otra cosa. */
@media (hover: hover) and (pointer: fine) {
  .portfolio-card:hover {
    transform: translateY(-4px);
    box-shadow: var(--shadow-md);
  }
}

.portfolio-card__img {
  /* 1200x624, que es la proporción real de una captura de pantalla de
     escritorio. Antes era 16/9 y obligaba a recortarles un 8% de ancho:
     como los hero están centrados, el recorte partía los titulares al medio.
     Es más barato adaptar la tarjeta que mutilar ocho capturas. */
  aspect-ratio: 1200 / 624;
  width: 100%;
  /* height:auto no es decorativo: sin él, el atributo height="624" del <img>
     fija la altura y el aspect-ratio no llega a aplicarse nunca. El bug ya
     estaba antes con height="225", pero como 225 quedaba cerca de lo que
     daba 16/9 no se notaba. Con 624 la tarjeta se estiraba al triple. */
  height: auto;
  object-fit: cover;
  background: var(--c-bg-alt);
  display: block;
}

.portfolio-card__body {
  padding: var(--sp-6);
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  flex: 1;
}

/* ---- Nombre del cliente DEBAJO de la captura ----
   Hasta el 27/09 el rótulo iba encima de la imagen, con un velo del 30 al
   95 % para que se leyera. Resolvía el texto y rompía lo importante: la
   captura es la prueba de que sabemos diseñar, y quedaba apagada justo donde
   el cliente la mira. Ahora la imagen va a plena luz y el nombre abajo, sobre
   la superficie de la tarjeta, donde se lee sin velos ni sombras.

   El HTML no cambió (el rótulo sigue adentro de __visual, en las cinco
   páginas que usan la tarjeta): el cambio es solo de CSS. */
.portfolio-card__visual {
  display: flex;
  flex-direction: column;
}

/* Filete bajo la captura: las webs con fondo blanco o muy oscuro se
   fundían con la tarjeta y no se veía dónde terminaba la imagen. */
.portfolio-card__visual .portfolio-card__img {
  border-bottom: 1px solid var(--c-border);
}

.portfolio-card__rotulo {
  padding: var(--sp-5, 1.25rem) var(--sp-6) 0;
}

.portfolio-card__rotulo h3 {
  color: var(--c-text);
  font-size: clamp(1.05rem, 1.5vw, 1.35rem);
  line-height: 1.2;
  letter-spacing: -0.015em;
  margin: 0 0 0.3rem;
  text-wrap: balance;
}

/* El rubro va como texto en versalitas y no como píldora: la tarjeta ya
   tiene píldoras abajo (las etiquetas) y dos tipos se confundirían. */
.portfolio-card__rubro {
  margin: 0;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--c-accent-ink);
}

/* El rótulo ya dejó aire arriba: el cuerpo arranca más cerca para que
   nombre y descripción se lean como un bloque. */
.portfolio-card__visual + .portfolio-card__body { padding-top: var(--sp-3); }

.portfolio-card__tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin-top: var(--sp-2);
}

.portfolio-card__tag {
  font-size: 0.8125rem;
  color: var(--c-text-muted);
  background: var(--c-bg-alt);
  padding: 0.2rem var(--sp-3);
  border-radius: 999px;
}

.portfolio-card__link {
  margin-top: var(--sp-4);
  font-weight: 600;
  color: var(--c-accent-hover);
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
}

.portfolio-card__link svg {
  width: 16px; height: 16px;
}

.portfolio-card[hidden] { display: none; }

/* ============ Nosotros ============ */

.values-grid {
  display: grid;
  gap: var(--sp-6);
  grid-template-columns: 1fr;
}

@media (min-width: 640px) {
  .values-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 1000px) {
  .values-grid { grid-template-columns: repeat(4, 1fr); }
}

.team-grid {
  display: grid;
  gap: var(--sp-8);
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  max-width: 700px;
}

.team-card {
  text-align: center;
}

.team-card img {
  width: 140px;
  height: 140px;
  border-radius: 50%;
  object-fit: cover;
  margin-inline: auto;
  margin-bottom: var(--sp-4);
}

.team-card h3 { font-size: 1.0625rem; margin-bottom: var(--sp-1); }
.team-card p { color: var(--c-text-muted); font-size: var(--fs-small); }

/* ============ Contacto ============ */

.contact-grid {
  display: grid;
  gap: var(--sp-6);
  grid-template-columns: 1fr;
}

@media (min-width: 700px) {
  .contact-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 1000px) {
  .contact-grid { grid-template-columns: repeat(3, 1fr); }
}

.contact-card {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
}

.contact-card--whatsapp {
  background: var(--c-primary);
  color: var(--c-text-invert);
  border-color: var(--c-primary);
}

.contact-card--whatsapp h3,
.contact-card--whatsapp p { color: var(--c-text-invert); }

.contact-card__icon {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: var(--c-accent-soft);
  display: flex;
  align-items: center;
  justify-content: center;
}

.contact-card--whatsapp .contact-card__icon {
  background: rgba(255,255,255,0.12);
}

.contact-card__icon svg {
  width: 24px; height: 24px;
}

.contact-card__value {
  font-weight: 600;
  font-size: 1.125rem;
}

.contact-card__social {
  display: flex;
  gap: var(--sp-3);
  margin-top: var(--sp-2);
}

.contact-card__social a {
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--c-border);
  border-radius: 50%;
  transition: background var(--transition), border-color var(--transition);
}

.contact-card__social a:hover {
  background: var(--c-primary);
  border-color: var(--c-primary);
}

.contact-card__social svg {
  width: 20px; height: 20px;
  fill: var(--c-primary);
  transition: fill var(--transition);
}

.contact-card__social a:hover svg { fill: #fff; }

.next-steps {
  display: grid;
  gap: var(--sp-8);
  grid-template-columns: 1fr;
  counter-reset: step;
}

@media (min-width: 700px) {
  .next-steps { grid-template-columns: repeat(3, 1fr); }
}

.next-steps li {
  position: relative;
  padding-left: 3.5rem;
}

.next-steps li::before {
  counter-increment: step;
  content: counter(step);
  position: absolute;
  left: 0; top: 0;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 50%;
  background: var(--c-accent-soft);
  color: var(--c-primary);
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
}

.next-steps p { color: var(--c-text-muted); }

.faq-list {
  max-width: var(--container-narrow);
}

/* ============ 404 ============ */

.error-page {
  text-align: center;
  padding-block: var(--sp-24);
}

.error-page__code {
  font-size: clamp(4rem, 12vw, 8rem);
  font-weight: 700;
  color: var(--c-accent-ink);
  line-height: 1;
}

.error-page__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--sp-4);
  margin-top: var(--sp-8);
}

/* ============ Gracias ============ */

.thanks-page {
  text-align: center;
  padding-block: var(--sp-24);
}

.thanks-page__icon {
  width: 72px;
  height: 72px;
  margin-inline: auto var(--sp-6);
  color: var(--c-success);
}

/* ============================================================
   Páginas legales (privacidad, términos)
   ============================================================
   Son textos largos que se leen de corrido, no se escanean. Lo único
   que necesitan es una columna angosta, aire entre bloques y que los
   subtítulos se distingan sin gritar. */

.legal-fecha {
  margin-top: var(--sp-3);
  font-size: 0.875rem;
  color: var(--c-text-muted);
}

.legal-titulo {
  font-size: 1.1875rem;
  margin-top: var(--sp-10);
  margin-bottom: var(--sp-3);
  /* El filete de arriba separa las secciones sin necesidad de más espacio:
     en un texto largo el aire solo termina pareciendo un error de maqueta. */
  padding-top: var(--sp-6);
  border-top: 1px solid var(--c-border);
}

.container-narrow .lede + .legal-titulo { margin-top: var(--sp-8); }

.legal-lista {
  margin: var(--sp-4) 0 0;
  padding-left: var(--sp-5);
  display: grid;
  gap: var(--sp-3);
}

.legal-lista li { padding-left: var(--sp-2); }
.legal-lista li::marker { color: var(--c-accent); }

.container-narrow p + p { margin-top: var(--sp-4); }

/* ==== home.css ==== */
/* ============================================================
   ZAIWEBS — Home en modo oscuro (dirección A)
   ------------------------------------------------------------
   Nació para index.html, pero hoy lo cargan TODAS las páginas del
   sitio (landings, portfolio, legales), después de los otros CSS.
   Cualquier cambio acá se ve en las ocho: probar más de una.

   La estrategia es redefinir los design tokens en <body>, no
   reescribir cada componente. Como todo el resto del CSS consume
   var(--c-...), la página entera cambia de mundo con este bloque.
   Lo que viene después son solo las piezas nuevas del hero y los
   ajustes de contraste que el fondo oscuro obliga.

   Si algún día el sitio entero va a oscuro, estos tokens se mudan
   a variables.css y este archivo desaparece casi por completo.
   ============================================================ */

body.tema-oscuro {
  /* Fondos */
  --c-bg:          #040B14;   /* base: casi negro con el azul de Zaiwebs (28/09; antes #071A2C) */
  --c-bg-alt:      #08131F;   /* alternancia de secciones. Hubo un intento de
                                 bajarlo a #0A2032 para suavizar el corte, pero
                                 nunca llegó a verse: las bandas se pintaban con
                                 un gemelo en RGB que quedó sin actualizar. Se
                                 vuelve a este, que es el que da 4.68 puntos de
                                 salto y hace que el cambio se note. */
  --c-bg-dark:     #02070D;   /* el más profundo: CTA y footer */
  --c-superficie:  #0C1B2B;   /* tarjetas sobre el fondo base */

  /* Texto — verificado sobre #040B14:
     #E7EFF6 = 17.0:1 · #9FB4C6 = 9.2:1 · #35D6EE = 11.3:1 */
  --c-text:        #E7EFF6;
  --c-text-muted:  #9FB4C6;
  --c-text-invert: #E7EFF6;
  --c-primary:     #E7EFF6;   /* invertido: lo que era azul oscuro ahora es claro */
  --c-border:      #1B3047;
  --c-border-strong: #2A4560; /* botones secundarios, chips, filetes que se tienen que ver */
  /* Placeholder: 5.0:1 sobre el fondo de los campos (--c-bg-dark) */
  --c-placeholder: #6A8196;

  /* Acento: sobre oscuro el cian brilla, no hace falta la versión ink */
  --c-accent:      #00B8D4;
  --c-accent-ink:  #35D6EE;
  --c-accent-hover:#35D6EE;
  --c-accent-soft: #0A2838;
  --c-accent-border: #1D3A4E; /* borde de las superficies teñidas de IA */
  --c-on-accent:   #05202F;   /* texto sobre cian: 7.0:1 */

  /* Botón principal (28/09): crema con texto azul marino, 14.9:1 */
  --c-cta:         #FFFAF1;
  --c-cta-hover:   #FFFFFF;
  --c-on-cta:      #0A2540;

  /* Burbuja del cliente en las charlas de ejemplo: 10.5:1 con --c-text */
  --c-burbuja-cliente: #0E3A4A;

  /* Vidrio del menú flotante. Sale de --c-bg con color-mix, así no hay un
     "gemelo en RGB" que se olvide al cambiar el fondo (ver --c-bg-alt).
     La primera línea es para navegadores sin color-mix. */
  --c-vidrio:        rgba(4, 11, 20, 0.62);
  --c-vidrio:        color-mix(in srgb, var(--c-bg) 62%, transparent);
  --c-vidrio-fuerte: rgba(4, 11, 20, 0.8);
  --c-vidrio-fuerte: color-mix(in srgb, var(--c-bg) 80%, transparent);

  /* Sombras: las de variables.css son del tema claro (azul marino al 6–12 %)
     y sobre este fondo no se veían. */
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
  --shadow-md: 0 8px 24px rgba(0, 0, 0, 0.4);
  --shadow-lg: 0 16px 40px rgba(0, 0, 0, 0.45);


  background: var(--c-bg);
  color: var(--c-text);
}

/* ============ Ajustes que el fondo oscuro obliga ============ */

/* ============ Menú flotante (28/09) ============
   La cabecera dejó de ser una franja de lado a lado: es una píldora de
   vidrio que flota arriba y deja ver la página alrededor.

   Ocupa lo mismo que la cabecera de antes (--header-h: 76px en escritorio
   = 16 de aire + 52 de barra + 8; en celular 64 = 12 + 52), así el scroll
   clavado de Servicios y las anclas siguen frenando justo debajo sin tocar
   main.js.

   Es fixed y no sticky para que el brillo del hero pase por detrás. Por eso
   la primera sección de cada página suma --header-h arriba (ver «Primera
   sección» al final de este archivo). */
body.tema-oscuro .site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: auto;
  padding: 16px var(--sp-6) 0;
  background: transparent;
  box-shadow: none;
  /* La franja transparente alrededor de la píldora no se come los clics
     de lo que pasa por debajo. */
  pointer-events: none;
}

body.tema-oscuro .site-header__inner {
  pointer-events: auto;
  max-width: 1080px;
  height: 52px;
  padding-inline: 16px 8px;
  border: 1px solid var(--c-border);
  border-radius: 12px;
  background: var(--c-vidrio);
  backdrop-filter: saturate(140%) blur(24px);
  -webkit-backdrop-filter: saturate(140%) blur(24px);
  transition: background-color 200ms ease, border-color 200ms ease;
}

/* Al bajar, un poco más opaca: sobre fotos y tarjetas claras el menú se
   seguía leyendo, pero justo. */
body.tema-oscuro .site-header.is-scrolled { box-shadow: none; }
body.tema-oscuro .site-header.is-scrolled .site-header__inner {
  background: var(--c-vidrio-fuerte);
  border-color: var(--c-border-strong);
}

body.tema-oscuro .site-header__logo img { height: 22px; width: 117px; }

@media (min-width: 900px) {
  body.tema-oscuro .site-header__logo img { height: 24px; width: 127px; }

  body.tema-oscuro .site-nav__link {
    font-size: 0.875rem;
    color: var(--c-text-muted);
  }

  body.tema-oscuro .site-nav__link:hover { color: #FFFFFF; }
}

/* El botón de la cabecera, del alto justo para la píldora */
body.tema-oscuro .site-header__actions .btn {
  min-height: 36px;
  padding: 0 1rem;
  font-size: 0.875rem;
}

/* Con dedo (tablets entre 640 y 899px, donde el botón ya se ve) vuelve a
   los 44px de mínimo: entra igual en la píldora de 52. */
@media (pointer: coarse) {
  body.tema-oscuro .site-header__actions .btn { min-height: 44px; }
}

@media (max-width: 899px) {
  body.tema-oscuro .site-header { padding: 12px var(--sp-4) 0; }
  body.tema-oscuro .site-header__inner { padding-inline: 14px 4px; }
}

body.tema-oscuro .menu-toggle__icon span { background: var(--c-text); }
body.tema-oscuro .mobile-menu { background: var(--c-bg); }

/* El botón primario es crema con texto azul marino (15:1), no cian: desde
   el 28/09 el cian queda para el logo, los brillos y lo que es IA. */
body.tema-oscuro .btn-primary { background: var(--c-cta); color: var(--c-on-cta); }

/* "Saltar al contenido" usaba --c-primary como color de texto, y acá arriba
   --c-primary pasó a ser claro: quedaba texto claro sobre cian, 2.1:1. Solo
   aparece al navegar con teclado, que es justo quien más lo necesita. */
body.tema-oscuro .skip-link { color: #05202F; }

body.tema-oscuro .btn-secondary {
  border-color: var(--c-border-strong);
  color: var(--c-text);
}

/* Solo con mouse (ver components.css). La sombra del hover se apaga: era un
   azul marino al 8 % que sobre este fondo no se veía y solo sumaba trabajo. */
@media (hover: hover) and (pointer: fine) {
  body.tema-oscuro .btn-primary:hover {
    background: var(--c-cta-hover);
    color: var(--c-on-cta);
    box-shadow: none;
  }

  body.tema-oscuro .btn-secondary:hover {
    background: transparent;
    border-color: var(--c-text-muted);
    color: #FFFFFF;
  }
}

/* Tarjetas: se levantan del fondo con superficie propia, no con sombra */
body.tema-oscuro .card,
body.tema-oscuro .portfolio-card,
body.tema-oscuro .testimonio {
  background: var(--c-superficie);
  border-color: var(--c-border);
}

@media (hover: hover) and (pointer: fine) {
  body.tema-oscuro .portfolio-card:hover,
  body.tema-oscuro .card:hover {
    border-color: #2E4A66;
    box-shadow: 0 20px 44px rgba(0, 0, 0, 0.42);
  }
}

/* Lo que el navegador dibuja solo también lleva la marca: la selección de
   texto y el cursor de los campos. Con los valores por defecto, seleccionar
   un párrafo pintaba un azul de sistema que no existe en el sitio. */
body.tema-oscuro ::selection {
  background: rgba(0, 184, 212, 0.38);
  color: #FFFFFF;
}

body.tema-oscuro input,
body.tema-oscuro textarea { caret-color: var(--c-accent); }

body.tema-oscuro .portfolio-card__tag {
  background: #112438;
  color: var(--c-text-muted);
}

body.tema-oscuro .badge {
  background: var(--c-accent-soft);
  color: var(--c-accent-ink);
}

body.tema-oscuro .filter-chip { border-color: var(--c-border); color: var(--c-text-muted); }
body.tema-oscuro .filter-chip:hover { color: var(--c-text); border-color: var(--c-text-muted); }
body.tema-oscuro .filter-chip[aria-pressed="true"] {
  background: var(--c-cta);
  border-color: var(--c-cta);
  color: var(--c-on-cta);
}

body.tema-oscuro .why-item__icon { background: var(--c-accent-soft); }
body.tema-oscuro .why-item__icon svg { stroke: var(--c-accent-ink); }
body.tema-oscuro .card__icon,
body.tema-oscuro .card__icon svg { color: var(--c-accent-ink); stroke: var(--c-accent-ink); }
body.tema-oscuro .process-step__number { color: var(--c-accent-ink); }

/* Color plano y filete, sin degradado. Se probó desvaneciendo los bordes y
   quedaba más suave, pero se perdía justamente lo que se buscaba: que el
   cambio de sección se note. El degradado disolvía la línea y también el
   aviso de que empezó otra cosa. */
body.tema-oscuro .section-alt {
  background: var(--c-bg-alt);
  border-block: 1px solid var(--c-border);
}

body.tema-oscuro .cta-final { background: var(--c-bg-dark); }


/* La CTA final y el pie comparten el mismo fondo, así que sin filete se leen
   como un solo bloque larguísimo y la CTA pierde el cierre. Es el único borde
   entre secciones que no viene de .section-alt. */
body.tema-oscuro .site-footer {
  background: var(--c-bg-dark);
  border-top: 1px solid var(--c-border);
}

/* ============ Hero ============ */

body.tema-oscuro .hero {
  position: relative;
  overflow: hidden;
  /* Arriba menos que abajo, a propósito. El header es sticky y ocupa su
     propio lugar en el flujo, así que este relleno no está despejando nada:
     es aire decorativo. Eran 120px y dejaban las solapas muy hundidas; con
     las solapas afuera (27/09) el titular pasó a ser lo primero y necesita
     un poco más de aire que ellas, no menos.

     Los dos valores no son iguales porque un bloque centrado en su caja se
     percibe caído: el ojo lo lee más arriba de lo que está. Con el de abajo
     un poco mayor, el conjunto queda ópticamente centrado. */
  padding-block: clamp(3rem, 6vw, 5.5rem) clamp(3.5rem, 7vw, 6rem);
  max-width: none;          /* el hero rompe el container para que el fondo sea a sangre */
  padding-inline: 0;
}

.hero__fondo {
  position: absolute;
  inset: -40%;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(closest-side, rgba(0, 184, 212, 0.26), transparent 72%) 20% 28% / 56% 56% no-repeat,
    radial-gradient(closest-side, rgba(27, 69, 112, 0.55), transparent 72%) 78% 66% / 62% 62% no-repeat;
  filter: blur(14px);
  animation: derivar 26s ease-in-out infinite alternate;
}

@keyframes derivar {
  from { transform: translate3d(-3%, -2%, 0) scale(1); }
  to   { transform: translate3d(4%, 3%, 0) scale(1.09); }
}

body.tema-oscuro .hero__inner {
  position: relative;
  z-index: 2;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--sp-6);
}

/* Titular grande, entra línea por línea */
body.tema-oscuro .hero__title {
  font-size: clamp(2.5rem, 6.6vw, 4.6rem);
  line-height: 0.99;
  letter-spacing: -0.035em;
  color: #FFFFFF;
  max-width: 16ch;
  margin-bottom: var(--sp-6);
}

/* overflow:hidden es lo que permite que el texto entre desde abajo, pero
   recorta las colas de g, j, p, q, y. El padding agranda la caja y el
   margen negativo lo descuenta, así las líneas no se separan. */
.linea {
  display: block;
  overflow: hidden;
  padding-bottom: 0.16em;
  margin-bottom: -0.16em;
}

.linea > span {
  display: block;
  transform: translateY(120%);
  opacity: 0;
  animation: subir 820ms cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

.linea:nth-child(2) > span { animation-delay: 95ms; }
.linea:nth-child(3) > span { animation-delay: 190ms; }

@keyframes subir { to { transform: translateY(0); opacity: 1; } }

.acento { color: var(--c-accent-ink); font-style: normal; }

body.tema-oscuro .hero__lede {
  color: var(--c-text-muted);
  font-size: 1.1rem;
  max-width: 48ch;
}


/* ============ Reveal al scrollear ============
   Eran 640 ms y 38 px, más una demora de hasta 400 ms entre elementos: al
   scrollear rápido, una sección entera se veía vacía durante un segundo. Con
   43 elementos animados en la home, la espera se sumaba en cada pantalla.
   Ahora 420 ms y 16 px: el movimiento se sigue leyendo, pero el contenido
   llega cuando el ojo llega. La demora entre elementos la fija main.js. */

body.tema-oscuro .reveal-init {
  opacity: 0;
  transform: translateY(16px);
}

body.tema-oscuro .reveal-init.is-visible {
  opacity: 1;
  transform: none;
  transition: opacity 420ms cubic-bezier(0.23, 1, 0.32, 1),
              transform 420ms cubic-bezier(0.23, 1, 0.32, 1);
}

/* ============ Tarjetas de proyecto con más vida ============ */

body.tema-oscuro .portfolio-card {
  transition: transform 280ms cubic-bezier(0.23, 1, 0.32, 1),
              box-shadow 280ms ease,
              border-color 280ms ease;
}

/* Sin el zoom de la captura al pasar el mouse: con el nombre ahora debajo de
   la imagen, la captura agrandada se montaba sobre el título. */
body.tema-oscuro .portfolio-card__img { background: #0C1B2B; }

body.tema-oscuro .portfolio-card__link { color: var(--c-accent-ink); }

body.tema-oscuro .portfolio-card__link svg {
  transition: transform 220ms ease;
}

@media (hover: hover) and (pointer: fine) {
  body.tema-oscuro .portfolio-card:hover { transform: translateY(-6px); }

  body.tema-oscuro .portfolio-card:hover .portfolio-card__link svg {
    transform: translate(3px, -3px);
  }
}

/* ============ Testimonios sobre oscuro ============ */

body.tema-oscuro .testimonio__cita { color: var(--c-text); }
body.tema-oscuro .testimonio__cliente { color: #FFFFFF; }
body.tema-oscuro .testimonio__rubro { color: var(--c-text-muted); }
body.tema-oscuro .testimonio__pie { border-top-color: var(--c-border); }

/* ============ WhatsApp siempre a la vista ============ */

body.tema-oscuro .whatsapp-float {
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.45);
}

/* En celular queda solo el círculo con el ícono. Antes se expandía a una
   píldora con la palabra "Escribime": 153px de ancho flotando sobre una
   pantalla de 390, que es el 39% del ancho tapando contenido de forma
   permanente. El ícono de WhatsApp ya se reconoce solo; la palabra costaba
   más de lo que aportaba. El aria-label del enlace sigue diciendo qué hace,
   así que para un lector de pantalla no cambia nada. */

/* ============ Respeto por quien pide menos movimiento ============ */

@media (prefers-reduced-motion: reduce) {
  .hero__fondo { animation: none; }
  .linea > span { animation: none; transform: none; opacity: 1; }
  body.tema-oscuro .reveal-init,
  body.tema-oscuro .reveal-init.is-visible { opacity: 1; transform: none; transition: none; }
  body.tema-oscuro .portfolio-card:hover { transform: none; }
}

/* ============================================================
   LANDING — una sola página
   ============================================================ */

/* Las anclas tienen que frenar por debajo del header pegajoso */
.seccion-ancla { scroll-margin-top: calc(var(--header-h) + var(--sp-4)); }

@media (max-width: 899px) {
  .seccion-ancla { scroll-margin-top: calc(var(--header-h-mobile) + var(--sp-4)); }
}

html { scroll-behavior: smooth; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

/* Enlace de la nav correspondiente a la sección visible */
body.tema-oscuro .site-nav__link.is-active { color: #FFFFFF; }

.titulo-menor {
  font-size: var(--fs-h3);
  font-weight: 700;
  color: var(--c-text);
}

/* ============ Servicios: columna fija + columna que scrollea ============
   La izquierda queda pegada mientras la derecha recorre los servicios.
   Es position: sticky puro, sin JavaScript. Debajo de 900px las dos
   columnas se apilan y la izquierda deja de pegarse. */

.servicios-doble {
  display: grid;
  gap: var(--sp-12);
  grid-template-columns: 1fr;
}

@media (min-width: 900px) {
  .servicios-doble {
    grid-template-columns: 0.85fr 1.15fr;
    gap: var(--sp-16);
    align-items: start;
  }

  .servicios-fijo {
    position: sticky;
    top: calc(var(--header-h) + var(--sp-12));
  }
}

.servicios-fijo h2 { margin-bottom: var(--sp-4); }
.servicios-fijo .lede { margin-bottom: var(--sp-6); }

.servicios-fijo__nota {
  color: var(--c-text-muted);
  font-size: var(--fs-small);
  margin-bottom: var(--sp-8);
  max-width: 34ch;
}

.servicios-lista {
  display: flex;
  flex-direction: column;
  gap: var(--sp-8);
}

/* En tablet vertical las tarjetas plegadas van de a dos: una sola columna
   de 700px dejaba cada tarjeta con media fila vacía. La quinta ocupa la
   fila entera. align-items: start hace que al abrir una no se estire la
   de al lado. */
@media (min-width: 640px) and (max-width: 899px) {
  [data-pin-tarjetas] .servicios-lista {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--sp-5, 1.25rem);
    align-items: start;
  }

  [data-pin-tarjetas] .servicio:last-child:nth-child(odd) { grid-column: 1 / -1; }
}

.servicio {
  background: var(--c-superficie, var(--c-bg-alt));
  border: 1px solid var(--c-border);
  border-radius: var(--radius-lg);
  padding: var(--sp-8);
  transition: border-color 260ms ease, transform 260ms cubic-bezier(0.4, 0, 0.2, 1);
}

@media (hover: hover) and (pointer: fine) {
  .servicio:hover {
    border-color: #2E4A66;
    transform: translateY(-3px);
  }
}

.servicio__icono {
  width: 44px;
  height: 44px;
  border-radius: var(--radius);
  background: var(--c-accent-soft);
  display: grid;
  place-content: center;
  margin-bottom: var(--sp-5, 1.25rem);
}

.servicio__icono svg {
  width: 22px;
  height: 22px;
  stroke: var(--c-accent-ink);
  fill: none;
  stroke-width: 2;
}

.servicio__titulo {
  font-size: var(--fs-h3);
  font-weight: 700;
  margin-bottom: var(--sp-3);
  color: var(--c-text);
}

.servicio__intro {
  color: var(--c-text-muted);
  margin-bottom: var(--sp-6);
}

.servicio .check-list { margin-bottom: var(--sp-6); }

.servicio__meta {
  font-size: var(--fs-small);
  color: var(--c-text-muted);
  margin-bottom: var(--sp-6);
}

.servicio__meta strong { color: var(--c-text); }

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

/* ============ Tarjeta final de la pista: lleva al portfolio ============ */

.tarjeta-mas {
  flex: 0 0 clamp(240px, 24vw, 320px);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--sp-4);
  padding: var(--sp-8);
  border: 1px dashed var(--c-border);
  border-radius: var(--radius-lg);
  background: transparent;
  transition: border-color 260ms ease, background 260ms ease;
}

@media (hover: hover) and (pointer: fine) {
  .tarjeta-mas:hover {
    border-color: var(--c-accent);
    background: var(--c-accent-soft);
  }
}

.tarjeta-mas h3 {
  font-size: var(--fs-h3);
  color: var(--c-text);
  margin: 0;
}

.tarjeta-mas p { color: var(--c-text-muted); font-size: var(--fs-small); margin: 0; }

/* Los tildes venían en verde de éxito. Sobre el fondo oscuro el cian
   de marca es más coherente y contrasta mejor. */
body.tema-oscuro .check-list svg {
  color: var(--c-accent-ink);
  stroke: var(--c-accent-ink);
}

/* Dupla de botones bajo una grilla: uno convierte, el otro deja explorar. */
.acciones-par {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--sp-4);
  margin-top: var(--sp-12);
}

@media (max-width: 520px) {
  .acciones-par { flex-direction: column; align-items: stretch; }
  .acciones-par .btn { width: 100%; }
}

/* ============================================================
   Hero: una sola promesa
   ------------------------------------------------------------
   Hasta el 27/09 el hero tenía cuatro solapas (Web + IA, Diseño web, SEO,
   Tiendas). Se sacaron: sumaban cuatro decisiones antes de que llegara la
   promesa, repetían lo que ya dice Servicios, y como cada panel medía
   distinto la página de abajo saltaba al cambiar. Queda el panel que la
   mayoría veía igual, el de Web + IA. Las otras tres frases están en el
   respaldo del 27/09 por si vuelven a servir en otra parte.
   ============================================================ */

/* A todo el ancho, sin imagen: el titular ocupa el escenario */
body.tema-oscuro .hero__inner {
  display: block;
  max-width: 1000px;
}

.hero__eyebrow {
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--c-accent-ink);
  margin-bottom: var(--sp-4);
}

body.tema-oscuro .hero__title {
  max-width: 18ch;
  font-size: clamp(2.5rem, 7.2vw, 5rem);
}

/* Sin imagen al costado, la bajada puede respirar más */
body.tema-oscuro .hero__lede { max-width: 54ch; }

/* ============================================================
   Hero centrado
   Para volver al alineado a la izquierda, borrá este bloque entero.
   ============================================================ */

body.tema-oscuro .hero__inner { text-align: center; }

/* El <p> del hero hereda max-width 65ch: sin margen automático queda
   pegado a la izquierda aunque su texto esté centrado. */
.hero__eyebrow { margin-inline: auto; }

body.tema-oscuro .hero__title {
  margin-inline: auto;
  max-width: 20ch;
}

/* Centrado, el texto corrido se lee peor: la bajada va más angosta */
body.tema-oscuro .hero__lede {
  margin-inline: auto;
  max-width: 46ch;
}

body.tema-oscuro .hero__actions { justify-content: center; }

@media (max-width: 620px) {
  /* En pantallas angostas el centrado deja renglones muy dispares:
     conviene volver a la izquierda, que se lee mejor. */
  body.tema-oscuro .hero__inner { text-align: left; }
  .hero__eyebrow,
  body.tema-oscuro .hero__title,
  body.tema-oscuro .hero__lede { margin-inline: 0; }
  body.tema-oscuro .hero__actions { justify-content: flex-start; }
}

/* ============================================================
   Cinta de clientes
   Sin encabezado: los logos son el mensaje.
   ============================================================ */

/* La tira NO usa el tono claro de .section-alt aunque lleve esa clase.
   Motivo: ese tono es el de las secciones, y esto no es una sección — no
   tiene título ni contenido propio, es una tira de prueba social. Vestida
   de sección, el ojo la lee como una sección vacía.

   Va en el tono más profundo, el mismo de la CTA final. Tres consecuencias:
   los logos blancos resaltan más, el salto contra el hero y contra Servicios
   es de 3.67 puntos de L* de cada lado (se lee), y la tira gana identidad
   propia en vez de imitar a las bandas de arriba y abajo.

   Sin borde arriba y con borde abajo: así la tira sale del hero sin costura
   —parece que el hero se hunde— pero cierra contra Servicios con un límite
   claro. Con borde arriba se veía como un cajón pegado; sin el de abajo,
   Servicios arrancaba sin aviso.

   El relleno es la mitad del de una sección. Antes eran 128px de aire para
   55px de logo: el 70% de la banda era vacío. */
.clientes {
  position: relative;      /* para el botón de pausa */
  padding-block: clamp(1.6rem, 2.4vw, 2.2rem);
  background: var(--c-bg-dark);
  border-top: 0;
  border-bottom: 1px solid var(--c-border);
}

/* Si lo que sigue a la tira es una banda alternada (en la home, Proyectos
   desde el 27/09), su filete de arriba se sumaba al de abajo de la tira y
   quedaba una raya doble. */
.clientes + .section-alt { border-top: 0; }

body.tema-oscuro .clientes { background: var(--c-bg-dark); }

/* El viewport recorta la cinta y la desvanece en los bordes. Sin la máscara
   los logos aparecen y desaparecen de golpe contra el borde de la pantalla,
   que es lo que delata que hay un truco atrás. Va a todo el ancho a propósito:
   una cinta que arranca y termina dentro del container se ve como una caja,
   no como algo que sigue de largo. */
.clientes-viewport {
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
}

/* ---- Estado base: SIN JavaScript ----
   Una sola tanda, quieta, envuelta y centrada. Es también lo que se ve con
   "reducir movimiento" activado. Todo lo de la animación cuelga de la clase
   .cinta-lista, que agrega main.js recién después de clonar las tandas: así
   nunca se ve una cinta a medio armar. */
.clientes-cinta {
  display: flex;
  justify-content: center;
}

.clientes-tanda {
  --gap: clamp(2rem, 3.4vw, 3.4rem);
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: var(--gap);
  row-gap: clamp(1.75rem, 3vw, 2.5rem);
  padding-inline: calc(var(--gap) / 2);
  list-style: none;
  margin-inline: auto;
  max-width: var(--container);
}

.clientes-tanda li {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
}

/* ---- Estado con JavaScript: la cinta desfila ----
   main.js clona la tanda hasta que la cinta mide más del doble que la
   pantalla, escribe cuántas quedaron en --tandas y pone esta clase.
   El desplazamiento es -100% ÷ --tandas: exactamente el ancho de UNA tanda.
   Al llegar ahí la tanda 2 está donde arrancó la 1, así que volver a cero no
   se nota y el loop parece infinito. Calcularlo con la variable (en vez de
   un -33% escrito a mano) es lo que permite que la cantidad de copias cambie
   según el tamaño de pantalla sin romper el calce. */
.clientes-cinta.cinta-lista {
  width: max-content;
  justify-content: flex-start;
  animation: desfilar var(--dur-cinta, 30s) linear infinite;
  will-change: transform;
}

/* width:max-content en la cinta no alcanza: sin flex:none, flex igual
   comprimiría las tandas, y ahí el tercio dejaría de calzar. */
.cinta-lista .clientes-tanda {
  flex: none;
  flex-wrap: nowrap;
  max-width: none;
  margin-inline: 0;
}

@keyframes desfilar {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(calc(-100% / var(--tandas, 3)), 0, 0); }
}

/* SIN pausa al pasar el mouse. La había puesto "por si alguien quiere mirar
   un logo", y era una mala idea: la tira ocupa todo el ancho y está justo
   debajo del hero, así que al scrollear el cursor le queda encima casi
   siempre. La cinta se frenaba sola y parecía rota.

   Además no había nada que mirar con calma: los logos no son enlaces ni
   tienen texto para leer. Una pausa que no sirve para nada, que se dispara
   sin querer y que hace parecer que la página se colgó. */

/* SIN filtro de blanqueo. Antes había un `filter: brightness(0) invert(1)`
   para forzar todo a blanco: destruye los logos que tienen texto calado
   adentro de una forma (CELP y SWS quedaban como manchas blancas macizas,
   porque el filtro pinta de blanco tanto el fondo del badge como las letras
   que van encima). Los siete archivos ya vienen en blanco, así que no hace
   falta. Si alguna vez entra un logo oscuro, se blanquea el archivo, no acá. */
.clientes-tanda img {
  width: auto;
  max-width: none;
  object-fit: contain;
  opacity: 0.78;
  transition: opacity 260ms ease;
}

/* Altos por proporción, no uno solo para todos. Un logo apaisado y uno
   cuadrado al mismo alto no pesan lo mismo en la fila: el cuadrado se ve
   diminuto. Estos valores igualan el área aproximada de cada uno. */
.clientes-tanda .logo--ancho  img { height: clamp(26px, 2.6vw, 36px); }
.clientes-tanda .logo--medio  img { height: clamp(33px, 3.3vw, 45px); }
.clientes-tanda .logo--alto   img { height: clamp(41px, 4.1vw, 56px); }

/* Excepción para el logo que trae dos renglones de texto adentro (CELP).
   Con el alto de `logo--ancho` los renglones quedaban en 6px y se leían como
   una mancha. Va un poco más grande aunque rompa el equilibrio de áreas:
   entre un logo parejo pero ilegible y uno legible, gana el legible. */
.clientes-tanda .logo--lockup img { height: clamp(31px, 3.1vw, 43px); }

.clientes-tanda img:hover { opacity: 1; }

/* ---- Botón de pausa ----
   La cinta se mueve sola todo el tiempo, y WCAG 2.2.2 (nivel A) pide que lo
   que se mueve solo más de cinco segundos junto a otro contenido se pueda
   parar. Respetar "reducir movimiento" no alcanza: hay quien no sabe que esa
   opción existe. La pausa al pasar el mouse ya se probó y se descartó (ver
   arriba): se disparaba sola al scrollear. Un botón explícito no.

   Lo crea main.js, y solo cuando la cinta arranca a moverse: sin JavaScript
   o con movimiento reducido la tira está quieta y el botón no tiene sentido.
   Va sobre el borde IZQUIERDO, donde la máscara ya desvanece los logos. A la
   derecha quedaba abajo del botón flotante de WhatsApp cada vez que la tira
   pasaba por el pie de la pantalla (en la primera pantalla, siempre). El
   área de toque es de 44px aunque el círculo visible mida 32. */
.cinta-pausa {
  position: absolute;
  left: var(--sp-3);
  top: 50%;
  z-index: 1;
  width: 44px;
  height: 44px;
  display: grid;
  place-content: center;
  border-radius: 50%;
  color: var(--c-text-muted);
  transform: translateY(-50%);
  transition: color 200ms ease, transform 160ms cubic-bezier(0.23, 1, 0.32, 1);
}

.cinta-pausa::before {
  content: "";
  position: absolute;
  inset: 6px;
  z-index: -1;
  border-radius: 50%;
  background: var(--c-bg-dark);
  border: 1px solid var(--c-border);
  transition: border-color 200ms ease;
}

/* display:grid le gana al atributo hidden: sin esto el botón se vería
   también con la cinta quieta. */
.cinta-pausa[hidden] { display: none; }

.cinta-pausa svg { width: 12px; height: 12px; fill: currentColor; }

@media (hover: hover) and (pointer: fine) {
  .cinta-pausa:hover { color: var(--c-text); }
  .cinta-pausa:hover::before { border-color: var(--c-text-muted); }
}

.cinta-pausa:active { transform: translateY(-50%) scale(0.94); }

.clientes-cinta.cinta-pausada { animation-play-state: paused; }

/* Con "reducir movimiento" main.js ni siquiera clona, así que alcanza con
   apagar la máscara y las transiciones: el estado base ya es la grilla quieta. */
@media (prefers-reduced-motion: reduce) {
  .clientes-viewport {
    -webkit-mask-image: none;
            mask-image: none;
    padding-inline: var(--sp-6);
  }
  .clientes-tanda img { transition: none; }
}

/* ============================================================
   Servicios — tarjetas que se reemplazan al scrollear
   ============================================================
   .pin-alto es una caja alta y vacía cuyo único trabajo es dar scroll.
   .pin-clavado va adentro con position:sticky y se queda quieta mientras
   ese scroll se consume. La altura la escribe main.js, porque depende del
   alto de la ventana y de cuántas tarjetas haya.

   Todo cuelga de .con-pin, que main.js agrega solo cuando corresponde. Sin
   esa clase el bloque se comporta como la lista de siempre, que es lo que
   se ve en celular, con movimiento reducido o sin JavaScript.
   ============================================================ */

@media (min-width: 900px) {

  /* Sin relleno de sección: la caja pegajosa ya centra su contenido en el
     alto de la ventana. Los dos juntos daban 274px vacíos antes del título. */
  #servicios { padding-block: 0; }

  .pin-alto.con-pin { position: relative; }

  .con-pin .pin-clavado {
    position: sticky;
    top: var(--header-h);
    min-height: calc(100vh - var(--header-h));
    display: flex;
    flex-direction: column;
    justify-content: center;
  }

  /* Las cuatro tarjetas comparten la MISMA celda de grilla: por eso se
     superponen en vez de apilarse. El alto de la pila lo marca la más alta,
     así que al cambiar de tarjeta la caja no salta de tamaño. */
  .con-pin .servicios-lista {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0;
  }

  .con-pin .servicio {
    grid-area: 1 / 1;
    opacity: 0;
    visibility: hidden;
    transition: opacity 420ms ease,
                transform 420ms cubic-bezier(0.22, 1, 0.36, 1),
                visibility 0s linear 420ms;
  }

  /* visibility además de opacity: una tarjeta en opacity:0 sigue siendo
     clickeable y sus enlaces siguen entrando en el recorrido del tabulador.
     El delay en la transición de visibility es para que no desaparezca de
     golpe antes de terminar de desvanecerse. */
  .con-pin .servicio.is-activa {
    opacity: 1;
    visibility: visible;
    transition-delay: 0s;
  }

  /* La que todavía no llegó espera abajo, la que ya pasó se va para arriba:
     el movimiento cuenta hacia dónde va el scroll. Sin esto el cambio se
     nota poco si el visitante está leyendo en vez de mirando. */
  .con-pin .servicio           { transform: translateY(26px); }
  .con-pin .servicio.ya-paso   { transform: translateY(-26px); }
  .con-pin .servicio.is-activa { transform: translateY(0); }

  /* El hover no puede mover la tarjeta acá adentro: usa el mismo transform
     que la transición de entrada y salida, y se pisarían. */
  .con-pin .servicio.is-activa:hover { transform: translateY(0); }

  .con-pin .pin-progreso { display: block; }
}

/* Barra de avance. Escondida por defecto: sin pin no significa nada. */
.pin-progreso {
  display: none;
  height: 2px;
  margin-top: var(--sp-10, 2.5rem);
  background: var(--c-border);
  border-radius: 2px;
  overflow: hidden;
}

.pin-progreso > span {
  display: block;
  height: 100%;
  width: 0;
  background: var(--c-accent);
  border-radius: 2px;
}

@media (prefers-reduced-motion: reduce) {
  .con-pin .servicio { transition: none; }
}

/* ---- Índice de servicios (solo con el pin) ----
   Con el pin se ve una tarjeta por vez, y hasta el 27/09 no había forma de
   saber cuáles venían ni de ir directo a una: para comparar había que
   acordarse de las anteriores. El índice muestra los cinco nombres, marca el
   que está a la vista y lleva a cualquiera con un clic (main.js calcula a qué
   altura del recorrido aparece cada tarjeta).

   Sin pin —celular, movimiento reducido o sin JavaScript— las tarjetas están
   todas a la vista y el índice sobra, así que ni se dibuja. */
.servicios-indice { display: none; }

@media (min-width: 900px) {
  .con-pin .servicios-indice {
    display: flex;
    flex-direction: column;
    margin: var(--sp-6) 0 var(--sp-8);
    padding: 0;
    list-style: none;
  }
}

.servicios-indice a {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-height: 40px;
  font-weight: 600;
  color: var(--c-text-muted);
  transition: color 200ms ease;
}

/* La rayita crece en el que está activo. Es horizontal y va con transform:
   anima barato y no mueve el texto. */
.servicios-indice a::before {
  content: "";
  flex: none;
  width: 20px;
  height: 2px;
  border-radius: 2px;
  background: var(--c-accent);
  opacity: 0.45;
  transform: scaleX(0.3);
  transform-origin: left;
  transition: transform 280ms cubic-bezier(0.23, 1, 0.32, 1), opacity 200ms ease;
}

.servicios-indice a[aria-current="true"] { color: var(--c-text); }

.servicios-indice a[aria-current="true"]::before {
  opacity: 1;
  transform: scaleX(1);
}

@media (hover: hover) and (pointer: fine) {
  .servicios-indice a:hover { color: var(--c-text); }
}

/* Con índice, la nota "¿No sabés cuál te sirve?" pierde el margen grande:
   índice, nota y botón se leen como un solo bloque. */
.con-pin .servicios-fijo__nota { margin-bottom: var(--sp-5, 1.25rem); }

/* ---- Tarjetas plegables en celular (solo la home) ----
   En una pantalla de 390px las cinco tarjetas completas medían unos 4.300px:
   cinco pantallas de scroll antes de llegar a la sección de IA. Plegadas
   muestran ícono, nombre y la frase que explica el servicio, y el botón
   "Ver qué incluye" abre la lista, el "para quién" y la consulta.

   Todo cuelga de .servicios-plegables, que main.js pone solo abajo de 900px.
   Sin JavaScript las tarjetas quedan completas, como antes. */
.servicio__abrir {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: 44px;
  font-weight: 600;
  color: var(--c-accent-ink);
}

.servicio__abrir[hidden] { display: none; }

.servicio__abrir svg {
  width: 18px;
  height: 18px;
  stroke: currentColor;
  fill: none;
  stroke-width: 2;
  transition: transform 220ms cubic-bezier(0.23, 1, 0.32, 1);
}

.servicio__abrir[aria-expanded="true"] svg { transform: rotate(180deg); }

.servicios-plegables .servicio { padding: var(--sp-6); }
.servicios-plegables .servicio__intro { margin-bottom: var(--sp-2); }
.servicios-plegables .servicio__detalle { padding-top: var(--sp-4); }
.servicios-plegables .servicio__detalle:not(.is-abierto) { display: none; }

.servicios-plegables .servicio__detalle.is-abierto {
  animation: detalle-entra 240ms cubic-bezier(0.23, 1, 0.32, 1);
}

@keyframes detalle-entra {
  from { opacity: 0; transform: translateY(-6px); }
}

@media (prefers-reduced-motion: reduce) {
  .servicios-plegables .servicio__detalle.is-abierto { animation: none; }
  .servicio__abrir svg { transition: none; }
}


/* ============================================================
   Estudio — presentación en dos columnas y tarjetas numeradas
   ============================================================ */

.estudio-doble {
  display: grid;
  gap: var(--sp-12);
  grid-template-columns: 1fr;
  align-items: start;
}

@media (min-width: 900px) {
  /* La izquierda un poco más angosta que la derecha: es texto corrido y por
     encima de 70 caracteres por renglón se vuelve incómodo de leer. */
  .estudio-doble { grid-template-columns: 0.92fr 1.08fr; gap: var(--sp-16); }
}

/* :not(.volanta) no es un detalle: la volanta también es un <p> hijo directo,
   así que sin la exclusión se comía su color celeste y encima le sumaba un
   margen superior de 20px que ninguna otra sección tiene. Eso hacía que esta
   columna arrancara 19px más abajo que la de al lado. */
.estudio-doble__texto > p:not(.volanta) {
  color: var(--c-text-muted);
  margin-top: var(--sp-5, 1.25rem);
}

/* Un solo párrafo cargando toda la presentación: va un punto más grande que
   el texto corrido normal, para que tenga el peso de una bajada y no el de
   un párrafo suelto. El <strong> del nombre es lo único que se destaca. */
.estudio-doble__lede {
  font-size: 1.0625rem;
  line-height: 1.65;
  max-width: 46ch;
}

.estudio-doble__lede strong { color: var(--c-text); font-weight: 700; }
.estudio-doble__texto h2 { margin-bottom: var(--sp-2); }

/* ---- Píldoras de tecnología ---- */
.pildoras {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  list-style: none;
  margin: var(--sp-8) 0 0;
  padding: 0;
}

.pildora {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.45rem var(--sp-4);
  border: 1px solid var(--c-border);
  border-radius: 999px;
  font-size: var(--fs-small);
  color: var(--c-text-muted);
}

/* El puntito de color: hace que la lista se lea como un conjunto y no como
   botones. Va en ::before para no ensuciar el HTML con spans vacíos. */
.pildora::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--c-accent);
  flex: none;
}

.estudio-doble__acciones {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-4);
  margin-top: var(--sp-8);
}

/* ---- Columna derecha ---- */
.estudio-doble__pruebas {
  display: flex;
  flex-direction: column;
  gap: var(--sp-5, 1.25rem);
}

.dato-grande {
  display: flex;
  align-items: center;
  gap: var(--sp-6);
  background: var(--c-superficie);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-lg);
  padding: var(--sp-8);
}

.dato-grande__cifra {
  font-size: clamp(2.6rem, 4.5vw, 3.6rem);
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--c-text);
  margin: 0;
  flex: none;
}

.dato-grande__texto {
  margin: 0;
  color: var(--c-text-muted);
  font-size: var(--fs-small);
  max-width: 30ch;
}

.capacidad {
  background: var(--c-superficie);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-lg);
  padding: var(--sp-6) var(--sp-8);
}

.capacidad__titulo {
  font-size: 1.0625rem;
  margin-bottom: var(--sp-2);
}

.capacidad p { color: var(--c-text-muted); margin: 0; }

/* ---- El proceso: línea de tiempo ----
   Sin tarjetas a propósito. Con el molde de tarjeta (superficie, borde,
   esquinas) el bloque se leía como una sección más, huérfana: era la misma
   caja que Servicios, las capacidades y los testimonios. Los números sobre
   una línea que los une hacen que el 01–04 signifique orden de verdad.

   En pantallas anchas la línea es horizontal y los pasos van en fila; en
   angostas la línea baja por la izquierda y los pasos se apilan. El anillo
   del color del fondo alrededor de cada número es lo que "corta" la línea
   para que no lo atraviese. */
.numeradas {
  display: grid;
  gap: var(--sp-8);
  grid-template-columns: 1fr;
  position: relative;
}

/* línea vertical (pantallas angostas): pasa por el centro de los números */
.numeradas::before {
  content: "";
  position: absolute;
  left: 20px;
  top: 10px;
  bottom: 10px;
  width: 2px;
  background: linear-gradient(180deg, transparent, var(--c-border) 6%, var(--c-border) 94%, transparent);
}

.numerada { position: relative; }

.numerada__cabeza {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  margin-bottom: var(--sp-3);
}

.numerada__numero {
  flex: none;
  width: 42px;
  height: 42px;
  display: grid;
  place-content: center;
  border-radius: var(--radius);
  background: var(--c-accent);
  color: var(--c-on-accent, #05202F);   /* 7.0:1 sobre el cian */
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  position: relative;
  z-index: 1;
  /* el anillo que interrumpe la línea al pasar por atrás del número */
  box-shadow: 0 0 0 6px var(--c-bg);
}

.numerada h4 { margin: 0; font-size: 1.0625rem; line-height: 1.25; }

.numerada p {
  color: var(--c-text-muted);
  margin: 0;
  /* alineado con el título, no con el número: en angosto la línea vertical
     pasa por la izquierda y el texto no debe pisarla */
  padding-left: calc(42px + var(--sp-4));
}

@media (min-width: 900px) {
  .numeradas { grid-template-columns: repeat(4, 1fr); gap: var(--sp-8); }

  /* línea horizontal: a la altura del centro de los números (21px) */
  .numeradas::before {
    left: 2%;
    right: 2%;
    top: 21px;
    bottom: auto;
    width: auto;
    height: 2px;
    background: linear-gradient(90deg, transparent, var(--c-border) 6%, var(--c-border) 94%, transparent);
  }

  /* el número arriba, el título debajo: cada paso es una columnita */
  .numerada__cabeza {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--sp-4);
    margin-bottom: var(--sp-2);
  }

  .numerada p { padding-left: 0; font-size: 0.9375rem; }
}


/* ============================================================
   Resplandor de fondo fuera del hero
   ------------------------------------------------------------
   Misma receta que .hero__fondo, con dos diferencias:

   1. Se mueve más. La deriva del hero dura 26s y recorre poco, porque ahí
      compite con el titular que entra línea por línea. Acá dura 17s y
      recorre casi el doble.

   2. Solo se anima mientras la sección está en pantalla. main.js pone y
      saca .glow-activo con un IntersectionObserver. Sin eso el navegador
      sostiene dos animaciones con blur para siempre, aunque estén a tres
      pantallas de distancia, y eso se paga en el scroll de un celular.
   ============================================================ */

.fondo-glow {
  position: absolute;
  inset: -45%;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(closest-side, rgba(0, 184, 212, 0.20), transparent 72%) 24% 30% / 58% 58% no-repeat,
    radial-gradient(closest-side, rgba(27, 69, 112, 0.48), transparent 72%) 76% 68% / 64% 64% no-repeat;
  filter: blur(16px);
}

.fondo-glow.glow-activo {
  animation: derivar-amplio 17s ease-in-out infinite alternate;
  will-change: transform;
}

@keyframes derivar-amplio {
  from { transform: translate3d(-6%, -4%, 0) scale(1); }
  to   { transform: translate3d(7%, 5%, 0) scale(1.16); }
}

/* El resplandor de la CTA es un poco más intenso: es el cierre de la página
   y no tiene contenido compitiéndole al lado. */
.fondo-glow--cta {
  background:
    radial-gradient(closest-side, rgba(0, 184, 212, 0.26), transparent 70%) 28% 42% / 62% 78% no-repeat,
    radial-gradient(closest-side, rgba(27, 69, 112, 0.55), transparent 72%) 74% 58% / 66% 82% no-repeat;
}

/* --- Contenedores --- */

/* En Servicios el recorte va en .pin-clavado, que ES el elemento sticky.
   Si se pusiera en la <section>, el sticky dejaría de pegarse. */
.pin-clavado {
  position: relative;
  overflow: hidden;
}

.pin-clavado > .container { position: relative; z-index: 1; }

.cta-final {
  position: relative;
  overflow: hidden;
}

.cta-final > .container { position: relative; z-index: 1; }

@media (prefers-reduced-motion: reduce) {
  .fondo-glow.glow-activo { animation: none; }
}


/* ============================================================
   Contacto — argumento a la izquierda, formulario a la derecha
   ============================================================ */

.contacto-doble {
  display: grid;
  gap: var(--sp-12);
  /* minmax(0, 1fr) y no 1fr a secas. Es la misma columna elástica pero con
     mínimo cero, y esa diferencia era el bug del contacto en celular.

     Un track `1fr` tiene mínimo automático: no baja del ancho mínimo de su
     contenido. Y adentro había dos cosas que se niegan a achicarse — el
     <select> nunca mide menos que su opción más larga, y .btn lleva
     white-space: nowrap con el texto más largo del sitio. Entre los dos
     estiraban la columna a 373px dentro de un contenedor de 342, y como el
     desborde queda recortado y no scrolleable, el texto aparecía cortado
     contra el borde derecho. */
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
  text-align: left;      /* .cta-final centra todo; acá no queremos eso */
}

@media (min-width: 900px) {
  .contacto-doble { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--sp-16); }
}

/* .cta-final centraba su contenido y ese centrado sube por herencia.
   Acá se reinicia para las dos columnas. */
.contacto-doble h2,
.contacto-doble p { text-align: left; margin-inline: 0; }

.contacto-doble__texto h2 { margin-bottom: var(--sp-4); }
.contacto-doble__texto .lede { color: var(--c-text-muted); }

.contacto-doble__nota {
  color: var(--c-text-muted);
  font-size: var(--fs-small);
  margin-top: var(--sp-5, 1.25rem);
  max-width: 46ch;
}

.contacto-doble__acciones { margin-top: var(--sp-8); }
.contacto-doble .cta-final__email { margin-top: var(--sp-6); }

/* ---- El formulario ---- */
.contacto-form {
  background: var(--c-superficie);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-lg);
  padding: var(--sp-8);
  display: flex;
  flex-direction: column;
  gap: var(--sp-5, 1.25rem);
}

.contacto-form__titulo {
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--c-accent-ink);
  margin: 0;
}

/* Nombre y negocio comparten renglón en pantallas anchas: son dos datos
   cortos y ponerlos uno debajo del otro alarga el formulario sin motivo. */
.contacto-form__par {
  display: grid;
  gap: var(--sp-4);
  grid-template-columns: 1fr;
}

@media (min-width: 560px) {
  .contacto-form__par { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
}

.campo { display: flex; flex-direction: column; gap: var(--sp-2); }

.campo label {
  font-size: var(--fs-small);
  font-weight: 600;
  color: var(--c-text);
}

.campo__opcional { font-weight: 400; color: var(--c-text-muted); }

.campo input,
.campo select,
.campo textarea {
  width: 100%;
  font: inherit;
  color: var(--c-text);
  background: var(--c-bg-dark);
  border: 1px solid var(--c-border);
  border-radius: var(--radius);
  padding: 0.7rem var(--sp-4);
  /* 44px de alto mínimo: es el tamaño por debajo del cual un dedo falla. */
  min-height: 44px;
  transition: border-color 200ms ease, box-shadow 200ms ease;
}

.campo textarea { resize: vertical; min-height: 88px; line-height: 1.5; }

/* Antes #62798D, anotado como 4.6:1, pero medido sobre el fondo real del
   campo (#04121F) daba 4.2:1. Este da 4.7:1 y sigue viéndose más apagado que
   lo que escribe la persona, que es la diferencia que importa. */
.campo input::placeholder,
.campo textarea::placeholder { color: var(--c-placeholder, #6A8196); }

.campo input:focus-visible,
.campo select:focus-visible,
.campo textarea:focus-visible {
  outline: none;
  border-color: var(--c-accent);
  /* El aro además del color: quien no distingue el cian del gris necesita
     una señal de foco que no dependa del color. */
  box-shadow: 0 0 0 3px rgba(0, 184, 212, 0.28);
}

/* La flecha del select dibujada a mano: la nativa se pinta con los colores
   del sistema y en un campo oscuro suele quedar negra sobre negro. */
.campo select {
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239FB4C6' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--sp-4) center;
  background-size: 18px;
  padding-right: var(--sp-10, 2.5rem);
}

/* El desplegable abierto lo pinta el sistema operativo, no esta hoja: sin
   esto, en Windows las opciones salen blancas sobre blanco. */
.campo select option { background: #08131F; color: var(--c-text); }

.contacto-form__aviso {
  margin: 0;
  font-size: var(--fs-small);
  color: var(--c-text-muted);
}

@media (prefers-reduced-motion: reduce) {
  .campo input, .campo select, .campo textarea { transition: none; }
}


/* ============================================================
   Testimonios
   ============================================================
   Hubo un intento de poner el logo del cliente en cada pie. Se sacó: de las
   cuatro reseñas solo tres tienen logo, y una tarjeta sin él al lado de tres
   con él se lee como un error, no como una variante. Tres cuartos de una
   idea aplicada es peor que la idea sin aplicar.
   ============================================================ */

.testimonio__pie {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.15rem;
}


/* Acá había un segundo `#servicios.section { padding-block: 0 }` fuera de
   todo media query. Era un duplicado de la regla que ya vive dentro del
   bloque de 900px, y como esta no tenía condición, aplicaba también en
   celular — donde el pin está apagado y ese relleno SÍ hace falta.
   Consecuencia: "Qué hace Zaiwebs" quedaba pegado a la tira de logos y la
   última tarjeta pegada a Proyectos, las dos con 0px de separación. */


/* ============================================================
   Ajustes táctiles — celular y tablet
   ------------------------------------------------------------
   Abajo de 900px todo se toca con el dedo, y el mínimo por debajo del cual
   se falla es 44x44. Estos enlaces medían entre 17 y 29px de alto: no es que
   se vieran mal, es que erraban al tocarlos.

   Se resuelve con padding y margen negativo: el área de toque crece pero el
   texto queda donde estaba, así que no cambia el diseño ni un píxel.
   ============================================================ */

@media (max-width: 899px) {

  /* "Ver sitio" de cada tarjeta de proyecto: medía 26px */
  .portfolio-card__link {
    padding-block: var(--sp-3);
    margin-block: calc(var(--sp-3) * -1);
  }

  /* Enlaces del pie: medían 17px. La clase real es .site-footer__list, no
     __nav — el primer intento apuntó a un selector que no existe.

     min-height en vez de padding a ojo: con padding quedaban en 42px, dos
     por debajo del mínimo. Así el número es el número. */
  .site-footer__list a,
  .site-footer__bottom a,
  .cta-final__email a,
  .contacto-doble__texto a[href^="mailto:"] {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }

  /* El logo del header medía 28px de alto como zona de toque. */
  .site-header__logo {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }

  /* El rubro de cada proyecto estaba en 11.2px, por debajo de lo cómodo
     de leer en una pantalla chica sostenida a distancia de brazo. */
  .portfolio-card__rubro { font-size: 0.75rem; }
}


/* ============================================================
   Carruseles de celular
   ------------------------------------------------------------
   Proyectos y Testimonios apilan sus tarjetas una debajo de otra, y en una
   pantalla de 390px eso son 1.700 y 1.400px de scroll para tres y cuatro
   elementos que se comparan entre sí. Deslizando de costado ocupan el alto
   de uno solo y se comparan mejor.

   Es CSS puro, sin JavaScript: scroll-snap se encarga de que cada tarjeta
   quede centrada al soltar el dedo, y el navegador aporta la inercia. Un
   carrusel con JS acá sería peor: más código, peor rendimiento y perdería el
   scroll nativo del sistema.
   ============================================================ */

@media (max-width: 899px) {

  .portfolio-preview-grid,
  .testimonios-grid {
    display: flex;
    gap: var(--sp-4);
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    /* El padding lateral y el margen negativo hacen que las tarjetas puedan
       llegar hasta el borde de la pantalla al deslizar, en vez de frenar
       contra el margen del container. Eso es lo que le da la sensación de
       carrusel y no de caja con scroll. */
    padding-inline: var(--sp-6);
    margin-inline: calc(var(--sp-6) * -1);
    padding-bottom: var(--sp-4);
    scroll-padding-inline: var(--sp-6);
    /* Sin barra a la vista: en celular no se usa y ocupa lugar. */
    scrollbar-width: none;
  }

  .portfolio-preview-grid::-webkit-scrollbar,
  .testimonios-grid::-webkit-scrollbar { display: none; }

  .portfolio-preview-grid > *,
  .testimonios-grid > * {
    /* 86% deja asomar la tarjeta siguiente. Ese borde asomando es lo que
       avisa que hay más para el costado; con 100% nadie desliza. */
    flex: 0 0 86%;
    scroll-snap-align: start;
    max-width: none;
  }

  /* La tarjeta de proyecto es flex en columna y con ancho fijo se estiraba;
     esto la deja crecer solo lo que necesita. */
  .portfolio-preview-grid .portfolio-card { height: auto; }
}

/* ============================================================
   Contacto en pantalla angosta — que nada empuje la columna
   ============================================================ */

/* El minmax(0,1fr) de arriba permite que la columna se achique; esto permite
   que el contenido acompañe. Sin min-width:0 los hijos de un flex o un grid
   tampoco bajan de su ancho mínimo, así que el arreglo quedaba a mitad. */
.contacto-form,
.contacto-form__par,
.campo { min-width: 0; }

.campo input,
.campo select,
.campo textarea { min-width: 0; max-width: 100%; }

@media (max-width: 899px) {
  /* "Escribir por WhatsApp sin formulario" es el texto de botón más largo del
     sitio: 342px en una sola línea, justo el ancho útil de una pantalla de
     390. El white-space: nowrap general de .btn está bien para botones cortos,
     pero acá hay que levantarlo o el botón sobresale sí o sí. */
  .contacto-doble__acciones .btn {
    white-space: normal;
    text-align: center;
    line-height: 1.35;
    padding-block: 0.8rem;
  }

  /* De paso ocupa todo el ancho: un botón suelto de 342px en una columna de
     342 ya estaba a ancho completo de hecho, así que esto solo lo formaliza y
     evita que quede un pixel colgando. */
  .contacto-doble__acciones { display: flex; }
  .contacto-doble__acciones .btn { flex: 1; }
}


/* ============================================================
   Automatización con IA — argumento a la izquierda, conversación
   de ejemplo a la derecha
   ------------------------------------------------------------
   Va en el tono más profundo y con filete arriba y abajo: queda entre
   Servicios (fondo base) y Proyectos (banda alternada), y así se despega
   de las dos en vez de fundirse con alguna.
   ============================================================ */

.seccion-ia {
  position: relative;
  background: var(--c-bg-dark);
  border-block: 1px solid var(--c-border);
}

.ia-doble {
  display: grid;
  gap: var(--sp-12);
  /* minmax(0, …) por el mismo motivo que en Contacto: sin mínimo cero, una
     burbuja o una píldora larga estira la columna y desborda en celular. */
  grid-template-columns: minmax(0, 1fr);
  align-items: center;
}

@media (min-width: 900px) {
  .ia-doble {
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
    gap: var(--sp-16);
  }
}

.ia-doble__texto h2 { margin-bottom: var(--sp-2); }
.ia-doble__texto .lede { max-width: 50ch; }

/* Tres ideas cortas, SIN tarjetas: con la conversación al lado, tres cajas
   más convertían la sección en una grilla de cuatro rectángulos que
   competían con el chat. Un filete a la izquierda alcanza para agruparlas. */
.ia-puntos {
  display: grid;
  gap: var(--sp-5, 1.25rem);
  margin-top: var(--sp-8);
}

.ia-puntos li {
  padding-left: var(--sp-5, 1.25rem);
  border-left: 2px solid var(--c-border);
}

.ia-puntos h3 {
  font-size: 1.0625rem;
  margin-bottom: var(--sp-1);
  color: var(--c-text);
}

.ia-puntos p {
  margin: 0;
  font-size: 0.9375rem;
  color: var(--c-text-muted);
}

.ia-doble__rubros {
  margin-top: var(--sp-8);
  font-size: var(--fs-small);
  font-weight: 600;
  color: var(--c-text);
}

/* .pildoras trae 32px de margen arriba, pensado para ir después de un
   párrafo. Acá va pegada a su propio rótulo. */
.ia-doble__pildoras { margin-top: var(--sp-3); }

.ia-doble__ejemplos {
  margin-top: var(--sp-4);
  max-width: 52ch;
  font-size: var(--fs-small);
  color: var(--c-text-muted);
}

.ia-doble__acciones {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-4);
  margin-top: var(--sp-8);
}

/* .btn fuerza display:inline-flex, que le gana al atributo hidden. Sin
   esto "Probá a Zai" se vería aunque el chat esté apagado. */
[data-zai-abrir][hidden] { display: none; }

/* ---- La conversación de ejemplo ---- */

.chat-demo {
  margin: 0;
  width: 100%;
  max-width: 460px;
  justify-self: center;
  background: var(--c-superficie);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-lg);
  overflow: hidden;
}

.chat-demo__cabeza {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5, 1.25rem);
  border-bottom: 1px solid var(--c-border);
}

.chat-demo__avatar {
  flex: none;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: var(--c-accent-soft);
  display: grid;
  place-content: center;
}

.chat-demo__avatar svg {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: var(--c-accent-ink);
  stroke-width: 2;
}

.chat-demo__quien {
  display: flex;
  flex-direction: column;
  line-height: 1.3;
}

.chat-demo__nombre {
  font-weight: 600;
  font-size: 0.9375rem;
  color: var(--c-text);
}

.chat-demo__estado {
  font-size: 0.8125rem;
  color: var(--c-accent-ink);
}

/* El fondo del chat es el tono base: las burbujas del asistente usan la
   superficie de las tarjetas y así se leen como objetos sobre un fondo. */
.chat-demo__mensajes {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  padding: var(--sp-5, 1.25rem);
  background: var(--c-bg);
  list-style: none;
}

.chat-msg {
  max-width: 85%;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding: 0.6rem 0.85rem 0.45rem;
  border-radius: 14px;
  font-size: 0.9375rem;
  line-height: 1.45;
  color: var(--c-text);
}

/* La hora: #9FB4C6 da 5.9:1 sobre la burbuja del cliente y 6.8:1 sobre la
   del asistente. */
.chat-msg time {
  align-self: flex-end;
  font-size: 0.6875rem;
  color: var(--c-text-muted);
  font-variant-numeric: tabular-nums;
}

/* Visto desde el teléfono del cliente: lo suyo a la derecha, el asistente
   a la izquierda. Es la convención que cualquiera reconoce de WhatsApp. */
.chat-msg--cliente {
  align-self: flex-end;
  background: var(--c-burbuja-cliente, #0E3A4A);
  border-bottom-right-radius: 4px;
}

.chat-msg--asistente {
  align-self: flex-start;
  background: var(--c-superficie);
  border: 1px solid var(--c-border);
  border-bottom-left-radius: 4px;
}

.chat-demo__derivacion {
  align-self: center;
  margin-top: var(--sp-2);
  padding: 0.35rem 0.8rem;
  border: 1px solid var(--c-border);
  border-radius: 999px;
  background: var(--c-bg-dark);
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--c-accent-ink);
  text-align: center;
}

.chat-demo__aviso {
  padding: var(--sp-3) var(--sp-5, 1.25rem);
  border-top: 1px solid var(--c-border);
  font-size: 0.8125rem;
  color: var(--c-text-muted);
}

/* ============================================================
   Primera sección (28/09)
   ------------------------------------------------------------
   El menú flotante es fixed: ya no ocupa lugar en el flujo. La primera
   sección de cada página suma su alto arriba, así el contenido arranca
   donde arrancaba antes y el brillo del hero pasa por detrás del menú.
   Cubre las tres formas de empezar que tiene el sitio: el hero de la
   home, el de las landings y la primera .section de portfolio y legales.
   ============================================================ */

body.tema-oscuro .hero {
  padding-top: calc(var(--header-h-mobile) + clamp(3rem, 6vw, 5.5rem));
}

body.tema-oscuro .lp-hero {
  padding-top: calc(var(--header-h-mobile) + clamp(2.5rem, 5vw, 4.5rem));
}

body.tema-oscuro main > .section:first-child {
  padding-top: calc(var(--header-h-mobile) + var(--section-y));
}

/* 404 y gracias (solo en el servidor) empiezan con .error-page y
   .thanks-page, que ya traen 96px arriba: con la píldora encima quedaban
   pegados a ella. */
body.tema-oscuro main > .error-page:first-child,
body.tema-oscuro main > .thanks-page:first-child {
  padding-top: calc(var(--header-h-mobile) + var(--sp-16));
}

/* En gracias el ícono quedaba corrido a la derecha (pages.css le pone
   margin-inline: auto var(--sp-6)) y la bajada, a la izquierda (max-width
   sin margen automático). */
.thanks-page__icon { margin: 0 auto var(--sp-6); }
.thanks-page .lede { margin-inline: auto; }

@media (min-width: 900px) {
  body.tema-oscuro .hero {
    padding-top: calc(var(--header-h) + clamp(3rem, 6vw, 5.5rem));
  }

  body.tema-oscuro .lp-hero {
    padding-top: calc(var(--header-h) + clamp(2.5rem, 5vw, 4.5rem));
  }

  body.tema-oscuro main > .section:first-child {
    padding-top: calc(var(--header-h) + var(--section-y));
  }

  body.tema-oscuro main > .error-page:first-child,
  body.tema-oscuro main > .thanks-page:first-child {
    padding-top: calc(var(--header-h) + var(--sp-16));
  }
}

/* ============================================================
   Automatización con IA: panel teñido (28/09)
   ------------------------------------------------------------
   La sección de IA es la única con superficie teñida de cian: en este
   estilo el cian marca lo que es IA. Adentro, el mismo reparto de antes
   (argumento a la izquierda, la charla con forma de celular a la derecha)
   y abajo, a lo ancho, las situaciones en las que rinde.
   ============================================================ */

.seccion-ia {
  background: var(--c-bg);
  border-block: 0;
}

.panel-ia {
  display: grid;
  gap: var(--sp-12);
  grid-template-columns: minmax(0, 1fr);
  align-items: center;
  padding: clamp(1.5rem, 4.5vw, 3.5rem);
  border: 1px solid var(--c-accent-border);
  border-radius: 20px;
  background:
    radial-gradient(90% 120% at 0% 0%, color-mix(in srgb, var(--c-accent) 13%, transparent), transparent 60%),
    linear-gradient(160deg, var(--c-accent-soft), var(--c-superficie) 70%);
}

@media (min-width: 900px) {
  .panel-ia {
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
    gap: var(--sp-12) var(--sp-16);
  }
}

.panel-ia__volanta {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  margin-bottom: var(--sp-4);
}

.panel-ia__volanta .volanta { margin: 0; }

.ai-badge {
  display: inline-flex;
  align-items: center;
  height: 22px;
  padding: 0 9px;
  border-radius: 999px;
  background: var(--c-accent);
  color: var(--c-on-accent);
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.06em;
}

/* Los tres puntos, como tarjetas chicas con su ícono */
.panel-ia .ia-puntos { gap: var(--sp-2); }

.panel-ia .ia-puntos li {
  display: flex;
  gap: var(--sp-4);
  padding: var(--sp-4);
  border: 1px solid var(--c-border);
  border-left-width: 1px;
  border-radius: 12px;
  background: rgba(2, 7, 13, 0.45);
  background: color-mix(in srgb, var(--c-bg-dark) 45%, transparent);
}

.ia-puntos__icono {
  flex: none;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: color-mix(in srgb, var(--c-accent) 12%, transparent);
}

.ia-puntos__icono svg {
  width: 17px;
  height: 17px;
  fill: none;
  stroke: var(--c-accent-ink);
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.panel-ia .ia-doble__acciones { align-items: center; }

/* Enlace de texto a la landing del asistente */
.enlace-flecha {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  min-height: 44px;
  font-weight: 600;
  color: var(--c-text);
}

.enlace-flecha svg {
  width: 1.1em;
  height: 1.1em;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform 200ms cubic-bezier(0.23, 1, 0.32, 1);
}

@media (hover: hover) and (pointer: fine) {
  .enlace-flecha:hover { color: #FFFFFF; }
  .enlace-flecha:hover svg { transform: translateX(3px); }
}

.panel-ia__rubros {
  grid-column: 1 / -1;
  padding-top: var(--sp-8);
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}

.panel-ia__rubros .ia-doble__rubros { margin-top: 0; }

/* El menú del celular abre a pantalla completa. Su fila de arriba queda
   en el mismo lugar que la píldora (12px de aire + 52 de alto), así el
   logo y la cruz no saltan al abrirlo. */
@media (max-width: 899px) {
  body.tema-oscuro .mobile-menu { padding-top: 12px; }

  body.tema-oscuro .mobile-menu__top {
    height: 52px;
    padding-left: 7px;
    margin-right: -3px;
  }

  body.tema-oscuro .mobile-menu__top img { height: 22px; width: 117px; }
}

/* ============================================================
   El teléfono de la sección de IA (28/09)
   ------------------------------------------------------------
   La charla de ejemplo dentro de un celular. Las burbujas son las de
   .chat-msg (las mismas de las landings); acá solo va lo del aparato
   y lo que cambia adentro de él. La reproducción la hace telefono.js.
   ============================================================ */

.telefono-escena {
  position: relative;
  isolation: isolate;
  margin: 0;
  width: 100%;
  /* Hasta 320px, pero en pantallas bajas (una tablet acostada, una
     notebook de 720px) se achica para entrar entero debajo de la
     cabecera: 76px de cabecera y 36 de aire. Nunca menos de 240px. */
  max-width: 320px;
  max-width: min(320px, max(240px, (100vh - 112px) * 9 / 19.5));
  max-width: min(320px, max(240px, (100svh - 112px) * 9 / 19.5));
  justify-self: center;
  container: telefono / inline-size;
  display: grid;
  gap: var(--sp-4);
}

/* Un resplandor cian detrás del aparato: lo separa del panel teñido */
.telefono-escena::before {
  content: "";
  position: absolute;
  inset: 6% -20% 18%;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--c-accent) 22%, transparent), transparent 72%);
  filter: blur(20px);
}

/* Siempre con la forma de un celular de verdad (9 × 19,5), sin importar
   cuánto texto tenga la charla: lo que no entra se scrollea adentro de
   la pantalla. Los min-width y min-height en 0 evitan que el contenido
   lo agrande. */
.telefono {
  position: relative;
  display: flex;
  flex-direction: column;
  width: 100%;
  min-width: 0;
  min-height: 0;
  aspect-ratio: 9 / 19.5;
  padding: 9px;
  border-radius: 46px;
  background: linear-gradient(160deg, var(--c-border-strong), var(--c-bg-dark) 42%, var(--c-superficie));
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, 0.08),
    inset 0 1px 0 rgba(255, 255, 255, 0.16),
    0 30px 60px -12px rgba(0, 0, 0, 0.65),
    0 12px 24px -8px rgba(0, 0, 0, 0.4);
}

/* Los botones de volumen y encendido, apenas asomados */
.telefono::before,
.telefono::after {
  content: "";
  position: absolute;
  width: 3px;
  border-radius: 2px;
  background: var(--c-border-strong);
}

.telefono::before { left: -2px; top: 112px; height: 52px; }
.telefono::after { right: -2px; top: 140px; height: 72px; }

.telefono__pantalla {
  position: relative;
  flex: 1 1 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  border-radius: 37px;
  overflow: hidden;
  background: var(--c-bg);
}

.telefono__estado {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  height: 40px;
  padding: 8px 22px 0 26px;
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--c-text);
  font-variant-numeric: tabular-nums;
}

.telefono__isla {
  width: 88px;
  height: 24px;
  border-radius: 999px;
  background: #000;
}

.telefono__iconos {
  justify-self: end;
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--c-text);
}

.telefono__iconos svg { height: 10px; width: auto; fill: currentColor; }

.telefono .telefono__cabeza {
  gap: var(--sp-2);
  padding: 10px 14px 10px 8px;
  background: var(--c-superficie);
}

.telefono__volver {
  flex: none;
  width: 22px;
  height: 22px;
  fill: none;
  stroke: var(--c-accent-ink);
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.telefono .chat-demo__avatar { width: 34px; height: 34px; }
.telefono .chat-demo__nombre { font-size: 0.875rem; }

.telefono .chat-demo__estado {
  min-height: 1.3em;
  font-size: 0.75rem;
  transition: color 200ms ease;
}

.telefono .chat-demo__estado.is-escribiendo { color: var(--c-text); font-style: italic; }

/* El fondo del chat con un punteado apenas visible, como el de las apps */
.telefono__mensajes {
  flex: 1 1 0;
  min-height: 0;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--c-border-strong) transparent;
  gap: 8px;
  padding: 14px 12px;
  background-color: var(--c-bg);
  background-image: radial-gradient(color-mix(in srgb, var(--c-text-muted) 10%, transparent) 1px, transparent 1.6px);
  background-size: 18px 18px;
}

/* Si la charla es corta, queda abajo, pegada al campo de escribir. Va con
   margen automático y no con justify-content: flex-end, que dejaría los
   primeros mensajes fuera del alcance del scroll. */
.telefono__mensajes > :first-child { margin-top: auto; }

.telefono__mensajes:focus-visible { outline-offset: -3px; }

/* Mientras se reproduce se ven siempre los últimos mensajes y no se
   scrollea; al terminar, telefono.js deja la charla abajo de todo. */
.telefono.is-animando .telefono__mensajes { justify-content: flex-end; overflow: hidden; }

/* Como en WhatsApp, la hora va al final del último renglón y no en uno
   propio. */
.telefono .chat-msg { display: flow-root; max-width: 86%; font-size: 0.875rem; }

.telefono .chat-msg time {
  float: right;
  display: inline-flex;
  align-items: center;
  gap: 3px;
  margin: 0.35rem -0.2rem -0.3rem 0.6rem;
}

.tildes {
  width: 16px;
  height: 11px;
  fill: none;
  stroke: var(--c-text-muted);
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: stroke 300ms ease;
}

/* Leído: las tildes pasan a cian cuando el asistente empieza a responder */
.tildes.is-leido,
.telefono:not(.is-animando) .tildes { stroke: var(--c-accent-ink); }

.telefono .chat-demo__derivacion {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.telefono .chat-demo__derivacion svg {
  flex: none;
  width: 13px;
  height: 13px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Los puntos de «escribiendo…» que telefono.js pone antes de cada respuesta */
.telefono__puntos {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 0.8rem 0.9rem;
}

.telefono__puntos span {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--c-text-muted);
  animation: telefono-punto 1.1s ease-in-out infinite;
}

.telefono__puntos span:nth-child(2) { animation-delay: 0.15s; }
.telefono__puntos span:nth-child(3) { animation-delay: 0.3s; }

@keyframes telefono-punto {
  0%, 80%, 100% { opacity: 0.35; transform: translateY(0); }
  40% { opacity: 1; transform: translateY(-3px); }
}

/* Mientras se reproduce, lo que todavía no llegó no ocupa lugar: cada
   mensaje nuevo entra abajo y empuja a los anteriores, como en el chat. */
.telefono.is-animando .telefono__mensajes > .is-oculto { display: none; }

/* Entra desde su propio lado: el cliente desde la derecha, el asistente
   desde la izquierda, la derivación desde el centro. */
.telefono .is-entrando { animation: telefono-entra 420ms cubic-bezier(0.23, 1, 0.32, 1) both; }
.telefono .chat-msg--cliente.is-entrando { transform-origin: bottom right; }
.telefono .chat-msg--asistente.is-entrando { transform-origin: bottom left; }
.telefono .chat-demo__derivacion.is-entrando { transform-origin: center; }

@keyframes telefono-entra {
  from { opacity: 0; transform: translateY(10px) scale(0.94); }
  to { opacity: 1; transform: none; }
}

.telefono__escribir {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px 6px;
  background: var(--c-superficie);
  border-top: 1px solid var(--c-border);
}

.telefono__campo {
  flex: 1;
  display: flex;
  align-items: center;
  height: 36px;
  padding: 0 14px;
  border: 1px solid var(--c-border);
  border-radius: 999px;
  background: var(--c-bg-dark);
  font-size: 0.8125rem;
  color: var(--c-placeholder);
}

.telefono__boton {
  flex: none;
  width: 36px;
  height: 36px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--c-accent);
  color: var(--c-on-accent);
}

.telefono__boton svg {
  width: 17px;
  height: 17px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
}

.telefono__barra {
  display: block;
  width: 110px;
  height: 4px;
  margin: 6px auto 8px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--c-text) 55%, transparent);
}

.telefono__pie {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2) var(--sp-4);
  font-size: 0.8125rem;
  color: var(--c-text-muted);
  text-align: center;
}

/* display:inline-flex le gana al atributo hidden: sin esto «Ver de nuevo»
   se veía mientras la charla se reproducía. */
.telefono__repetir[hidden] { display: none; }

.telefono__repetir {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 44px;
  padding: 0 var(--sp-2);
  font-weight: 600;
  color: var(--c-text);
}

.telefono__repetir svg {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform 300ms cubic-bezier(0.23, 1, 0.32, 1);
}

@media (hover: hover) and (pointer: fine) {
  .telefono__repetir:hover { color: #FFFFFF; }
  .telefono__repetir:hover svg { transform: rotate(-60deg); }
}

@media (max-width: 420px) {
  .telefono { border-radius: 40px; padding: 8px; }
  .telefono__pantalla { border-radius: 32px; }
}

/* Con el celular más angosto que 320px (en el celular, o achicado por
   el alto en una tablet acostada) la etiqueta ocupa dos renglones: deja
   de ser píldora y el texto va a la izquierda, junto al ícono. */
@container telefono (max-width: 319px) {
  .telefono .chat-demo__derivacion {
    border-radius: 12px;
    text-align: left;
  }
}

@media (prefers-reduced-motion: reduce) {
  .telefono .is-entrando { animation: none; }
  .telefono__puntos span { animation: none; }
}

/* ============ Idioma: ES / EN (23/10) ============
   Desde que existe zaiwebs.com/en/, la cabecera lleva un enlace corto al
   otro idioma, al lado de «Hablemos». Es un enlace y no un desplegable:
   con dos idiomas, el menú solo sumaba un clic. Va también en celular
   (el botón de «Hablemos» se esconde abajo de 640px; este no), porque
   quien llega de afuera a la versión en español tiene que verlo sin abrir
   el menú. En el menú móvil están los dos, con el actual marcado.
   El viejo .lang-switch de components.css (maqueta para pt-BR) ya no se
   usa en ninguna página. */
.idioma {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 36px;
  min-height: 36px;
  padding: 0 0.5rem;
  border-radius: 8px;
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--c-text-muted);
  text-decoration: none;
  transition: color 150ms ease, background-color 150ms ease;
}

@media (hover: hover) and (pointer: fine) {
  .idioma:hover {
    color: #FFFFFF;
    background: rgba(255, 255, 255, 0.06);
  }
}

@media (pointer: coarse) {
  .idioma { min-width: 44px; min-height: 44px; }
}

.mobile-menu__lang a[aria-current] {
  color: var(--c-text);
  border-color: var(--c-text-muted);
}

/* Nota chica debajo de los testimonios y del portfolio en inglés
   («Testimonials translated from Spanish.»). */
.testimonios-nota {
  margin: var(--sp-6) auto 0;
  max-width: 60ch;
  text-align: center;
  font-size: 0.8125rem;
  color: var(--c-text-muted);
}

