@font-face {
  font-family: 'Space Grotesk';
  src: url('/fuentes/space-grotesk-var.woff2') format('woff2-variations');
  font-weight: 400 700; font-display: swap; font-style: normal;
}
@font-face {
  font-family: 'Inter';
  src: url('/fuentes/inter-var.woff2') format('woff2-variations');
  font-weight: 400 700; font-display: swap; font-style: normal;
}

:root {
  color-scheme: dark light;
  --fondo: #0A0A0B;
  --fondo-elevado: #121214;
  --texto: #F4F4F0;
  --texto-suave: #A1A1A6;
  --acento: #C6F24E;
  --acento-texto: #0A0A0B;
  --acento-enlace: #C6F24E;
  --borde: rgba(244, 244, 240, .10);
  --radio: 14px;
  --fuente-titular: 'Space Grotesk', system-ui, sans-serif;
  --fuente-cuerpo: 'Inter', system-ui, sans-serif;
  --ancho: 1200px;
  --paso: clamp(1rem, 2.5vw, 1.5rem);
  --duracion: .6s;
  --curva: cubic-bezier(.22, 1, .36, 1);
}

@media (prefers-color-scheme: light) {
  :root:not([data-tema='oscuro']) {
    --fondo: #FBFBF9;
    --fondo-elevado: #FFFFFF;
    --texto: #0A0A0B;
    --texto-suave: #56565B;
    --borde: rgba(10, 10, 11, .12);
    /* El lima no alcanza 4,5:1 sobre blanco: como texto se usa la version oscura.
       Como relleno de boton sigue siendo --acento con --acento-texto encima. */
    --acento-enlace: #46610A;
  }
}
:root[data-tema='oscuro'] { color-scheme: dark; }

/* Tarea 17: transiciones de pagina nativas (View Transitions API). En los
   navegadores que no la soportan, la navegacion sigue siendo la normal de
   siempre -- no hay fallback que escribir. */
@view-transition { navigation: auto; }

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--fondo);
  color: var(--texto);
  font-family: var(--fuente-cuerpo);
  font-size: clamp(1rem, .96rem + .2vw, 1.0625rem);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}
img, svg, canvas { display: block; max-width: 100%; height: auto; }
a { color: var(--acento-enlace); }
:focus-visible { outline: 2px solid var(--acento-enlace); outline-offset: 3px; border-radius: 4px; }

h1, h2, h3, .display {
  font-family: var(--fuente-titular);
  font-weight: 600;
  line-height: 1.05;
  letter-spacing: -.02em;
  text-wrap: balance;
  margin: 0 0 .5em;
}
.display { font-size: clamp(2.5rem, 7vw, 5.25rem); letter-spacing: -.035em; }
h2 { font-size: clamp(1.75rem, 4vw, 3rem); }
h3 { font-size: clamp(1.15rem, 2vw, 1.5rem); }
.entradilla { font-size: clamp(1.05rem, 1.6vw, 1.3rem); color: var(--texto-suave); max-width: 62ch; text-wrap: pretty; }

.contenedor { width: min(100% - 2 * var(--paso), var(--ancho)); margin-inline: auto; }
/* Redisenho de portada (2026-09-27): el aire vertical estaba en 8rem por
   lado, o sea 256 px entre seccion y seccion a 1440 px. No se leia como
   elegancia sino como falta de contenido. El ritmo lo dan ahora las
   bandas oscuras (.banda-oscura), no el vacio. */
.seccion { padding-block: clamp(3rem, 6.5vw, 5.5rem); }
.visualmente-oculto {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important; animation-iteration-count: 1 !important;
    transition-duration: .01ms !important; scroll-behavior: auto !important;
  }
}

/* Tarea 4: componentes de interfaz (botones, tarjetas, formularios, etc.) */
/* Regla de "cero colores literales": son tokens de base.css o, cuando no fijan
   ningun color propio, las palabras clave transparent y currentColor. Ambas
   estan permitidas en todo el proyecto (ruling del coordinador). */

/* ---------- Salto de contenido ---------- */
.saltar {
  position: absolute;
  left: var(--paso);
  top: -4rem;
  z-index: 100;
  background: var(--fondo-elevado);
  color: var(--texto);
  border: 1px solid var(--borde);
  padding: .75em 1.25em;
  border-radius: var(--radio);
  text-decoration: none;
  transition: top .2s var(--curva);
}
.saltar:focus {
  top: var(--paso);
}

/* ---------- Cabecera ---------- */
.cabecera {
  position: sticky;
  top: 0;
  z-index: 50;
  border-bottom: 1px solid var(--borde);
}
/* El backdrop-filter vive en un pseudo-elemento, no en .cabecera: puesto
   directamente en .cabecera convertiria la cabecera en el containing block
   de sus descendientes position:fixed (como el panel #navegacion a pantalla
   completa), encogiendolo a la altura de la cabecera en vez de cubrir la
   pantalla entera. */
.cabecera::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: color-mix(in srgb, var(--fondo) 82%, transparent);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}
.cabecera__fila {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--paso);
  padding-block: 1rem;
}
.cabecera__marca {
  text-decoration: none;
}
.marca {
  font-family: var(--fuente-titular);
  font-weight: 700;
  font-size: 1.25rem;
  color: var(--texto);
}
.marca__punto {
  color: var(--acento-enlace);
}

.cabecera__menu {
  display: none;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  flex: none;
  background: transparent;
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  cursor: pointer;
}
.cabecera__icono {
  position: relative;
  display: block;
  width: 1.25rem;
  height: 2px;
  background: var(--texto);
  border-radius: 2px;
}
.cabecera__icono::before,
.cabecera__icono::after {
  content: '';
  position: absolute;
  left: 0;
  width: 1.25rem;
  height: 2px;
  background: var(--texto);
  border-radius: 2px;
}
.cabecera__icono::before { top: -6px; }
.cabecera__icono::after { top: 6px; }

/* ---------- Navegacion ---------- */
.navegacion__lista {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .75rem clamp(1rem, 2vw, 2rem);
  list-style: none;
  margin: 0;
  padding: 0;
}
.navegacion__lista a {
  text-decoration: none;
  color: var(--texto);
  font-weight: 500;
}
.navegacion__lista a:hover,
.navegacion__lista a:focus-visible {
  color: var(--acento-enlace);
}
.navegacion__lista a.boton {
  color: var(--acento-texto);
}

@media (max-width: 899px) {
  html.js .cabecera__menu {
    display: inline-flex;
  }
  html.js .navegacion {
    display: none;
    position: fixed;
    inset: 4.5rem 0 0 0;
    background: var(--fondo);
    overflow-y: auto;
    padding: var(--paso);
    border-top: 1px solid var(--borde);
  }
  html.js.menu-abierto .navegacion {
    display: block;
  }
  html.js .navegacion__lista {
    flex-direction: column;
    align-items: stretch;
    gap: 1.25rem;
  }
}

@media (min-width: 900px) {
  .navegacion__lista {
    flex-wrap: nowrap;
  }
}

