@charset "UTF-8";
/* ══════════════════════════════════════════════════════════════════════════
   SISTEMA ESCOLAR DE QUERÉTARO — hoja de estilo única de la landing
   ──────────────────────────────────────────────────────────────────────────
   Todo lo que hay aquí está medido sobre
   MOCKUP/Sistema_Escolar_de_Queretaro_Web_Mockup.pdf.

   El mockup es una página de 1080 x 2625 pt que representa un escritorio de
   1440 px: la equivalencia es 1 pt = 1.333 px. Los tamaños de letra que
   aparecen comentados ("55.5 pt") son los del PDF; el valor en px es esa
   medida ya convertida.

   METODOLOGÍA: MOBILE FIRST.
   Todo lo que está fuera de un @media es el diseño para teléfono. Las media
   queries usan SIEMPRE min-width, nunca max-width: se agrega complejidad al
   subir de tamaño, nunca se tapa al bajar.

     (sin media query)  → teléfono   320-639 px
     @media (min-width: 640px)  → teléfono grande / tablet vertical
     @media (min-width: 900px)  → tablet horizontal / laptop
     @media (min-width: 1200px) → escritorio, que es lo que dibuja el mockup

   Los colores y la tipografía NO se editan aquí: son variables que
   contenido.txt sobrescribe al cargar. Ver LEEME.md
   ══════════════════════════════════════════════════════════════════════════ */

/* ── 1. TOKENS ─────────────────────────────────────────────────────────── */
:root {
  /* Color — se sobrescriben desde contenido.txt → sección "colores" */
  --tinta:          #122033;
  --tinta-fuerte:   #0F1C2C;
  --tinta-rgb:      18, 32, 51;
  --marino:         #142236;
  --hero-1:         #0B1524;
  --hero-2:         #111F30;
  --hero-3:         #16283C;
  --texto:          #738194;
  --texto-sec:      #778496;
  --texto-suave:    #8190A0;
  --etiqueta:       #66768A;
  --etiqueta-clara: #92A7BD;
  --azul-claro:     #9FB5CB;
  --azul-suave:     #B8C7D8;
  --blanco:         #FFFFFF;
  --panel:          #F7F8FA;
  --panel-borde:    #EDF0F3;
  --panel-vision:   #E9EEF3;
  --tarjeta:        #F6F9FC;
  --linea:          #E4E8EC;

  /* Tipografía — una sola familia, como el mockup */
  --font: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;

  /* Escala fluida. El valor máximo de cada una es la medida del mockup ya
     convertida a px; el mínimo es lo que hace falta para que quepa en un
     teléfono de 320 px sin desbordar. */
  --fs-h1:      clamp(2.5rem,  1.55rem + 4.20vw, 4.625rem);  /* 55.5 pt → 74 px */
  --fs-titulo:  clamp(1.95rem, 1.35rem + 2.60vw, 3rem);      /* 36.0 pt → 48 px */
  --fs-vision:  clamp(2.1rem,  1.30rem + 3.55vw, 4.125rem);  /* 49.5 pt → 66 px */
  --fs-cita:    clamp(1.35rem, 1.05rem + 1.30vw, 1.9375rem); /* 23.2 pt → 31 px */
  --fs-cta:     clamp(1.7rem,  1.25rem + 1.95vw, 2.5rem);    /* 30.0 pt → 40 px */
  --fs-flotante: 1.4375rem;                                  /* 17.3 pt → 23 px */
  --fs-tarjeta: 1.375rem;                                    /* 16.5 pt → 22 px */
  --fs-paso:    1.125rem;                                    /* 13.5 pt → 18 px */
  --fs-lead:    clamp(1.0625rem, 0.98rem + 0.35vw, 1.1875rem); /* 14.2 pt → 19 px */
  --fs-base:    0.875rem;                                    /* 10.5 pt → 14 px */
  --fs-sm:      0.78125rem;                                  /*  9.4 pt → 12.5 px */
  --fs-ui:      0.8125rem;                                   /*  9.8 pt → 13 px */
  --fs-xs:      0.625rem;                                    /*  7.5 pt → 10 px */

  /* Ritmo vertical */
  --sp-1: 0.25rem;  --sp-2: 0.5rem;  --sp-3: 0.75rem; --sp-4: 1rem;
  --sp-5: 1.5rem;   --sp-6: 2rem;    --sp-7: 3rem;    --sp-8: 4rem;

  /* Aire de sección: 78 pt arriba y 69 pt abajo en el mockup ≈ 104 px */
  --sp-seccion: 4rem;

  /* El contenido del mockup va de x=79 a x=1001 de 1080 pt: 922 pt de ancho
     útil, que a 1.333 son 1230 px. */
  --ancho-max: 1230px;
  --alto-nav:  72px;

  --radio-chico:  12px;   /* monograma, botón cuadrado */
  --radio:        18px;   /* tarjetas */
  --radio-grande: 28px;   /* bloques de visión y de contacto */

  --sombra-flotante: 0 18px 40px rgba(var(--tinta-rgb), 0.28);
  --transicion: 200ms cubic-bezier(0.4, 0, 0.2, 1);
}

@media (min-width: 900px) {
  :root { --sp-seccion: 6.5rem; --alto-nav: 125px; }
}

