/* ============================================================
   Cē · Plataforma de ingeniería digital
   Hoja de estilos principal — mobile first.

   Índice:
   1.  Tokens de diseño (variables)
   2.  Reset y base
   3.  Utilidades y layout (rejilla, secciones, tipografía de sección)
   4.  Componentes: botones, enlaces, marca, header, navegación
   5.  Secciones: hero, servicios, producto (+ modal de precio), nosotros, contacto
   6.  Footer
   7.  Animaciones y accesibilidad
   8.  Media queries (tablet / escritorio / pantallas bajas / grandes / impresión)

   La paleta (--ocre/--turquesa/--negro/--blanco) y la tipografía de marca
   (Geist, --font-marca) viven en brand-tokens.css — única fuente, compartida
   con el panel (frontend/panel). index.html la enlaza antes que esta hoja.
   ============================================================ */

/* ------------------------------------------------------------
   1. TOKENS DE DISEÑO

   Dos familias de superficie, no una:
   · claro  — fondo blanco/superficie, tinta negra   (--tinta-*)
   · oscuro — fondo negro, tinta blanca              (--tinta-* redefinidos)

   Las superficies oscuras (.hero, .section--dark, .site-footer) redefinen los
   mismos nombres, así los componentes (eyebrow, tarjeta, botón) se escriben
   una sola vez y funcionan sobre cualquier fondo.
   ------------------------------------------------------------ */

:root {
  /* --- Superficies claras (por defecto) --- */
  --fondo:      var(--blanco);
  --superficie: #FFFDF9;
  --elevado:    #FFFFFF;

  /* --- Tinta sobre fondo claro --- */
  --tinta:      var(--negro);
  --tinta-80:   rgba(20, 19, 15, 0.80);
  --tinta-60:   rgba(20, 19, 15, 0.62);
  --tinta-40:   rgba(20, 19, 15, 0.38);

  /* --- Líneas: una sola escala, siempre hairline --- */
  --linea:       rgba(20, 19, 15, 0.12);
  --linea-sutil: rgba(20, 19, 15, 0.07);

  /* --- Variantes de acento por contraste ---
     El ocre #C98A2E y el turquesa #17A398 de marca no cambian: se usan tal cual
     como grafismo (viñetas, marcas de sección, mockup, logotipo). Pero ninguno
     de los dos alcanza AA como *texto* sobre fondo claro (2.9:1 y 2.7:1), ni
     sostiene texto blanco encima (~3:1). El texto de acento y las superficies de
     acción usan una versión oscurecida del mismo tono, y sobre negro una
     aclarada. Mismo color de marca, distinta luminosidad. */
  --turquesa-texto: #0F7C73;  /* 4.7:1 sobre --blanco; blanco encima: 5:1 */
  --ocre-texto:     #96631C;  /* 4.7:1 sobre --blanco */
  --turquesa-claro: #3FC4B8;  /* 8.6:1 sobre --negro */
  --ocre-claro:     #E0A854;  /* 8.7:1 sobre --negro */

  /* Superficie de acción (botón primario, volver arriba): texto blanco encima
     con AA. El hover oscurece, nunca aclara — el contraste sube, no baja. */
  --accion:       var(--turquesa-texto);
  --accion-hover: #0B665F;

  /* Error: terracota, fuera de la paleta de marca a propósito — el ocre y el
     turquesa ya significan acento y acción, un error no debe confundirse con
     ellos. Contraste ~5:1 sobre el fondo blanco. */
  --error: #B23A2B;
  --error-claro: #E08376;

  --acento:   var(--turquesa-texto);
  --acento-2: var(--ocre-texto);

  /* --- Tipografía --- */
  --font-sans: var(--font-marca);
  --leading-tight: 1.05;
  --leading-body: 1.6;

  /* Escala fluida: se adapta al ancho sin media queries. Cuatro tamaños de
     titular, uno por nivel — hero, manifiesto, sección, tarjeta. Los mínimos
     son deliberadamente contenidos: en móvil pequeño un título enorme rompe
     palabras y obliga a scroll horizontal. */
  --fs-hero:     clamp(2.75rem, 8vw, 6.25rem);
  --fs-title-xl: clamp(2rem, 5vw, 3.75rem);
  --fs-title:    clamp(1.75rem, 3.6vw, 2.75rem);
  --fs-card:     1.25rem;
  --fs-lead:     clamp(1.0625rem, 1.6vw, 1.25rem);
  --fs-body:     1rem;
  --fs-small:    0.875rem;
  --fs-micro:    0.75rem;

  /* --- Espaciado y geometría --- */
  --space-section: clamp(4.5rem, 10vw, 8rem);
  --space-head:    clamp(2.5rem, 5vw, 3.5rem);   /* encabezado de sección → contenido */
  --container: 1180px;
  --gutter: clamp(1.25rem, 5vw, 3rem);
  --radius: 16px;
  --radius-sm: 10px;
  --radius-xs: 6px;

  /* Altura real del header — la usan el scroll-padding y el panel móvil,
     así un cambio de alto no descuadra los anclajes. */
  --header-h: 4.5rem;

  /* --- Sombras: tres niveles, siempre difusas y frías --- */
  --sombra-sm: 0 2px 8px -4px rgba(20, 19, 15, 0.18);
  --sombra-md: 0 18px 44px -28px rgba(20, 19, 15, 0.40);
  --sombra-lg: 0 40px 80px -48px rgba(20, 19, 15, 0.55);

  /* --- Movimiento: rápido, discreto, consistente --- */
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-out: cubic-bezier(0.33, 1, 0.68, 1);
  --speed-fast: 0.18s;
  --speed: 0.32s;
  --speed-slow: 0.6s;
}

/* Superficies oscuras: mismos nombres, otros valores. */
.hero,
.section--dark,
.site-footer {
  --fondo:       var(--negro);
  --superficie:  #1B1A15;
  --elevado:     #1F1E18;
  --tinta:       var(--blanco);
  --tinta-80:    rgba(247, 245, 240, 0.78);
  --tinta-60:    rgba(247, 245, 240, 0.62);
  --tinta-40:    rgba(247, 245, 240, 0.34);
  --linea:       rgba(247, 245, 240, 0.14);
  --linea-sutil: rgba(247, 245, 240, 0.08);
  /* Sobre negro el turquesa y el ocre base quedan bajos de contraste */
  --acento:      var(--turquesa-claro);
  --acento-2:    var(--ocre-claro);
  --error:       var(--error-claro);
}

