/* =========================================================
   Nexo Studio — Sistema de diseño
   Tokens + componentes + utilidades + responsive
   ========================================================= */

:root {
  /* ─────────────────────────────────────────────────────────
     LOS COLORES — UN SOLO TEMA
     ─────────────────────────────────────────────────────────
     Solo hay una paleta. Antes había tres (oscuro, claro y "colorido")
     con un conmutador en la barra: se quitó porque un sitio para
     comercios no necesita tres,~ y porque mantener tres paletas es
     mantener tres veces el mismo trabajo de contraste.

     ── POR QUÉ EL VERDE ESTÁ EN DOS TONOS ──

     `--brand` es #10b981, el verde de la marca: el del botón
     principal, donde el texto va en grande y en oscuro sobre verde.

     `--accent` es #059669, el mismo verde oscurecido. Es lo que va
     en iconos, bordes de tarjeta y tildes, y eso va SOBRE el fondo:
     #10b981 sobre casi blanco queda por debajo del contraste mínimo,
     y un icono que no se ve no es un icono. */
  --bg: #f8fafc;
  --bg-soft: #f1f5f9;
  --surface: #ffffff;
  --surface-2: #f8fafc;
  --border: rgba(15, 23, 42, 0.1);
  --border-strong: rgba(15, 23, 42, 0.2);
  --text: #0f172a;
  --text-muted: #475569;
  /* El gris mas apagado.
     Da 4,76:1 sobre blanco, que pasa, y 4,34:1 sobre los fondos
     con lavado, que no. Es el color de los enlaces legales, el
     copyright y los titulos de columna del pie: lo que menos se
     lee y mas importa leer. */
  --text-dim: #5b6879;

  /* El verde de marca. */
  --brand: #10b981;
  --brand-deep: #047857;

  /* Para texto e iconos que van sobre el fondo. */
  --accent: #059669;
  /* El ambar, UN TONO MAS OSCURO que el de la paleta (#F59E0B).

     El de la paleta es un color medio: sobre el fondo off-white da
     3,04:1 y no llega al minimo de WCAG para texto normal, que es
     4,5:1. Con thirty reglas usando este valor como color de texto
     (insignias, etiquetas, enlaces del pie, iconos), eso era el mismo
     problema en treinta sitios.

     #b45309 da 4,80:1 y sigue siendo el mismo ambar.

     Conviene notar que #d97706 era, ademas, IGUAL que `--warning`: el
     color de acento y el de "algo va mal" eran el mismo numero, y por
     eso todo lo que llevaba acento parecia una advertencia. */
  --accent-2: #b45309;
  /* El degradado del botón principal. SE QUEDA EN LA FAMILIA DEL
     VERDE a propósito: con el ámbar al final, el camino entre
     #10b981 y #d97706 pasa por oliva y el botón sale con una
     mancha marrón en el centro.

     El ámbar sigue en `--accent-2`, que es donde la paleta lo
     coloca: insignias, avisos y acentos sueltos. */
  --accent-grad: linear-gradient(120deg, #10b981 0%, #059669 100%);

  /* Texto sobre el verde del botón. Azul noche y no blanco: blanco
     sobre #10b981 se queda en 2,4:1 y no llega ni a texto grande. */
  --brand-ink: #0f172a;

  --success: #059669;
  --success-text: #065f46;
  --success-bg: rgba(5, 150, 105, 0.1);
  --success-border: rgba(5, 150, 105, 0.4);

  /* ── Aviso: ni bien ni mal ──
     El tercer estado. Rojo y verde no cubren "esto no esta roto,
     pero se va a romper": un modulo a la venta sin url detras, una
     migracion sin aplicar, un despliegue viejo. Sin el, todo lo que
     no este bien tiene que pintarse de rojo, y un panel donde todo
     es rojo deja de ensenar nada. */
  --warning: #d97706;
  --warning-text: #78350f;
  --warning-bg: rgba(217, 119, 6, 0.1);
  --warning-border: rgba(217, 119, 6, 0.4);
  --danger: #dc2626;

  /* ── Dos estados más que el panel necesitaba ──
   *
   * El panel usaba dos colores escritos a mano, sin token. Un literal
   * no cambia con el tema y rompía el contraste.
   *
   * `--info` NO puede ser verde: el panel pinta con él los chips de
   * salud de cada caja de Evolution, donde el verde significa
   * "funciona". Con los dos en la misma familia, un bot caído y uno
   * sano se parecen. */
  --info: #2563eb;
  --urgent: #ea580c;

  --on-accent: #0f172a;
  --icon-color: #047857;

  /* El degradado del titular. El ámbar entra al final para que la
     palabra destacada termine en el color de acento en vez de volver
     al verde, que es lo que lo haría parecer un degradado mal hecho.
     Los dos tonos van oscurecidos porque esto va sobre blanco. */
  /* El degradado del titular. También solo verde: sobre azul noche
     el salto al ámbar se nota más que en el botón. */
  --text-grad: linear-gradient(120deg, #047857 0%, #10b981 100%);

  --header-bg: rgba(255, 255, 255, 0.85);
  --header-bg-solid: rgba(255, 255, 255, 0.97);
  --menu-bg: #ffffff;

  /* Degradados de fondo. Muy bajos a propósito: esto va detrás de
     texto y un verde fuerte detrás de un titular lo vuelve ilegible. */
  /* Verde, y solo verde. Con ámbar al lado derecho el hero se iba a
     naranja y el conjunto daba atardecer en vez de frescura. */
  --hero-glow: radial-gradient(
    ellipse at center,
    rgba(16, 185, 129, 0.2) 0%,
    rgba(14, 165, 233, 0.07) 45%,
    transparent 70%
  );
  --page-glow: radial-gradient(ellipse at center, rgba(16, 185, 129, 0.14), transparent 70%);
  --grid-line: rgba(15, 23, 42, 0.04);
  --stats-bg: rgba(255, 255, 255, 0.9);
  --raise: rgba(15, 23, 42, 0.03);
  --raise-strong: rgba(15, 23, 42, 0.06);
  --btn-glow: 0 10px 26px rgba(5, 150, 105, 0.22);
  --btn-glow-strong: 0 14px 34px rgba(5, 150, 105, 0.34);
  --featured-bg: linear-gradient(180deg, rgba(16, 185, 129, 0.12), rgba(255, 255, 255, 0.95));
  --featured-glow: 0 24px 50px rgba(5, 150, 105, 0.16);
  --cta-bg: linear-gradient(120deg, rgba(16, 185, 129, 0.14), rgba(14, 165, 233, 0.08));
  --cta-border: rgba(16, 185, 129, 0.35);
  --thumb-overlay: linear-gradient(180deg, transparent 40%, rgba(15, 23, 42, 0.55) 100%);

  /* Tipografía */
  --font-display: "Outfit", "Plus Jakarta Sans", "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-body: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;

  /* ── La monoespaciada ──
     El sistema no tenía ninguna, y eso se notaba justo donde más
     importa: en las cifras.

     Sin ella, una columna de importes usa la fuente de texto, donde
     los números no ocupan el mismo ancho. "1.500" y "250" miden
     distinto, así que las cifras quedan descentradas y comparar dos
     precios de un vistazo es trabajo de cabeza.

     Con monoespaciada los dígitos ocupan lo mismo, la columna se
     alinea sola y el ojo baja por ella sin leer. Además es la señal
     de "esto es un dato técnico" que distingue un panel de
     herramienta de una web de marketing, que es lo que se buscaba.

     JetBrains Mono y no la del sistema porque en Windows la
     monoespaciada por defecto (Consolas) es más ancha y menos
     cuidada. Con la del sistema, el diseño depende de una fuente que
     cambia según el ordenador, que es la forma más fácil de que un
     panel se vea distinto en cada casa. La de reserva va igual, para
     el caso de que el CDN no cargue. */
  --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --fs-hero: clamp(2.4rem, 6vw, 4.2rem);
  --fs-h1: clamp(2rem, 4.5vw, 3rem);
  --fs-h2: clamp(1.6rem, 3.4vw, 2.35rem);
  --fs-h3: clamp(1.15rem, 2vw, 1.4rem);
  --fs-body: 1rem;
  --fs-sm: 0.9rem;
  --fs-xs: 0.8rem;

  /* Espaciado y layout */
  --radius: 16px;
  --radius-sm: 10px;
  --radius-lg: 26px;
  --container: 1160px;
  --gap: clamp(1rem, 2vw, 1.5rem);
  --section-y: clamp(4rem, 9vw, 7rem);

  --shadow: 0 20px 50px rgba(0, 0, 0, 0.45);

  /* La sombra de tarjeta. --shadow es la profunda, para el menu y
     la paleta, donde el elemento esta despegado. Esta es la suave,
     pegada al lienzo, que en tema oscuro se apoya mas en el borde
     que en la sombra: por eso el radio es pequeño. */
  --shadow-soft: 0 10px 30px -12px rgba(0, 0, 0, 0.35);
  /* Alto suficiente para que la marca, la nav, el conmutador y el CTA
     respiren sin quedar apretados */
  --header-h: 78px;
  /* Alto al hacer scroll (--header-h menos el margen de seguridad) */
  --header-h-compact: 64px;
}

/* ---------- Reset ---------- */
*,
*::before,
*::after {
  box-sizing: border-box;
}

* {
  margin: 0;
}

html {
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + 16px);
}

body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

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

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

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

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

h1,
h2,
h3,
h4 {
  font-family: var(--font-display);
  line-height: 1.15;
  font-weight: 700;
  letter-spacing: -0.02em;
}

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

::selection {
  background: color-mix(in srgb, var(--accent) 40%, transparent);
}

/* ---------- Layout ---------- */
.container {
  width: min(100% - 2.5rem, var(--container));
  margin-inline: auto;
}

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

.section--soft {
  background: var(--bg-soft);
  border-block: 1px solid var(--border);
}

.section-head {
  max-width: 660px;
  margin-bottom: clamp(2rem, 5vw, 3.2rem);
}

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

.section-head h2 {
  font-size: var(--fs-h2);
  margin-bottom: 0.75rem;
}

.section-head p {
  color: var(--text-muted);
  font-size: 1.05rem;
}

/* El verde profundo de la marca, no el ambar.

   El texto va en `--brand-deep` (#047857, 5,24:1 sobre el fondo) y no
   en `--accent` (#059669, 3,60:1) ni en el ambar (#d97706, 3,04:1):
   los tres son el mismo color de marca y solo uno llega al minimo de
   WCAG AA para texto normal.

   El fondo y el borde leen del MISMO color por una razón práctica: si
   solo cambiara el texto, la etiqueta saldria con letras verdes sobre
   un lavado naranja. */
.eyebrow {
  display: inline-block;
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  /* El verde de la etiqueta va sobre su propio lavado, y el lavado
     baja el fondo un poco: con #047857 daba 4,19:1. Este es el
     mismo verde un paso mas oscuro y llega a 6,9. */
  color: #036249;
  background: color-mix(in srgb, #036249 8%, transparent);
  border: 1px solid color-mix(in srgb, #036249 24%, transparent);
  border-radius: 999px;
  padding: 0.35rem 0.85rem;
  margin-bottom: 1rem;
}

.gradient-text {
  background: var(--text-grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* ---------- Botones ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.85rem 1.6rem;
  border-radius: 999px;
  border: 1px solid transparent;
  font-weight: 600;
  font-size: var(--fs-sm);
  cursor: pointer;
  transition: transform 0.2s ease, box-shadow 0.2s ease, background 0.2s ease,
    border-color 0.2s ease, color 0.2s ease;
  white-space: nowrap;
}

.btn:hover {
  transform: translateY(-2px);
}

.btn-primary {
  background: var(--accent-grad);
  color: var(--on-accent);
  box-shadow: var(--btn-glow);
}

.btn-primary:hover {
  box-shadow: var(--btn-glow-strong);
}

.btn-ghost {
  background: var(--raise);
  border-color: var(--border-strong);
  color: var(--text);
}

.btn-ghost:hover {
  background: var(--raise-strong);
  border-color: var(--accent);
}

.btn-lg {
  padding: 1rem 2rem;
  font-size: 1rem;
}

/* Variante compacta: para la cabecera, donde el alto está muy limitado */
.btn-sm {
  padding: 0.55rem 1.05rem;
  font-size: var(--fs-xs);
  gap: 0.4rem;
}

.btn-block {
  width: 100%;
}

/* ---------- Header ---------- */
.site-header {
  position: fixed;
  inset: 0 0 auto 0;
  height: var(--header-h);
  z-index: 100;
  background: var(--header-bg);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid transparent;
  /* La altura también se transiciona: el header se encoge al bajar
     y vuelve a su tamaño al subir. Antes el encogido se hacía con
     padding-block dentro de una altura fija, lo que además de
     desbordar no devolvía el header a su medida original. */
  transition: border-color 0.25s ease, background 0.25s ease, height 0.28s ease,
    box-shadow 0.28s ease;
}

/* Encogido: se aplica y se retira con la clase .is-compact, que
   main.js gestiona de forma simétrica al bajar y al subir. */
.site-header.is-compact {
  height: var(--header-h-compact);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.22);
}

.site-header.is-compact {
  box-shadow: 0 10px 24px rgba(18, 20, 44, 0.08);
}

.site-header.is-scrolled {
  border-bottom-color: var(--border);
  background: var(--header-bg-solid);
}

.header-inner {
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.brand {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.15rem;
  letter-spacing: -0.02em;
}

.brand svg {
  width: 34px;
  height: 34px;
}

.nav {
  display: flex;
  align-items: center;
  gap: 0.35rem;
}

.nav a {
  padding: 0.5rem 0.8rem;
  border-radius: 999px;
  font-size: var(--fs-sm);
  color: var(--text-muted);
  transition: color 0.2s ease, background 0.2s ease;
  white-space: nowrap;
}

.nav a:hover {
  color: var(--text);
  background: var(--raise-strong);
}

.nav a.active {
  color: var(--text);
  background: color-mix(in srgb, var(--accent) 16%, transparent);
}

.nav a.mobile-cta {
  display: none;
}

.header-cta {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

/* Conmutador de temas */














.nav-toggle {
  display: none;
  width: 44px;
  height: 44px;
  border-radius: 12px;
  background: var(--raise);
  border: 1px solid var(--border);
  cursor: pointer;
  position: relative;
}

.nav-toggle span,
.nav-toggle span::before,
.nav-toggle span::after {
  content: "";
  position: absolute;
  left: 50%;
  width: 18px;
  height: 2px;
  background: var(--text);
  border-radius: 2px;
  transform: translateX(-50%);
  transition: transform 0.25s ease, opacity 0.2s ease;
}

.nav-toggle span {
  top: 50%;
  margin-top: -1px;
}

.nav-toggle span::before {
  top: -6px;
}

.nav-toggle span::after {
  top: 6px;
}

.nav-toggle[aria-expanded="true"] span {
  background: transparent;
}

.nav-toggle[aria-expanded="true"] span::before {
  transform: translateX(-50%) translateY(6px) rotate(45deg);
}

.nav-toggle[aria-expanded="true"] span::after {
  transform: translateX(-50%) translateY(-6px) rotate(-45deg);
}

/* ---------- Hero ---------- */
.hero {
  padding-top: calc(var(--header-h) + clamp(3rem, 8vw, 6rem));
  padding-bottom: clamp(3rem, 7vw, 5.5rem);
  position: relative;
  overflow: hidden;
}

/* El hero usa ahora .hero-bg (aurora + rejilla), no el halo antiguo */
.hero::before {
  display: none;
}

.hero-grid {
  position: absolute;
  inset: 0;
  background-image: linear-gradient(var(--grid-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
  background-size: 56px 56px;
  mask-image: radial-gradient(ellipse at 50% 30%, #000 20%, transparent 75%);
  pointer-events: none;
}

.hero-inner {
  position: relative;
  max-width: 820px;
  text-align: center;
  margin-inline: auto;
}

.hero h1 {
  font-size: var(--fs-hero);
  margin-bottom: 1.25rem;
}

.hero p.lead {
  font-size: clamp(1.02rem, 2vw, 1.2rem);
  color: var(--text-muted);
  max-width: 640px;
  margin: 0 auto 2rem;
}

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.9rem;
  justify-content: center;
  margin-bottom: 3rem;
}

.hero-note {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: var(--fs-xs);
  color: var(--text-dim);
  margin-top: -1.6rem;
  margin-bottom: 3rem;
}

.hero-note .dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--success);
  box-shadow: 0 0 10px var(--success);
}

/* Stats */
.stats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--gap);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: clamp(1.25rem, 3vw, 2rem);
  backdrop-filter: blur(8px);
  background: var(--stats-bg);
}

.stat {
  text-align: center;
  padding-inline: 0.5rem;
}

.stat strong {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(1.7rem, 3.5vw, 2.4rem);
  background: var(--text-grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.stat span {
  font-size: var(--fs-xs);
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

/* ---------- Logos / marcas ---------- */
.logos {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: clamp(1.5rem, 5vw, 3.5rem);
  align-items: center;
}

.logos li {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.05rem;
  color: var(--text-dim);
  letter-spacing: 0.02em;
  transition: color 0.2s ease;
}

.logos li:hover {
  color: var(--text-muted);
}

/* ---------- Cards ---------- */
.grid {
  display: grid;
  gap: var(--gap);
}

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

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

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: clamp(1.4rem, 3vw, 1.9rem);
  transition: transform 0.25s ease, border-color 0.25s ease, background 0.25s ease;
  position: relative;
  overflow: hidden;
}

.card:hover {
  transform: translateY(-5px);
  border-color: color-mix(in srgb, var(--accent) 50%, transparent);
  background: var(--surface-2);
}

.card h3 {
  font-size: var(--fs-h3);
  margin-bottom: 0.6rem;
}

.card p {
  color: var(--text-muted);
  font-size: var(--fs-sm);
}

.card .icon {
  width: 48px;
  height: 48px;
  border-radius: 14px;
  display: grid;
  place-items: center;
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
  margin-bottom: 1.1rem;
  color: var(--icon-color);
}

.card .icon svg {
  width: 24px;
  height: 24px;
}

.card-list {
  margin-top: 1rem;
  display: grid;
  gap: 0.5rem;
}

.card-list li {
  font-size: var(--fs-sm);
  color: var(--text-muted);
  display: flex;
  gap: 0.6rem;
  align-items: flex-start;
}

.card-list li::before {
  content: "✓";
  color: var(--success);
  font-weight: 700;
  flex-shrink: 0;
}

/* ---------- Proyectos ---------- */
.project-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  transition: transform 0.25s ease, border-color 0.25s ease;
  display: flex;
  flex-direction: column;
}

.project-card:hover {
  transform: translateY(-5px);
  border-color: color-mix(in srgb, var(--accent-2) 45%, transparent);
}

.project-thumb {
  aspect-ratio: 16 / 10;
  position: relative;
  display: grid;
  place-items: center;
  overflow: hidden;
}

.project-thumb .thumb-art {
  font-family: var(--font-display);
  font-size: clamp(2rem, 5vw, 3rem);
  font-weight: 700;
  color: rgba(255, 255, 255, 0.9);
  letter-spacing: -0.03em;
  text-shadow: 0 6px 30px rgba(0, 0, 0, 0.35);
}

.project-thumb::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--thumb-overlay);
}

.thumb-1 { background: linear-gradient(135deg, #047857, #0ea5e9 55%, #0b7285); }
.thumb-2 { background: linear-gradient(135deg, #059669, #34d399 50%, #84cc16); }
.thumb-3 { background: linear-gradient(135deg, #0f766e, #0e7490 55%, #1d4ed8); }
.thumb-4 { background: linear-gradient(135deg, #d97706, #f59e0b 55%, #fbbf24); }
.thumb-5 { background: linear-gradient(135deg, #065f46, #047857 50%, #0f172a); }
.thumb-6 { background: linear-gradient(135deg, #0e7490, #14b8a6 50%, #4d7c0f); }

.project-body {
  padding: 1.4rem 1.5rem 1.6rem;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  flex: 1;
}

.project-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}

.tag {
  font-size: var(--fs-xs);
  padding: 0.2rem 0.65rem;
  border-radius: 999px;
  background: var(--raise);
  border: 1px solid var(--border);
  color: var(--text-muted);
}

.project-body h3 {
  font-size: 1.15rem;
}

.project-body p {
  color: var(--text-muted);
  font-size: var(--fs-sm);
  flex: 1;
}

.project-result {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--accent-2);
  border-top: 1px dashed var(--border);
  padding-top: 0.85rem;
}

/* Filtros */
.filters {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-bottom: 2rem;
}

.filter-btn {
  padding: 0.55rem 1.2rem;
  border-radius: 999px;
  background: var(--raise);
  border: 1px solid var(--border);
  color: var(--text-muted);
  font-size: var(--fs-sm);
  cursor: pointer;
  transition: all 0.2s ease;
}

.filter-btn:hover {
  border-color: var(--accent);
  color: var(--text);
}

.filter-btn.is-active {
  background: var(--accent-grad);
  color: var(--on-accent);
  border-color: transparent;
  font-weight: 600;
}

.project-card.is-hidden {
  display: none;
}

/* ---------- Proceso ---------- */
.steps {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--gap);
  counter-reset: step;
}

.step {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: clamp(1.4rem, 3vw, 1.8rem);
  position: relative;
  counter-increment: step;
}

.step::before {
  content: counter(step, decimal-leading-zero);
  font-family: var(--font-display);
  font-size: 2.4rem;
  font-weight: 700;
  background: var(--text-grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  display: block;
  margin-bottom: 0.75rem;
  opacity: 0.85;
}

.step h3 {
  font-size: 1.1rem;
  margin-bottom: 0.5rem;
}

.step p {
  color: var(--text-muted);
  font-size: var(--fs-sm);
}

/* ---------- Precios ---------- */
.price-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--gap);
  align-items: stretch;
}

.price-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: clamp(1.6rem, 3vw, 2.2rem);
  display: flex;
  flex-direction: column;
  transition: transform 0.25s ease, border-color 0.25s ease;
  position: relative;
}

.price-card:hover {
  transform: translateY(-5px);
  border-color: color-mix(in srgb, var(--accent) 55%, transparent);
}

.price-card.featured {
  background: var(--featured-bg);
  border-color: color-mix(in srgb, var(--accent) 55%, transparent);
  box-shadow: var(--featured-glow);
}

.badge {
  position: absolute;
  top: -13px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--accent-grad);
  color: var(--on-accent);
  font-size: var(--fs-xs);
  font-weight: 700;
  padding: 0.3rem 0.9rem;
  border-radius: 999px;
  white-space: nowrap;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.price-card h3 {
  font-size: 1.2rem;
  margin-bottom: 0.35rem;
}

.price-card .plan-desc {
  color: var(--text-muted);
  font-size: var(--fs-sm);
  margin-bottom: 1.4rem;
  min-height: 48px;
}

.price {
  display: flex;
  align-items: baseline;
  gap: 0.4rem;
  margin-bottom: 0.35rem;
}

.price .amount {
  font-family: var(--font-display);
  font-size: clamp(2.2rem, 4vw, 2.9rem);
  font-weight: 700;
  letter-spacing: -0.03em;
}

.price .currency {
  font-size: 1.3rem;
  font-weight: 600;
  color: var(--text-muted);
}

.price-note {
  font-size: var(--fs-xs);
  color: var(--text-dim);
  margin-bottom: 1.5rem;
}

.price-features {
  display: grid;
  gap: 0.65rem;
  margin-bottom: 1.8rem;
  flex: 1;
}

.price-features li {
  display: flex;
  gap: 0.6rem;
  font-size: var(--fs-sm);
  color: var(--text-muted);
  align-items: flex-start;
}

.price-features li::before {
  content: "✓";
  color: var(--success);
  font-weight: 700;
  flex-shrink: 0;
}

.price-features li.muted {
  opacity: 0.45;
}

.price-features li.muted::before {
  content: "—";
  color: var(--text-dim);
}

/* Tabla comparativa */
.compare-wrap {
  overflow-x: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
}

table.compare {
  width: 100%;
  border-collapse: collapse;
  min-width: 640px;
  font-size: var(--fs-sm);
}

table.compare th,
table.compare td {
  padding: 0.95rem 1.2rem;
  text-align: left;
  border-bottom: 1px solid var(--border);
}

table.compare thead th {
  font-family: var(--font-display);
  font-size: 1rem;
  background: var(--surface-2);
}

table.compare tbody tr:last-child td {
  border-bottom: none;
}

table.compare td:not(:first-child),
table.compare th:not(:first-child) {
  text-align: center;
}

table.compare .yes {
  color: var(--success);
  font-weight: 700;
}

table.compare .no {
  color: var(--text-dim);
}

/* ---------- FAQ / acordeón ---------- */
.accordion {
  display: grid;
  gap: 0.8rem;
  max-width: 780px;
  margin-inline: auto;
}

.acc-item {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
}

.acc-trigger {
  width: 100%;
  background: none;
  border: none;
  padding: 1.1rem 1.3rem;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  text-align: left;
  cursor: pointer;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1rem;
  color: var(--text);
}

.acc-trigger .acc-icon {
  flex-shrink: 0;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: color-mix(in srgb, var(--accent) 18%, transparent);
  color: var(--icon-color);
  font-size: 1.1rem;
  line-height: 1;
  transition: transform 0.25s ease;
}

.acc-item.is-open .acc-icon {
  transform: rotate(45deg);
}

.acc-panel {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.3s ease;
}

.acc-panel p {
  padding: 0 1.3rem 1.2rem;
  color: var(--text-muted);
  font-size: var(--fs-sm);
}

/* ---------- Testimonios ---------- */
.quote {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: clamp(1.4rem, 3vw, 1.9rem);
  display: flex;
  flex-direction: column;
  gap: 1.1rem;
}

.quote blockquote {
  font-size: 1.02rem;
  color: var(--text);
  line-height: 1.7;
}

.quote blockquote::before {
  content: "“";
  display: block;
  font-family: var(--font-display);
  font-size: 3rem;
  line-height: 1;
  background: var(--text-grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  margin-bottom: 0.4rem;
}

.quote-person {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  margin-top: auto;
}

.avatar {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.95rem;
  color: #08080f;
  flex-shrink: 0;
}

.avatar-1 { background: linear-gradient(135deg, #059669, #0ea5e9); }
.avatar-2 { background: linear-gradient(135deg, #d97706, #fbbf24); }
  .avatar-3 { background: linear-gradient(135deg, #10b981, #34d399); }

.quote-person strong {
  display: block;
  font-size: var(--fs-sm);
}

.quote-person span {
  font-size: var(--fs-xs);
  color: var(--text-dim);
}

/* ---------- CTA final ---------- */
.cta-band {
  position: relative;
  background: var(--cta-bg);
  border: 1px solid var(--cta-border);
  border-radius: var(--radius-lg);
  padding: clamp(2.2rem, 6vw, 4rem);
  text-align: center;
  overflow: hidden;
}

.cta-band h2 {
  font-size: var(--fs-h2);
  margin-bottom: 0.8rem;
}

.cta-band p {
  color: var(--text-muted);
  max-width: 560px;
  margin: 0 auto 1.8rem;
}

.cta-actions {
  display: flex;
  gap: 0.9rem;
  justify-content: center;
  flex-wrap: wrap;
}

/* ---------- Page hero (páginas internas) ---------- */
.page-hero {
  padding-top: calc(var(--header-h) + clamp(2.5rem, 6vw, 4.5rem));
  padding-bottom: clamp(2rem, 5vw, 3.5rem);
  position: relative;
  overflow: hidden;
}

.page-hero::before {
  content: "";
  position: absolute;
  top: -200px;
  left: 20%;
  width: 700px;
  height: 460px;
  background: var(--page-glow);
  pointer-events: none;
}

.page-hero .container {
  position: relative;
  max-width: 780px;
}

.page-hero h1 {
  font-size: var(--fs-h1);
  margin-bottom: 0.9rem;
}

.page-hero p {
  color: var(--text-muted);
  font-size: 1.08rem;
}

.breadcrumb {
  display: flex;
  gap: 0.5rem;
  font-size: var(--fs-xs);
  color: var(--text-dim);
  margin-bottom: 1.1rem;
}

.breadcrumb a:hover {
  color: var(--accent-2);
}

/* ---------- Detalle de servicios ---------- */
.service-block {
  position: relative;
  isolation: isolate;
  overflow: hidden;

  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(1.5rem, 4vw, 3.5rem);
  align-items: start;
  padding: clamp(1.6rem, 4vw, 2.6rem);
  margin-bottom: var(--sp-5, 1.5rem);

  /* Tarjeta, no separacion. Antes solo llevaba un borde abajo, que
     hacia de cada bloque un parrafo con un rayon debajo. Con borde
     completo, sombra y radio, cada bloque es una pieza y la pagina
     se lee como una lista de seis cosas, no como un texto largo
     con titulos. */
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg, 16px);
  box-shadow: var(--shadow-soft, 0 10px 30px -12px rgba(0, 0, 0, 0.35));
}

.service-block:last-child {
  margin-bottom: 0;
}

/* ── El lavado de color ──

   Un radial desde la esquina de arriba a la izquierda, en el color
   del bloque, al 14%. Es deliberadamente tan bajo que no se lee
   como "este bloque es violeta": se lee como que la luz cae mas
   fuerte por ahi. Subirlo a 25% lo convierte en una mancha y hay
   que subirlo mas para igualar el degradado entero, que es donde
   el texto deja de leerse bien.

   Va en un pseudoelemento con z-index -1 y el padre con isolation,
   para que quede DETRAS del texto y no encima, y para que no se
   salga por el radio: overflow hidden lo recorta. */
.service-block::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: radial-gradient(
    130% 110% at 0% 0%,
    color-mix(in srgb, var(--tinte) 14%, transparent) 0%,
    transparent 58%
  );
}

/* ── El numero del bloque ──

   Arriba a la izquierda, al lado de la etiqueta, y en el color
   del bloque. No va detras de nada: es la cifra del bloque, leida
   de izquierda a derecha junto al titulo.

   Estuvo primero como marca de agua gigante en la esquina de la
   derecha y no funcionaba, porque ahi vive la caja de que incluye
   y el numero quedaba partido por su borde. Un elemento que se ve
   cortado no se lee como decoracion: se lee como roto.

   El tamano es 2.1rem y no mas, porque es un indice y no un
   titular: tiene que resaltar el bloque sin competir con el h2,
   que va a 1.8rem. Y con tabular-nums, porque si no el 01 y el 02
   ocupan anchuras distintas y la columna de titulos baila al
   bajar por la pagina. */
.service-cab {
  display: flex;
  align-items: baseline;
  gap: 0.7rem;
  margin-bottom: 0.9rem;
}

.service-num {
  font-family: var(--font-display);
  font-size: 2.1rem;
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.04em;
  font-variant-numeric: tabular-nums;
  color: color-mix(in srgb, var(--tinte) 82%, var(--text));
}

/* La etiqueta se queda en apagada: al lado de una cifra de color,
   si la etiqueta tambien va en color hay dos cosas compitiendo y
   la etiqueta, que es la que dice de que va el bloque, pierde. */
.service-cab .eyebrow {
  font-size: var(--fs-xs);
  letter-spacing: 0.12em;
  color: var(--text-dim);
}

/* El tinte de cada uno. Los seis primeros colores de .thumb-1 a
   .thumb-6, que son los degradados que ya usa /proyectos. */
.servicio-1 { --tinte: #047857; }
.servicio-2 { --tinte: #0e7490; }
.servicio-3 { --tinte: #0f766e; }
.servicio-4 { --tinte: #d97706; }
.servicio-5 { --tinte: #0f172a; }
.servicio-6 { --tinte: #0d9488; }

/* ── Lo que va DENTRO ──

   El cintillo pasa a ser el numero grande del bloque, en vez de
   repetir "01 · Web" en un tamano pequeno arriba. Se queda el
   texto y se le quita la cifra, porque la cifra ya esta gigante en
   la esquina y repetirla es ruido. */
.service-block .eyebrow {
  font-size: var(--fs-xs);
  letter-spacing: 0.12em;
  color: color-mix(in srgb, var(--tinte) 75%, var(--text-muted));
}

/* La caja de "que incluye" deja de estar pegada al borde del bloque
   y coge relieve: es el contenido util y tiene que leerse antes que
   el parrafo de al lado. */
.service-block .deliverables {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: clamp(1.2rem, 2.6vw, 1.7rem);
  box-shadow: var(--shadow-soft, 0 10px 30px -12px rgba(0, 0, 0, 0.35));
}

.service-block h2 {
  font-size: var(--fs-h3);
  font-size: clamp(1.4rem, 2.6vw, 1.8rem);
  margin-bottom: 0.8rem;
}

.service-block p {
  color: var(--text-muted);
}

.service-meta {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1rem;
  margin-top: 1.4rem;
}

.meta-box {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 1rem 1.1rem;
}

.meta-box span {
  display: block;
  font-size: var(--fs-xs);
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  margin-bottom: 0.25rem;
}

.meta-box strong {
  font-family: var(--font-display);
  font-size: 1.05rem;
}

.deliverables {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: clamp(1.3rem, 3vw, 1.8rem);
}

.deliverables h3 {
  font-size: 1.05rem;
  margin-bottom: 1rem;
}

/* ---------- Formulario ---------- */
.contact-layout {
  display: grid;
  grid-template-columns: 1.15fr 0.85fr;
  gap: clamp(1.5rem, 4vw, 3rem);
  align-items: start;
}

.form-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: clamp(1.6rem, 4vw, 2.4rem);
}

.form-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1.1rem;
}

.field {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.field.full {
  grid-column: 1 / -1;
}

.field label {
  font-size: var(--fs-sm);
  font-weight: 600;
}

.field label .req {
  color: var(--accent-2);
}

.field input,
.field select,
.field textarea {
  background: var(--bg-soft);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  padding: 0.8rem 1rem;
  font-size: var(--fs-sm);
  transition: border-color 0.2s ease, background 0.2s ease;
  width: 100%;
}

.field textarea {
  resize: vertical;
  min-height: 130px;
}

.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 7%, transparent);
}

.field .error-msg {
  font-size: var(--fs-xs);
  color: var(--danger);
  min-height: 1em;
}

.field.has-error input,
.field.has-error select,
.field.has-error textarea {
  border-color: var(--danger);
}

.form-note {
  font-size: var(--fs-xs);
  color: var(--text-dim);
  margin-top: 0.9rem;
}

.form-success {
  display: none;
  background: var(--success-bg);
  border: 1px solid var(--success-border);
  color: var(--success-text);
  border-radius: var(--radius-sm);
  padding: 1rem 1.2rem;
  font-size: var(--fs-sm);
  margin-bottom: 1.2rem;
}

.form-success.is-visible {
  display: block;
}

.contact-info {
  display: grid;
  gap: 1rem;
}

.info-item {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.3rem 1.4rem;
  display: flex;
  gap: 1rem;
  align-items: flex-start;
}

.info-item .icon {
  width: 42px;
  height: 42px;
  flex-shrink: 0;
  border-radius: 12px;
  background: color-mix(in srgb, var(--accent-2) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent-2) 30%, transparent);
  display: grid;
  place-items: center;
  color: var(--accent-2);
}

.info-item .icon svg {
  width: 20px;
  height: 20px;
}

.info-item strong {
  display: block;
  font-size: var(--fs-sm);
  margin-bottom: 0.15rem;
}

.info-item span,
.info-item a {
  font-size: var(--fs-sm);
  color: var(--text-muted);
}

.info-item a:hover {
  color: var(--accent-2);
}

/* ---------- Footer ---------- */
.site-footer {
  background: var(--bg-soft);
  border-top: 1px solid var(--border);
  padding-top: clamp(3rem, 6vw, 4.5rem);
  margin-top: 0;
}

.footer-grid {
  display: grid;
  grid-template-columns: 1.6fr 1fr 1fr 1fr;
  gap: clamp(1.5rem, 4vw, 3rem);
  padding-bottom: clamp(2.5rem, 5vw, 3.5rem);
}

.footer-brand p {
  color: var(--text-muted);
  font-size: var(--fs-sm);
  margin-top: 0.9rem;
  max-width: 320px;
}

.footer-col h4 {
  font-size: var(--fs-sm);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-dim);
  margin-bottom: 1rem;
  font-weight: 600;
}

.footer-col ul {
  display: grid;
  gap: 0.6rem;
}

.footer-col a {
  font-size: var(--fs-sm);
  color: var(--text-muted);
  transition: color 0.2s ease;
}

.footer-col a:hover {
  color: var(--accent-2);
}

.footer-bottom {
  border-top: 1px solid var(--border);
  padding-block: 1.4rem;
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.8rem;
  font-size: var(--fs-xs);
  color: var(--text-dim);
}

/* Acceso al panel.
   Vive en el pie y no en la navegación principal a propósito:
   no es un argumento de venta, ocupa sitio donde el visitante
   decide si nos contrata, y la cabecera ya va justa de espacio.

   Ocultarlo no es seguridad: /panel/login es adivinable igual.
   Lo que protege de verdad es la sesión + las políticas RLS. */
.footer-login {
  color: var(--accent-2);
  font-weight: 600;
  text-decoration: none;
}

.footer-login:hover {
  text-decoration: underline;
  text-underline-offset: 3px;
}

.socials {
  display: flex;
  gap: 0.6rem;
  margin-top: 1.2rem;
}

.socials a {
  width: 38px;
  height: 38px;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--raise);
  display: grid;
  place-items: center;
  color: var(--text-muted);
  transition: all 0.2s ease;
}

.socials a:hover {
  border-color: var(--accent);
  color: var(--text);
  transform: translateY(-2px);
}

.socials svg {
  width: 18px;
  height: 18px;
}

/* ---------- Reveal animation ---------- */
/* ─────────────────────────────────────────────────────────
   LA ANIMACIÓN DE ENTRADA, Y POR QUÉ DEPENDE DE QUE HAYA JS

   El estado inicial (invisible, desplazado 24 px) está detrás de
   `.js`, que el <head> añade con una línea de script.

   Sin esa condición, todo bloque con `.reveal` empieza en
   `opacity: 0` y solo se ve cuando JavaScript le añade
   `.is-visible`. Medido en el navegador: con JS aparecen los 7
   bloques de la portada al hacer scroll; SIN JS, los 7 se quedan
   invisibles.

   Eso no es una animación que no se anima: es la página entera menos
   el hero en blanco para quien tenga JavaScript desactivado. Y en la
   portada ese texto es el producto —el problema, la solución y los
   tres planes—, no un adorno.

   `.reveal.is-visible` va después a propósito. `.js .reveal` y
   `.reveal.is-visible` valen lo mismo (dos clases), así que gana la
   que viene después: con las dos clases presentes, gana la que
   muestra. Si se invirtieran, añadir `js` dejaría la página
   invisible para siempre.
   ───────────────────────────────────────────────────────── */
.js .reveal {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 0.6s ease, transform 0.6s ease;
}

.reveal.is-visible {
  opacity: 1;
  transform: none;
}

/* ---------- Responsive ---------- */
@media (max-width: 960px) {
  .grid-3,
  .price-grid,
  .steps {
    grid-template-columns: repeat(2, 1fr);
  }

  .footer-grid {
    grid-template-columns: repeat(2, 1fr);
  }

  .contact-layout,
  .service-block {
    grid-template-columns: 1fr;
  }

  .stats {
    grid-template-columns: repeat(2, 1fr);
    gap: 1.5rem;
  }
}

@media (max-width: 760px) {
  .sticky-cta {
    display: flex;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 95;
    gap: 0.6rem;
    padding: 0.7rem 1rem calc(0.7rem + env(safe-area-inset-bottom));
    background: var(--header-bg-solid);
    backdrop-filter: blur(14px);
    border-top: 1px solid var(--border);
  }

  .sticky-cta .btn {
    flex: 1;
    padding-block: 0.8rem;
  }

  body {
    padding-bottom: 74px;
  }

  .project-thumb::before {
    display: none;
  }

  .nav-toggle {
    display: block;
  }

  .header-cta .btn {
    display: none;
  }

  .nav {
    position: fixed;
    top: var(--header-h);
    left: 0;
    right: 0;
    background: var(--menu-bg);
    backdrop-filter: blur(16px);
    border-bottom: 1px solid var(--border);
    flex-direction: column;
    align-items: stretch;
    padding: 1rem 1.25rem 1.5rem;
    gap: 0.25rem;
    transform: translateY(-140%);
    transition: transform 0.3s ease;
    max-height: calc(100vh - var(--header-h));
    overflow-y: auto;
  }

  .nav.is-open {
    transform: translateY(0);
  }

  .nav a {
    padding: 0.85rem 1rem;
    font-size: 1rem;
    border-radius: var(--radius-sm);
  }

  .nav a.mobile-cta {
    display: block;
    margin-top: 0.75rem;
    text-align: center;
    background: var(--accent-grad);
    color: var(--on-accent) !important;
    font-weight: 600;
  }

  /* Acceso y alta, dentro del desplegable.

     En escritorio viven en la barra, arriba a la derecha. En móvil la
     barra se queda con el tema y el botón de presupuesto, así que
     si no se meten aquí no aparecen en ninguna parte: la única forma
     de llegar a la cuenta sería escribir la URL.

     "Acceder" va arriba del todo del menú, antes que las secciones.
     Quien vuelve a entrar a mirar una factura no está buscando
     "Servicios": está buscando su cuenta. Puesto abajo, con cinco
     secciones de websites por delante, cuesta más de lo que cuesta. */
  .nav a.mobile-only-nav {
    display: block;
  }

  .nav a.mobile-only-nav:first-of-type {
    order: -1;
    margin-bottom: 0.5rem;
    padding-bottom: 0.9rem;
    border-bottom: 1px solid var(--border);
    font-weight: 600;
  }

  /* En la barra de escritorio sobran estas dos: aquí ya están en el
     desplegable, y si no se ocultan se verían dos veces. */
  .header-acceso,
  .header-alta {
    display: none;
  }
}

@media (max-width: 640px) {
  .grid-3,
  .grid-2,
  .price-grid,
  .steps,
  .form-grid,
  .service-meta {
    grid-template-columns: 1fr;
  }

  .footer-grid {
    grid-template-columns: 1fr;
    gap: 2rem;
  }

  .hero-actions .btn {
    width: 100%;
  }

  .price-card.featured {
    order: -1;
  }
}

/* =========================================================
   Mejoras inspiradas en Clay, STRV y Netguru
   ========================================================= */

/* --- Entrada escalonada del hero (tipo Clay/STRV) --- */
@keyframes fadeUp {
  from {
    opacity: 0;
    transform: translateY(28px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* La entrada escalonada ahora la gestiona .hero-title por líneas (ver bloque Hero premium) */
.hero-inner > * {
  animation: none;
}

.hero-inner > *:nth-child(1) { animation-delay: 0.05s; }
.hero-inner > *:nth-child(2) { animation-delay: 0.15s; }
.hero-inner > *:nth-child(3) { animation-delay: 0.25s; }
.hero-inner > *:nth-child(4) { animation-delay: 0.35s; }
.hero-inner > *:nth-child(5) { animation-delay: 0.45s; }

/* --- Marquee de servicios (movimiento continuo tipo agencia) --- */
.marquee {
  overflow: hidden;
  border-block: 1px solid var(--border);
  padding-block: 1.05rem;
  background: var(--bg-soft);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
}

.marquee-track {
  display: flex;
  width: max-content;
  gap: 2.75rem;
  animation: marquee 34s linear infinite;
}

.marquee:hover .marquee-track {
  animation-play-state: paused;
}

.marquee-track span {
  font-family: var(--font-display);
  font-size: 1.02rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--text-dim);
  white-space: nowrap;
}

.marquee-track span::after {
  content: "◆";
  margin-left: 2.75rem;
  font-size: 0.6rem;
  color: var(--accent);
  vertical-align: middle;
}

@keyframes marquee {
  to {
    transform: translateX(-50%);
  }
}

/* --- Hover de proyectos: zoom + "Ver caso" (tipo Clay) --- */
.project-thumb .thumb-art {
  transition: transform 0.45s cubic-bezier(0.22, 0.61, 0.36, 1), opacity 0.35s ease;
}

.project-thumb::before {
  content: "Ver caso →";
  position: absolute;
  z-index: 2;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -35%);
  opacity: 0;
  padding: 0.6rem 1.3rem;
  border-radius: 999px;
  background: rgba(7, 7, 13, 0.86);
  border: 1px solid rgba(255, 255, 255, 0.28);
  color: #fff;
  font-family: var(--font-display);
  font-size: 0.85rem;
  font-weight: 600;
  white-space: nowrap;
  transition: opacity 0.3s ease, transform 0.35s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.project-card:hover .project-thumb::before {
  opacity: 1;
  transform: translate(-50%, -50%);
}

.project-card:hover .thumb-art {
  transform: scale(1.08);
  opacity: 0.35;
}

/* --- Fila de confianza bajo los CTA (tipo Netguru/STRV) --- */
.trust-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.6rem 1.6rem;
  margin-top: 1.6rem;
  font-size: var(--fs-sm);
  color: var(--text-muted);
}

.trust-row li {
  display: flex;
  align-items: center;
  gap: 0.45rem;
}

.trust-row li::before {
  content: "✓";
  color: var(--success);
  font-weight: 700;
}

/* --- Barra CTA fija en móvil (CTA persistente tipo Netguru) --- */
.sticky-cta {
  display: none;
}

/* --- Destacados de resultados junto al titular de proyectos --- */
.result-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-top: 1.3rem;
}

.result-pills li {
  font-size: var(--fs-xs);
  font-weight: 600;
  padding: 0.4rem 0.9rem;
  border-radius: 999px;
  background: color-mix(in srgb, var(--success) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--success) 35%, transparent);
  color: var(--success);
}

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

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }

  .reveal {
    opacity: 1;
    transform: none;
  }
}

@media (max-width: 760px) {
  .sticky-cta {
    display: flex;
  }
}

/* =========================================================
   RGPD · Blog · Contenido editorial
   ========================================================= */

/* --- Casilla de consentimiento --- */
.field input[type="checkbox"] {
  width: 18px;
  height: 18px;
  padding: 0;
  border: none;
  background: transparent;
  accent-color: var(--accent);
  cursor: pointer;
  flex-shrink: 0;
}

.check-label {
  display: flex;
  align-items: flex-start;
  gap: 0.7rem;
  font-size: var(--fs-sm);
  font-weight: 400;
  color: var(--text-muted);
  line-height: 1.55;
  cursor: pointer;
}

.check-label a {
  color: var(--accent-2);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.check-label a:hover {
  color: var(--accent);
}

.field.has-error .check-label {
  color: var(--danger);
}

/* --- Tarjetas de blog --- */
.blog-card {
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
}

.blog-card .post-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1rem;
  font-size: var(--fs-xs);
  color: var(--text-dim);
}

.blog-card h3 {
  font-size: 1.2rem;
}

.blog-card h3 a {
  transition: color 0.2s ease;
}

.blog-card h3 a:hover {
  color: var(--accent-2);
}

.blog-card .read-more {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--accent-2);
  margin-top: auto;
}

.blog-card .read-more:hover {
  color: var(--accent);
}

/* --- Artículos --- */
.post-header {
  max-width: 760px;
}

.chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 1.2rem;
}

.prose {
  max-width: 760px;
  margin-inline: auto;
}

.prose > * + * {
  margin-top: 1.1rem;
}

.prose h2 {
  font-size: clamp(1.35rem, 2.5vw, 1.7rem);
  margin-top: 2.6rem;
}

.prose h3 {
  font-size: 1.12rem;
  margin-top: 1.8rem;
}

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

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

.prose a {
  color: var(--accent-2);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.prose ul,
.prose ol {
  display: grid;
  gap: 0.6rem;
  padding-left: 0;
}

.prose li {
  color: var(--text-muted);
  padding-left: 1.5rem;
  position: relative;
}

.prose ul li::before {
  content: "—";
  position: absolute;
  left: 0;
  color: var(--accent-2);
}

.prose ol {
  counter-reset: paso;
}

.prose ol li {
  counter-increment: paso;
}

.prose ol li::before {
  content: counter(paso) ".";
  position: absolute;
  left: 0;
  color: var(--accent-2);
  font-weight: 600;
}

.prose blockquote {
  border-left: 3px solid var(--accent);
  background: var(--raise);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  padding: 1rem 1.2rem;
  color: var(--text);
  font-style: normal;
}

.prose .callout {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 1.1rem 1.3rem;
}

.prose .callout p {
  margin: 0;
  font-size: var(--fs-sm);
}

.post-cta {
  margin-top: 2.8rem;
}

.related-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--gap);
}

@media (max-width: 760px) {
  .related-grid {
    grid-template-columns: 1fr;
  }
}

/* --- Error del servidor en el formulario --- */
.form-success.form-error {
  background: color-mix(in srgb, var(--danger) 12%, transparent);
  border-color: color-mix(in srgb, var(--danger) 45%, transparent);
  color: color-mix(in srgb, var(--danger) 85%, var(--text));
}

/* =========================================================
   HOME — bloques compactos (proceso y blog)
   Se reducen para que la home no se alargue sin añadir valor.
   ========================================================= */

.section--slim {
  padding-block: clamp(2.5rem, 5vw, 4rem);
}

/* ---------- Proceso en una franja ---------- */
.process-strip {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--gap);
  list-style: none;
  padding: 0;
  margin: 0;
  counter-reset: none;
}

.process-strip li {
  position: relative;
  padding-top: 1.5rem;
}

.process-strip li::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 2px;
  background: linear-gradient(90deg, var(--accent), color-mix(in srgb, var(--accent-2) 70%, transparent));
  border-radius: 2px;
  opacity: 0.75;
}

.process-num {
  display: block;
  font-family: var(--font-display);
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.1em;
  color: var(--accent-2);
  margin-bottom: 0.45rem;
}

.process-strip h3 {
  font-size: 1.02rem;
  margin-bottom: 0.3rem;
}

.process-strip p {
  font-size: var(--fs-sm);
  color: var(--text-muted);
  margin: 0;
}

/* ---------- Blog en franja ---------- */
.blog-strip {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr) auto;
  gap: clamp(1.5rem, 3vw, 2.5rem);
  align-items: center;
}

.blog-strip-copy h2 {
  font-size: var(--fs-h2);
  margin-bottom: 0.5rem;
}

.blog-strip-copy p {
  font-size: var(--fs-sm);
  color: var(--text-muted);
  margin: 0;
  max-width: 42ch;
}

.blog-strip-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 0.5rem;
}

.blog-strip-list a {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 0.75rem;
  padding: 0.7rem 0.9rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--raise);
  color: inherit;
  transition: border-color 0.25s ease, background 0.25s ease, transform 0.25s ease;
}

.blog-strip-list a:hover {
  border-color: color-mix(in srgb, var(--accent) 50%, transparent);
  background: var(--raise-strong);
  transform: translateX(3px);
}

.blog-strip-list .tag {
  white-space: nowrap;
}

.blog-strip-list strong {
  font-size: var(--fs-sm);
  font-weight: 600;
  line-height: 1.35;
  /* 2 líneas como máximo con recorte limpio; nowrap cortaba demasiado */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.blog-strip-list em {
  font-style: normal;
  font-size: var(--fs-xs);
  color: var(--text-dim);
  white-space: nowrap;
}

.blog-strip-cta {
  white-space: nowrap;
}

@media (max-width: 1024px) {
  .blog-strip {
    grid-template-columns: 1fr;
    text-align: left;
  }

  .blog-strip-cta {
    justify-self: start;
  }
}

@media (max-width: 760px) {
  .process-strip {
    grid-template-columns: repeat(2, 1fr);
    gap: 1.5rem var(--gap);
  }

  .blog-strip-list a {
    grid-template-columns: auto minmax(0, 1fr);
  }

  .blog-strip-list em {
    display: none;
  }
}

@media (max-width: 480px) {
  .process-strip {
    grid-template-columns: 1fr;
  }
}

/* =========================================================
   BLOQUES NUEVOS — Tecnologías y encaje de cliente
   ========================================================= */

/* ---------- Tecnologías e integraciones ---------- */
.tech-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--gap);
}

.tech-group {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.2rem 1.3rem;
}

.tech-group h3 {
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-dim);
  font-weight: 700;
  margin-bottom: 0.8rem;
}

.tech-group ul {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}

.tech-group li {
  font-size: var(--fs-xs);
  padding: 0.32rem 0.7rem;
  border-radius: 999px;
  background: var(--raise);
  border: 1px solid var(--border);
  color: var(--text-muted);
  white-space: nowrap;
}

/* Bloque de auditoría: es el gancho de captación */
.tech-note {
  margin-top: 2rem;
  padding: clamp(1.4rem, 3vw, 2.2rem);
  border-radius: var(--radius-lg);
  border: 1px solid var(--cta-border);
  background: var(--cta-bg);
  text-align: center;
}

.tech-note h3 {
  font-size: var(--fs-h3);
  margin-bottom: 0.4rem;
}

.tech-note > p {
  color: var(--text-muted);
  max-width: 58ch;
  margin: 0 auto 1.1rem;
}

.tech-checks {
  list-style: none;
  padding: 0;
  margin: 0 0 1.3rem;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.5rem 1.2rem;
  font-size: var(--fs-sm);
  color: var(--text-muted);
}

.tech-checks li {
  display: flex;
  align-items: center;
  gap: 0.4rem;
}

.tech-checks li::before {
  content: "✓";
  color: var(--success);
  font-weight: 700;
}

/* ---------- Encaje: sí / no ---------- */
.fit-section {
  background: var(--bg-soft);
}

.fit-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--gap);
  max-width: 900px;
  margin-inline: auto;
}