/* ── 2. REINICIO ───────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  /* Compensa la barra fija al saltar a un #ancla */
  scroll-padding-top: calc(var(--alto-nav) + 12px);
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--blanco);
  color: var(--texto);
  font-family: var(--font);
  font-size: var(--fs-base);
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* Sin text-wrap: balance a proposito. El mockup parte los titulos LLENANDO
   cada renglon ("Transformamos necesidades / educativas en proyectos /
   concretos."), y `balance` los reparte a partes iguales, que da otro
   dibujo: "Transformamos / necesidades educativas / en proyectos
   concretos.". Donde el corte importa, el .txt lo marca con <br>. */
h1, h2, h3 {
  margin: 0;
  color: var(--tinta);
  font-weight: 700;
  line-height: 1.12;
  letter-spacing: -0.02em;
}

p { margin: 0 0 var(--sp-4); }
p:last-child { margin-bottom: 0; }

ul, ol { margin: 0; padding: 0; list-style: none; }

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

button { font: inherit; color: inherit; border: 0; background: none; cursor: pointer; }

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

blockquote { margin: 0; }

/* Foco visible SIEMPRE: es el único camino de quien navega con teclado */
:focus-visible {
  outline: 2px solid var(--azul-claro);
  outline-offset: 3px;
  border-radius: 4px;
}

/* Quien pidió menos movimiento en su sistema, no recibe animaciones */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ── 3. UTILIDADES ─────────────────────────────────────────────────────── */
/* --ancho-max es el ancho del CONTENIDO, no el de la caja: por eso el
   max-width le suma el relleno de los lados. Si no, el contenido queda 48 px
   mas angosto que en el mockup, y eso basta para que los titulos grandes
   partan en un renglon de mas. */
.contenedor {
  width: 100%;
  max-width: calc(var(--ancho-max) + var(--sp-5) * 2);
  margin-inline: auto;
  padding-inline: var(--sp-5);
}

.seccion { padding-block: var(--sp-seccion); }
/* La visión va pegada a lo de arriba: en el mockup el bloque arranca justo
   donde terminan las tarjetas de servicios. */
.seccion--sin-tope { padding-top: 0; }

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

/* Salto al contenido: primer tabulador de la página */
.saltar {
  position: absolute; top: -100px; left: var(--sp-4);
  z-index: 200; padding: var(--sp-3) var(--sp-5);
  background: var(--blanco); color: var(--tinta);
  font-size: var(--fs-ui); font-weight: 700; border-radius: 999px;
  transition: top var(--transicion);
}
.saltar:focus { top: var(--sp-3); }

/* Antetítulo: versalitas muy espaciadas. El mockup lo usa en las cinco
   secciones, en gris sobre claro y en azul pálido sobre oscuro. */
.eyebrow {
  margin: 0 0 var(--sp-4);
  color: var(--etiqueta);
  font-size: var(--fs-xs);          /* 7.5 pt */
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  line-height: 1.4;
}
.eyebrow--claro { color: var(--etiqueta-clara); }

/* Variante con punto delante, la del hero */
.eyebrow--punto {
  display: flex; align-items: center; gap: var(--sp-3);
  color: var(--azul-suave);
  font-size: 0.6875rem;             /* 8.2 pt */
  font-weight: 600;
}
.eyebrow--punto::before {
  content: ""; flex-shrink: 0;
  width: 6px; height: 6px;
  background: currentColor; border-radius: 50%;
}

.titulo-seccion { font-size: var(--fs-titulo); }

/* Cabecera de sección: título a la izquierda, párrafo a la derecha.
   En el mockup el párrafo cierra alineado con la última línea del título,
   de ahí el align-items: end. */
.cabecera { display: grid; gap: var(--sp-5); margin-bottom: var(--sp-8); }
.cabecera__texto { color: var(--texto); }

@media (min-width: 900px) {
  .cabecera {
    grid-template-columns: 1.5fr 1fr;
    align-items: end;
    gap: var(--sp-8);
    margin-bottom: 5.5rem;
  }
  .cabecera__texto { padding-bottom: 0.35rem; }

  /* Las dos cabeceras del mockup no reparten igual: la de "Como trabajamos"
     le da mas sitio al parrafo (420 pt contra 330 pt) y menos al titulo, y
     por eso alli el titulo cae en tres renglones y no en dos. */
  .cabecera--texto-ancho { grid-template-columns: 1.15fr 1fr; }
}

/* ── 4. BOTONES ────────────────────────────────────────────────────────── */
/* El mockup los dibuja en Inter Regular, no en negrita: la única excepción
   es el "Contáctanos" del bloque final. */
.btn {
  position: relative;
  overflow: hidden;                 /* recorta el barrido de brillo */
  display: inline-flex; align-items: center; justify-content: center;
  gap: 0.55rem;
  /* 39 pt de alto en el mockup = 52 px, por encima del mínimo táctil de 44 */
  min-height: 52px;
  padding-inline: 1.625rem;
  font-family: var(--font);
  font-size: var(--fs-ui);
  font-weight: 400;
  line-height: 1.2;
  text-align: center;
  border: 1px solid transparent;
  border-radius: 999px;
  cursor: pointer;
  transition: background var(--transicion), color var(--transicion),
              border-color var(--transicion), transform var(--transicion);
}
.btn:hover { transform: translateY(-2px); }
.btn:active { transform: translateY(0) scale(0.98); }

.btn__icono { width: 17px; height: 17px; flex-shrink: 0; }

/* Barrido de brillo: una banda diagonal que cruza el botón al pasar por
   encima. Va en un pseudo-elemento para no tocar el contenido, y se mueve
   con transform —no con `left`— para que la anime la tarjeta gráfica. */
.btn::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(100deg,
              transparent 20%, rgba(255, 255, 255, 0.42) 50%, transparent 80%);
  transform: translateX(-120%);
  transition: transform 620ms cubic-bezier(0.4, 0, 0.2, 1);
  pointer-events: none;
}
.btn:hover::after { transform: translateX(120%); }
/* Sobre el botón blanco la banda blanca no se vería: ahí se oscurece. */
.btn--blanco::after {
  background: linear-gradient(100deg,
              transparent 20%, rgba(var(--tinta-rgb), 0.10) 50%, transparent 80%);
}