/* ------------------------------------------------------------
   2. RESET Y BASE
   ------------------------------------------------------------ */
*,
*::before,
*::after { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  /* Compensa el header fijo al saltar a un ancla, con aire extra */
  scroll-padding-top: calc(var(--header-h) + 1.5rem);
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--blanco);
  color: var(--negro);
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  line-height: var(--leading-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* Nunca scroll horizontal accidental */
  overflow-x: clip;
}

/* Bloquea el scroll del documento mientras el menú móvil está abierto */
body.is-locked { overflow: hidden; }

h1, h2, h3 {
  margin: 0 0 0.5em;
  line-height: var(--leading-tight);
  letter-spacing: -0.03em;
  font-weight: 640;
  text-wrap: balance;
}

p { margin: 0 0 1.25rem; }
p:last-child { margin-bottom: 0; }

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

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

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

/* `hidden` gana siempre. El display del navegador para [hidden] es una regla de
   user agent: cualquier clase que declare display le gana. Esta regla evita que
   lo oculto con el atributo (panel de éxito, toggle de precios, errores de
   campo, campo Mensaje con prefill, línea de contexto) se muestre igual. */
[hidden] { display: none !important; }

strong { font-weight: 640; }

/* Foco visible y consistente en todo el sitio, también sobre negro */
:focus-visible {
  outline: 2px solid var(--acento);
  outline-offset: 3px;
  border-radius: var(--radius-xs);
}

::selection { background: rgba(23, 163, 152, 0.22); }

/* ------------------------------------------------------------
   3. UTILIDADES Y LAYOUT
   ------------------------------------------------------------ */
.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.section {
  position: relative;
  padding-block: var(--space-section);
  background: var(--fondo);
  color: var(--tinta);
}

/* Alterna la superficie sin cambiar de familia de tinta. Filo entre dos
   secciones claras: una línea, nunca una sombra. Junto a una oscura sobra —
   el cambio de fondo ya es el corte. */
.section--alt { background: var(--superficie); }
.section + .section:not(.section--dark) { border-top: 1px solid var(--linea-sutil); }
.section--dark + .section { border-top: 0; }

/* --- Encabezado de sección: etiqueta + título ---
   Un solo bloque, mismo ritmo vertical en todas las secciones. */
.section__head { max-width: 62ch; margin-bottom: var(--space-head); }

.section__title { font-size: var(--fs-title); max-width: 18ch; margin-bottom: 1.25rem; }
.section__title:last-child { margin-bottom: 0; }

/* Etiqueta corta sobre cada título de sección, con marca de conteo (el "uno") */
.eyebrow {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  margin: 0 0 1.125rem;
  font-size: var(--fs-micro);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--acento-2);
}
.eyebrow::before {
  content: "";
  flex: none;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
}

.prose {
  max-width: 60ch;
  color: var(--tinta-80);
  font-size: var(--fs-lead);
  line-height: 1.6;
}

/* Palabra destacada dentro de un párrafo editorial */
.mark {
  color: var(--tinta);
  font-weight: 640;
  box-shadow: inset 0 -0.32em 0 rgba(23, 163, 152, 0.16);
}

.grid-2 { display: grid; gap: clamp(2.5rem, 5vw, 4.5rem); }
/* Sin esto un hijo de ancho fijo (el widget de Turnstile mide 300px) ensancha
   toda la columna por encima del viewport en móviles de 360px. */
.grid-2 > * { min-width: 0; }

/* Enlace de salto: sólo aparece al navegar con teclado */
.skip-link {
  position: absolute;
  left: 1rem;
  top: -100%;
  z-index: 999;
  padding: 0.75rem 1.25rem;
  background: var(--negro);
  color: var(--blanco);
  border-radius: var(--radius-sm);
  transition: top var(--speed-fast) var(--ease);
}
.skip-link:focus { top: 1rem; }

/* ------------------------------------------------------------
   4. COMPONENTES
   ------------------------------------------------------------ */

/* --- Botones ---
   Dos variantes y una sola gramática de movimiento: 1px de elevación al
   hover, ninguna al :active. Nada de escalas ni sombras de color.
   Alto mínimo 44px en todos los tamaños: objetivo táctil recomendado. */
.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: 44px;
  padding: 0.8rem 1.5rem;
  border: 1px solid transparent;
  border-radius: 999px;
  font-family: inherit;
  font-size: 0.9375rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1.2;
  cursor: pointer;
  white-space: nowrap;
  transition: transform var(--speed-fast) var(--ease),
              background-color var(--speed-fast) var(--ease),
              color var(--speed-fast) var(--ease),
              border-color var(--speed-fast) var(--ease);
}
.btn:hover { transform: translateY(-1px); }
.btn:active { transform: none; }
.btn--sm { padding: 0.55rem 1.1rem; font-size: var(--fs-small); }
.btn--lg { min-height: 52px; padding: 0.95rem 1.9rem; font-size: 1rem; }