.fit-card {
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--surface);
  padding: clamp(1.3rem, 3vw, 1.8rem);
}

.fit-card--yes {
  border-color: color-mix(in srgb, var(--success) 38%, transparent);
  background: color-mix(in srgb, var(--success) 7%, var(--surface));
}

.fit-card--no {
  border-color: var(--border);
}

.fit-card h3 {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-size: 1.05rem;
  margin-bottom: 1rem;
}

.fit-card h3 svg {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
}

.fit-card--yes h3 svg {
  color: var(--success);
}

.fit-card--no h3 svg {
  color: var(--text-dim);
}

.fit-card ul {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 0.7rem;
}

.fit-card li {
  position: relative;
  padding-left: 1.4rem;
  font-size: var(--fs-sm);
  color: var(--text-muted);
  line-height: 1.55;
}

.fit-card li::before {
  position: absolute;
  left: 0;
  top: 0;
  font-weight: 700;
}

.fit-card--yes li::before {
  content: "✓";
  color: var(--success);
}

.fit-card--no li::before {
  content: "×";
  color: var(--text-dim);
}

@media (max-width: 900px) {
  .tech-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 640px) {
  .tech-grid,
  .fit-grid {
    grid-template-columns: 1fr;
  }

  .tech-checks {
    flex-direction: column;
    align-items: center;
    gap: 0.4rem;
  }
}

