/* GENERADO POR scripts/build-css.mjs — NO EDITAR A MANO.
   Se edita el archivo suelto correspondiente y se corre `npm run build:css`.
   Fuentes, en orden de cascada:
     css/fonts.css
     css/reset.css
     css/variables.css
     css/main.css
     css/navbar.css
     css/contact.css
     css/footer.css
 */

/* ── css/fonts.css ────────────────────────────────── */
/* Fuentes self-hosted (subset latin) — reemplazan a Google Fonts.
   Descargadas de Google Fonts (SIL Open Font License 1.1). Solo el subset
   'latin' (U+0000–00FF), que cubre todo el español (ñ, á, é, í, ó, ú, ¿, ¡).
   font-display: swap para no bloquear el render del texto.

   Poppins: instancias estáticas (un archivo por peso).
   Sour Gummy: fuente variable — un solo archivo cubre el eje wght 400–900. */

/* ---- Poppins (body) ---- */
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../assets/fonts/poppins-400.woff2') format('woff2');
}
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('../assets/fonts/poppins-500.woff2') format('woff2');
}
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('../assets/fonts/poppins-600.woff2') format('woff2');
}
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('../assets/fonts/poppins-700.woff2') format('woff2');
}
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url('../assets/fonts/poppins-800.woff2') format('woff2');
}

/* ---- Sour Gummy (display) — variable, eje wght 400–900 ---- */
@font-face {
  font-family: 'Sour Gummy';
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url('../assets/fonts/sourgummy.woff2') format('woff2');
}

/* ── css/reset.css ────────────────────────────────── */
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  font-size: 16px;
  scroll-behavior: smooth;
  overflow-x: clip; /* clip ≠ hidden: no crea scroll container, no rompe position:sticky */
}

body {
  line-height: 1;
  -webkit-font-smoothing: antialiased;
}

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

picture {
  display: contents;
}

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

p, h1, h2, h3, h4, h5, h6 {
  overflow-wrap: break-word;
}

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

ul, ol {
  list-style: none;
}

/* ── css/variables.css ────────────────────────────────── */
:root {
  --design-width: 1440;  /* ancho de referencia del escalado desktop */

  /* Brand Colors */
  --color-purple:       #8768F5;
  --color-purple-mid:   #9F5FE8;
  --color-purple-light: #EDE9FE;
  --color-purple-bg:    #F5F0FF;
  --color-purple-dark:  #6B4FD8;
  --color-lila-2:       var(--color-brand-lila);   /* links/copy sobre fondo --color-purple (footer) */
  --color-orange:       #F97316;
  --color-yellow:       #FBBF24;
  --color-pink:         #EC4899;
  --color-teal:         #06B6D4;
  --color-blue:         #3B82F6;
  --color-green:        #10B981;

  /* Neutrals */
  --color-text:         #1A1A2E;
  --color-text-muted:   #6B7280;
  --color-text-soft:    #8391A1;   /* texto placeholder, etiquetas suaves */
  --color-bg:           #FFFFFF;
  --color-bg-alt:       #F9FAFB;
  --color-surface:      #F1F1F1;   /* fondo de componentes: chips, cards light, inputs */
  --color-border:       #E5E7EB;

  /* Typography */
  --font-display: 'Sour Gummy', cursive;
  --font-body:    'Poppins', sans-serif;

  /* Escala tipográfica fluida — única fuente de verdad para font-size */
  /* Mínimos derivados por proporción desde el diseño desktop — recalibrar cuando exista el frame mobile de Figma */
  --fs-xs:   0.75rem;
  --fs-sm:   clamp(0.8125rem, 0.77rem + 0.19vw, 0.9375rem);
  --fs-body: 1rem;
  --fs-lg:   clamp(1rem, 0.96rem + 0.19vw, 1.125rem);
  --fs-xl:   clamp(1.125rem, 1.05rem + 0.42vw, 1.25rem);
  --fs-2xl:  clamp(1.25rem, 1.1rem + 0.65vw, 1.5rem);
  --fs-h3:   clamp(1.3125rem, 1.11rem + 0.85vw, 1.875rem);
  --fs-4xl:  clamp(1.75rem, 1.38rem + 1.55vw, 2rem);
  --fs-h2:   clamp(1.75rem, 1.27rem + 2.07vw, 3.125rem);
  --fs-h1:   clamp(2.25rem, 1.72rem + 2.25vw, 3.75rem);
  --fs-5xl:  3rem;
  --fs-hero: clamp(3rem, 2.19rem + 3.47vw, 5.3125rem); /* candidato a ajuste con frame mobile */

  /* Spacing */
  --space-1:  0.25rem;
  --space-2:  0.5rem;
  --space-3:  0.75rem;
  --space-4:  1rem;
  --space-5:  1.25rem;
  --space-6:  1.5rem;
  --space-8:  2rem;
  --space-10: 2.5rem;
  --space-12: 3rem;
  --space-16: 4rem;
  --space-20: 5rem;
  --space-24: 6rem;
  --space-32: 8rem;

  /* Macro-espaciado fluido — ritmo vertical de secciones, sin media queries */
  --space-section:    clamp(3rem, 2rem + 5vw, 7.5rem);
  --space-section-sm: clamp(2rem, 1.5rem + 2.5vw, 4rem);
  --space-gap:        clamp(1rem, 0.8rem + 1vw, 2rem);
  --space-gap-lg:     clamp(1.5rem, 1rem + 2.5vw, 4rem);

  /* Layout */
  --container-max:     75rem;
  --container-padding: clamp(1rem, 0.5rem + 2vw, 2rem);

  /* Border radius */
  --radius-sm:   0.375rem;
  --radius-md:   0.75rem;
  --radius-lg:   1.25rem;
  --radius-xl:   1.5rem;
  --radius-2xl:  2rem;
  --radius-3xl:  3rem;
  --radius-full: 9999px;

  /* Shadows */
  --shadow-sm:  0 1px 3px rgba(0, 0, 0, 0.08);
  --shadow-md:  0 4px 12px rgba(0, 0, 0, 0.10);
  --shadow-lg:  0 10px 30px rgba(0, 0, 0, 0.12);
  --shadow-xl:  0 20px 60px rgba(0, 0, 0, 0.15);
  --shadow-purple: 0 8px 30px rgba(124, 58, 237, 0.35);

  /* ── Colores de marca (base) ──────────────────────────────────────────────
     Los hexes de marca viven aquí UNA sola vez. Las tokens semánticas de
     pill/tab/card y los componentes los referencian — no repetir hex sueltos. */
  --color-brand-teal:        #00C8CE;
  --color-brand-teal-dark:   #11AAB2;
  --color-brand-pink:        #FF53AB;
  --color-brand-magenta:     #F0288F;
  --color-brand-purple:      #9476FF;
  --color-brand-lila:        #C3B2FF;
  --color-brand-yellow:      #FFC10F;
  --color-brand-orange:      #FF7A00;
  --color-brand-green:       #61CE61;
  --color-brand-blue:        #1990F8;
  --color-brand-blue-strong: #196EF8;

  /* Variantes claras de borde (cards, testimonials) */
  --color-brand-yellow-soft: #FFE393;
  --color-brand-orange-soft: #FFA450;
  --color-brand-blue-soft:   #64B7FF;

  /* Utilitarios */
  --color-surface-hover: #f5f5f5;   /* hover de botones blancos */
  --color-border-mid:    #D6D6D6;
  --color-ink:           #1E1E1E;
  --color-pink-soft:     #FFD6D6;
  --color-purple-tint:   #F8F5FF;
  --color-skeleton-1:    #eeeeee;
  --color-skeleton-2:    #e0e0e0;

  /* Texto de las labels de customization (colores propios del frame Figma).
     Label 2 usa color distinto en desktop vs mobile a propósito (texto sobre
     fondo claro en desktop, crema sobre fondo de color en mobile). */
  /* −12% del rojo del frame (#EC4330, 3.88:1 con blanco) → 4.84:1. Las
     etiquetas 2 y 4 (crema sobre morado, ~3.7:1) se dejan: anotan la imagen
     de los teléfonos y entran en la excepción de texto incidental de 1.4.3. */
  --color-cust-label-1:        #D03B2A;
  --color-cust-label-2:        #3D200B;   /* desktop */
  --color-cust-label-2-mobile: #FFF9EF;   /* mobile (intencional) */
  --color-cust-label-3:        #1F3A91;
  --color-cust-label-4:        #FFF5E3;

  /* Marquee pill image colors */
  --color-pill-purple: var(--color-brand-purple);
  --color-pill-teal:   var(--color-brand-teal);
  --color-pill-pink:   var(--color-brand-pink);
  --color-pill-green:  var(--color-brand-green);
  --color-pill-yellow: var(--color-brand-yellow);

  /* Feature tabs */
  --color-tab-calendar: var(--color-brand-teal);
  --color-tab-diary:    var(--color-brand-yellow);
  --color-tab-chat:     var(--color-brand-orange);
  --color-tab-gallery:  var(--color-brand-lila);
  --color-tab-info:     var(--color-brand-green);
  --color-tab-obs:      var(--color-brand-pink);

  /* Fondos para texto blanco (value-cards de Solución y paneles de Personas) */
  /* Oscurecidos respecto al token de marca para que el texto blanco del cuerpo
     alcance 4.5:1. Son tokens propios y NO redefiniciones de
     --color-brand-magenta / --color-purple / --color-brand-teal-dark, que se
     usan como color de marca en toda la landing y no deben moverse: el borde de
     la carta sigue en el tono vivo, solo el panel de texto se oscurece. */
  --color-card-pink:          #DC2483;   /* −8% de #F0288F → 4.54:1 con blanco */
  --color-card-purple:        #7D60E3;   /* −7% de #8768F5 → 4.51:1 con blanco */
  /* Panel de "Papás y mamás": texto blanco como en las otras dos cartas, con
     el teal oscurecido (4.60:1). Sobre el teal claro de antes el blanco daba
     2.83:1. El borde de la carta sigue en el teal vivo. */
  --color-card-teal:          #0D8288;
  /* Texto de error de los formularios: variante tonal del rosa de marca. El
     #FF53AB que se usaba daba 2.75:1 sobre el gris del formulario — el mensaje
     que explica qué corregir era el texto menos legible de la página. Este da
     5.13:1 sobre ese gris y 5.55:1 sobre blanco. */
  --color-error-text:         #C41E74;
  --color-card-pink-border:   var(--color-brand-pink);
  --color-card-purple-border: var(--color-brand-purple);
  --color-card-blue:          var(--color-brand-blue-strong);
  --color-card-blue-border:   var(--color-brand-blue);

  /* Transitions */
  --transition-fast: 150ms ease;
  --transition-base: 250ms ease;
  --transition-slow: 400ms ease;

  /* ── Motion ────────────────────────────────────────────────────────────────
     Lenguaje: suave y "redondo", juguetón sin rebotar. Las salidas siempre más
     rápidas que las entradas. Solo se anima transform y opacity (salvo los
     trazos SVG que se dibujan una vez, excepción documentada en
     docs/ui-ux-audit.md §5.3). Los --transition-* de arriba se mantienen para
     el código existente; lo nuevo usa estos. */
  --motion-press:  100ms;   /* feedback al presionar */
  --motion-fast:   160ms;   /* hover, focus, microinteracciones */
  --motion-base:   240ms;   /* acordeón, pestañas, cambios de estado */
  --motion-reveal: 560ms;   /* revelados al entrar en pantalla */
  --motion-hero:   720ms;   /* secuencia de entrada del hero */
  --motion-exit:   180ms;   /* salidas */

  --ease-out-soft: cubic-bezier(0.22, 1, 0.36, 1);     /* entradas: frena largo, sin rebote */
  --ease-spring:   cubic-bezier(0.34, 1.36, 0.64, 1);  /* pops pequeños: ~4% de overshoot */
  --ease-in-soft:  cubic-bezier(0.4, 0, 1, 1);         /* salidas */
  --ease-in-out:   cubic-bezier(0.65, 0, 0.35, 1);     /* loops lentos (flotación) */

  --motion-stagger: 80ms;     /* desfase entre hermanos */
  --motion-rise:    1.5rem;   /* recorrido de un revelado */
  --motion-lift:    -3px;     /* elevación al hover: feedback, no desplazamiento */

  /* Anillo de foco: purple-dark sobre fondos claros (5.62:1 con blanco) y
     blanco sobre morado. 3px + offset para que no se confunda con el borde. */
  --focus-ring-color: var(--color-purple-dark);
  --focus-ring-width: 3px;
  --focus-ring-offset: 3px;

  /* Elevación teñida de marca (purple-dark), para hover/press de tarjetas. */
  --elev-1: 0 2px 6px rgba(107, 79, 216, 0.10), 0 1px 2px rgba(26, 26, 46, 0.06);
  --elev-2: 0 10px 24px rgba(107, 79, 216, 0.16), 0 2px 6px rgba(26, 26, 46, 0.06);
  --elev-3: 0 22px 48px rgba(107, 79, 216, 0.22), 0 4px 12px rgba(26, 26, 46, 0.08);
}

