/* ==========================================================================
   Vantage 5G
   Dirección de arte tomada de la plantilla Manufactt (Tailwind 4): blanco,
   titulares enormes en Mona Sans con una palabra en el naranja quemado de la
   casa, texto en Geist a 18px, esquinas RECTAS, retículas con filetes finos y
   secciones muy aireadas.

   Los tres gestos que hacen a esa plantilla reconocible, y que aquí se
   respetan: la insignia con un cuadradito de acento, el rótulo entre barras
   (// ASÍ //) y el botón oscuro con el cuadrado de acento a la derecha.
   ========================================================================== */

/* ------------------------------------------------------- 1. Tipografías -- */
/* Mona Sans (GitHub) y Geist (Vercel), las dos con licencia SIL OFL. Google
   las sirve como fuentes variables: un fichero por familia cubre todos los
   pesos, 69 KB los dos juntos. Las licencias van en assets/fonts. */
@font-face {
  font-family: "Mona Sans";
  src: url("../fonts/mona-sans-var.woff2") format("woff2");
  font-weight: 200 900; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Geist";
  src: url("../fonts/geist-var.woff2") format("woff2");
  font-weight: 100 900; font-style: normal; font-display: swap;
}

/* ----------------------------------------------------------- 2. Tokens --- */
:root {
  /* Los colores de la plantilla, medidos de su CSS y pasados de oklch a hex. */
  --accent:    #c8370b;   /* la palabra resaltada, los cuadrados, el botón */
  --ink:       #18181b;   /* titulares y bloques oscuros */
  --ink-soft:  #3f3f46;
  --body:      #52525b;   /* texto corrido de la plantilla: 7.0:1 sobre blanco */
  /* Rótulos pequeños. El zinc-500 de la plantilla (#71717a) da 4.83 sobre
     blanco pero solo 4.40 sobre la banda gris, y ahí es donde van la mitad de
     los rótulos. Un paso más oscuro: 6.04 y 5.49. */
  --muted:     #62626b;

  --surface:   #ffffff;
  --alt:       #f4f4f5;   /* banda alterna */
  --line:      #e4e4e7;
  --line-firm: #d4d4d8;

  /* Sobre el negro. */
  --on-ink:      #d4d4d8;
  --on-ink-soft: #a1a1aa;

  --head-font: "Mona Sans", "Helvetica Neue", Arial, sans-serif;
  --body-font: "Geist", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;

  --page: 82.5rem;        /* 1320px: la plantilla va ancha */
  --text: 44rem;
  --ease: cubic-bezier(.4, 0, .2, 1);
  /* Los dos de la plantilla, sacados de sus clases Tailwind:
     ease-[cubic-bezier(0.19,1,0.22,1)] (easeOutExpo) a 1.125s para el
     deslizamiento de los botones, y duration-500 para el zoom de las
     fotos. El desplazamiento es translate-y-7 / top-7 = 1.75rem. */
  --ease-desl: cubic-bezier(.19, 1, .22, 1);
  --dur-desl: 1.125s;
  --desl: 1.75rem;
}

/* ------------------------------------------------------------- 3. Base --- */
*, *::before, *::after { box-sizing: border-box; }

/* `[hidden]` lo pone el navegador con la especificidad más baja que hay, así
   que CUALQUIER clase que fije `display` lo anula. Pasó de verdad: `.form`
   lleva `display: grid`, `form.hidden = true` no ocultaba nada, y al enviar se
   quedaban el formulario y el botón con "Sending…" encima del panel de
   confirmación. Afectaba a los tres formularios del sitio. */
[hidden] { display: none !important; }

body {
  margin: 0;
  font-family: var(--body-font);
  font-size: 1.125rem;      /* 18px, como la plantilla */
  line-height: 1.6;
  color: var(--body);
  background: var(--surface);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

h1, h2, h3, h4 {
  margin: 0 0 .5em;
  font-family: var(--head-font);
  color: var(--ink);
  letter-spacing: -.02em;
  text-wrap: balance;
}
/* Interlineado corto en los tamaños grandes: es lo que da el aire compacto de
   la plantilla, donde el h1 ocupa dos líneas muy juntas. */
h1 { font-size: clamp(2.75rem, 6.2vw, 4.5rem); font-weight: 700; line-height: 1.04; }
h2 { font-size: clamp(2rem, 4.2vw, 3.4rem); font-weight: 600; line-height: 1.08; }
h3 { font-size: 1.375rem; font-weight: 600; line-height: 1.25; letter-spacing: -.015em; }
h4 { font-size: 1.0625rem; font-weight: 600; letter-spacing: -.01em; }

/* La palabra resaltada del titular. */
.hl { color: var(--accent); }

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

a { color: var(--accent); text-underline-offset: .2em; }
a:hover { color: var(--accent); }

:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }
img { max-width: 100%; height: auto; display: block; }

.wrap { width: 100%; max-width: var(--page); margin: 0 auto; padding: 0 1.75rem; }
.lede { font-size: 1.1875rem; color: var(--body); max-width: var(--text); }
.fine { font-size: .9375rem; line-height: 1.55; color: var(--muted); }
.actions { display: flex; flex-wrap: wrap; gap: .85rem; margin: 2.5rem 0 0; }

.skip { position: absolute; left: -9999px; }
.skip:focus {
  left: 1rem; top: 1rem; z-index: 200;
  background: var(--accent); color: #fff;
  padding: .75rem 1.25rem; font-weight: 600;
}

/* Dato provisional. Se ve en pantalla a propósito: si llega a producción, se
   nota. deploy.sh además cuenta las marcas y bloquea la publicación. */
[data-sample] {
  text-decoration: underline dotted rgba(200, 55, 11, .7);
  text-underline-offset: .22em;
}

/* --------------------------------------------- 4. Insignia y rótulos ----- */
/* Píldora con un cuadradito de acento: el arranque del hero en la plantilla. */
.badge {
  display: inline-flex; align-items: center; gap: .6rem;
  padding: .55rem 1rem;
  font-size: .875rem; color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line-firm);
  border-radius: 999px;      /* la única curva del sitio, igual que el original */
}
.badge::before {
  content: ""; width: .45rem; height: .45rem; flex: none;
  background: var(--accent);
}

/* Rótulo entre barras: // COMO ESTE // */
.eyebrow {
  display: block; margin: 0 0 1.25rem;
  font-size: .8125rem; font-weight: 500; letter-spacing: .12em;
  text-transform: uppercase; color: var(--muted);
}
.eyebrow::before { content: "// "; color: var(--accent); }
.eyebrow::after  { content: " //"; color: var(--accent); }
.band .eyebrow, .footer .eyebrow { color: var(--on-ink-soft); }