/* =========================================================
   AUTOMATIZACIÓN E IA — sección propia (no es "diseño web")
   ========================================================= */

.automation-section {
  position: relative;
  overflow: clip;
}

/* ---------- Diagrama de flujo ---------- */
.flow {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--gap);
  list-style: none;
  padding: 0;
  margin: 0 0 clamp(2.5rem, 5vw, 3.5rem);
  counter-reset: none;
}

.flow-step {
  position: relative;
  padding: 1.4rem 1.2rem 1.2rem;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--surface);
}

/* Línea que conecta los pasos */
.flow-step:not(:last-child)::after {
  content: "";
  position: absolute;
  top: 2.35rem;
  right: calc(var(--gap) / -2 - 1px);
  width: calc(var(--gap) + 2px);
  height: 1px;
  background: linear-gradient(90deg, var(--accent), transparent);
  z-index: 1;
}

.flow-icon {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  border-radius: 13px;
  margin-bottom: 0.9rem;
  color: var(--accent-2);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 32%, transparent);
}

.flow-icon svg {
  width: 22px;
  height: 22px;
}

.flow-num {
  position: absolute;
  top: 1.3rem;
  right: 1.3rem;
  font-family: var(--font-display);
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.1em;
  color: var(--text-dim);
}

.flow-step h3 {
  font-size: 1.02rem;
  margin-bottom: 0.35rem;
}