.btn--blanco {
  background: var(--blanco); color: var(--tinta); border-color: var(--blanco);
}
.btn--blanco:hover { background: #E8EDF2; border-color: #E8EDF2; }

.btn--linea-clara {
  background: transparent; color: var(--blanco);
  border-color: rgba(255, 255, 255, 0.32);
}
.btn--linea-clara:hover {
  background: rgba(255, 255, 255, 0.10);
  border-color: rgba(255, 255, 255, 0.55);
}

.grupo-btn { display: flex; flex-wrap: wrap; gap: var(--sp-3); }

/* ── 5. BARRA ──────────────────────────────────────────────────────────── */
.nav {
  position: fixed; inset: 0 0 auto 0; z-index: 100;
  height: var(--alto-nav);
  background: transparent;
  transition: background var(--transicion), box-shadow var(--transicion),
              transform 320ms cubic-bezier(0.4, 0, 0.2, 1);
}
/* Al bajar se retira; al subir vuelve entera. Gana sitio de pantalla en
   teléfono sin esconder nunca la navegación cuando se la busca. */
.nav--oculta { transform: translateY(-100%); }

/* CUIDADO AL TOCAR ESTO.
   Un `transform` distinto de `none` —y también un `backdrop-filter`—
   convierte al elemento en el marco de referencia de sus hijos
   `position: fixed`. El panel del menú de teléfono es uno de ellos: en vez
   de medirse contra la pantalla pasaba a medirse contra la barra, 72 px de
   alto, y el menú se abría roto: los enlaces flotando sobre la página, sin
   su fondo.

   Pasaba con las DOS propiedades, y por motivos distintos:
     · .nav--solido lleva backdrop-filter, así que bastaba con haber hecho
       scroll para que el menú saliera mal;
     · .nav--oculta lleva transform, así que además se iba fuera de vista.

   Mientras el menú está abierto se apagan las dos. `transition: none` es
   parte del arreglo: durante los 320 ms de la transición el `transform`
   todavía no vale `none` y el problema seguiría vivo ese rato. */
.nav--menu-abierto {
  transform: none !important;
  backdrop-filter: none !important;
  transition: none;
}
/* Al despegarse del tope, la barra se vuelve sólida: de ahí para abajo la
   página es blanca y sin fondo propio el menú blanco desaparecería. */
.nav--solido {
  background: rgba(11, 21, 36, 0.94);
  backdrop-filter: blur(10px);
  box-shadow: 0 8px 30px rgba(var(--tinta-rgb), 0.18);
}

.nav__interior {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-4);
  height: 100%;
  max-width: calc(var(--ancho-max) + var(--sp-5) * 2); margin-inline: auto;
  padding-inline: var(--sp-5);
}

/* Marca: monograma + nombre + lema, todo texto */
.marca { display: flex; align-items: center; gap: 0.8rem; min-height: 44px; }

.marca__monograma {
  display: grid; place-items: center;
  flex-shrink: 0;
  width: 44px; height: 44px;
  color: var(--blanco);
  font-size: 0.9375rem;             /* 11.2 pt */
  font-weight: 700;
  letter-spacing: 0.01em;
  border: 1px solid rgba(255, 255, 255, 0.38);
  border-radius: var(--radio-chico);
}

.marca__texto { display: flex; flex-direction: column; gap: 2px; }
.marca__nombre {
  color: var(--blanco);
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.01em;
}
/* En teléfono el lema se va: con el nombre en dos renglones más el lema en
   otros dos, la marca no cabe en la barra sin apretarla. Vuelve en cuanto
   hay ancho. */
.marca__lema { display: none; }

@media (min-width: 640px) {
  .marca__nombre {
    max-width: 12ch;                /* parte en dos renglones, como el mockup */
    font-size: 1.0625rem;           /* 12.8 pt */
  }
  .marca__lema {
    display: block;
    color: rgba(255, 255, 255, 0.55);
    font-size: var(--fs-xs);
    letter-spacing: 0.16em;
    text-transform: uppercase;
    line-height: 1.3;
  }
}

.nav__abrir, .nav__cerrar {
  display: grid; place-items: center;
  width: 48px; height: 48px; margin-right: -10px;
  color: var(--blanco); border-radius: var(--radio-chico);
}
.nav__abrir svg, .nav__cerrar svg { width: 26px; height: 26px; }

/* Menú en teléfono: panel deslizante a pantalla completa */
.nav__menu {
  position: fixed; inset: 0; z-index: 110;
  display: flex; flex-direction: column;
  padding: var(--sp-5);
  background: var(--hero-1);
  transform: translateX(100%);
  visibility: hidden;
  transition: transform 280ms cubic-bezier(0.4, 0, 0.2, 1), visibility 280ms;
}
.nav__menu[data-abierto="true"] { transform: translateX(0); visibility: visible; }

.nav__menu-cab {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: var(--sp-7);
}

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

.nav__link {
  display: block;
  padding: var(--sp-4) var(--sp-2);
  color: rgba(255, 255, 255, 0.88);
  font-size: 1.125rem; font-weight: 600;
  border-bottom: 1px solid rgba(255, 255, 255, 0.10);
  transition: color var(--transicion), padding-left var(--transicion);
}
.nav__link:hover { color: var(--blanco); padding-left: var(--sp-4); }
.nav__link[aria-current="true"] { color: var(--azul-claro); }

.nav__menu .btn { margin-top: var(--sp-6); }