/* ── Escalado proporcional de font-size raíz ────────────────────────────────
   MOBILE (≤768px): 1rem = viewport / 768 × 16px.
   Todos los valores rem escalan en proporción al ancho desde el frame Figma
   mobile (768px). Piso 13px: texto cuerpo legible en pantallas muy pequeñas.

   DESKTOP (≥769px): 1rem = viewport / 1440 × 16px, acotado a [13px, 16px].
   El ancho de referencia es 1440 —no 1920— porque es la resolución real de la
   mayoría de portátiles. Con ÷1920 el root caía a 12px en un 1440 y a 8.5px en
   un 1024: el cuerpo quedaba en 11-16px y el público objetivo (directivos de
   jardín) leía texto demasiado pequeño.

   · ≥1440px → el techo de 16px lo congela. A 1920 el resultado es idéntico al
     de la calibración anterior: root 16px, contenedor 1200px. No hay regresión
     en pantallas grandes.
   · 769-1440px → escala proporcionalmente (8.5px → 16px sin el piso).
   · El piso de 13px cubre 769-1170px, donde el proporcional puro deja el cuerpo
     por debajo de 14px. Verificado sin scroll horizontal en 769/900/1024.

   El techo del clamp hace innecesario un freeze aparte por encima del ancho de
   referencia.

   Nota técnica: rem en media queries evalúa contra el font-size INICIAL del
   navegador (~16px), no contra este valor autor. Los breakpoints siguen
   disparando en los mismos píxeles absolutos de siempre.
   ────────────────────────────────────────────────────────────────────────── */
html {
  font-size: clamp(13px, calc(100vw / 768 * 16), 16px);
}

@media (min-width: 48.0625rem) {
  html {
    font-size: clamp(13px, calc(100vw / var(--design-width) * 16), 16px);
  }
}

/* ── Tokens tipográficos mobile (≤768px) — sin vw ──────────────────────────
   Por debajo de 624px el root queda fijo en 13px (piso del clamp), así que
   1rem = 13px en TODOS los teléfonos. Al eliminar el componente vw de estos
   tokens la fuente resultante es idéntica en cualquier ancho mobile — resuelve
   la inconsistencia entre dispositivos como iPhone 14 Pro Max vs Samsung S25 Ultra.

   En el rango 624-768px el root sí escala (13→16px), y estos valores rem
   escalan con él automáticamente — no se necesitan media queries intermedias.

   Los tokens sin vw (--fs-xs, --fs-body, --fs-5xl) ya eran consistentes; se
   omiten aquí para no duplicar. ──────────────────────────────────────────── */
@media (max-width: 48rem) {
  :root {
    --fs-sm:   0.8125rem;   /* 10.6px @ root 13px */
    --fs-lg:   1rem;        /* 13.0px @ root 13px */
    --fs-xl:   1.125rem;    /* 14.6px @ root 13px */
    --fs-2xl:  1.25rem;     /* 16.25px @ root 13px */
    --fs-h3:   1.4rem;      /* 18.2px @ root 13px */
    --fs-4xl:  1.75rem;     /* 22.75px @ root 13px */
    --fs-h2:   2.8rem;      /* 36.4px @ root 13px */
    --fs-h1:   2.375rem;    /* 30.9px @ root 13px */
    --fs-hero: 3.375rem;    /* 43.9px @ root 13px */
  }
}

/* ── css/main.css ────────────────────────────────── */
body {
  font-family: var(--font-body);
  font-size: var(--fs-body);
  color: var(--color-text);
  background-color: var(--color-bg);
  overflow-x: clip; /* clip ≠ hidden: no crea scroll container, no rompe position:sticky */
}

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