.btn--primary { background: var(--accion); color: #FFFFFF; }
.btn--primary:hover { background: var(--accion-hover); }

/* Contorno sobre cualquier superficie: hereda la tinta del contexto */
.btn--ghost {
  border-color: var(--tinta-40);
  color: var(--tinta);
  background: transparent;
}
.btn--ghost:hover { border-color: var(--acento); color: var(--acento); }

/* Flecha del botón: se desplaza un pelo al hover */
.btn__arrow {
  flex: none;
  transition: transform var(--speed) var(--ease);
}
.btn:hover .btn__arrow { transform: translateX(3px); }

/* Estado de envío: rueda dentro del propio botón, sin cambiar su ancho */
.btn[disabled] { opacity: 0.75; cursor: progress; transform: none; }
.btn.is-loading .btn__label { visibility: hidden; }
.btn.is-loading::after {
  content: "";
  position: absolute;
  width: 1.05rem;
  height: 1.05rem;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: girar 0.7s linear infinite;
}
@keyframes girar { to { transform: rotate(360deg); } }

/* Enlace de texto dentro de un párrafo: siempre subrayado (no depende sólo
   del color para distinguirse), el subrayado se engrosa al hover. */
.link {
  font-weight: 600;
  color: var(--acento);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
  transition: text-decoration-thickness var(--speed-fast) var(--ease);
  overflow-wrap: anywhere;
}
.link:hover { text-decoration-thickness: 2px; }

/* --- Marca (logotipo + palabra) ---
   Uso del logotipo, según el manual (docs/MARCA.md):
   · Alto mínimo 24 px — por debajo se pierde el píxel turquesa.
   · Área de respeto = el ancho del asta (~11.5 % del alto del logotipo).
     Con el alto máximo usado aquí (32 px) el área requerida es ~3.7 px; el gap
     de 0.6rem (9.6 px) y el min-height del header la cubren de sobra.
   · Prohibido: estirar, rotar, sombras, contornos, degradados, filter: invert(),
     opacity o encerrarlo en un círculo de color. La variante se cambia
     intercambiando el archivo, nunca alterando el que ya está en pantalla. */
.brand { display: inline-flex; align-items: center; gap: 0.6rem; }
.brand__mark {
  /* Tamaño explícito: el SVG mide 1024 px de forma nativa y sin esto
     se pintaría a tamaño completo. Nunca por debajo de 24 px. */
  width: 32px;
  height: 32px;
  flex: none;
  object-fit: contain;
}
.site-footer .brand__mark { width: 28px; height: 28px; }
.brand__word {
  font-size: 1.3rem;
  font-weight: 640;
  letter-spacing: -0.02em;
}

/* --- Header fijo ---
   Sobre el hero el header no tiene fondo propio: el negro del hero es su fondo.
   Al dejar atrás el hero (main.js añade .is-scrolled) pasa a superficie clara.
   Las dos variantes del logotipo están en el HTML y se intercambian por
   archivo — nunca con filter: invert() ni opacity, según el manual de marca. */
.site-header {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 100;
  background: transparent;
  border-bottom: 1px solid transparent;
  /* Tinta clara mientras flota sobre el hero */
  --tinta:    var(--blanco);
  --tinta-80: rgba(247, 245, 240, 0.80);
  --tinta-40: rgba(247, 245, 240, 0.34);
  --linea-sutil: rgba(247, 245, 240, 0.08);
  --acento:   var(--turquesa-claro);
  color: var(--tinta);
  transition: border-color var(--speed) var(--ease),
              background-color var(--speed) var(--ease);
}

/* Variante del logotipo según el fondo real de la barra */
.brand__mark--claro  { display: none; }
.brand__mark--oscuro { display: block; }

/* Superficie clara: al pasar el hero, o con el menú móvil abierto (el panel
   es claro, así que la barra tiene que acompañarlo). */
.site-header.is-scrolled,
.site-header.is-menu-open {
  background: rgba(247, 245, 240, 0.92);
  backdrop-filter: saturate(180%) blur(16px);
  -webkit-backdrop-filter: saturate(180%) blur(16px);
  border-bottom-color: var(--linea);
  --tinta:    var(--negro);
  --tinta-80: rgba(20, 19, 15, 0.80);
  --tinta-40: rgba(20, 19, 15, 0.38);
  --linea-sutil: rgba(20, 19, 15, 0.07);
  --acento:   var(--turquesa-texto);
}
/* Con el menú abierto la barra es opaca: continúa el panel sin costura */
.site-header.is-menu-open { background: var(--blanco); }
.site-header.is-scrolled .brand__mark--claro,
.site-header.is-menu-open .brand__mark--claro { display: block; }
.site-header.is-scrolled .brand__mark--oscuro,
.site-header.is-menu-open .brand__mark--oscuro { display: none; }

.header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  min-height: var(--header-h);
}

/* --- Navegación (móvil: panel a pantalla completa) --- */
.nav {
  /* absolute, no fixed: el panel cuelga del header (su ancestro posicionado) y
     ocupa el resto de la pantalla. Con `fixed` no funciona: al abrirse, el header
     gana .is-menu-open y con ella `backdrop-filter`, que crea containing block
     para los descendientes fixed (igual que transform), y el panel se mediría
     contra la barra de 4.5rem, con altura cero. */
  position: absolute;
  inset: 100% 0 auto 0;
  height: calc(100vh - var(--header-h));
  height: calc(100dvh - var(--header-h));
  background: var(--blanco);
  /* Fuera de pantalla y sin foco alcanzable hasta abrirse */
  visibility: hidden;
  opacity: 0;
  transform: translateY(-8px);
  transition: opacity var(--speed) var(--ease),
              transform var(--speed) var(--ease),
              visibility var(--speed) var(--ease);
  overflow-y: auto;
  overscroll-behavior: contain;
}
.nav.is-open { visibility: visible; opacity: 1; transform: none; }

.nav__list {
  display: flex;
  flex-direction: column;
  padding: 0.5rem var(--gutter) 2.5rem;
}
.nav__item { border-bottom: 1px solid var(--linea-sutil); }

.nav__link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.05rem 0;
  font-size: 1.125rem;
  font-weight: 500;
  color: var(--tinta-80);
  transition: color var(--speed-fast) var(--ease);
}
.nav__link:hover { color: var(--acento); }

/* Sección actualmente en pantalla — la marca main.js (§ scrollspy) */
.nav__link.is-active { color: var(--tinta); font-weight: 620; }
.nav__link.is-active::after {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--turquesa);
}

.nav__cta { margin-top: 1.5rem; }
.nav__cta .btn { width: 100%; }

