@charset "UTF-8";
/* ==========================================================================
   MELI SERVICES GROUP — Sistema de diseño
   --------------------------------------------------------------------------
   DOS FUENTES, Y NINGUNA ES UNA OPINIÓN PROPIA:

   1) El documento del cliente (LINEAMIENTOS_WEB_MELI_SERVICES_GROUP):
        "La imagino oscura, técnica y premium.
         AZUL OSCURO + NEGRO/GRAFITO + BLANCO.
         Fotografía de obra real a pantalla completa. Tipografía grande.
         Muy poco texto por pantalla. Animaciones sutiles.
         Planos/detalles técnicos utilizados como elementos gráficos.
         Nada de plantillas típicas de construcción."

      → La paleta es EXACTAMENTE esa. Azul marino, grafito, blanco y un azul
        brillante para el énfasis. No hay un quinto color, y en particular
        no hay naranja: el color de señal de este sitio es azul.

   2) La referencia visual que dio el cliente (liquidrubberpanama.com).
      De ahí salen cuatro recursos concretos, que se usan en todo el sitio:

        · TITULAR EN MAYÚSCULAS A DOS TONOS. Las primeras líneas en el color
          base y la línea de énfasis en azul brillante. Es la firma visual.
        · DOBLE FILETE bajo el titular: dos barras cortas, una oscura y una
          celeste, una al lado de la otra.
        · EYEBROW con guion delante: "— Servicios", en azul y versalitas.
        · TARJETA DE SERVICIO = fotografía a sangre con un NÚMERO ENORME
          (01–08) y el nombre encima. No es una tarjeta con icono.

   Mobile first. Puntos de quiebre: 640 / 900 / 1024 / 1280.
   ========================================================================== */

/* --- 1. Tokens ---------------------------------------------------------- */
:root {
  /* ── Azul oscuro — el color de la marca, domina el sitio ── */
  --navy-950: #060F1C;
  --navy-900: #0A1A2F;
  --navy-800: #0F2440;
  --navy-700: #143054;
  --navy-600: #1B3F6B;
  --navy-400: #38618F;

  /* ── Negro / grafito — el segundo plano del documento ── */
  --ink:      #05070A;
  --graphite: #0C1117;
  --graphite-hi: #131A23;

  /* ── Azul brillante — el énfasis. El único color de señal ── */
  --blue:     #2E7DE0;
  --blue-600: #1F63BC;
  --blue-400: #5AA0EE;
  --blue-200: #A8CBF5;
  --blue-050: #E8F1FC;
  --blue-dim: rgba(46, 125, 224, .14);

  /* ── Blanco y grises claros ── */
  --white:    #FFFFFF;
  --gray-050: #F5F7FA;
  --gray-100: #E9EEF4;
  --gray-200: #D5DEE8;
  --gray-400: #8B9AAC;

  /* ── Texto, por fondo ── */
  --on-dark:       #EAF0F7;
  --on-dark-soft:  #9DB0C6;
  --on-dark-dim:   #6B7F98;
  --on-light:      #0A1A2F;
  --on-light-soft: #4A5C73;

  /* ── Bordes ── */
  --line-dark:  #1A2C43;
  --line-dark-hi: #26405C;
  --line-light: #DEE5EE;

  /* ── Estados ── */
  --ok:      #1E9E63;
  --ok-dim:  rgba(30, 158, 99, .12);
  --warn:    #B7801A;
  --warn-dim:rgba(214, 158, 46, .14);
  --err:     #D6454A;
  --err-dim: rgba(214, 69, 74, .14);

  /* ── Tipografía ──────────────────────────────────────────────────────
     Chivo para los titulares. Antes había Poppins, y ese fue el problema:
     Poppins es la misma geométrica de círculo perfecto que usa la
     referencia (liquidrubberpanama.com), así que los titulares se leían
     como calco. De la referencia se conservan los recursos de COMPOSICIÓN
     —titular a dos tonos, doble filete, tarjeta con número— que es lo que
     el cliente pidió; la letra tenía que ser propia.
     Chivo es una grotesca robusta y neutra: pesa en mayúsculas sin llamar
     la atención sobre sí misma, que es lo contrario de una geométrica
     redonda. Elegida por el cliente sobre el comparador de /_fuentes.
     Inter para el texto corrido, que es donde importa la legibilidad.

     El tracking de los titulares (h1 −0.06em, h2 −0.045em) sale del banco
     /_titulares, no de una preferencia: en h2 es menos cerrado a propósito,
     porque a tamaño pequeño el mismo valor se come la legibilidad. Si se
     toca, hay que volver a mirar /_movil?w=320 con "IMPERMEABILIZACIÓN" en
     pantalla.

     Escala fluida: cada tamaño interpola entre su valor a 320px y a 1280px.
     Es lo que evita el fallo más común en español — un titular fijo de 36px
     hace que "IMPERMEABILIZACIÓN" mida 389px y se salga de una pantalla de
     360px. --fs-base se queda fijo en 16px a propósito: por debajo de eso
     iOS hace zoom automático al enfocar un campo de formulario. */
  --font-display: "Chivo", "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, Helvetica, Arial, sans-serif;
  --font:         "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-mono:    ui-monospace, "SFMono-Regular", "Cascadia Mono", Consolas, monospace;

  --fs-xs:   0.75rem;                                          /* 12 fijo */
  --fs-sm:   clamp(0.8125rem, 0.792rem + 0.10vw, 0.875rem);    /* 13 → 14 */
  --fs-base: 1rem;                                             /* 16 fijo */
  --fs-md:   clamp(1rem, 0.969rem + 0.16vw, 1.0625rem);        /* 16 → 17 */
  --fs-lg:   clamp(1.0625rem, 1.0rem + 0.31vw, 1.25rem);       /* 17 → 20 */
  --fs-xl:   clamp(1.1875rem, 1.104rem + 0.42vw, 1.4375rem);   /* 19 → 23 */
  --fs-2xl:  clamp(1.5rem, 1.229rem + 1.35vw, 2.375rem);       /* 24 → 38 */
  --fs-3xl:  clamp(1.75rem, 1.271rem + 2.40vw, 3.3125rem);     /* 28 → 53 */
  --fs-4xl:  clamp(1.875rem, 1.354rem + 2.60vw, 3.5rem);       /* 30 → 56 */
  --fs-num:  clamp(3.5rem, 2.5rem + 5vw, 6.5rem);              /* números 01–08 */

  --lh-tight: 1.02;
  --lh-snug:  1.16;
  --lh-base:  1.62;
  --track-caps: 0.14em;   /* versalitas de eyebrow */

  /* ── Espaciado ── */
  --s-1: .25rem;  --s-2: .5rem;   --s-3: .75rem;  --s-4: 1rem;
  --s-5: 1.5rem;  --s-6: 2rem;    --s-7: 3rem;    --s-8: 4rem;
  --s-9: 5.5rem;  --s-10: 7rem;   --s-11: 9rem;

  /* ── Formas ── */
  --r-sm: 2px; --r-md: 4px; --r-lg: 8px; --r-full: 999px;
  --shadow-sm: 0 1px 3px rgba(6, 15, 28, .12);
  --shadow-md: 0 10px 30px rgba(6, 15, 28, .16);
  --shadow-lg: 0 28px 70px rgba(6, 15, 28, .35);

  /* ── Layout ── */
  --wrap: 1200px;
  --wrap-wide: 1440px;
  --wrap-narrow: 720px;
  --header-h: 66px;
  --tap: 44px;               /* objetivo táctil mínimo */
  --ease: cubic-bezier(.4, 0, .2, 1);
  --ease-out: cubic-bezier(.16, 1, .3, 1);
}

@media (min-width: 1024px) { :root { --header-h: 84px; } }

/* --- 2. Base ------------------------------------------------------------ */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + 16px);
  background: var(--navy-950);
  color-scheme: dark;
  /* También en <html>, no solo en <body>. El panel de navegación móvil es
     position:fixed y se aparca con translateX(100%): un elemento fijo se
     posiciona contra el viewport, así que el overflow del body NO lo recorta
     y a 320px generaba 48px de scroll horizontal en toda la página. Recortar
     en la raíz sí lo contiene. */
  overflow-x: clip;
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    transition-duration: .01ms !important;
    animation-iteration-count: 1 !important;
  }
}

body {
  margin: 0;
  background: var(--navy-950);
  color: var(--on-dark);
  font-family: var(--font);
  font-size: var(--fs-base);
  line-height: var(--lh-base);
  -webkit-font-smoothing: antialiased;
  /* 'clip' y no 'hidden': hidden convierte el body en contenedor de scroll y
     rompe el position:sticky de la cabecera. Es una red de seguridad, no la
     solución — lo que desborde hay que corregirlo en su sitio. */
  overflow-x: clip;
}

img, svg, video { max-width: 100%; height: auto; display: block; }
button { font: inherit; color: inherit; }
hr { border: 0; border-top: 1px solid var(--line-dark); margin: var(--s-7) 0; }
::selection { background: var(--blue); color: #fff; }
:focus-visible { outline: 2px solid var(--blue-400); outline-offset: 3px; border-radius: 2px; }

a { color: var(--blue-400); text-decoration-thickness: 1px; text-underline-offset: 3px; transition: color .18s var(--ease); }
a:hover { color: var(--blue-200); }

p { margin: 0 0 var(--s-4); text-wrap: pretty; overflow-wrap: break-word; }
ul, ol { margin: 0 0 var(--s-4); padding-left: 1.15rem; }
li { overflow-wrap: break-word; }
/* Correos y URLs largas en los textos legales y el pie. */
address, .prose a, .site-footer a, code { overflow-wrap: anywhere; }
code { font-family: var(--font-mono); font-size: .9em; }

/* ── Titulares ──────────────────────────────────────────────────────────
   Todos en la display, mayúsculas y muy apretados de interlínea. Es el rasgo
   que separa "empresa de ingeniería" de "contratista de mantenimiento".

   Las tres propiedades de abajo no son decorativas: el español encadena
   palabras larguísimas ("IMPERMEABILIZACIÓN", "CONSULTORÍA"). Reparten las
   líneas de forma pareja, permiten guionar y, como último recurso, parten
   la palabra antes que desbordar la pantalla. */
:where(h1, h2, h3, h4) {
  font-family: var(--font-display);
  margin: 0 0 var(--s-4);
  line-height: var(--lh-snug);
  letter-spacing: -0.015em;
  font-weight: 700;
  text-wrap: balance;
  hyphens: auto;
  overflow-wrap: break-word;
}
h1 { font-size: var(--fs-3xl); line-height: var(--lh-tight); letter-spacing: -0.06em;  font-weight: 600; text-transform: uppercase; }
h2 { font-size: var(--fs-2xl); line-height: var(--lh-snug);  letter-spacing: -0.045em; font-weight: 600; text-transform: uppercase; }
h3 { font-size: var(--fs-lg); font-weight: 600; letter-spacing: -0.005em; }
h4 { font-size: var(--fs-md); font-weight: 600; }

.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--blue); color: #fff; padding: var(--s-3) var(--s-4);
  font-weight: 600; border-radius: 0 0 var(--r-md) 0;
}
.skip-link:focus { left: 0; }