/* ---------- Botones ---------- */
.boton {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5em;
  padding: .75em 1.5em;
  border-radius: var(--radio);
  border: 1px solid transparent;
  font-family: var(--fuente-cuerpo);
  font-weight: 600;
  font-size: 1rem;
  line-height: 1.2;
  text-decoration: none;
  cursor: pointer;
  transition: background-color .2s var(--curva), border-color .2s var(--curva), color .2s var(--curva), filter .2s var(--curva);
}
.boton--primario {
  background-color: var(--acento);
  color: var(--acento-texto);
  border-color: transparent;
}
.boton--primario:hover,
.boton--primario:focus-visible {
  filter: brightness(1.08);
}
.boton--fantasma {
  background-color: transparent;
  color: var(--texto);
  border-color: var(--borde);
}
.boton--fantasma:hover,
.boton--fantasma:focus-visible {
  color: var(--acento-enlace);
  border-color: var(--acento-enlace);
}

/* ---------- Tarjeta ---------- */
.tarjeta {
  background: var(--fondo-elevado);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  padding: var(--paso);
}

/* ---------- Rejilla ---------- */
.rejilla {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(clamp(260px, 30vw, 340px), 1fr));
  gap: var(--paso);
}

/* ---------- FAQ (details/summary nativos) ---------- */
.faq {
  border-top: 1px solid var(--borde);
}
.faq details {
  border-bottom: 1px solid var(--borde);
}
.faq summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--paso);
  padding-block: 1.25rem;
  cursor: pointer;
  font-family: var(--fuente-titular);
  font-weight: 600;
  color: var(--texto);
  list-style: none;
}
.faq summary::-webkit-details-marker {
  display: none;
}
.faq summary::marker {
  content: '';
}
.faq summary::after {
  content: '+';
  flex: none;
  font-size: 1.5rem;
  color: var(--acento-enlace);
  transition: transform .2s var(--curva);
}
.faq details[open] summary::after {
  transform: rotate(45deg);
}
.faq__respuesta {
  margin: 0;
  padding-bottom: 1.25rem;
  color: var(--texto-suave);
}

/* ---------- Cinta ---------- */
.cinta {
  background: var(--acento);
  color: var(--acento-texto);
  padding: var(--paso);
  border-radius: var(--radio);
  text-align: center;
  font-weight: 600;
}

/* ---------- Tabla de precios (Tarea 8) ---------- */
/* La tabla es la estructura real que un modelo extrae (<table> con
   <caption> y <th scope>). En uso normal, a 390px, las dos columnas caben
   sin desplazar nada: la primera se ajusta a varias lineas (el nombre del
   servicio NO lleva white-space: nowrap ni la tabla un min-width que fuerce
   su ancho) y la segunda es corta ("Desde 3.900 €"). El precio es lo que
   el visitante viene a ver en esta pagina; obligarlo a descubrir un scroll
   horizontal para leerlo seria perder visitas justo donde ya ha decidido
   que le interesa el dinero (correccion del coordinador, ronda 2).
   El contenedor .tabla-precios conserva overflow-x: auto como red de
   seguridad para pantallas muy estrechas o texto muy agrandado, nunca en
   el body, asi que la pagina en si nunca tiene scroll horizontal. Es
   alcanzable con teclado porque un contenedor con overflow y tabindex="0"
   entra en el orden de tabulacion nativo. */
.tabla-precios {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  border: 1px solid var(--borde);
  border-radius: var(--radio);
}
.tabla-precios:focus-visible {
  outline: 2px solid var(--acento-enlace);
  outline-offset: -2px;
}
.tabla-precios table {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
}
.tabla-precios caption {
  text-align: left;
  padding: var(--paso);
  font-weight: 600;
  color: var(--texto);
  border-bottom: 1px solid var(--borde);
}
.tabla-precios th,
.tabla-precios td {
  padding: .9rem var(--paso);
  text-align: left;
  border-bottom: 1px solid var(--borde);
}
.tabla-precios thead th {
  background: var(--fondo-elevado);
  color: var(--texto-suave);
  font-size: .85rem;
  text-transform: uppercase;
  letter-spacing: .03em;
}
.tabla-precios thead th:last-child {
  width: 52%;
}
.tabla-precios tbody th {
  font-weight: 600;
  color: var(--texto);
}
.tabla-precios tbody tr:last-child th,
.tabla-precios tbody tr:last-child td {
  border-bottom: none;
}
/* El importe ("Desde 390 €/mes") es corto e indivisible por definicion:
   partir la cifra de su moneda entre dos lineas se lee como un error. Aqui
   si es el sitio correcto para nowrap (al contrario que el nombre del
   servicio, que puede ocupar varias lineas sin problema): ver correccion
   del coordinador, ronda 3. */
.tabla-precios__importe {
  white-space: nowrap;
}

/* ---------- Etiqueta ---------- */
.etiqueta {
  display: inline-flex;
  align-items: center;
  gap: .35em;
  padding: .25em .85em;
  border: 1px solid var(--borde);
  border-radius: 999px;
  background: var(--fondo-elevado);
  color: var(--texto-suave);
  font-size: .85rem;
  font-weight: 500;
}

/* ---------- Heroe (Tarea 6) ---------- */
.heroe {
  padding-block: clamp(3rem, 8vw, 6rem);
}
.heroe__fila {
  display: grid;
  grid-template-columns: 1fr;
  align-items: center;
  gap: clamp(2rem, 5vw, 3.5rem);
}
.heroe__texto .etiqueta {
  margin-block: .75rem 1rem;
}
.heroe__acciones {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  margin-top: 1.75rem;
}
/* El contenedor de la escena reserva SIEMPRE la misma proporcion (4:3, la
   del heroe-reserva.webp provisional de la Tarea 6), para que el hueco no
   cambie de tamaño cuando la Tarea 18 monte el render 3D definitivo encima. */
.heroe__escena {
  position: relative;
  aspect-ratio: 1200 / 900;
  border-radius: var(--radio);
  overflow: hidden;
  background: var(--fondo-elevado);
  border: 1px solid var(--borde);
}
.heroe__escena img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* El canvas lo inserta escena-motor.js (Tarea 18) solo si la escena 3D
   monta con exito. Se superpone a la imagen de reserva (position:relative
   en el contenedor de arriba) en vez de apilarse debajo en el flujo normal
   -- si no, overflow:hidden lo recortaria entero y el hueco se veria vacio. */
.heroe__escena canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}
@media (min-width: 900px) {
  .heroe__fila {
    grid-template-columns: 1.05fr 1fr;
  }
}

/* ---------- Servicios y proyectos (Tarea 6) ---------- */
.servicios .rejilla,
.proyectos .rejilla {
  margin-top: clamp(1.5rem, 3vw, 2.5rem);
}
.tarjeta h3 {
  margin-bottom: .5rem;
}
.tarjeta__precio {
  font-weight: 600;
  color: var(--texto);
  margin: .75rem 0 1.25rem;
}
.servicios__nota {
  margin-top: 1.5rem;
  color: var(--texto-suave);
  font-size: .9rem;
}
.tarjeta--proyecto img {
  width: 100%;
  height: auto;
  border-radius: calc(var(--radio) - 6px);
  margin-bottom: 1rem;
}
.tarjeta--proyecto .boton {
  margin-top: .5rem;
}