/* --- Botón hamburguesa --- */
.nav-toggle {
  /* El user agent le da a <button> su propio `color` (buttontext), así que sin
     esto no hereda la tinta del header y las barras serían negras sobre el hero
     negro. Con inherit siguen al estado de la barra, igual que el logotipo. */
  color: inherit;
  display: inline-flex;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 44px;
  height: 44px;
  padding: 0 10px;
  margin-right: -10px;
  background: none;
  border: 0;
  cursor: pointer;
}
.nav-toggle__bar {
  height: 2px;
  background: currentColor;
  border-radius: 2px;
  transition: transform var(--speed) var(--ease);
}
/* Estado abierto: las dos barras forman una X */
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:first-child { transform: translateY(3.5px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:last-child  { transform: translateY(-3.5px) rotate(-45deg); }

/* ------------------------------------------------------------
   5. SECCIONES
   ------------------------------------------------------------ */

/* --- 5.1 Hero --- */
.hero {
  position: relative;
  background: var(--fondo);
  color: var(--tinta);
  padding-block: calc(var(--header-h) + clamp(2.5rem, 9vw, 6.5rem)) clamp(3.5rem, 8vw, 6.5rem);
  overflow: hidden;
}

.hero__inner {
  display: grid;
  gap: clamp(2.5rem, 7vw, 4rem);
  align-items: center;
}

.hero__eyebrow {
  margin: 0 0 clamp(1.25rem, 3vw, 1.75rem);
  font-size: var(--fs-micro);
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--acento-2);
}

.hero__title {
  font-size: var(--fs-hero);
  font-weight: 660;
  letter-spacing: -0.045em;
  line-height: 1;
  margin: 0 0 clamp(1.25rem, 3vw, 1.75rem);
}
/* El punto final del tagline en turquesa: el "uno" que abre todo */
.hero__title .punto { color: var(--acento); }

.hero__lead {
  max-width: 46ch;
  font-size: var(--fs-lead);
  color: var(--tinta-80);
  margin-bottom: clamp(2rem, 4vw, 2.5rem);
}

/* En móvil los dos botones ocupan el ancho: mismo tamaño, mismo peso visual
   de objetivo táctil; desde tablet vuelven a su ancho natural (§ 8). */
.hero__actions,
.producto__acciones { display: flex; flex-wrap: wrap; gap: 0.75rem; }
.hero__actions .btn,
.producto__acciones .btn { flex: 1 1 100%; }

/* --- Visual del hero: uno → todo ---
   Un nodo origen (el logotipo) y la red que sale de él. Construido con el
   mismo vocabulario del logotipo (punto + barra del conteo mesoamericano),
   no una ilustración genérica. Decorativo: en móvil se queda chico para no
   empujar el resto del contenido fuera de pantalla. */
.hero__visual {
  position: relative;
  display: grid;
  place-items: center;
  margin-inline: auto;
  width: min(72%, 18rem);
  aspect-ratio: 1 / 1;
}
.hero__net { position: absolute; inset: 0; width: 100%; height: 100%; }
.hero__net .arista {
  /* Sobre negro el turquesa base se apaga: la red usa la variante clara */
  stroke: var(--turquesa-claro);
  stroke-width: 1.4;
  stroke-opacity: 0.7;
  fill: none;
  stroke-linecap: round;
}
.hero__net .nodo { fill: var(--turquesa-claro); }
.hero__net .nodo--ocre { fill: var(--ocre-claro); }
/* Halo: el mismo color, muy abierto — da presencia sin subir el ruido */
.hero__net .halo { fill: var(--turquesa-claro); opacity: 0.18; }
.hero__net .halo--ocre { fill: var(--ocre-claro); }
.hero__net .anillo { fill: none; stroke: var(--linea); stroke-width: 1; }

.hero__logo {
  position: relative;
  /* Nunca por debajo de 24px de alto; el logotipo es cuadrado (1:1) */
  width: clamp(64px, 17vw, 124px);
  aspect-ratio: 1 / 1;
  object-fit: contain;
}

/* --- 5.2 Servicios ---
   Tarjetas informativas, no enlaces: sin hover que prometa un clic que no hay. */
.cards { display: grid; gap: clamp(1rem, 2vw, 1.5rem); }

.card {
  display: grid;
  align-content: start;
  gap: 0.75rem;
  padding: clamp(1.5rem, 4vw, 2.25rem);
  background: var(--elevado);
  border: 1px solid var(--linea);
  border-radius: var(--radius);
}

/* Numeración: la misma voz que los valores (§ 5.4) y los pasos (§ 5.5) */
.card__num,
.value__term::before,
.pasos li::before {
  font-size: var(--fs-micro);
  font-weight: 600;
  letter-spacing: 0.14em;
  color: var(--acento-2);
  font-variant-numeric: tabular-nums;
}
.card__title { font-size: var(--fs-card); margin: 0; }
.card__text { color: var(--tinta-60); margin: 0; }

/* --- 5.3 Producto --- */
.producto__inner { align-items: center; }

.feature-list {
  display: grid;
  gap: 0.85rem;
  margin: 1.75rem 0 2.25rem;
  color: var(--tinta-80);
}
.feature-list li {
  position: relative;
  padding-left: 1.75rem;
}
/* Viñeta: el "uno" del conteo mesoamericano */
.feature-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--turquesa);
}

/* Marco del mockup: el producto se presenta como pantalla, no como imagen suelta */
.mockup-frame {
  margin: 0;
  padding: clamp(0.5rem, 1.5vw, 0.75rem);
  background: var(--elevado);
  border: 1px solid var(--linea);
  border-radius: calc(var(--radius) + 6px);
  box-shadow: var(--sombra-lg);
}
.mockup { width: 100%; border-radius: var(--radius); }

/* Pie del mockup: qué se está viendo. Texto real del producto. */
.mockup-frame__pie {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0.75rem 0.25rem 0.25rem;
  font-size: var(--fs-micro);
  color: var(--tinta-60);
}
.mockup-frame__pie::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--turquesa);
}

/* --- Modal de precio ---
   Abierto por el botón "Ver precio" (<dialog>, sin librería: ESC, backdrop y
   focus-trap nativos). Renderiza en el top layer, así que su posición en el
   DOM no importa para el layout visible — pero sigue atado a SU producto (ids
   con sufijo -pos): un segundo producto trae su propio <dialog> con el mismo
   patrón, no comparte éste. */