.flow-step p {
  font-size: var(--fs-sm);
  color: var(--text-muted);
  margin: 0;
  line-height: 1.55;
}

/* ---------- Tarjetas de servicio ---------- */
.auto-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--gap);
}

.auto-card {
  position: relative;
  padding: clamp(1.4rem, 3vw, 1.9rem);
  border-radius: var(--radius-lg);
  border: 1px solid var(--border);
  background: var(--surface);
  transition: border-color 0.3s ease, transform 0.3s ease;
}

.auto-card:hover {
  border-color: color-mix(in srgb, var(--accent) 45%, transparent);
  transform: translateY(-3px);
}

.auto-icon {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  border-radius: 13px;
  margin-bottom: 1rem;
  color: var(--accent-2);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 32%, transparent);
}

.auto-icon svg {
  width: 23px;
  height: 23px;
}

/* Distintivo para lo que aún no está disponible */
.auto-flag {
  position: absolute;
  top: 1.2rem;
  right: 1.2rem;
  font-size: 0.62rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  padding: 0.24rem 0.6rem;
  border-radius: 999px;
  color: #fbbf24;
  background: rgba(251, 191, 36, 0.12);
  border: 1px solid rgba(251, 191, 36, 0.4);
}

.auto-card--next {
  border-style: dashed;
}

.auto-card h3 {
  font-size: 1.15rem;
  margin-bottom: 0.5rem;
  padding-right: 7rem;
}

.auto-lead {
  color: var(--text-muted);
  margin-bottom: 1.1rem;
  line-height: 1.6;
}

.auto-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 0.55rem;
}

.auto-list li {
  position: relative;
  padding-left: 1.5rem;
  font-size: var(--fs-sm);
  color: var(--text-muted);
}

.auto-list li::before {
  content: "✓";
  position: absolute;
  left: 0;
  color: var(--success);
  font-weight: 700;
}

.auto-note {
  margin-top: 1.1rem;
  padding-top: 0.9rem;
  border-top: 1px dashed var(--border-strong);
  font-size: var(--fs-xs);
  color: var(--text-dim);
}

.automation-cta {
  margin-top: 2rem;
  text-align: center;
  display: grid;
  gap: 1rem;
  justify-items: center;
}

.automation-cta p {
  color: var(--text-muted);
  max-width: 58ch;
  margin: 0;
}

/* ---------- Responsive ---------- */
@media (max-width: 960px) {
  .flow {
    grid-template-columns: repeat(2, 1fr);
  }

  /* Sin línea conectora cuando la rejilla se parte */
  .flow-step::after {
    display: none !important;
  }

  .auto-grid {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 560px) {
  .flow {
    grid-template-columns: 1fr;
  }
}

/* =========================================================
   CASO DE PROYECTO — /proyectos/<slug>
   ========================================================= */

.page-hero--case .case-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
  list-style: none;
  padding: 0;
  margin: 0 0 1.4rem;
}

/* Captura del proyecto: reutiliza los degradados .thumb-N */
.case-shot {
  aspect-ratio: 16 / 10;
  display: grid;
  place-items: center;
}

.case-shot-art {
  font-family: var(--font-display);
  font-size: clamp(2.5rem, 6vw, 4rem);
  font-weight: 700;
  color: rgba(255, 255, 255, 0.92);
  letter-spacing: -0.03em;
  text-shadow: 0 8px 30px rgba(0, 0, 0, 0.45);
}

/* ---------- Cifras ---------- */
.case-metrics {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--gap);
  max-width: 860px;
  margin-inline: auto;
}

.case-metric {
  text-align: center;
  padding: 0.6rem 0.5rem;
}

.case-metric strong {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(1.6rem, 3.4vw, 2.2rem);
  background: var(--text-grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  line-height: 1.2;
}

.case-metric span {
  font-size: var(--fs-xs);
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

/* ---------- Reto / Solución / Resultado ---------- */
.case-body {
  display: grid;
  gap: clamp(2rem, 4vw, 3rem);
  max-width: 820px;
}

.case-block-title {
  display: flex;
  align-items: baseline;
  gap: 0.8rem;
  font-size: var(--fs-h3);
  margin-bottom: 0.9rem;
}

.case-step {
  font-family: var(--font-display);
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.1em;
  color: var(--accent-2);
}

.case-lead {
  font-size: 1.06rem;
  color: var(--text-muted);
  line-height: 1.7;
  margin: 0;
}

.case-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 0.8rem;
}

.case-list li {
  position: relative;
  padding-left: 1.7rem;
  color: var(--text-muted);
  line-height: 1.65;
}

.case-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.55em;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent-grad);
}

/* ---------- Ficha técnica ---------- */
.case-facts {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  padding: clamp(1.2rem, 3vw, 1.8rem);
}

.case-facts h3 {
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-dim);
  margin-bottom: 1rem;
}

.case-facts dl {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1.1rem var(--gap);
  margin: 0;
}

.case-facts dt {
  font-size: var(--fs-xs);
  color: var(--text-dim);
  margin-bottom: 0.2rem;
}

.case-facts dd {
  margin: 0;
  font-size: var(--fs-sm);
  font-weight: 600;
}

.case-facts-wide {
  grid-column: 1 / -1;
}

.case-stack {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}

.case-stack span {
  font-size: var(--fs-xs);
  padding: 0.28rem 0.65rem;
  border-radius: 999px;
  background: var(--raise);
  border: 1px solid var(--border);
  color: var(--text-muted);
  font-weight: 500;
}

/* ---------- Testimonio del caso ---------- */
.quote--case {
  max-width: 760px;
  margin-inline: auto;
  text-align: left;
}

/* ---------- Tarjetas como enlace ---------- */
.project-card--link {
  display: block;
  color: inherit;
  text-decoration: none;
}

.project-card--link:hover {
  transform: translateY(-4px);
  border-color: color-mix(in srgb, var(--accent) 45%, transparent);
}

@media (max-width: 760px) {
  .case-metrics {
    grid-template-columns: 1fr;
    gap: 1.25rem;
  }

  .case-facts dl {
    grid-template-columns: 1fr;
  }
}

/* =========================================================
   ENCABEZADO PREMIUM DE PÁGINAS INTERIORES
   ========================================================= */

.page-hero--premium {
  padding-top: calc(var(--header-h) + clamp(2.5rem, 6vw, 4.5rem));
  padding-bottom: clamp(2.5rem, 6vw, 4.5rem);
  position: relative;
  isolation: isolate;
  overflow: clip;
  max-width: 100%;
}

/* Fondo: reutiliza la aurora y la rejilla del hero de la home */
.page-hero-bg {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  overflow: hidden;
}

.page-hero--premium .page-hero-bg .hero-grid {
  mask-image: radial-gradient(ellipse 70% 60% at 35% 30%, #000 10%, transparent 75%);
  -webkit-mask-image: radial-gradient(ellipse 70% 60% at 35% 30%, #000 10%, transparent 75%);
}

.page-hero--premium .aurora-1 {
  width: 540px;
  height: 540px;
  top: -240px;
  left: -160px;
}

.page-hero--premium .aurora-2 {
  width: 480px;
  height: 480px;
  top: -160px;
  right: -60px;
}

.page-hero--premium .page-hero-bg .aurora {
  opacity: 0.45;
}

.page-hero--premium .page-hero-bg .aurora {
  opacity: 0.34;
}

/* Rejilla de dos columnas */
.page-hero-layout {
  display: grid;
  grid-template-columns: minmax(0, 1.08fr) minmax(0, 0.92fr);
  gap: clamp(2rem, 4vw, 3.25rem);
  align-items: center;
}

/* El .page-hero clásico impone max-width:780px a su .container.
   Necesita la misma especificidad (dos clases) y ir después para ganar. */
.page-hero--premium .page-hero-layout {
  max-width: var(--container);
}

/* Ambas columnas pueden encogerse: nada debe forzar ancho extra */
.page-hero-layout > * {
  min-width: 0;
}

.page-hero--premium .page-hero-copy {
  min-width: 0;
  max-width: 640px;
}

.page-hero-title {
  font-size: clamp(2rem, 4.1vw, 3.35rem);
  line-height: 1.08;
  letter-spacing: -0.035em;
  margin-bottom: 1.25rem;
}

.page-hero-title .line {
  display: block;
  overflow: hidden;
  padding-bottom: 0.06em;
  /* Sin nowrap: los titulares interiores son más largos que los de la home
     y con nowrap se salían de la columna y quedaban cortados. */
}

html:not(.has-gsap) .page-hero-title .line > span {
  display: block;
  animation: lineUp 0.95s cubic-bezier(0.16, 0.84, 0.28, 1) both;
}

html:not(.has-gsap) .page-hero-title .line:nth-child(1) > span { animation-delay: 0.08s; }
html:not(.has-gsap) .page-hero-title .line:nth-child(2) > span { animation-delay: 0.2s; }
html:not(.has-gsap) .page-hero-title .line:nth-child(3) > span { animation-delay: 0.32s; }

.page-hero--premium .lead {
  font-size: clamp(1rem, 1.9vw, 1.14rem);
  color: var(--text-muted);
  max-width: 540px;
  margin: 0 0 1.75rem;
}

.page-hero--premium .breadcrumb {
  margin-bottom: 1rem;
}

.page-hero--premium .breadcrumb span[aria-current] {
  color: var(--text);
}

.page-hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.7rem;
  margin-bottom: 1.25rem;
}

.page-hero--premium .trust-row {
  justify-content: flex-start;
  margin-top: 0;
}

/* Columna del mockup */
.page-hero-showcase {
  position: relative;
  perspective: 1400px;
  min-width: 0;
  overflow: visible;
  animation: showcaseIn 1.1s cubic-bezier(0.16, 0.84, 0.28, 1) 0.3s both;
}

html:not(.has-gsap) .page-hero-showcase {
  animation: showcaseIn 1.1s cubic-bezier(0.16, 0.84, 0.28, 1) 0.3s both;
}

.mock-page {
  padding: 1rem 1.1rem 1.2rem;
  min-height: 230px;
}

/* El contenido del mockup nunca debe ensanchar su columna */
.mock-window,
.mock-page,
.mock-board,
.mock-gallery,
.mock-plans,
.mock-articles,
.mock-calendar,
.mock-reader {
  min-width: 0;
  max-width: 100%;
}

/* ---------- Variante: servicios (tablero) ---------- */
.mock-board {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.55rem;
}

.mock-col {
  background: var(--raise);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.55rem;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.mock-col-title {
  font-size: 0.62rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-dim);
  font-weight: 700;
}

.mock-task {
  font-size: 0.72rem;
  padding: 0.4rem 0.5rem;
  border-radius: 7px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--text-muted);
}