/* Shared section utilities */
.section-tag {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-4);
  border-radius: var(--radius-full);
  font-family: var(--font-body);
  /* Piso de 14px: --fs-sm daba 11px con el root en 13px. Afecta a las 8
     secciones que usan .section-tag. */
  font-size: max(14px, var(--fs-sm));
  font-weight: 600;
  /* --color-text-soft (#8391A1) sobre --color-surface (#F1F1F1) daba 2.85:1,
     muy por debajo del 4.5:1 de AA. --color-purple-dark da 4.98:1 y además
     convierte el rótulo en señal de marca en vez de ruido gris. Afecta a las
     8 secciones que usan .section-tag. */
  color: var(--color-purple-dark);
  background: var(--color-surface);
  /* --space-6, no --space-10: el rótulo quedaba más lejos de su título que el
     título del contenido y dejaba de leerse como parte del encabezado. */
  margin-bottom: var(--space-6);
}

/* Sticker dentro del rótulo de sección. */
.section-tag .sticker {
  font-size: 1.7em;
  margin-block: -0.35em;
  rotate: -8deg;
}

/* ── Etiqueta de acento ("sticker") ───────────────────────────────────────
   Palabras de acento en amarillo de marca sobre morado ("Sin líos.", "está
   conectado!", "¡Claro que sí!"). Sobre el morado de la sección el amarillo
   daba 2.36–2.42:1, por debajo del 3:1 de texto grande. La etiqueta pone
   purple-dark detrás de la palabra (3.45:1) y la inclina un poco, como una
   calcomanía: es el mismo amarillo y el mismo morado, con más presencia. */
.text-sticker {
  display: inline-block;
  padding: 0.02em 0.28em 0.08em;
  border-radius: 0.32em;
  background: var(--color-purple-dark);
  color: var(--color-brand-yellow);
  rotate: -2deg;
  /* Una etiqueta no se parte: si no cabe, baja entera a la línea siguiente. */
  white-space: nowrap;
  box-shadow: 0 0.08em 0 rgba(26, 26, 46, 0.25);
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}

/* ── Stickers 3D ────────────────────────────────────────────────────────────
   Emojis 3D (Fluent Emoji de Microsoft, licencia MIT — el mismo estilo de las
   caritas 3D del hero y de Solución) con tratamiento de calcomanía: borde
   blanco y sombra corta. El borde son cuatro drop-shadow en `em`, así escala
   con el tamaño del sticker. Miden 1em: el tamaño lo da el font-size del
   contenedor. Son imágenes estáticas: el filtro se pinta una vez. */