.modal-precio {
  /* Sin `position` propia a propósito: el UA stylesheet le da `position: fixed`
     vía `dialog:modal` cuando se abre con showModal() — eso es lo que lo centra
     sin depender del scroll. Pisarlo con `relative` haría que el navegador
     tratara su posición real en el DOM como la que hay que traer a la vista,
     forzando un scroll hasta la sección Producto al abrir. `fixed` también
     sirve de contenedor para el botón cerrar en absolute. */
  width: min(30rem, calc(100vw - 2.5rem));
  max-height: min(88vh, 46rem);
  overflow-y: auto;
  margin: auto;
  padding: clamp(1.75rem, 4vw, 2.5rem);
  border: 1px solid var(--linea);
  border-radius: calc(var(--radius) + 4px);
  background: var(--elevado);
  box-shadow: var(--sombra-lg);
  color: var(--tinta);
  /* `display`/`overlay` en la transición son lo que permite animar la
     ENTRADA (junto con @starting-style abajo); en navegadores que no
     soportan @starting-style esto se ignora y el modal sólo aparece,
     sin animar — degradación aceptable, no un fallback que mantener. */
  transition: opacity var(--speed) var(--ease), transform var(--speed) var(--ease),
              overlay var(--speed) allow-discrete, display var(--speed) allow-discrete;
}
.modal-precio::backdrop { background: rgba(20, 19, 15, 0.55); }
@starting-style {
  .modal-precio[open] { opacity: 0; transform: translateY(0.5rem); }
}

.modal-precio__cerrar {
  position: absolute;
  top: 1rem;
  right: 1rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border: 1px solid var(--linea);
  border-radius: 50%;
  background: var(--superficie);
  color: var(--tinta-60);
  cursor: pointer;
  transition: color var(--speed-fast) var(--ease), border-color var(--speed-fast) var(--ease);
}
.modal-precio__cerrar:hover { color: var(--tinta); border-color: var(--tinta-40); }

.modal-precio__titulo { margin: 0 0 0.5rem; font-size: clamp(1.5rem, 4vw, 1.875rem); padding-right: 3rem; }
.modal-precio .prose { margin: 0 0 1.5rem; font-size: var(--fs-body); }

/* Escape hatch del precio revelado: una línea, no otro bloque grande — quien
   ya vio el precio y no le sirve no necesita un segundo argumento de venta,
   solo la salida hacia una cotización real. */
.modal-precio__pie {
  margin: 1.75rem 0 0;
  padding-top: 1.5rem;
  border-top: 1px solid var(--linea-sutil);
  color: var(--tinta-60);
  font-size: var(--fs-small);
}

/* Precio de un solo producto: una tarjeta, del ancho del modal */
.pricing { display: grid; gap: 1rem; margin-top: 1.25rem; }
.pricing:empty { display: none; }

.pricing-card {
  display: grid;
  align-content: start;
  padding: 1.5rem;
  background: var(--elevado);
  border: 1px solid var(--linea);
  border-radius: var(--radius);
}

.pricing-card__precio {
  display: flex;
  align-items: baseline;
  gap: 0.4rem;
  margin: 0;
  font-variant-numeric: tabular-nums;
}
.pricing-card__precio-valor {
  font-size: clamp(2rem, 4vw, 2.5rem);
  font-weight: 680;
  letter-spacing: -0.04em;
}
.pricing-card__precio-ciclo { color: var(--tinta-60); font-size: var(--fs-small); }

.pricing-card__ahorro { margin: 0.35rem 0 0; color: var(--acento); font-size: var(--fs-small); font-weight: 600; }

/* Sin tarifa fija (ej. planes de consultoría a medida) */
.pricing-card__cotizacion { margin: 0; font-size: 1.25rem; font-weight: 680; }

.pricing__toggle {
  display: inline-flex;
  gap: 0.25rem;
  padding: 3px;
  border: 1px solid var(--linea);
  border-radius: 999px;
  background: var(--elevado);
}
.pricing__toggle-btn {
  border: 0;
  background: none;
  padding: 0.5rem 1.15rem;
  border-radius: 999px;
  font-family: inherit;
  font-size: var(--fs-small);
  font-weight: 600;
  color: var(--tinta-60);
  cursor: pointer;
  transition: background-color var(--speed-fast) var(--ease), color var(--speed-fast) var(--ease);
}
.pricing__toggle-btn:hover { color: var(--tinta); }
.pricing__toggle-btn.is-active { background: var(--negro); color: var(--blanco); }

.pricing__status { margin: 1.25rem 0 0; color: var(--tinta-60); }
.pricing__status--error { color: var(--error); }

/* Esqueleto de carga: el modal nunca aparece vacío mientras llega el catálogo */
.pricing-skeleton { pointer-events: none; }
.pricing-skeleton__linea {
  height: 0.75rem;
  border-radius: 999px;
  background: var(--linea);
  margin-bottom: 0.75rem;
  animation: pulso 1.4s var(--ease) infinite;
}
.pricing-skeleton__linea:nth-child(1) { width: 40%; }
.pricing-skeleton__linea:nth-child(2) { width: 70%; height: 2rem; margin-block: 1.25rem; }
.pricing-skeleton__linea:nth-child(3) { width: 55%; margin-bottom: 0; }

@keyframes pulso {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.45; }
}

/* --- 5.4 Nosotros: nombre + manifiesto ---
   El único momento oscuro entre hero y footer: marca el cambio de registro,
   de lo que hacemos a quiénes somos. */
.nosotros__inner { display: grid; gap: clamp(2.5rem, 6vw, 4rem); align-items: end; }

.nosotros__quote {
  font-size: var(--fs-title-xl);
  letter-spacing: -0.04em;
  max-width: 17ch;
  margin: 0 0 clamp(1.5rem, 3vw, 2rem);
}
.nosotros__quote .claridad { color: var(--acento); }

/* La palabra Cē tratada como entrada de diccionario, no como decoración */
.glosa {
  display: grid;
  gap: 0.25rem;
  margin: 0;
  padding: clamp(1.5rem, 4vw, 2.25rem);
  border: 1px solid var(--linea);
  border-radius: var(--radius);
  background: var(--superficie);
}
.glosa__palabra {
  margin: 0;
  font-size: clamp(3.25rem, 8vw, 5rem);
  font-weight: 640;
  letter-spacing: -0.05em;
  line-height: 1;
}
.glosa__fonetica { margin: 0; color: var(--tinta-60); font-size: var(--fs-small); }
.glosa__def {
  display: grid;
  gap: 0.35rem;
  margin: 1.25rem 0 0;
  padding-top: 1.25rem;
  border-top: 1px solid var(--linea);
}
.glosa__def dt {
  font-size: var(--fs-micro);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--acento-2);
}
.glosa__def dd { margin: 0; font-size: 1.125rem; font-weight: 600; }