/* ---------- Prueba social: contadores (Tarea 6) ---------- */
/* El numero va escrito en el HTML (data-contador="11" + "11" como texto):
   asi cualquiera que no ejecute JS (incluidos los rastreadores) lo lee. La
   Tarea 17 solo anima el numero que ya existe, no lo escribe. */
.contadores {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: clamp(2rem, 8vw, 6rem);
  text-align: center;
}
.contador__numero {
  font-family: var(--fuente-titular);
  font-weight: 700;
  font-size: clamp(3rem, 7vw, 4.5rem);
  line-height: 1;
  margin: 0;
  color: var(--acento-enlace);
}
.contador__etiqueta {
  margin: .5rem 0 0;
  color: var(--texto-suave);
}

/* ---------- Proceso (Tarea 6) ---------- */
.proceso__lista {
  list-style: none;
  margin: clamp(1.5rem, 3vw, 2.5rem) 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--paso);
  counter-reset: none;
}
.proceso__paso h3 {
  font-size: 1.15rem;
}
.proceso__paso p {
  color: var(--texto-suave);
  margin: 0;
}

/* ---------- CTA final (Tarea 6) ---------- */
.cta {
  border-top: 1px solid var(--borde);
}
.cta__caja {
  text-align: center;
  max-width: 62ch;
}
.cta__caja .entradilla {
  margin-inline: auto;
}
.cta__acciones {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 1rem;
  margin-top: 1.75rem;
}

/* ---------- Ficha de proyecto (Tarea 9) ---------- */
/* Escritorio y movil van uno junto al otro desde 700px; por debajo, en
   columna. El movil se limita en ancho (280px) para no dominar la fila junto
   a la captura de escritorio, mucho mas ancha. */
.ficha-proyecto__capturas {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: var(--paso);
  margin-block: clamp(1.5rem, 3vw, 2.5rem);
}
.ficha-proyecto__escritorio {
  flex: 2 1 420px;
  border-radius: var(--radio);
  border: 1px solid var(--borde);
}
.ficha-proyecto__movil {
  flex: 1 1 200px;
  max-width: 280px;
  border-radius: var(--radio);
  border: 1px solid var(--borde);
}
.ficha-proyecto__tecnologias {
  display: flex;
  flex-wrap: wrap;
  gap: .6rem;
  list-style: none;
  margin: 1rem 0 0;
  padding: 0;
}
.ficha-proyecto__tecnologias li {
  padding: .35em .9em;
  border: 1px solid var(--borde);
  border-radius: 999px;
  background: var(--fondo-elevado);
  color: var(--texto-suave);
  font-size: .9rem;
}

/* ---------- Rejilla de apps (Tarea 9) ---------- */
/* Cada app tiene un numero variable de capturas (APPS[].capturas;
   Visionarte tiene 2 y AniVerse 5). Las miniaturas se colocan en una fila flex que
   solo ocupa el ancho de las imagenes reales presentes -- nunca una rejilla
   de tres columnas fijas -- para que una tarjeta con 2 capturas no deje un
   hueco vacio donde iria la tercera. */
.tarjeta--app__capturas {
  display: flex;
  gap: .5rem;
  margin-bottom: 1rem;
}
.tarjeta--app__capturas img {
  border-radius: calc(var(--radio) - 8px);
  border: 1px solid var(--borde);
  width: auto;
  height: 9rem;
  /* Tarea 17, correccion: la proporcion 222/480 (ver comentario de la
     seccion "App insignia" mas abajo) se fuerza aqui en vez de dejar que
     el navegador la calcule a partir del archivo real. Sin esto, si una
     captura real no mide exactamente 222x480 px (ocurre con las de
     AniVerse), "width: auto" la ensancha mas de lo previsto y la fila de
     capturas se sale del viewport a 390px -- justo la restriccion de "sin
     scroll horizontal" que esta tarea tiene que respetar. */
  aspect-ratio: 222 / 480;
  object-fit: cover;
}
.tarjeta--app h3 {
  margin-bottom: .35rem;
}
.tarjeta--app p {
  color: var(--texto-suave);
  margin: 0 0 1rem;
}

/* ---------- App insignia (Tarea 15B) ---------- */
/* Bloque destacado de la app marcada `destacada: true` en APPS (hoy
   AniVerse): mas grande que una tarjeta normal de la rejilla, con sus
   capturas reales. Las cinco vistas de AniVerse se permiten envolver para
   conservar un ancho comodo y evitar desplazamiento horizontal en movil. */
.tarjeta--app-destacada {
  padding: clamp(1.5rem, 3vw, 2.5rem);
}
.tarjeta--app-destacada__medios {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 1.25rem;
  margin-bottom: 1.25rem;
}
.tarjeta--app-destacada__medios .tarjeta--app__capturas {
  margin-bottom: 0;
  flex-wrap: wrap;
}
.tarjeta--app-destacada__medios .tarjeta--app__capturas img {
  height: 13rem;
}
.tarjeta--app-destacada h3 {
  font-size: 1.4rem;
}
.tarjeta--app-destacada > p:last-child {
  font-size: 1.05rem;
}

/* ---------- Pie ---------- */
.pie {
  border-top: 1px solid var(--borde);
  padding-block: clamp(2.5rem, 6vw, 4rem);
  color: var(--texto-suave);
}
.pie__rejilla {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  /* Tarea 19: en movil (2 columnas de 160px+) la columna de contacto y la
     primera columna de enlaces quedan en filas casi alineadas; con
     column-gap = var(--paso) (16px en 412px de ancho) Lighthouse marca
     "target-size" porque el enlace mailto y el primer enlace de la columna
     vecina quedan a menos de 24px de distancia diagonal -- pasaba solo en
     ingles porque "Websites" (una linea) deja el primer <a> mas arriba que
     su equivalente espanol mas largo. Separacion horizontal minima de
     1.5rem (24px) para cumplir el objetivo de touch target sin tocar el
     espaciado vertical entre filas.
  */
  column-gap: max(var(--paso), 1.5rem);
  row-gap: var(--paso);
}
.pie__contacto {
  margin: .75rem 0 0;
  line-height: 1.8;
}
.pie__contacto a {
  color: var(--texto-suave);
}
.pie__contacto a:hover,
.pie__contacto a:focus-visible {
  color: var(--acento-enlace);
}
.pie__titulo {
  font-family: var(--fuente-cuerpo);
  font-size: 1rem;
  font-weight: 600;
  color: var(--texto);
  margin: 0 0 .75rem;
}
.pie__lista {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: .6rem;
}
.pie__lista a {
  color: var(--texto-suave);
  text-decoration: none;
}
.pie__lista a:hover,
.pie__lista a:focus-visible {
  color: var(--acento-enlace);
}
.pie__pie {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--paso);
  margin-top: clamp(2rem, 5vw, 3rem);
  padding-top: var(--paso);
  border-top: 1px solid var(--borde);
}
.pie__idiomas {
  display: flex;
  gap: .75rem;
  font-size: .85rem;
}
.pie__idiomas [aria-current] {
  color: var(--texto);
  font-weight: 600;
}
.pie__idioma-futuro {
  color: var(--texto-suave);
  opacity: .5;
}