/* ---------------------------------------------------------- 5. Botones --- */
/* Bloque oscuro con el cuadrado de acento a la derecha. Sin redondear.

   El efecto de hover es el de la plantilla, calcado de su DOM: la etiqueta y
   la flecha van escritas DOS veces. Al pasar por encima, la primera copia se
   desplaza fuera de una caja con overflow:hidden y la segunda, que esperaba
   justo detrás del recorte, entra en su sitio. La etiqueta se mueve en
   vertical, la flecha en horizontal, las cuatro a la vez.

   Medido del original: 1.125s con cubic-bezier(.19,1,.22,1), desplazamiento
   de 1.75rem, e interlineado 1.3. El interlineado importa: con 1 el recorte
   corta los descendentes de la etiqueta ("coverage").

   El fondo NO cambia al pasar por encima; en la plantilla no hay ninguna
   regla que lo toque, el deslizamiento es todo el efecto. */
.btn {
  display: inline-flex; align-items: stretch; gap: 0;
  font-family: var(--head-font); font-size: 1rem; font-weight: 600;
  text-decoration: none; white-space: nowrap;
  color: #fff; background: var(--ink);
  border: 0; padding: 0; line-height: 1.3;
}
.btn__t {
  display: flex; align-items: center;
  padding: 1rem 1.5rem;             /* el relleno va en el texto, no en el enlace:
                                       así el cuadrado de la flecha llega a los
                                       bordes, que es lo que hace la plantilla */
}
.btn__i {
  display: flex; align-items: center; justify-content: center; flex: none;
  width: 3.25rem; background: var(--accent); font-style: normal;
  font-size: 1.1rem;
}

/* La caja que recorta, y las dos copias dentro. */
.btn__desl { position: relative; display: block; overflow: hidden; }
.btn__desl > span {
  display: block;
  transition: transform var(--dur-desl) var(--ease-desl),
              top      var(--dur-desl) var(--ease-desl),
              right    var(--dur-desl) var(--ease-desl);
}
.btn__desl > span + span { position: absolute; left: 0; top: var(--desl); }

.btn:hover  .btn__t .btn__desl > span:first-child,
.btn:focus-visible .btn__t .btn__desl > span:first-child { transform: translateY(calc(var(--desl) * -1)); }
.btn:hover  .btn__t .btn__desl > span + span,
.btn:focus-visible .btn__t .btn__desl > span + span { top: 0; }

/* La flecha: misma mecánica girada 90 grados. La copia que entra espera a la
   izquierda del recorte (right: 1.75rem) y llega a right: 0. */
.btn__i .btn__desl,
.btn__i .btn__desl > span { width: 1.5rem; text-align: center; }
.btn__i .btn__desl > span + span { top: 0; left: auto; right: var(--desl); }

.btn:hover  .btn__i .btn__desl > span:first-child,
.btn:focus-visible .btn__i .btn__desl > span:first-child { transform: translateX(var(--desl)); }
.btn:hover  .btn__i .btn__desl > span + span,
.btn:focus-visible .btn__i .btn__desl > span + span { right: 0; }