/* --- 3. Superficies -----------------------------------------------------
   Cuatro fondos, y cada uno arrastra sus colores de texto. Así una sección
   se cambia de claro a oscuro tocando UNA clase, sin repintar sus hijos. */
.s-navy   { background: var(--navy-900); color: var(--on-dark); }
.s-navy-d { background: var(--navy-950); color: var(--on-dark); }
.s-ink    { background: var(--graphite); color: var(--on-dark); }
.s-light  { background: var(--white);    color: var(--on-light); }
.s-gray   { background: var(--gray-050); color: var(--on-light); }

.s-navy :where(h1,h2,h3,h4), .s-navy-d :where(h1,h2,h3,h4), .s-ink :where(h1,h2,h3,h4) { color: var(--white); }
.s-light :where(h1,h2,h3,h4), .s-gray :where(h1,h2,h3,h4) { color: var(--navy-900); }

.s-navy p, .s-navy-d p, .s-ink p { color: var(--on-dark-soft); }
.s-light p, .s-gray p { color: var(--on-light-soft); }

.s-navy strong, .s-navy-d strong, .s-ink strong { color: var(--white); font-weight: 600; }
.s-light strong, .s-gray strong { color: var(--navy-900); font-weight: 600; }

.s-light a, .s-gray a { color: var(--blue-600); }
.s-light a:hover, .s-gray a:hover { color: var(--navy-900); }

/* --- 4. Utilidades ------------------------------------------------------ */
.wrap { width: 100%; max-width: var(--wrap); margin-inline: auto; padding-inline: var(--s-4); }
.wrap--wide { max-width: var(--wrap-wide); }
.wrap--narrow { max-width: var(--wrap-narrow); }
@media (min-width: 640px)  { .wrap { padding-inline: var(--s-5); } }
@media (min-width: 1024px) { .wrap { padding-inline: var(--s-6); } }

.section { padding-block: var(--s-8); position: relative; }
@media (min-width: 1024px) { .section { padding-block: var(--s-10); } }
.section--tight { padding-block: var(--s-7); }

.sr-only { position:absolute; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0; }
.mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.lead { font-size: var(--fs-md); line-height: 1.62; max-width: 62ch; }
@media (min-width: 1024px) { .lead { font-size: var(--fs-lg); } }
.text-soft { color: var(--on-dark-soft); }
.s-light .text-soft, .s-gray .text-soft { color: var(--on-light-soft); }
.text-dim { color: var(--on-dark-dim); }
.s-light .text-dim, .s-gray .text-dim { color: var(--gray-400); }

/* ── Eyebrow — el "— Servicios" de la referencia ── */
.eyebrow {
  display: inline-flex; align-items: center; gap: var(--s-3);
  font-family: var(--font); font-size: var(--fs-xs); font-weight: 700;
  letter-spacing: var(--track-caps); text-transform: uppercase;
  color: var(--blue-400); margin-bottom: var(--s-5);
}
.eyebrow::before { content: ""; width: 30px; height: 2px; background: currentColor; flex: none; }
.s-light .eyebrow, .s-gray .eyebrow { color: var(--blue-600); }

/* ── Titular a dos tonos ──────────────────────────────────────────────
   El recurso central de la referencia: las primeras líneas en el color
   base y la línea de énfasis en azul brillante. Se marca con un <span>. */
/* TITULAR A DOS TONOS — MONOCROMO.
   El énfasis era azul brillante, y eso era el calco: el titular blanco +
   azul es la firma de liquidrubberpanama.com, la referencia del cliente.
   Ahora los dos tonos viven dentro del mismo color —la primera línea se
   apaga, la de énfasis va a blanco puro o a marino— y el azul queda
   reservado a lo que se puede pulsar: botones, enlaces, filetes y los
   números del mosaico. Esa regla, "azul = acción", es además lo que más
   ordena la lectura de la página.

   Se conserva la ESTRUCTURA de dos líneas, que es lo que pidió el cliente;
   lo que se quita es el color prestado. Y de paso queda más cerca del PDF,
   que pide "azul oscuro + negro/grafito + blanco" y nunca un azul de acento.

   El :has() evita el efecto secundario obvio: un titular sin <em> no tiene
   línea de énfasis, así que apagar su base lo dejaría gris y débil. Si el
   navegador no soporta :has(), la base se queda como está y el titular se
   lee como monotono — degradación aceptable, nada se rompe. */