.mock-task.is-done {
  opacity: 0.55;
  text-decoration: line-through;
}

.mock-task.is-live {
  background: color-mix(in srgb, var(--accent) 18%, transparent);
  border-color: color-mix(in srgb, var(--accent) 45%, transparent);
  color: var(--text);
}

/* ---------- Variante: proyectos (galería) ---------- */
.mock-gallery {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.5rem;
}

.mock-tile {
  aspect-ratio: 4 / 3;
  border-radius: var(--radius-sm);
  display: flex;
  align-items: flex-end;
  padding: 0.45rem;
  position: relative;
  overflow: hidden;
}

.mock-tile em {
  font-style: normal;
  font-size: 0.62rem;
  font-weight: 700;
  color: #fff;
  text-shadow: 0 1px 6px rgba(0, 0, 0, 0.6);
}

.mock-tile.t1 { background: linear-gradient(135deg, #059669, #0ea5e9); }
.mock-tile.t2 { background: linear-gradient(135deg, #047857, #0d9488); }
.mock-tile.t3 { background: linear-gradient(135deg, #0d9488, #34d399); }
.mock-tile.t4 { background: linear-gradient(135deg, #f59e0b, #d97706); }
.mock-tile.t5 { background: linear-gradient(135deg, #0f172a, #047857); }
  .mock-tile.t6 { background: linear-gradient(135deg, #10b981, #34d399); }

/* ---------- Variante: precios (planes) ---------- */
.mock-plans {
  display: grid;
  gap: 0.5rem;
}

.mock-plan {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.6rem 0.75rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--raise);
}

.mock-plan.is-featured {
  border-color: color-mix(in srgb, var(--accent) 50%, transparent);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
}

.mock-plan-name {
  font-size: 0.78rem;
  font-weight: 600;
}

.mock-plan strong {
  font-family: var(--font-display);
  font-size: 0.95rem;
  white-space: nowrap;
}

.mock-plan-meta {
  font-size: 0.66rem;
  color: var(--text-dim);
  white-space: nowrap;
}

/* ---------- Variante: contacto (agenda) ---------- */
.mock-calendar {
  display: grid;
  gap: 0.7rem;
}

.mock-cal-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
}

.mock-cal-head span {
  font-family: var(--font-display);
  font-size: 0.95rem;
  font-weight: 600;
}

.mock-cal-head em {
  font-style: normal;
  font-size: 0.68rem;
  color: var(--text-dim);
}

.mock-slots {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}

.mock-slot {
  font-size: 0.72rem;
  padding: 0.4rem 0.65rem;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--surface-2);
  color: var(--text-muted);
}

.mock-slot.is-picked {
  background: var(--accent-grad);
  color: var(--on-accent);
  border-color: transparent;
  font-weight: 700;
}

.mock-confirm {
  text-align: center;
  font-size: 0.78rem;
  font-weight: 600;
  padding: 0.55rem;
  border-radius: 999px;
  background: var(--raise-strong);
  color: var(--text);
}

/* ---------- Variante: blog (artículos) ---------- */
.mock-articles {
  display: grid;
  gap: 0.5rem;
}

.mock-article {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.55rem 0.7rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--raise);
}

.mock-article em {
  font-style: normal;
  font-size: 0.6rem;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  font-weight: 700;
  color: var(--accent-2);
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  padding: 0.16rem 0.5rem;
  white-space: nowrap;
}

.mock-article strong {
  font-size: 0.8rem;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---------- Variante: artículo (lector) ---------- */
.mock-reader {
  display: grid;
  gap: 0.5rem;
}

/* ---------- Artículos: encabezado con mockup ---------- */
.page-hero--article .post-header {
  max-width: 100%;
}

.page-hero--article .chip-row {
  margin-bottom: 1rem;
}

.post-meta-line {
  font-size: var(--fs-xs);
  color: var(--text-dim);
}

/* ---------- Legales: encabezado sin mockup ---------- */
.page-hero--slim .lead {
  margin-bottom: 0;
}

.page-hero--slim .page-hero-title {
  margin-bottom: 1rem;
}

/* ---------- 404: encabezado centrado ---------- */
.page-hero--centered .lead {
  margin-inline: auto;
}

.page-hero--centered .eyebrow-pill {
  margin-inline: auto;
}

.mock-reader-bar {
  height: 4px;
  border-radius: 999px;
  background: var(--raise-strong);
  overflow: hidden;
  margin-bottom: 0.3rem;
}

.mock-reader-bar span {
  display: block;
  height: 100%;
  width: var(--w);
  background: var(--accent-grad);
}

.mock-line {
  height: 9px;
  border-radius: 5px;
  background: var(--raise-strong);
}

.mock-line.w100 { width: 100%; }
.mock-line.w90 { width: 90%; }
.mock-line.w80 { width: 80%; }
.mock-line.w70 { width: 70%; }
.mock-line.w45 { width: 45%; }

/* ---------- Responsive ---------- */
@media (max-width: 1024px) {
  .page-hero-layout {
    grid-template-columns: 1fr;
    gap: 2.75rem;
  }

  .page-hero-title .line {
    white-space: normal;
  }

  .page-hero--premium .page-hero-copy {
    max-width: 100%;
  }

  .page-hero-showcase {
    max-width: 520px;
    margin-inline: auto;
    width: 100%;
  }
}

@media (max-width: 640px) {
  .page-hero-showcase {
    max-width: 100%;
  }

  .mock-page {
    padding: 0.85rem;
  }

  .mock-plan {
    flex-wrap: wrap;
    gap: 0.25rem;
  }
}

/* ---------- Respeta el movimiento reducido ---------- */
@media (prefers-reduced-motion: reduce) {
  .page-hero-showcase {
    animation: none !important;
  }
}

/* =========================================================
   Motion con GSAP / Lenis — elementos y estados
   ========================================================= */

/* --- Barra de progreso de lectura --- */
.scroll-progress {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  z-index: 200;
  transform: scaleX(0);
  transform-origin: 0 50%;
  background: var(--accent-grad);
  box-shadow: 0 0 12px color-mix(in srgb, var(--accent) 60%, transparent);
  pointer-events: none;
  will-change: transform;
}

/* --- Tilt 3D: prepara la tarjeta y añade el brillo que sigue al puntero --- */
.tilt-3d {
  transform-style: preserve-3d;
  will-change: transform;
}

/* Las tarjetas con tilt necesitan position para que el brillo se posicione.
   SIN overflow:hidden a propósito: el badge "Más elegido" de .price-card
   sobresale por arriba (top:-13px) y lo recortaba. El brillo ya se
   redondea solo con border-radius:inherit, no necesita el recorte. */
.project-card,
.price-card,
.quote,
.info-item,
.blog-card {
  position: relative;
}

/* El brillo no debe capturar clics ni tapar el texto */
.tilt-shine {
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  opacity: 0;
  border-radius: inherit;
  mix-blend-mode: overlay;
  background: radial-gradient(
    380px circle at var(--shine-x, 50%) var(--shine-y, 50%),
    rgba(255, 255, 255, 0.14),
    transparent 62%
  );
  transition: opacity 0.35s ease;
}

.tilt-3d:hover .tilt-shine {
  opacity: 1;
}

/* --- Cabecera compacta ---
   El encogido se hace ahora con la altura del propio header
   (ver bloque "Header" más arriba) y no con padding-block sobre
   .header-inner: dentro de una altura fija, el padding desbordaba
   y el header no recuperaba su medida original al subir. */

/* --- Split de titulares: evita el salto al aplicar la animación --- */
.section-head h2,
.page-hero h1,
.post-header h1,
.cta-band h2 {
  will-change: transform, opacity;
}

/* --- Lenis: desactiva el scroll-behavior nativo para evitar conflictos --- */
html.lenis,
html.lenis body {
  height: auto;
}

.lenis.lenis-smooth {
  scroll-behavior: auto !important;
}

.lenis.lenis-stopped {
  overflow: hidden;
}

/* =========================================================
   HERO PREMIUM — fondo aurora, titular por líneas y mockup
   ========================================================= */

.hero {
  position: relative;
  /* clip recorta el desbordamiento del mockup y las tarjetas flotantes */
  overflow: clip;
  padding-top: calc(var(--header-h) + clamp(2.5rem, 6vw, 4.5rem));
  padding-bottom: clamp(3rem, 7vw, 6rem);
  isolation: isolate;
  max-width: 100%;
}

/* ---------- Fondo animado ---------- */
.hero-bg {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  overflow: hidden;
}

.hero-grid {
  position: absolute;
  inset: -10% -10% 0;
  background-image: linear-gradient(var(--grid-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
  background-size: 64px 64px;
  mask-image: radial-gradient(ellipse 80% 60% at 50% 25%, #000 15%, transparent 78%);
  -webkit-mask-image: radial-gradient(ellipse 80% 60% at 50% 25%, #000 15%, transparent 78%);
  animation: gridDrift 26s linear infinite;
}

@keyframes gridDrift {
  to {
    background-position: 64px 64px;
  }
}

/* Manchas de color: degradado de malla con movimiento muy lento */
.aurora {
  position: absolute;
  display: block;
  border-radius: 50%;
  filter: blur(90px);
  opacity: 0.55;
  will-change: transform;
}

.aurora-1 {
  width: 620px;
  height: 620px;
  top: -220px;
  left: -140px;
  background: radial-gradient(circle at 30% 30%, var(--accent) 0%, transparent 68%);
  animation: drift1 22s ease-in-out infinite alternate;
}

/* El verde azulado, no el ambar.

   Este halo es de 560 px en la esquina superior derecha: con el ambar
   teñia media cabecera de arena y la pagina daba atardecer. El verde
   azulado mantiene la profundidad que daba el ambar y sigue siendo de
   la familia. */
.aurora-2 {
  width: 560px;
  height: 560px;
  top: -120px;
  right: -120px;
  background: radial-gradient(
    circle at 60% 40%,
    color-mix(in srgb, var(--accent) 60%, var(--info)) 0%,
    transparent 68%
  );
  animation: drift2 26s ease-in-out infinite alternate;
}

.aurora-3 {
  width: 700px;
  height: 420px;
  bottom: -160px;
  left: 32%;
  background: radial-gradient(ellipse at 50% 50%, var(--accent) 0%, transparent 70%);
  opacity: 0.32;
  animation: drift3 30s ease-in-out infinite alternate;
}

@keyframes drift1 {
  to {
    transform: translate3d(90px, 70px, 0) scale(1.15);
  }
}

@keyframes drift2 {
  to {
    transform: translate3d(-80px, 90px, 0) scale(1.12);
  }
}

@keyframes drift3 {
  to {
    transform: translate3d(60px, -50px, 0) scale(1.2);
  }
}

/* Grano sutil: evita el banding de los degradados */
.hero-noise {
  position: absolute;
  inset: 0;
  opacity: 0.16;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
}

/* ---------- Rejilla de dos columnas ---------- */
.hero-layout {
  display: grid;
  /* La columna de texto necesita más ancho para que el titular respete sus 3 líneas */
  grid-template-columns: minmax(0, 1.18fr) minmax(0, 0.82fr);
  gap: clamp(2rem, 3.5vw, 2.75rem);
  align-items: center;
  margin-bottom: clamp(2.5rem, 6vw, 4rem);
}

.hero-copy {
  max-width: 640px;
}

/* ---------- Etiqueta superior ---------- */
.eyebrow-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.45rem 1rem 0.45rem 0.75rem;
  border-radius: 999px;
  border: 1px solid var(--border-strong);
  background: var(--raise);
  backdrop-filter: blur(10px);
  font-size: var(--fs-xs);
  letter-spacing: 0.02em;
}

.eyebrow-pill .dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--success);
  box-shadow: 0 0 0 0 var(--success);
  animation: pulseDot 2.4s ease-out infinite;
  flex-shrink: 0;
}

@keyframes pulseDot {
  0% {
    box-shadow: 0 0 0 0 color-mix(in srgb, var(--success) 70%, transparent);
  }
  70% {
    box-shadow: 0 0 0 9px transparent;
  }
  100% {
    box-shadow: 0 0 0 0 transparent;
  }
}

/* ---------- Titular con revelado por líneas ---------- */
.hero-title {
  font-size: clamp(2.05rem, 3.85vw, 3.15rem);
  line-height: 1.08;
  letter-spacing: -0.035em;
  margin-bottom: 1.5rem;
}

.hero-title .line {
  display: block;
  overflow: hidden;
  padding-bottom: 0.06em;
  /* nowrap por línea: el titular respalda siempre 3 líneas, no 4 */
  white-space: nowrap;
}

/* ---------- Titular con revelado por líneas ----------
   Con GSAP cargado el revelado lo hace motion.js, así que la animación
   CSS se desactiva para que ambas no compitan por el mismo transform. */
html:not(.has-gsap) .hero-title .line > span {
  display: block;
  animation: lineUp 0.95s cubic-bezier(0.16, 0.84, 0.28, 1) both;
}

html:not(.has-gsap) .hero-title .line:nth-child(1) > span { animation-delay: 0.1s; }
html:not(.has-gsap) .hero-title .line:nth-child(2) > span { animation-delay: 0.22s; }
html:not(.has-gsap) .hero-title .line:nth-child(3) > span { animation-delay: 0.34s; }

@keyframes lineUp {
  from {
    transform: translateY(105%);
    opacity: 0;
  }
  to {
    transform: none;
    opacity: 1;
  }
}

.hero-title em {
  font-style: normal;
}

.hero-copy .lead {
  max-width: 560px;
  margin: 0 0 2rem;
}

.hero-copy .lead strong {
  color: var(--text);
  font-weight: 600;
}

/* ---------- Botones con icono ---------- */
.hero-actions .btn svg {
  width: 18px;
  height: 18px;
  transition: transform 0.3s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.hero-actions .btn:hover svg {
  transform: translateX(4px);
}

/* ---------- Prueba social ---------- */
.hero-proof {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-bottom: 1.25rem;
}

.hero-proof-text p {
  font-size: var(--fs-sm);
  color: var(--text-muted);
  margin: 0.2rem 0 0;
}

.hero-proof-text strong {
  color: var(--text);
}

.stars {
  display: inline-flex;
  gap: 2px;
  color: #fbbf24;
}

.stars svg {
  width: 15px;
  height: 15px;
}

.hero-copy .hero-note {
  margin: 0;
}

/* ---------- Mockup de producto ---------- */
.hero-showcase {
  position: relative;
  perspective: 1400px;
  /* Evita que el navegador recorte el 3D y las tarjetas que sobresalen */
  overflow: visible;
}

/* El mockup, las barras y las órbitas entran con GSAP cuando está disponible */
html:not(.has-gsap) .hero-showcase {
  animation: showcaseIn 1.1s cubic-bezier(0.16, 0.84, 0.28, 1) 0.42s both;
}

@keyframes showcaseIn {
  from {
    opacity: 0;
    transform: translate3d(0, 40px, -60px) rotateY(-8deg);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.mock-window {
  border-radius: var(--radius);
  border: 1px solid var(--border-strong);
  background: var(--surface);
  box-shadow: 0 40px 90px rgba(0, 0, 0, 0.55), 0 0 0 1px var(--raise);
  overflow: hidden;
  transform-style: preserve-3d;
  transition: transform 0.5s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.mock-bar {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.7rem 0.9rem;
  border-bottom: 1px solid var(--border);
  background: var(--surface-2);
}

.mock-dots {
  display: flex;
  gap: 5px;
}

.mock-dots i {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--border-strong);
}

.mock-dots i:first-child { background: #ff5f57; }
.mock-dots i:nth-child(2) { background: #febc2e; }
.mock-dots i:nth-child(3) { background: #28c840; }

.mock-url {
  flex: 1;
  text-align: center;
  font-size: 0.72rem;
  color: var(--text-dim);
  background: var(--raise);
  border-radius: 6px;
  padding: 0.28rem 0.6rem;
  font-family: var(--font-display);
}

.mock-pill {
  font-size: 0.62rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--success);
  background: var(--success-bg);
  border: 1px solid var(--success-border);
  border-radius: 999px;
  padding: 0.2rem 0.55rem;
}

.mock-body {
  display: grid;
  grid-template-columns: 52px 1fr;
}

.mock-side {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.85rem;
  padding: 0.9rem 0;
  border-right: 1px solid var(--border);
  background: var(--bg-soft);
}

.mock-logo {
  width: 24px;
  height: 24px;
  border-radius: 7px;
  background: var(--accent-grad);
  margin-bottom: 0.4rem;
}

.mock-nav {
  width: 22px;
  height: 22px;
  border-radius: 6px;
  background: var(--raise-strong);
}

.mock-nav.is-active {
  background: color-mix(in srgb, var(--accent) 45%, transparent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent);
}

.mock-main {
  padding: 1rem 1.1rem 1.2rem;
  display: grid;
  gap: 0.9rem;
}

.mock-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1rem;
}

.mock-head strong {
  display: block;
  font-family: var(--font-display);
  font-size: 1.02rem;
}

.mock-kicker {
  font-size: 0.66rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-dim);
}

.mock-chip {
  font-size: 0.66rem;
  color: var(--text-muted);
  background: var(--raise);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0.24rem 0.6rem;
  white-space: nowrap;
}

.mock-kpis {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.55rem;
}

.mock-kpi {
  background: var(--raise);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.6rem 0.65rem;
}

.mock-kpi span {
  display: block;
  font-size: 0.62rem;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.mock-kpi strong {
  display: block;
  font-family: var(--font-display);
  font-size: 1.18rem;
  line-height: 1.3;
}

.mock-kpi em {
  font-style: normal;
  font-size: 0.66rem;
  font-weight: 700;
}

.mock-kpi .up {
  color: var(--success);
}

.mock-kpi .down {
  color: var(--danger);
}

/* Gráfico de barras: crece al entrar en pantalla */
.mock-chart {
  display: flex;
  align-items: flex-end;
  gap: 6px;
  height: 108px;
  padding-top: 0.5rem;
  border-bottom: 1px solid var(--border);
}

.mock-chart span {
  flex: 1;
  height: var(--h);
  border-radius: 4px 4px 0 0;
  background: linear-gradient(180deg, var(--accent), color-mix(in srgb, var(--accent-2) 75%, transparent));
  opacity: 0.85;
  transform-origin: bottom;
}

/* Con GSAP cargado el crecimiento lo hace motion.js */
html:not(.has-gsap) .mock-chart span {
  animation: barGrow 0.9s cubic-bezier(0.16, 0.84, 0.28, 1) both;
}

html:not(.has-gsap) .mock-chart span:nth-child(1) { animation-delay: 0.75s; }
html:not(.has-gsap) .mock-chart span:nth-child(2) { animation-delay: 0.82s; }
html:not(.has-gsap) .mock-chart span:nth-child(3) { animation-delay: 0.89s; }
.mock-chart span:nth-child(4) { animation-delay: 0.96s; }
.mock-chart span:nth-child(5) { animation-delay: 1.03s; }
html:not(.has-gsap) .mock-chart span:nth-child(6) { animation-delay: 1.1s; }
html:not(.has-gsap) .mock-chart span:nth-child(7) { animation-delay: 1.17s; }
html:not(.has-gsap) .mock-chart span:nth-child(8) { animation-delay: 1.24s; }
html:not(.has-gsap) .mock-chart span:nth-child(9) { animation-delay: 1.31s; }
html:not(.has-gsap) .mock-chart span:nth-child(10) { animation-delay: 1.38s; }
html:not(.has-gsap) .mock-chart span:nth-child(11) { animation-delay: 1.45s; }
html:not(.has-gsap) .mock-chart span:nth-child(12) { animation-delay: 1.52s; }

@keyframes barGrow {
  from {
    transform: scaleY(0);
  }
  to {
    transform: scaleY(1);
  }
}

/* ---------- Tarjetas flotantes ---------- */
.float-card {
  position: absolute;
  z-index: 3;
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.7rem 0.95rem;
  border-radius: 14px;
  border: 1px solid var(--border-strong);
  background: color-mix(in srgb, var(--surface) 88%, transparent);
  backdrop-filter: blur(16px);
  box-shadow: 0 22px 50px rgba(0, 0, 0, 0.45);
  /* --float-shift lo escribe main.js con el paralaje del scroll */
  animation: floaty 6s ease-in-out infinite;
  will-change: transform;
}

/* Las tarjetas sobresalen por las esquinas: no deben tapar los KPI ni el gráfico */
.float-card--a {
  top: -1.4rem;
  left: -4.5rem;
}

.float-card--b {
  bottom: -1.4rem;
  right: -3.5rem;
  animation-delay: -3s;
}

@keyframes floaty {
  0%,
  100% {
    transform: translateY(var(--float-shift, 0px));
  }
  50% {
    transform: translateY(calc(var(--float-shift, 0px) - 12px));
  }
}

.float-icon {
  width: 34px;
  height: 34px;
  border-radius: 10px;
  display: grid;
  place-items: center;
  flex-shrink: 0;
}

.float-icon svg {
  width: 17px;
  height: 17px;
}

.float-icon--up {
  color: var(--success);
  background: var(--success-bg);
  border: 1px solid var(--success-border);
}

.float-icon--ok {
  color: var(--accent-2);
  background: color-mix(in srgb, var(--accent-2) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent-2) 38%, transparent);
}

.float-card strong {
  display: block;
  font-family: var(--font-display);
  font-size: 0.98rem;
  line-height: 1.25;
}

.float-card span:not(.float-icon) {
  font-size: 0.72rem;
  color: var(--text-muted);
  white-space: nowrap;
}

/* ---------- Órbitas decorativas ---------- */
.orbit {
  position: absolute;
  border-radius: 50%;
  border: 1px solid var(--border);
  pointer-events: none;
  z-index: 0;
}

.orbit--1 {
  width: 340px;
  height: 340px;
  top: -14%;
  right: -12%;
  border-style: dashed;
  opacity: 0.55;
  animation: spin 44s linear infinite;
}

.orbit--2 {
  width: 220px;
  height: 220px;
  bottom: -12%;
  left: -8%;
  opacity: 0.4;
  animation: spin 32s linear infinite reverse;
}

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

/* ---------- Indicador de scroll ---------- */
.scroll-hint {
  position: absolute;
  left: 50%;
  bottom: 1.2rem;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.55rem;
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--text-dim);
  transition: color 0.25s ease;
}

.scroll-hint:hover {
  color: var(--text-muted);
}

.scroll-hint-line {
  width: 1px;
  height: 42px;
  background: linear-gradient(180deg, var(--accent), transparent);
  position: relative;
  overflow: hidden;
}

.scroll-hint-line::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--accent-2);
  animation: hintRun 2.2s ease-in-out infinite;
}

@keyframes hintRun {
  0% {
    transform: translateY(-100%);
  }
  100% {
    transform: translateY(100%);
  }
}

/* ---------- Ajustes por tema ---------- */
.mock-window {
  box-shadow: 0 30px 70px rgba(18, 20, 44, 0.16), 0 0 0 1px rgba(13, 16, 40, 0.05);
}

.float-card {
  box-shadow: 0 18px 40px rgba(18, 20, 44, 0.14);
}

.aurora {
  opacity: 0.42;
}

/* ---------- Responsive del hero ---------- */
@media (max-width: 1024px) {
  .hero-layout {
    grid-template-columns: 1fr;
    gap: 3rem;
    /* Nada de lo que cuelga del mockup puede ensanchar la columna */
    min-width: 0;
  }

  .hero-copy {
    min-width: 0;
  }

  .hero-title .line {
    white-space: normal;
  }

  .hero-copy {
    max-width: 100%;
    text-align: center;
    margin-inline: auto;
  }

  .hero-copy .lead {
    margin-inline: auto;
  }

  .hero-actions,
  .hero-proof,
  .hero-copy .hero-note {
    justify-content: center;
  }

  .hero-proof {
    justify-content: center;
  }

  .hero-showcase {
    max-width: 560px;
    margin-inline: auto;
    width: 100%;
    min-width: 0;
  }

  /* La prueba social no debe forzar ancho en pantallas estrechas */
  .hero-proof {
    flex-wrap: wrap;
    justify-content: center;
  }

  .float-card--a {
    left: -3%;
  }

  .float-card--b {
    right: -3%;
  }

  .orbit--1,
  .orbit--2 {
    display: none;
  }

  .scroll-hint {
    display: none;
  }
}

@media (max-width: 640px) {
  /* En móvil el titular sí puede partirse: evita desbordes */
  .hero-title .line {
    white-space: normal;
  }

  /* Palabras largas (URLs, emails) no deben ensanchar la página */
  .hero-copy,
  .hero-copy .lead {
    min-width: 0;
    overflow-wrap: break-word;
  }

  .eyebrow-pill {
    max-width: 100%;
    text-align: center;
  }

  .hero-showcase {
    max-width: 100%;
  }

  .mock-body {
    grid-template-columns: 40px 1fr;
  }

  .mock-nav {
    width: 18px;
    height: 18px;
  }

  .mock-kpi strong {
    font-size: 1rem;
  }

  /* Las tarjetas flotantes se apilan y no tapan el mockup */
  .float-card--a {
    top: -0.6rem;
    left: -0.4rem;
    padding: 0.55rem 0.7rem;
  }

  .float-card--b {
    bottom: -0.6rem;
    right: -0.4rem;
    padding: 0.55rem 0.7rem;
  }

  .float-card span:not(.float-icon) {
    display: none;
  }

  .float-icon {
    width: 30px;
    height: 30px;
  }
}

/* ---------- Respeta la preferencia de movimiento reducido ---------- */
@media (prefers-reduced-motion: reduce) {
  .hero-grid,
  .aurora,
  .orbit,
  .float-card,
  .scroll-hint-line::after,
  .eyebrow-pill .dot {
    animation: none !important;
  }

  .hero-title .line > span {
    animation: none !important;
    transform: none !important;
    opacity: 1 !important;
  }

  .hero-showcase {
    animation: none !important;
  }

  .mock-chart span {
    animation: none !important;
    transform: none !important;
  }
}

/* =========================================================
   UTILIDADES
   ========================================================= */

/* Visible para el lector de pantalla, invisible en pantalla.

   Se usa para lo que hace falta decir pero no ensucia la vista: el
   "Acciones" de una cabecera de columna, o a qué cliente pertenece
   un boton "Abrir" repetido 18 veces. Ese último caso importa mas de
   lo que parece: dieciocho botones "Abrir" iguales no dicen a quien
   abren, asi que un lector de pantalla oye dieciocho veces lo mismo
   y no sabe cual es cual.

   NO es `display: none`, que lo saca tambien del arbol de
   accesibilidad: un lector de pantalla se lo saltaria. De ahi el
   recorte a 1px en vez de ocultarlo. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* =========================================================
   CUENTA DE CLIENTE
   =========================================================
   Las dos pantallas de /cuenta. Visten con la misma carta que el
   resto del sitio —.form-card, .form-grid, .field, .error-msg— y no
   con una propia: una cuenta que se parece a la web hace menos
   ruido que una que parece de otro producto, y el camino de alta es
   el mismo que el de pedir presupuesto.

   El reparto es de dos columnas porque la columna izquierda vende en
   cuatro líneas lo que va a pasar después de darle al botón. En
   "entrar" no hace falta: no hay nada que contar, así que se queda
   sola la tarjeta y no queda un hueco al lado con texto de relleno.
*/

.cuenta-grid {
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
  gap: 3rem;
  align-items: start;
}

.cuenta-grid--simple {
  grid-template-columns: minmax(0, 1fr);
  max-width: 30rem;
  margin-inline: auto;
}

.cuenta-lado h1 {
  margin-bottom: 0.75rem;
}

.cuenta-lado .lead {
  margin-bottom: 1.75rem;
}

.cuenta-lista {
  display: grid;
  gap: 0.7rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Cada punto lleva su propio.tick en vez de un `li` con viñeta: la
   viñeta del navegador se alinea a la primera línea del texto y,
   con dos líneas, queda flotando sola arriba. Un pseudo:before
   con `align-self` no tiene ese problema. */
.cuenta-lista li {
  position: relative;
  padding-inline-start: 1.75rem;
  color: var(--text-muted);
}

.cuenta-lista li::before {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  top: 0.5em;
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 999px;
  background: var(--accent-2);
}

.cuenta-pie {
  margin-top: 1.25rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--border);
  font-size: var(--fs-sm);
  color: var(--text-muted);
  text-align: center;
}

/* En una columna la tarjeta va arriba y la columna de texto debajo.

   Al revés —texto primero, tarjeta después— obligaría a scrollar
   para llegar al botón, y en un formulario de alta ese scroll es
   exactamente el punto en el que la gente se va. Con la columna de
   texto debajo, lo primero que se ve al llegar desde el menú es el
   formulario. */
@media (max-width: 860px) {
  .cuenta-grid {
    grid-template-columns: minmax(0, 1fr);
    gap: 2rem;
  }

  .cuenta-grid .cuenta-lado {
    order: 2;
  }

  .cuenta-grid .form-card {
    order: 1;
  }
}

/* La trampa para robots.

   `position: absolute` y no `display: none` a propósito. Con
   `display: none` el navegador NO rellena el campo al enviar
   formulario, y muchos bots lo buscan precisamente ahí para
   saltarse la trampa. Lo que se quiere es que exista, sea invisible
   y siga llegando vacío: si viene relleno, es un bot.

   Y sin `left: -9999px` fuera de pantalla, porque un lector de
   pantalla se lo saltaría y entonces el aviso al usuario real
   sería "este campo es obligatorio" sin ver dónde. */
.cuenta-trampa {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* ---------- Acceso y alta en la barra ---------- */

/* "Acceder" es texto plano, sin caja. Va justo al lado del botón
   primario para que se lea como un sitio donde pinchar y no como un
   botón más: quien ya es cliente no viene a pedir presupuesto. */
.header-acceso {
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--text-muted);
  text-decoration: none;
  white-space: nowrap;
  padding: 0.5rem 0.25rem;
  border-radius: 6px;
  transition: color 0.15s ease;
}

.header-acceso:hover,
.header-acceso:focus-visible {
  color: var(--text);
}

/* Los enlaces que en escritorio están en la barra y en móvil dentro
   del menú desplegado. Por eso se llaman distinto a las dos veces: lo
   que se ve en móvil no puede ser un enlace suelto del nav, que en
   escritorio lo escondería. */
.mobile-only-nav {
  display: none;
}

/* =========================================================
   BOT DE WHATSAPP
   =========================================================
   Dos columnas: a la izquierda lo que hace, a la derecha el chat.

   El reparto va 1fr/1fr y no 1,2/1 porque lo de la izquierda son
   cuatro tarjetas con texto largo y lo de la derecha es un móvil
   con poca altura de conversación. Intercambiarlos no cambia
   mucho, pero con el chat a la izquierda se leen primero los
   párrafos y la demo queda como una imagen al final; el chat
   primero es lo que hace que alguien pulse.
*/

.wa-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 2.5rem;
  align-items: start;
}

.wa-lado {
  display: grid;
  gap: 1rem;
}

.wa-lado-card {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 0.35rem 1.1rem;
  align-items: start;
}

.wa-lado-card .icon {
  grid-row: span 2;
  margin: 0;
}

.wa-lado-card h3 {
  margin: 0;
  font-size: var(--fs-lg);
}

.wa-lado-card p {
  margin: 0;
  color: var(--text-muted);
}

/* ---------- La demo ---------- */

.wa-demo {
  padding: 1.5rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg, 20px);
  background: var(--surface);
}

.wa-demo-cabecera {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 0.75rem;
}

.wa-demo-cabecera h3 {
  margin: 0;
}

/* El rótulo de "demostración".

   Va al lado del título y no dentro del chat, a propósito: dentro se
   lee como si fuera parte de la interfaz del producto —como un
   elemento más de WhatsApp— y de ahí es donde no se cuela. Al lado
   del título se lee como una aclaración de quien ha hecho la página.

   Con borde, no con relleno: un fondo de color dentro del área del
   chat parece una etiqueta del bot. */
.wa-demo-chap {
  padding: 0.2rem 0.55rem;
  border: 1px solid color-mix(in srgb, var(--warning) 45%, transparent);
  border-radius: 999px;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--warning);
  white-space: nowrap;
}

.wa-demo-aviso {
  margin: 0 0 1rem;
  padding: 0.7rem 0.85rem;
  border-left: 3px solid var(--warning);
  border-radius: 0 8px 8px 0;
  background: color-mix(in srgb, var(--warning) 9%, transparent);
  font-size: var(--fs-sm);
  color: var(--text-muted);
}

.wa-demo-pie {
  margin: 1rem 0 0;
  font-size: var(--fs-xs);
  color: var(--text-dim);
  text-align: center;
}

/* ---------- La conversación ---------- */

.wa-chat {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  height: 19rem;
  padding: 1rem;
  overflow-y: auto;
  border-radius: 12px;
  /* Un patrón muy tenue que se lee como el fondo con textura de
     WhatsApp sin copiarlo. Es un degradado con líneas, no una
     imagen: pesa cero. */
  background:
    repeating-linear-gradient(
      0deg,
      transparent,
      transparent 21px,
      color-mix(in srgb, var(--border) 22%, transparent) 21px,
      color-mix(in srgb, var(--border) 22%, transparent) 22px
    ),
    var(--bg-soft);
  scrollbar-width: thin;
}

/* La burbuja del bot a la izquierda y la del usuario a la derecha, que
   es como se lee una conversación de verdad y no como dos bloques
   centrados que podrían ser las dos del bot. */
.wa-msg {
  position: relative;
  max-width: 82%;
  padding: 0.55rem 0.75rem;
  border-radius: 12px;
  font-size: var(--fs-sm);
  line-height: 1.45;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.12);
}

.wa-msg--bot {
  align-self: flex-start;
  border-bottom-left-radius: 4px;
  background: var(--surface);
  border: 1px solid var(--border);
}

.wa-msg--user {
  align-self: flex-end;
  border-bottom-right-radius: 4px;
  background: color-mix(in srgb, var(--accent) 22%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
}

/* La hora va dentro de la burbuja y en su propia línea, en pequeño y
   atenuada. Fuera de la burbuja parece otra línea del chat. */
.wa-hora {
  display: block;
  margin-top: 0.15rem;
  font-size: 0.65rem;
  color: var(--text-dim);
  text-align: right;
}

/* ---------- Los botones de ejemplo ---------- */

.wa-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-top: 0.9rem;
}

.wa-chip {
  padding: 0.3rem 0.7rem;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: var(--bg-soft);
  color: var(--text);
  font-family: inherit;
  font-size: var(--fs-xs);
  cursor: pointer;
  transition: border-color 0.15s ease, color 0.15s ease;
}

.wa-chip:hover {
  border-color: var(--accent-2);
  color: var(--accent-2);
}

.wa-enviar {
  display: flex;
  gap: 0.5rem;
  margin-top: 0.7rem;
}

.wa-enviar input {
  flex: 1 1 auto;
  min-width: 0;
  padding: 0.55rem 0.85rem;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: var(--bg-soft);
  color: var(--text);
  font-family: inherit;
  font-size: var(--fs-sm);
}

.wa-enviar input:focus {
  outline: 2px solid var(--accent-2);
  outline-offset: 1px;
}

/* ---------- El cierre ---------- */

.wa-cta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  justify-content: center;
  margin-top: 2.5rem;
}

@media (max-width: 900px) {
  .wa-grid {
    grid-template-columns: minmax(0, 1fr);
  }

  /* En una columna el chat va primero: es lo que hay que tocar para
     entender el producto, y quien llega desde el botón de abajo
     acaba de leer que se le contesta solo. */
  .wa-demo {
    order: -1;
  }

  /* Menos alto en móvil: 19rem con el resto de la sección empuja la
     página hacia abajo y el chat queda por encima del todo. */
  .wa-chat {
    height: 15rem;
  }
}

/* =========================================================
   ENLACES ANCLA Y LA CABECERA FIJA
   =========================================================
   La cabecera es `position: sticky` y se queda arriba. Sin esto, al
   saltar a una sección por ancla el título queda DETRÁS de la
   cabecera: la sección aparece cortada justo por el texto que la
   identifica, y parece que la página está rota.

   No es un detalle de esta sección del bot: afecta a todos los
   `id` de la web (#servicios, #proyectos, #precios, #whatsapp).
   Por eso va aquí y no en la sección.

   `scroll-margin-top` es lo que hay que usar, y no un margen: mueve
   el punto de parada del scroll sin mover la caja del elemento, así
   que el resto del diseño no se entera. */
section[id],
[id] {
  scroll-margin-top: calc(var(--header-h) + 1.5rem);
}

/* El precio de los planes de mantenimiento.

   Antes cada uno llevaba `style="margin-top:1rem"` y
   `style="font-size:1.8rem"` escritos en su línea. Al ser tres
   bloques idénticos con tres estilos distintos, cambiar el tamaño
   de la cifra era editar tres sitios y era fácil olvidar uno: un
   plan salía más grande que los otros dos y no se veía por qué.

   Con los planes viniendo de datos, el estilo va en una clase. El
   `!important` está porque las reglas originales de `.price .amount`
   usan selector de clase y gana la última en escribirse; sin esto, el
   `font-size` inline seguiría mandando por orden de cascada. */
.price.precio-mensual {
  margin-top: 1rem;
}

.price.precio-mensual .amount {
  font-size: 1.8rem !important;
}
/* =========================================================
   WHATSAPP: QUE LA SECCION PAREZCA DE WHATSAPP
   =========================================================
   Esto estaba en violeta y cian, los colores de acento del
   sitio. Y el acento del sitio no dice nada: la mitad de las
   secciones de la portada son violeta y cian.

   El bot de WhatsApp es de lo que se vive, segun el propio
   partial, y la unica senal de que aqui hay un producto de
   WhatsApp era la palabra "WhatsApp" escrita en un <span>.
   Eso no se ve, se lee.

   ── LA MARCA, LITERAL ──

   Los tres verdes de WhatsApp, que son los de verdad:

     #25D366  el verde de la marca
     #128C7E  el teal
     #075E54  el teal oscuro

   ── POR QUE NO SE USA EL VERDE PARA ESCRIBIR ──

   Porque #25D366 sobre blanco da 1.98: no se lee. Es un color
   de relleno, no un color de tinta, y el error clasico de
   ponerlo de fondo con texto blanco encima es justo eso.

   La tinta la lleva #075E54, que sobre blanco da 7.67. Y en
   fondo oscuro el orden se invierte del todo: #075E54 sobre el
   fondo del sitio da 2.62, o sea invisible.

   De ahi que la tinta sea una variable y no un color fijo.
   Cada tema mide, se elige y se comprueba:

     tema oscuro    #07070d   #25D366   10.13
     tema colorido  #0a0416   #25D366   10.16
     tema claro     #f7f8fc   #075E54    7.23

   ── EL CHAT ──

   WhatsApp tiene dos paletas oficiales, la clara y la oscura, y
   esta usa la que toca en cada tema. No es una decision
   estetica: con el tema oscuro y el chat en blanco seria un
   recuadro blanco del tamano de un movil en mitad de una pagina
   negra, y con el tema claro al reves.

   Con las dos, lo que se ve es siempre un WhatsApp de verdad, y
   la pagina no se rompe. Comprobado el texto en los tres temas:
   el chat oscuro da 15.79 y el claro 13.99.
   ========================================================= */

/* ── Los tokens de la paleta de WhatsApp ──

   Estaban encerrados en `#whatsapp`, y el hero los necesita
   tambien: pinta un chat del mismo servicio. Con los tokens
   dentro del id, tenerlos en los dos sitios obligaba a copiar
   los ocho hex, que es la forma segura de que un dia cambien
   uno y no el otro.

   Aqui no hay selector. Las propiedades personalizadas se
   heredan, asi que `#whatsapp` sigue recibirlas sin que se haya
   tocado ni una de las reglas que las usa.

   La marca se usa tal cual, sin retocar: si el dia que WhatsApp
   cambia de verde hay que tocar cuatro lineas, es porque son
   cuatro usos y no cuarenta. */

/* ─────────────────────────────────────────────────────────
   LA PALETA DEL CHAT DE WHATSAPP
   ─────────────────────────────────────────────────────────
   Con un solo tema no hay a qué alternar, así que estos tokens
   son directamente los de WhatsApp en claro: el mismo #ece5dd de
   los chats de verdad, y no una versión aproximada.

   El `--wa-ink` (el verde que se pinta encima) es el oscuro de la
   marca, no el #25d366 de WhatsApp: el verde de la marca sobre un
   fondo casi blanco se lee, y el de WhatsApp se lava. */
:root {
  --wa-verde: #25d366;
  --wa-teal: #128c7e;
  --wa-oscuro: #075e54;
  --wa-ink: var(--wa-oscuro);

  /* El chat, en la paleta clara de WhatsApp. */
  --wa-papel: #ece5dd;
  --wa-burbuja: #ffffff;
  --wa-propia: #dcf8c6;
  --wa-texto: #111b21;
  /* El gris secundario de los chats.
     Oscurecido un poco: con el valor de WhatsApp daba 3,72:1
     sobre el papel claro, por debajo del 4,5:1 de texto normal. */
  --wa-tenue: #54666f;
  --wa-linea: rgba(0, 0, 0, 0.08);
  --wa-muesca: rgba(0, 0, 0, 0.05);
}

/* ── El fondo de la seccion ──

   Un lavado verde muy bajo. No para pintar la seccion de verde,
   que seria shouting, sino para que se separe del resto de la
   portada sin necesitar una linea que la recorte. Y con
   color-mix, no con un color plano: en el tema claro sale un
   verde casi gris y en el oscuro casi negro, que es lo que
   corresponde en cada uno. */

#whatsapp.section--soft {
  background: color-mix(in srgb, var(--wa-verde) 5%, var(--bg-soft));
}

/* ── El cintillo de arriba ──

   El texto "WhatsApp" del encabezado. Pasa a la tinta de marca,
   que en cada tema es el verde que se lee. Antes heredaba el
   acento violeta del sitio, igual que cualquier otra seccion. */

#whatsapp .eyebrow {
  color: var(--wa-ink);
}

/* Y el icono que va al lado. El logo de verdad, no un circulo
   verde cualquiera: es lo que hace que alguien que no lee la
   pagina diga "ah, esto es lo del WhatsApp" antes de llegar al
   parrafo. Lo pone el partial. */
#whatsapp .wa-logo {
  width: 1.05em;
  height: 1.05em;
  margin-right: 0.4em;
  vertical-align: -0.14em;
  fill: var(--wa-verde);
}

/* ── Los cuatro iconos de lo que hace ── */

#whatsapp .wa-lado-card .icon {
  color: var(--wa-verde);
  background: color-mix(in srgb, var(--wa-verde) 12%, transparent);
  border-color: color-mix(in srgb, var(--wa-verde) 28%, transparent);
}

#whatsapp .wa-lado-card h3 {
  color: var(--wa-ink);
}