.sticker {
  display: block;
  width: 1em;
  height: 1em;
  flex-shrink: 0;
  object-fit: contain;
  filter:
    drop-shadow(0.045em 0 0 #fff)
    drop-shadow(-0.045em 0 0 #fff)
    drop-shadow(0 0.045em 0 #fff)
    drop-shadow(0 -0.045em 0 #fff)
    drop-shadow(0 0.08em 0.1em rgba(26, 26, 46, 0.22));
  transition: rotate var(--motion-base) var(--ease-spring), scale var(--motion-base) var(--ease-spring);
}

/* Guiño al pasar el mouse por el bloque que lo contiene. */
@media (hover: hover) {
  .section-tag:hover .sticker,
  .problem__card:hover .sticker,
  .customization__feature:hover .sticker,
  .solution__badge:hover .sticker {
    rotate: 8deg;
    scale: 1.12;
  }
}

/* ── Íconos (Phosphor duotone, inline) ─────────────────────────────────────
   Miden 1em: el tamaño lo da el font-size del contenedor. La capa de tono se
   colorea con --ico-tone y --ico-tone-opacity desde cada componente. */
.ico {
  display: block;
  width: 1em;
  height: 1em;
  flex-shrink: 0;
  fill: currentColor;
}

.ico-tone {
  fill: var(--ico-tone, currentColor);
  opacity: var(--ico-tone-opacity, 0.2);
}

.section-title {
  font-family: var(--font-display);
  font-size: var(--fs-h1);
  line-height: clamp(2.4rem, 1.7rem + 2.5vw, 4rem);
  color: var(--color-text);
  margin-bottom: var(--space-6);
}

.section-title strong {
  font-weight: 600;
}

.section-title__underline {
  position: absolute;
  left: 83%;
  bottom: -40%;
  transform: translateX(-50%);
  width: auto;
  max-width: 13.75rem;
  height: 1.125rem;
  object-fit: contain;
  pointer-events: none;
}

.underline-accent {
  position: relative;
  display: inline-block;
}

/* Subrayado — diseño Figma (node 3170:27432): 231 × 25px, mismo patrón que problem/solution/features */
.underline-accent .section-title__underline {
  left: 45%;
  bottom: -2rem;
  transform: translateX(-50%);
  width: 14.4375rem;
  height: 1.5625rem;
  max-width: none;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* Mínimo táctil de WCAG. Va como min-height a propósito: gana sobre el
     `height` explícito de las variantes, así que solo levanta a los que se
     quedan cortos —los rem se encogen entre 769 y ~1280px y bajo 624px, donde
     el root está en su piso de 13px— y no toca a los que ya cumplen. */
  min-height: 44px;
  padding: var(--space-3) var(--space-8);
  border-radius: var(--radius-full);
  font-family: var(--font-body);
  /* Piso de 14px: con el root en 13px (769–1170px y bajo 624px) --fs-body daba
     13px y el texto de los CTA quedaba por debajo de lo legible. */
  font-size: max(14px, var(--fs-body));
  font-weight: 600;
  cursor: pointer;
  /* Solo transform y color: la sombra de la elevación no se transiciona (es
     paint) — aparece con el hover, el movimiento lo pone el transform. */
  transition:
    transform var(--motion-fast) var(--ease-out-soft),
    background-color var(--motion-fast) ease,
    color var(--motion-fast) ease;
  border: none;
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
}

@media (hover: hover) {
  .btn:hover {
    transform: translateY(var(--motion-lift));
    box-shadow: var(--elev-2);
  }
}

.btn:active {
  transform: translateY(0) scale(0.97);
  box-shadow: var(--elev-1);
  transition-duration: var(--motion-press);
}

/* Dimensiones exactas del diseño Figma (node 3101:27793): 294.34 × 53px */
/* min-width y no width: con el piso de 14px el texto ya no cabía en los
   18.4rem fijos de la banda muerta (239px a root 13) y se partía en dos
   líneas. Así conserva el ancho de diseño y solo crece cuando hace falta. */
.btn-lg {
  width: auto;
  min-width: min(18.4rem, 100%);
  max-width: 100%;
  padding-inline: var(--space-6);
  white-space: nowrap;
  /* Entre 769 y ~1280px el root está en su piso de 13px y 3.3125rem daban
     43.1px: bajo el mínimo táctil de 44. Arriba de eso no cambia nada
     (a root 16 son 53px). */
  height: max(44px, 3.3125rem);
  padding-block: 0;
  border-radius: 1.65625rem;
  /* Mismo piso que .btn: --fs-sm daba 11.96px a 1024px. */
  font-size: max(14px, var(--fs-sm));
}

/* Fondo en --color-card-purple (−7% del morado de marca), no en --color-purple:
   con texto blanco el de marca da 3.94:1 y no llega al 4.5:1 de AA. Es el mismo
   token que ya usan las value-cards por la misma razón; a simple vista es el
   mismo morado. Hover/active bajan a purple-dark (5.62:1). */
.btn-primary {
  background: var(--color-card-purple);
  color: #fff;
}

.btn-primary:hover,
.btn-primary:active {
  background: var(--color-purple-dark);
}

/* Texto en purple-dark, no en purple: sobre blanco el morado de marca da
   3.94:1 y no cumple AA. Solo cambia la letra; el fondo sigue igual. */
.btn-outline {
  background: transparent;
  color: var(--color-purple-dark);
  border: 1.5px solid var(--color-purple);
}

.btn-outline:hover {
  background: var(--color-purple-light);
}

.btn-white {
  background: #fff;
  color: var(--color-purple-dark);
}

.btn-white:hover {
  background: var(--color-surface-hover);
}

/* ── Estado de éxito de los formularios ────────────────────────────────────
   Compartido por la landing (.faq__success) y la página de contacto
   (.contact__success): el envío correcto reemplaza al formulario entero por un
   solo mensaje centrado, en vez de dejar el form a medias con el botón trabado
   en "Enviando...". */
.form-success {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: var(--space-3);
  /* Padding lateral corto a propósito: el contenedor (.faq__form-wrap /
     .contact__right) ya aporta el suyo, y en desktop la columna del formulario
     de contacto mide 218px — cada píxel de más partía el correo a la mitad. */
  padding: var(--space-10) var(--space-2);
  /* Ocupa el hueco que dejó el formulario: sin esto la tarjeta se desploma y la
     página pega un salto justo cuando el visitante acabó de convertir. */
  flex: 1;
  min-height: 18rem;
}

.form-success[hidden] {
  display: none;
}

/* Al aparecer, la tarjeta de éxito entra con un pop suave y el ✓ se dibuja
   (trazo de una sola pasada). */
.form-success:not([hidden]) {
  animation: success-in var(--motion-reveal) var(--ease-out-soft);
}

.form-success:not([hidden]) .form-success__icon {
  animation: success-pop var(--motion-reveal) var(--ease-spring) 120ms both;
}

.form-success:not([hidden]) .form-success__icon polyline {
  stroke-dasharray: 26;
  stroke-dashoffset: 26;
  animation: success-draw 520ms var(--ease-out-soft) 380ms forwards;
}

@keyframes success-in {
  from { opacity: 0; scale: 0.96; }
}

@keyframes success-pop {
  from { opacity: 0; scale: 0.4; }
}

@keyframes success-draw {
  to { stroke-dashoffset: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .form-success:not([hidden]) .form-success__icon polyline {
    animation: none;
    stroke-dashoffset: 0;
  }
}

.form-success__icon {
  display: grid;
  place-items: center;
  width: max(56px, 3.5rem);
  height: max(56px, 3.5rem);
  border-radius: 50%;
  /* Verde más oscuro que --color-green: el check blanco sobre #10B981 da
     2.54:1 y WCAG 1.4.11 pide 3:1 para iconos que comunican información. */
  background: #059669;
  color: #fff;
  margin-bottom: var(--space-2);
}

.form-success__icon svg {
  width: 55%;
  height: 55%;
}

.form-success__title {
  font-family: var(--font-display);
  font-size: max(20px, var(--fs-h3));
  font-weight: 700;
  line-height: 1.2;
  color: var(--color-text);
}

.form-success__body {
  font-family: var(--font-body);
  font-size: max(14px, var(--fs-body));
  font-weight: 500;
  line-height: 1.5;
  color: var(--color-text-muted);
  max-width: 34ch;
}

.form-success__email {
  font-family: var(--font-body);
  font-size: max(13px, var(--fs-sm));
  font-weight: 500;
  line-height: 1.5;
  color: var(--color-text-muted);
  /* Un correo largo no debe desbordar la tarjeta en un móvil angosto. */
  overflow-wrap: anywhere;
  max-width: 100%;
}

.form-success__email strong {
  color: var(--color-text);
  font-weight: 600;
}

.form-success__email[hidden] {
  display: none;
}

/* Reveal animation classes (driven by GSAP) */
/* El ocultado va condicionado a `reveal-armed`, que pone un script inline en el
   <head> y que se quita solo si GSAP tarda demasiado o no llega.
   Antes era incondicional: 27 bloques de contenido —siete secciones enteras—
   quedaban invisibles hasta que GSAP cargaba desde un CDN de terceros. Medido:
   6,9 s en una 3G típica, 12,2 s en una mala, y PARA SIEMPRE si el CDN no
   responde. La animación es un adorno; el contenido no puede depender de ella. */
/* La regla vive en el <style> crítico de cada página, no acá: si llega con
   esta hoja externa el contenido se pinta visible y después se oculta. */

@keyframes float {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  33%       { transform: translateY(-0.75rem) rotate(3deg); }
  66%       { transform: translateY(-0.375rem) rotate(-2deg); }
}

@keyframes float-slow {
  0%, 100% { transform: translateY(0); }
  50%       { transform: translateY(-1.125rem); }
}

/* Ícono flotante entre secciones — altura cero, flota encima de ambas */
.section-float-icon {
  position: relative;
  height: 0;
  overflow: visible;
  display: flex;
  justify-content: center;
  z-index: 10;
}

.section-float-icon img {
  position: absolute;
  top: 50%;
  right: 10%;
  width: clamp(7rem, 12vw, 15rem);
  height: auto;
  pointer-events: none;
  filter: drop-shadow(0 8px 24px rgba(135, 104, 245, 0.25));
  animation: float-section-icon 3.5s ease-in-out infinite;
}

@keyframes float-section-icon {
  0%, 100% { transform: translateY(-50%); }
  33%       { transform: translateY(calc(-50% - 0.75rem)); }
  66%       { transform: translateY(calc(-50% - 0.375rem)); }
}

@media (prefers-reduced-motion: reduce) {
  .section-float-icon img {
    animation: none;
    transform: translateY(-50%);
  }
}

/* Línea animada entre testimonials y FAQ — idéntica a .steps__animated-line, solo mobile */
.tf-connector-line {
  display: none;
}

@media (prefers-reduced-motion: reduce) {
  .tf-connector-line path { animation: none; }
}

/* ── Foco visible ──────────────────────────────────────────────────────────
   Antes no había ninguno propio: todo dependía del anillo por defecto del
   navegador (1px, azul), que sobre los fondos morados casi no se ve. Un solo
   anillo para todo el sitio; las secciones moradas lo pasan a blanco
   redefiniendo --focus-ring-color (ver la lista de abajo). Las reglas
   :focus-visible más específicas que ya existen (puntos de carrusel, marquee,
   WhatsApp) siguen ganando. */
:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring-color);
  outline-offset: var(--focus-ring-offset);
}

/* Fondos morados o de color saturado: anillo blanco. */
.hero,
.features,
.steps,
.cta-final__card,
.footer,
.solution__badges,
.video-modal {
  --focus-ring-color: #fff;
}

/* ── Saltar al contenido ───────────────────────────────────────────────────
   Primer elemento enfocable de la página. Fuera de pantalla hasta que recibe
   foco con el teclado; z-index por encima del loader. */
.skip-link {
  position: fixed;
  top: var(--space-3);
  left: var(--space-3);
  z-index: 100000;
  padding: var(--space-3) var(--space-5);
  border-radius: var(--radius-full);
  font-family: var(--font-body);
  font-size: max(14px, var(--fs-sm));
  font-weight: 600;
  color: #fff;
  background: var(--color-purple-dark);
  text-decoration: none;
  transform: translateY(calc(-100% - var(--space-6)));
  transition: transform var(--motion-fast) var(--ease-out-soft);
}

.skip-link:focus-visible {
  transform: none;
  --focus-ring-color: var(--color-text);
}

/* Destino del skip link: recibe el foco por programa (tabindex="-1"), no es
   un control, así que no pinta anillo alrededor de toda la página. */
#contenido:focus {
  outline: none;
}

/* ── Utilidades de motion ──────────────────────────────────────────────────
   .reveal (opacidad) se arma en el <style> crítico del <head>. Estas son
   variantes que se suman a él.

   .reveal--rise: además sube. Usa la propiedad `translate`, NO `transform`:
   varios bloques reciben un transform de GSAP o de su propio layout (abanico
   de Personas, cards rotadas) y un translateY acá se los pisaba. `translate`
   compone con `transform` en vez de reemplazarlo. */
.reveal-armed .reveal--rise {
  translate: 0 var(--motion-rise);
  transition:
    opacity var(--motion-reveal) var(--ease-out-soft),
    translate var(--motion-reveal) var(--ease-out-soft);
  transition-delay: calc(var(--reveal-order, 0) * var(--motion-stagger));
}

.reveal-armed .reveal--rise.is-visible {
  translate: none;
}

/* .reveal--pop: entra creciendo desde 92%, con el overshoot suave. Para
   elementos chicos (insignias, íconos, números). */
.reveal-armed .reveal--pop {
  scale: 0.92;
  transition:
    opacity var(--motion-reveal) var(--ease-out-soft),
    scale var(--motion-reveal) var(--ease-spring);
  transition-delay: calc(var(--reveal-order, 0) * var(--motion-stagger));
}

.reveal-armed .reveal--pop.is-visible {
  scale: none;
}

/* .btn--shine: un reflejo que cruza el botón al pasar el mouse. Es un
   pseudo-elemento que se traslada (transform), no un gradiente animado.
   --shine-color se ajusta por variante: blanco sobre botones de color,
   morado tenue sobre los blancos (un reflejo blanco no se vería). */
.btn--shine {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  --shine-color: rgba(255, 255, 255, 0.45);
}

.btn-white.btn--shine {
  --shine-color: rgba(135, 104, 245, 0.22);
}

.btn--shine::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(105deg, transparent 30%, var(--shine-color) 50%, transparent 70%);
  translate: -110% 0;
  pointer-events: none;
}

@media (hover: hover) {
  .btn--shine:hover::after {
    translate: 110% 0;
    transition: translate 700ms var(--ease-out-soft);
  }
}

/* .btn--shine-once: además cruza una vez sola al terminar la entrada, para
   señalar la acción principal sin parpadeo ni bucle. */
@keyframes shine-sweep {
  from { translate: -110% 0; }
  to   { translate: 110% 0; }
}

.btn--shine-once::after {
  animation: shine-sweep 900ms var(--ease-out-soft) 1.5s 1;
}

@media (prefers-reduced-motion: reduce) {
  .btn--shine-once::after { animation: none; }
}

/* .lift: elevación al hover para tarjetas. Solo el transform se anima. */
.lift {
  transition: transform var(--motion-fast) var(--ease-out-soft);
}

@media (hover: hover) {
  .lift:hover {
    transform: translateY(var(--motion-lift));
  }
}

/* .float-slow: flotación lenta para mascotas e ilustraciones. Se pausa fuera
   de pantalla (js/motion.js marca .is-offscreen). */
@keyframes float-soft {
  0%, 100% { translate: 0 0; }
  50%       { translate: 0 -0.5rem; }
}

.float-slow {
  animation: float-soft 7s var(--ease-in-out) infinite;
}

/* Cualquier animación CSS continua se congela mientras está fuera de pantalla
   (js/motion.js pone .is-offscreen): el navegador la sigue calculando aunque no
   se vea. El !important es a propósito: los trazos SVG declaran su animación
   en un style="" inline, que gana a cualquier regla normal de hoja. */
.is-offscreen,
.is-offscreen * {
  animation-play-state: paused !important;
}

@media (prefers-reduced-motion: reduce) {
  .reveal-armed .reveal--rise,
  .reveal-armed .reveal--pop {
    translate: none;
    scale: none;
  }
  .float-slow {
    animation: none;
  }
}

/* Visually hidden but accessible to screen readers */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border-width: 0;
}