.values {
  display: grid;
  margin: clamp(3rem, 7vw, 4.5rem) 0 0;
  border-top: 1px solid var(--linea);
}
.value {
  padding: 1.5rem 0;
  border-bottom: 1px solid var(--linea);
}
.value__term {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  font-size: 1.125rem;
  font-weight: 640;
  letter-spacing: -0.02em;
  margin-bottom: 0.4rem;
}
.value__term::before { content: attr(data-num); }
.value__desc { margin: 0; color: var(--tinta-60); max-width: 42ch; }

/* --- 5.5 Contacto --- */
.contacto__inner { align-items: start; }

/* Qué pasa después de enviar — quita la incertidumbre del formulario.
   El título es una etiqueta (tipografía de .field__label, § Formulario), no un
   titular: sin punto. */
.pasos__titulo {
  margin: clamp(2rem, 5vw, 2.75rem) 0 1rem;
  padding-top: 1.75rem;
  border-top: 1px solid var(--linea);
}
.pasos {
  display: grid;
  gap: 1rem;
  margin: 0 0 clamp(2rem, 5vw, 2.75rem);
  color: var(--tinta-80);
  counter-reset: paso;
}
.pasos li {
  display: grid;
  grid-template-columns: 2rem 1fr;
  counter-increment: paso;
}
.pasos li::before {
  content: counter(paso, decimal-leading-zero);
  padding-top: 0.2em;
}

.contacto__correo { color: var(--tinta-60); font-size: var(--fs-small); }

/* --- Formulario de contacto --- */
.form {
  display: grid;
  gap: 1.125rem;
  /* Mínimo contenido a propósito: en 360px el widget de Turnstile (300px fijos)
     tiene que caber dentro del borde del formulario. */
  padding: clamp(1rem, 5vw, 2.25rem);
  background: var(--elevado);
  border: 1px solid var(--linea);
  border-radius: var(--radius);
  box-shadow: var(--sombra-sm);
}

.form__titulo {
  margin: 0;
  font-size: 1.0625rem;
  font-weight: 640;
}

/* Mensaje ya resuelto por un CTA (data-prefill): se muestra en vez del campo */
.form__contexto {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.25rem 1rem;
  margin: 0;
  padding: 0.85rem 1rem;
  background: var(--superficie);
  border: 1px solid var(--linea);
  border-radius: var(--radius-sm);
  font-size: var(--fs-small);
  color: var(--tinta-80);
}
.form__contexto strong { color: var(--tinta); }
/* Botón con aspecto de enlace (.link): sólo se quita el aspecto de botón */
.form__editar {
  padding: 0.5rem 0;
  border: 0;
  background: none;
  font-family: inherit;
  font-size: inherit;
  cursor: pointer;
}

.field { display: grid; gap: 0.4rem; }

.field__label,
.pasos__titulo {
  font-size: var(--fs-small);
  font-weight: 600;
  letter-spacing: 0.01em;
}
.field__opt { font-weight: 400; color: var(--tinta-60); }
.field__hint { margin: 0; font-size: var(--fs-small); color: var(--tinta-60); }

.field__input {
  width: 100%;
  min-height: 48px;
  padding: 0.8rem 1rem;
  font: inherit;
  color: var(--negro);
  background: #FFFFFF;
  /* 3:1 contra el blanco: el borde de un campo es un componente de interfaz */
  border: 1px solid rgba(20, 19, 15, 0.42);
  border-radius: var(--radius-sm);
  transition: border-color var(--speed-fast) var(--ease), box-shadow var(--speed-fast) var(--ease);
}
.field__input::placeholder { color: var(--tinta-60); }
.field__input:hover { border-color: rgba(20, 19, 15, 0.6); }
.field__input:focus {
  outline: none;
  border-color: var(--accion);
  box-shadow: 0 0 0 3px rgba(23, 163, 152, 0.22);
}
.field__input--area { resize: vertical; min-height: 7.5rem; line-height: 1.55; }

/* Estado de error: borde + texto, nunca sólo color */
.field__input[aria-invalid="true"] { border-color: var(--error); }
.field__input[aria-invalid="true"]:focus { box-shadow: 0 0 0 3px rgba(178, 58, 43, 0.18); }
.field__error {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0;
  font-size: var(--fs-small);
  color: var(--error);
}
.field__error::before { content: "!"; font-weight: 700; }

.form__submit { justify-self: stretch; margin-top: 0.25rem; }

.form__status {
  margin: 0;
  font-size: var(--fs-small);
  line-height: 1.5;
}
.form__status:empty { display: none; }
.form__status--ok { color: var(--acento); font-weight: 600; }
.form__status--error { color: var(--error); font-weight: 600; }

/* Éxito: el formulario se sustituye por una confirmación, no por un texto suelto */
.form__exito {
  display: grid;
  gap: 0.75rem;
  justify-items: start;
  padding: clamp(1.75rem, 4vw, 2.5rem);
  background: var(--elevado);
  border: 1px solid var(--turquesa);
  border-radius: var(--radius);
}
.form__exito h3 { margin: 0; font-size: var(--fs-card); }
.form__exito p { margin: 0; color: var(--tinta-60); }
.form__exito-icono {
  display: grid;
  place-items: center;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 50%;
  background: rgba(23, 163, 152, 0.12);
  color: var(--acento);
}

/* Honeypot: fuera de la pantalla, pero no display:none — algunos bots
   ignoran los campos ocultos con display:none o hidden. */