/* Variante clara, para usar sobre el bloque oscuro. */
.btn--light { color: var(--ink); background: #fff; }

/* Terciario: solo texto con una flecha. */
.btn--plain {
  background: none; color: var(--ink); padding: 0;
  border-bottom: 2px solid var(--accent);
}
.btn--plain > .btn__t { padding: .35rem 0; }
.btn--plain > .btn__i { width: auto; background: none; color: var(--accent); padding-left: .6rem; }
.btn--plain:hover { color: var(--accent); }

button.btn { cursor: pointer; }
button.btn[disabled] { opacity: .6; cursor: default; }

/* ------------------------------------------------------- 6. Cabecera ----- */
.masthead {
  position: sticky; top: 0; z-index: 100;
  background: rgba(255, 255, 255, .95);
  border-bottom: 1px solid var(--line);
  backdrop-filter: blur(10px);
}
.masthead__inner { display: flex; align-items: center; gap: 2rem; min-height: 5.25rem; }

.logo { display: inline-flex; align-items: center; gap: .7rem; text-decoration: none;
        margin-right: auto; color: var(--ink); }
.logo__mark { display: block; color: var(--accent); }
.logo__mark svg { width: 2rem; height: 2rem; display: block; }
.logo__name {
  font-family: var(--head-font); font-weight: 700; font-size: 1.5rem;
  letter-spacing: -.03em; text-transform: uppercase; line-height: 1;
}
.logo__name b { font-weight: 700; color: var(--accent); }

.masthead nav { display: flex; align-items: center; gap: 2.5rem; }
.masthead nav ul { display: flex; gap: 2rem; margin: 0; padding: 0; list-style: none; }
/* El cuadradito va EN FLUJO, no absoluto: en la plantilla es un <span> con
   me-1.25 dentro del enlace, así que reserva su sitio siempre y al pasar por
   encima sólo escala de 0 a 1. Nada se mueve. Medido: 7px y hueco de 5px. */
.masthead nav ul a {
  position: relative; display: flex; align-items: center; padding: .4rem 0;
  font-size: 1rem; color: var(--ink-soft); text-decoration: none;
  transition: color .2s var(--ease);
}
.masthead nav ul a::before {
  content: ""; flex: none;
  width: 7px; height: 7px; margin: 0 5px 2px 0; background: var(--accent);
  transform: scale(0); transition: transform .3s var(--ease);
}
.masthead nav ul a:hover { color: var(--accent); }
.masthead nav ul a:hover::before,
.masthead nav ul a[aria-current="page"]::before { transform: scale(1); }
.masthead nav ul a[aria-current="page"] { color: var(--ink); font-weight: 500; }

.menu-btn {
  display: none;
  font: 600 .875rem/1 var(--head-font); letter-spacing: .06em; text-transform: uppercase;
  color: #fff; background: var(--ink); border: 0; padding: .85rem 1.25rem; cursor: pointer;
}

/* ----------------------------------------------------------- 7. Hero ----- */
/* Retícula con filetes verticales, como la plantilla: el contenido a la
   izquierda y una columna estrecha a la derecha con el resumen y el botón. */
.hero { position: relative; padding: clamp(3.5rem, 8vw, 7rem) 0 0; }
/* Grano en el hero. SVG incrustado (feTurbulence), no un fichero. La plantilla
   NO lo trae —lo que parecía grano en sus capturas era compresión JPEG—, así
   que esto es añadido.

   Dos cosas que costaron encontrar:

   1. Con `saturate 0` el filtro devuelve un gris CLARO (luma 123-234) a media
      transparencia: el píxel más oscuro que llegaba a pintar sobre blanco era
      #F8F8F8, un 2.7% de modulación, invisible. La solución es una MÁSCARA
      NEGRA: la matriz pone RGB a cero y lleva la luminancia al alfa, así que se
      pinta negro con alfa variable y la opacidad del CSS sí manda.
   2. A igual amplitud, el grano GRUESO se percibe mucho más. baseFrequency
      bajó de .85 a .7.

   Calibrado midiendo los píxeles reales del filtro:

       opacidad   más oscuro   cuerpo   rótulos
         0.09      #ECECEC      6.54      5.11   (no se notaba)
         0.16      #E0E0E0      5.86      4.57
         0.20      #D8D8D8      5.42      4.24   <- aquí
         0.24      #D1D1D1      5.06      3.95

   A 0.20 el gris de rótulos --muted se queda en 4.24 y SUSPENDE, así que el
   hero redefine --muted a #565660 sólo para él: con ese tono da 5.09. El resto
   del sitio conserva la paleta que ya estaba medida y no se toca. */
.hero { --muted: #565660; }
.hero::before {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  opacity: .2;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.7' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .33 .33 .33 0 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
.hero > * { position: relative; z-index: 1; }
.hero__grid {
  display: grid; grid-template-columns: minmax(0, 1fr) 20rem;
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: start;
  padding-bottom: clamp(2.5rem, 5vw, 4rem);
}
.hero h1 { margin: 1.75rem 0 0; }
.hero__aside p { font-size: 1rem; }
.hero__aside .btn { margin-top: 1.75rem; width: 100%; }
.hero__aside .btn > :first-child { flex: 1; }

/* Pie del hero: tres datos pequeños separados por filetes. */
.hero__meta {
  display: grid; grid-template-columns: repeat(3, 1fr);
  border-top: 1px solid var(--line);
  font-size: .8125rem; letter-spacing: .06em; text-transform: uppercase;
  color: var(--muted);
}
.hero__meta span { padding: 1.25rem 0; }
.hero__meta span + span { border-left: 1px solid var(--line); padding-left: 1.5rem; }

/* Cabecera de las páginas interiores. */
.page-head { padding: clamp(2.5rem, 5vw, 4rem) 0 clamp(1.75rem, 3vw, 2.5rem);
             border-bottom: 1px solid var(--line); }
.page-head h1 { margin: 1.25rem 0 1rem; }

/* -------------------------------------------------------- 8. Secciones --- */
/* La plantilla respira mucho: 200px arriba y abajo en escritorio. */
/* La plantilla usa 200px arriba y abajo, pero sus secciones traen mucho más
   contenido que las nuestras: con el nuestro quedaban franjas vacías de casi
   300px entre una sección y la siguiente. Bajado a 84px máximo. */
.section { padding: clamp(2.75rem, 6vw, 5.25rem) 0; }
.section--alt { background: var(--alt); }
.section--tight { padding: clamp(2rem, 4vw, 3.25rem) 0; }
.section__head { max-width: 46rem; margin-bottom: clamp(1.75rem, 3.5vw, 2.75rem); }
.section__head h2 { margin-bottom: 1rem; }
.section__head--split {
  max-width: none; display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, .9fr);
  gap: clamp(1.5rem, 4vw, 4rem); align-items: end;
}

/* ------------------------------------------------- 9. Rejilla de fichas -- */
/* Filetes en vez de tarjetas: la plantilla separa con líneas, no con sombras. */
.tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
         border-top: 1px solid var(--line); }
.tile {
  padding: 2.5rem 2rem 2.5rem 0;
  border-bottom: 1px solid var(--line);
  transition: background-color .3s var(--ease);
}
.tile + .tile { border-left: 1px solid var(--line); padding-left: 2rem; }
/* Caja de icono. La misma en fichas y pasos, para que se lean como una
   familia. Cuadrada y sin redondear, como todo en esta plantilla. */
.tile__i, .step__i {
  display: grid; place-items: center; flex: none;
  width: 3.5rem; height: 3.5rem;
  color: var(--accent); background: rgba(200, 55, 11, .08);
  border: 1px solid rgba(200, 55, 11, .18);
}
.tile__i svg, .step__i svg { width: 1.6rem; height: 1.6rem; }
.tile__i { margin-bottom: 1.5rem; }
.tile h3 { margin-bottom: .6rem; }
.tile p { font-size: 1rem; margin: 0; }
.section--alt .tile { border-color: var(--line-firm); }

/* --------------------------------------------------- 10. Lista de pasos -- */
.steps { margin: 0; padding: 0; list-style: none; display: grid; gap: 0;
         border-top: 1px solid var(--line); }
.step {
  display: grid; grid-template-columns: 3.5rem minmax(0, 22rem) minmax(0, 1fr);
  gap: clamp(1rem, 3vw, 3rem); align-items: start;
  padding: 2.25rem 0; border-bottom: 1px solid var(--line);
}

.step h3 { margin: 0; }
.step p { margin: 0; font-size: 1rem; }

/* ------------------------------------------------------- 10b. Imágenes ---- */
/* Franja a sangre bajo el hero, como la de la plantilla. */
.banda-img { display: block; }
.banda-img img { width: 100%; height: clamp(16rem, 30vw, 27rem); object-fit: cover;
                 object-position: center 62%; }

/* Banda con el mapa de cobertura de fondo y el titular de la sección encima.
   El velo no es decorativo: sobre las zonas iluminadas del mapa el texto blanco
   se pierde, y el mapa tiene ciudades muy brillantes justo donde cae el
   titular. Medido sobre los píxeles reales de la imagen. */
/* El límite de ancho va en un div DENTRO de .wrap, no en el propio .wrap:
   .wrap lleva margin:0 auto, así que ponerle un max-width lo centraba y el
   texto arrancaba en 336px mientras el resto del sitio arranca en 44. */

/* Figura dentro de una columna. Sin redondear y sin sombra: aquí las imágenes
   se apoyan en el filete, no flotan. */
/* El zoom de la plantilla: duration-500 group-hover:scale-110 sobre una
   envoltura con overflow:hidden. Sin el recorte la foto se sale. */
.figura { margin: 2.5rem 0 0; border: 1px solid var(--line); overflow: hidden; }
.figura img { width: 100%; height: 100%; display: block; object-fit: cover;
              transition: transform .5s var(--ease); }
.figura:hover img, .caso__foto:hover img { transform: scale(1.1); }
/* Proporción fija: son fotos de distinto formato y sin esto cada columna
   quedaba de un alto. */
.figura { aspect-ratio: 3 / 2; }
/* Foto junto a texto. La columna de la imagen iba a 4/5 y medía 943px de alto
   contra 175 del texto: cinco veces más. Ahora es apaisada, las dos columnas
   se centran entre sí y el encuadre sube un poco para no cortar las antenas. */
.split--media { grid-template-columns: minmax(0, .92fr) minmax(0, 1.08fr);
                align-items: center; }
.figura--media { margin: 0; aspect-ratio: 4 / 3; }
.figura--media img { object-position: center 22%; }
@media (max-width: 54rem) { .figura--media { aspect-ratio: 3 / 2; } }

/* ------------------------------------------------------- 11. Bloque oscuro */
.band { background: var(--ink); color: var(--on-ink); padding: clamp(3rem, 6vw, 5rem) 0; }

/* Transición de blanco a naranja y de ahí al negro, que es lo que pidió el
   operador. Va de arriba abajo y la banda arranca justo debajo de una sección
   blanca, así que el borde superior desaparece.

   El texto NO puede caer en la franja naranja: blanco sobre #c8370b da 3.57 y
   suspende. Por eso el relleno superior es tan grande —la parte naranja queda
   vacía— y el contenido entra ya en la zona oscura. Medido, no estimado. */
.band--glow {
  background:
    repeating-linear-gradient(90deg,
      rgba(255, 255, 255, .06) 0 1px, transparent 1px 25%),
    linear-gradient(180deg,
      #ffffff 0%,
      #c8370b 14%,
      #8f2708 30%,
      #3a1409 46%,
      var(--ink) 60%);
  padding-top: clamp(6rem, 13vw, 10rem);
}
.band h2, .band h3 { color: #fff; }
.band p { color: var(--on-ink); }
.band__split { display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr);
               gap: 2.5rem; align-items: center; }
.band__split .actions { margin: 0; justify-content: flex-end; }

/* Cifras sobre el bloque oscuro. */
.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
         gap: 2rem; margin: 0; padding-top: 3rem; border-top: 1px solid rgba(255,255,255,.14); }