/* ── La ventana de la demo ──

   El marco, no el contenido. Es la caja que hace que lo de
   dentro se lea como una aplicacion y no como un bloque de
   texto con margenes. */

#whatsapp .wa-demo {
  background: var(--wa-papel);
  border-color: var(--wa-linea);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.12);
}

/* La cabecera va en el teal de marca, con el titulo en blanco:
   7.67 de contraste. Es la franja que todo el mundo reconhece
   de un vistazo, y es la que hace que esto se lea como
   WhatsApp y no como un chat inventado. */

#whatsapp .wa-demo-cabecera {
  margin: -1.5rem -1.5rem 1rem;
  padding: 0.9rem 1.25rem;
  background: var(--wa-oscuro);
  border-radius: calc(var(--radius-lg, 20px) - 1px) calc(var(--radius-lg, 20px) - 1px) 0 0;
}

#whatsapp .wa-demo-cabecera h3 {
  color: #ffffff;
}

/* El rotulo de "Demostracion" sigue en ambar y con borde, y no
   se toca. El comentario que hay en el css original explica por
   que: un relleno de color dentro del area del chat parece una
   etiqueta del bot, y justo de ahi es de donde no se cuela que
   esto sea una demo. Sobre el teal se lee peor que antes, y esa
   es la parte que conviene que se lea peor. */