@media (max-width: 48rem) {
  .btn {
    padding: var(--space-3) var(--space-6);
  }

  .section-float-icon img {
    top: calc(50% + clamp(230px, 99px + 45.5vw, 448px));
    right: 1%;
    width: clamp(6.5rem, 3.9rem + 12.7vw, 10rem);
  }

  .tf-connector-line {
    display: block;
    position: absolute;
    top: clamp(3.75rem, 26.92vw, 13.5rem);
    right: clamp(-1.5rem, -3.125vw, -0.625rem);
    width: clamp(9rem, 34vw, 13.5rem);
    height: clamp(15rem, 58vw, 22.5rem);
    overflow: visible;
    pointer-events: none;
    z-index: 0;
    transform: rotate(115deg);
    transform-origin: top right;
  }
}

/* ── prefers-reduced-motion: regla global ─────────────────────────────────
   CLAUDE.md §5 la documentaba, pero no estaba implementada: solo había reglas
   sueltas por elemento en 12 archivos, así que la mayoría de los flotados
   decorativos seguían animándose para quien pide menos movimiento.

   `animation-iteration-count: 1` es la pieza que suele faltar en esta receta:
   con solo `animation-duration: 0.01ms`, una animación `infinite` cicla miles
   de veces por fotograma y queda en un punto ALEATORIO — ni se detiene ni es
   determinista. Esto era, medido, la mitad del ruido entre capturas de
   goldens (bandas de Problema y Testimonios/FAQ).

   Se respetan las reglas más específicas que ya existen (p. ej. el marquee,
   que pone `animation: none` y cede el movimiento a scroll nativo). */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ── css/navbar.css ────────────────────────────────── */
.navbar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  padding: var(--space-8) var(--space-6);
  /* Sin will-change permanente: una capa de compositor fija por elemento es la
     hipótesis #1 del jank de scroll en iOS (KNOWN-ISSUES.md). Un transform en
     un elemento fixed ya se compone barato.
     Reaparece frenando largo, sin el rebote de antes (overshoot del 56%). */
  transition: transform var(--motion-reveal) var(--ease-out-soft);
}

/* Al ocultar: salida corta y acelerada. */
.navbar--hidden {
  transform: translateY(-110%);
  transition-duration: var(--motion-base);
  transition-timing-function: var(--ease-in-soft);
  pointer-events: none;
}

/* Si alguien tabula hasta el navbar mientras está escondido, vuelve: un
   control enfocado no puede quedar fuera de la vista (WCAG 2.4.11). */
.navbar--hidden:focus-within {
  transform: none;
  pointer-events: auto;
}

.navbar__inner {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: #F1F1F1B2;
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-radius: 2.0625rem;
  padding: var(--space-3) var(--space-6);
  max-width: var(--container-max);
  margin-inline: auto;
}

/* Elevación al despegarse del tope (ui.js pone .scrolled pasados 40px). La
   sombra vive en un pseudo-elemento y lo que se anima es su opacidad: animar
   box-shadow repinta en cada frame. */
.navbar__inner::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  box-shadow: var(--elev-2);
  opacity: 0;
  transition: opacity var(--motion-base) ease;
  pointer-events: none;
}

.navbar.scrolled .navbar__inner::before {
  opacity: 1;
}

.navbar__logo {
  display: flex;
  align-items: center;
  text-decoration: none;
  /* El logo es un enlace al inicio: necesita el mismo objetivo táctil que
     el resto. Medía 63x42 en 1440 y 51x34 en 1024. */
  min-height: 44px;
}

.navbar__logo-img {
  height: 2.625rem;
  width: auto;
  transition: transform var(--motion-base) var(--ease-spring);
}

/* Guiño al pasar por el logo: un giro de 4°, nada más. */
@media (hover: hover) {
  .navbar__logo:hover .navbar__logo-img {
    transform: rotate(-4deg) scale(1.04);
  }
}

.navbar__logo-fallback {
  display: none;
  align-items: center;
  font-family: var(--font-display);
  font-size: var(--fs-xl);
  font-weight: 800;
  color: var(--color-purple);
}

.navbar__logo-fallback span {
  color: var(--color-orange);
}