.stat__n { font-family: var(--head-font); font-size: clamp(2.25rem, 4vw, 3rem);
           font-weight: 700; line-height: 1; color: #fff; margin-bottom: .4rem; }
.stat dd { margin: 0; font-size: .9375rem; color: var(--on-ink-soft); }

/* La misma fila de cifras sobre fondo claro, para las páginas de servicio. */
.stats--light { border-top-color: var(--line); }
.stats--light .stat__n { color: var(--ink); }
.stats--light .stat dd { color: var(--muted); }

/* ------------------------------------------------------ 12. Acordeón ----- */
.faq { border-top: 1px solid var(--line); }
.faq details { border-bottom: 1px solid var(--line); }
.faq summary {
  display: flex; align-items: center; justify-content: space-between; gap: 1.5rem;
  padding: 1.6rem 0; cursor: pointer; list-style: none;
  font-family: var(--head-font); font-size: 1.1875rem; font-weight: 600;
  color: var(--ink);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: ""; flex: none; width: 1.5rem; height: 1.5rem;
  background: var(--accent);
  -webkit-mask: linear-gradient(#000 0 0) center/100% 2px no-repeat,
                linear-gradient(#000 0 0) center/2px 100% no-repeat;
          mask: linear-gradient(#000 0 0) center/100% 2px no-repeat,
                linear-gradient(#000 0 0) center/2px 100% no-repeat;
  transition: transform .25s var(--ease);
}
.faq details[open] summary::after { transform: rotate(45deg); }
.faq details > div { padding: 0 0 1.6rem; max-width: 52rem; font-size: 1rem; }

/* ---------------------------------------------------- 13. Dos columnas --- */
.split { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
         gap: clamp(2rem, 5vw, 4.5rem); align-items: start; }
.split > * { min-width: 0; }


.checks { margin: 0; padding: 0; list-style: none; display: grid; gap: 1.1rem; }
.checks li { position: relative; padding-left: 2.25rem; font-size: 1rem; }
.checks li::before {
  content: ""; position: absolute; left: 0; top: .45rem;
  width: .9rem; height: .9rem; background: var(--accent);
}

/* ------------------------------------------- 13b. Caso (de la plantilla) -- */
/* Copia de la sección "Real results from real projects" del original: insignia,
   titular con el texto de apoyo alineado ABAJO a su derecha, y una rejilla de
   cinco columnas donde el panel ocupa dos y la foto tres. Las medidas salen de
   su DOM: 20px de separación, radio 6px, 40px de relleno y la foto a 400px. */
.caso__cabecera {
  display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr);
  gap: clamp(1.5rem, 4vw, 3.25rem);
  align-items: end;                 /* items-end, igual que la plantilla */
  margin: 1.75rem 0 3rem;
}
.caso__cabecera h2 { margin: 0; }
.caso__cabecera .lede { margin: 0; }

.caso { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 1.25rem; }

.caso__panel {
  grid-column: span 2;
  display: flex; flex-direction: column; gap: 1.25rem;
  padding: 2.5rem; border-radius: 6px;
  /* El degradado del original: negro hasta la mitad y el acento oscurecido en
     la esquina superior derecha. */
  background: linear-gradient(to top right, #000 0%, #000 50%, #9e3211 100%);
  color: #e4e4e7;
}
.caso__panel h3 { color: #fff; font-size: 1.5rem; margin: 0; }
.caso__lista { margin: 0; padding: 0; list-style: none; display: grid; gap: .9rem; }
.caso__lista li { position: relative; padding-left: 1.6rem; font-size: .9375rem; line-height: 1.5; }
.caso__lista li::before {
  content: ""; position: absolute; left: 0; top: .45rem;
  width: .55rem; height: .55rem; background: #ff9468;
}
/* #ff9468 y no el naranja de marca: medido contra la esquina más clara del
   degradado (#9e3211), el acento da 2.79 y un gráfico necesita 3.0. En la
   práctica las viñetas caen sobre la mitad negra, pero así no depende de
   dónde acabe el degradado si alguien cambia el panel de tamaño. */
.caso__lista b { color: #fff; font-weight: 600; }

/* El pie se empuja abajo: así el botón queda alineado con el borde inferior
   aunque la lista sea corta, que es lo que hace el mt-auto del original. */
.caso__pie {
  margin-top: auto; display: flex; flex-wrap: wrap;
  align-items: flex-end; justify-content: space-between; gap: 1rem;
  padding-top: 1rem;
}
.caso__cifra { display: block; font-family: var(--head-font); font-weight: 700;
               font-size: 2.5rem; line-height: 1; color: #fff; }
.caso__etiqueta { display: block; margin-top: .35rem; font-size: .875rem; color: #d4d4d8; }

/* La proporción tiene que estar FIJADA aquí. Sin ella el <figure> no tiene
   altura definida, el `height:100%` de la imagen se resuelve como `auto`, y el
   alto del bloque acaba dictado por la proporción natural del fichero: con una
   foto apaisada salían 563px y con una vertical, 1126. Con aspect-ratio manda
   la maqueta y object-fit se encarga del recorte, venga la foto como venga. */
.caso__foto { grid-column: span 3; margin: 0; border-radius: 6px; overflow: hidden;
              aspect-ratio: 4 / 3; }
/* El encuadre importa: la foto del mástil es vertical y en un marco apaisado
   se recortaba a una franja de cielo con una antena al fondo. Subiendo el
   punto de interés al 35% entra el equipo y no el aire. El suelo baja de
   25rem a 20rem para que el bloque no arranque ya alto. */
.caso__foto img { width: 100%; height: 100%; min-height: 20rem; object-fit: cover;
                  object-position: center 35%; display: block;
                  transition: transform .5s var(--ease); }

@media (max-width: 68rem) {
  .caso__cabecera { grid-template-columns: 1fr; align-items: start; }
  .caso { grid-template-columns: 1fr; }
  .caso__panel, .caso__foto { grid-column: auto; }
  .caso__foto img { min-height: 18rem; }
}

/* --------------------------------------------------------- 14. Prosa ----- */
.prose { max-width: var(--text); }
.prose h2 { font-size: clamp(1.5rem, 2.6vw, 2rem); margin: 2.75rem 0 .85rem; }
.prose h2:first-child { margin-top: 0; }
.prose ul { margin: 0 0 1.15rem; padding-left: 1.2rem; }
.prose li { margin-bottom: .45rem; }

/* ----------------------------------------------------- 15. Formularios -- */
.form { display: grid; gap: 1.25rem; }
.form--boxed { padding: clamp(1.75rem, 3vw, 2.5rem); background: var(--surface);
               border: 1px solid var(--line-firm); }
.section--alt .form--boxed { border-color: var(--line-firm); }
.field { display: grid; gap: .4rem; }
.field label { font-family: var(--head-font); font-size: .9375rem; font-weight: 600; color: var(--ink); }
.req { color: var(--accent); }
.form input, .form select, .form textarea {
  font: inherit; font-size: 1rem; color: var(--ink);
  padding: .9rem 1rem; background: var(--surface);
  border: 1px solid var(--line-firm); border-radius: 0;
  transition: border-color .2s var(--ease);
  /* Los controles de formulario traen anchura intrínseca propia (un input
     number ronda las 20 columnas) y no encogen por debajo de ella dentro de una
     rejilla. Sin esto la calculadora desbordaba 9px a 390px. */
  width: 100%; min-width: 0;
}
.form textarea { resize: vertical; min-height: 8rem; }
.form input:focus, .form select:focus, .form textarea:focus { border-color: var(--accent); }

/* Casilla de consentimiento: el texto largo va al lado, no debajo. */
.check { display: grid; grid-template-columns: 1.25rem 1fr; gap: .85rem; align-items: start; }
.check input { width: 1.25rem; height: 1.25rem; margin: .2rem 0 0; accent-color: var(--accent); }
.check label { font-family: var(--body-font); font-weight: 400; font-size: .9375rem;
               line-height: 1.55; color: var(--body); }

/* Campo trampa: fuera de pantalla, nunca display:none, porque un bot que lee el
   DOM ignora lo oculto y rellena lo que no lo está. */
.trap { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.form__error { margin: 0; padding: .9rem 1rem; font-size: .9375rem; color: #7f1d1d;
               background: #fef2f2; border: 1px solid #fecaca; }
.form__done { padding: clamp(1.75rem, 3vw, 2.5rem); background: var(--surface);
              border: 1px solid var(--line-firm); }
.form__done h2 { font-size: clamp(1.5rem, 2.6vw, 2rem); margin-bottom: .85rem; }

.aside-card { padding: clamp(1.75rem, 3vw, 2.25rem); background: var(--ink); color: var(--on-ink); }
.aside-card h2 { color: #fff; font-size: 1.5rem; margin-bottom: .6rem; }
.aside-card h3 { color: #fff; font-size: 1.0625rem; margin: 1.75rem 0 .4rem; }
.aside-card p { color: var(--on-ink); font-size: 1rem; }
.aside-card a { color: #fff; }
.aside-card .fine { color: var(--on-ink-soft); }
.contact-list { margin: 1.75rem 0 0; display: grid; grid-template-columns: auto 1fr;
                gap: .65rem 1.5rem; }
.contact-list dt { font-family: var(--head-font); font-size: .75rem; font-weight: 600;
                   text-transform: uppercase; letter-spacing: .1em;
                   color: var(--on-ink-soft); padding-top: .2rem; }
.contact-list dd { margin: 0; font-size: 1rem; color: #fff; }
.aside-card [data-sample] { text-decoration-color: rgba(255, 160, 120, .85); }

/* ------------------------------------------------------------ 16. Pie ---- */
.footer { background: var(--ink); color: var(--on-ink); padding: clamp(3.5rem, 7vw, 5.5rem) 0 2rem; }
.footer a { color: var(--on-ink); text-decoration: none; }
.footer a:hover { color: #fff; text-decoration: underline; }
.footer__grid { display: grid; gap: 3rem; grid-template-columns: minmax(0, 1.7fr) repeat(3, minmax(0, 1fr)); }
.footer .logo { color: #fff; margin-right: 0; }
.footer .logo__mark { color: var(--accent); }
.footer__tagline { font-size: 1rem; max-width: 26rem; margin-top: 1.5rem; color: var(--on-ink); }
.footer__contact { margin: 1.5rem 0 0; padding: 0; list-style: none; display: grid; gap: .4rem; font-size: 1rem; }
.footer__col h2 { font-family: var(--head-font); font-size: .8125rem; font-weight: 600;
                  text-transform: uppercase; letter-spacing: .1em; color: #fff; margin-bottom: 1.25rem; }
.footer__col ul { margin: 0; padding: 0; list-style: none; display: grid; gap: .65rem; font-size: 1rem; }
.footer__disclaimer { margin: 3.5rem 0 0; padding-top: 2rem; max-width: 56rem; font-size: .9375rem;
                      color: var(--on-ink-soft); border-top: 1px solid rgba(255,255,255,.14); }
.footer__base { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 1rem;
                margin-top: 2.5rem; padding-top: 1.75rem;
                border-top: 1px solid rgba(255,255,255,.14); font-size: .875rem; }
.footer__base p { margin: 0; color: var(--on-ink-soft); }
.footer__fine { display: flex; gap: 1.5rem; flex-wrap: wrap; }
.footer [data-sample] { text-decoration-color: rgba(255, 160, 120, .85); }

/* ------------------------------------------- 16b. Fichas con fotografía --- */
/* Las "solution cards" de AllPower: foto arriba, título, una línea y la flecha.
   Enlazan a su propia página. Toda la ficha es el enlace, así que el área de
   pulsación es la tarjeta entera y no sólo el texto. */
.tarjetas { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1.25rem; margin: 0; }
.tarjetas--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.tarjeta {
  display: flex; flex-direction: column; text-decoration: none; color: inherit;
  border: 1px solid var(--line); background: #fff;
  transition: border-color .25s var(--ease);
}
.tarjeta:hover { border-color: var(--ink); color: inherit; }
.tarjeta__foto { aspect-ratio: 4 / 3; overflow: hidden; background: var(--alt); }
.tarjeta__foto img { width: 100%; height: 100%; object-fit: cover; display: block;
                     transition: transform .5s var(--ease); }
.tarjeta:hover .tarjeta__foto img { transform: scale(1.1); }
.tarjeta__cuerpo { padding: 1.75rem; display: flex; flex-direction: column; flex: 1; gap: .75rem; }
.tarjeta__cuerpo h3 { font-size: 1.25rem; margin: 0; }
.tarjeta__cuerpo p { margin: 0; font-size: 1rem; color: var(--body); }
/* El pie se pega abajo aunque un texto sea más corto que los otros: si no, las
   flechas de cuatro tarjetas acaban a cuatro alturas distintas. */
.tarjeta__pie { margin-top: auto; padding-top: .5rem; display: flex; align-items: center;
                gap: .5rem; font-family: var(--head-font); font-weight: 600; font-size: .9375rem;
                color: var(--ink); }
.tarjeta__pie i { font-style: normal; color: var(--accent);
                  transition: transform .25s var(--ease); }
.tarjeta:hover .tarjeta__pie i { transform: translateX(4px); }

/* ---------------------------------------------- 16c. Programas de ayuda --- */
/* Lista de programas con nombre. Cada uno lleva su etiqueta de a quién va
   dirigido, porque la mitad de las preguntas que llegan son "¿esto me vale a
   mí?" y la respuesta cabe en dos palabras. */
.programas { display: grid; gap: 0; margin: 0; padding: 0; list-style: none;
             border-top: 1px solid var(--line); }
.programa { border-bottom: 1px solid var(--line); padding: 2rem 0;
            display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.6fr); gap: 2.5rem; }
.programa__nombre { margin: 0; font-size: 1.25rem; }
.programa__quien { display: block; margin-top: .6rem; font-size: .8125rem; font-weight: 500;
                   letter-spacing: .1em; text-transform: uppercase; color: var(--muted); }
.programa p { margin: 0; font-size: 1rem; }

/* -------------------------------------------------- 16d. La calculadora --- */
.calc { border: 1px solid var(--line-firm); background: #fff; padding: clamp(1.75rem, 4vw, 2.75rem); }
.calc__campos { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.5rem; }
.calc__campos > .field--ancho { grid-column: 1 / -1; }
.calc__acciones { margin-top: 1.75rem; display: flex; align-items: center; gap: 1.25rem; flex-wrap: wrap; }
.calc__reiniciar { background: none; border: 0; padding: 0; cursor: pointer;
                   font: inherit; font-size: .9375rem; color: var(--muted);
                   text-decoration: underline; text-underline-offset: 3px; }
.calc__reiniciar:hover { color: var(--accent); }

.calc__salida { margin-top: 2rem; border-top: 1px solid var(--line); padding-top: 2rem; }
.calc__cifra { font-family: var(--head-font); font-weight: 700; line-height: 1;
               font-size: clamp(2.75rem, 7vw, 4rem); letter-spacing: -.03em; color: var(--ink); }
.calc__pie-cifra { display: block; margin-top: .6rem; font-size: .8125rem; font-weight: 500;
                   letter-spacing: .1em; text-transform: uppercase; color: var(--muted); }
.calc__lista { margin: 1.75rem 0 0; padding: 0; list-style: none; display: grid; gap: .9rem; }
.calc__lista li { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: .85rem;
                  align-items: start; font-size: 1rem; }
.calc__lista li::before { content: ""; width: .5rem; height: .5rem; margin-top: .45rem;
                          background: var(--accent); }
.calc__lista b { font-weight: 600; }
.calc__nota { margin: 1.75rem 0 0; font-size: .875rem; color: var(--muted); max-width: 46rem; }

/* ----------------------------------------------------- 16e. Testimonios --- */
.citas { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1.25rem; margin: 0; }
.cita { margin: 0; padding: 2rem; border: 1px solid var(--line); background: #fff;
        display: flex; flex-direction: column; gap: 1.25rem; }
.cita blockquote { margin: 0; font-size: 1.0625rem; color: var(--body); }
.cita figcaption { margin-top: auto; font-family: var(--head-font); font-weight: 600;
                   font-size: .9375rem; color: var(--ink); }
.cita figcaption span { display: block; font-weight: 400; font-size: .875rem; color: var(--muted); }

/* ---------------------------------------------------- 16f. Ficha lateral -- */
/* El bloque misión/visión/objetivo de la página "sobre nosotros". */
.hitos { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1.25rem; margin: 0; }
.hito { padding: 2rem; background: var(--alt); }
.hito h3 { font-size: 1.125rem; margin: 0 0 .75rem; }
.hito p { margin: 0; font-size: 1rem; }

@media (max-width: 68rem) {
  .tarjetas { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .citas, .hitos { grid-template-columns: 1fr; }
  .tarjetas--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 54rem) {
  .tarjetas, .tarjetas--3 { grid-template-columns: 1fr; }
  .programa { grid-template-columns: 1fr; gap: .9rem; }
  .calc__campos { grid-template-columns: 1fr; }
}

/* ------------------------------------------- 16g. Filas apiladas ---------- */
/* El patrón de "Scalable capabilities" de la plantilla: cada fila se queda
   pegada arriba a una altura distinta y la siguiente se le monta encima. La
   forma de la fila es la suya: icono, foto, titular grande y una lista de
   comprobación a la derecha.

   El desplazamiento de cada fila lo pone el generador con --i, porque cada una
   necesita un `top` distinto o se apilarían todas en el mismo sitio. El margen
   de 5.5rem es la cabecera pegajosa más un respiro. */
.apiladas { display: flex; flex-direction: column; margin: 0; padding: 0; list-style: none; }
.apilada {
  position: sticky;
  /* 5rem por fila es lo que mide la franja que queda visible cuando la
     siguiente se le monta encima: el relleno superior más la caja del
     número. Con menos, el titular se cortaba por la mitad. */
  top: calc(5.25rem + var(--i) * 5rem);
  background: #fff;
  border-top: 1px solid var(--line-firm);
}
.apilada__fila {
  display: grid;
  grid-template-columns: auto minmax(0, 15rem) minmax(0, 1.2fr) minmax(0, 1fr) auto;
  gap: 1.5rem; align-items: start; padding: 1.75rem 0;
}
.apilada__i { display: flex; flex: none; width: 3rem; height: 3rem; color: var(--accent); }
.apilada__i svg { width: 100%; height: 100%; }
.apilada__foto { margin: 0; aspect-ratio: 4 / 3; overflow: hidden; background: var(--alt); }
.apilada__foto img { width: 100%; height: 100%; object-fit: cover; display: block;
                     transition: transform .5s var(--ease); }
.apilada:hover .apilada__foto img { transform: scale(1.1); }
.apilada h3 { margin: 0; font-size: clamp(1.2rem, 1.9vw, 1.6rem); line-height: 1.15;
               padding-top: .35rem; }
.apilada__rotulo { display: block; margin: .35rem 0 .9rem; font-size: .8125rem; font-weight: 500;
                   letter-spacing: .1em; text-transform: uppercase; color: var(--muted); }
.apilada__lista { margin: 0; padding: 0; list-style: none; display: grid; gap: .6rem; }
.apilada__lista li { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: .7rem;
                     align-items: start; font-size: .9375rem; }
.apilada__lista li::before { content: ""; width: .5rem; height: .5rem; margin-top: .42rem;
                             background: var(--accent); }
.apilada__n { display: flex; flex: none; align-items: center; justify-content: center;
              width: 3.25rem; height: 3.25rem; background: var(--accent); color: #fff;
              font-family: var(--head-font); font-weight: 600; font-size: 1.1rem; }

/* ------------------------------------------------- 16h. Círculos de cifra -- */
/* La fila de círculos de la plantilla: alternan cifra y fotografía. Es lo que
   rompe la monotonía de una página hecha sólo de rectángulos. */
.circulos { display: flex; flex-wrap: wrap; justify-content: center; align-items: center;
            gap: 1.25rem; margin: 0; }
.circulo {
  width: clamp(15rem, 23vw, 24rem); aspect-ratio: 1; border-radius: 50%;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; padding: 2.5rem; margin: 0;
}
.circulo--claro  { background: #fff; border: 1px solid var(--line-firm); }
.circulo--oscuro { background: var(--ink); color: #fff; }
.circulo--foto   { padding: 0; overflow: hidden; background: var(--alt); }
.circulo--foto img { width: 100%; height: 100%; object-fit: cover; display: block; }
.circulo__rotulo { font-size: .8125rem; font-weight: 500; letter-spacing: .1em;
                   text-transform: uppercase; color: var(--accent); margin-bottom: 1rem; }
.circulo__n { font-family: var(--head-font); font-weight: 700; line-height: 1;
              font-size: clamp(2.25rem, 4vw, 3.25rem); letter-spacing: -.03em; }
.circulo--claro .circulo__n { color: var(--ink); }
.circulo p { margin: .9rem 0 0; font-size: .9375rem; max-width: 17rem; }
.circulo--oscuro p { color: var(--on-ink); }
.circulo--oscuro .circulo__rotulo { color: #ff9468; }

/* --------------------------------------------- 16i. Panel sobre fotografía -- */
/* El bloque de cristal de la plantilla. El velo es opaco a propósito: el panel
   tiene que leerse sea cual sea la foto de detrás, y un backdrop-filter que el
   navegador ignore no puede ser lo único que sostenga el contraste. */
.cristal-band { position: relative; padding: clamp(3rem, 6vw, 5rem) 0; background: #0a0a0c; }
.cristal-band > img { position: absolute; inset: 0; width: 100%; height: 100%;
                      object-fit: cover; opacity: .62; }
.cristal {
  position: relative; max-width: 46rem;
  background: rgba(12, 12, 14, .82);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  border: 1px solid rgba(255, 255, 255, .16); border-radius: 6px;
  padding: clamp(1.75rem, 4vw, 3rem); color: var(--on-ink);
}
.cristal h2 { color: #fff; margin: 0 0 1.5rem; font-size: clamp(1.5rem, 3vw, 2rem); }
.cristal .checks li { color: var(--on-ink); }
.cristal .checks li::before { background: var(--accent); }
.cristal .actions { margin: 1.75rem 0 0; }
/* El texto fino hereda --muted, y sobre el panel eso da 1.95 en el peor caso
   (una zona clara de la foto bajo el velo del 82%). Aquí va el gris claro:
   7.95 en ese mismo peor caso. Medido componiendo el velo, no a ojo. */
.cristal .fine { color: var(--on-ink); }

@media (max-width: 68rem) {
  .apilada__fila { grid-template-columns: auto minmax(0, 12rem) minmax(0, 1fr); }
  .apilada__lista-col { grid-column: 2 / -1; }
}
@media (max-width: 54rem) {
  /* Pegarlas en móvil deja la pantalla llena de cabeceras y sin contenido. */
  .apilada { position: static; }
  .apilada__fila { grid-template-columns: 1fr; gap: 1.1rem; }
  .apilada__lista-col { grid-column: auto; }
  .circulo { width: min(20rem, 82vw); }
}

/* ------------------------------------------- 16j. Banda hero con foto ------ */
/* Una sección entera sobre fotografía, con el fondo fijo para que haga
   parallax al desplazar. Se usa en el bloque de compromiso de la portada y como
   cabecera de la página de 5G.

   `background-attachment: fixed` es la forma sin JavaScript de conseguirlo, y
   tiene dos pegas conocidas: en iOS se comporta mal y con movimiento reducido
   no debería moverse nada. Las dos están contempladas más abajo. */
.foto-hero { position: relative; isolation: isolate; overflow: hidden;
             background: #0a1020; color: var(--on-ink);
             padding: clamp(3.5rem, 8vw, 6.5rem) 0; }
.foto-hero__fondo {
  position: absolute; inset: 0; z-index: -2;
  background-position: center; background-size: cover; background-repeat: no-repeat;
  background-attachment: fixed;
}
/* El velo. Denso a la izquierda, donde va el texto, y abierto a la derecha para
   que la fotografía se vea. Las paradas están medidas componiendo los píxeles
   reales de cada imagen, no a ojo. */
.foto-hero::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(90deg, rgba(6, 10, 20, .94) 0%, rgba(6, 10, 20, .90) 55%,
                              rgba(6, 10, 20, .62) 78%, rgba(6, 10, 20, .38) 100%);
}
.foto-hero__inner { max-width: 50rem; }
.foto-hero h1, .foto-hero h2 { color: #fff; margin: 0 0 1.25rem; }
.foto-hero .eyebrow { color: #ffb394; }
.foto-hero .eyebrow::before, .foto-hero .eyebrow::after { color: #ff9468; }
.foto-hero p { color: var(--on-ink); }
.foto-hero .lede { color: #fff; }
/* El resaltado del titular es el acento, y sobre el velo oscuro da 3.5:1.
   En un titular grande eso pasa justo, pero se queda sin margen si la foto
   cambia; el tono claro da holgura de sobra. */
.hl--claro { color: #ff8f5e; }
.foto-hero .actions { margin: 2rem 0 0; }

@media (max-width: 64rem) {
  /* iOS no soporta bien el fondo fijo: se ve a saltos o se recorta mal. */
  .foto-hero__fondo { background-attachment: scroll; }
}
@media (prefers-reduced-motion: reduce) {
  .foto-hero__fondo { background-attachment: scroll; }
}

/* --------------------------------------------- 16k. Tarjetas de producto --- */
/* Las fichas de producto de la plantilla: cuatro en fila, fondo oscuro, filete
   propio, y debajo de la descripción una tabla de especificaciones con las
   filas separadas por línea, etiqueta a la izquierda y valor a la derecha.
   Sustituyen a dos columnas de listas de comprobación, que era lo mismo cuatro
   veces y no se distinguía una categoría de otra. */
.productos { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1.5rem; margin: 0; }
.producto {
  background: var(--ink); border: 1px solid #3f3f46; border-radius: 4px;
  padding: 1.75rem 1.25rem; display: flex; flex-direction: column;
}
.producto h3 { color: #fff; font-size: 1.35rem; margin: 0 0 1.25rem; }
.producto__foto { margin: 0 0 1.5rem; border-radius: 6px; overflow: hidden;
                  aspect-ratio: 4 / 3; background: #27272a; }
.producto__foto img { width: 100%; height: 100%; object-fit: cover; display: block;
                      transition: transform .5s var(--ease); }
.producto:hover .producto__foto img { transform: scale(1.06); }
.producto > p { margin: 0 0 1.5rem; font-size: 1rem; color: var(--on-ink-soft); }
.producto__specs { margin-top: auto; }
.producto__spec {
  display: flex; align-items: baseline; justify-content: space-between; gap: 1rem;
  padding: .85rem 0; border-top: 1px solid #3f3f46;
}
.producto__spec dt { font-size: .875rem; color: var(--on-ink-soft); flex: none; }
.producto__spec dd { margin: 0; font-size: .875rem; color: #fff; text-align: right; }

@media (max-width: 68rem) { .productos { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 40rem) { .productos { grid-template-columns: 1fr; } }

/* ----------------------------------------------------- 17. Revelado ------ */
.reveal { opacity: 1; transform: none; }
html.js .reveal { opacity: 0; transform: translateY(22px);
                  transition: opacity .6s var(--ease), transform .6s var(--ease); }
html.js .reveal.is-in { opacity: 1; transform: none; }

/* --------------------------------------------------- 18. Responsive ------ */
@media (max-width: 68rem) {
  .hero__grid { grid-template-columns: 1fr; }
  .hero__aside { max-width: 34rem; }
  .section__head--split { grid-template-columns: 1fr; align-items: start; }
  .band__split { grid-template-columns: 1fr; }
  .band__split .actions { justify-content: flex-start; }
  .footer__grid { grid-template-columns: 1fr 1fr; }
  .footer__brand { grid-column: 1 / -1; }
  .step { grid-template-columns: 4rem minmax(0, 1fr); }
  .step p { grid-column: 2; }
}

@media (max-width: 54rem) {
  .menu-btn { display: block; }
  .masthead nav {
    display: none; position: absolute; left: 0; right: 0; top: 100%;
    flex-direction: column; align-items: stretch; gap: 1.25rem;
    padding: 1.5rem 1.75rem 2rem;
    background: #fff; border-bottom: 1px solid var(--line-firm);
  }
  .masthead nav.is-open { display: flex; }
  .masthead nav ul { flex-direction: column; gap: .35rem; }
  .masthead nav ul a { padding: .65rem 0; }
  .split, .tiles { grid-template-columns: 1fr; }
  .tile { padding: 2rem 0; }
  .tile + .tile { border-left: 0; padding-left: 0; }
  .hero__meta { grid-template-columns: 1fr; }
  .hero__meta span + span { border-left: 0; border-top: 1px solid var(--line); padding-left: 0; }
}

@media (max-width: 34rem) {
  .footer__grid { grid-template-columns: 1fr; }
  .actions .btn { width: 100%; }
  .actions .btn > :first-child { flex: 1; }
  .step { grid-template-columns: 1fr; gap: .5rem; }
  .step__n { font-size: 1.75rem; }
}

@media (prefers-reduced-motion: reduce) {
  html.js .reveal { opacity: 1; transform: none; transition: none; }
  * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}