.field-hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* --- Volver arriba (flotante, abajo a la derecha) --- */
.to-top {
  position: fixed;
  right: clamp(1rem, 3vw, 2rem);
  bottom: clamp(1rem, 3vw, 2rem);
  z-index: 90;                    /* por debajo del header (100) */
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  /* Superficie de acción: el control cruza secciones claras y oscuras; en
     negro se perdería sobre el hero, Nosotros y el footer. */
  background: var(--accion);
  color: #FFFFFF;
  border-radius: 999px;
  box-shadow: var(--sombra-md);

  /* Oculto hasta que main.js añade .is-visible.
     visibility: hidden lo saca también del orden de tabulación. */
  opacity: 0;
  visibility: hidden;
  transform: translateY(10px);
  transition: opacity var(--speed) var(--ease), transform var(--speed) var(--ease),
              visibility var(--speed) var(--ease), background-color var(--speed-fast) var(--ease);
}
.to-top.is-visible { opacity: 1; visibility: visible; transform: none; }
/* Mismo hover que .btn--primary: un solo lenguaje para los elementos de acción */
.to-top:hover { background: var(--accion-hover); transform: translateY(-1px); }

/* ------------------------------------------------------------
   6. FOOTER
   ------------------------------------------------------------ */
.site-footer {
  background: var(--fondo);
  color: var(--tinta);
  padding-block: clamp(2.5rem, 6vw, 3.5rem);
  border-top: 1px solid var(--linea);
}
.footer__inner { display: grid; gap: 1.25rem; }
.footer__tag { margin: 0; color: var(--acento-2); font-weight: 500; }
.footer__legal {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 1.5rem;
  margin: 0;
  font-size: var(--fs-small);
  color: var(--tinta-60);
}
/* Enlaces del pie: alto táctil (44px) sin agrandar la tipografía */
.footer__legal a {
  padding-block: 0.75rem;
  transition: color var(--speed-fast) var(--ease);
}
.footer__legal a:hover { color: var(--acento); }

/* ------------------------------------------------------------
   7. ANIMACIONES Y ACCESIBILIDAD
   ------------------------------------------------------------ */

/* Aparición al hacer scroll.
   El estado oculto sólo se aplica si JS está activo (clase .js en <html>),
   así el contenido nunca queda invisible cuando el script no carga.
   Sólo opacity + transform: nada que fuerce layout. */
.js .reveal {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity var(--speed-slow) var(--ease-out),
              transform var(--speed-slow) var(--ease-out);
}
.js .reveal.is-visible { opacity: 1; transform: none; }

/* Entrada del hero: la misma gramática, sin esperar al scroll. */
.js .hero__inner > * > .enter {
  opacity: 0;
  transform: translateY(16px);
  animation: entrar 0.75s var(--ease-out) forwards;
}
.js .enter-1 { animation-delay: 0.05s; }
.js .enter-2 { animation-delay: 0.14s; }
.js .enter-3 { animation-delay: 0.23s; }
.js .enter-4 { animation-delay: 0.32s; }

@keyframes entrar {
  to { opacity: 1; transform: none; }
}

/* La red del hero se dibuja una vez, al cargar */
.js .hero__net .arista {
  stroke-dasharray: var(--largo, 200);
  stroke-dashoffset: var(--largo, 200);
  animation: trazar 1.5s var(--ease-out) forwards;
  animation-delay: 0.3s;
}
.js .hero__net .anillo {
  opacity: 0;
  animation: aparecer 0.8s var(--ease-out) 0.9s forwards;
}
@keyframes trazar { to { stroke-dashoffset: 0; } }
@keyframes aparecer { to { opacity: 1; } }
@keyframes aparecer-halo { to { opacity: 0.18; } }

/* --- Vida continua de la constelación ---

   Reglas que se siguen en todo este bloque:
   · Sólo transform y opacity — ninguna propiedad que dispare layout o repinte
     el SVG. El compositor se encarga de cada capa por su cuenta.
   · Cada animación continua arranca DESPUÉS de la entrada (delay ≥ 1.8s) y
     sobre una propiedad distinta a la que usó la entrada, así conviven en el
     mismo elemento sin pisarse: `aparecer` deja la opacidad, `respirar` toma
     el transform.
   · Los desfases salen de `--i` (índice puesto en el HTML). Ningún ciclo es
     múltiplo exacto de otro: el conjunto no vuelve a alinearse.
   · Nada de filter/blur ni box-shadow animados — el halo del centro es un
     degradado dentro del SVG (ver el <circle class="glow"> del HTML). */

/* Fuera de pantalla no hay nada que animar: main.js (§ 9) marca el hero cuando
   deja de verse y aquí se congela todo. */
.js .hero.esta-oculto .hero__net *,
.js .hero.esta-oculto .hero__logo { animation-play-state: paused; }

/* Órbita: dos sentidos, dos velocidades. Tan lento que no se "ve" girar,
   sólo se nota que la figura nunca es exactamente la misma. */
.js .hero__net .orbita {
  transform-box: view-box;
  transform-origin: 200px 200px;
  will-change: transform;
}
.js .hero__net .orbita--red     { animation: orbitar 150s linear 1.8s infinite; }
.js .hero__net .orbita--anillos { animation: orbitar 260s linear reverse 1.8s infinite; }

@keyframes orbitar { to { transform: rotate(360deg); } }

/* Nodos y halos: respiran desfasados. transform-box: fill-box → cada uno
   escala sobre su propio centro, aunque vaya dentro del grupo que rota. */
.js .hero__net .nodo,
.js .hero__net .halo,
.js .hero__net .pulso {
  transform-box: fill-box;
  transform-origin: 50% 50%;
}
.js .hero__net .nodo {
  opacity: 0;
  animation: aparecer 0.8s var(--ease-out) 0.9s forwards,
             respirar 5.2s var(--ease) calc(1.8s + var(--i, 0) * 0.62s) infinite;
}
.js .hero__net .halo {
  opacity: 0;
  animation: aparecer-halo 0.8s var(--ease-out) 0.9s forwards,
             respirar-halo 5.2s var(--ease) calc(1.8s + var(--i, 0) * 0.62s) infinite;
}

@keyframes respirar {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.16); }
}
/* El halo respira más amplio y en contrafase suave: el nodo parece emitir */
@keyframes respirar-halo {
  0%, 100% { transform: scale(1);    opacity: 0.18; }
  50%      { transform: scale(1.28); opacity: 0.28; }
}