@media (min-width: 900px) {
  .nav__abrir, .nav__cerrar, .nav__menu-cab { display: none; }

  /* La línea fina bajo la barra va del ancho del contenido, no de la
     pantalla: en el mockup arranca y termina con el texto. */
  .nav__interior { border-bottom: 1px solid rgba(255, 255, 255, 0.10); }
  .nav--solido .nav__interior { border-bottom-color: transparent; }

  .nav__menu {
    position: static; inset: auto;
    flex-direction: row; align-items: center; gap: 2.75rem;
    padding: 0; background: none;
    transform: none; visibility: visible;
  }
  .nav__links { flex-direction: row; align-items: center; gap: 2.75rem; }
  .nav__link {
    position: relative;
    padding: var(--sp-2) 0;
    font-size: var(--fs-ui); font-weight: 400;
    border-bottom: 0;
  }
  /* Subrayado que crece desde la izquierda. Se anima scaleX y no width:
     así el navegador no tiene que rehacer el diseño en cada cuadro. */
  .nav__link::after {
    content: ""; position: absolute; left: 0; right: 0; bottom: -2px;
    height: 1.5px;
    background: var(--azul-suave);
    transform: scaleX(0); transform-origin: left;
    transition: transform 260ms cubic-bezier(0.4, 0, 0.2, 1);
  }
  .nav__link:hover::after,
  .nav__link[aria-current="true"]::after { transform: scaleX(1); }
  .nav__link:hover { padding-left: 0; color: var(--blanco); }
  .nav__menu .btn { margin-top: 0; min-height: 44px; padding-inline: 1.5rem; }
}

/* ── 6. PORTADA ────────────────────────────────────────────────────────── */
.hero {
  position: relative;
  display: flex; align-items: center;
  min-height: 100svh;
  padding-top: calc(var(--alto-nav) + var(--sp-7));
  padding-bottom: var(--sp-8);
  /* Degradado en diagonal: oscuro arriba a la izquierda, más claro abajo a
     la derecha. Los tres colores están medidos sobre el mockup. */
  background: linear-gradient(135deg,
              var(--hero-1) 0%, var(--hero-2) 46%, var(--hero-3) 100%);
  color: var(--blanco);
  overflow: hidden;
}

/* Las figuras del fondo. Van dentro del contenedor y no del hero porque sus
   posiciones son un porcentaje del ancho útil —igual que las tarjetas—, y
   así se mantienen en su sitio en cualquier pantalla.

   --desliz lo escribe seq-ui.js al hacer scroll (parallax). Vale 0 si el
   JavaScript no corre o si el sistema pidió menos movimiento. */
.hero__figuras {
  position: absolute; inset: 0; z-index: 0;
  translate: 0 var(--desliz, 0px);
  pointer-events: none;
}
.figura {
  position: absolute;
  aspect-ratio: 1;
  border-radius: 50%;
  translate: -50% -50%;             /* las posiciones son de su CENTRO */
}

/* El disco de detrás de las tarjetas. En el mockup es un círculo BLANCO AL
   7 %, no un degradado: por eso su borde se nota. Mide 504 pt (672 px) y su
   centro cae en el 91 % del ancho útil y por debajo de las tarjetas, que es
   lo que le da ese aire de capa de fondo. */
.figura--disco {
  left: 78%; top: 92%;
  width: clamp(20rem, 74vw, 42rem);
  background: rgba(255, 255, 255, 0.07);
}

/* Los dos aros concéntricos, más arriba y a la izquierda que el disco. */
.figura--aro {
  left: 72%; top: 52%;
  border: 1px solid rgba(255, 255, 255, 0.06);
}
.figura--aro-1 { width: clamp(17rem, 58vw, 31.25rem); }   /* 375 pt */
.figura--aro-2 { width: clamp(14rem, 49vw, 26.25rem); }   /* 315 pt */

.hero__interior {
  position: relative; z-index: 1;
  display: grid; gap: var(--sp-8);
  align-items: center;
}

/* Por encima de las figuras, cada uno en su capa */
.hero__contenido, .flotantes { position: relative; z-index: 1; }

@media (min-width: 900px) {
  /* Medido sobre el mockup: el disco al 91 % del ancho útil y su centro
     109 % del alto de la caja de las tarjetas —o sea, por debajo—; los aros
     al 79 % y al 58 %. */
  .figura--disco { left: 91%; top: 88%; }
  .figura--aro   { left: 79%; top: 58%; }
}

.hero__titulo {
  margin-bottom: var(--sp-5);
  color: var(--blanco);
  font-size: var(--fs-h1);
  line-height: 1.04;
  letter-spacing: -0.03em;
}
/* Los saltos del .txt son los del mockup, y solo valen donde hay sitio: en
   teléfono estorban, así que el navegador vuelve a partir el título solo.

   Esto obliga a que en el .txt haya un ESPACIO antes de cada <br>. Sin él,
   al ocultarlos las palabras quedan pegadas ("Estrategiaeducativa.") y el
   titulo se convierte en una palabra larguisima que no puede partirse: la
   columna crece a 597 px dentro de una pantalla de 390 y el hero recorta
   medio titular. */
.hero__titulo br { display: none; }

.hero__texto {
  max-width: 40rem;
  margin-bottom: var(--sp-6);
  color: rgba(255, 255, 255, 0.74);
  font-size: var(--fs-lead);
  line-height: 1.7;
}

/* ── Menú de teléfono: los enlaces entran en cascada ──────────────────── */
/* Solo cuando el panel está abierto, así que se repite cada vez que se abre
   y no una sola vez al cargar. */
.nav__menu[data-abierto="true"] .nav__links li,
.nav__menu[data-abierto="true"] > .btn {
  animation: entrar-lateral 420ms cubic-bezier(0.22, 1, 0.36, 1) both;
}
.nav__menu[data-abierto="true"] .nav__links li:nth-child(1) { animation-delay:  90ms; }
.nav__menu[data-abierto="true"] .nav__links li:nth-child(2) { animation-delay: 150ms; }
.nav__menu[data-abierto="true"] .nav__links li:nth-child(3) { animation-delay: 210ms; }
.nav__menu[data-abierto="true"] .nav__links li:nth-child(4) { animation-delay: 270ms; }
.nav__menu[data-abierto="true"] > .btn { animation-delay: 330ms; }

@keyframes entrar-lateral {
  from { opacity: 0; transform: translateX(26px); }
  to   { opacity: 1; transform: none; }
}