.title em, .title .hl { font-style: normal; color: #FFFFFF; display: block; }
.title:has(em), .title:has(.hl) { color: var(--on-dark-dim); }

.s-light .title em, .s-light .title .hl,
.s-gray  .title em, .s-gray  .title .hl { color: var(--navy-900); }
.s-light .title:has(em), .s-light .title:has(.hl),
.s-gray  .title:has(em), .s-gray  .title:has(.hl) { color: var(--gray-400); }

/* El hero es la excepción, y no por gusto: en móvil su titular va SOBRE el
   video, y --on-dark-dim sobre imagen en movimiento se pierde. Usa el mismo
   gris claro que la línea de especialidades, que ya está probado ahí. */
.hero h1.title:has(em) { color: #C6D3E1; }

/* ── Doble filete bajo el titular ────────────────────────────────────
   Dos barras cortas, una oscura y una celeste. Es el detalle que ata
   visualmente todas las secciones del sitio y cuesta cero. */
.rules { display: flex; gap: var(--s-3); margin: var(--s-5) 0; }
.rules::before, .rules::after { content: ""; height: 4px; }
.rules::before { width: 118px; background: var(--white); }
.rules::after  { width: 56px;  background: var(--blue); }
.s-light .rules::before, .s-gray .rules::before { background: var(--navy-900); }
.rules--center { justify-content: center; }

.section-head { max-width: 68ch; margin-bottom: var(--s-7); }
.section-head--center { margin-inline: auto; text-align: center; }
.section-head--center .eyebrow { justify-content: center; }
.section-head--center .lead { margin-inline: auto; }
.section-head .lead { margin-bottom: 0; }

/* --- 5. Botones --------------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s-2);
  min-height: var(--tap); padding: var(--s-3) var(--s-5);
  border: 2px solid transparent; border-radius: var(--r-md);
  font-family: var(--font); font-size: var(--fs-sm); font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase;
  text-decoration: none; cursor: pointer; white-space: nowrap;
  transition: background-color .18s var(--ease), border-color .18s var(--ease),
              color .18s var(--ease), transform .18s var(--ease);
}
.btn:active { transform: translateY(1px); }
.btn .icon { flex: none; }

/* Primario: azul brillante. Es el único color de acción del sitio. */
.btn--primary { background: var(--blue); border-color: var(--blue); color: #fff; }
.btn--primary:hover { background: var(--blue-600); border-color: var(--blue-600); color: #fff; }

/* Secundario sobre oscuro */
.btn--outline { background: transparent; border-color: rgba(255,255,255,.32); color: #fff; }
.btn--outline:hover { background: #fff; border-color: #fff; color: var(--navy-900); }

/* Secundario sobre claro */
.btn--outline-dark { background: transparent; border-color: var(--navy-900); color: var(--navy-900); }
.btn--outline-dark:hover { background: var(--navy-900); color: #fff; }

.btn--white { background: #fff; border-color: #fff; color: var(--navy-900); }
.btn--white:hover { background: var(--gray-100); border-color: var(--gray-100); color: var(--navy-900); }

.btn--lg { padding: var(--s-4) var(--s-6); font-size: var(--fs-base); min-height: 54px; }
.btn--sm { padding: var(--s-2) var(--s-4); min-height: 38px; font-size: var(--fs-xs); }
.btn--block { width: 100%; }

.btn-row { display: flex; flex-wrap: wrap; gap: var(--s-3); margin-block: var(--s-6); }
.btn-row:last-child { margin-bottom: 0; }

/* Enlace con flecha que avanza al pasar el puntero */
.arrow-link {
  display: inline-flex; align-items: center; gap: var(--s-2);
  font-weight: 600; font-size: var(--fs-sm); letter-spacing: .02em;
  color: var(--blue-400); text-decoration: none;
}
.s-light .arrow-link, .s-gray .arrow-link { color: var(--blue-600); }
.arrow-link .icon { transition: transform .22s var(--ease-out); }
.arrow-link:hover .icon { transform: translateX(5px); }

/* --- 6. Iconos ---------------------------------------------------------- */
.icon { width: 20px; height: 20px; flex: none; }
.icon--xs { width: 14px; height: 14px; }
.icon--sm { width: 16px; height: 16px; }
.icon--lg { width: 28px; height: 28px; }
.icon--xl { width: 40px; height: 40px; }

/* --- 7. Cabecera -------------------------------------------------------- */
/* Sin backdrop-filter, y es deliberado. Un desenfoque de fondo en una
   cabecera FIJA obliga al navegador a rerasterizar la franja en cada
   fotograma de scroll, y sobre una página con imágenes filtradas debajo
   llega a bloquear el hilo principal. Un degradado opaco da la misma
   sensación de profundidad y cuesta cero. */
.site-header {
  position: sticky; top: 0; z-index: 100;
  background: linear-gradient(180deg, rgba(6,15,28,.94) 0%, rgba(6,15,28,.72) 100%);
  border-bottom: 1px solid transparent;
  transition: background-color .25s var(--ease), border-color .25s var(--ease);
}
/* Sobre el hero la cabecera es casi transparente; al hacer scroll gana
   fondo y borde. Lo conmuta main.js con .is-stuck. */
.site-header.is-stuck { background: var(--navy-950); border-bottom-color: var(--line-dark); }

.topbar { font-size: var(--fs-xs); padding: var(--s-2) 0; }
.topbar .wrap { display: flex; align-items: center; gap: var(--s-2); }
.topbar--alert { background: var(--warn-dim); color: #E8C77A; border-bottom: 1px solid rgba(214,158,46,.24); }

.site-header__inner { display: flex; align-items: center; gap: var(--s-4); min-height: var(--header-h); }
.brand { display: flex; align-items: center; flex: none; text-decoration: none; }
.brand__logo { height: 32px; width: auto; }
@media (min-width: 1024px) { .brand__logo { height: 42px; } }

.nav { margin-left: auto; }
@media (max-width: 1023px) { .nav { margin-left: 0; } }
.nav__list { display: flex; align-items: center; gap: var(--s-1); list-style: none; margin: 0; padding: 0; }
.nav__item { position: relative; }
.nav__link {
  display: flex; align-items: center; gap: var(--s-2);
  padding: var(--s-2) var(--s-3); min-height: var(--tap);
  font-size: var(--fs-sm); font-weight: 600; letter-spacing: .03em;
  color: var(--on-dark-soft); text-decoration: none;
  background: none; border: 0; cursor: pointer;
  transition: color .18s var(--ease);
}
.nav__link:hover, .nav__link[aria-expanded="true"], .nav__link.is-current { color: #fff; }
.nav__chev { transition: transform .2s var(--ease); }
.nav__link[aria-expanded="true"] .nav__chev { transform: rotate(180deg); }
/* Subrayado azul de la sección actual */
.nav__link.is-current { position: relative; }
.nav__link.is-current::after {
  content: ""; position: absolute; left: var(--s-3); right: var(--s-3); bottom: 10px;
  height: 2px; background: var(--blue);
}

/* Submenú */
.subnav {
  position: absolute; top: calc(100% + 4px); left: 50%; translate: -50% 0;
  width: min(700px, 92vw);
  display: grid; grid-template-columns: 1fr 1fr; gap: 2px;
  list-style: none; margin: 0; padding: var(--s-3);
  background: var(--navy-900); border: 1px solid var(--line-dark-hi);
  border-radius: var(--r-lg); box-shadow: var(--shadow-lg);
  opacity: 0; visibility: hidden; translate: -50% 10px;
  transition: opacity .2s var(--ease), translate .2s var(--ease), visibility .2s;
}
.nav__item.is-open .subnav { opacity: 1; visibility: visible; translate: -50% 0; }
.subnav__link {
  display: flex; align-items: flex-start; gap: var(--s-3);
  padding: var(--s-3); border-radius: var(--r-md);
  text-decoration: none; color: var(--on-dark);
  transition: background-color .16s var(--ease);
}
.subnav__link:hover, .subnav__link.is-current { background: var(--navy-700); color: var(--on-dark); }
.subnav__icon { color: var(--blue-400); margin-top: 2px; }
.subnav__link strong { display: block; font-size: var(--fs-sm); font-weight: 600; color: #fff; }
.subnav__link em { display: block; font-style: normal; font-size: var(--fs-xs); color: var(--on-dark-dim); margin-top: 2px; }

.site-header__actions { display: flex; align-items: center; gap: var(--s-3); flex: none; margin-left: auto; }
.tel {
  display: none; align-items: center; gap: var(--s-2);
  font-size: var(--fs-sm); font-weight: 700; color: #fff; text-decoration: none;
  font-variant-numeric: tabular-nums;
}
.tel .icon { color: var(--blue-400); }
@media (min-width: 1280px) { .tel { display: flex; } }

.burger {
  display: grid; place-items: center; width: var(--tap); height: var(--tap);
  background: none; border: 1px solid var(--line-dark-hi); border-radius: var(--r-md);
  color: #fff; cursor: pointer;
}
.burger__close { display: none; }
.burger[aria-expanded="true"] .burger__open { display: none; }
.burger[aria-expanded="true"] .burger__close { display: block; }
@media (min-width: 1024px) { .burger { display: none; } }

/* Navegación en móvil: panel a pantalla completa */
@media (max-width: 1023px) {
  .nav {
    position: fixed; inset: var(--header-h) 0 0; z-index: 90;
    background: var(--navy-950);
    padding: var(--s-5) var(--s-4) var(--s-8);
    overflow-y: auto;
    transform: translateX(100%);
    transition: transform .3s var(--ease-out);
    visibility: hidden;
  }
  .nav.is-open { transform: none; visibility: visible; }
  /* Cinturón y tirantes por si un navegador no soporta overflow:clip en la
     raíz: cerrado, el panel no ocupa ni un píxel de ancho. */
  .nav:not(.is-open) { width: 0; overflow: hidden; }
  .nav__list { flex-direction: column; align-items: stretch; gap: 0; }
  .nav__item { border-bottom: 1px solid var(--line-dark); }
  .nav__link { justify-content: space-between; width: 100%; padding: var(--s-4) 0; font-size: var(--fs-md); }
  .nav__link.is-current::after { display: none; }
  .subnav {
    position: static; translate: none; width: auto; opacity: 1; visibility: visible;
    display: none; grid-template-columns: 1fr; background: none; border: 0;
    box-shadow: none; padding: 0 0 var(--s-4);
  }
  .nav__item.is-open .subnav { display: grid; translate: none; }
}

/* --- 8. Hero -------------------------------------------------------------
   Dos montajes distintos con UN SOLO elemento de video:

   · Escritorio (≥900px) → partido, como la referencia: columna de texto
     sobre azul marino a la izquierda y el video en columna a la derecha.

   · Móvil → el video cubre el hero COMPLETO. El texto va encima, sobre un
     velo oscuro que garantiza el contraste, y debajo queda una franja de
     video limpia. Antes el bloque de texto tenía fondo plano y se veía
     vacío; ahora el vídeo se ve detrás del titular y sigue viéndose abajo.

   Se reutiliza el mismo <video>, no se duplica: dos elementos de video
   decodificando el mismo archivo a la vez es de los errores que más caro
   salen en batería y en memoria en un móvil de gama media.

   Restricción del material: los tres videos del cliente son VERTICALES
   (1080×1920, grabados con dron), así que en móvil llenan la pantalla sin
   recortar nada — que es justo lo que hace valioso ese metraje. */
.hero {
  position: relative;
  background: var(--navy-950);
  margin-top: calc(var(--header-h) * -1);
  overflow: hidden;
}
.hero__grid { display: grid; grid-template-columns: 1fr; min-height: min(100svh, 900px); }
@media (min-width: 900px) { .hero__grid { grid-template-columns: 1.02fr 1fr; } }


.hero__text {
  position: relative; z-index: 2;
  display: flex; flex-direction: column; justify-content: center;
  padding: calc(var(--header-h) + var(--s-8)) var(--s-4) var(--s-8);
}
/* En móvil el texto arranca arriba y deja libre el tercio inferior, para que
   el video se lea como imagen y no solo como textura tras las letras. */
@media (max-width: 899px) {
  .hero__text { justify-content: flex-start; padding-bottom: 38vh; }

  /* Velo propio DEL BLOQUE DE TEXTO, además del general del media.
     Es la diferencia entre que el texto se lea siempre y que se lea "casi
     siempre": el video cambia de fotograma, y con una toma a contraluz o
     con el cielo entrando en cuadro, un velo calculado por porcentaje de
     altura deja de tapar lo que tiene que tapar. Este va anclado al texto,
     así que lo acompaña mida lo que mida y muestre lo que muestre el video. */
  .hero__text::before {
    content: ""; position: absolute; inset: 0 0 auto; z-index: -1;
    /* Cubre el alto del texto más un margen, y se desvanece al final. */
    height: calc(100% - 26vh);
    background: linear-gradient(180deg,
      rgba(6,15,28,.90) 0%,
      rgba(6,15,28,.86) 62%,
      rgba(6,15,28,.62) 86%,
      rgba(6,15,28,0) 100%);
    pointer-events: none;
  }
}
@media (min-width: 640px)  { .hero__text { padding-inline: var(--s-6); } }
@media (min-width: 900px)  { .hero__text { padding-inline: clamp(var(--s-6), 5vw, var(--s-10)); } }
/* En escritorio la columna respeta el ancho máximo del sitio en su lado. */
@media (min-width: 1440px) { .hero__text { padding-left: calc((100vw - var(--wrap-wide)) / 2 + var(--s-6)); } }

.hero h1 { font-size: var(--fs-4xl); max-width: 14ch; margin-bottom: 0; }
/* Sombra de texto solo en móvil, que es donde las letras caen sobre el
   video. Permite bajar el velo —y que la imagen se vea— sin perder
   contraste sobre las zonas claras del cielo. */
@media (max-width: 899px) {
  .hero h1,
  .hero__claim,
  .hero__lead,
  .hero__specialties { text-shadow: 0 1px 16px rgba(6,15,28,.85), 0 0 42px rgba(6,15,28,.6); }
  .hero__lead { color: #D7E1EC; }
  .hero__specialties { color: #C6D3E1; }
}
/* El claim NO va en azul: ese color está reservado a la línea de énfasis
   del titular. Dos azules seguidos anulan la jerarquía que crea el titular
   a dos tonos, que es el recurso central del sistema. */
.hero__claim {
  display: block; font-family: var(--font-display); font-size: var(--fs-lg);
  font-weight: 500; text-transform: none; letter-spacing: -0.005em;
  color: rgba(255,255,255,.82); margin-top: var(--s-4);
}
.hero__lead { font-size: var(--fs-lg); color: var(--on-dark-soft); max-width: 48ch; margin-bottom: var(--s-6); }

/* Línea de especialidades del §1 del documento, separada por puntos medios */
.hero__specialties {
  display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-4);
  list-style: none; margin: 0 0 var(--s-6); padding: 0;
  font-size: var(--fs-sm); color: var(--on-dark-dim); letter-spacing: .01em;
}
.hero__specialties li { display: flex; align-items: center; gap: var(--s-4); }
.hero__specialties li:not(:last-child)::after { content: "·"; color: var(--blue); font-weight: 700; }

/* Media: en móvil va debajo y a sangre; en escritorio ocupa la columna. */
.hero__media { position: relative; min-height: 62vh; background: var(--navy-800); }
@media (min-width: 900px) { .hero__media { min-height: 0; } }
.hero__media > img, .hero__media > video {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: center 38%;
}
/* El video aparece encima del póster con un fundido cuando ya puede
   reproducir. Evita el salto en negro típico del autoplay en móvil. */
.hero__video { opacity: 0; transition: opacity .8s var(--ease); }
.hero__video.is-ready { opacity: 1; }
/* Velo azul marino: liga la fotografía con la paleta y sostiene el contraste
   del texto. En móvil carga arriba —donde está el titular— y se abre en el
   tercio inferior, que es la franja de video que se deja ver limpia. */
.hero__media::after {
  content: ""; position: absolute; inset: 0;
  background:
    linear-gradient(180deg,
      rgba(6,15,28,.55) 0%,
      rgba(6,15,28,.34) 34%,
      rgba(6,15,28,.14) 58%,
      rgba(6,15,28,.10) 72%,
      rgba(6,15,28,.72) 100%);
}
@media (min-width: 900px) {
  .hero__media::after {
    background: linear-gradient(90deg, var(--navy-950) 0%, rgba(6,15,28,.45) 22%, rgba(6,15,28,.05) 60%, transparent 100%);
  }
}

/* MÓVIL: el media sale del flujo y se estira por todo el hero, quedando
   DETRÁS del texto. La rejilla pasa a una sola fila, así que el texto ya no
   empuja al video hacia abajo: se superponen.

   Va al final de la sección a propósito. Estas reglas tienen la misma
   especificidad que las de arriba, así que si se declararan antes perderían
   por orden de cascada y el media seguiría en el flujo. */
@media (max-width: 899px) {
  .hero__grid  { grid-template-rows: 1fr; }
  .hero__media { position: absolute; inset: 0; z-index: 0; min-height: 0; }
  .hero__text  { grid-row: 1; }
}

.hero__tag {
  position: absolute; left: var(--s-4); bottom: var(--s-4); z-index: 3;
  display: inline-flex; align-items: center; gap: var(--s-2);
  font-family: var(--font-mono); font-size: var(--fs-xs); letter-spacing: .06em;
  color: #fff; background: rgba(6, 15, 28, .88);
  border: 1px solid rgba(255,255,255,.16); border-radius: var(--r-full);
  padding: var(--s-2) var(--s-4);
}
.hero__tag::before {
  content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--blue);
  animation: ping 2.2s var(--ease) infinite;
}
@keyframes ping {
  0%   { box-shadow: 0 0 0 0 rgba(46,125,224,.65); }
  70%  { box-shadow: 0 0 0 9px rgba(46,125,224,0); }
  100% { box-shadow: 0 0 0 0 rgba(46,125,224,0); }
}

/* --- 9. Franja de cifras -------------------------------------------------
   §2 del documento: "una franja visual con números reales". */
.stats { background: var(--blue); }
/* auto-fit y no un número fijo de columnas: las cifras se añaden y se quitan
   desde app/data/site.php según lo que la empresa pueda respaldar, y la
   franja tiene que quedar bien con tres, con cuatro o con cinco. */
.stats__grid {
  display: grid; gap: 1px; background: rgba(255,255,255,.22);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
}
.stat { background: var(--blue); padding: var(--s-6) var(--s-4); text-align: center; }
@media (min-width: 1024px) { .stat { padding: var(--s-7) var(--s-5); } }
.stat__value {
  display: block; font-family: var(--font-display); font-size: var(--fs-3xl);
  font-weight: 700; line-height: 1; color: #fff; letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums; margin-bottom: var(--s-3);
}
.stat__label { font-size: var(--fs-sm); color: rgba(255,255,255,.86); text-wrap: balance; }

/* --- 9b. Franja de clientes ---------------------------------------------
   "Confían en nosotros" a la izquierda y la fila de logos a la derecha,
   como en la referencia. En móvil se apila. */
.title--sm { font-size: var(--fs-lg); }

/* CINTA DE CLIENTES ------------------------------------------------------
   Los diez logotipos desfilan en bucle. Es una franja de credibilidad, no
   contenido: tiene que leerse de un vistazo y no pedir atencion.

   Los PNG del cliente vienen con fondo transparente, asi que van directos
   sobre el gris de la banda. Nada de filter: grayscale() para apagarlos —
   es la trampa del duotono de las fotos (§8 de CLAUDE.md), una capa de
   composicion por imagen, y aqui serian veinte moviendose a la vez. Se
   apagan con opacity, que el compositor ya resuelve gratis.

   El bucle sin costura son DOS pistas identicas desplazandose -100%: en el
   instante en que la primera sale por la izquierda, la segunda ocupa
   exactamente su sitio inicial. Por eso la animacion no necesita reinicio
   ni JavaScript. */
.cinta {
  display: flex;
  overflow: hidden;
  position: relative;
  margin-top: var(--s-6);
  /* Full-bleed: la cinta se sale del .wrap y toca los dos bordes, que es lo
     que la hace leerse como cinta y no como otra fila de contenido. */
  width: 100%;
}
.cinta__pista {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex: 0 0 auto; align-items: center;
  /* La separación baja en móvil junto con el tamaño: mantenerla en 32px
     mientras el logotipo encoge deja la cinta pareciendo más hueco que
     contenido. */
  gap: clamp(var(--s-5), 6vw, var(--s-8));
  padding-inline: clamp(var(--s-5), 3vw, var(--s-8));
}
/* Solo desfila cuando main.js ha clonado la segunda pista. Sin JavaScript
   una sola pista animandose dejaria medio ancho en blanco en cada vuelta:
   mejor quieta y recorrible a mano. */
.cinta--activa .cinta__pista { animation: cinta-desfile 46s linear infinite; }
.cinta:not(.cinta--activa) { overflow-x: auto; }
.cinta__pista li { flex: 0 0 auto; display: flex; align-items: center; }
/* La altura es la del LIENZO, no la del dibujo: los diez PNG miden 440x220
   y cada logotipo ocupa dentro lo que le toca segun la igualacion optica.
   Por eso el numero parece grande — la tinta real queda en torno al 85% de
   el, y por debajo de ~70px los logotipos con bajada de texto ("Asociacion
   de Profesionales Administradores de PH") dejan de leerse. */
.cinta__pista img {
  /* En móvil NO se encoge proporcionalmente. Un logotipo se dimensiona por
     legibilidad, no por porcentaje de pantalla: en un teléfono se mira más
     de cerca y la marca tiene que leerse igual. Con 10vw el clamp caía al
     mínimo de 64px en cualquier teléfono y la cinta parecía un pie de
     página. Por eso el suelo sube a 84px y el techo solo a 104. */
  display: block; width: auto; height: clamp(84px, 20vw, 104px);
  /* Casi a color pleno. Apagarlos al 68% los hacia "discretos" sobre el
     papel, pero varios de estos logotipos llevan una linea de texto
     pequena —"Digital Plaza", "Administracion Integral de Condominios"— y
     esa linea es lo primero que desaparece al bajar la opacidad. Un logo
     de cliente que no se lee no acredita nada. */
  opacity: .92;
  transition: opacity .25s ease;
}
/* Al pasar por encima, ese logotipo recupera su color pleno y la cinta se
   detiene: si alguien se para en una marca es porque quiere leerla, y una
   cinta que sigue moviendose bajo el cursor es un logotipo que no se puede
   mirar. */
.cinta--activa:hover .cinta__pista,
.cinta--activa:focus-within .cinta__pista { animation-play-state: paused; }
.cinta__pista img:hover { opacity: 1; }

/* Desvanecido en los dos extremos, para que los logotipos no aparezcan y
   desaparezcan de golpe contra el borde. Es un degradado del propio color
   de la banda, no una mascara: mask-image obliga a rasterizar la cinta
   entera en cada fotograma. */
.cinta::before, .cinta::after {
  content: ""; position: absolute; top: 0; bottom: 0; width: clamp(40px, 8vw, 120px);
  z-index: 1; pointer-events: none;
}
.cinta::before { left: 0;  background: linear-gradient(90deg, var(--gray-050), transparent); }
.cinta::after  { right: 0; background: linear-gradient(270deg, var(--gray-050), transparent); }

@keyframes cinta-desfile { to { transform: translateX(-100%); } }

/* Sin movimiento: la cinta se convierte en una fila que se puede recorrer a
   mano. La segunda pista sobra y se retira, que si no se ven los diez dos
   veces. */
@media (prefers-reduced-motion: reduce) {
  .cinta { overflow-x: auto; scrollbar-width: thin; }
  .cinta__pista { animation: none; }
  .cinta__pista[aria-hidden="true"] { display: none; }
  .cinta__pista img { opacity: 1; }
}

/* Fotografia de equipo de /empresa/. Viene compuesta por el cliente, con el
   logotipo y el claim dentro, asi que se sirve ENTERA: nada de object-fit,
   que recortaria justo el lockup. La proporcion la fija la propia imagen. */
.equipo { margin: 0; }
.equipo img { display: block; width: 100%; height: auto; border-radius: var(--r-md); }

/* BANDA FOTOGRAFICA A SANGRE. Corta dos bloques largos de texto y da
   respiro. No lleva padding lateral a proposito: toca los dos bordes, que
   es lo que la distingue de una imagen dentro de una seccion. */
.banda { margin: 0; display: block; line-height: 0; }
.banda img {
  display: block; width: 100%; height: clamp(180px, 26vw, 340px);
  object-fit: cover; object-position: 50% 40%;
}

/* --- 10. Tarjetas de servicio (mosaico fotográfico) ----------------------
   El recurso más característico de la referencia: NO es una tarjeta con
   icono y párrafo, es una fotografía a sangre con un número enorme y el
   nombre del servicio encima. El número alterna de esquina para que la
   retícula no se lea como una tabla. */
.tiles { display: grid; gap: var(--s-3); grid-template-columns: 1fr; }
@media (min-width: 560px)  { .tiles { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .tiles { grid-template-columns: repeat(4, 1fr); gap: var(--s-4); } }

.tile {
  position: relative; display: block; overflow: hidden;
  aspect-ratio: 3 / 4; border-radius: var(--r-md);
  background: var(--navy-800); text-decoration: none; color: #fff;
  isolation: isolate;
}
/* El duotono se consigue con un VELO de color sobre la foto, no con
   filter: grayscale(). El filtro obliga a una capa de composición propia
   por cada imagen —aquí son ocho— y en equipos sin aceleración por GPU eso
   se traduce en scroll a tirones. El velo es una capa pintada y ya está. */
.tile img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  transition: transform .7s var(--ease-out);
}
.tile:hover img { transform: scale(1.05); }
.tile::after {
  content: ""; position: absolute; inset: 0; z-index: 1;
  background:
    linear-gradient(180deg, rgba(6,15,28,.6) 0%, rgba(10,26,47,.22) 38%, rgba(6,15,28,.94) 100%),
    linear-gradient(0deg, rgba(15,36,64,.45), rgba(15,36,64,.45));
  transition: opacity .35s var(--ease);
}
.tile:hover::after { opacity: .78; }

/* Número arriba a la derecha, nombre abajo a la izquierda. SIEMPRE.
   La referencia los alterna de esquina, pero con nombres largos en español
   —"Consultoría y diagnóstico estructural"— la alternancia acaba haciendo
   que el texto pase por debajo del número en algún cruce de tamaño de
   pantalla. Fijar las posiciones hace la colisión imposible por
   construcción, y el ritmo de la retícula lo da igualmente el número. */
.tile__num {
  position: absolute; z-index: 2; right: var(--s-4); top: var(--s-2);
  font-family: var(--font-display); font-size: var(--fs-num); font-weight: 700;
  line-height: .9; letter-spacing: -0.05em; color: rgba(255,255,255,.9);
  pointer-events: none;
}

.tile__body {
  position: absolute; z-index: 3;
  left: var(--s-4); right: var(--s-4); bottom: var(--s-5);
}

.tile__name {
  display: block;
  font-family: var(--font-display); font-size: var(--fs-md); font-weight: 600;
  color: #fff; margin: 0 0 var(--s-3); letter-spacing: -0.005em;
  text-transform: none; line-height: 1.25;
  text-shadow: 0 1px 12px rgba(6,15,28,.7);
}
.tile__more {
  display: inline-flex; align-items: center; gap: var(--s-2);
  font-size: var(--fs-xs); font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  color: var(--blue-400);
}
.tile__more .icon { transition: transform .22s var(--ease-out); }
.tile:hover .tile__more .icon { transform: translateX(4px); }

/* Filo azul que se dibuja al pasar el puntero */
.tile::before {
  content: ""; position: absolute; inset: auto 0 0 0; height: 3px; z-index: 4;
  background: var(--blue); transform: scaleX(0); transform-origin: left;
  transition: transform .4s var(--ease-out);
}
.tile:hover::before { transform: scaleX(1); }

/* --- 11. Tarjetas de texto ---------------------------------------------- */
.grid { display: grid; gap: var(--s-4); grid-template-columns: 1fr; }
@media (min-width: 640px)  { .grid--2, .grid--3, .grid--4 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .grid--3 { grid-template-columns: repeat(3, 1fr); } .grid--4 { grid-template-columns: repeat(4, 1fr); } }
.grid--split { display: grid; gap: var(--s-7); grid-template-columns: 1fr; }
@media (min-width: 1024px) { .grid--split { grid-template-columns: 1fr 1fr; gap: var(--s-8); align-items: start; } }

.card {
  display: flex; flex-direction: column; position: relative;
  padding: var(--s-5); border-radius: var(--r-md);
  text-decoration: none; color: inherit;
  border: 1px solid var(--line-dark); background: var(--navy-900);
  transition: border-color .2s var(--ease), background-color .2s var(--ease), transform .2s var(--ease);
}
.s-light .card, .s-gray .card { background: var(--white); border-color: var(--line-light); box-shadow: var(--shadow-sm); }
a.card:hover { transform: translateY(-3px); border-color: var(--blue); }
.card__icon {
  display: grid; place-items: center; width: 48px; height: 48px;
  border-radius: var(--r-md); background: var(--blue-dim); color: var(--blue-400);
  margin-bottom: var(--s-4);
}
.s-light .card__icon, .s-gray .card__icon { background: var(--blue-050); color: var(--blue-600); }
.card__title { font-size: var(--fs-lg); margin-bottom: var(--s-3); text-transform: none; }
.card__text { font-size: var(--fs-sm); margin-bottom: var(--s-4); flex: 1; }
.card__more {
  margin-top: auto; display: inline-flex; align-items: center; gap: var(--s-2);
  font-size: var(--fs-xs); font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--blue-400);
}
.s-light .card__more, .s-gray .card__more { color: var(--blue-600); }
.card__more .icon { transition: transform .22s var(--ease-out); }
a.card:hover .card__more .icon { transform: translateX(4px); }

/* --- 12. Proceso numerado (Método MSG, §6) ------------------------------ */
.steps { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-4); counter-reset: paso; }
@media (min-width: 700px)  { .steps { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1100px) { .steps { grid-template-columns: repeat(3, 1fr); } }
.steps li {
  counter-increment: paso; position: relative;
  padding: var(--s-6) var(--s-5) var(--s-5);
  border-top: 3px solid var(--blue);
  background: var(--navy-900);
}
.s-light .steps li, .s-gray .steps li { background: var(--white); box-shadow: var(--shadow-sm); }
.steps li::before {
  content: "0" counter(paso);
  display: block; font-family: var(--font-display); font-size: var(--fs-2xl); font-weight: 700;
  line-height: 1; letter-spacing: -0.03em; color: var(--blue); margin-bottom: var(--s-4);
}
.steps h3 { font-size: var(--fs-md); text-transform: uppercase; letter-spacing: .04em; margin-bottom: var(--s-3); }
.steps p { font-size: var(--fs-sm); margin: 0; }

/* Línea de tiempo vertical, para casos de estudio y "cómo funciona" */
.timeline { list-style: none; margin: 0; padding: 0 0 0 var(--s-7); position: relative; }
.timeline::before { content: ""; position: absolute; left: 8px; top: 10px; bottom: 10px; width: 2px; background: var(--line-dark-hi); }
.s-light .timeline::before, .s-gray .timeline::before { background: var(--gray-200); }
.timeline li { position: relative; padding-bottom: var(--s-6); }
.timeline li:last-child { padding-bottom: 0; }
.timeline li::before {
  content: ""; position: absolute; left: calc(var(--s-7) * -1); top: 6px;
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--navy-950); border: 3px solid var(--blue);
}
.s-light .timeline li::before, .s-gray .timeline li::before { background: var(--white); }
.timeline__num { font-family: var(--font-mono); font-size: var(--fs-xs); font-weight: 700; letter-spacing: .1em; color: var(--blue-400); }
.s-light .timeline__num, .s-gray .timeline__num { color: var(--blue-600); }
.timeline h3 { font-size: var(--fs-md); margin: var(--s-1) 0 var(--s-2); text-transform: uppercase; letter-spacing: .03em; }
.timeline p { font-size: var(--fs-sm); margin: 0; }

/* --- 13. Proyectos ------------------------------------------------------
   §4: "el visitante entra y ve fotografías grandes". */
.projects { display: grid; gap: var(--s-4); grid-template-columns: 1fr; }
@media (min-width: 768px)  { .projects { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1200px) { .projects { grid-template-columns: repeat(3, 1fr); } }
/* El primero ocupa doble ancho: jerarquiza sin necesidad de más texto. */
@media (min-width: 768px) { .projects > :first-child { grid-column: span 2; } }

.project {
  position: relative; display: block; overflow: hidden; border-radius: var(--r-md);
  aspect-ratio: 4 / 3; background: var(--navy-800); text-decoration: none; color: #fff;
}
@media (min-width: 768px) { .projects > :first-child.project { aspect-ratio: 16 / 10; } }
.project img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; transition: transform .7s var(--ease-out); }
.project:hover img { transform: scale(1.05); }
.project::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(180deg, transparent 25%, rgba(10,26,47,.6) 58%, rgba(6,15,28,.95) 100%);
}
.project__body { position: absolute; z-index: 2; inset: auto 0 0; padding: var(--s-5); }
.project__place {
  display: flex; align-items: center; gap: var(--s-2);
  font-size: var(--fs-xs); font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  color: var(--blue-400); margin-bottom: var(--s-2);
}
.project__title { font-size: var(--fs-xl); color: #fff; margin-bottom: var(--s-2); }
.project__type { font-size: var(--fs-sm); color: var(--on-dark-soft); margin: 0; }
/* Ficha técnica que asoma al pasar el puntero */
.project__specs {
  display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-5); margin-top: 0;
  font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--on-dark-soft);
  max-height: 0; overflow: hidden; opacity: 0;
  transition: max-height .35s var(--ease-out), opacity .3s var(--ease), margin-top .35s var(--ease-out);
}
.project:hover .project__specs, .project:focus-visible .project__specs { max-height: 120px; opacity: 1; margin-top: var(--s-4); }
.project__specs b { color: #fff; font-weight: 600; }
/* Sin puntero (táctil) la ficha va siempre visible: no hay hover que dispararla. */
@media (hover: none) { .project__specs { max-height: 120px; opacity: 1; margin-top: var(--s-4); } }

/* Ficha de proyecto en página propia */
.proyecto { display: grid; gap: var(--s-6); padding-block: var(--s-8); border-top: 1px solid var(--line-dark); }
.s-light .proyecto, .s-gray .proyecto { border-top-color: var(--line-light); }
.proyecto:first-of-type { border-top: 0; padding-top: 0; }
@media (min-width: 1024px) { .proyecto { grid-template-columns: 5fr 7fr; gap: var(--s-8); align-items: start; } }
.proyecto__media img { width: 100%; border-radius: var(--r-md); }
.proyecto__bloques { display: grid; gap: var(--s-4); margin: var(--s-5) 0; }
.proyecto__bloques dt {
  font-family: var(--font); font-size: var(--fs-xs); font-weight: 700;
  letter-spacing: var(--track-caps); text-transform: uppercase; color: var(--blue-400); margin-bottom: var(--s-2);
}
.s-light .proyecto__bloques dt, .s-gray .proyecto__bloques dt { color: var(--blue-600); }
.proyecto__bloques dd { margin: 0; font-size: var(--fs-sm); }

.ficha { list-style: none; margin: 0; padding: 0; display: grid; gap: 1px; background: var(--line-dark); border: 1px solid var(--line-dark); }
.s-light .ficha, .s-gray .ficha { background: var(--line-light); border-color: var(--line-light); }
@media (min-width: 560px) { .ficha { grid-template-columns: repeat(2, 1fr); } }
.ficha li { background: var(--navy-900); padding: var(--s-4); display: flex; flex-direction: column; gap: var(--s-1); }
.s-light .ficha li, .s-gray .ficha li { background: var(--white); }
.ficha__l { font-size: var(--fs-xs); letter-spacing: .06em; text-transform: uppercase; color: var(--on-dark-dim); }
.s-light .ficha__l, .s-gray .ficha__l { color: var(--gray-400); }
.ficha__v { font-family: var(--font-display); font-weight: 600; font-size: var(--fs-md); }
/* Celda de ficha cuyo valor es una frase, no una cifra. En /empresa/ la
   cuarta celda describe el equipamiento propio: puesta en la tipografia de
   las cifras se leia como un titular roto. */
.ficha__v--texto { font-family: var(--font); font-weight: 400; font-size: var(--fs-sm); line-height: 1.5; }

/* Antes | Durante | Después */
.phases { display: grid; gap: var(--s-3); grid-template-columns: repeat(3, 1fr); }
.phase { position: relative; overflow: hidden; border-radius: var(--r-md); margin: 0; }
.phase img { width: 100%; aspect-ratio: 3/4; object-fit: cover; }
.phase__label {
  position: absolute; top: var(--s-2); left: var(--s-2);
  font-family: var(--font-mono); font-size: var(--fs-xs); letter-spacing: .1em; text-transform: uppercase;
  background: rgba(6,15,28,.85); color: #fff; padding: 4px var(--s-2); border-radius: var(--r-sm);
}

/* --- 14. Capacidad operativa (§8) --------------------------------------- */
.caps { display: grid; gap: 1px; background: var(--line-dark); border: 1px solid var(--line-dark); grid-template-columns: repeat(2, 1fr); }
.s-light .caps, .s-gray .caps { background: var(--line-light); border-color: var(--line-light); }
@media (min-width: 768px)  { .caps { grid-template-columns: repeat(4, 1fr); } }
.cap { background: var(--navy-900); padding: var(--s-6) var(--s-4); text-align: center; transition: background-color .2s var(--ease); }
.s-light .cap, .s-gray .cap { background: var(--white); }
.cap:hover { background: var(--navy-700); }
.s-light .cap:hover, .s-gray .cap:hover { background: var(--blue-050); }
.cap .icon { color: var(--blue); margin: 0 auto var(--s-3); }
.cap__name { font-family: var(--font-display); font-size: var(--fs-sm); font-weight: 600; margin: 0; }

/* --- 15. Seguridad (§7) — bloque con foto de obra a sangre -------------- */
.safety { position: relative; overflow: hidden; background: var(--navy-950); }
.safety__bg { position: absolute; inset: 0; z-index: 0; }
.safety__bg img { width: 100%; height: 100%; object-fit: cover; opacity: .26; }
.safety__bg::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, var(--navy-950) 0%, rgba(10,26,47,.9) 55%, rgba(10,26,47,.55) 100%);
}
.safety > .wrap { position: relative; z-index: 1; }

/* --- 16. Listas --------------------------------------------------------- */
.checklist { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-4); }
@media (min-width: 768px) { .checklist--2 { grid-template-columns: repeat(2, 1fr); } }
.checklist li { display: flex; align-items: flex-start; gap: var(--s-3); }
.checklist .icon { color: var(--blue); margin-top: 3px; flex: none; }
.checklist strong { display: block; font-size: var(--fs-sm); margin-bottom: 2px; }
.checklist span { display: block; font-size: var(--fs-sm); color: var(--on-dark-soft); }
.s-light .checklist span, .s-gray .checklist span { color: var(--on-light-soft); }

/* "Qué incluye" en las páginas de servicio */
.includes { list-style: none; margin: 0; padding: 0; display: grid; gap: 1px; background: var(--line-dark); border: 1px solid var(--line-dark); }
.s-light .includes, .s-gray .includes { background: var(--line-light); border-color: var(--line-light); }
@media (min-width: 768px) { .includes { grid-template-columns: repeat(2, 1fr); } }
.includes li { background: var(--navy-900); padding: var(--s-5); position: relative; }
.s-light .includes li, .s-gray .includes li { background: var(--white); }
.includes strong { display: block; font-family: var(--font-display); font-size: var(--fs-md); font-weight: 600; margin-bottom: var(--s-2); }
.includes p { font-size: var(--fs-sm); margin: 0; }

.tags { display: flex; flex-wrap: wrap; gap: var(--s-2); list-style: none; margin: 0; padding: 0; }
.tags li {
  font-size: var(--fs-xs); font-weight: 500; padding: var(--s-2) var(--s-4);
  border: 1px solid var(--line-dark-hi); color: var(--on-dark-soft); border-radius: var(--r-full);
}
.s-light .tags li, .s-gray .tags li { border-color: var(--gray-200); color: var(--on-light-soft); }

/* --- 17. Respuesta directa (AEO) ----------------------------------------
   El bloque que extraen y citan los asistentes de IA. Tiene selector propio
   porque es lo que declara 'speakable' en el Schema. */
.answer { border-left: 4px solid var(--blue); padding: var(--s-5) var(--s-5) var(--s-5) var(--s-6); background: var(--navy-900); }
.s-light .answer, .s-gray .answer { background: var(--gray-050); }
@media (min-width: 1024px) { .answer { padding: var(--s-6) var(--s-7); } }
.answer__q { font-family: var(--font-display); font-size: var(--fs-lg); font-weight: 600; margin: 0 0 var(--s-3); text-transform: none; }
.s-navy .answer__q, .s-navy-d .answer__q, .s-ink .answer__q { color: #fff; }
.s-light .answer__q, .s-gray .answer__q { color: var(--navy-900); }
.answer__a { font-size: var(--fs-md); margin: 0; line-height: 1.65; }
.s-navy .answer__a, .s-navy-d .answer__a, .s-ink .answer__a { color: var(--on-dark); }
/* Desarrollo del bloque de respuesta. Va un punto por debajo de .answer__a
   en tamano y en color: el parrafo citable tiene que seguir siendo el que
   destaca, no el que viene despues. */
.answer__mas { font-size: var(--fs-sm); line-height: 1.7; margin: var(--s-4) 0 0; max-width: 78ch; }
.s-navy .answer__mas, .s-navy-d .answer__mas, .s-ink .answer__mas { color: var(--on-dark-soft); }
.s-light .answer__mas, .s-gray .answer__mas { color: var(--on-light-soft); }

.answer__links { display: flex; flex-wrap: wrap; gap: var(--s-5); margin-top: var(--s-5); padding-top: var(--s-4); border-top: 1px solid var(--line-dark); }
.s-light .answer__links, .s-gray .answer__links { border-top-color: var(--line-light); }

/* --- 18. Preguntas frecuentes -------------------------------------------
   Van plegadas al final de cada página: arriba la página tiene que vender
   ("muy poco texto por pantalla"), pero el texto debe existir en el HTML
   porque es lo que sostiene el FAQPage del Schema y lo que citan los
   asistentes. El acordeón solo lo colapsa visualmente. */
.faq { border-top: 1px solid var(--line-dark); }
.s-light .faq, .s-gray .faq { border-top-color: var(--line-light); }
.faq__item { border-bottom: 1px solid var(--line-dark); }
.s-light .faq__item, .s-gray .faq__item { border-bottom-color: var(--line-light); }
.faq__q {
  display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s-4);
  width: 100%; padding: var(--s-5) 0; min-height: var(--tap);
  background: none; border: 0; cursor: pointer; text-align: left;
  font-family: var(--font-display); font-size: var(--fs-md); font-weight: 600;
  color: inherit; transition: color .18s var(--ease);
}
.faq__q:hover { color: var(--blue-400); }
.s-light .faq__q:hover, .s-gray .faq__q:hover { color: var(--blue-600); }
.faq__q .icon { flex: none; margin-top: 3px; color: var(--blue); transition: transform .25s var(--ease); }
.faq__item.is-open .faq__q .icon { transform: rotate(45deg); }
.faq__a { display: none; padding: 0 0 var(--s-5); max-width: 80ch; }
.faq__a p:last-child { margin-bottom: 0; }
/* El botón vive dentro de un <h3>, así que .faq__a NO es su hermano
   adyacente: el estado se lleva en la clase del contenedor. */
.faq__item.is-open .faq__a { display: block; animation: fadeUp .3s var(--ease-out); }
/* Sin JavaScript todas las respuestas quedan visibles y rastreables. */
.no-js .faq__a { display: block; }
@keyframes fadeUp { from { opacity: 0; transform: translateY(-5px); } to { opacity: 1; transform: none; } }

/* --- 19. Formularios ---------------------------------------------------- */
.form { background: var(--white); color: var(--on-light); padding: var(--s-5); border-radius: var(--r-md); box-shadow: var(--shadow-md); }
@media (min-width: 1024px) { .form { padding: var(--s-7); } }
.form h2 { color: var(--navy-900); font-size: var(--fs-xl); }
.form p { color: var(--on-light-soft); }
.form__grid { display: grid; gap: var(--s-4); }
@media (min-width: 640px) { .form__grid--2 { grid-template-columns: 1fr 1fr; } }

.field { display: flex; flex-direction: column; gap: var(--s-2); }
.field--full { grid-column: 1 / -1; }
.field > label { font-size: var(--fs-sm); font-weight: 600; color: var(--navy-900); }
.field .req { color: var(--blue); }
.field input, .field select, .field textarea {
  font: inherit; font-size: var(--fs-base);   /* 16px: evita el zoom de iOS */
  width: 100%; min-height: var(--tap); padding: var(--s-3) var(--s-4);
  background: var(--gray-050); color: var(--on-light);
  border: 1px solid var(--gray-200); border-radius: var(--r-md);
  transition: border-color .18s var(--ease), box-shadow .18s var(--ease), background-color .18s var(--ease);
}
.field textarea { min-height: 120px; resize: vertical; line-height: 1.55; }
.field input::placeholder, .field textarea::placeholder { color: var(--gray-400); }
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none; background: var(--white);
  border-color: var(--blue); box-shadow: 0 0 0 3px var(--blue-dim);
}
.field__hint { font-size: var(--fs-xs); color: var(--gray-400); }
.field__error { font-size: var(--fs-sm); color: var(--err); }
.field.has-error input, .field.has-error select, .field.has-error textarea { border-color: var(--err); }

/* Adjuntar fotografías — §11 del documento:
   "El administrador puede mandar las fotos directamente." */
.dropzone {
  display: flex; flex-direction: column; align-items: center; gap: var(--s-2);
  padding: var(--s-6) var(--s-4); text-align: center; cursor: pointer; position: relative;
  border: 2px dashed var(--gray-200); border-radius: var(--r-md);
  background: var(--gray-050); color: var(--on-light-soft);
  transition: border-color .2s var(--ease), background-color .2s var(--ease);
}
.dropzone:hover, .dropzone.is-over { border-color: var(--blue); background: var(--blue-050); }
.dropzone .icon { color: var(--blue); }
.dropzone strong { font-size: var(--fs-sm); color: var(--navy-900); }
.dropzone small { font-size: var(--fs-xs); color: var(--gray-400); }
.dropzone input[type="file"] { position: absolute; width: 1px; height: 1px; opacity: 0; }
.filelist { list-style: none; margin: var(--s-3) 0 0; padding: 0; display: grid; gap: var(--s-2); }
.filelist li {
  display: flex; align-items: center; gap: var(--s-3); font-size: var(--fs-sm);
  background: var(--gray-050); border: 1px solid var(--gray-200); border-radius: var(--r-sm);
  padding: var(--s-2) var(--s-3); color: var(--on-light);
}
.filelist .icon { color: var(--gray-400); }
.filelist span { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.filelist button { background: none; border: 0; color: var(--gray-400); cursor: pointer; padding: 4px; line-height: 0; }
.filelist button:hover { color: var(--err); }

.form__legal { font-size: var(--fs-xs); color: var(--gray-400); margin: var(--s-4) 0 0; }
.alert { padding: var(--s-4); border-radius: var(--r-md); font-size: var(--fs-sm); border: 1px solid; }
.alert--error   { background: var(--err-dim); border-color: rgba(214,69,74,.35); color: #9B2C2F; }
.alert--success { background: var(--ok-dim);  border-color: rgba(30,158,99,.35); color: #14663F; }

/* --- 20. Banda de llamada a la acción ----------------------------------- */
.cta-band { background: var(--blue); position: relative; overflow: hidden; }
.cta-band::before {
  content: ""; position: absolute; inset: 0;
  background: radial-gradient(900px 380px at 12% 0%, rgba(255,255,255,.14), transparent 62%);
}
.cta-band > .wrap { position: relative; }
.cta-band__inner { display: grid; gap: var(--s-5); align-items: center; }
@media (min-width: 900px) { .cta-band__inner { grid-template-columns: 1fr auto; gap: var(--s-8); } }
.cta-band .eyebrow { color: rgba(255,255,255,.8); }
.cta-band h2 { color: #fff; margin: 0; max-width: 22ch; }
.cta-band p { color: rgba(255,255,255,.88); margin: var(--s-4) 0 0; max-width: 56ch; }

/* --- 21. Pie ------------------------------------------------------------ */
.site-footer { background: var(--navy-950); border-top: 1px solid var(--line-dark); padding-block: var(--s-8) var(--s-6); font-size: var(--fs-sm); }
.site-footer__grid { display: grid; gap: var(--s-7); grid-template-columns: 1fr; }
@media (min-width: 768px)  { .site-footer__grid { grid-template-columns: 1.5fr 1fr 1fr; } }
@media (min-width: 1100px) { .site-footer__grid { grid-template-columns: 1.7fr 1fr 1fr 1.1fr; } }
.site-footer h3 {
  font-family: var(--font); font-size: var(--fs-xs); font-weight: 700;
  letter-spacing: var(--track-caps); text-transform: uppercase;
  color: var(--blue-400); margin-bottom: var(--s-4);
}
.site-footer ul { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-3); }
.site-footer a { color: var(--on-dark-soft); text-decoration: none; }
.site-footer a:hover { color: #fff; }
.site-footer p { color: var(--on-dark-soft); }
.site-footer__brand img { height: 44px; width: auto; margin-bottom: var(--s-4); }
.site-footer__claim { font-family: var(--font-display); font-size: var(--fs-md); font-weight: 500; color: var(--blue-400); margin-bottom: var(--s-3); }
.site-footer__bottom {
  display: flex; flex-wrap: wrap; gap: var(--s-3) var(--s-5);
  justify-content: space-between; align-items: center;
  margin-top: var(--s-7); padding-top: var(--s-5); border-top: 1px solid var(--line-dark);
  font-size: var(--fs-xs); color: var(--on-dark-dim);
}
.site-footer__legal { display: flex; flex-wrap: wrap; gap: var(--s-4); list-style: none; margin: 0; padding: 0; }
.social { display: flex; gap: var(--s-2); margin-top: var(--s-4); }
.social a { display: grid; place-items: center; width: 40px; height: 40px; border: 1px solid var(--line-dark-hi); border-radius: var(--r-md); color: var(--on-dark-soft); }
.social a:hover { border-color: var(--blue); color: var(--blue-400); }

/* --- 22. Botón flotante de WhatsApp ------------------------------------- */
.fab {
  position: fixed; right: var(--s-4); bottom: var(--s-4); z-index: 80;
  display: inline-flex; align-items: center; gap: var(--s-3);
  min-height: 54px; padding: var(--s-3) var(--s-5);
  background: #1FA855; color: #fff; text-decoration: none;
  border-radius: var(--r-full); box-shadow: var(--shadow-md);
  font-size: var(--fs-sm); font-weight: 700;
  transition: transform .25s var(--ease), background-color .2s var(--ease);
}
.fab:hover { background: #17904A; color: #fff; }
.fab .icon { width: 24px; height: 24px; }
.fab.is-pending { background: var(--gray-400); }
/* Mientras el visitante baja leyendo, el flotante se atenúa para no robar
   atención al texto. Nunca desaparece ni se sale de la pantalla: sigue
   siendo tocable en todo momento. En escritorio sobra espacio y no estorba,
   así que allí no se toca. */
@media (max-width: 899px) {
  .is-reading .fab { opacity: .5; }
  .is-reading .fab:hover, .is-reading .fab:focus-visible { opacity: 1; }
}
@media (max-width: 639px) {
  .fab__label { display: none; }
  .fab { padding: var(--s-3); width: 56px; justify-content: center; }
}

/* --- 23. Marcadores de contenido pendiente ------------------------------
   Regla del proyecto: nunca lorem ipsum. Siempre un marcador visible para
   que sea evidente qué falta antes de publicar. */
.pending {
  display: inline-block; font-family: var(--font-mono); font-size: var(--fs-xs);
  background: var(--warn-dim); color: #E8C77A; border: 1px dashed rgba(214,158,46,.45);
  padding: 2px var(--s-2); border-radius: var(--r-sm);
}
.s-light .pending, .s-gray .pending { color: #8A6212; border-color: rgba(184,132,26,.5); background: #FDF6E3; }
/* Sobre la franja azul de cifras el amarillo desaparece: allí va en blanco. */
.stats .pending { color: #fff; background: rgba(6,15,28,.28); border-color: rgba(255,255,255,.45); }
.ph {
  display: grid; place-content: center; gap: var(--s-2); text-align: center;
  aspect-ratio: var(--ratio, 16/9); padding: var(--s-5);
  background: var(--graphite); border: 1px dashed var(--line-dark-hi);
  border-radius: var(--r-md); color: var(--on-dark-dim);
  background-image: repeating-linear-gradient(45deg, transparent, transparent 11px, rgba(255,255,255,.016) 11px, rgba(255,255,255,.016) 22px);
}
.s-light .ph, .s-gray .ph { background: var(--gray-050); border-color: var(--gray-200); color: var(--gray-400); background-image: repeating-linear-gradient(45deg, transparent, transparent 11px, rgba(10,26,47,.03) 11px, rgba(10,26,47,.03) 22px); }
.ph__label { font-family: var(--font-mono); font-size: var(--fs-xs); color: #E8C77A; }
.s-light .ph__label, .s-gray .ph__label { color: #8A6212; }
.ph__hint { font-size: var(--fs-xs); max-width: 42ch; margin-inline: auto; }

/* --- 24. Prosa (textos legales, artículos) ------------------------------ */
.prose { max-width: 74ch; }
.prose h2 { margin-top: var(--s-8); font-size: var(--fs-xl); }
.prose h3 { margin-top: var(--s-6); text-transform: none; }
.prose ul, .prose ol { padding-left: 1.3rem; }
.prose li { margin-bottom: var(--s-2); }
.prose li::marker { color: var(--blue); }
.prose blockquote { margin: var(--s-6) 0; padding: var(--s-4) var(--s-5); border-left: 4px solid var(--blue); background: var(--navy-900); }
.s-light .prose blockquote, .s-gray .prose blockquote { background: var(--gray-050); }
.prose blockquote p:last-child { margin-bottom: 0; }
.prose table { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); margin-bottom: var(--s-5); }
.prose th, .prose td { text-align: left; padding: var(--s-3); border-bottom: 1px solid var(--line-dark); }
.s-light .prose th, .s-light .prose td, .s-gray .prose th, .s-gray .prose td { border-bottom-color: var(--line-light); }
.prose th { font-weight: 700; }
/* Cualquier tabla ancha desborda dentro de su propio contenedor, nunca el body. */
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* --- 25. Migas de pan --------------------------------------------------- */
.breadcrumbs { font-size: var(--fs-xs); padding-block: var(--s-4) var(--s-5); }
.breadcrumbs ol { display: flex; flex-wrap: wrap; gap: var(--s-2); list-style: none; margin: 0; padding: 0; }
.breadcrumbs li { color: var(--on-dark-dim); }
.s-light .breadcrumbs li, .s-gray .breadcrumbs li { color: var(--gray-400); }
.breadcrumbs li:not(:last-child)::after { content: "/"; margin-left: var(--s-2); opacity: .5; }
.breadcrumbs a { color: inherit; text-decoration: none; }
.breadcrumbs a:hover { color: var(--blue-400); }

/* --- 26. Cabecera de página interior ------------------------------------ */
.page-head {
  position: relative; overflow: hidden; background: var(--navy-900);
  /* Se mete bajo la cabecera transparente y le devuelve el espacio con
     padding, para que el degradado de la cabecera caiga sobre la imagen y
     no sobre el fondo plano de la sección anterior. */
  margin-top: calc(var(--header-h) * -1);
  padding-top: calc(var(--header-h) + var(--s-7));
  padding-bottom: var(--s-8);
}
@media (min-width: 1024px) { .page-head { padding-bottom: var(--s-9); } }
/* El último elemento de la cabecera no debe quedar pegado al borde. */
.page-head > .wrap > :last-child { margin-bottom: 0; }
.page-head__bg { position: absolute; inset: 0; z-index: 0; }
.page-head__bg img { width: 100%; height: 100%; object-fit: cover; opacity: .3; }
.page-head__bg::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, var(--navy-950) 10%, rgba(10,26,47,.86) 60%, rgba(10,26,47,.5) 100%);
}
.page-head > .wrap { position: relative; z-index: 1; }
.page-head h1 { max-width: 18ch; }
.page-head .lead { color: var(--on-dark-soft); }

/* --- 27. Aviso de cookies ----------------------------------------------- */
.cookiebar {
  position: fixed; left: var(--s-4); right: var(--s-4); bottom: var(--s-4); z-index: 95;
  max-width: 520px; display: none; flex-direction: column; gap: var(--s-4);
  background: var(--white); color: var(--on-light);
  border-radius: var(--r-md); padding: var(--s-5); box-shadow: var(--shadow-lg);
  border-top: 4px solid var(--blue);
}
.cookiebar.is-visible { display: flex; animation: fadeUp .35s var(--ease-out); }
.cookiebar p { font-size: var(--fs-sm); margin: 0; color: var(--on-light-soft); }
.cookiebar__actions { display: flex; flex-wrap: wrap; gap: var(--s-2); }
@media (min-width: 640px) { .cookiebar { left: auto; right: var(--s-5); bottom: var(--s-5); } }

/* --- 28. Aparición al hacer scroll --------------------------------------
   "Animaciones sutiles": 14px y opacidad, una sola vez, y nada más. */
[data-reveal] { opacity: 0; transform: translateY(14px); }
[data-reveal].is-visible { opacity: 1; transform: none; transition: opacity .6s var(--ease-out), transform .6s var(--ease-out); }
[data-reveal].is-visible:nth-child(2) { transition-delay: .07s; }
[data-reveal].is-visible:nth-child(3) { transition-delay: .14s; }
[data-reveal].is-visible:nth-child(4) { transition-delay: .21s; }
@media (prefers-reduced-motion: reduce) { [data-reveal] { opacity: 1; transform: none; } }

/* --- 28b. Asistente ------------------------------------------------------
   Lanzador redondo bajo el flotante de WhatsApp y panel que sube desde
   abajo. En móvil ocupa casi toda la pantalla; en escritorio es una columna
   estrecha anclada a la esquina. */
.chat-launcher {
  position: fixed; right: var(--s-4); bottom: calc(var(--s-4) + 68px); z-index: 80;
  width: 54px; height: 54px; display: grid; place-items: center;
  background: var(--navy-800); color: #fff; cursor: pointer;
  border: 1px solid var(--line-dark-hi); border-radius: 50%;
  box-shadow: var(--shadow-md);
  transition: background-color .2s var(--ease), transform .25s var(--ease);
}
.chat-launcher:hover { background: var(--navy-700); }
@media (max-width: 899px) {
  .is-reading .chat-launcher { opacity: .5; }
  .is-reading .chat-launcher:hover, .is-reading .chat-launcher:focus-visible { opacity: 1; }
}
.chat-open .chat-launcher { display: none; }

.chat {
  position: fixed; z-index: 96; right: var(--s-4); bottom: var(--s-4);
  left: var(--s-4); max-height: min(78svh, 620px);
  display: none; flex-direction: column; overflow: hidden;
  background: var(--white); color: var(--on-light);
  border-radius: var(--r-lg); box-shadow: var(--shadow-lg);
  border-top: 4px solid var(--blue);
}
.chat.is-open { display: flex; animation: fadeUp .3s var(--ease-out); }
@media (min-width: 640px) { .chat { left: auto; width: 380px; right: var(--s-5); bottom: var(--s-5); } }

.chat__head {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-3);
  padding: var(--s-4) var(--s-5); border-bottom: 1px solid var(--line-light);
}
.chat__head strong { display: block; font-family: var(--font-display); font-size: var(--fs-md); color: var(--navy-900); }
.chat__head span { display: block; font-size: var(--fs-xs); color: var(--gray-400); }
.chat__close { background: none; border: 0; color: var(--gray-400); cursor: pointer; padding: var(--s-2); line-height: 0; }
.chat__close:hover { color: var(--navy-900); }

.chat__log { flex: 1; overflow-y: auto; padding: var(--s-4) var(--s-5); display: grid; gap: var(--s-3); align-content: start; }

/* LAS BURBUJAS.
   Durante un tiempo esto no pintó nada: chat.js emitía `msg msg--user` y aquí
   solo existía `.chat__msg--user`. Las clases nunca coincidieron, así que los
   mensajes salían como texto suelto y no se distinguía quién decía qué. Si se
   vuelve a tocar el nombre de una clase, hay que tocarlo en los DOS sitios.

   Tres roles, y los tres los decide chat.js: 'user', 'bot' y 'sys'.
   'sys' son los avisos del propio widget —límite de mensajes alcanzado, fallo
   de red—, y no puede parecer que los dice el asistente: si el visitante lee
   "no pude responder" dentro de una burbuja del bot, entiende que la empresa
   no supo contestarle. */
.chat__msg {
  max-width: 88%; font-size: var(--fs-sm); line-height: 1.55;
  padding: var(--s-3) var(--s-4); border-radius: var(--r-lg);
}
.chat__msg--bot {
  background: var(--gray-050); color: var(--on-light);
  justify-self: start; border-bottom-left-radius: var(--r-sm);
}
/* El del visitante es el único elemento azul del panel, y va a la derecha:
   color y lado dicen lo mismo por dos vías, que es lo que hace que se lea
   de un vistazo sin tener que leerlo. */
.chat__msg--user {
  background: var(--blue); color: #fff;
  justify-self: end; border-bottom-right-radius: var(--r-sm);
}
/* Ni burbuja ni lado: es el widget hablando, no una de las dos partes. */
.chat__msg--sys {
  justify-self: stretch; max-width: 100%; text-align: center;
  background: none; padding: var(--s-2) 0;
  font-size: var(--fs-xs); color: var(--gray-400);
}
.chat__msg a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }

/* Puntos de "escribiendo". Sin esto el hueco de espera quedaba vacío y
   parecía que el envío no había salido. */
.chat__typing { display: inline-flex; gap: 4px; align-items: center; padding: 2px 0; }
.chat__typing i {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--gray-400); display: block;
  animation: chat-dot 1.2s var(--ease) infinite;
}
.chat__typing i:nth-child(2) { animation-delay: .15s; }
.chat__typing i:nth-child(3) { animation-delay: .3s; }
@keyframes chat-dot {
  0%, 60%, 100% { opacity: .3; transform: translateY(0); }
  30%           { opacity: 1;  transform: translateY(-3px); }
}
@media (prefers-reduced-motion: reduce) {
  .chat__typing i { animation: none; opacity: .55; }
}

/* Botón de paso a WhatsApp dentro del chat. Verde de WhatsApp y no el azul
   del sitio: es el único punto donde el visitante sale a otra aplicación, y
   conviene que se vea que va allí. */
.btn--wa { background: #1FA855; color: #fff; border-color: #1FA855; }
.btn--wa:hover { background: #17904A; border-color: #17904A; color: #fff; }

.chat__chips { display: flex; flex-wrap: wrap; gap: var(--s-2); padding: 0 var(--s-5) var(--s-3); }
.chat__chips button {
  font-size: var(--fs-xs); padding: var(--s-2) var(--s-3); cursor: pointer;
  background: var(--white); color: var(--blue-600);
  border: 1px solid var(--gray-200); border-radius: var(--r-full);
}
.chat__chips button:hover { border-color: var(--blue); background: var(--blue-050); }

.chat__form { display: flex; gap: var(--s-2); padding: var(--s-3) var(--s-4) var(--s-4); border-top: 1px solid var(--line-light); }
.chat__input {
  flex: 1; font: inherit; font-size: var(--fs-base); min-height: var(--tap);
  padding: var(--s-2) var(--s-4); color: var(--on-light);
  background: var(--gray-050); border: 1px solid var(--gray-200); border-radius: var(--r-full);
}
.chat__input:focus { outline: none; background: #fff; border-color: var(--blue); box-shadow: 0 0 0 3px var(--blue-dim); }
.chat__send {
  width: var(--tap); height: var(--tap); flex: none; display: grid; place-items: center;
  background: var(--blue); color: #fff; border: 0; border-radius: 50%; cursor: pointer;
}
.chat__send:hover { background: var(--blue-600); }
.chat__send:disabled { opacity: .5; cursor: default; }
.chat__status { font-size: var(--fs-xs); color: var(--gray-400); margin: 0; padding: 0 var(--s-5) var(--s-4); }
.chat__status:empty { display: none; }

/* --- 29. Barra de avisos SEO (solo desarrollo) -------------------------- */
.devbar {
  position: fixed; left: var(--s-3); bottom: var(--s-3); z-index: 120; max-width: 380px;
  background: var(--err-dim); border: 1px solid rgba(214,69,74,.45); color: #FFB4B6;
  border-radius: var(--r-md); padding: var(--s-3) var(--s-4); font-size: var(--fs-xs);
}
.devbar ul { margin: var(--s-2) 0 0; padding-left: 1.1rem; }

/* --- 29b. Equilibrio de superficies --------------------------------------
   El sitio nació muy oscuro: en la portada había siete secciones marinas
   frente a cinco claras. El cliente pidió aclararlo, así que el reparto se
   invirtió — claro por defecto, oscuro como puntuación.

   Lo oscuro que QUEDA, y por qué cada uno:
   · El hero. Lleva el video de dron detrás; en claro el texto se cae.
   · El bloque de respuesta directa (answer-block), en TODAS las páginas.
     Es el párrafo que declara `speakable` para los asistentes de IA y
     conviene que se distinga del resto de un vistazo. Es la única banda
     oscura que se repite, y eso lo vuelve un patrón reconocible.
   · La franja de seguridad, que es una fotografía a sangre.
   · La llamada final a solicitar inspección: cierra la página con peso.

   Ojo si se añaden secciones: el ritmo va alternando claro y gris, y las
   bandas oscuras deben quedar separadas por al menos tres secciones. Dos
   oscuras seguidas devuelven el sitio a lo que era.

   ADVERTENCIA HONESTA: el documento del cliente decía "la imagino oscura,
   técnica y premium". Esto se aparta de esa frase a petición expresa suya,
   posterior al documento. Si el cliente final lo cuestiona, la conversación
   es esa y no un descuido. */

/* --- 30. Titular cinético del hero --------------------------------------
   El h1 del inicio está vivo: las letras entran escalonadas, una luz lo
   recorre solo al terminar de entrar, y responde al dedo o al cursor. Es lo
   único animado del sitio a propósito — un titular que responde se lee como
   trabajo hecho a medida, que es lo que pide el §1 del documento.

   ESTÁ PENSADO PARA MÓVIL, no adaptado a móvil: ahí está el 90 % del
   tráfico. Como en un teléfono no hay cursor que seguir, la luz hace una
   pasada sola después de la entrada, y a partir de ahí sigue al dedo si se
   arrastra sobre el hero. En escritorio, lo mismo con el ratón.

   DOS CANDADOS:
   · Si el visitante pidió reducir movimiento, no se trocea nada.
   · Nada de `will-change`. Son ~40 letras: promoverlas todas a capa propia
     es el error que ya costó una sesión con el duotono de las fotos. Con
     transform 2D basta y el compositor no se llena.

   El marcado que llega del servidor es texto plano; el troceado lo hace
   main.js tras cargar la fuente. Sin JavaScript el titular es un h1 normal,
   y el texto accesible es idéntico en los dos casos. */

.hero h1 .kw { display: inline-block; }
.hero h1 .kl { display: inline-block; transform: translateY(var(--ky, 0px)); }

/* La transición solo existe FUERA del seguimiento: mientras la letra
   persigue al dedo, interpolar añade retardo a cada fotograma. */
.hero h1:not(.is-tracking) .kl { transition: transform .5s var(--ease); }

/* Entrada. `backwards` mantiene la letra oculta durante su propio retardo;
   sin eso aparecen todas de golpe y luego saltan.
   El escalonado se corta a 12 ms por letra para que el titular entero esté
   pintado antes de 700 ms: por encima de eso empieza a contar contra el LCP,
   que en el inicio ya lo marca el póster del video. */
.hero h1.is-kinetic .kl {
  animation: kl-in .5s cubic-bezier(.2, .75, .25, 1) backwards;
  animation-delay: calc(var(--i) * 12ms);
}
@keyframes kl-in {
  from { opacity: 0; transform: translateY(.5em); }
  to   { opacity: 1; transform: translateY(0); }
}

/* LA LUZ.
   Va en CADA LETRA, no en el <em>. Ese fue el fallo de la primera versión:
   `background-clip: text` recorta el fondo contra el texto del PROPIO
   elemento, y al trocear el titular el texto pasó a estar en <span> hijos.
   El <em> se quedaba sin texto que recortar mientras `-webkit-text-fill-color:
   transparent` SÍ se heredaba a los hijos — resultado: la segunda línea del
   titular desaparecía entera.

   Para que las letras compartan un mismo foco y no tenga cada una el suyo,
   cada letra guarda su desplazamiento dentro del h1 (--ox/--oy) y el centro
   del degradado se calcula restándolo. Así hay un solo sistema de
   coordenadas, el del titular completo.

   La luz no puede ser el azul de marca: si el énfasis ya es azul, un foco
   azul sobre letras azules no se ve. El centro es un azul casi blanco y el
   aro sí es el de marca, así se nota sea cual sea el color del titular. */
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .hero h1.is-kinetic .kl {
    --klight: #DCEBFF;
    background-image:
      radial-gradient(var(--kr, 190px) var(--kr, 190px)
                      at calc(var(--mx, -9999px) - var(--ox, 0px))
                         calc(var(--my, -9999px) - var(--oy, 0px)),
                      var(--klight) 0%, var(--blue-400) 42%, transparent 70%),
      linear-gradient(currentColor, currentColor);
    -webkit-background-clip: text;
            background-clip: text;
    -webkit-text-fill-color: transparent;
  }
}

/* --- 31. Utilidades de visibilidad --------------------------------------
   Van al final: aquí sí ganan a .btn y al resto de componentes. */
.hide-sm { display: none; }
@media (min-width: 1024px) { .hide-sm { display: inline-flex; } }
.hide-lg { display: block; }
@media (min-width: 1024px) { .hide-lg { display: none; } }