/* Pulsos: nacen en el centro y recorren su eje hasta el nodo.
   Un solo translate interpolado — el trayecto es recto, como la arista. */
.hero__net .pulso { fill: var(--turquesa-claro); opacity: 0; }
.js .hero__net .pulso {
  animation: pulsar 6.4s var(--ease-out) calc(2.4s + var(--i, 0) * 1.05s) infinite;
}
@keyframes pulsar {
  0%   { transform: translate(0, 0) scale(0.6); opacity: 0; }
  12%  { opacity: 0.85; }
  55%  { transform: translate(var(--dx), var(--dy)) scale(1); opacity: 0; }
  /* El resto del ciclo queda en reposo: los pulsos no se encadenan sin pausa */
  100% { transform: translate(var(--dx), var(--dy)) scale(1); opacity: 0; }
}

/* Halo del centro y logotipo laten juntos, muy despacio y muy poco:
   1.5 % de escala es suficiente para que se lea como respiración. */
.js .hero__net .glow {
  transform-box: fill-box;
  transform-origin: 50% 50%;
  opacity: 0;
  animation: aparecer 1.4s var(--ease-out) 0.6s forwards,
             latir-glow 7s var(--ease) 2s infinite;
}
.js .hero__logo {
  animation: latir 7s var(--ease) 2s infinite;
  will-change: transform;
}
@keyframes latir {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.015); }
}
@keyframes latir-glow {
  0%, 100% { transform: scale(1);    opacity: 1; }
  50%      { transform: scale(1.07); opacity: 0.78; }
}

/* Respeta la preferencia de movimiento reducido del sistema.
   Todo lo de arriba se apaga: la constelación queda en su estado final, quieta. */
@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;
  }
  .js .reveal,
  .js .hero__inner > * > .enter { opacity: 1; transform: none; animation: none; }
  .js .hero__net .arista { stroke-dashoffset: 0; animation: none; }
  .js .hero__net .nodo,
  .js .hero__net .anillo,
  .js .hero__net .glow { opacity: 1; animation: none; }
  .js .hero__net .halo { opacity: 0.18; animation: none; }
  .js .hero__net .pulso,
  .js .hero__net .orbita,
  .js .hero__logo { animation: none; }
}

/* ------------------------------------------------------------
   8. MEDIA QUERIES
   ------------------------------------------------------------ */

/* --- Tablet --- */
@media (min-width: 720px) {
  .hero__actions .btn,
  .producto__acciones .btn { flex: 0 0 auto; }
  .form__submit { justify-self: start; }

  .values { grid-template-columns: repeat(3, 1fr); gap: 0 2.5rem; }
  .value { border-bottom: 0; padding-bottom: 0; }

  .footer__inner {
    grid-template-columns: auto 1fr auto;
    align-items: center;
  }
  .footer__legal { justify-content: flex-end; }

  /* Nosotros: manifiesto a la izquierda, la glosa como nota al margen */
  .nosotros__inner { grid-template-columns: 1fr 15rem; }
}

/* --- Escritorio: navegación horizontal, sin hamburguesa --- */
@media (min-width: 980px) {
  .nav-toggle { display: none; }

  .nav {
    position: static;
    /* En móvil el panel ocupa la pantalla; aquí mide lo que su contenido */
    height: auto;
    visibility: visible;
    opacity: 1;
    transform: none;
    background: none;
    overflow: visible;
  }
  .nav__list {
    flex-direction: row;
    align-items: center;
    gap: 0.25rem;
    padding: 0;
  }
  .nav__item { border: 0; }
  .nav__link {
    position: relative;
    display: block;
    padding: 0.5rem 0.75rem;
    font-size: 0.9375rem;
    border-radius: var(--radius-xs);
  }
  /* Marca de sección activa: una barra corta bajo el enlace, no un punto */
  .nav__link.is-active::after {
    position: absolute;
    left: 0.75rem;
    right: 0.75rem;
    bottom: 0.2rem;
    width: auto;
    height: 2px;
    border-radius: 1px;
  }
  .nav__cta { margin: 0 0 0 0.75rem; }
  .nav__cta .btn { width: auto; }

  .cards { grid-template-columns: repeat(3, 1fr); }
  .grid-2 { grid-template-columns: 1fr 1fr; }
  .producto__inner { grid-template-columns: 1fr 1.1fr; }

  .hero__inner { grid-template-columns: 1.2fr 0.8fr; }
  .hero__visual { width: 100%; max-width: 28rem; }

  .nosotros__inner { grid-template-columns: 1fr 17rem; gap: 5rem; }
}

/* --- Pantallas bajas (celular en horizontal, móviles de 568px de alto) ---
   El aire del hero se calcula con el ancho; aquí manda el alto: sin esto, en un
   celular en horizontal el titular y los botones quedan bajo el pliegue. */
@media (max-height: 600px) {
  .hero { padding-block: calc(var(--header-h) + 1.5rem) 3rem; }
  .hero__eyebrow { margin-bottom: 1rem; }
  .hero__title { font-size: min(var(--fs-hero), 14vh); margin-bottom: 1rem; }
  .hero__lead { margin-bottom: 1.5rem; }
}
/* En horizontal sobra ancho y falta alto: texto a más ancho (una línea menos)
   y botones lado a lado, no apilados. */
@media (max-height: 600px) and (orientation: landscape) {
  .hero__lead { max-width: 62ch; }
  .hero__actions .btn { flex: 0 0 auto; }
}

/* --- Pantallas grandes: el contenido no se estira sin límite --- */
@media (min-width: 1440px) {
  :root { --container: 1280px; }
}

/* --- Impresión: sin fondos oscuros ni elementos interactivos --- */
@media print {
  .site-header, .hero__visual, .nav-toggle, .btn, .to-top { display: none !important; }
  body, .section--dark, .hero, .site-footer { background: #fff !important; color: #000 !important; }

  /* Los fondos pasan a blanco, así que la variante de asta blanca quedaría
     ilegible. No se puede invertir el logotipo: se oculta y queda el nombre. */
  .site-footer .brand__mark { display: none !important; }
}