/* ── Tarjetas flotantes de la portada ─────────────────────────────────── */
/* En teléfono son una lista normal, apiladas y sin inclinar. La inclinación
   y el solapamiento solo aparecen cuando hay ancho para ellos. */
.flotantes { display: grid; gap: var(--sp-4); }

.flotante {
  padding: 1.35rem 1.4rem 1.15rem;
  background: var(--tarjeta);
  border-radius: var(--radio);
  box-shadow: var(--sombra-flotante);
}
.flotante__etiqueta {
  margin: 0 0 var(--sp-4);
  padding-right: 2rem;              /* deja sitio al punto de la esquina */
  color: #93A0AD;
  font-size: 0.5625rem;             /* 6.8 pt */
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.flotante__titulo {
  margin-bottom: var(--sp-3);
  font-size: var(--fs-flotante);
  line-height: 1.2;
}
.flotante__texto {
  margin: 0;
  color: var(--texto-sec);
  font-size: var(--fs-sm);
  line-height: 1.5;
}

/* El punto oscuro de la esquina */
.flotante::before {
  content: ""; position: absolute; top: 1.35rem; right: 1.4rem;
  width: 18px; height: 18px;
  background: #1E2E42; border-radius: 50%;
}
.flotante { position: relative; }

/* La barrita del pie: el riel completo es el fondo, y --avance —que viene
   del .txt— dice cuánto se pinta. */
.flotante__barra {
  display: block; position: relative;
  height: 3px; margin-top: 1.1rem;
  background: #DCE4EC; border-radius: 999px;
}
.flotante__barra::before {
  content: ""; position: absolute; inset: 0 auto 0 0;
  width: var(--avance, 55%);
  background: #3D5C7E; border-radius: 999px;
}

@media (min-width: 900px) {
  .hero { min-height: 920px; }     /* 690 pt del mockup */
  .hero__interior { grid-template-columns: 1fr 1fr; gap: var(--sp-7); }
  .hero__titulo br { display: inline; }

  /* De aquí para arriba las tarjetas dejan de ser una lista apilada y se
     colocan una a una, inclinadas y montándose entre ellas, como en el
     mockup. Los ángulos son -2°, 2.5° y -1°, medidos sobre el PDF. */
  .flotantes {
    position: relative;
    display: block;
    height: 33rem;
  }
  /* 189 pt de ancho en el mockup, que a 1.333 son 252 px. Es lo que hace que
     "Innovacion educativa" caiga en dos renglones, como alli. */
  .flotante {
    position: absolute;
    width: 15.75rem;
  }
  /* Posiciones medidas sobre el mockup, en porcentaje del ancho util:
     la primera arranca en el 55 %, la segunda en el 78.6 % y la tercera en
     el 60.3 %. Como esta columna ocupa la mitad derecha, aqui son el doble
     menos 100. La segunda se sale un poco por la derecha: en el mockup
     tambien, y por eso el hero lleva overflow: hidden.

     La inclinacion va en `rotate` y NO en `transform` a proposito. La
     animacion de entrada anima `transform` y termina en `transform: none`;
     si el giro viviera ahi, la entrada se lo llevaria por delante y las
     tarjetas acabarian derechas. `rotate`, `translate` y `transform` son
     tres propiedades distintas y se acumulan sin pisarse: el giro es de
     esta regla, el balanceo usa `translate` y la entrada, `transform`. */
  .flotante:nth-child(1) { top: 0;       left: 10%; rotate: -2deg; }
  .flotante:nth-child(2) { top: 10.5rem; left: 57%; rotate: 2.5deg; }
  .flotante:nth-child(3) { top: 20.5rem; left: 21%; rotate: -1deg; }

  /* El ciclo se repite si algún día se agrega una cuarta tarjeta al .txt */
  .flotante:nth-child(3n + 4) { top: 30rem; left: 34%; rotate: -2deg; }
}

@media (min-width: 1200px) {
  .flotante { width: 16.75rem; }
}

/* ── 7. QUÉ HACEMOS ────────────────────────────────────────────────────── */
.servicios { display: grid; gap: 1.2rem; }

.servicio {
  display: flex; flex-direction: column;
  /* Separacion fija entre la cabecera y el cuerpo, no space-between: en el
     mockup los cuatro titulos arrancan a la misma altura contando DESDE
     ARRIBA, y debajo del texto queda aire. Con space-between los titulos
     bailaban segun lo largo que fuera cada texto. */
  /* 55.5 pt de separacion en el mockup: deja el titulo al 40 % del alto de
     la tarjeta, contando desde arriba. */
  gap: 3.4rem;
  /* 24.5 pt de relleno y 227 pt de alto en el mockup */
  min-height: 19rem;
  padding: 2rem;
  background: var(--panel);
  border: 1px solid var(--panel-borde);
  border-radius: var(--radio);
  transition: transform var(--transicion), box-shadow var(--transicion),
              border-color var(--transicion);
}
.servicio:hover {
  transform: translateY(-4px);
  border-color: #DFE5EB;
  box-shadow: 0 16px 40px rgba(var(--tinta-rgb), 0.08);
}

.servicio__cab { display: flex; align-items: flex-start; justify-content: space-between; }
.servicio__num {
  color: #93A0AD;
  font-size: 0.6875rem;             /* 8.2 pt */
  font-weight: 700;
  letter-spacing: 0.16em;
}
.servicio__flecha {
  display: grid; place-items: center;
  width: 37px; height: 37px;
  color: #53677E;
  border: 1px solid var(--linea);
  border-radius: 50%;
  transition: background var(--transicion), color var(--transicion),
              border-color var(--transicion);
}
.servicio__flecha svg {
  width: 16px; height: 16px;
  transition: transform 260ms cubic-bezier(0.4, 0, 0.2, 1);
}
.servicio:hover .servicio__flecha {
  background: var(--tinta); color: var(--blanco); border-color: var(--tinta);
  transform: rotate(45deg);
}
/* La flecha gira con el círculo y además se desplaza en su diagonal: da la
   sensación de que sale de la tarjeta. */
.servicio:hover .servicio__flecha svg { transform: translate(1px, -1px); }
.servicio__flecha { transition: background var(--transicion), color var(--transicion),
                                border-color var(--transicion),
                                transform 260ms cubic-bezier(0.4, 0, 0.2, 1); }

.servicio__titulo { margin-bottom: var(--sp-3); font-size: var(--fs-tarjeta); line-height: 1.18; }
.servicio__texto { margin: 0; color: var(--texto-sec); font-size: var(--fs-sm); line-height: 1.65; }

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

/* ── 8. NUESTRA VISIÓN ─────────────────────────────────────────────────── */
.vision {
  display: grid;
  border-radius: var(--radio-grande);
  overflow: hidden;                 /* recorta las dos mitades al redondeo */
}

.vision__claro {
  position: relative;
  padding: 2.5rem 1.8rem;
  background: var(--panel-vision);
  overflow: hidden;
}
/* El aro tenue de la esquina.
   Aquí el mockup NO lleva un disco relleno como el de la portada, sino un
   trazo fino: comprobado midiendo los píxeles, dentro del círculo el fondo
   sigue siendo el mismo #E9EEF3 y lo único que cambia es la línea del
   borde. Mide 182 pt (243 px) y su centro cae casi sobre el filo de abajo
   del panel, así que solo se ve la mitad de arriba. */
.vision__claro::after {
  content: ""; position: absolute;
  left: 89%; top: 92%;
  width: 15.2rem; aspect-ratio: 1;
  translate: -50% -50%;
  border: 1px solid rgba(44, 74, 103, 0.16);
  border-radius: 50%;
  pointer-events: none;
}

/* Ojo: este título va en REGULAR, no en negrita. Es la única pieza grande
   del mockup que no es Inter Bold, y es lo que le da el aire. */
.vision__titulo {
  position: relative; z-index: 1;
  margin-bottom: var(--sp-6);
  color: #16263A;
  font-size: var(--fs-vision);
  font-weight: 400;
  line-height: 1.02;
  /* Tracking medido, no elegido: en el mockup "Mas tecnologia" mide 317 pt a
     49.5 pt de cuerpo. Con el tracking normal esa linea se pasa 8 px del
     ancho de la columna y el titulo cae en seis renglones en vez de cinco. */
  letter-spacing: -0.045em;
}
.vision__texto {
  position: relative; z-index: 1;
  max-width: 30rem; margin: 0;
  color: #68798C;
}

.vision__oscuro {
  display: flex; flex-direction: column; justify-content: center;
  padding: 2.5rem 1.8rem;
  background: var(--marino);
}
.vision__cita {
  margin-bottom: var(--sp-7);
  color: var(--blanco);
  font-size: var(--fs-cita);
  font-weight: 400;
  line-height: 1.35;
  letter-spacing: -0.01em;
  text-wrap: pretty;
}
.vision__cita em { font-style: normal; color: var(--azul-claro); }
.vision__firma {
  margin: 0;
  color: rgba(255, 255, 255, 0.85);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

@media (min-width: 900px) {
  /* 424 pt claro y 498 pt oscuro sobre 922 pt de ancho útil */
  .vision { grid-template-columns: 0.85fr 1fr; }
  .vision__claro  { padding: 4.3rem 3.8rem; }
  .vision__oscuro { padding: 4.3rem 3.8rem; }
}

/* ── 9. CÓMO TRABAJAMOS ────────────────────────────────────────────────── */
/* Filas separadas por filetes, con filete también encima de la primera */
.pasos { border-top: 1px solid var(--linea); }

.paso {
  display: grid;
  gap: var(--sp-1) var(--sp-4);
  padding-block: 1.5rem;
  border-bottom: 1px solid var(--linea);
}
.paso {
  transition: background var(--transicion);
}
.paso__num {
  color: #9AA5B0;
  font-size: 0.75rem;               /* 9 pt */
  font-weight: 700;
  letter-spacing: 0.14em;
  transition: color var(--transicion);
}
.paso__titulo { transition: transform 260ms cubic-bezier(0.4, 0, 0.2, 1); }

@media (hover: hover) {
  .paso:hover { background: var(--panel); }
  .paso:hover .paso__num { color: var(--tinta); }
  .paso:hover .paso__titulo { transform: translateX(6px); }
}
.paso__titulo { font-size: var(--fs-paso); color: #1A293D; }
.paso__texto  { margin: 0; color: var(--texto-sec); font-size: var(--fs-sm); }

@media (min-width: 900px) {
  /* Medido sobre el mockup: el numero arranca en 0, el titulo en 95.8 pt y
     el texto en 432.6 pt del ancho util. Con el hueco de 24 px, las columnas
     que dejan cada cosa en su sitio son estas. */
  .paso {
    grid-template-columns: 104px 425px 1fr;
    align-items: center;
    gap: var(--sp-5);
    padding-block: 1.6rem;
  }
}

/* ── 10. CONVERSEMOS ───────────────────────────────────────────────────── */
.conversemos {
  position: relative;
  overflow: hidden;                 /* recorta el resplandor al redondeo */
  display: grid; gap: var(--sp-6);
  padding: 2.5rem 1.8rem;
  background: var(--tinta-fuerte);
  border-radius: var(--radio-grande);
  color: var(--blanco);
}

/* El resplandor de la esquina superior derecha: en el mockup es un disco
   claro que entra por ahí y se apaga hacia el centro. Muy tenue —se nota
   más de lo que se ve—, y es lo que evita que el bloque quede como un
   rectángulo negro y plano. */
.conversemos::before {
  content: ""; position: absolute; z-index: 0;
  top: -34%; right: -6%;
  width: min(26rem, 78%); aspect-ratio: 1;
  background: radial-gradient(circle,
              rgba(255, 255, 255, 0.085) 0%,
              rgba(255, 255, 255, 0.035) 52%,
              rgba(255, 255, 255, 0) 72%);
  border-radius: 50%;
  pointer-events: none;
}
/* El contenido, por encima del resplandor */
.conversemos > * { position: relative; z-index: 1; }
.conversemos__titulo {
  margin-bottom: var(--sp-4);
  color: var(--blanco);
  font-size: var(--fs-cta);
  line-height: 1.14;
}
.conversemos__sub {
  max-width: 44rem; margin: 0;
  color: rgba(255, 255, 255, 0.68);
  font-size: var(--fs-ui);
  line-height: 1.7;
}
/* La única excepción a los botones en regular: el mockup lo pone en negrita */
.conversemos .btn { font-weight: 700; }

/* En teléfono los dos botones ocupan el ancho y se apilan: son el final del
   recorrido y tienen que ser fáciles de apretar con el pulgar. */
.conversemos__botones { flex-direction: column; align-items: stretch; }

@media (min-width: 640px) {
  .conversemos__botones { flex-direction: row; align-items: center; }
}

@media (min-width: 900px) {
  .conversemos {
    grid-template-columns: 1fr auto;
    align-items: center;
    gap: var(--sp-8);
    padding: 4.5rem 4.3rem;
  }
  .conversemos__botones { flex-direction: column; align-items: stretch; }
}

/* ── 11. PIE ───────────────────────────────────────────────────────────── */
.pie { padding-block: 3.5rem 5rem; }

.pie__grid { display: grid; gap: var(--sp-5); }
.pie__razon {
  margin: 0 0 var(--sp-1);
  color: #34465A;
  font-size: 0.75rem;               /* 9 pt */
  font-weight: 700;
}
.pie__linea { margin: 0; color: var(--texto-suave); font-size: var(--fs-xs); }

/* Los mismos dos contactos del bloque de arriba, en discreto. Alto de 44 px
   porque en el teléfono son enlaces que se tocan con el dedo. */
.pie__contacto {
  display: flex; flex-direction: column; gap: var(--sp-1);
  margin-top: var(--sp-4);
}
.pie__contacto a {
  display: inline-flex; align-items: center; gap: 0.55rem;
  min-height: 44px;
  color: var(--texto);
  font-size: var(--fs-sm);
  transition: color var(--transicion);
}
.pie__contacto svg { width: 15px; height: 15px; flex-shrink: 0; color: var(--texto-suave);
                     transition: color var(--transicion); }
.pie__contacto a:hover { color: var(--tinta); }
.pie__contacto a:hover svg { color: var(--tinta); }
.pie__legal {
  margin: 0;
  color: var(--texto-suave);
  font-size: var(--fs-xs);
  line-height: 1.6;
}

@media (min-width: 900px) {
  .pie { padding-block: 5rem 6.5rem; }
  .pie__grid { grid-template-columns: 1fr 1fr; align-items: start; gap: var(--sp-8); }
  .pie__legal { max-width: 31rem; margin-left: auto; text-align: right; }
}

/* ── 12. REVELADO AL HACER SCROLL ──────────────────────────────────────── */
/* El estado inicial solo se aplica si JS está vivo (seq-ui.js pone .js en
   <html>). Sin JS todo el contenido se ve: nunca se esconde algo detrás de
   una animación que podría no ejecutarse. */
.js [data-revelar] {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 600ms ease, transform 600ms ease;
}
.js [data-revelar][data-visible="true"] { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .js [data-revelar] { opacity: 1; transform: none; }
}

/* ── 13. MOVIMIENTO ────────────────────────────────────────────────────── */
/* Todo lo de esta sección es decoración. Nada de lo que hay aquí esconde
   contenido de forma permanente ni hace falta para entender la página: si el
   JavaScript no corre o el sistema pide menos movimiento, la landing se ve
   igual, solo que quieta.

   Regla que se siguió en todas: se anima `transform` y `opacity`, que el
   navegador resuelve en la tarjeta gráfica, y nunca `width`, `top` o
   `margin`, que le obligan a rehacer el diseño en cada cuadro. */

/* ── Barra de progreso de lectura ─────────────────────────────────────── */
.progreso {
  position: fixed; inset: 0 0 auto 0; z-index: 120;
  height: 3px;
  pointer-events: none;
}
.progreso::before {
  content: ""; display: block; height: 100%;
  width: var(--avance-scroll, 0%);
  background: linear-gradient(90deg, var(--azul-claro), var(--blanco));
  transition: width 80ms linear;
}

/* ── Entrada de la portada ────────────────────────────────────────────── */
/* El estado inicial solo existe si el JavaScript está vivo (pone .js en el
   <html>), y la animación arranca cuando además marca .cargado. Sin JS no se
   esconde nada. */
.js [data-entrada] > * { opacity: 0; }

.js.cargado [data-entrada] > * {
  animation: entrar 720ms cubic-bezier(0.22, 1, 0.36, 1) forwards;
}
/* Escalonado: cada elemento arranca un poco después que el anterior, que es
   lo que hace que se lea como una secuencia y no como un parpadeo. */
.js.cargado .hero__contenido > *:nth-child(1) { animation-delay:  80ms; }
.js.cargado .hero__contenido > *:nth-child(2) { animation-delay: 160ms; }
.js.cargado .hero__contenido > *:nth-child(3) { animation-delay: 260ms; }
.js.cargado .hero__contenido > *:nth-child(4) { animation-delay: 360ms; }

@keyframes entrar {
  from { opacity: 0; transform: translateY(22px); }
  to   { opacity: 1; transform: none; }
}

/* ── Menú de teléfono: los enlaces entran en cascada ──────────────────── */
/* Solo cuando el panel está abierto, así que se repite cada vez que se abre
   y no una sola vez al cargar. */
.nav__menu[data-abierto="true"] .nav__links li,
.nav__menu[data-abierto="true"] > .btn {
  animation: entrar-lateral 420ms cubic-bezier(0.22, 1, 0.36, 1) both;
}
.nav__menu[data-abierto="true"] .nav__links li:nth-child(1) { animation-delay:  90ms; }
.nav__menu[data-abierto="true"] .nav__links li:nth-child(2) { animation-delay: 150ms; }
.nav__menu[data-abierto="true"] .nav__links li:nth-child(3) { animation-delay: 210ms; }
.nav__menu[data-abierto="true"] .nav__links li:nth-child(4) { animation-delay: 270ms; }
.nav__menu[data-abierto="true"] > .btn { animation-delay: 330ms; }

@keyframes entrar-lateral {
  from { opacity: 0; transform: translateX(26px); }
  to   { opacity: 1; transform: none; }
}

/* ── Tarjetas flotantes de la portada ─────────────────────────────────── */
/* Entran de abajo hacia arriba, ya inclinadas: el ángulo vive en `rotate`,
   que es otra propiedad y no se pisa con el `transform` de la entrada. */
.js.cargado .flotantes > * { animation: entrar 760ms cubic-bezier(0.22, 1, 0.36, 1) forwards; }

/* Dos valores en el retraso: el primero es para la entrada y el segundo para
   el balanceo que se le suma en escritorio. Aquí abajo solo hay una
   animación y el segundo valor se ignora sin ruido. */
.js.cargado .flotantes > *:nth-child(1) { animation-delay: 320ms, 1.4s; }
.js.cargado .flotantes > *:nth-child(2) { animation-delay: 440ms, 1.7s; }
.js.cargado .flotantes > *:nth-child(3) { animation-delay: 560ms, 2.0s; }

@media (min-width: 900px) {
  /* Una vez colocadas, respiran. Tres duraciones distintas a propósito: con
     la misma, las tres suben y bajan a la vez y parece un fallo. */
  .js.cargado .flotantes > * {
    animation: entrar 760ms cubic-bezier(0.22, 1, 0.36, 1) forwards,
               flotar 7s ease-in-out infinite;
  }
  .js.cargado .flotantes > *:nth-child(2) { animation-duration: 760ms, 8.5s; }
  .js.cargado .flotantes > *:nth-child(3) { animation-duration: 760ms, 6.2s; }

  /* Al pasar por encima se detiene el balanceo, la tarjeta se endereza, se
     levanta sobre las demás y su sombra se hace más profunda. */
  .flotante {
    transition: box-shadow 320ms cubic-bezier(0.4, 0, 0.2, 1),
                rotate 320ms cubic-bezier(0.4, 0, 0.2, 1);
  }
  .flotante:hover {
    animation-play-state: paused;
    z-index: 3;
    rotate: 0deg;
    box-shadow: 0 28px 60px rgba(var(--tinta-rgb), 0.38);
  }
}

@keyframes flotar {
  0%, 100% { translate: 0 0; }
  50%      { translate: 0 -10px; }
}

/* ── El bloque de la visión entra desde los lados ─────────────────────── */
@media (min-width: 900px) {
  .js .vision[data-revelar] .vision__claro  { transform: translateX(-18px); opacity: 0; }
  .js .vision[data-revelar] .vision__oscuro { transform: translateX(18px);  opacity: 0; }
  .js .vision[data-revelar] .vision__claro,
  .js .vision[data-revelar] .vision__oscuro {
    transition: transform 720ms cubic-bezier(0.22, 1, 0.36, 1) 120ms,
                opacity 720ms ease 120ms;
  }
  .js .vision[data-visible="true"] .vision__claro,
  .js .vision[data-visible="true"] .vision__oscuro { transform: none; opacity: 1; }
}

/* ── WhatsApp flotante ────────────────────────────────────────────────── */
.wa {
  position: fixed; right: var(--sp-4); bottom: var(--sp-4); z-index: 95;
  display: grid; place-items: center;
  width: 56px; height: 56px;
  background: #25D366;
  border-radius: 50%;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.28);
  /* Nace fuera de la vista y solo entra cuando seq-ui.js lo dice. */
  opacity: 0; visibility: hidden;
  transform: translateY(16px) scale(0.9);
  transition: opacity 320ms ease, transform 320ms cubic-bezier(0.34, 1.4, 0.64, 1),
              visibility 320ms;
}
.wa--visible { opacity: 1; visibility: visible; transform: none; }
.wa:hover { transform: scale(1.08); }
.wa svg { width: 30px; height: 30px; position: relative; z-index: 1; }

/* El anillo que late. Es un pseudo-elemento aparte y no el botón mismo:
   así el `scale` del hover no pelea con la animación. */
.wa__pulso {
  position: absolute; inset: 0;
  border-radius: 50%;
  background: #25D366;
  animation: pulso 2.6s ease-out infinite;
}
@keyframes pulso {
  0%   { transform: scale(1);    opacity: 0.55; }
  70%  { transform: scale(1.75); opacity: 0; }
  100% { transform: scale(1.75); opacity: 0; }
}

@media (min-width: 900px) {
  .wa { right: var(--sp-5); bottom: var(--sp-5); width: 60px; height: 60px; }
}

/* ── Menos movimiento: se apaga todo lo de arriba ─────────────────────── */
/* El bloque general del reinicio ya acorta las transiciones; esto se asegura
   de que lo que empieza invisible termine visible igual, y de que nada quede
   latiendo en bucle. */
@media (prefers-reduced-motion: reduce) {
  .js [data-entrada] > *,
  .js.cargado [data-entrada] > *,
  .js.cargado .flotantes > * {
    opacity: 1;
    transform: none;
    animation: none !important;
  }
  .js .vision[data-revelar] .vision__claro,
  .js .vision[data-revelar] .vision__oscuro { opacity: 1; transform: none; }
  .wa__pulso { animation: none; }
  .progreso::before { transition: none; }
}