#whatsapp .wa-demo-chap {
  border-color: rgba(255, 193, 7, 0.65);
  color: #ffd54f;
}

/* ── El papel del chat ──

   La textura se mantiene: sigue siendo un degradado de lineas y
   pesa cero, que es lo que se buscaba cuando se puso. Lo que
   cambia es el tono, y ahora es el del papel real de WhatsApp en
   vez de un gris neutro que no significaba nada. */

#whatsapp .wa-chat {
  background:
    repeating-linear-gradient(
      0deg,
      transparent,
      transparent 21px,
      var(--wa-muesca) 21px,
      var(--wa-muesca) 22px
    ),
    var(--wa-papel);
}

/* ── Las burbujas ──
   Los colores son los de WhatsApp, no aproximaciones: la del bot
   blanca a la izquierda, la del usuario verde a la derecha. El
   radio Bajito en una esquina es el detalle que las hace leer
   como burbujas y no como parrafos con fondo. */

#whatsapp .wa-msg {
  color: var(--wa-texto);
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.13);
}

#whatsapp .wa-msg--bot {
  background: var(--wa-burbuja);
  border: 1px solid var(--wa-linea);
}

#whatsapp .wa-msg--user {
  background: var(--wa-propia);
  border: 1px solid transparent;
}

/* La hora va dentro de la burbuja, sobre su fondo, asi que el
   tono tenue se mide contra el de la burbuja y no contra el del
   papel. En oscuro da 4.69 y en claro 4.65. */

#whatsapp .wa-hora {
  color: var(--wa-tenue);
}

/* ── Los botones de ejemplo ──
   Las respuestas rapidas de WhatsApp: contorno verde, relleno
   ninguno. Con relleno seria otro boton mas y se perderian. */

#whatsapp .wa-chip {
  border-color: color-mix(in srgb, var(--wa-verde) 45%, transparent);
  background: transparent;
  color: var(--wa-ink);
}

#whatsapp .wa-chip:hover {
  border-color: var(--wa-verde);
  background: color-mix(in srgb, var(--wa-verde) 14%, transparent);
  color: var(--wa-ink);
}

/* ── El compositor ──
   El campo va en blanco con el texto de WhatsApp, porque es
   literalmente el sitio donde se escribe, y el boton de enviar
   en el teal oscuro con texto blanco: 7.67. Ponerlo en el verde
   de la marca con texto blanco habria sido lo obvio y habria
   sido ilegible. */

#whatsapp .wa-enviar {
  padding-top: 0.7rem;
  border-top: 1px solid var(--wa-linea);
}

#whatsapp .wa-enviar input {
  background: var(--wa-burbuja);
  border-color: var(--wa-linea);
  color: var(--wa-texto);
}

#whatsapp .wa-enviar input::placeholder {
  color: var(--wa-tenue);
}

#whatsapp .wa-enviar input:focus {
  outline-color: var(--wa-verde);
}