/* ---------- Formulario de contacto (Tarea 11) ---------- */
.contenedor--estrecha {
  width: min(100% - 2 * var(--paso), 640px);
  margin-inline: auto;
}
.formulario {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}
.formulario__campo {
  display: flex;
  flex-direction: column;
  gap: .5rem;
}
.formulario__campo label {
  font-weight: 600;
  font-size: .95rem;
}
.formulario__opcional {
  font-weight: 400;
  color: var(--texto-suave);
}
.formulario__campo input,
.formulario__campo select,
.formulario__campo textarea {
  width: 100%;
  padding: .85em 1em;
  background: var(--fondo-elevado);
  color: var(--texto);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  font-family: var(--fuente-cuerpo);
  font-size: 1rem;
}
.formulario__campo textarea {
  resize: vertical;
  min-height: 8rem;
}
.formulario .boton {
  align-self: flex-start;
}
/* Honeypot antispam: oculto por CSS, nunca con type="hidden". Un bot
   rellena tanto los campos ocultos como los que estan fuera de pantalla
   por CSS, y detectar eso -- no un simple `display:none` -- es el punto:
   ver el comentario del honeypot en src/paginas/contacto.html. */
.trampa {
  position: absolute;
  left: -9999px;
  top: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}
.formulario__mensaje {
  padding: 1rem var(--paso);
  margin-bottom: 1rem;
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  background: var(--fondo-elevado);
  font-weight: 600;
}
.formulario__mensaje[hidden] {
  display: none;
}

/* ============================================================
   Redisenho de portada (2026-09-27)
   ------------------------------------------------------------
   Diagnostico que lo motiva: todo era blanco sobre blanco, sin
   ninguna banda que rompiera; el trabajo (capturas reales de tres
   proyectos y 32 pantallas de apps) se mostraba en miniatura; la
   rejilla de servicios dejaba una tarjeta huerfana en segunda fila;
   y las cifras flotaban en mitad de un hueco enorme.
   El impacto se busca con ESCALA, CONTRASTE y las imagenes reales,
   nunca con adornos ni con mas animacion.
   ============================================================ */

/* ---------- Banda oscura reutilizable ---------- */
/* Redefine los TOKENS en local en vez de repintar pieza a pieza: todo lo
   que cae dentro (botones, bordes, texto suave, el acento como enlace)
   se recalcula solo. Es tambien la razon de que el acento pueda usarse
   aqui como color de texto sin romper la regla del proyecto: sobre
   #0A0A0B el lima pasa de sobra el 4,5:1 que no alcanzaba sobre blanco. */
.banda-oscura {
  --fondo: #0A0A0B;
  --fondo-elevado: #17171A;
  --texto: #F4F4F0;
  --texto-suave: #A8A8AE;
  --borde: rgba(244, 244, 240, .14);
  --acento-enlace: #C6F24E;
  background: var(--fondo);
  color: var(--texto);
}

/* ---------- Heroe ---------- */
/* La escena 3D del heroe (Tarea 18) esta construida PARA fondo oscuro: el
   cuerpo de los dispositivos es 0x1c1c1f, casi negro, y la luz de contorno
   es el lima de marca. Sobre el fondo claro anterior esos cuerpos negros
   se leian como manchas y las pantallas no destacaban. No hace falta tocar
   el motor 3D: basta con darle el fondo para el que fue escrito. */
.heroe.banda-oscura {
  padding-block: clamp(2.5rem, 6vw, 4.5rem) clamp(3rem, 7vw, 5.5rem);
}
@media (min-width: 900px) {
  /* Antes 1.05fr 1fr: el texto se quedaba con la parte ancha y la escena,
     que es el argumento de venta, con la estrecha. Invertido. */
  .heroe__fila { grid-template-columns: 1fr 1.12fr; }
}

/* ---------- Servicios: 2x2 ---------- */
/* Son CUATRO servicios. La rejilla automatica metia tres arriba y dejaba
   el cuarto solo en una segunda fila, con aspecto de resto. Dos columnas
   exactas reparten 2+2. */
@media (min-width: 740px) {
  .servicios .rejilla { grid-template-columns: repeat(2, 1fr); }
}

/* ---------- Proyectos: una fila por proyecto ---------- */
/* Solo en la home (la pagina /proyectos/ usa `.seccion` a secas y conserva
   su rejilla de tres). Tres tarjetas identicas en fila mostraban las
   capturas a un tercio de ancho; en filas alternas se ven al doble. */
.proyectos .rejilla {
  grid-template-columns: 1fr;
  gap: clamp(1.25rem, 3vw, 2rem);
}
@media (min-width: 820px) {
  .proyectos .tarjeta--proyecto {
    display: grid;
    grid-template-columns: 1.35fr 1fr;
    gap: clamp(1.5rem, 3vw, 2.5rem);
    align-items: center;
    padding: clamp(1.25rem, 2.2vw, 1.75rem);
  }
  .proyectos .tarjeta--proyecto img { margin-bottom: 0; }
  /* Alterna el lado de la imagen para que tres filas seguidas no se lean
     como una lista repetida. */
  .proyectos .tarjeta--proyecto:nth-child(even) img { order: 2; }
}

/* ---------- Cifras ancladas ---------- */
/* Antes: dos numeros sueltos en mitad de un hueco de 256 px, sin nada que
   los sostuviera. Ahora son una banda oscura con su propio peso. */
.prueba-social.banda-oscura {
  padding-block: clamp(2.75rem, 5vw, 4rem);
}
.prueba-social.banda-oscura .contador__numero {
  font-size: clamp(3.5rem, 8vw, 5.5rem);
}

/* ---------- App insignia equilibrada ---------- */
/* Antes: una caja de 1200 px de ancho con las capturas apelotonadas a la
   izquierda y media caja vacia a la derecha. Medios a un lado, texto al
   otro, y las capturas mas grandes. */
@media (min-width: 860px) {
  .tarjeta--app-destacada {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: clamp(1.5rem, 3vw, 3rem);
    align-items: center;
  }
  .tarjeta--app-destacada__medios { margin-bottom: 0; }
  .tarjeta--app-destacada__medios .tarjeta--app__capturas img { height: 15rem; }
}
.tarjeta--app-destacada__texto > p:last-child {
  margin-bottom: 0;
}

/* ---------- Cabecera sobre el heroe oscuro ---------- */
/* La cabecera blanca sobre el heroe negro partia la pantalla en dos losas
   sin relacion. Se oscurece SOLO en las paginas que abren con banda oscura
   (hoy las dos portadas), sin tocar las otras 39. Si un navegador no
   soporta :has(), la cabecera se queda clara: sigue siendo legible, solo
   pierde la continuidad. */
body:has(.heroe.banda-oscura) .cabecera {
  --fondo: #0A0A0B;
  --fondo-elevado: #17171A;
  --texto: #F4F4F0;
  --texto-suave: #A8A8AE;
  --borde: rgba(244, 244, 240, .14);
  --acento-enlace: #C6F24E;
  color: var(--texto);
}