.navbar__actions {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.btn-sm {
  min-width: 13.5625rem;
  /* min-height en px absolutos, no rem, A PROPÓSITO. Los 44px de objetivo
     táctil son una medida física del dedo: no deben encoger con el root
     escalado. Con `height: 2.4375rem` el botón caía a 32px en un viewport de
     1024 (root 13px) — el CTA principal del sitio por debajo del mínimo del
     checklist de CLAUDE.md §5. El `height` fluido se conserva como suelo de
     diseño; el min-height solo actúa cuando el root baja. */
  height: 2.4375rem;
  min-height: 44px;
  padding: 0.7rem 2.5rem;
  border-radius: var(--radius-full);
  /* max(14px, …) — el piso va en px absolutos por la misma razón que el
     min-height: 1rem vale 13px cuando el root baja, así que un piso en rem
     seguiría dando 11.4px en un viewport de 1024. Con --fs-xs caía a 9.75px.
     El root de este sitio ya es px literal (ver ARCHITECTURE-DECISION.md), así
     que esto no empeora el respeto a la preferencia de fuente del usuario:
     garantiza un mínimo legible en la navegación principal. */
  font-size: max(14px, clamp(0.875rem, 0.8rem + 0.25vw, 1rem));
  font-weight: 600;
  gap: 0.4375rem;
  line-height: 1;
  white-space: nowrap;
}

/* ── Hamburger button ── */
.navbar__hamburger {
  display: none;
  justify-content: center;
  align-items: center;
  width: 2.5rem;
  height: 2.5rem;
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  border-radius: var(--radius-md);
  transition:
    background-color var(--motion-fast) ease,
    transform var(--motion-fast) var(--ease-spring);
}

.navbar__hamburger:active {
  transform: scale(0.92);
  transition-duration: var(--motion-press);
}

/* Icono: tres barras con la geometría del hamburguesa de Figma — caja de
   22×15.85, barras largas de 21.9512×2.68293 y central de 16.4634. Al abrir,
   las dos largas rotan ±45° hasta el centro y la corta colapsa en el punto
   del nodo 4877:28919 — es el mismo botón, solo cambia el icono. */
.navbar__hamburger-icon {
  position: relative;
  display: block;
  width: 1.375rem;
  aspect-ratio: 21.9512 / 15.8536;
  pointer-events: none;
}

.navbar__hamburger-bar {
  position: absolute;
  left: 0;
  width: 100%;
  height: 16.923%;                 /* 2.68293 / 15.8536 */
  border-radius: var(--radius-full);
  background: var(--color-purple);
  transition: top var(--motion-base) var(--ease-out-soft),
              left var(--motion-base) var(--ease-out-soft),
              width var(--motion-base) var(--ease-out-soft),
              height var(--motion-base) var(--ease-out-soft),
              transform var(--motion-base) var(--ease-spring);
}

.navbar__hamburger-bar:nth-child(1) { top: 0; }
.navbar__hamburger-bar:nth-child(2) {
  top: 41.538%;                    /* 6.58521 / 15.8536 */
  left: 12.5%;                     /* 2.7439 / 21.9512 */
  width: 75%;                      /* 16.4634 / 21.9512 */
}
.navbar__hamburger-bar:nth-child(3) { top: 83.077%; }  /* 13.1707 / 15.8536 */

/* Abierto → X. El 245.45% es el desplazamiento hasta el centro del icono
   expresado en alturas de barra (41.538% / 16.923%). */
.navbar__hamburger.open .navbar__hamburger-bar:nth-child(1) {
  transform: translateY(245.45%) rotate(-45deg);
}

.navbar__hamburger.open .navbar__hamburger-bar:nth-child(2) {
  top: 40.539%;                    /* 50% − 18.923%/2 */
  left: 50%;
  width: 13.666%;                  /* punto de 3px: 3 / 21.9512 */
  height: 18.923%;                 /* 3 / 15.8536 */
  transform: translateX(-50%);
}

.navbar__hamburger.open .navbar__hamburger-bar:nth-child(3) {
  transform: translateY(-245.45%) rotate(45deg);
}

/* ── Mobile menu (Figma "Menu Perfil" 4879:28967 — frame 440px) ──
   Panel de 245×268 anclado bajo el hamburguesa, que queda embebido en su
   esquina superior derecha (círculo a 15px del borde derecho y 13px del
   superior). Todos los valores son la medida de Figma / 440 en vw, con piso
   y techo en rem. */
.navbar__mobile-menu {
  display: none;
  flex-direction: column;
  position: absolute;
  top: calc(2.25rem - clamp(0.5rem, 2.955vw, 1.25rem));    /* 13 sobre el hamburguesa */
  right: calc(2rem - clamp(0.625rem, 3.409vw, 1.5rem));    /* 15 a la derecha del hamburguesa */
  z-index: 1;
  width: clamp(13rem, 60vw, 29rem);                        /* 245 escalado ~1.15x */
  padding: clamp(4rem, 19vw, 8.5rem)                       /* deja libre el círculo */
           clamp(0.75rem, 3.75vw, 1.75rem)
           clamp(1.25rem, 5.25vw, 2.25rem);
  gap: clamp(0.25rem, 1.25vw, 0.625rem);
  background: rgba(241, 241, 241, 0.75);
  border: 1px solid #fff;
  border-radius: clamp(0.625rem, 3.409vw, 1.5rem);         /* 15 */
  backdrop-filter: blur(4.7px);
  -webkit-backdrop-filter: blur(4.7px);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-0.5rem) scale(0.94);
  transform-origin: top right;
  transition: opacity var(--motion-exit) var(--ease-in-soft),
              transform var(--motion-exit) var(--ease-in-soft),
              visibility 0s linear var(--motion-exit);
}

.navbar__mobile-menu-logo {
  display: none;
}

.navbar__mobile-menu-logo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.navbar__mobile-menu.open {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition: opacity var(--motion-base) var(--ease-out-soft),
              transform var(--motion-reveal) var(--ease-spring),
              visibility 0s;
}

.navbar__mobile-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: clamp(2.375rem, 10vw, 4.25rem);                  /* 39 escalado ~1.15x */
  /* Pisos absolutos: el clamp en rem/vw daba 32px de alto y 11.4px de texto
     en un viewport de 320. Mismo criterio que .btn-sm. */
  min-height: 44px;
  padding: 0;
  border: none;
  border-radius: var(--radius-full);                       /* Figma 28 > alto/2 */
  font-family: var(--font-body);
  font-size: max(15px, clamp(0.875rem, 2.75vw, 1.375rem));
  font-weight: 600;
  line-height: 1;
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background var(--transition-fast), color var(--transition-fast);
}

/* Colores con contraste AA: el morado de marca como texto sobre el gris del
   panel daba ~3.5:1 y el blanco sobre morado 3.94:1; el blanco sobre el rosa
   de marca 2.97:1. Se usan los tokens oscurecidos que ya existen para eso. */
.navbar__mobile-btn--outline {
  background: #fff;
  border: 1.4px solid var(--color-purple);                 /* Figma 1.393 */
  color: var(--color-purple-dark);
}

.navbar__mobile-btn--primary {
  background: var(--color-card-purple);
  color: #fff;
}

.navbar__mobile-btn--whatsapp {
  background: var(--color-card-pink);
  color: #fff;
}

.navbar__mobile-btn:active {
  transform: scale(0.97);
}

/* Al abrir, los botones entran escalonados desde arriba (el panel crece desde
   la esquina del hamburguesa). Al cerrar se van todos juntos y rápido. */
.navbar__mobile-menu > .navbar__mobile-btn {
  opacity: 0;
  translate: 0 -0.5rem;
  transition:
    opacity var(--motion-exit) ease,
    translate var(--motion-exit) ease,
    background-color var(--motion-fast) ease,
    transform var(--motion-press) ease;
}

.navbar__mobile-menu.open > .navbar__mobile-btn {
  opacity: 1;
  translate: none;
  transition:
    opacity var(--motion-base) var(--ease-out-soft),
    translate var(--motion-base) var(--ease-out-soft),
    background-color var(--motion-fast) ease,
    transform var(--motion-press) ease;
}

/* nth-child: el primer hijo es el logo, los botones van del 2 al 5. */
.navbar__mobile-menu.open > .navbar__mobile-btn:nth-child(2) { transition-delay: 60ms, 60ms, 0s, 0s; }
.navbar__mobile-menu.open > .navbar__mobile-btn:nth-child(3) { transition-delay: 120ms, 120ms, 0s, 0s; }
.navbar__mobile-menu.open > .navbar__mobile-btn:nth-child(4) { transition-delay: 180ms, 180ms, 0s, 0s; }
.navbar__mobile-menu.open > .navbar__mobile-btn:nth-child(5) { transition-delay: 240ms, 240ms, 0s, 0s; }

.navbar__mobile-btn:disabled {
  cursor: not-allowed;
}

/* ── Language toggle ──
   Solo la variante circular de desktop se acota a .navbar__actions: dentro del
   menú mobile el mismo botón adopta la píldora de .navbar__mobile-btn. */
.navbar__actions .navbar__lang-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.4375rem;
  height: 2.4375rem;
  min-width: 44px;
  min-height: 44px;
  padding: 0;
  /* Fondo blanco: la barra es translúcida y sobre el morado del hero el
     purple-dark caía a 3.43:1. Sobre blanco son 5.62:1 pase lo que pase atrás. */
  background: #fff;
  border: 1.5px solid var(--color-purple);
  border-radius: var(--radius-full);
  color: var(--color-purple-dark);
  font-family: var(--font-body);
  font-size: max(14px, clamp(0.8125rem, 0.75rem + 0.15vw, 0.9375rem));
  font-weight: 700;
  letter-spacing: 0.06em;
  cursor: pointer;
  transition:
    background-color var(--motion-fast) ease,
    color var(--motion-fast) ease,
    transform var(--motion-fast) var(--ease-spring);
  line-height: 1;
}

@media (hover: hover) {
  .navbar__actions .navbar__lang-toggle:hover {
    background: var(--color-purple-dark);
    color: #fff;
    transform: rotate(-8deg) scale(1.06);
  }
}

.navbar__actions .navbar__lang-toggle:active {
  transform: scale(0.94);
  transition-duration: var(--motion-press);
}

/* "Iniciar sesión" (outline) también sobre blanco, por la misma razón. */
.navbar__actions .btn-outline {
  background: #fff;
}

@media (hover: hover) {
  .navbar__actions .btn-outline:hover {
    background: var(--color-purple-light);
  }
}