/* El boton de ENVIAR, que es distinto del CTA de abajo y se
   confundia con el. Este vivia dentro de la ventana de WhatsApp
   y seguia siendo el degradado violeta-cian del sitio, que es
   justo lo que Rompe la ilusion: un boton de enviar violeta en
   un chat de WhatsApp.

   Y aqui el color va al reves que en el CTA. Adentro del chat el
   fondo ya es oscuro, en los dos temas, porque la paleta del
   chat no depende del tema; entonces el texto oscuro sobre el
   verde de marca se mediria contra un fondo que ya no es blanco.
   Lo que se necesita es el verde sobre el oscuro, que da 7.21. */
#whatsapp .wa-enviar .btn-primary {
  background: var(--wa-verde);
  background-image: none;
  color: #0b2e1a;
  box-shadow: none;
}

#whatsapp .wa-enviar .btn-primary:hover,
#whatsapp .wa-enviar .btn-primary:focus-visible {
  background: color-mix(in srgb, var(--wa-verde) 88%, #ffffff);
  color: #0b2e1a;
}

/* ── Los botones de abajo ──
   El principal deja el degradado violeta-cian del sitio y se
   pone en el verde de marca, con texto casi negro: 7.46. El
   secundario se queda en el tema, porque si los dos fueran
   verdes no habria jerarquia y ademas "ver todos los servicios"
   no es unbot de WhatsApp. */

#whatsapp .wa-cta .btn-primary {
  background: var(--wa-verde);
  background-image: none;
  color: #0b2e1a;
  box-shadow: none;
}

#whatsapp .wa-cta .btn-primary:hover,
#whatsapp .wa-cta .btn-primary:focus-visible {
  background: color-mix(in srgb, var(--wa-verde) 88%, #ffffff);
  color: #0b2e1a;
}

/* En el tema claro el boton verde sobre fondo casi blanco queda
   justo por debajo del minimo de texto normal, asi que ahi se
   oscurece. Sigue siendo el mismo verde de familia, y gana el
   contraste. */
#whatsapp .wa-cta .btn-primary {
  background: var(--wa-oscuro);
  color: #ffffff;
}

#whatsapp .wa-cta .btn-primary:hover,
#whatsapp .wa-cta .btn-primary:focus-visible {
  background: color-mix(in srgb, var(--wa-oscuro) 88%, #000000);
  color: #ffffff;
}

/* =========================================================
   Shopcito — La portada
   ------------------------------------------------------------
   Todo lo de esta sección está debajo de `.hero--shopcito` o de
   un bloque propio, y NO usa los tokens de sección antigua.

   ── POR QUÉ ESTA SECCIÓN VA AL FINAL Y NO EN SU SITIO ──

   Porque el orden importa en CSS solo cuando hay Selectores del
   mismo peso. Lo de aquí son clases nuevas que antes no existían,
   así que da igual dónde se declaren.

   Lo que NO se hace, en cambio, es reciclar las clases de la web
   anterior (`.mock-window`, `.float-card`, `.orbit`) para la
   conversación: son la maqueta de un panel de rendimiento, con sus
   medidas pensadas para eso. Pintar un chat con ellas daría algo
   que parece un panel con un chat dentro, que es justo el mensaje
   equivocado: aquí no se vende un panel, se vende una conversación.

   ── LOS COLORES DEL CHAT ──

   Vienen de los tokens `--wa-*`, los mismos que usa la sección de
   WhatsApp. Ver la cabecera de ese bloque.
   ========================================================= */

/* ─────────────────────────────────────────────────────────
   EL LOGO EN LA CHAPA BLANCA
   ─────────────────────────────────────────────────────────
   El archivo es un JPEG con fondo casi blanco y el sitio tiene
   tres temas: tal cual, sobre el oscuro sería un rectángulo
   blanco en la barra de arriba.

   La chapa lo convierte en parte del logotipo en vez de un
   defecto. Es un PARCHE: en cuanto llegue el PNG con
   transparencia o el SVG, esto sobra. */
.brand-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* El fondo del logo NO es blanco: medido sobre sus esquinas va de
     #eff4ed a #f2f7f1, con #f0f5ee en el medio. Con la chapa en
     #ffffff se ve un borde alrededor del logo, que es el unico
     detalle que delata que el logo es un recorte pegado sobre otra
     cosa.

     Si se regenera el logo, hay que volver a medir este valor. El
     generador de la imagen de Open Graph lleva el hash del logo con el
     que se midio y avisa cuando ya no coincide. */
  background: #f0f5ee;
  border-radius: 10px;
  padding: 4px 7px;
  flex-shrink: 0;
  line-height: 0;
}

.brand-mark img {
  display: block;
  height: 26px;
  width: auto;
}

/* /* El logo mide 26px de alto y el nombre va en la tipografía del
   sistema a 1.15rem, que se ve un poco más alto. Ese par de píxeles
   de `translateY` es lo que hace que los dos se lean centrados en
   vez de cruzados. */*/
.brand-mark {
  transform: translateY(-1px);
}

/* ─────────────────────────────────────────────────────────
   EL HERO
   ─────────────────────────────────────────────────────────
   La variante reutiliza la maqueta de dos columnas que ya había
   (`.hero-layout`): texto a la izquierda, visual a la derecha. La
   maqueta es buena y no era el problema.

   Lo que cambia es el contenido y lo que se ve al entrar. */
.hero--shopcito .hero-note {
  color: var(--text-muted);
}

/* ── Las tres promesas ──
   Van en fila en escritorio y se apilan en móvil.

   El hueco entre ellas es de 1px de línea, no un marco: son tres
   datos de la misma familia y un borde alrededor de cada uno los
   convierte en tres cajas que compiten con el botón de arriba. */
.promise-row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  list-style: none;
  margin: 2.2rem 0 0;
  padding: 0;
  background: var(--border);
  border: 1px solid var(--border);
  border-radius: 14px;
  overflow: hidden;
}

.promise {
  display: flex;
  gap: 0.7rem;
  padding: 1rem 0.9rem;
  background: var(--surface);
  align-items: flex-start;
}

.promise-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  flex-shrink: 0;
  border-radius: 9px;
  background: var(--accent-bg, rgba(16, 185, 129, 0.12));
  color: var(--accent);
}

.promise-icon svg {
  width: 17px;
  height: 17px;
}

.promise strong {
  display: block;
  font-size: var(--fs-sm);
  line-height: 1.35;
  color: var(--text);
}

/* ".promise-detalle" y no ".promise span".

   El icono de la izquierda también es un <span> dentro de
   ".promise", así que ".promise span" lo alcanzaba y, por tener más
   especificidad que ".promise-icon", le ponía el color gris, el
   display:block y un margen. El icono salía apagado.

   Con clase propia, cada elemento se pinta lo que dice su nombre. */
.promise-detalle {
  display: block;
  font-size: var(--fs-xs);
  line-height: 1.4;
  color: var(--text-muted);
  margin-top: 0.2rem;
}

/* ─────────────────────────────────────────────────────────
   EL CHAT DEL HERO
   ─────────────────────────────────────────────────────────
   Una conversación de ejemplo, no una captura: no hay cliente real
   que pueda mostrarse todavía.

   Los colores son los de WhatsApp de verdad (`--wa-*`). Un chat con
   los verdes de la marca se leería como "esto es un dibujo nuestro";
   con los de WhatsApp se lee como "esto es lo que vas a ver". */
.wa-window {
  width: 100%;
  max-width: 360px;
  margin-left: auto;
  background: var(--wa-papel);
  border: 1px solid var(--wa-linea);
  border-radius: 16px;
  overflow: hidden;
  box-shadow: 0 30px 70px rgba(0, 0, 0, 0.35);
}

/* La cabecera del chat, con la barra de "escribiendo…" de fondo. */
.wa-bar {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  padding: 0.75rem 0.9rem;
  background: var(--wa-oscuro);
  color: #ffffff;
}

.wa-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--wa-verde);
  color: #ffffff;
  font-weight: 700;
  font-size: 0.95rem;
}

.wa-who strong {
  display: block;
  font-size: 0.9rem;
  line-height: 1.2;
}

.wa-who span {
  display: block;
  font-size: var(--fs-xs);
  color: rgba(255, 255, 255, 0.75);
  line-height: 1.3;
  margin-top: 0.1rem;
}

/* El "muesca" es el fondo con textura de punto que lleva WhatsApp
   detrás de los mensajes. Se hace con un radial muy tenue; con la
   imagen real pesa un poco más y aquí no vale la pena. */
.wa-body {
  padding: 0.9rem 0.8rem 0.4rem;
  background-image: radial-gradient(var(--wa-muesca) 1px, transparent 1px);
  background-size: 18px 18px;
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
  min-height: 340px;
}

.wa-time {
  font-size: 0.68rem;
  color: var(--wa-tenue);
}

/* La hora va centrada arriba del todo, como en WhatsApp. */
.wa-body > .wa-time {
  text-align: center;
  margin: 0 0 0.3rem;
}

.wa-bubble {
  position: relative;
  max-width: 82%;
  padding: 0.5rem 0.65rem 0.35rem;
  border-radius: 10px;
  background: var(--wa-burbuja);
  color: var(--wa-texto);
  font-size: 0.85rem;
  line-height: 1.4;
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.14);
}

/* La burbuja de la derecha es la PROPIA: verde, pegada al borde. */
.wa-bubble.wa-out {
  align-self: flex-end;
  background: var(--wa-propia);
}

/* El rabito de la burbuja. Se hace con dos triángulos ya que con
   `border-radius` solo se consigue media esquina: el rabito es
   una punta y con dos radios no sale. */
.wa-bubble::after {
  content: "";
  position: absolute;
  top: 0;
  width: 8px;
  height: 13px;
}

.wa-bubble.wa-in::after {
  left: -7px;
  background: var(--wa-burbuja);
  clip-path: polygon(100% 0, 100% 100%, 0 0);
}

.wa-bubble.wa-out::after {
  right: -7px;
  background: var(--wa-propia);
  clip-path: polygon(0 0, 100% 0, 0 100%);
}

.wa-bubble p {
  margin: 0;
}

.wa-bubble .wa-time {
  display: block;
  text-align: right;
  margin-top: 0.15rem;
}

/* ── La tarjeta de producto ──
   Es lo que el bot vende. Un chat con dos mensajes de texto y sin
   nada más demuestra que "responde", pero no que hay una tienda, y
   la tienda es la mitad de lo que se vende. */
.wa-card {
  align-self: flex-end;
  max-width: 82%;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  padding: 0.6rem 0.65rem;
  border-radius: 10px;
  background: var(--wa-burbuja);
  color: var(--wa-texto);
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.14);
  border-left: 3px solid var(--wa-verde);
}

.wa-card-tag {
  font-size: 0.62rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--wa-oscuro);
  font-weight: 600;
}

.wa-card strong {
  font-size: 0.85rem;
  line-height: 1.3;
}

.wa-card-stock {
  font-size: var(--fs-xs);
  color: var(--wa-tenue);
}

/* El texto del boton NO va en blanco.
   Blanco sobre el verde de WhatsApp da 1,98:1, muy por debajo
   del 4,5:1. Es lo que hace WhatsApp en su propia interfaz y es
   una de esas decisiones que se copian sin medir. Con un verde
   muy oscuro se lee a 6,25:1 y el boton sigue siendo verde. */
.wa-card-btn {
  margin-top: 0.4rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.4rem;
  border-radius: 7px;
  background: var(--wa-verde);
  color: #0b3d16;
  font-size: 0.78rem;
  font-weight: 600;
}

/* La barra de escribir. No hace nada: es parte del dibujo, no un
   formulario. Va con `aria-hidden` en la vista. */
.wa-input {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0.35rem 0.6rem 0.7rem;
  padding: 0.55rem 0.75rem;
  border-radius: 10px;
  background: var(--wa-burbuja);
  color: var(--wa-tenue);
  font-size: 0.82rem;
}

/* ─────────────────────────────────────────────────────────
   PROBLEMA VS. SOLUCIÓN
   ─────────────────────────────────────────────────────────
   Dos columnas. En móvil se apilan con el problema primero, y ese
   orden no es casual: es el orden en que se leen las dos frases. */
.duelo {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2.2rem;
  align-items: start;
}

.duelo-col h2 {
  font-size: var(--fs-h2);
  line-height: 1.15;
  margin: 0.6rem 0 0.9rem;
}

.duelo-col > p {
  color: var(--text-muted);
  line-height: 1.65;
  margin: 0 0 1.5rem;
}

.duelo-list,
.pasos-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.duelo-list li {
  display: flex;
  gap: 0.8rem;
  align-items: flex-start;
}

.duelo-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  flex-shrink: 0;
  border-radius: 10px;
}

.duelo-icon svg {
  width: 19px;
  height: 19px;
}

/* Los iconos del problema son de aviso y los de la solución no.
   Es lo que hace que la columna se lea de un vistazo sin leer: un
   ojo entrenado distingue "esto te duele" de "esto te pasa". */
.duelo-col--mal .duelo-icon {
  background: var(--warning-bg);
  color: var(--warning-text);
}

.duelo-col--bien .duelo-icon {
  background: var(--success-bg);
  color: var(--success-text);
}

.duelo-list strong,
.pasos-list strong {
  display: block;
  font-size: var(--fs-body);
  color: var(--text);
  line-height: 1.35;
}

.duelo-list span,
.pasos-list span {
  display: block;
  font-size: var(--fs-sm);
  color: var(--text-muted);
  line-height: 1.55;
  margin-top: 0.25rem;
}

/* Los pasos van numerados con un círculo de marca, no con la lista
   por defecto, y con una línea que los une. */
.pasos-list {
  position: relative;
  gap: 1.35rem;
}

.pasos-list li {
  display: flex;
  gap: 0.9rem;
  align-items: flex-start;
  position: relative;
}

/* La línea vertical que une los tres pasos. Va en el `<ol>` y no en
   cada `<li>` para que no haya que ocultarla en el último a mano y
   se pueda añadir un paso sin acordarse. */
.pasos-list::before {
  content: "";
  position: absolute;
  left: 15px;
  top: 34px;
  bottom: 18px;
  width: 2px;
  background: var(--border);
}

.paso-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--featured-bg);
  border: 1px solid var(--cta-border);
  color: var(--accent);
  font-size: 0.78rem;
  font-weight: 700;
  position: relative;
  z-index: 1;
}

/* ─────────────────────────────────────────────────────────
   EL PRECIO "A CONSULTAR"
   ─────────────────────────────────────────────────────────
   Sale más grande que una cifra, pero no del tamaño de un titular:
   si ocupa lo mismo que el precio de un plan, promete una cantidad
   que no existe.

   Y lleva el "a" en un tono atenuado para que se lea como una
   ausencia y no como un dato. */
.amount--consultar {
  font-size: clamp(1.5rem, 3vw, 2rem);
  color: var(--text-muted);
  letter-spacing: -0.01em;
}

/* Sin cifra, el "desde" y el símbolo sobrarían. El bloque entero se
   apaga un poco para que la atención caiga en la lista de lo que
   incluye, que es lo que el visitante puede leer. */
/* Los precios CON cifra van en --accent (#059669, 3,77:1), no en
   --brand (#10b981, 2,54:1). A 46 px es texto grande y solo
   necesita 3:1, y 2,54 no llega. */
.price-card .price:not(:has(.amount--consultar)) {
  color: var(--accent);
}

/* ─────────────────────────────────────────────────────────
   RESPONSIVE
   ───────────────────────────────────────────────────────── */
@media (max-width: 980px) {
  .promise-row {
    grid-template-columns: 1fr;
  }

  .duelo {
    grid-template-columns: 1fr;
    gap: 2.6rem;
  }
}

@media (max-width: 720px) {
  .wa-window {
    max-width: 100%;
    margin: 0 auto;
  }

  /* La maqueta del hero en una sola columna ya está tratada en
     `styles.css`. Lo que hace falta aquí es que el chat no se
     salga de lado: sin esto, a 360px de ancho la conversación
     empuja el scroll horizontal. */
  .wa-bubble,
  .wa-card {
    max-width: 88%;
  }
}

/* ─────────────────────────────────────────────────────────
   PREFERENCIA DE MOVIMIENTO
   ─────────────────────────────────────────────────────────
   El tilt del visual (`data-tilt` lo mueve `motion.js`) y las
   animaciones de entrada respectan esto ya en el resto del sitio.
   Aquí solo se recuerda que este bloque hereda ese comportamiento,
   por si alguien añade un `animation` nuevo debajo. */
@media (prefers-reduced-motion: reduce) {
  .wa-window {
    transition: none;
  }
}