/* ---------- Proyectos en banda oscura ---------- */
/* Mismo motivo que el heroe: las capturas de MVPs, Visionarte, Foris e Isorga son
   interfaces oscuras y saturadas. Sobre blanco competian con el fondo;
   sobre negro se encienden. Ademas parte en dos el bloque blanco que
   ocupaba todo el centro de la pagina. */
.proyectos.banda-oscura .tarjeta--proyecto {
  background: var(--fondo-elevado);
}
@media (min-width: 820px) {
  /* La imagen ocupa el alto completo de la fila en vez de dejar aire
     arriba y abajo. */
  .proyectos .tarjeta--proyecto { align-items: stretch; }
  .proyectos .tarjeta--proyecto img {
    height: 100%;
    object-fit: cover;
    object-position: top center;
  }
  .proyectos .tarjeta--proyecto__texto { align-self: center; }
}

/* ---------- Cierre en oscuro, en las 41 paginas ---------- */
/* El CTA final es un parcial COMPARTIDO por todas las paginas, y se
   oscurece en todas a proposito: es el momento de conversion y cerraba en
   blanco, sin peso. Junto con la cabecera de pagina oscura de mas abajo,
   da a las 41 paginas el mismo arranque y el mismo cierre que la portada,
   que es lo que las hace parecer la misma web. */
.cta {
  --fondo: #0A0A0B;
  --fondo-elevado: #17171A;
  --texto: #F4F4F0;
  --texto-suave: #A8A8AE;
  --borde: rgba(244, 244, 240, .14);
  --acento-enlace: #C6F24E;
  background: var(--fondo);
  color: var(--texto);
  border-top: 0;
}

/* ---------- App insignia dentro del tramo oscuro ---------- */
/* Proyectos, apps y cifras forman UN solo tramo oscuro en vez de tres
   bandas alternas seguidas: el trabajo se ve de corrido y la pagina deja
   de parpadear entre claro y oscuro cada dos secciones. */
.app-insignia.banda-oscura .tarjeta--app-destacada {
  background: var(--fondo-elevado);
}
.app-insignia.banda-oscura,
.proyectos.banda-oscura + .app-insignia.banda-oscura {
  padding-top: 0;
}
.app-insignia.banda-oscura + .prueba-social.banda-oscura {
  padding-top: clamp(1rem, 2vw, 1.5rem);
}

/* ---------- Cabecera de pagina oscura en las interiores ---------- */
/* Las 39 paginas interiores abren con `<section class="seccion">` + un
   `h1.display`. Se les da el mismo arranque oscuro que la portada SIN
   tocar los 39 archivos: se seleccionan por su forma, no por una clase
   escrita a mano en cada uno. La portada no entra aqui porque su primera
   seccion es `.heroe`, no `.seccion`.
   Si un navegador no soporta :has(), la cabecera se queda clara: se pierde
   la continuidad visual, nunca la legibilidad. */
main > .seccion:first-child:has(h1.display) {
  --fondo: #0A0A0B;
  --fondo-elevado: #17171A;
  --texto: #F4F4F0;
  --texto-suave: #A8A8AE;
  --borde: rgba(244, 244, 240, .14);
  --acento-enlace: #C6F24E;
  background: var(--fondo);
  color: var(--texto);
  padding-block: clamp(2.5rem, 6vw, 4.5rem) clamp(2.5rem, 6vw, 4rem);
}
/* La cabecera fija tambien, mientras la pagina abra en oscuro.
   OJO: `:has()` NO puede anidarse dentro de otro `:has()`. Escrito como
   `body:has(main > .seccion:first-child:has(h1.display))` el selector es
   invalido, y un selector invalido dentro de una lista separada por comas
   tumba la regla ENTERA -- se llevaba por delante tambien la cabecera de
   la portada, que si funcionaba. Por eso se baja al hijo directo
   (`> .contenedor > h1.display`) en vez de anidar. */
body:has(main > .seccion:first-child > .contenedor > h1.display) .cabecera,
body:has(.heroe.banda-oscura) .cabecera {
  --fondo: #0A0A0B;
  --fondo-elevado: #17171A;
  --texto: #F4F4F0;
  --texto-suave: #A8A8AE;
  --borde: rgba(244, 244, 240, .14);
  --acento-enlace: #C6F24E;
  color: var(--texto);
}

/* Tarea 17: animaciones y transiciones, activas solo bajo html.js */

/* Estado inicial SOLO con JS activo. Sin .js, todo se ve en su sitio. */
.js [data-revelar] {
  opacity: 0;
  transform: translateY(24px);
}
.js [data-revelar].visible {
  opacity: 1;
  transform: none;
  transition: opacity var(--duracion) var(--curva), transform var(--duracion) var(--curva);
}

.js [data-revelar-lineas] .linea { display: block; overflow: hidden; }
.js [data-revelar-lineas] .linea > span {
  display: block;
  transform: translateY(100%);
  transition: transform .8s var(--curva);
}
.js [data-revelar-lineas].visible .linea > span { transform: none; }

/* La inclinacion 3D y el efecto magnetico no ocultan nada de partida: solo
   preparan la transicion suave del propio transform, que arranca en 0
   (sin desplazamiento) tanto con JS como sin el. Por eso viven fuera de
   .js sin romper la regla: no hay opacity:0 ni translate de estado inicial. */
[data-inclinar] { transform-style: preserve-3d; transition: transform .35s var(--curva); }
[data-magnetico] { transition: transform .25s var(--curva); }

::view-transition-old(root), ::view-transition-new(root) { animation-duration: .35s; }

@media (prefers-reduced-motion: reduce) {
  .js [data-revelar],
  .js [data-revelar-lineas] .linea > span {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  [data-inclinar], [data-magnetico] { transition: none !important; }
  ::view-transition-old(root), ::view-transition-new(root) { animation: none; }
}

/* Dirección visual 2026: estudio de producto digital, no plantilla corporativa. */
:root,
:root:not([data-tema='oscuro']) {
  color-scheme: dark;
  --fondo: #07080C;
  --fondo-elevado: #101218;
  --texto: #F7F8F2;
  --texto-suave: #9EA3AF;
  --acento: #C8FF43;
  --acento-texto: #090B0F;
  --acento-enlace: #C8FF43;
  --borde: rgba(255, 255, 255, .11);
  --radio: 22px;
  --ancho: 1240px;
  --cian: #58E8FF;
  --violeta: #8D75FF;
  --superficie: rgba(16, 18, 24, .78);
  --sombra: 0 30px 90px rgba(0, 0, 0, .38);
}

html { background: var(--fondo); overflow-x: clip; }
body {
  min-width: 320px;
  overflow-x: clip;
  background:
    radial-gradient(circle at 12% 8%, rgba(88, 232, 255, .08), transparent 24rem),
    radial-gradient(circle at 88% 4%, rgba(141, 117, 255, .10), transparent 28rem),
    var(--fondo);
  color: var(--texto);
}
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  opacity: .18;
  background-image:
    linear-gradient(rgba(255,255,255,.035) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.035) 1px, transparent 1px);
  background-size: 56px 56px;
  mask-image: linear-gradient(to bottom, black, transparent 72%);
}