/* ── Mobile: navbar transparente, solo hamburger flotante ── */
@media (max-width: 48rem) {
  .navbar {
    padding: 2.25rem var(--space-4) var(--space-3); /* top: 36px del diseño */
  }

  .navbar__inner {
    background: transparent;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    border-radius: 0;
    padding: 0;
    justify-content: flex-end;
  }

  /* En mobile la barra es transparente: no hay caja que elevar. */
  .navbar__inner::before {
    display: none;
  }

  .navbar__logo {
    display: none; /* logo vive en el hero en mobile */
  }

  .navbar__actions {
    display: none;
  }

  .navbar__hamburger {
    display: flex;
    position: relative;
    z-index: 2;                 /* el círculo va sobre el panel */
    width: clamp(3.125rem, calc(7.634vw + 1.336rem), 5rem);
    height: clamp(3.125rem, calc(7.634vw + 1.336rem), 5rem);
    min-width: 44px;
    min-height: 44px;
    background: rgba(241, 241, 241, 0.70);
    border-radius: 4rem;
    margin-right: 1rem;
  }

  .navbar__hamburger-icon {
    width: clamp(1.25rem, calc(3.053vw + 0.534rem), 2rem);
  }

  .navbar__mobile-menu {
    display: flex;
  }

  .navbar__mobile-menu-logo {
    display: block;
    position: absolute;
    top: clamp(0.5rem, 2.955vw, 1.25rem);       /* 13 — simétrico al offset del panel sobre el hamburguesa */
    left: clamp(0.625rem, 3.409vw, 1.5rem);     /* 15 — simétrico al offset derecho del panel */
    z-index: 2;
    width: clamp(3.125rem, calc(7.634vw + 1.336rem), 5rem);   /* mismo tamaño que .navbar__hamburger */
    height: clamp(3.125rem, calc(7.634vw + 1.336rem), 5rem);
    min-width: 44px;
    min-height: 44px;
  }

  .btn-sm {
    min-width: unset;
    padding: 0.625rem 1.5rem;
  }
}

/* ── css/contact.css ────────────────────────────────── */
/* ===== CONTACT PAGE ===== */

body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.contact {
  flex: 1;
  padding: 7.5rem var(--space-2) var(--space-6);
  background: var(--color-bg);
}

/* Purple rounded container */
.contact__wrapper {
  position: relative;
  background: var(--color-purple) url('../assets/images/background_contact@2x.webp') center center / cover no-repeat;
  border-radius: 24px;
  padding-block: var(--space-20);
  padding-right: clamp(3rem, 22.22vw, 20rem);
  padding-left: clamp(2.5rem, 16.67vw, 15rem);
  overflow: hidden;
  margin-inline: clamp(2.5rem, 5.21vw, 6.25rem);
}

/* ── Two-column layout ── */
.contact__inner {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: 1.5fr 1fr;
  align-items: center;
}

/* ── Left: title & subtitle ── */
.contact__left {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  text-align: left;
}

.contact__title {
  font-family: var(--font-display);
  font-size: clamp(2.5rem, 1.5rem + 4.23vw, 5.3125rem);
  font-weight: 700;
  color: #fff;
  line-height: 0.85;
  margin-bottom: var(--space-5);
}

.contact__title--accent {
  color: var(--color-yellow);
}

.contact__subtitle {
  font-family: var(--font-body);
  font-size: clamp(1.25rem, 0.9rem + 1.5vw, 2.25rem);
  font-weight: 400;
  color: #fff;
  line-height: 2;
}

.contact__subtitle strong {
  font-weight: 700;
}

/* ── Right: form card ── */
.contact__right {
  background: rgba(241, 241, 241, 0.61);
  backdrop-filter: blur(16px) saturate(120%);
  -webkit-backdrop-filter: blur(16px) saturate(120%);
  border-radius: 1.5rem;
  padding: 2.0625rem;
  border: 1px solid rgba(255, 255, 255, 0.4);
  transform: translateZ(0);
  -webkit-font-smoothing: antialiased;
}

/* ── Form ── */
.contact__form[hidden] {
  display: none;
}

.contact__form {
  /* Mismos tokens que el formulario del FAQ, calibrados al tamaño de esta
     página: el campo aquí no tiene borde y la letra es --fs-sm. */
  --field-pad-y: var(--space-3);
  --field-pad-x: var(--space-4);
  --field-fs: max(14px, var(--fs-sm));
  --field-border: 0px;
  --field-lh: 1.5;
  --field-label-h: max(15.5px, 1.05rem);

  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.contact__field {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding-top: var(--field-label-h);
}

/* display:flex del .contact__field le gana a la hoja del navegador. */
.contact__field[hidden] {
  display: none;
}

.contact__field--group {
  border: none;
  padding: 0;
  margin: 0;
}

/* ── Etiqueta flotante ──────────────────────────────────────────────────────
   Antes el único rótulo de cada campo era el placeholder —y aquí ni siquiera
   había <label> oculto—: desaparecía al escribir y dejaba al visitante sin
   saber qué está llenando. */
.contact__label {
  position: absolute;
  top: calc(var(--field-label-h) + var(--field-border) + var(--field-pad-y));
  left: calc(var(--field-pad-x) + var(--field-border));
  max-width: calc(100% - var(--field-pad-x) - var(--field-border) * 2);
  font-family: var(--font-body);
  font-size: var(--field-fs);
  font-weight: 500;
  line-height: var(--field-lh);
  color: var(--color-text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  pointer-events: none;
  transition: top var(--transition-fast), font-size var(--transition-fast),
              line-height var(--transition-fast), color var(--transition-fast);
}

.contact__field:has(.contact__textarea) .contact__label {
  line-height: 1.6;
  white-space: normal;
}

.contact__input:focus + .contact__label,
.contact__input:not(:placeholder-shown) + .contact__label,
.contact__textarea:focus + .contact__label,
.contact__textarea:not(:placeholder-shown) + .contact__label {
  top: 0;
  left: 0;
  max-width: 100%;
  font-size: max(12px, 0.82rem);
  line-height: 1.15;
  white-space: nowrap;
  color: var(--color-text);
}

.contact__input:focus + .contact__label,
.contact__textarea:focus + .contact__label {
  color: var(--color-purple-dark);
}

/* Rótulo fijo del grupo de roles: ocupa la misma banda que una etiqueta
   flotante, para que la fila mida igual que la de un campo. */
.contact__label--static {
  position: static;
  display: flex;
  align-items: center;
  height: calc(var(--field-label-h) - var(--space-1));
  max-width: 100%;
  font-size: max(12px, 0.82rem);
  line-height: 1.15;
  font-weight: 600;
  color: var(--color-text-muted);
}

.contact__field-error {
  font-family: var(--font-body);
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--color-brand-pink);
  min-height: 0;
  padding-left: var(--space-1);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.contact__field-error[hidden] {
  display: none;
}

.contact__input--invalid {
  box-shadow: 0 0 0 2px rgba(255, 83, 171, 0.55);
}

.contact__input,
.contact__textarea {
  width: 100%;
  padding: var(--field-pad-y) var(--field-pad-x);
  border: none;
  border-radius: var(--radius-md);
  font-family: var(--font-body);
  font-size: var(--field-fs);
  line-height: var(--field-lh);
  color: var(--color-text);
  background: #fff;
  outline: none;
  transition: box-shadow var(--transition-fast);
}

.contact__input:focus,
.contact__textarea:focus {
  box-shadow: 0 0 0 2.5px rgba(255, 255, 255, 0.55);
}

.contact__textarea {
  resize: none;
  line-height: 1.6;
}

/* ── Role pills ── */
.contact__role-pills {
  display: flex;
  gap: 0.625rem;
  flex-wrap: wrap;
}

.contact__role-pill {
  position: relative;
  cursor: pointer;
}

/* Oculto a la vista pero enfocable: con display:none el rol (obligatorio) no
   se podía elegir con el teclado. Mismo arreglo que .role-pill en faq.css. */
.contact__role-pill input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.contact__role-pill input:focus-visible + span {
  outline: var(--focus-ring-width) solid var(--focus-ring-color);
  outline-offset: 2px;
}

.contact__role-pill span {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0.6875rem 1.25rem;
  border-radius: 0.625rem;
  border: 1.5px solid var(--color-border);
  background: #fff;
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--color-text);
  transition: background var(--transition-fast), border-color var(--transition-fast), color var(--transition-fast);
  user-select: none;
}

.contact__role-pill:hover span {
  border-color: var(--color-teal);
}

/* Texto oscuro sobre el teal: con blanco daba 2.43:1. */
.contact__role-pill input:checked + span {
  background: var(--color-teal);
  border-color: var(--color-teal);
  color: var(--color-text);
}

/* ── Autorización de tratamiento de datos (Ley 1581 de 2012) ── */
.contact__consent {
  padding-top: 0;
}

.contact__consent-label {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 44px;
  cursor: pointer;
}

.contact__consent-label input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  flex-shrink: 0;
  width: max(20px, 1.25rem);
  height: max(20px, 1.25rem);
  margin: 0;
  border: 1.5px solid var(--color-text-muted);
  border-radius: 0.3rem;
  background: #fff;
  cursor: pointer;
  transition: background var(--transition-fast), border-color var(--transition-fast);
}