::selection { background: var(--acento); color: var(--acento-texto); }
.contenedor { width: min(100% - clamp(2rem, 6vw, 5rem), var(--ancho)); }
.seccion { position: relative; padding-block: clamp(4.5rem, 8vw, 8rem); }
.seccion + .seccion { border-top: 1px solid rgba(255, 255, 255, .055); }
.display {
  font-size: clamp(3rem, 7.2vw, 6.7rem);
  font-weight: 650;
  line-height: .94;
  letter-spacing: -.065em;
}
h2 { font-size: clamp(2.1rem, 4.5vw, 4.4rem); letter-spacing: -.05em; }
h3 { letter-spacing: -.035em; }
.entradilla { color: var(--texto-suave); line-height: 1.65; }
.texto-gradiente {
  display: block;
  color: transparent;
  background: linear-gradient(100deg, var(--acento) 5%, var(--cian) 56%, #DCD5FF 98%);
  -webkit-background-clip: text;
  background-clip: text;
}

/* Navegación suspendida */
.cabecera {
  top: 0;
  border: 0;
  padding-top: .75rem;
  background: transparent;
}
.cabecera::before { display: none; }
.cabecera__fila {
  min-height: 64px;
  padding: .55rem .7rem .55rem 1.2rem;
  border: 1px solid var(--borde);
  border-radius: 18px;
  background: rgba(9, 10, 14, .78);
  box-shadow: 0 16px 55px rgba(0, 0, 0, .24);
  backdrop-filter: blur(22px) saturate(150%);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
}
.cabecera__marca,
.pie__logotipo { display: inline-flex; align-items: center; gap: .65rem; }
.marca__simbolo { width: 34px; height: 34px; flex: none; filter: drop-shadow(0 8px 18px rgba(88,232,255,.12)); }
.marca { font-size: 1.12rem; letter-spacing: -.045em; }
.navegacion__lista { gap: .5rem clamp(.7rem, 1.35vw, 1.25rem); }
.navegacion__lista a:not(.boton) {
  color: #C7CAD2;
  font-size: .83rem;
  letter-spacing: -.01em;
}
.navegacion__lista a:not(.boton):hover { color: var(--texto); }
.navegacion__lista .boton { padding: .72rem 1.15rem; font-size: .84rem; }

/* Botones de producto */
.boton {
  min-height: 48px;
  border-radius: 13px;
  padding: .82em 1.45em;
  transition: transform .2s var(--curva), box-shadow .2s var(--curva), border-color .2s var(--curva), background .2s var(--curva);
}
.boton--primario {
  background: linear-gradient(110deg, var(--acento), #A9FF7A);
  box-shadow: 0 10px 35px rgba(200, 255, 67, .16), inset 0 1px rgba(255,255,255,.45);
}
.boton--primario:hover { transform: translateY(-2px); box-shadow: 0 15px 42px rgba(200, 255, 67, .27); }
.boton--fantasma {
  background: rgba(255, 255, 255, .035);
  border-color: rgba(255, 255, 255, .14);
  backdrop-filter: blur(12px);
}
.boton--fantasma:hover { transform: translateY(-2px); background: rgba(255,255,255,.07); }
.boton--whatsapp::before {
  content: '↗';
  display: inline-grid;
  place-items: center;
  width: 1.35rem;
  height: 1.35rem;
  border-radius: 50%;
  background: var(--acento-texto);
  color: var(--acento);
  font-size: .82rem;
  font-weight: 800;
}

/* Hero y escaparate real */
.heroe.banda-oscura {
  min-height: min(920px, calc(100svh - 1rem));
  display: grid;
  align-items: center;
  overflow: hidden;
  padding-block: clamp(4rem, 8vw, 7.5rem);
  background:
    radial-gradient(circle at 73% 45%, rgba(88, 232, 255, .12), transparent 25rem),
    radial-gradient(circle at 90% 15%, rgba(141, 117, 255, .12), transparent 24rem),
    transparent;
}
.heroe.banda-oscura::before {
  content: '';
  position: absolute;
  width: 46rem;
  height: 46rem;
  right: -20rem;
  top: -25rem;
  border: 1px solid rgba(200, 255, 67, .13);
  border-radius: 50%;
  box-shadow: 0 0 0 8rem rgba(200, 255, 67, .018), 0 0 0 16rem rgba(88, 232, 255, .012);
}
.heroe__fila { position: relative; z-index: 1; gap: clamp(3rem, 6vw, 6rem); }
.heroe__texto { max-width: 660px; }
.heroe__texto .display { margin-bottom: .32em; }
.heroe__texto .entradilla { max-width: 58ch; }
.etiqueta {
  padding: .45rem .78rem;
  background: rgba(255, 255, 255, .045);
  border-color: rgba(255, 255, 255, .12);
  color: #C9CDD6;
  font-family: var(--fuente-titular);
  font-size: .72rem;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.etiqueta__pulso {
  width: .48rem;
  height: .48rem;
  border-radius: 50%;
  background: var(--acento);
  box-shadow: 0 0 0 5px rgba(200, 255, 67, .11), 0 0 18px var(--acento);
}
.heroe__acciones { margin-top: 2rem; }
.heroe__pruebas {
  display: flex;
  flex-wrap: wrap;
  gap: .8rem 1.2rem;
  margin-top: 2.1rem;
  padding-top: 1.25rem;
  border-top: 1px solid rgba(255,255,255,.09);
  color: #858B98;
  font-size: .78rem;
}
.heroe__pruebas strong { color: var(--texto); font-family: var(--fuente-titular); }

.heroe__escena.escaparate {
  min-height: 560px;
  aspect-ratio: auto;
  overflow: visible;
  border: 0;
  border-radius: 0;
  background: transparent;
  isolation: isolate;
  perspective: 1200px;
}
.escaparate__halo {
  position: absolute;
  inset: 8% 1% 2% 7%;
  z-index: -1;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(88,232,255,.16), rgba(141,117,255,.07) 42%, transparent 70%);
  filter: blur(18px);
}
.escaparate__navegador {
  position: absolute;
  top: 7%;
  left: 0;
  width: 91%;
  overflow: hidden;
  border: 1px solid rgba(255,255,255,.17);
  border-radius: 17px;
  background: #11131A;
  box-shadow: 0 45px 100px rgba(0,0,0,.55), 0 0 0 1px rgba(88,232,255,.05);
  transform: rotateY(-4deg) rotateX(1.5deg);
}
.escaparate__barra {
  height: 36px;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 0 .8rem;
  background: #171A22;
  border-bottom: 1px solid rgba(255,255,255,.08);
}
.escaparate__barra > span { width: 7px; height: 7px; border-radius: 50%; background: #3D424E; }
.escaparate__barra > span:first-child { background: #FF647C; }
.escaparate__barra > span:nth-child(2) { background: #FFC85A; }
.escaparate__barra > span:nth-child(3) { background: #C8FF43; }
.escaparate__barra code { margin-left: .55rem; color: #7F8694; font-size: .63rem; }
.escaparate__navegador img { width: 100%; height: auto; }
.escaparate__estado {
  position: absolute;
  right: .7rem;
  bottom: .7rem;
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  padding: .45rem .65rem;
  border: 1px solid rgba(255,255,255,.14);
  border-radius: 999px;
  color: #E8EADF;
  background: rgba(8,10,13,.8);
  backdrop-filter: blur(12px);
  font-size: .62rem;
  font-weight: 650;
}
.escaparate__estado i { width: 6px; height: 6px; border-radius: 50%; background: var(--acento); box-shadow: 0 0 12px var(--acento); }
.escaparate__movil {
  position: absolute;
  z-index: 3;
  right: 1%;
  bottom: 1%;
  width: 26%;
  padding: 5px;
  overflow: hidden;
  border: 1px solid rgba(255,255,255,.22);
  border-radius: 25px;
  background: #050609;
  box-shadow: 0 35px 80px rgba(0,0,0,.65), 0 0 45px rgba(141,117,255,.12);
  transform: rotateY(-8deg) rotateZ(2deg);
}
.escaparate__movil img { width: 100%; border-radius: 20px; }
.escaparate__isla { position: absolute; z-index: 2; top: 11px; left: 50%; width: 35%; height: 9px; transform: translateX(-50%); border-radius: 999px; background: #060608; }
.escaparate__terminal {
  position: absolute;
  z-index: 4;
  left: -3%;
  bottom: 4%;
  width: min(330px, 58%);
  padding: .9rem 1rem;
  border: 1px solid rgba(200,255,67,.2);
  border-radius: 13px;
  background: rgba(8,10,13,.9);
  box-shadow: 0 22px 55px rgba(0,0,0,.42);
  backdrop-filter: blur(18px);
  color: #BBC0CA;
  font: 500 .68rem/1.7 ui-monospace, SFMono-Regular, Menlo, monospace;
}
.escaparate__terminal span { color: var(--cian); }
.escaparate__terminal .terminal__ok { color: var(--acento); }
.escaparate__stack {
  position: absolute;
  z-index: 4;
  top: 0;
  right: 2%;
  display: flex;
  gap: .35rem;
}
.escaparate__stack span {
  padding: .35rem .55rem;
  border: 1px solid rgba(255,255,255,.12);
  border-radius: 999px;
  background: rgba(15,17,23,.82);
  color: #ADB2BE;
  font: 600 .58rem/1 var(--fuente-titular);
}

/* Superficies, servicios y contenido */
.tarjeta {
  position: relative;
  overflow: hidden;
  border-color: rgba(255,255,255,.1);
  background: linear-gradient(145deg, rgba(22,25,33,.9), rgba(11,13,18,.92));
  box-shadow: inset 0 1px rgba(255,255,255,.035);
}
.tarjeta::before {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(circle at 10% 0%, rgba(88,232,255,.07), transparent 32%);
}
.servicios { background: linear-gradient(180deg, rgba(255,255,255,.018), transparent); }
.servicios .tarjeta { min-height: 280px; padding: clamp(1.5rem, 3vw, 2.25rem); }
.servicios .tarjeta::after {
  position: absolute;
  top: 1.35rem;
  right: 1.5rem;
  color: rgba(255,255,255,.18);
  font: 650 2rem/1 var(--fuente-titular);
}
.servicios .tarjeta:nth-child(1)::after { content: '01'; }
.servicios .tarjeta:nth-child(2)::after { content: '02'; }
.servicios .tarjeta:nth-child(3)::after { content: '03'; }
.servicios .tarjeta:nth-child(4)::after { content: '04'; }
.servicios .tarjeta h3 { max-width: 75%; font-size: clamp(1.45rem, 2.2vw, 2rem); }
.servicios .tarjeta > p:not(.tarjeta__precio) { max-width: 42ch; color: var(--texto-suave); }
.servicios .tarjeta__precio { color: var(--acento); }
.servicios .tarjeta .boton { position: absolute; left: clamp(1.5rem, 3vw, 2.25rem); bottom: 1.7rem; }

.proyectos.banda-oscura,
.app-insignia.banda-oscura,
.prueba-social.banda-oscura { background: transparent; }
.proyectos .tarjeta--proyecto {
  border-radius: 28px;
  background: linear-gradient(135deg, #13161D, #0B0D12);
  box-shadow: var(--sombra);
}
.proyectos .tarjeta--proyecto img {
  border-radius: 17px;
  border: 1px solid rgba(255,255,255,.1);
  box-shadow: 0 25px 55px rgba(0,0,0,.28);
}
.tarjeta--proyecto__texto h3 { font-size: clamp(1.7rem, 3vw, 2.6rem); }
.tarjeta--proyecto__texto p { color: var(--texto-suave); }

.app-insignia .tarjeta--app-destacada { border-radius: 28px; }
.tarjeta--app__capturas img { border-radius: 13px; box-shadow: 0 15px 35px rgba(0,0,0,.28); }
.contador { min-width: 220px; padding: 1.7rem 2.2rem; border: 1px solid var(--borde); border-radius: 20px; background: rgba(255,255,255,.025); }
.contador__numero { color: var(--acento); text-shadow: 0 0 35px rgba(200,255,67,.2); }

.proceso__lista { position: relative; gap: 0; border: 1px solid var(--borde); border-radius: 22px; overflow: hidden; background: rgba(255,255,255,.018); }
.proceso__paso { min-height: 220px; padding: 1.7rem; border-right: 1px solid var(--borde); }
.proceso__paso:last-child { border-right: 0; }
.proceso__paso h3 { color: var(--texto); }

/* Interiores */
main > .seccion:first-child:has(h1.display) {
  position: relative;
  overflow: hidden;
  min-height: 440px;
  display: grid;
  align-items: center;
  background:
    radial-gradient(circle at 82% 30%, rgba(88,232,255,.11), transparent 22rem),
    radial-gradient(circle at 70% 0%, rgba(141,117,255,.1), transparent 25rem),
    transparent;
}
main > .seccion:first-child:has(h1.display)::after {
  content: '</>';
  position: absolute;
  right: max(5vw, calc((100vw - var(--ancho))/2));
  bottom: -2rem;
  color: rgba(255,255,255,.025);
  font: 700 clamp(9rem, 22vw, 20rem)/1 ui-monospace, monospace;
}
main > .seccion:first-child .contenedor { position: relative; z-index: 1; }
main > .seccion:first-child .display { max-width: 14ch; font-size: clamp(3rem, 7vw, 6.2rem); }

.ficha-proyecto__capturas { padding: clamp(1rem, 2vw, 1.5rem); border: 1px solid var(--borde); border-radius: 26px; background: rgba(255,255,255,.025); box-shadow: var(--sombra); }
.ficha-proyecto__escritorio,
.ficha-proyecto__movil { border-color: rgba(255,255,255,.13); box-shadow: 0 25px 60px rgba(0,0,0,.34); }
.ficha-proyecto__tecnologias li { color: #D5D8DF; background: rgba(255,255,255,.045); }

.tabla-precios { border-radius: 22px; background: rgba(255,255,255,.022); box-shadow: var(--sombra); }
.tabla-precios caption { padding: 1.5rem; }
.tabla-precios thead th { background: rgba(255,255,255,.045); color: #AEB3BE; }
.tabla-precios th, .tabla-precios td { padding: 1.25rem 1.5rem; }
.tabla-precios tbody tr { transition: background .2s ease; }
.tabla-precios tbody tr:hover { background: rgba(200,255,67,.04); }
.tabla-precios__importe { color: var(--acento); font-family: var(--fuente-titular); font-weight: 650; }

.formulario { padding: clamp(1.5rem, 4vw, 2.75rem); border: 1px solid var(--borde); border-radius: 24px; background: linear-gradient(145deg, rgba(22,25,33,.86), rgba(10,12,16,.9)); box-shadow: var(--sombra); }
.formulario__intro { margin-bottom: 2rem; }
.formulario__campo input,
.formulario__campo select,
.formulario__campo textarea { min-height: 52px; border-radius: 12px; background: rgba(255,255,255,.035); border-color: rgba(255,255,255,.12); }
.formulario__campo input:focus,
.formulario__campo select:focus,
.formulario__campo textarea:focus { outline: none; border-color: var(--cian); box-shadow: 0 0 0 3px rgba(88,232,255,.1); }

.faq { border-top-color: rgba(255,255,255,.12); }
.faq details { border-bottom-color: rgba(255,255,255,.1); }
.faq summary { padding-block: 1.55rem; font-size: clamp(1rem, 1.5vw, 1.18rem); }
.faq details[open] summary { color: var(--acento); }
.faq__respuesta { max-width: 74ch; }

/* Lectura editorial: líneas cortas, jerarquía clara y aire constante. */
.contenedor--articulo {
  width: min(100% - clamp(2rem, 6vw, 5rem), 860px);
}
.contenedor--articulo .display {
  max-width: 13ch;
  font-size: clamp(2.8rem, 6vw, 5.2rem);
}
.contenedor--articulo .articulo__meta,
.contenedor--articulo .articulo__fuente {
  color: var(--texto-suave);
  font-size: .86rem;
}
.contenedor--articulo h2 {
  margin-top: clamp(3rem, 7vw, 5rem);
  font-size: clamp(1.8rem, 4vw, 3.2rem);
}
.contenedor--articulo h3 { margin-top: 2.5rem; }
.contenedor--articulo p,
.contenedor--articulo li { color: #C8CBD3; }
.contenedor--articulo strong { color: var(--texto); }
.contenedor--articulo .tabla-precios { margin-block: 2rem 1rem; }

#articulos .tarjeta { min-height: 360px; padding: 1.5rem; }
#articulos .tarjeta h3 { font-size: clamp(1.3rem, 2.1vw, 1.8rem); }
#articulos .tarjeta h3 a { color: var(--texto); text-decoration: none; }
#articulos .tarjeta h3 a:hover { color: var(--acento); }
#articulos .tarjeta > p:not(.etiqueta) { color: var(--texto-suave); }
#articulos .tarjeta .boton { position: absolute; left: 1.5rem; bottom: 1.5rem; }

main > .seccion:not(:first-child) ul:not(.pie__lista):not(.ficha-proyecto__tecnologias),
main > article.seccion ul {
  max-width: 78ch;
  padding-left: 1.25rem;
}
main > .seccion:not(:first-child) li::marker,
main > article.seccion li::marker { color: var(--acento); }

.cta {
  position: relative;
  overflow: hidden;
  background: radial-gradient(circle at 50% 110%, rgba(200,255,67,.16), transparent 34rem), #090A0E;
}
.cta::before { content: ''; position: absolute; inset: 1.5rem; border: 1px solid rgba(255,255,255,.08); border-radius: 28px; pointer-events: none; }
.cta__caja { position: relative; z-index: 1; }
.pie { background: #050609; border-top-color: rgba(255,255,255,.08); }
.pie__logotipo .marca__simbolo { width: 38px; height: 38px; }
.pie__whatsapp { color: var(--acento) !important; font-weight: 700; text-decoration: none; }

/* Responsive */
@media (min-width: 900px) {
  .heroe__fila { grid-template-columns: minmax(0, .95fr) minmax(520px, 1.05fr); }
}
@media (max-width: 899px) {
  .cabecera { padding-top: .45rem; }
  .cabecera__fila { border-radius: 14px; }
  html.js .navegacion { inset: 0; padding: 6rem 1.5rem 2rem; background: rgba(7,8,12,.97); backdrop-filter: blur(25px); }
  html.js .navegacion__lista { font-size: 1.35rem; }
  .heroe.banda-oscura { min-height: auto; }
  .heroe__texto { max-width: none; }
  .heroe__escena.escaparate { min-height: min(520px, 125vw); }
  .escaparate__navegador { top: 5%; width: 94%; }
  .escaparate__movil { width: 29%; right: 0; bottom: 2%; }
  .escaparate__terminal { left: 0; bottom: 3%; }
  .escaparate__stack { right: 0; }
  .proceso__lista { grid-template-columns: 1fr 1fr; }
  .proceso__paso:nth-child(2) { border-right: 0; }
  .proceso__paso:nth-child(-n+2) { border-bottom: 1px solid var(--borde); }
}
@media (max-width: 620px) {
  .display { font-size: clamp(2.8rem, 14vw, 4.2rem); }
  .heroe__pruebas span:last-child { flex-basis: 100%; }
  .heroe__escena.escaparate { min-height: 430px; }
  .escaparate__barra code { display: none; }
  .escaparate__movil { width: 32%; bottom: 1%; }
  .escaparate__terminal { bottom: 2%; width: 66%; font-size: .58rem; }
  .escaparate__stack { top: -1%; }
  .escaparate__stack span:nth-child(2), .escaparate__stack span:nth-child(3) { display: none; }
  .servicios .tarjeta { min-height: 260px; }
  .proceso__lista { grid-template-columns: 1fr; }
  .proceso__paso { min-height: 0; border-right: 0; border-bottom: 1px solid var(--borde); }
  .proceso__paso:last-child { border-bottom: 0; }
  .contador { min-width: min(100%, 280px); }
  .cta::before { inset: .75rem; }
}

@media (prefers-reduced-motion: no-preference) {
  .escaparate__movil { animation: flotar-movil 6s ease-in-out infinite; }
  .escaparate__terminal { animation: flotar-terminal 7s ease-in-out infinite; }
  .etiqueta__pulso { animation: pulso 2.2s ease-out infinite; }
}
@keyframes flotar-movil { 0%,100% { translate: 0 0; } 50% { translate: 0 -9px; } }
@keyframes flotar-terminal { 0%,100% { translate: 0 0; } 50% { translate: 5px -6px; } }
@keyframes pulso { 0%,100% { box-shadow: 0 0 0 4px rgba(200,255,67,.11), 0 0 14px var(--acento); } 50% { box-shadow: 0 0 0 8px rgba(200,255,67,0), 0 0 24px var(--acento); } }