.contact__consent-label input[type="checkbox"]:checked {
  background: var(--color-purple) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23fff' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='3 8.5 6.5 12 13 4.5'/%3E%3C/svg%3E") center / 80% no-repeat;
  border-color: var(--color-purple);
}

.contact__consent-label input[type="checkbox"]:focus-visible {
  outline: 2px solid var(--color-purple);
  outline-offset: 2px;
}

.contact__consent-text {
  font-family: var(--font-body);
  font-size: max(13px, var(--fs-sm));
  font-weight: 500;
  line-height: 1.4;
  color: var(--color-text);
}

.contact__consent-text a {
  color: var(--color-purple-dark);
  text-decoration: underline;
}

/* ── Error message ── */
.contact__error {
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  color: var(--color-pink-soft);
  margin: 0;
}

/* ── Submit button ── */
.contact__submit {
  width: 60%;
  display: block;
  margin-inline: auto;
  /* No es un .btn, así que el piso global de main.css no lo alcanza: con el
     root en 13px este padding daba 38px de alto. */
  min-height: 44px;
  padding-block: 0.975rem;
  border: none;
  border-radius: 1.707rem;
  background: var(--color-purple);
  color: #fff;
  font-family: var(--font-body);
  font-size: var(--fs-body);
  font-weight: 600;
  cursor: pointer;
  transition: background var(--transition-fast), transform var(--transition-fast), opacity var(--transition-fast);
}

.contact__submit:hover:not(:disabled) {
  background: var(--color-purple-dark);
  transform: translateY(-2px);
}

.contact__submit:disabled {
  opacity: 0.65;
  cursor: not-allowed;
  transform: none;
}

/* ── Success state ──
   El aspecto lo da .form-success en main.css, compartido con el formulario de
   la landing. Las reglas que había acá pintaban el título en #fff sobre el
   panel claro: 1.13:1, ilegible. */

/* ── Responsive ── */
@media (max-width: 73.75rem) {
  .contact__wrapper {
    padding: var(--space-16) var(--space-10);
  }

  .contact__inner {
    grid-template-columns: 1fr;
    gap: var(--space-10);
  }

  /* Apilado, la tarjeta no debe estirarse al ancho del bloque: a 1180px el
     campo llegaba a 922px. Se centra con un ancho de lectura razonable. */
  .contact__right {
    width: 100%;
    max-width: min(34rem, 100%);
    margin-inline: auto;
  }

  .contact__left {
    align-items: center;
  }
}

@media (max-width: 480px) {
  .contact {
    padding: 88px var(--space-3) var(--space-8);
  }

  .contact__wrapper {
    padding: var(--space-12) var(--space-5);
    border-radius: 16px;
  }

  .contact__title {
    font-size: clamp(2rem, 9vw, 2.5rem);
  }

  .contact__right {
    padding: var(--space-5);
  }
}

/* ── css/footer.css ────────────────────────────────── */
.footer-outer {
  padding: clamp(2.5rem, 12.5vw, 6rem);
}

.footer {
  background: var(--color-purple-dark);
  padding: var(--space-12) 0;
  border-radius: 1.5rem;
  margin-inline: auto;
}

.footer__inner {
  display: grid;
  grid-template-columns: 12.5rem repeat(2, 1fr) 11.25rem;
  gap: var(--space-8);
  align-items: start;
}

/* Logo */
.footer__logo {
  display: flex;
  align-self: center;
}

.footer__logo img {
  height: 4.5rem;
  width: auto;
}

/* Store badges (App Store / Google Play) — mobile only, ver .footer__inner mobile */
.footer__stores {
  display: none;
}

.footer__store-badge {
  display: flex;
  align-items: center;
  min-height: 44px;
  transition: transform var(--motion-fast) var(--ease-out-soft);
}

@media (hover: hover) {
  .footer__store-badge:hover {
    transform: translateY(var(--motion-lift));
  }
}

.footer__store-badge img {
  display: block;
  width: auto;
}

.footer__logo-fallback {
  display: none;
  font-family: var(--font-display);
  font-size: var(--fs-xl);
  font-weight: 800;
  color: #fff;
  padding: var(--space-2) var(--space-4);
  background: rgba(255,255,255,0.15);
  border-radius: var(--radius-lg);
}

.footer__logo-fallback span {
  color: var(--color-yellow);
}

/* Columns */
.footer__col .footer__heading {
  font-family: var(--font-body);
  font-size: max(13px, var(--fs-sm));
  font-weight: 700;
  color: #fff;
  margin-bottom: var(--space-4);
}

.footer__col ul {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0;
}

.footer__col a {
  /* Piso de 13px: entre 769 y ~1280px el root cae a su suelo y --fs-sm rendía
     11.7px. */
  font-size: max(13px, var(--fs-sm));
  color: #fff;
  font-weight: 500;
  /* Mínimo táctil: los enlaces medían 18px de alto (16.5 en esa misma banda).
     El padding negativo en el eje horizontal mantiene la alineación con el
     título de la columna. */
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  position: relative;
  text-decoration: none;
}

/* Subrayado que crece desde la izquierda al pasar el mouse o con foco: un
   pseudo-elemento que escala en X (transform), sin bajar la opacidad del
   texto como antes. */
.footer__col a::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0.7rem;
  height: 2px;
  border-radius: 1px;
  background: var(--color-brand-yellow);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--motion-base) var(--ease-out-soft);
}

.footer__col a:hover::after,
.footer__col a:focus-visible::after {
  transform: scaleX(1);
}

.footer__col a:focus-visible {
  outline: var(--focus-ring-width) solid #fff;
  outline-offset: 3px;
  border-radius: 0.25rem;
}

/* Copyright */
.footer__copy {
  /* Piso de 12px: rendía 9.75px a 320px y en la banda de 800-1180. */
  font-size: max(12px, var(--fs-xs));
  color: #fff;
  line-height: 1.4;
}

.footer__copy strong {
  font-weight: 700;
}

.footer__made {
  margin-top: var(--space-3);
  color: #fff;
  font-size: max(13px, var(--fs-sm));
}

/* Versión del build — discreta; sirve para verificar la actualización en el navegador */
.footer__version {
  margin-top: var(--space-2);
  color: #fff;
  font-size: max(12px, var(--fs-xs));
  /* 0.9 y no 0.75: con 0.75 daba 3.91:1 sobre el morado del footer. */
  opacity: 0.9;
  letter-spacing: 0.03em;
}

/* ── Mobile (≤768px) — columna única centrada, orden Figma ── */
@media (max-width: 48rem) {
  
  .footer {
    padding-block: clamp(3.25rem, 16.3vw, 7.8rem);
    padding-inline: 0;
    border-radius: 1rem;
  }

  .footer__inner {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: clamp(1.53rem, 7.67vw, 3.68rem);
  }

  .footer__logo img {
    height: clamp(2.65rem, 13.26vw, 6.79rem);
  }

  .footer__stores {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: clamp(0.46rem, 2.33vw, 1.12rem);
    margin-bottom: calc(clamp(2rem, 10vw, 4.8rem) - clamp(1.53rem, 7.67vw, 3.68rem));
  }

  .footer__store-badge img {
    height: clamp(1.86rem, 9.3vw, 4.47rem);
  }

  .footer__col ul {
    align-items: center;
  }

  /* Texto footer — uniforme en todo el rango mobile */
  .footer__col .footer__heading,
  .footer__col a,
  .footer__made {
    font-size: var(--fs-body);
  }

  .footer__copy {
    font-size: var(--fs-body);
    line-height: 1.6;
  }
}
