/* ============================================================
   TIGERVOLT — ARCHIVO GENERADO. NO EDITAR A MANO.
   Se arma con ./build-css.sh desde los cuatro parciales:
     css/_00-base.css       tokens, reset, nav, footer, botones
     css/_10-hero.css       hero, norma, triaje, tesis
     css/_20-servicios.css  servicios, marcas, protocolo
     css/_30-prueba.css     acreditacion, metodo, terreno, cobertura, cierre
   Edita el parcial que corresponda y vuelve a correr el script.
   ============================================================ */

/* ============================================================
   TIGERVOLT — PROTOCOLO 0,1 Hz
   css/_00-base.css — BASE DEL SISTEMA. Primer archivo concatenado.

   Contiene, en orden:
     01  Tokens maestros (:root)          07  Botones y enlaces
     02  Tipografía (@font-face)          08  Foco visible global
     03  Reset                            09  Grano y viñeta (efecto firma 5)
     04  Base html / body / tipografía    10  Nav persistente
     05  Utilidades y sistema de sección  11  Pie
     06  Capa mono / datos / reveal       12  Dock WhatsApp + banner de cookies
                                          13  Reduced motion (bloque global)

   REGLAS DE ESTE ARCHIVO
   · Ningún color, radio, curva o tamaño fuera del bloque :root.
   · Todo lo que OCULTE algo para animarlo va prefijado `.js`.
     Sin JavaScript el sitio se lee al 100%.
   · Hover siempre dentro de @media (hover:hover) and (pointer:fine).
   · Breakpoints min-width: 560 / 768 / 900 / 1024 / 1200. Alturas svh/dvh.
   ============================================================ */


/* ============================================================
   01 · TOKENS MAESTROS
   ============================================================ */

:root{
  /* ---------- SUSTRATO (82% de la superficie) ----------
     Negros con sesgo azul: hacen que el naranja lea más caliente
     sin tocar el hex de marca. */
  --void:#05070A;            /* fondo de página */
  --carbon:#0B0D12;          /* secciones alternas */
  --panel:#12151C;           /* tarjeta, barra, bloque denso en texto */
  --pozo:#030407;            /* hueco/inset: canvas wells, preview mono */
  --linea:#1E232D;           /* hairline estructural 1px (90% de bordes) */
  --linea-viva:#2A313E;      /* hairline en hover/focus */
  --linea-carga:rgba(255,107,0,.45); /* hairline energizado */

  /* ---------- PLASMA (2%, y por eso funciona) ---------- */
  --plasma:#F2F8FF;          /* núcleo de la onda, flash de CORTE, tesis */
  --arco-azul:#BFE6FF;       /* halo de onda, focus ring */
  --cian:#7DD3FC;            /* solo canvas y ejes. NUNCA en UI */

  /* ---------- MARCA (6%) ---------- */
  --naranja:#FF6B00;         /* core: CTA, bordes cargados, títulos ≥24px */
  --naranja-hot:#FF8C42;     /* hover, parada alta de gradiente */
  --naranja-ambar:#FFB347;   /* acento terciario, picos de descarga parcial */
  --naranja-lo:#7A3300;      /* naranja apagado: borde de panel activo */
  --naranja-wash:rgba(255,107,0,.08);
  --naranja-halo:rgba(255,107,0,.38);

  /* ---------- TEXTO (10%) ---------- */
  --txt:#E8EDF4;             /* titulares  ~16,5:1 sobre --void */
  --txt-2:#C7D0DC;           /* CUERPO POR DEFECTO  ~12,7:1 */
  --txt-3:#9AA4B2;           /* secundario, labels mono  ~8,0:1 */
  --txt-4:#6B7482;           /* SOLO decorativo/deshabilitado. Nunca informativo */
  --txt-sobre-naranja:#0A0500; /* ~6,9:1 sobre #FF6B00. JAMÁS blanco (3,2:1, reprueba AA) */

  /* ---------- PAPEL (inversión: sección protocolo) ----------
     Los dos bloques claros del sitio coinciden con los dos bloques
     donde todo es verdad o está marcado MUESTRA. El color codifica veracidad. */
  --papel:#F2F0EA;
  --papel-2:#E7E4DC;
  --papel-tinta:#12151C;     /* ~15,9:1 sobre --papel */
  --papel-tinta-2:rgba(18,21,28,.62);
  --papel-regla:#C9C5B8;
  --papel-timbre:#C0341F;

  /* ---------- SEÑAL FUNCIONAL (<1% de superficie) ---------- */
  --ok:#3FE08A;              /* SOLO el chip RESULTADO: APROBADO */
  --alarma:#FF4D4D;          /* SOLO el evento de falla del método. 2 apariciones máx */

  /* ---------- TIPOGRAFÍA ---------- */
  --f-display:'Big Shoulders Display','Archivo Narrow','Arial Narrow',
              'Helvetica Neue Condensed',BigShouldersFallback,sans-serif;
  --f-texto:'Inter',InterFallback,-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;
  --f-mono:'JetBrains Mono',ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;

  /* Escala fluida. Cada rol tiene UN token. No inventar tamaños. */
  --t-h1:clamp(3.6rem,15vw,13rem);        /* hero. lh .82 */
  --t-h2:clamp(2.4rem,6.5vw,5.75rem);     /* sección. lh .90 */
  --t-h3:clamp(1.6rem,3.4vw,2.75rem);     /* nombre de servicio. lh .98 */
  --t-h4:clamp(1.125rem,1.6vw,1.375rem);  /* subtítulo de bloque */
  --t-cifra:clamp(2.75rem,7vw,6rem);      /* números grandes, tabular */
  --t-lead:clamp(1.0625rem,1.4vw,1.3125rem);
  --t-body:clamp(1rem,.95rem + .25vw,1.125rem);
  --t-small:.9375rem;
  --t-mono:.8125rem;         /* lectura de datos */
  --t-mono-s:.6875rem;       /* kicker, slug, spec */
  --t-mono-xs:.625rem;       /* solo chips en móvil */

  --lh-h1:.82; --lh-h2:.90; --lh-h3:.98; --lh-body:1.65; --lh-lead:1.5;
  --ls-h1:-.02em; --ls-h2:-.015em; --ls-kicker:.22em; --ls-mono:.06em; --ls-slug:.14em;
  --w-medida:62ch;           /* ancho máximo de prosa. NUNCA más */
  --w-lead:46ch;

  /* ---------- ESPACIADO (escala de 4px) ---------- */
  --s-1:4px;  --s-2:8px;  --s-3:12px; --s-4:16px; --s-5:24px;
  --s-6:32px; --s-7:48px; --s-8:64px; --s-9:96px; --s-10:128px;
  --pad-seccion:clamp(72px,10vw,168px);
  --pad-seccion-aire:clamp(112px,16vw,240px); /* solo tesis */
  --gutter:clamp(20px,5vw,64px);
  --ancho-max:1320px;
  --ancho-angosto:820px;

  /* ---------- RADIOS. La infraestructura no tiene esquinas blandas ---------- */
  --r-1:2px;   /* chips, celdas, tablas */
  --r-2:6px;   /* botones, paneles */
  --r-3:10px;  /* máximo absoluto del sitio */

  /* ---------- Z-INDEX ---------- */
  --z-canvas:0; --z-grid:1; --z-contenido:10; --z-nav:100;
  --z-dock:200; --z-modal:300; --z-grano:9999;

  /* ---------- CURVAS CON NOMBRE. Cinco, ni una más ---------- */
  --e-revelado:cubic-bezier(.16,1,.3,1);   /* expo-out. caballo de batalla */
  --e-carga:cubic-bezier(.7,0,.84,0);      /* expo-IN. algo está POR disparar */
  --e-descarga:cubic-bezier(.22,1,.36,1);  /* decaimiento de chispa */
  --e-rele:cubic-bezier(.83,0,.17,1);      /* snap de contactor: estados binarios */
  --e-estado:cubic-bezier(.83,0,.17,1);    /* alias de --e-rele para transiciones de estado (panel, dock, cookies) */
  --e-micro:cubic-bezier(.4,0,.2,1);       /* hover, focus */

  --d-micro:140ms; --d-hover:180ms; --d-rele:240ms; --d-carga:320ms;
  --d-estado:420ms; --d-revelado:720ms; --d-largo:900ms;
  --stagger:70ms;
  --flash:90ms;              /* fotograma blanco del CORTE */

  /* ---------- BLOOM. Pares apilados de drop-shadow, jamás filter:blur() ---------- */
  --glow-naranja:drop-shadow(0 0 4px rgba(255,140,66,.9)) drop-shadow(0 0 24px rgba(255,107,0,.45));
  --glow-plasma:drop-shadow(0 0 3px rgba(242,248,255,.9)) drop-shadow(0 0 16px rgba(191,230,255,.35));
  --glow-txt:0 0 14px var(--naranja-halo);
  --sombra-panel:0 24px 60px -20px rgba(0,0,0,.85);
  --bisel:inset 0 1px 0 rgba(255,255,255,.045),inset 0 -1px 0 rgba(0,0,0,.55);
  --anillo-foco:0 0 0 2px var(--arco-azul);

  /* ---------- GRADIENTES. Solo dos, ambos funcionales ---------- */
  --grad-brasa:linear-gradient(180deg,#FF8C42 0%,#FF6B00 55%,#C24800 100%);
  --grad-descarga:linear-gradient(90deg,transparent,var(--plasma) 45%,var(--arco-azul) 55%,transparent);
  --grad-vineta:radial-gradient(ellipse 120% 80% at 50% 45%,transparent 35%,rgba(0,0,0,.55) 100%);
  --grad-legible:linear-gradient(90deg,var(--void) 0%,rgba(5,7,10,.85) 42%,transparent 78%);

  /* ---------- REJILLA TÉCNICA (solo 3 secciones: tesis, método, cobertura) ---------- */
  --grid-linea:rgba(232,244,255,.035);
  --grid-paso:48px;

  /* ---------- ALTURA DEL NAV (usada por scroll-padding y por el dock) ---------- */
  --h-nav:64px;

  color-scheme:dark;
}


/* ============================================================
   02 · TIPOGRAFÍA — @font-face
   Fuentes AUTO-HOSPEDADAS en /fonts/. Las rutas van relativas a
   css/styles.css (../fonts/…) para que resuelvan igual en raíz de
   dominio, en subdirectorio y en file:// durante la revisión.
   ============================================================ */

@font-face{font-family:'Big Shoulders Display';src:url('../fonts/big-shoulders-display-var-latin.woff2') format('woff2-variations');font-weight:400 900;font-display:swap;font-style:normal}
@font-face{font-family:'Inter';src:url('../fonts/inter-var-latin.woff2') format('woff2-variations');font-weight:400 700;font-display:swap;font-style:normal}
/* Un solo archivo para 400 y 500: el subset de JetBrains Mono descargado es el regular.
   Declararlo dos veces hacia que el navegador bajara 62 KB para una sola tipografia. */
@font-face{font-family:'JetBrains Mono';src:url('../fonts/jetbrains-mono-400-latin.woff2') format('woff2');font-weight:400 500;font-display:swap;font-style:normal}

/* Fallbacks métricos: matan el CLS del H1 gigante al hacer swap.
   Van junto a los tokens porque son parte del sistema tipográfico. */
@font-face{font-family:BigShouldersFallback;src:local('Arial Narrow'),local('Helvetica Neue Condensed'),local('Roboto Condensed'),local('Arial');size-adjust:64%;ascent-override:96%;descent-override:22%;line-gap-override:0%}
@font-face{font-family:InterFallback;src:local('Helvetica Neue'),local('Arial');size-adjust:107%;ascent-override:90%;descent-override:22%;line-gap-override:0%}


/* ============================================================
   03 · RESET
   ============================================================ */

*,*::before,*::after{box-sizing:border-box}

html{
  -webkit-text-size-adjust:100%;
  text-size-adjust:100%;
  scroll-padding-top:calc(var(--h-nav) + var(--s-5));
  -webkit-tap-highlight-color:transparent;
}

/* scroll-behavior condicionado: nunca se impone a quien pidió menos movimiento. */
@media (prefers-reduced-motion:no-preference){
  html{scroll-behavior:smooth}
}

body,h1,h2,h3,h4,h5,h6,p,figure,blockquote,dl,dd,dt,ol,ul,fieldset,legend,pre{margin:0;padding:0}
ul[class],ol[class]{list-style:none}
fieldset{border:0}

img,picture,video,canvas,svg{display:block;max-width:100%}
img{height:auto;border:0}

input,button,textarea,select{font:inherit;color:inherit;letter-spacing:inherit}
button{background:none;border:0;cursor:pointer}

table{border-collapse:collapse;border-spacing:0;width:100%}

/* Sin :target{scroll-margin-top}: se sumaba al scroll-padding-top del html y la
   llegada con #fragmento dejaba el destino a ~176 px del borde en vez de 88. */

::selection{background:var(--naranja);color:var(--txt-sobre-naranja)}


/* ============================================================
   04 · BASE — html / body / escala tipográfica
   ============================================================ */

html{background:var(--void)}

body{
  min-height:100svh;
  background:var(--void);
  color:var(--txt-2);
  font-family:var(--f-texto);
  font-size:var(--t-body);
  font-weight:400;
  line-height:var(--lh-body);
  font-synthesis-weight:none;
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
  text-rendering:optimizeLegibility;
  overflow-x:hidden;   /* fallback navegadores antiguos */
  overflow-x:clip;     /* preferido: no crea contenedor de scroll */
}

/* --- Titulares. La familia display es condensada y va SIEMPRE en versal. --- */
h1,h2,h3,h4,h5,h6,.h2,.h3{
  font-family:var(--f-display);
  font-weight:700;
  color:var(--txt);
  text-transform:uppercase;
  font-variant-numeric:tabular-nums;
}

h1{font-size:var(--t-h1);line-height:var(--lh-h1);letter-spacing:var(--ls-h1);font-weight:800}
/* Sin text-wrap:balance en el H1: los saltos son manuales (<br>) para que un
   fallback más ancho rompa en la misma cantidad de líneas. Es el elemento LCP. */

h2,.h2{font-size:var(--t-h2);line-height:var(--lh-h2);letter-spacing:var(--ls-h2);text-wrap:balance}
h3,.h3{font-size:var(--t-h3);line-height:var(--lh-h3);letter-spacing:var(--ls-h2);text-wrap:balance}
h4{font-size:var(--t-h4);line-height:1.2;letter-spacing:.01em}
h5,h6{font-size:var(--t-body);line-height:1.25;letter-spacing:var(--ls-slug)}

p{text-wrap:pretty}
p + p{margin-top:1em}

small{font-size:var(--t-small);line-height:1.5;color:var(--txt-3)}
strong,b{font-weight:600;color:var(--txt)}
em,i{font-style:italic}
code,kbd,samp,pre{font-family:var(--f-mono);font-size:var(--t-mono)}

/* Enlaces de componente: sin decoración (cada bloque pone la suya).
   Enlaces de prosa (sin clase): subrayado explícito, nunca solo color. */
a{color:inherit;text-decoration:none}
a:not([class]){
  color:var(--naranja-hot);
  text-decoration-line:underline;
  text-decoration-thickness:1px;
  text-underline-offset:.22em;
  transition:color var(--d-hover) var(--e-micro);
}
@media (hover:hover) and (pointer:fine){
  a:not([class]):hover{color:var(--naranja-ambar)}
}

hr{border:0;height:1px;background:var(--linea);margin:var(--s-6) 0}


/* ============================================================
   05 · UTILIDADES Y SISTEMA DE SECCIÓN
   ============================================================ */

/* --- Contenedores --- */
.wrap{
  width:min(100% - 2 * var(--gutter),var(--ancho-max));
  margin-inline:auto;
}
.wrap--angosto{width:min(100% - 2 * var(--gutter),var(--ancho-angosto))}
.medida{max-width:var(--w-medida)}
.medida--lead{max-width:var(--w-lead)}

/* --- Accesibilidad --- */
.sr-only{
  position:absolute;
  width:1px;height:1px;
  padding:0;margin:-1px;
  overflow:hidden;
  clip:rect(0 0 0 0);
  clip-path:inset(50%);
  white-space:nowrap;
  border:0;
}

.skip-link{
  position:fixed;
  top:var(--s-3);
  left:var(--s-3);
  z-index:calc(var(--z-modal) + 1);
  display:inline-flex;
  align-items:center;
  min-height:48px;
  padding:0 var(--s-5);
  background:var(--naranja);
  color:var(--txt-sobre-naranja);
  border-radius:var(--r-2);
  font-family:var(--f-texto);
  font-weight:600;
  font-size:var(--t-small);
  text-decoration:none;
  transform:translateY(calc(-100% - var(--s-6)));
  transition:transform var(--d-rele) var(--e-rele);
}
.skip-link:focus,
.skip-link:focus-visible{transform:none}

/* <noscript> — nunca visible cuando hay JS. */
.no-js-aviso{
  display:block;
  padding:var(--s-3) var(--gutter);
  background:var(--panel);
  border-bottom:1px solid var(--naranja-lo);
  color:var(--txt-2);
  font-size:var(--t-small);
}
.js .no-js-aviso{display:none}

/* --- Sistema de sección --- */
.seccion{
  position:relative;
  padding-block:var(--pad-seccion);
}
.seccion--void{background:var(--void)}
.seccion--carbon{background:var(--carbon)}
.seccion--aire{padding-block:var(--pad-seccion-aire)}

/* INVERSIÓN A PAPEL — tema con SCOPE LOCAL.
   Jamás reasignar tokens en :root: obligaría a transicionar background/color
   en prácticamente `*` y produce repaint de documento completo en pleno scroll. */
.seccion--papel{
  --void:var(--papel);
  --carbon:var(--papel-2);
  --panel:var(--papel);
  --pozo:var(--papel-2);
  --linea:var(--papel-regla);
  --linea-viva:var(--papel-regla);
  --txt:var(--papel-tinta);
  --txt-2:var(--papel-tinta-2);
  --txt-3:var(--papel-tinta-2);
  --txt-4:var(--papel-tinta-2);
  background:var(--papel);
  color:var(--papel-tinta);
  color-scheme:light;
}

.seccion__cab{
  max-width:var(--ancho-angosto);
  margin-bottom:var(--s-8);
}
.seccion__cab > * + *{margin-top:var(--s-4)}

.kicker{
  font-family:var(--f-mono);
  font-weight:500;
  font-size:var(--t-mono-s);
  line-height:1.2;
  letter-spacing:var(--ls-kicker);
  text-transform:uppercase;
  color:var(--naranja);
}

.lead{
  font-size:var(--t-lead);
  line-height:var(--lh-lead);
  color:var(--txt-2);
  max-width:var(--w-lead);
  text-wrap:pretty;
}

.prosa{
  font-size:var(--t-body);
  line-height:var(--lh-body);
  color:var(--txt-2);
  max-width:var(--w-medida);
  text-wrap:pretty;
}
.prosa > * + *{margin-top:var(--s-4)}

/* --- Separadores --- */
.regla{
  display:block;
  border:0;
  height:1px;
  width:100%;
  margin:var(--s-6) 0;
  background:var(--linea);
  transform-origin:left center;
}
.regla--carga{height:2px;background:var(--naranja)}
.js .regla{transform:scaleX(0);transition:transform var(--d-revelado) var(--e-revelado)}
.js .regla.is-in{transform:scaleX(1)}

/* --- Rejilla técnica. SOLO tesis, método y cobertura. --- */
.rejilla{position:relative;isolation:isolate}
.rejilla::before{
  content:"";
  position:absolute;
  inset:0;
  z-index:var(--z-canvas);
  pointer-events:none;
  background-image:
    linear-gradient(to right,var(--grid-linea) 1px,transparent 1px),
    linear-gradient(to bottom,var(--grid-linea) 1px,transparent 1px);
  background-size:var(--grid-paso) var(--grid-paso);
  -webkit-mask-image:radial-gradient(ellipse 95% 75% at 50% 50%,black 15%,transparent 80%);
  mask-image:radial-gradient(ellipse 95% 75% at 50% 50%,black 15%,transparent 80%);
}
.rejilla > *{position:relative;z-index:var(--z-grid)}


/* ============================================================
   06 · CAPA MONO / DATOS / CHIPS / REVEAL
   Instrumentación: estructural, no decorativa.
   ============================================================ */

.mono{
  font-family:var(--f-mono);
  font-size:var(--t-mono);
  letter-spacing:var(--ls-mono);
  font-variant-numeric:tabular-nums;
  line-height:1.55;
}
.mono--s{
  font-family:var(--f-mono);
  font-size:var(--t-mono-s);
  letter-spacing:var(--ls-slug);
  text-transform:uppercase;
  color:var(--txt-3);
  line-height:1.45;
  font-variant-numeric:tabular-nums;
}
.mono--dim{color:var(--txt-3)}

.dato{display:flex;flex-direction:column;gap:var(--s-1)}
.dato__val{
  font-family:var(--f-mono);
  font-weight:500;
  font-size:var(--t-mono);
  font-variant-numeric:tabular-nums;
  letter-spacing:var(--ls-mono);
  color:var(--txt);
}
.dato__uni{font-size:var(--t-mono-s);color:var(--txt-3)}
.dato__eti{
  font-family:var(--f-mono);
  font-size:var(--t-mono-s);
  letter-spacing:var(--ls-slug);
  text-transform:uppercase;
  color:var(--txt-3);
}

.cifra{
  font-family:var(--f-display);
  font-weight:900;
  font-size:var(--t-cifra);
  line-height:.9;
  letter-spacing:var(--ls-h2);
  font-variant-numeric:tabular-nums;
  color:var(--txt);
}

.chip{
  display:inline-flex;
  align-items:center;
  gap:6px;
  padding:4px 8px;
  border:1px solid var(--linea);
  border-radius:var(--r-1);
  font-family:var(--f-mono);
  font-size:var(--t-mono-s);
  line-height:1.35;
  letter-spacing:.1em;
  text-transform:uppercase;
  color:var(--txt-3);
  transition:border-color var(--d-hover) var(--e-micro),color var(--d-hover) var(--e-micro);
}
.chip--norma{color:var(--txt-3)}
.chip--muestra{color:var(--naranja-ambar);border-color:var(--naranja-lo)}
.chip--ok{color:var(--ok);border-color:currentColor}
.chip--alarma{color:var(--alarma);border-color:currentColor}

/* --- REVELADO ---
   Patrón `.js` obligatorio: sin JavaScript NADA se esconde.
   js/app.js debe además revelar todo si falta IntersectionObserver. */
.js [data-reveal],
.js .reveal{
  opacity:0;
  transform:translateY(28px);
  transition:
    opacity var(--d-revelado) var(--e-revelado) calc(var(--reveal-d,0) * var(--stagger)),
    transform var(--d-revelado) var(--e-revelado) calc(var(--reveal-d,0) * var(--stagger));
  will-change:opacity,transform;
}
.js [data-reveal].is-in,
.js .reveal.is-in{opacity:1;transform:none;will-change:auto}

.js [data-reveal-delay="1"]{--reveal-d:1}
.js [data-reveal-delay="2"]{--reveal-d:2}
.js [data-reveal-delay="3"]{--reveal-d:3}
.js [data-reveal-delay="4"]{--reveal-d:4}
.js [data-reveal-delay="5"]{--reveal-d:5}
.js [data-reveal-delay="6"]{--reveal-d:6}
.js [data-reveal-delay="7"]{--reveal-d:7}
.js [data-reveal-delay="8"]{--reveal-d:8}


/* ============================================================
   07 · BOTONES Y ENLACES
   REGLA ACOPLADA NO NEGOCIABLE: sobre relleno naranja el texto es
   SIEMPRE var(--txt-sobre-naranja). Blanco sobre #FF6B00 da 3,2:1
   y reprueba AA.
   ============================================================ */

.btn{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  gap:10px;
  min-height:48px;
  padding:var(--s-2) var(--s-5);
  border:1px solid transparent;
  border-radius:var(--r-2);
  background:transparent;
  color:var(--txt);
  font-family:var(--f-texto);
  font-weight:600;
  font-size:var(--t-small);
  line-height:1.25;
  letter-spacing:.01em;
  text-align:center;
  text-decoration:none;
  cursor:pointer;
  transition:
    background-color var(--d-hover) var(--e-micro),
    border-color var(--d-hover) var(--e-micro),
    color var(--d-hover) var(--e-micro),
    box-shadow var(--d-hover) var(--e-micro),
    transform var(--d-micro) var(--e-micro);
}

/* PRIMARIO — WhatsApp */
.btn--wa{
  background-image:var(--grad-brasa);
  background-color:var(--naranja);
  color:var(--txt-sobre-naranja);
  border-color:transparent;
}
.btn--wa:active{
  transform:translateY(2px);
  transition-timing-function:var(--e-carga);
}

/* FANTASMA */
.btn--ghost{
  background:transparent;
  border-color:var(--linea);
  color:var(--txt);
}
.btn--ghost:active{transform:translateY(2px);transition-timing-function:var(--e-carga)}

/* TAMAÑOS */
.btn--bloque{width:100%;min-height:56px}
.btn--gigante{min-height:76px;font-size:var(--t-h4);padding-inline:var(--s-7)}

.btn__ico{
  flex:0 0 auto;
  width:20px;
  height:20px;
  fill:none;
  stroke:currentColor;
  stroke-width:1.5;
  stroke-linecap:butt;
  stroke-linejoin:miter;
}
.btn__txt{display:inline-block}

/* Estados de puntero fino. En táctil manda :active, definido arriba. */
@media (hover:hover) and (pointer:fine){
  .btn--wa:hover{
    box-shadow:0 0 0 1px color-mix(in srgb,var(--naranja-hot) 55%,transparent),
                0 10px 30px -14px var(--naranja-halo);
    background-color:var(--naranja-hot);
  }
  .btn--ghost:hover{border-color:var(--naranja);color:var(--txt)}
}
@media (hover:none){
  .btn:active{transform:scale(.985);transition-duration:90ms}
}

/* ENLACE DE TEXTO — subrayado que crece scaleX(0→1) desde la izquierda.
   Lleva SIEMPRE una regla de reposo: el color nunca es el único indicador. */
.enlace{
  position:relative;
  display:inline-block;
  padding-bottom:2px;
  color:var(--txt);
  font-weight:600;
  font-size:var(--t-small);
  text-decoration:none;
  transition:color var(--d-hover) var(--e-micro);
}
.enlace::before,
.enlace::after{
  content:"";
  position:absolute;
  left:0;right:0;bottom:0;
  height:1px;
}
.enlace::before{background:var(--linea-viva)}
.enlace::after{
  background:var(--naranja);
  transform:scaleX(0);
  transform-origin:left center;
  transition:transform var(--d-hover) var(--e-micro);
}
.enlace:focus-visible::after{transform:scaleX(1)}
@media (hover:hover) and (pointer:fine){
  .enlace:hover{color:var(--txt)}
  .enlace:hover::after{transform:scaleX(1)}
}


/* ============================================================
   08 · FOCO VISIBLE GLOBAL
   Outline 2px --arco-azul, offset 3px. Jamás se remueve.
   ============================================================ */

a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible{
  outline:2px solid var(--arco-azul);
  outline-offset:3px;
}
:focus:not(:focus-visible){outline:none}


/* ============================================================
   09 · GRANO Y VIÑETA — EFECTO FIRMA 5
   IMPLEMENTACIÓN CORREGIDA:
   (1) inset NEGATIVO de -64px: la baldosa queda sobredimensionada y el
       desplazamiento nunca descubre un borde.
   (2) se anima TRANSFORM, jamás background-position: transform es
       compositable y no repinta nada.
   (3) CERO mix-blend-mode: un blend a pantalla completa fuerza un contexto
       de blending sobre todo el documento y saca del fast path a los dos
       canvas y al nav. Además, contra luminancia 5/255 el modo overlay
       satura a casi nada: se paga completo y no se ve. Opacity plana da el
       mismo resultado visible por cero costo.
   Textura: ruido monocromo 128x128 (1 bit) embebido como data-URI. Cero red.
   NOTA PARA EL BUILDER DE HTML: .vineta y .grano van como últimos hijos de
   <body> para que pinten por encima de los fondos opacos de sección.
   ============================================================ */

.grano{
  position:fixed;
  inset:-64px;
  z-index:var(--z-grano);
  pointer-events:none;
  opacity:.03;                 /* móvil */
  background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACAAQAAAADrRVxmAAAIi0lEQVR42gGACH/3AB4tDK+zrZuPX2plJjNqbmsAp0C2hK1y6T+JFvu861bCkwDFx4DhuckzQX465hv88THaACHo3saPB0PhLlzIHRYNtaIAQVv4cW9vsg4XX6n4QezF6gB8OmLajavCrhY5D+KrnMmQADfoTA9MGgiguXC6cYR/ktsAqqSTHPvPSCAfLAxjbJaeJQDoMiQLXv6Bb7gxfYZ9Ne3LAHgc/yTxKOjP/EWa2pUN4jUAOI6YUTwSA6CRVH+vwS6ZMgAl00ViY1xhgdAD2b25ErUFAG4MYJc4dyruO8CIXI61xgIAk2E5fgK0e075ItQkZMnAtADx8kyvKoXqBV6ridFztaIzAEX7kTwEkNqEWmcHx5nJLoQAJWu06cChQMtn7g5imi71pwAcB+3AFmVQ63IYAHoQUnmVAHfR6fXSTcmEzc9djgd1iJYAyp1lzjSD8CUXGcOY70kFJQCIF0GX1ShbSuyRWr/y6v6mABw+mZxm53nqnH30hQpDchQAXK09C/fc8qXh9JF8H+ihlwBR4uGQ7grzJbQ+d2YW0CYgAFo0j02nunDrS7WGwQVx1QUAw1hF48l+UmuBAyDP74lZcQCBymMVpRf4JCqSRSLoaqI1ADXOPX+b2siEKkYjeAIWHsEAVVhbMxNjUeoD31K7NeBuBABoJ4A5mbxpTgIn5LHfHGrwAAv0p2lZg9MBra8x3Ii7GbQAvr1oIatFowFjKf6AcI8VwADcLs/temdqT4yqt2VhqESBAGQDVEftISvPzEw5b4mUQVEATpVzs2oA4IClyaTGtDFykQBx0awbTcWKIOSdOt7dXH5hADIBq5Ms/GBOd4RjG5o/BaAAp2mimVbggK7lum0RcEcrUQDlq4fNHthLYVqxYLpnpFkQAHnmWucUHhnhTPLOIK3c3WQAM3V+iZw9y7xz87XFvvc+YQAo3CbnInq7LSKXy4tGz7L0AGtHUhPeSWJy05a+ZFNtY3EA3giGuSCeM8IDwBh++8XmxQCs3qJn4afovfif+a/uZBXAAFCyer0ye5CIquEf/SZYmfcAOiCeaeHHePeV+EoaI/9g9AAFOEJH0ksYR5is3ARLA8xGAGaqdjHzYpMQNawNsVHsPtUA18WuA9SlkYG1yMsh+5G6ZgCVOoo3kRYT3h6FjsDMZklFAAlXlx3PwDNufOuA+jaax3cAQ8WwzRf6uJEXwJlPITm0dQBc7WtdrTSrIV6+B1/JAYFHAB9ffMglHTBfs6fbvtwg8kQAyjPjY79QCO9313XkNBj+sgCM80SWZnmxsMi2XBFRuod0ADCSn6ObvIAg2tDyBb3ai4IAWiG41n7NC/7gWg/gqrnZ5QBlDGe9WZsLTvi08RrAwd2TAAabkGhYqYs1QRmA6dYirNUAu/ZL60tvK4WR7ab7DF6gKwDRBGQsGkSA+258w15TedvgAG1uu4NoD6NLOMolULlE9hoAO/TdNog2KBROeXS3rvGFUgAsyJUVNuJQBD6PYqVSbQsqAC9+sVKq0qtbhwJ3BEfi4EMAshNtWTQG2IoH7/Muj75tugD4wElI/rcD1axGMkmaeb5zAGSv0UuUMFNlruK8HzKleo8AJhh1jv0bgxqIY6H6tWeLAgATNZknhtTzq4yRL/JfPwe/AHavvdLXbxh0ISrmH2js/bIAy8clPcCxeOTh1EhBhzRRjgChJQHwxYmwuwpddYWQvaKDAB1JXPnzTfgqSPFLjSClLB4AP915rCPsM3EqXTNkNSZXkwAK8LCn8SlQ0Wq73T7du1ovAGtD17oxEJu+1zi4Seg8CSYA1mIIhZvKy51Dzp5XAHAfHwCY8K9yMbAZ0tx37/oFN2wWAAScfNkP7mtSxs8Z4OlrYK4ARmobRFLV0B38VswzPqwaJgDTFNTeDRLgnawgSin0+Ba8ABKGcwxEM3jTVQNLhOP9R7cAn6uoJn92YHOFZU2aGOBLyQCVHI5aTmdrnHplGG0PczCHACl5ECB8s0o8NAWON+drPfkATyomVLyL41IabJ9asmhOtgDyQVx8ekXD8hoQkUZ2MOhIABvzeqS+7kC9swnck3PzG4YApt/mfgppczkzfzLJmyuXWADEWcKqvkrI95R4yyCM4X0XAHEVGgKAjPhX0j51OGat82kAMs+u/sk8Yji8fwqN0WggIwCvpnLAkuh4mNga5JNrtKTZAGM3FvTL1eP3NRMNfnwzVxIAvzrP3PQY0hb1SaPWki/a6QD9qeqI8bF7WUZS13eEqCuiAGjAt4r2fhtZVCShZWw1j9gAKxKKSnNF2BZqdfCCSar88wCWThOgxZOZt34hdszh9vBMAHzSNlY14VDYwyhzKfS1isMAwv7r9MW3MHgXQnU7FO3EfQCkbE4wBY76F+BIJNgDLJfwAAEl13obQ6i2swayst10g00AYvbgKAZqe3nIjydXSnbxQACfmx8qOSYK/Yg7qcfgbv98AFUNuW5UHvGyJa7gZvf9jFQAywtjRDvIgzKJeI5sH+2o7ACJiQHwcvvYfCbz94kb7ttlABzhy1RpvIHcIR1NndOy1t0AWzPtkfibSLMOljQ4xnWv3QDGfrcaThwok0wUWhIqqCPtAAzt1Y+oJeLNp5Qz839t0OwAssQPjl75oF1vYJmjhyF0HADQXSnbikEjAoLxaFawpobcAGVQ4+SclROSxyeOyFI6CAgARsZBEZykqc64uM8vxbH7TQD/utDytmObfu4GTX0vqW85AB1o9SX/wACBUY/drGgrvH0AqyAsvqAGGTHJS0m2gLMzGQDJsA1v/TyAa3DKGBmxIMhcAHSdBGTC4rD7YS0aB1h4RKsAPwIBe2+bGqR+ohvyTTm3aACiT9hA09Y6NCh8nei1YRO6AHCc+TVD/7tr36XMx6KqY/kA4vGgGtE6mxoLWbbZKPdvihDc/B+MOV+/AAAAAElFTkSuQmCC");
  background-repeat:repeat;
  background-size:128px 128px;
  will-change:transform;
  animation:grano .666s steps(8) infinite;
}
@media (min-width:900px){
  .grano{opacity:.04}
}

@keyframes grano{
  0%   {transform:translate3d(0,0,0)}
  12.5%{transform:translate3d(-6px,-4px,0)}
  25%  {transform:translate3d(5px,-8px,0)}
  37.5%{transform:translate3d(-3px,7px,0)}
  50%  {transform:translate3d(8px,3px,0)}
  62.5%{transform:translate3d(-7px,-2px,0)}
  75%  {transform:translate3d(4px,6px,0)}
  87.5%{transform:translate3d(3px,-7px,0)}
}

/* Gama baja (js/app.js: hardwareConcurrency < 4). El grano se CONGELA,
   no desaparece: la textura sigue estando, deja de costar. */
html.sin-grano .grano{animation-play-state:paused}

.vineta{
  position:fixed;
  inset:0;
  z-index:var(--z-canvas);
  pointer-events:none;
  background:var(--grad-vineta);
}


/* ============================================================
   10 · NAV PERSISTENTE
   ============================================================ */

.nav{
  position:relative;   /* sin JS: en flujo, el panel abierto empuja la página */
  z-index:var(--z-nav);
  background:transparent;
  border-bottom:1px solid var(--linea);
  transition:background-color var(--d-rele) var(--e-rele),
             border-color var(--d-rele) var(--e-rele);
}

.js .nav{
  position:fixed;
  top:0;left:0;right:0;
}

.nav__inner{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:var(--s-4);
  height:var(--h-nav);
}

/* Estado tras 40px de scroll. Se aceptan las dos escrituras del contrato. */
.nav--solida,
.nav.is-solida{
  background-color:rgba(18,21,28,.96);   /* táctil: SÓLIDO, sin blur (= --panel .96) */
  background-color:color-mix(in srgb,var(--panel) 96%,transparent);
  border-bottom-color:var(--linea);
}

/* BACKDROP-FILTER RACIONADO: exactamente UN elemento en todo el sitio, y solo
   en puntero fino ≥1024px. Un blur corriendo el 100% del scroll en un Android
   de gama media es jank garantizado. */
@supports ((-webkit-backdrop-filter:blur(1px)) or (backdrop-filter:blur(1px))){
  @media (min-width:1024px) and (hover:hover) and (pointer:fine){
    .nav--solida,
    .nav.is-solida{
      background-color:rgba(18,21,28,.72);
      background-color:color-mix(in srgb,var(--panel) 72%,transparent);
      -webkit-backdrop-filter:blur(20px) saturate(1.2);
      backdrop-filter:blur(20px) saturate(1.2);
    }
  }
}

/* Con el panel móvil abierto el nav es opaco siempre. */
.nav:has(.nav__panel.is-abierto){
  background-color:rgba(18,21,28,.98);
  background-color:color-mix(in srgb,var(--panel) 98%,transparent);
  border-bottom-color:var(--linea);
}

.nav__logo{
  flex:0 0 auto;
  display:inline-flex;
  align-items:center;
  text-decoration:none;
}
.nav__logo-img{
  height:34px;
  width:auto;
  display:block;
}

.nav__links{display:none}
.nav__link{
  position:relative;
  display:inline-block;
  padding:var(--s-2) 0;
  font-size:var(--t-small);
  font-weight:500;
  color:var(--txt-3);
  text-decoration:none;
  transition:color var(--d-hover) var(--e-micro);
}
.nav__link::after{
  content:"";
  position:absolute;
  left:0;right:0;bottom:0;
  height:1px;
  background:var(--naranja);
  transform:scaleX(0);
  transform-origin:left center;
  transition:transform var(--d-hover) var(--e-micro);
}
.nav__link[aria-current]{color:var(--txt)}
.nav__link[aria-current]::after{transform:scaleX(1)}
.nav__link:focus-visible{color:var(--txt)}
@media (hover:hover) and (pointer:fine){
  .nav__link:hover{color:var(--txt)}
  .nav__link:hover::after{transform:scaleX(1)}
}

/* CTA compacto. Oculto <560px: ahí lo cubre el dock. */
.nav__cta{display:none}

/* Hamburguesa: 44x44. Solo existe si hay JS que la haga funcionar. */
.nav__burger{
  display:none;
  flex:0 0 auto;
  align-items:center;
  justify-content:center;
  width:44px;
  height:44px;
  padding:0;
  border:1px solid var(--linea);
  border-radius:var(--r-2);
  background:transparent;
  color:var(--txt);
  transition:border-color var(--d-hover) var(--e-micro),
             background-color var(--d-hover) var(--e-micro);
}
.js .nav__burger{display:inline-flex}
.nav__burger svg{
  width:22px;height:22px;
  fill:none;
  stroke:currentColor;
  stroke-width:1.5;
  stroke-linecap:butt;
  stroke-linejoin:miter;
}
.nav__burger[aria-expanded="true"]{
  border-color:var(--naranja);
  background-color:var(--naranja-wash);
}
@media (hover:hover) and (pointer:fine){
  .nav__burger:hover{border-color:var(--linea-viva)}
}

/* PANEL MÓVIL.
   Sin JS queda ABIERTO y legible (regla anti-página-en-blanco): en <900px es
   la única navegación disponible, así que no puede depender de un script. */
.nav__panel{
  display:block;
  background:var(--panel);
  border-top:1px solid var(--linea);
  border-bottom:1px solid var(--linea);
  padding-block:var(--s-2);
}
.js .nav__panel{
  max-height:0;
  padding-block:0;
  overflow:hidden;
  visibility:hidden;
  border-color:transparent;
  transition:max-height var(--d-estado) var(--e-estado),
             padding-block var(--d-estado) var(--e-estado),
             border-color var(--d-estado) var(--e-estado),
             visibility 0s linear var(--d-estado);
}
.js .nav__panel.is-abierto{
  max-height:min(72svh,560px);
  padding-block:var(--s-2);
  visibility:visible;
  border-color:var(--linea);
  transition:max-height var(--d-estado) var(--e-estado),
             padding-block var(--d-estado) var(--e-estado),
             border-color var(--d-estado) var(--e-estado),
             visibility 0s;
}

.nav__panel-link{
  display:flex;
  align-items:center;
  min-height:48px;
  padding:var(--s-3) var(--gutter);
  color:var(--txt-2);
  font-family:var(--f-texto);
  font-weight:600;
  font-size:var(--t-h4);
  text-decoration:none;
  border-bottom:1px solid var(--linea);
  transition:color var(--d-hover) var(--e-micro),
             background-color var(--d-hover) var(--e-micro);
}
.nav__panel-link:last-child{border-bottom:0}
.nav__panel-link:active{background-color:var(--naranja-wash);color:var(--txt)}
@media (hover:hover) and (pointer:fine){
  .nav__panel-link:hover{color:var(--txt);background-color:var(--naranja-wash)}
}

/* --- Nav: cortes de layout --- */
@media (min-width:560px){
  .nav__cta{
    display:inline-flex;
    margin-left:auto;
    min-height:44px;   /* 44x44 cumple objetivo táctil dentro de una barra de 64px */
    padding-inline:var(--s-4);
    font-size:var(--t-small);
  }
}
@media (min-width:900px){
  .nav__links{
    display:flex;
    align-items:center;
    gap:clamp(var(--s-4),2.2vw,var(--s-6));
    margin-left:auto;
  }
  .nav__cta{margin-left:var(--s-2)}
  .js .nav__burger{display:none}
  .nav__panel{display:none}
}


/* ============================================================
   11 · PIE
   ============================================================ */

.pie{
  position:relative;
  z-index:var(--z-contenido);
  background:var(--void);
  border-top:1px solid var(--linea);
  padding-block:var(--s-9) var(--s-7);
}

.pie__cols{
  display:grid;
  grid-template-columns:1fr;
  gap:var(--s-7);
}
.pie__col{
  display:flex;
  flex-direction:column;
  align-items:flex-start;
}
.pie__tit{
  margin-bottom:var(--s-3);
  color:var(--naranja);
  font-family:var(--f-mono);
  font-weight:500;
  font-size:var(--t-mono-s);
  letter-spacing:var(--ls-slug);
  text-transform:uppercase;
  line-height:1.2;
}
.pie__link{
  display:block;
  margin:0;
  padding:var(--s-2) 0;
  font-size:var(--t-small);
  line-height:1.45;
  color:var(--txt-3);
  text-decoration:none;
  transition:color var(--d-hover) var(--e-micro);
}

/* «Preferencias de cookies»: es un <button> (reabre el aviso, no navega)
   con la piel de .pie__link. Sin JavaScript no puede hacer nada, así que
   no se muestra: sin JS tampoco se carga ninguna medición. */
.pie__cookies{
  display:none;
  width:100%;
  background:none;
  border:0;
  font:inherit;
  font-size:var(--t-small);
  text-align:left;
  cursor:pointer;
}
.js .pie__cookies{display:block}
a.pie__link:focus-visible{color:var(--txt)}
@media (hover:hover) and (pointer:fine){
  a.pie__link:hover{color:var(--txt)}
}

.pie__legal{
  display:grid;
  gap:var(--s-4);
  align-items:center;
  margin-top:var(--s-8);
  padding-top:var(--s-6);
  border-top:1px solid var(--linea);
}
.pie__logo{
  width:120px;
  height:auto;
  opacity:.85;
}
.pie__legal .mono--s{color:var(--txt-3)}
.pie__colofon{
  color:var(--txt-3);
  max-width:var(--w-medida);
}

@media (min-width:560px){
  .pie__cols{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media (min-width:900px){
  .pie__cols{grid-template-columns:repeat(4,minmax(0,1fr));gap:var(--s-6)}
  .pie__legal{
    grid-template-columns:auto minmax(0,1fr) auto;
    gap:var(--s-6);
  }
  .pie__colofon{text-align:right}
}


/* ============================================================
   12 · DOCK WHATSAPP + BANNER DE COOKIES
   El dock es la conversión persistente. Sin JS queda visible desde el
   primer frame: nunca se esconde el CTA principal detrás de un script.
   ============================================================ */

.dock,
.dock--barra{
  position:fixed;
  left:0;right:0;bottom:0;
  z-index:var(--z-dock);
  display:flex;
  align-items:stretch;
  gap:var(--s-2);
  padding:var(--s-1) var(--gutter);
  padding-bottom:calc(var(--s-1) + env(safe-area-inset-bottom,0px));
  background-color:rgba(11,13,18,.97);   /* = --carbon .97 */
  background-color:color-mix(in srgb,var(--carbon) 97%,transparent);
  border-top:1px solid var(--linea);
}
.js .dock{
  transform:translateY(110%);
  transition:transform var(--d-estado) var(--e-estado);
  will-change:transform;
}
.js .dock.is-visible{transform:none}

.dock__wa{flex:1 1 auto;min-height:48px}
.dock__tel{flex:0 0 auto;min-height:48px;padding-inline:var(--s-4)}

/* ≥768px: pastilla abajo a la derecha que se expande en hover.
   El texto NUNCA sale del DOM: colapsa por max-width, sigue en el árbol
   de accesibilidad. Nada de botones solo-icono. */
@media (min-width:768px){
  .dock,
  .dock--pastilla{
    left:auto;
    right:clamp(16px,3vw,32px);
    bottom:clamp(16px,3vw,32px);
    width:auto;
    padding:0;
    background-color:transparent;
    border-top:0;
  }
  .dock__tel{display:none}
  .dock__wa{
    gap:0;
    min-height:56px;
    padding-inline:var(--s-4);
    border-radius:var(--r-3);
    box-shadow:var(--sombra-panel);
  }
  .dock__wa .btn__txt{
    max-width:0;
    margin-left:0;
    opacity:0;
    overflow:hidden;
    white-space:nowrap;
    transition:max-width var(--d-carga) var(--e-revelado),
               margin-left var(--d-carga) var(--e-revelado),
               opacity var(--d-hover) var(--e-micro);
  }
}
@media (min-width:768px) and (hover:hover) and (pointer:fine){
  .dock:hover .dock__wa .btn__txt,
  .dock:focus-within .dock__wa .btn__txt{
    max-width:18rem;
    margin-left:10px;
    opacity:1;
  }
}
/* Tablet táctil: no hay hover, la pastilla va siempre expandida. */
@media (min-width:768px) and (pointer:coarse){
  .dock__wa .btn__txt{max-width:18rem;margin-left:10px;opacity:1}
}

/* --- BANNER DE COOKIES ---
   Contrato: .cookies / .cookies__txt / .cookies__acciones, tal como lo emite
   index.html. Los botones reutilizan el sistema .btn (.btn--wa y .btn--ghost),
   asi que aqui no se re-estilizan.
   El banner nace con el atributo [hidden] y lo destapa un script inline de
   ~10 lineas al final del body — deliberadamente fuera de js/app.js, porque
   el consentimiento es cumplimiento legal y no debe depender de que cargue
   un modulo. Por eso el estado se lee de :not([hidden]), no de una clase.

   EL :not([hidden]) VA TAMBIEN EN ESTA REGLA BASE, no solo en las de abajo:
   un estilo de autor le gana SIEMPRE al [hidden]{display:none} del navegador,
   sin importar la especificidad. Sin el :not(), el banner se declara [hidden],
   el script lo cierra con b.hidden=true... y el display:grid lo revive. Quedaba
   abierto para siempre, tapando el dock de WhatsApp en movil. */
.cookies:not([hidden]){
  position:fixed;
  left:0;right:0;bottom:0;
  z-index:calc(var(--z-dock) + 10);
  display:grid;
  gap:var(--s-4);
  align-items:center;
  padding:var(--s-4) var(--gutter);
  padding-bottom:calc(var(--s-4) + env(safe-area-inset-bottom,0px));
  background:var(--panel);
  border-top:1px solid var(--linea);
  box-shadow:var(--sombra-panel);
}

/* Entrada por animacion y no por transicion: el script alterna [hidden]
   (display:none), y desde display:none una transicion no dispara nunca. */
@media (prefers-reduced-motion:no-preference){
  .cookies:not([hidden]){
    animation:cookies-entra var(--d-estado) var(--e-estado) both;
  }
}
@keyframes cookies-entra{
  from{transform:translateY(110%)}
  to{transform:none}
}

.cookies__txt{
  margin:0;
  max-width:var(--w-medida);
  font-size:var(--t-small);
  line-height:1.5;
  color:var(--txt-2);
}
.cookies__acciones{
  display:flex;
  flex-wrap:wrap;
  gap:var(--s-2);
}

/* Dos barras fijas al mismo borde se tapan. Mientras el aviso este en
   pantalla, el dock se retira; vuelve solo al aceptar o rechazar. */
body:has(.cookies:not([hidden])) .dock{
  transform:translateY(110%);
  pointer-events:none;
}

@media (min-width:900px){
  .cookies{grid-template-columns:minmax(0,1fr) auto;gap:var(--s-6)}
}


/* ============================================================
   13 · REDUCED MOTION — MODO, NO APAGÓN
   Bloque global. Va aquí, en la base, porque usa !important sobre `*`
   y por tanto gana a cualquier archivo concatenado después.
   ============================================================ */

@media (prefers-reduced-motion:reduce){
  :root{--d-micro:1ms;--d-hover:1ms;--d-rele:1ms;--d-carga:1ms;
        --d-estado:1ms;--d-revelado:1ms;--d-largo:1ms;--stagger:0ms;--flash:0ms}
  *,*::before,*::after{animation-duration:1ms!important;animation-iteration-count:1!important;
        transition-duration:1ms!important;scroll-behavior:auto!important}

  /* El grano queda FIJO pero PRESENTE. La viñeta es estática por naturaleza. */
  .grano{animation-play-state:paused!important}

  /* Nada puede quedarse esperando un observer que ya no anima nada. */
  .js [data-reveal],
  .js .reveal,
  .js .regla{opacity:1!important;transform:none!important}
}

/* Espejo por clase: js/app.js añade html.reduce con matchMedia y escucha el
   cambio en caliente, para el usuario que activa la preferencia sin recargar. */
html.reduce .grano{animation-play-state:paused}
.js.reduce [data-reveal],
.js.reduce .reveal,
.js.reduce .regla{opacity:1;transform:none}


/* ============================================================
   TIGERVOLT — PROTOCOLO 0,1 Hz
   _10-hero.css — EL ACTO DE APERTURA
   Secciones 2 a 5:  .hero · .norma · .triaje · .tesis
   ------------------------------------------------------------
   Depende de: tokens (:root), reset/base, .wrap, .seccion,
   .kicker, .h2, .lead, .prosa, .mono, .dato, .chip, .btn,
   .rejilla  — TODOS definidos en otros archivos. Aquí no se
   redefine ni un token ni una utilidad global.
   ------------------------------------------------------------
   REGLA LCP: el H1 se pinta VISIBLE en el primer frame.
   Ninguna regla sin prefijo .js oculta nada.
   ============================================================ */


/* ============================================================
   2 · HERO  —  #hero / .hero
   ============================================================ */

.hero{
  position:relative;
  min-height:100svh;
  display:grid;
  align-content:end;
  overflow:clip;
  background:var(--void);
  /* 64px = altura de la nav fija. El contenido nunca queda bajo ella. */
  padding-block:calc(64px + var(--s-7)) clamp(var(--s-7),8svh,var(--s-9));
  isolation:isolate;
}

/* ---- Canvas del oscilograma VLF -------------------------------
   Dimensiones CSS 100% estables desde el primer frame: está fuera
   del flujo (position:absolute + inset:0), así que su
   inicialización por JS no puede provocar layout shift. El
   atributo width/height intrínseco de <canvas> (300x150) queda
   anulado por width/height:100%. */
.hero__canvas{
  position:absolute;
  inset:0;
  width:100%;
  height:100%;
  display:block;
  z-index:var(--z-canvas);
  pointer-events:none;
  /* Sin JS o si onda.js falla: transparente sobre --void. */
  background:transparent;
}

/* ---- Contorno de tigre a una línea ---------------------------
   Si el path no existe, el <svg> se elimina del HTML y el diseño
   no cambia: nada de este bloque afecta al layout del contenido. */
.hero__tigre{
  position:absolute;
  top:50%;
  right:-10%;
  translate:0 -50%;
  width:min(76vw,520px);
  height:auto;
  aspect-ratio:1/1;
  z-index:var(--z-canvas);
  pointer-events:none;
  opacity:.06;
  fill:none;
  stroke:var(--linea-viva);
  stroke-width:1.25;
  stroke-linecap:butt;
  stroke-linejoin:miter;
}

/* ---- Overlay de legibilidad ----------------------------------
   Garantiza el contraste del texto sobre la onda. En móvil el
   texto está ABAJO y la onda vive en cy = H*0.62, o sea justo
   detrás: el scrim va de abajo hacia arriba. En >=900px el texto
   ocupa la mitad izquierda y se usa el gradiente horizontal del
   token. */
.hero__legible{
  position:absolute;
  inset:0;
  z-index:var(--z-grid);
  pointer-events:none;
  display:block;
  background:var(--grad-legible);
  /* Progressive enhancement: si color-mix no existe, queda el token. */
  background:linear-gradient(
    0deg,
    var(--void) 0%,
    color-mix(in srgb,var(--void) 88%,transparent) 34%,
    color-mix(in srgb,var(--void) 55%,transparent) 62%,
    transparent 96%
  );
}

.hero__inner{
  position:relative;
  z-index:var(--z-contenido);
}

.hero__kicker{
  margin:0 0 var(--s-5);
}

/* ---- H1: EL ELEMENTO LCP -------------------------------------
   Texto plano. opacity 1. Sin split, sin máscara, sin clase de
   entrada. Se pinta en el primer frame aunque el JS nunca llegue.
   Los saltos de línea son MANUALES (<br>) en el HTML: un fallback
   más ancho rompe en la misma cantidad de líneas. Por eso aquí
   NO se usa text-wrap:balance ni pretty — cambiarían el conteo de
   líneas al hacer swap de fuente y el CLS caería sobre el
   elemento más grande del viewport. */
.hero__h1{
  position:relative;
  margin:0;
  max-width:100%;
  font-family:var(--f-display);
  font-weight:800;
  font-size:var(--t-h1);
  line-height:var(--lh-h1);
  letter-spacing:var(--ls-h1);
  color:var(--txt);
  text-transform:uppercase;
  text-wrap:wrap;
  overflow-wrap:normal;
  word-break:normal;
  hyphens:none;
  /* Aberración cromática sutil. Si se nota, está mal calibrada. */
  text-shadow:-0.5px 0 rgba(255,107,0,.35), 0.5px 0 rgba(191,230,255,.28);
  /* Blindaje explícito del LCP: ninguna cascada posterior lo apaga. */
  opacity:1;
  visibility:visible;
  transform:none;
  animation:none;
}

.hero__sub{
  margin:var(--s-5) 0 0;
  max-width:var(--w-lead);
}

.hero__acciones{
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  gap:var(--s-3);
  margin-top:var(--s-6);
}
.hero__acciones>.btn{
  flex:1 1 100%;
  justify-content:center;
}

/* ---- Lecturas: instrumentación, no adorno --------------------
   En móvil cada lectura es una fila etiqueta/valor (formato de
   display de instrumento): ahorra alto sin perder información. */
.hero__lecturas{
  display:grid;
  grid-template-columns:1fr;
  gap:var(--s-2);
  margin:var(--s-7) 0 0;
  padding-top:var(--s-4);
  border-top:1px solid var(--linea);
}
.hero__lectura{
  display:flex;
  align-items:baseline;
  justify-content:space-between;
  gap:var(--s-4);
  margin:0;
}
.hero__lectura>dt,
.hero__lectura>dd{
  margin:0;
}
.hero__lectura .dato__val{
  text-align:right;
}

/* ---- Contador de ciclo en vivo -------------------------------
   tabular-nums + reserva de ancho: el dígito que corre no puede
   empujar el texto que lo rodea. */
.hero__ciclo{
  margin:var(--s-4) 0 0;
  font-family:var(--f-mono);
  font-weight:500;
  font-size:var(--t-mono);
  letter-spacing:var(--ls-mono);
  font-variant-numeric:tabular-nums;
  color:var(--arco-azul);
}
.hero__ciclo [data-onda-ciclo]{
  display:inline-block;
  min-width:3ch;
  text-align:right;
  font-variant-numeric:tabular-nums;
}

/* Pie del canvas: "Onda VLF a 0,1 Hz. Puedes cronometrarla." */
.hero__inner>.mono--s{
  margin:var(--s-3) 0 0;
  max-width:var(--w-lead);
}

/* ---- Indicador de scroll -------------------------------------
   Estático a propósito: cero flechas rebotando. */
.hero__scroll{
  position:absolute;
  right:var(--gutter);
  bottom:clamp(var(--s-5),5svh,var(--s-7));
  z-index:var(--z-contenido);
  display:none;
  place-items:center;
  width:32px;
  height:32px;
  color:var(--txt-3);
}
.hero__scroll svg{width:20px;height:20px;stroke:currentColor;stroke-width:1.5;fill:none}
.reduce .hero__scroll{display:none!important}


/* ---- ENTRADA DEL HERO ----------------------------------------
   TODO bajo el prefijo .js. Sin JavaScript nada de esto existe y
   el hero completo es legible al 100%.
   No depende de IntersectionObserver ni de .is-in: la animación
   arranca sola al pintar. Si un observer nunca llega, el hero ya
   está en su estado final. El H1 NO participa: nunca se oculta. */
.js .hero__kicker,
.js .hero__sub,
.js .hero__acciones,
.js .hero__lecturas,
.js .hero__ciclo,
.js .hero__inner>.mono--s{
  animation:hero-entra var(--d-revelado) var(--e-revelado) both;
  animation-delay:calc(var(--i,0) * var(--stagger));
}
.js .hero__kicker{--i:0}
.js .hero__sub{--i:1}
.js .hero__acciones{--i:2}
.js .hero__lecturas{--i:3}
.js .hero__ciclo{--i:4}
.js .hero__inner>.mono--s{--i:5}

@keyframes hero-entra{
  from{opacity:0;transform:translateY(28px)}
  to{opacity:1;transform:none}
}

/* Barrido de brillo SOBRE texto ya visible. Jamás sobre su
   visibilidad. clip-path:inset(0) contiene el barrido dentro de
   la caja del titular. */
@media (prefers-reduced-motion:no-preference){
  .js .hero__h1{clip-path:inset(0)}
  .js .hero__h1::after{
    content:"";
    position:absolute;
    inset:0;
    pointer-events:none;
    background:var(--grad-descarga);
    opacity:0;
    mix-blend-mode:screen;
    transform:translateX(-110%);
    animation:hero-barrido var(--d-revelado) var(--e-revelado) 240ms 1 both;
  }
}
@keyframes hero-barrido{
  0%{opacity:0;transform:translateX(-110%)}
  18%{opacity:.42}
  100%{opacity:0;transform:translateX(110%)}
}


/* ---- HERO · >=560px ------------------------------------------ */
@media (min-width:560px){
  .hero__acciones{gap:var(--s-4)}
  .hero__acciones>.btn{flex:0 1 auto;justify-content:flex-start}

  .hero__lecturas{
    grid-template-columns:repeat(3,minmax(0,1fr));
    gap:var(--s-5);
  }
  .hero__lectura{
    display:block;
  }
  .hero__lectura .dato__val{
    display:block;
    margin-top:var(--s-1);
    text-align:left;
  }
}

/* ---- HERO · >=900px ------------------------------------------ */
@media (min-width:900px){
  .hero{padding-block:calc(64px + var(--s-8)) clamp(var(--s-8),10svh,var(--s-9))}

  /* El scrim vuelve al gradiente horizontal del token: el texto
     vive en la mitad izquierda y la onda respira a la derecha. */
  .hero__legible{background:var(--grad-legible)}

  .hero__h1{
    max-width:78%;
    /* Techo por alto de viewport: tres líneas del H1 nunca pasan
       de ~64svh, así el sub, los CTA y las lecturas quedan sobre
       el pliegue en un portátil de 900px de alto. svh y no vh:
       es estable frente a la barra de direcciones. */
    font-size:min(var(--t-h1),26svh);
  }

  .hero__sub{margin-top:var(--s-6)}
  .hero__lecturas{max-width:78%}
  .hero__scroll{display:grid}
  .hero__tigre{right:-4%;width:min(46vw,600px);opacity:.08}
}

/* ---- HERO · >=1200px ----------------------------------------- */
@media (min-width:1200px){
  .hero__h1{max-width:min(78%,15ch)}
  .hero__lecturas{max-width:64%;gap:var(--s-7)}
  .hero__tigre{right:2%;width:min(38vw,640px)}
}


/* ============================================================
   3 · BANDA NORMATIVA  —  #norma / .norma
   ESTÁTICA. Cero animación, cero marquesina, cero scroll
   horizontal. Es un respiro deliberado entre el hero y el triaje.
   ============================================================ */

.norma{
  position:relative;
  background:var(--carbon);
  border-top:1px solid var(--linea);
  border-bottom:1px solid var(--linea);
  padding-block:var(--s-4);
}

.norma__lista{
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  justify-content:flex-start;
  gap:var(--s-3) var(--s-5);
  margin-block:0;
  padding-inline:0;
  list-style:none;
}

.norma__item{
  margin:0;
}

.norma__sep{
  flex:0 0 auto;
  width:4px;
  height:4px;
  margin:0;
  background:var(--naranja);
  transform:rotate(45deg);
}

@media (min-width:900px){
  .norma{padding-block:var(--s-5)}
  .norma__lista{justify-content:center;gap:var(--s-4) var(--s-5)}
}


/* ============================================================
   4 · TRIAJE  —  #triaje / .triaje
   Conversión temprana de máxima intención. Cada celda es un <a>
   completo a wa.me con contexto técnico distinto.
   ============================================================ */

.triaje{
  position:relative;
}

.triaje__grid{
  display:grid;
  grid-template-columns:1fr;
  gap:var(--s-3);
  margin-top:var(--s-7);
}

.triaje__celda{
  position:relative;
  display:grid;
  grid-template-columns:auto 1fr auto;
  grid-template-rows:auto 1fr;
  grid-template-areas:
    "ico  .    tag"
    "txt  txt  flecha";
  gap:var(--s-4) var(--s-4);
  min-height:128px;
  padding:var(--s-5);
  background:var(--panel);
  border:1px solid var(--linea);
  border-radius:var(--r-1);
  color:var(--txt-2);
  text-decoration:none;
  box-shadow:var(--bisel);
  transition:
    border-color var(--d-hover) var(--e-micro),
    background-color var(--d-hover) var(--e-micro),
    transform 90ms var(--e-micro);
}

/* Marcas de registro: apagadas en reposo, encendidas en el estado
   activo. Son las esquinas de un blanco de mira, no una sombra. */
.triaje__celda::before,
.triaje__celda::after{
  content:"";
  position:absolute;
  width:10px;
  height:10px;
  border:0 solid var(--naranja);
  opacity:0;
  pointer-events:none;
  transition:opacity var(--d-hover) var(--e-micro);
}
.triaje__celda::before{
  top:-1px;
  left:-1px;
  border-top-width:1px;
  border-left-width:1px;
}
.triaje__celda::after{
  right:-1px;
  bottom:-1px;
  border-right-width:1px;
  border-bottom-width:1px;
}

.triaje__ico{
  grid-area:ico;
  width:24px;
  height:24px;
  color:var(--naranja);
  stroke:currentColor;
  stroke-width:1.5;
  fill:none;
}

.triaje__tag{
  grid-area:tag;
  align-self:start;
  justify-self:end;
  white-space:nowrap;
}

.triaje__txt{
  grid-area:txt;
  align-self:end;
  max-width:34ch;
  font-size:var(--t-small);
  line-height:1.45;
  color:var(--txt-2);
}

.triaje__flecha{
  grid-area:flecha;
  align-self:end;
  justify-self:end;
  width:20px;
  height:20px;
  color:var(--txt-3);
  stroke:currentColor;
  stroke-width:1.5;
  fill:none;
  transition:
    transform var(--d-hover) var(--e-micro),
    color var(--d-hover) var(--e-micro);
}

/* Foco: idéntico al hover. Todo lo que descubre el mouse lo
   descubre el teclado. Nunca se remueve el outline. */
.triaje__celda:focus-visible{
  outline:2px solid var(--arco-azul);
  outline-offset:3px;
  border-color:var(--naranja);
}
.triaje__celda:focus-visible::before,
.triaje__celda:focus-visible::after{opacity:1}
.triaje__celda:focus-visible .triaje__flecha{
  transform:translateX(8px);
  color:var(--naranja);
}

/* Táctil: no hay hover. Feedback por :active. */
.triaje__celda:active{
  transform:scale(.985);
  transition-duration:90ms;
}

@media (hover:hover) and (pointer:fine){
  .triaje__celda:hover{
    border-color:var(--naranja);
    background-color:var(--panel);
  }
  .triaje__celda:hover::before,
  .triaje__celda:hover::after{opacity:1}
  .triaje__celda:hover .triaje__flecha{
    transform:translateX(8px);
    color:var(--naranja);
  }
  .triaje__celda:hover .triaje__txt{color:var(--txt)}
}

@media (min-width:560px){
  .triaje__grid{
    grid-template-columns:repeat(2,minmax(0,1fr));
    gap:var(--s-4);
  }
}

@media (min-width:900px){
  .triaje__grid{
    grid-template-columns:repeat(3,minmax(0,1fr));
    margin-top:var(--s-8);
  }
  .triaje__celda{min-height:148px;padding:var(--s-5) var(--s-5) var(--s-4)}
}


/* ============================================================
   5 · TESIS  —  #tesis / .tesis
   El gancho emocional. La única licencia dramática del sitio.
   Cero movimiento salvo el revelado por palabra, UNA vez.
   ============================================================ */

.tesis{
  position:relative;
}

.tesis__frase{
  margin:0;
  max-width:18ch;
  font-family:var(--f-display);
  font-weight:700;
  font-size:clamp(2rem,9vw,7rem);
  line-height:.92;
  letter-spacing:var(--ls-h2);
  color:var(--plasma);
  text-transform:uppercase;
  text-wrap:wrap;
  text-shadow:0 0 28px color-mix(in srgb,var(--arco-azul) 20%,transparent);
}

/* Los spans nacen VISIBLES. Escritos a mano en el HTML: el lector
   de pantalla lee la frase completa, no palabra por palabra, y la
   selección de texto sigue funcionando. */
.tesis__frase>span{
  display:inline-block;
  opacity:1;
  transform:none;
}

.tesis__pie{
  margin:var(--s-7) 0 0;
  color:var(--txt-2);
}

/* ---- Revelado por palabra. TODO bajo .js --------------------- */
.js .tesis__frase[data-reveal]>span{
  opacity:0;
  transform:translateY(.22em);
  transition:
    opacity var(--d-revelado) var(--e-revelado),
    transform var(--d-revelado) var(--e-revelado);
  transition-delay:0ms;
}
.js .tesis__frase[data-reveal].is-in>span{
  opacity:1;
  transform:none;
}

/* Stagger 55ms escrito a mano: no depende de que el JS inyecte
   ninguna variable por palabra. */
.js .tesis__frase[data-reveal]>span:nth-child(1){transition-delay:0ms}
.js .tesis__frase[data-reveal]>span:nth-child(2){transition-delay:55ms}
.js .tesis__frase[data-reveal]>span:nth-child(3){transition-delay:110ms}
.js .tesis__frase[data-reveal]>span:nth-child(4){transition-delay:165ms}
.js .tesis__frase[data-reveal]>span:nth-child(5){transition-delay:220ms}
.js .tesis__frase[data-reveal]>span:nth-child(6){transition-delay:275ms}
.js .tesis__frase[data-reveal]>span:nth-child(7){transition-delay:330ms}
.js .tesis__frase[data-reveal]>span:nth-child(8){transition-delay:385ms}
.js .tesis__frase[data-reveal]>span:nth-child(9){transition-delay:440ms}
.js .tesis__frase[data-reveal]>span:nth-child(10){transition-delay:495ms}
.js .tesis__frase[data-reveal]>span:nth-child(11){transition-delay:550ms}
.js .tesis__frase[data-reveal]>span:nth-child(12){transition-delay:605ms}
.js .tesis__frase[data-reveal]>span:nth-child(13){transition-delay:660ms}
.js .tesis__frase[data-reveal]>span:nth-child(14){transition-delay:715ms}
.js .tesis__frase[data-reveal]>span:nth-child(n+15){transition-delay:770ms}

@media (min-width:900px){
  .tesis__pie{margin-top:var(--s-8)}
}


/* ============================================================
   REDUCED MOTION — modo, no apagón.
   El bloque global de :root ya aplasta las duraciones. Aquí se
   retira lo que no tiene sentido como "instantáneo": el barrido
   de brillo del H1 y el desplazamiento de la flecha.
   Ningún elemento queda oculto.
   ============================================================ */
@media (prefers-reduced-motion:reduce){
  .js .hero__kicker,
  .js .hero__sub,
  .js .hero__acciones,
  .js .hero__lecturas,
  .js .hero__ciclo,
  .js .hero__inner>.mono--s{
    animation:none;
    opacity:1;
    transform:none;
  }
  .js .hero__h1{clip-path:none}
  .js .hero__h1::after{content:none;animation:none}

  .js .tesis__frase[data-reveal]>span{
    opacity:1;
    transform:none;
    transition-delay:0ms;
  }

  .triaje__celda:active{transform:none}
  .triaje__celda:hover .triaje__flecha,
  .triaje__celda:focus-visible .triaje__flecha{transform:none}
}


/* ============================================================
   TIGERVOLT — PROTOCOLO 0,1 Hz
   _20-servicios.css — NÚCLEO DE OFERTA
   Secciones 6, 7 y 8:
     · .servicios  — LA MORDIDA (efecto firma #2, CSS puro)
     · .marcas     — compatibilidad de sistemas (CSS puro, cero JS)
     · .protocolo  — LA INVERSIÓN A PAPEL (efecto firma #3)
   Solo tokens del bloque :root maestro. Ningún hex suelto.
   Todo lo que se oculta para animarse va prefijado .js
   ============================================================ */


/* ============================================================
   6. SERVICIOS — LA MORDIDA
   Cinco barras a ancho completo, todas escaneables en paralelo.
   Cero pin, cero scrub, cero JS para el efecto (solo el gancho
   móvil que añade .is-activa desde un IntersectionObserver).
   ============================================================ */

.servicios{
  position:relative;
}

.servicios .seccion__cab{
  margin-bottom:clamp(40px,6vw,72px);
}

.servicios__lista{
  list-style:none;
  margin:0;
  padding:0;
  border-top:1px solid var(--linea);
}

/* ---- La barra ---- */
.serv{
  position:relative;
  overflow:clip;
  border-bottom:1px solid var(--linea);
  background:var(--void);
}

/* ---- LA MORDIDA: panel naranja con filo cortado a 7° ----
   Entra desde el borde izquierdo y SE RETIRA POR EL MISMO
   borde izquierdo. Se siente barrido, no toggle.
   5,2vw ≈ tangente de 7° sobre el alto de la barra. */
.serv__mordida{
  position:absolute;
  inset:0;
  z-index:0;
  display:block;
  background:var(--naranja);
  clip-path:polygon(0 0, 0 0, 0 100%, 0 100%);
  transition:clip-path var(--d-carga) var(--e-carga);
  pointer-events:none;
}

/* ---- Rejilla interna de la barra ---- */
.serv__link{
  position:relative;
  z-index:var(--z-contenido);
  display:grid;
  grid-template-columns:auto minmax(0,1fr);
  align-items:start;
  gap:var(--s-3) var(--s-4);
  padding-block:clamp(24px,5vw,32px);
  text-decoration:none;
  color:inherit;
}

.serv__idx{
  grid-column:1;
  color:var(--naranja);
  padding-top:.35em;
  transition:color var(--d-hover) var(--e-micro);
}

.serv__nombre{
  margin:0 0 var(--s-2);
  transition:color var(--d-hover) var(--e-micro);
}

.serv__desc{
  margin:0;
  font-size:var(--t-small);
  line-height:var(--lh-lead);
  color:var(--txt-2);
  max-width:38ch;
  transition:color var(--d-hover) var(--e-micro);
}

/* ---- Chips de especificación ---- */
.serv__specs{
  grid-column:1 / -1;
  display:flex;
  flex-wrap:wrap;
  gap:var(--s-2);
  align-content:flex-start;
}

.serv__specs .chip{
  transition:color var(--d-hover) var(--e-micro),
             border-color var(--d-hover) var(--e-micro);
}

/* ---- Foto: solo ≥900px, src diferido por activación ---- */
.serv__foto{
  display:none;
  width:240px;
  height:112px;
  object-fit:cover;
  background:var(--pozo);
  clip-path:polygon(7% 0, 100% 0, 93% 100%, 0 100%);
  filter:contrast(1.08) saturate(.85) brightness(.86);
  opacity:.72;
  transition:opacity var(--d-carga) var(--e-revelado),
             filter var(--d-carga) var(--e-revelado);
}

/* ---- Bloque de conversión de la barra ---- */
.serv__link > :last-child{
  grid-column:1 / -1;
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  gap:var(--s-4);
}

.serv__link > :last-child .btn,
.serv__cta{
  min-height:48px;
  padding-inline:var(--s-5);
  transition:background var(--d-hover) var(--e-micro),
             color var(--d-hover) var(--e-micro),
             border-color var(--d-hover) var(--e-micro);
}

.serv__mas{
  color:var(--txt-3);
  font-size:var(--t-small);
  transition:color var(--d-hover) var(--e-micro);
}

/* ============================================================
   ESTADO ACTIVO DE LA BARRA
   Base: .is-activa (IntersectionObserver móvil) y :focus-within
   (teclado, en cualquier dispositivo).
   Desktop: :hover, dentro de @media (hover:hover) and (pointer:fine).
   REGLA DE CONTRASTE NO NEGOCIABLE: sobre relleno naranja el
   texto es SIEMPRE --txt-sobre-naranja. Jamás blanco.
   ============================================================ */

.serv.is-activa .serv__mordida,
.serv:focus-within .serv__mordida{
  clip-path:polygon(0 0, calc(100% + 5.2vw) 0, 100% 100%, 0 100%);
}

.serv.is-activa .serv__idx,
.serv.is-activa .serv__nombre,
.serv.is-activa .serv__desc,
.serv.is-activa .serv__mas,
.serv:focus-within .serv__idx,
.serv:focus-within .serv__nombre,
.serv:focus-within .serv__desc,
.serv:focus-within .serv__mas{
  color:var(--txt-sobre-naranja);
}

.serv.is-activa .serv__specs .chip,
.serv:focus-within .serv__specs .chip{
  color:var(--txt-sobre-naranja);
  border-color:color-mix(in srgb, var(--txt-sobre-naranja) 34%, transparent);
}

.serv.is-activa .serv__link > :last-child .btn--wa,
.serv.is-activa .serv__cta,
.serv:focus-within .serv__link > :last-child .btn--wa,
.serv:focus-within .serv__cta{
  background:var(--txt-sobre-naranja);
  color:var(--naranja-hot);
}

.serv.is-activa .serv__foto,
.serv:focus-within .serv__foto{
  opacity:1;
  filter:contrast(1.08) saturate(.9) brightness(1);
}

@media (hover:hover) and (pointer:fine){
  .serv:hover .serv__mordida{
    clip-path:polygon(0 0, calc(100% + 5.2vw) 0, 100% 100%, 0 100%);
  }
  .serv:hover .serv__idx,
  .serv:hover .serv__nombre,
  .serv:hover .serv__desc,
  .serv:hover .serv__mas{
    color:var(--txt-sobre-naranja);
  }
  .serv:hover .serv__specs .chip{
    color:var(--txt-sobre-naranja);
    border-color:color-mix(in srgb, var(--txt-sobre-naranja) 34%, transparent);
  }
  .serv:hover .serv__link > :last-child .btn--wa,
  .serv:hover .serv__cta{
    background:var(--txt-sobre-naranja);
    color:var(--naranja-hot);
  }
  .serv:hover .serv__foto{
    opacity:1;
    filter:contrast(1.08) saturate(.9) brightness(1);
  }
}

/* Táctil: acuse de recibo en vez de hover */
@media (hover:none){
  .serv__link > :last-child .btn:active,
  .serv__mas:active{
    transform:scale(.985);
    transition-duration:90ms;
  }
}

/* ---- ≥560px: los chips y el CTA ganan aire ---- */
@media (min-width:560px){
  .serv__link{
    grid-template-columns:auto minmax(0,1fr);
    gap:var(--s-4) var(--s-5);
  }
  .serv__specs{
    grid-column:2;
  }
  .serv__link > :last-child{
    grid-column:2;
  }
}

/* ---- ≥900px: la barra completa en una fila ----
   [idx 64px] [nombre+desc 1fr] [specs 1fr] [foto 240px] [cta auto] */
@media (min-width:900px){
  .serv__link{
    grid-template-columns:64px minmax(0,1.15fr) minmax(0,1fr) 240px auto;
    align-items:center;
    gap:var(--s-6);
    min-height:148px;
    padding-block:var(--s-6);
  }
  .serv__idx{
    grid-column:1;
    padding-top:0;
  }
  .serv__specs{
    grid-column:auto;
  }
  .serv__foto{
    display:block;
    grid-column:auto;
  }
  .serv__link > :last-child{
    grid-column:auto;
    flex-direction:column;
    align-items:flex-start;
    gap:var(--s-3);
  }
  .serv__desc{
    max-width:32ch;
  }
}

@media (min-width:1200px){
  .serv__link{
    grid-template-columns:64px minmax(0,1.2fr) minmax(0,1fr) 260px auto;
    min-height:164px;
  }
  .serv__foto{
    width:260px;
    height:124px;
  }
}


/* ============================================================
   7. MARCAS — compatibilidad de sistemas
   No es una sopa de logos: son números de parte.
   CSS puro, cero JavaScript. Respiro de rendimiento.
   ============================================================ */

.marcas__grid{
  list-style:none;
  margin:clamp(40px,6vw,64px) 0 0;
  padding:0;
  display:grid;
  grid-template-columns:repeat(2,minmax(0,1fr));
  gap:var(--s-3);
}

.marca{
  position:relative;
  isolation:isolate; /* confina el mix-blend-mode:screen del logo a esta celda */
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:space-between;
  gap:var(--s-4);
  min-height:clamp(124px,18vw,152px);
  padding:var(--s-5);
  background:var(--panel);
  border:1px solid var(--linea);
  border-radius:var(--r-1);
  box-shadow:var(--bisel);
}

/* Barrido de borde naranja, 220ms --e-carga */
.marca__borde{
  position:absolute;
  inset:-1px;
  display:block;
  border:1px solid var(--naranja);
  border-radius:var(--r-1);
  clip-path:inset(0 100% 0 0);
  transition:clip-path 220ms var(--e-carga);
  pointer-events:none;
}

/* Los 8 logos son marca oscura sobre #F5F5F5 a 900×600.
   grayscale + invert + screen borra el fondo contra la celda. */
.marca__logo{
  display:block;
  width:100%;
  max-width:148px;
  height:auto;
  margin-block:auto;
  filter:grayscale(1) invert(1) contrast(1.15);
  mix-blend-mode:screen;
  opacity:.78;
  transition:opacity var(--d-hover) var(--e-micro);
}

/* Las 4 sin archivo: tratamiento tipográfico, no logo ajeno */
.marca__nombre{
  margin-block:auto;
  font-family:var(--f-texto);
  font-weight:600;
  font-size:var(--t-small);
  line-height:1.25;
  letter-spacing:.12em;
  text-transform:uppercase;
  text-align:center;
  color:var(--txt);
  text-wrap:balance;
}

/* La línea de familias SIEMPRE es legible: en móvil por decisión
   (la información gana), en desktop gana presencia en hover. */
.marca__familias{
  margin:0;
  text-align:center;
  color:var(--txt-3);
  transition:color var(--d-hover) var(--e-micro),
             opacity var(--d-hover) var(--e-micro);
}

.marca.is-activa .marca__borde,
.marca:focus-within .marca__borde{
  clip-path:inset(0);
}

.marca.is-activa .marca__logo,
.marca:focus-within .marca__logo{
  opacity:1;
}

.marca.is-activa .marca__familias,
.marca:focus-within .marca__familias{
  color:var(--txt-2);
  opacity:1;
}

@media (hover:hover) and (pointer:fine){
  .marca__familias{
    opacity:.78;
  }
  .marca:hover .marca__borde{
    clip-path:inset(0);
  }
  .marca:hover .marca__logo{
    opacity:1;
  }
  .marca:hover .marca__familias{
    color:var(--txt-2);
    opacity:1;
  }
}

.marcas .prosa.mono--s{
  margin-top:var(--s-6);
  color:var(--txt-3);
}

@media (min-width:560px){
  .marcas__grid{
    grid-template-columns:repeat(3,minmax(0,1fr));
  }
}

@media (min-width:900px){
  .marcas__grid{
    grid-template-columns:repeat(4,minmax(0,1fr));
    gap:var(--s-4);
  }
}

@media (min-width:1200px){
  .marcas__grid{
    grid-template-columns:repeat(6,minmax(0,1fr));
  }
  .marca{
    min-height:164px;
  }
}


/* ============================================================
   8. PROTOCOLO — LA INVERSIÓN A PAPEL
   Tema SCOPED, jamás en :root: reasignar tokens globales
   dispara un repaint de documento completo en medio del scroll.
   ============================================================ */

.seccion--papel.protocolo{
  --void:var(--papel);
  --carbon:var(--papel-2);
  --panel:var(--papel);
  --linea:var(--papel-regla);
  --linea-viva:var(--papel-regla);
  --txt:var(--papel-tinta);
  --txt-2:var(--papel-tinta-2);
  --txt-3:var(--papel-tinta-2);
  --txt-4:var(--papel-tinta-2);
  background:var(--papel);
  color:var(--papel-tinta);
  border-block:1px solid var(--papel-regla);
}

/* El naranja de marca no alcanza AA sobre papel: el kicker pasa
   a tinta de timbre (~5,4:1), que además es lenguaje de documento. */
.protocolo .kicker{
  color:var(--papel-timbre);
}

/* ---- La hoja ---- */
.protocolo__hoja{
  position:relative;
  max-width:980px;
  margin:clamp(40px,6vw,64px) auto 0;
  padding:clamp(20px,4.5vw,48px);
  background:var(--papel);
  border:1px solid var(--papel-regla);
  border-radius:var(--r-1);
  box-shadow:var(--sombra-panel);
}

.protocolo__hoja > .chip--muestra{
  display:inline-flex;
  align-items:center;
  color:var(--papel-timbre);
  border-color:var(--papel-timbre);
  background:transparent;
}

/* ---- Encabezado del informe ---- */
.protocolo__enc{
  display:grid;
  grid-template-columns:1fr;
  gap:var(--s-4);
  margin-top:var(--s-5);
  padding-bottom:var(--s-5);
  border-bottom:1px solid var(--papel-regla);
}

.protocolo__campo{
  display:flex;
  flex-direction:column;
  gap:var(--s-1);
  padding-top:var(--s-2);
  border-top:1px solid var(--papel-regla);
  min-width:0;
}

.protocolo__campo > :first-child{
  font-family:var(--f-mono);
  font-size:var(--t-mono-s);
  letter-spacing:var(--ls-slug);
  text-transform:uppercase;
  color:var(--papel-tinta-2);
}

.protocolo__campo > :last-child{
  font-size:var(--t-mono);
  color:var(--papel-tinta);
  overflow-wrap:anywhere;
}

/* ---- Tabla REAL. Jamás canvas, jamás imagen ---- */
.protocolo__scroll{
  margin-top:var(--s-5);
  overflow-x:auto;
  overscroll-behavior-x:contain;
  -webkit-overflow-scrolling:touch;
}

.protocolo__tabla{
  width:100%;
  min-width:620px;
  border-collapse:collapse;
  font-variant-numeric:tabular-nums;
}

.protocolo__tabla caption{
  text-align:left;
  font-family:var(--f-mono);
  font-size:var(--t-mono-s);
  letter-spacing:var(--ls-mono);
  color:var(--papel-tinta-2);
  padding-bottom:var(--s-3);
}

.protocolo__tabla th,
.protocolo__tabla td{
  position:relative;
  text-align:left;
  padding:var(--s-3) var(--s-4) var(--s-3) 0;
  vertical-align:baseline;
}

.protocolo__tabla thead th{
  font-family:var(--f-mono);
  font-weight:500;
  font-size:var(--t-mono-s);
  letter-spacing:var(--ls-slug);
  text-transform:uppercase;
  color:var(--papel-tinta-2);
  border-bottom:1px solid var(--papel-tinta);
  white-space:nowrap;
}

.protocolo__tabla tbody th,
.protocolo__tabla tbody td{
  font-family:var(--f-mono);
  font-size:var(--t-mono);
  letter-spacing:var(--ls-mono);
  color:var(--papel-tinta);
}

.protocolo__tabla tbody th{
  font-weight:500;
}

/* Las reglas horizontales se trazan scaleX(0→1) desde la izquierda */
.protocolo__tabla tbody th::after,
.protocolo__tabla tbody td::after{
  content:"";
  position:absolute;
  left:0;
  right:0;
  bottom:0;
  height:1px;
  background:var(--papel-regla);
  transform:scaleX(1);
  transform-origin:left center;
}

/* Columna FASE fija: el body nunca hace scroll horizontal */
.protocolo__tabla thead th:first-child,
.protocolo__tabla tbody th[scope="row"]{
  position:sticky;
  left:0;
  z-index:1;
  background:var(--papel);
  padding-right:var(--s-5);
  box-shadow:1px 0 0 var(--papel-regla);
}

/* ---- Veredicto, timbre y honestidad obligatoria ---- */
.protocolo__veredicto{
  display:inline-flex;
  align-items:center;
  margin-top:var(--s-5);
  padding:var(--s-2) var(--s-4);
  background:var(--papel-tinta);
  color:var(--ok);
  border-color:var(--papel-tinta);
  border-radius:var(--r-1);
}

.protocolo__timbre{
  position:absolute;
  top:clamp(16px,3.5vw,36px);
  right:clamp(16px,3.5vw,36px);
  width:clamp(84px,12vw,120px);
  height:auto;
  fill:var(--papel-timbre);
  opacity:.82;
  transform:rotate(-7deg);
  transform-origin:center;
  pointer-events:none;
}

.protocolo__nota{
  margin-top:var(--s-5);
  max-width:var(--w-medida);
  font-family:var(--f-mono);
  font-size:var(--t-mono-s);
  line-height:1.6;
  letter-spacing:var(--ls-mono);
  color:var(--papel-tinta-2);
  padding-top:var(--s-4);
  border-top:1px solid var(--papel-regla);
}

.protocolo__cta{
  margin-top:var(--s-6);
}

/* ============================================================
   COREOGRAFÍA DE IMPRESIÓN
   Todo nace visible. Solo con html.js se oculta para animar.
   Un fallo de script no puede vaciar esta sección.
   ============================================================ */

.js .protocolo .protocolo__fila{
  opacity:0;
  transform:translateY(8px);
}

.js .protocolo .protocolo__fila th::after,
.js .protocolo .protocolo__fila td::after{
  transform:scaleX(0);
}

.js .protocolo .protocolo__veredicto,
.js .protocolo .protocolo__timbre{
  opacity:0;
}

.js .protocolo.is-impreso .protocolo__fila{
  opacity:1;
  transform:none;
  transition:opacity 320ms var(--e-revelado) calc(var(--i) * 45ms),
             transform 320ms var(--e-revelado) calc(var(--i) * 45ms);
}

.js .protocolo.is-impreso .protocolo__fila th::after,
.js .protocolo.is-impreso .protocolo__fila td::after{
  transform:scaleX(1);
  transition:transform 400ms var(--e-revelado) calc(var(--i) * 45ms);
}

.js .protocolo.is-impreso .protocolo__veredicto{
  animation:proto-veredicto var(--d-estado) var(--e-descarga) 260ms both;
}

.js .protocolo.is-impreso .protocolo__timbre{
  animation:proto-timbre var(--d-rele) var(--e-rele) 380ms both;
}

@keyframes proto-veredicto{
  0%{opacity:0;transform:translateY(6px);filter:none}
  62%{opacity:1;transform:none;filter:none}
  70%{filter:brightness(2.4)}
  100%{opacity:1;transform:none;filter:none}
}

@keyframes proto-timbre{
  0%{opacity:0;transform:rotate(-7deg) scale(1.35)}
  100%{opacity:.82;transform:rotate(-7deg) scale(1)}
}

/* .is-plano: un solo fade de 400ms para todo el bloque.
   El escalonado fila a fila compite con el scroll táctil. */
.js .protocolo.is-plano.is-impreso .protocolo__fila{
  transition-duration:400ms;
  transition-delay:0ms;
}

.js .protocolo.is-plano.is-impreso .protocolo__fila th::after,
.js .protocolo.is-plano.is-impreso .protocolo__fila td::after{
  transition-duration:400ms;
  transition-delay:0ms;
}

.js .protocolo.is-plano.is-impreso .protocolo__veredicto,
.js .protocolo.is-plano.is-impreso .protocolo__timbre{
  animation-delay:0ms;
  animation-duration:400ms;
}

/* ---- ≥560px: encabezado a 3 columnas ---- */
@media (min-width:560px){
  .protocolo__enc{
    grid-template-columns:repeat(3,minmax(0,1fr));
    gap:var(--s-5);
  }
}

@media (min-width:900px){
  .protocolo__tabla th,
  .protocolo__tabla td{
    padding:var(--s-4) var(--s-5) var(--s-4) 0;
  }
  .protocolo__tabla thead th:first-child,
  .protocolo__tabla tbody th[scope="row"]{
    position:static;
    box-shadow:none;
  }
  .protocolo__nota{
    max-width:var(--w-medida);
  }
}

/* ============================================================
   REDUCED MOTION — el documento llega completamente impreso.
   La inversión de tema ya es instantánea por ser scoped.
   ============================================================ */

@media (prefers-reduced-motion:reduce){
  .js .protocolo .protocolo__fila{
    opacity:1;
    transform:none;
  }
  .js .protocolo .protocolo__fila th::after,
  .js .protocolo .protocolo__fila td::after{
    transform:scaleX(1);
  }
  .js .protocolo .protocolo__veredicto,
  .js .protocolo .protocolo__timbre{
    opacity:1;
    animation:none;
  }
  .js .protocolo.is-impreso .protocolo__veredicto,
  .js .protocolo.is-impreso .protocolo__timbre{
    animation:none;
  }
  .protocolo__timbre{
    opacity:.82;
  }
  /* La mordida sigue cambiando de color: es feedback funcional,
     no decoración. Lo que se retira es el barrido. */
}

/* --- ETIQUETA DE CAMPO DEL INFORME ---
   Antes reusaba .acred__eti, que pertenece al bloque ACREDITACIÓN y arrastra
   un tick naranja decorativo por ::before — fuera de lugar sobre papel.
   Mismo tratamiento tipográfico, tinta del papel, sin el tick. */
.protocolo__eti{
  display:block;
  font-family:var(--f-mono);
  font-size:var(--t-mono-s);
  letter-spacing:var(--ls-slug);
  text-transform:uppercase;
  color:var(--papel-tinta-2);
  margin:0 0 var(--s-1);
}

/* --- FOCO DENTRO DE LA SECCIÓN PAPEL ---
   El anillo global usa --arco-azul (#BFE6FF), que da 15,35:1 sobre --void
   pero apenas 1,15:1 sobre --papel (#F2F0EA): invisible justo encima del
   CTA del protocolo. Aquí se invierte a la tinta del papel. */
.seccion--papel a:focus-visible,
.seccion--papel button:focus-visible,
.seccion--papel [tabindex]:focus-visible{
  outline-color:var(--papel-tinta);
  outline-offset:3px;
}

/* ============================================================
   ANATOMÍA — los cortes esquemáticos de cada tipo de mufa.
   Van a dos columnas en escritorio (~560 px por figura) porque
   los rótulos técnicos no se leen en una miniatura de 240 px.
   ============================================================ */

.anatomia__grid{
  list-style:none;
  margin:clamp(40px,6vw,72px) 0 0;
  padding:0;
  display:grid;
  grid-template-columns:1fr;
  gap:var(--s-6);
}

.anatomia__fig{margin:0}

.anatomia__fig img{
  display:block;
  width:100%;
  height:auto;
  background:var(--pozo);
  border:1px solid var(--linea);
  border-radius:var(--r-2);
}

.anatomia__cap{
  display:flex;
  align-items:baseline;
  gap:var(--s-3);
  margin-top:var(--s-3);
  color:var(--txt-2);
}

.anatomia__num{color:var(--naranja)}

/* Sin columna de foto: la barra reparte ese ancho entre texto y chips */
@media (min-width:900px){
  .servicios__lista--sin-foto .serv__link{
    grid-template-columns:64px minmax(0,1.3fr) minmax(0,1fr) auto;
  }
  .anatomia__grid{
    grid-template-columns:repeat(2,1fr);
    gap:var(--s-7) var(--s-6);
  }
}

/* ============================================================
   CATÁLOGO CONTRA TERRENO
   Cada figura son dos paneles (1200x500), así que va a una sola
   columna y con ancho acotado: partida en dos no se leería.
   ============================================================ */

.realidad__grid{
  list-style:none;
  margin:clamp(40px,6vw,72px) auto 0;
  padding:0;
  display:grid;
  gap:clamp(32px,5vw,64px);
  max-width:1040px;
}

.realidad__fig{margin:0}

.realidad__fig img{
  display:block;
  width:100%;
  height:auto;
  background:var(--pozo);
  border:1px solid var(--linea);
  border-radius:var(--r-2);
}

.realidad__cap{
  display:block;
  margin-top:var(--s-4);
  max-width:var(--w-medida);
}

.realidad__tit{
  display:block;
  color:var(--naranja);
  margin-bottom:var(--s-2);
}

.realidad__txt{
  display:block;
  color:var(--txt-2);
  font-size:var(--t-small);
  line-height:var(--lh-lead);
}


/* ============================================================
   EVIDENCIA — CIGRE TB 815
   Las únicas cifras de la página que no son propias. El gráfico
   son dos paneles de 520x512 que se apilan en teléfono: un solo
   SVG de 1200 de ancho dejaba la tipografía en 4px a 390.
   ============================================================ */

.evidencia__fig{
  margin:clamp(40px,6vw,72px) auto 0;
  max-width:1040px;
}

/* Dos paneles separados en vez de un SVG ancho: apilados en telefono
   la tipografia del grafico queda legible (a 1200 de ancho caia a 4px).
   520x512 cada uno, asi que el par cabe lado a lado sobre 820. */
.evidencia__paneles{
  display:grid;
  grid-template-columns:1fr;
  gap:var(--s-4);
}

.evidencia__paneles img{
  display:block;
  width:100%;
  height:auto;
  background:var(--pozo);
  border:1px solid var(--linea);
  border-radius:var(--r-2);
}

@media (min-width:820px){
  .evidencia__paneles{grid-template-columns:repeat(2,minmax(0,1fr))}
}

/* El pie del gráfico es una CITA, no un epígrafe decorativo: por eso
   queda en mono y en --txt-3, el mismo tono de las etiquetas de dato. */
.evidencia__pie{
  display:block;
  margin-top:var(--s-4);
  max-width:var(--w-medida);
  color:var(--txt-3);
  line-height:var(--lh-lead);
}

.evidencia__pie cite{font-style:italic}

/* La prosa va a ancho completo (.prosa ya se acota a --w-medida sola).
   Probado a dos columnas con la grilla al lado: la derecha quedaba el
   doble de alta que la izquierda. */
.evidencia__fig + .prosa{margin-block-start:clamp(40px,6vw,72px)}

.evidencia__h3{
  color:var(--txt);
  font-family:var(--f-display);
  letter-spacing:var(--ls-h2);
  margin:clamp(40px,6vw,72px) 0 0;
}

/* .acred__grid pasa a 3 columnas en _30-prueba.css, que se concatena
   DESPUÉS de este archivo: un selector de una sola clase perdería por
   orden de cascada. Con .evidencia delante gana por especificidad, sin
   !important. Son cuatro ítems: en dos columnas quedan 2x2 parejos,
   en tres quedaría uno huérfano. */
.evidencia .acred__grid{margin-block-start:var(--s-6)}

@media (min-width:900px){
  .evidencia .acred__grid{grid-template-columns:repeat(2,minmax(0,1fr))}
}



/* ============================================================
   DIAGRAMAS AMPLIABLES
   Cada diagrama es un enlace a su propio SVG. A 390 px de ancho los
   rótulos quedan en 4-6 px: subirlos dentro del SVG los haría chocar,
   porque cada composición está armada a mano para su tamaño. Abierto
   solo, el navegador lo muestra a pantalla completa y se amplía con
   dos dedos sin perder nitidez: es vectorial.
   ============================================================ */

.zoom{
  display:block;
  position:relative;
  border-radius:var(--r-2);
}

/* El aviso solo aparece donde hace falta: pantallas angostas. Va
   DEBAJO de la imagen y no encima: superpuesto tapaba rótulos (en el
   empalme recto se comía el «404» de «IEEE 404»), y cada diagrama
   tiene los rótulos en un lugar distinto. */
@media (max-width:719px){
  .zoom::after{
    content:'↗ Toca para ampliar';
    display:block;
    margin-top:var(--s-2);
    text-align:right;
    font-family:var(--f-mono);
    font-size:var(--t-mono-xs);
    letter-spacing:var(--ls-mono);
    color:var(--txt-3);
  }
}

/* ============================================================
   TIGERVOLT — PROTOCOLO 0,1 Hz
   _30-prueba.css — PRUEBA, CONFIANZA Y CIERRE
   Secciones 9 a 13: .acred · .metodo · .terreno · .cobertura · .cierre

   REGLAS QUE ESTE ARCHIVO RESPETA:
   · Solo tokens del bloque :root. Cero hex sueltos.
   · Toda regla que OCULTE algo para animarlo va prefijada `.js`.
     Sin JavaScript no se esconde nada: las cinco secciones se leen completas.
   · Todo :hover vive dentro de @media (hover:hover) and (pointer:fine).
   · Mobile-first. Breakpoints canónicos: 560 / 900 / 1200. Alturas en svh.
   · No define tokens, reset, .nav ni .pie.
   ============================================================ */


/* Anclas: la nav fija mide 64px. Que un deep link no deje el
   titular debajo de la barra. */
.acred,
.metodo,
.terreno,
.cobertura,
.cierre{scroll-margin-top:var(--s-8)}


/* ============================================================
   9 · ACREDITACIÓN — .acred
   «Lo que pide un contrato.»
   El bloque que decide la orden de compra. Deliberadamente plano
   y denso: después de la hoja de papel, la contención visual ES
   la señal de credibilidad. Se lee como un libro de registro, no
   como una tarjeta de marketing.
   ============================================================ */

.acred__grid{
  display:grid;
  grid-template-columns:1fr;
  /* Ledger de hairlines: el gap PINTA la línea. Un solo trazo
     continuo entre celdas, nunca bordes dobles. */
  gap:1px;
  background:var(--linea);
  border:1px solid var(--linea);
  margin:0;
  margin-block-start:var(--s-7);
}

.acred__item{
  display:flex;
  flex-direction:column;
  gap:var(--s-3);
  /* --panel y no --void: bloque denso en texto. A las dos de la
     tarde en un patio de subestación, el 3% de luminancia es un
     espejo negro. */
  background:var(--panel);
  box-shadow:var(--bisel);
  padding:var(--s-5);
  margin:0;
}

.acred__eti{
  display:flex;
  align-items:center;
  gap:var(--s-2);
  font-family:var(--f-mono);
  font-size:var(--t-mono-s);
  letter-spacing:var(--ls-slug);
  text-transform:uppercase;
  color:var(--txt-3);
  margin:0;
}

/* Marca de registro: un tick naranja de 10px por casillero.
   Es la única licencia decorativa de la sección. */
.acred__eti::before{
  content:"";
  flex:none;
  width:10px;
  height:2px;
  background:var(--naranja);
}

.acred__val{
  font-size:var(--t-small);
  line-height:var(--lh-body);
  color:var(--txt-2);
  margin:0;
  max-width:var(--w-medida);
}

/* La cifra dentro del casillero no compite con el H2: se acota a
   --t-h3 (mínimo 25,6px, sobre el umbral de 24px que habilita el
   naranja como color de texto). */
.acred__val .cifra{
  font-size:var(--t-h3);
  line-height:1;
  color:var(--naranja);
  margin-inline-end:.15em;
}

/* Nota de integridad: no publicamos logos de clientes sin permiso. */
.acred__nota{
  margin-block-start:var(--s-6);
  padding-inline-start:var(--s-4);
  border-inline-start:2px solid var(--linea);
  font-size:var(--t-small);
  line-height:var(--lh-body);
  color:var(--txt-3);
}

/* Dos vías de contacto: WhatsApp (rápida) y correo formal con RFQ. */
.acred__vias{
  display:grid;
  grid-template-columns:1fr;
  gap:var(--s-5);
  align-items:center;
  margin-block-start:var(--s-7);
  padding-block-start:var(--s-6);
  border-block-start:1px solid var(--linea);
}

.acred__vias .prosa{margin:0}

.acred__mail{
  width:100%;
  justify-content:center;
  text-align:center;
}


/* ============================================================
   10 · MÉTODO — .metodo
   «De la llamada al protocolo, en cuatro etapas.»
   Unifilar IEC 60617 arriba, cuatro etapas abajo. Baja la
   ansiedad de contratar a un proveedor nuevo.
   Fondo: .seccion--carbon + .rejilla (definidos aguas arriba).
   ============================================================ */

.metodo__svg{
  display:block;
  width:100%;
  height:auto;
  /* El viewBox es 1200×120. aspect-ratio fija la caja ANTES de
     que pinte el SVG: cero CLS y ningún hueco por preserveAspectRatio. */
  aspect-ratio:1200 / 120;
  overflow:visible;
  margin-block:var(--s-7);
  color:var(--txt-3);
}

/* El diagrama se dibuja con currentColor: un solo punto de verdad
   de color para símbolos, conductores y textos del unifilar. */
.metodo__svg path,
.metodo__svg line,
.metodo__svg polyline,
.metodo__svg circle,
.metodo__svg rect,
.metodo__svg g{
  fill:none;
  stroke:currentColor;
  stroke-width:1.5;
  stroke-linecap:butt;
  stroke-linejoin:miter;
  /* El SVG escala 10:1; sin esto el trazo engorda en desktop. */
  vector-effect:non-scaling-stroke;
}

.metodo__svg text,
.metodo__svg .metodo__svg-txt{
  fill:var(--txt-3);
  stroke:none;
  font-family:var(--f-mono);
  font-size:var(--t-mono-s);
  letter-spacing:var(--ls-slug);
  text-transform:uppercase;
}

/* TRAZADO DEL UNIFILAR.
   Cada nodo del SVG lleva pathLength="1", así el dashoffset es
   1 → 0 sin importar el largo real del path.
   Prefijo .js: sin JavaScript el diagrama nace dibujado. */
.js .metodo .metodo__svg > path,
.js .metodo .metodo__svg > line,
.js .metodo .metodo__svg > polyline,
.js .metodo .metodo__svg > circle,
.js .metodo .metodo__svg > rect,
.js .metodo .metodo__svg > g{
  stroke-dasharray:1;
  stroke-dashoffset:1;
}

.js .metodo .metodo__svg.is-in > path,
.js .metodo .metodo__svg.is-in > line,
.js .metodo .metodo__svg.is-in > polyline,
.js .metodo .metodo__svg.is-in > circle,
.js .metodo .metodo__svg.is-in > rect,
.js .metodo .metodo__svg.is-in > g{
  stroke-dashoffset:0;
  transition:stroke-dashoffset var(--d-largo) var(--e-revelado);
}

/* Stagger de 200ms por nodo: fuente → seccionador → transformador → carga. */
.js .metodo .metodo__svg.is-in > :nth-child(1){transition-delay:0ms}
.js .metodo .metodo__svg.is-in > :nth-child(2){transition-delay:200ms}
.js .metodo .metodo__svg.is-in > :nth-child(3){transition-delay:400ms}
.js .metodo .metodo__svg.is-in > :nth-child(4){transition-delay:600ms}
.js .metodo .metodo__svg.is-in > :nth-child(5){transition-delay:800ms}
.js .metodo .metodo__svg.is-in > :nth-child(6){transition-delay:1000ms}

.metodo__pasos{
  display:grid;
  grid-template-columns:1fr;
  gap:var(--s-6);
  list-style:none;
  margin:0;
  padding:0;
  counter-reset:none;
}

.metodo__paso{
  position:relative;
  padding-block-start:var(--s-4);
  border-block-start:1px solid var(--linea);
}

/* Hairline energizado: los primeros 32px de la regla van en naranja.
   Es la firma de «esta etapa está bajo tensión». */
.metodo__paso::before{
  content:"";
  position:absolute;
  inset-block-start:-1px;
  inset-inline-start:0;
  width:32px;
  height:1px;
  background:var(--naranja);
}

.metodo__num{
  display:block;
  font-family:var(--f-mono);
  font-size:var(--t-mono-s);
  letter-spacing:var(--ls-slug);
  color:var(--naranja);
  margin-block-end:var(--s-2);
}

/* .h3 reducido: cuatro columnas de ~290px no admiten el h3 pleno. */
.metodo__paso .metodo__tit{
  font-size:var(--t-h4);
  letter-spacing:.02em;
  margin:0 0 var(--s-3);
}

.metodo__txt{
  font-size:var(--t-small);
  line-height:var(--lh-body);
  color:var(--txt-2);
  max-width:var(--w-medida);
  margin:0;
}


/* ============================================================
   11 · TERRENO — .terreno
   «Trabajo propio, en terreno.»
   Seis fotos reales de 800px. NUNCA a sangre: a ancho de columna
   se ven nítidas, a pantalla completa se ven blandas.
   Grado fotográfico unificado = un archivo heterogéneo leído como
   una sola película.
   ============================================================ */

.terreno{
  /* Encuadre único para las seis. Las fuentes son 800×601 y 800×451;
     un solo aspect-ratio con object-fit:cover unifica la grilla y
     además clava la altura antes de la descarga: CLS 0. */
  --terreno-ratio:3 / 2;
}

.terreno__grid{
  display:grid;
  grid-template-columns:1fr;
  gap:var(--s-5);
  margin-block-start:var(--s-7);
}

.terreno__item{
  position:relative;
  /* Aísla el color-dodge del overlay: sin esto el blend se
     propaga al fondo de la sección. */
  isolation:isolate;
  margin:0;
}

.terreno__img{
  display:block;
  width:100%;
  height:auto;
  aspect-ratio:var(--terreno-ratio);
  object-fit:cover;
  background:var(--pozo);
  border:1px solid var(--linea);
  /* GRADO UNIFICADO */
  filter:contrast(1.08) saturate(.85) brightness(.92);
  transition:filter var(--d-revelado) var(--e-revelado);
}

.terreno__grado{
  position:absolute;
  inset-block-start:0;
  inset-inline:0;
  aspect-ratio:var(--terreno-ratio);
  background:var(--naranja);
  mix-blend-mode:color-dodge;
  opacity:.12;
  pointer-events:none;
  transition:opacity var(--d-revelado) var(--e-revelado);
}

.terreno__slug{
  display:block;
  margin-block-start:var(--s-3);
  padding-block-start:var(--s-3);
  border-block-start:1px solid var(--linea);
  color:var(--txt-3);
  transition:color var(--d-hover) var(--e-micro),
             border-color var(--d-hover) var(--e-micro);
}

/* ESTADO ACTIVO: color pleno. En móvil lo activa el
   IntersectionObserver de la foto centrada en el viewport. */
.terreno__item.is-activa .terreno__img{filter:none}
.terreno__item.is-activa .terreno__grado{opacity:0}
.terreno__item.is-activa .terreno__slug{
  color:var(--txt-2);
  border-block-start-color:var(--linea-carga);
}

.terreno__nota{
  margin-block-start:var(--s-6);
  padding-inline-start:var(--s-4);
  border-inline-start:2px solid var(--linea);
  color:var(--txt-3);
}


/* ============================================================
   12 · COBERTURA — .cobertura
   «Donde esté el cable.»
   La objeción logística chilena. Sin mapa de Chile, sin pines
   pulsando: una sola vertical con tres marcas. Chile abstracto,
   sofisticación por sustracción.
   Fondo: .seccion--carbon + .rejilla.
   ============================================================ */

.cobertura__cols{
  display:grid;
  grid-template-columns:1fr;
  gap:var(--s-7);
  align-items:start;
  margin-block-start:var(--s-7);
}

/* Columna izquierda: zonas y plazos indicativos como lectura de
   instrumento, no como bullets de folleto. */
.cobertura__zonas{
  display:grid;
  grid-template-columns:1fr;
  gap:0;
  margin:0;
}

.cobertura__zonas > dt{
  padding-block-start:var(--s-3);
  border-block-start:1px solid var(--linea);
}

.cobertura__zonas > dd{
  margin:0 0 var(--s-5);
  padding-block-start:var(--s-2);
  font-size:var(--t-mono);
  line-height:var(--lh-body);
  color:var(--txt-2);
}

.cobertura__zonas > dd:last-child{margin-block-end:0}

/* LA LÍNEA.
   Un solo elemento. La línea y las TRES marcas de actividad son
   background-image, así las marcas se descubren solas a medida
   que el trazo avanza — el escalonado sale de la geometría, no de
   tres transition-delay inventados.
   Móvil: horizontal, se dibuja de izquierda a derecha.
   ≥900px: vertical de 400px, se dibuja de arriba abajo. */
.cobertura__linea{
  display:block;
  width:100%;
  height:12px;
  justify-self:center;
  background-image:
    linear-gradient(90deg,var(--linea-viva),var(--linea-viva)),
    linear-gradient(180deg,var(--naranja),var(--naranja)),
    linear-gradient(180deg,var(--naranja),var(--naranja)),
    linear-gradient(180deg,var(--naranja),var(--naranja));
  background-repeat:no-repeat;
  background-size:100% 1px, 2px 12px, 2px 12px, 2px 12px;
  background-position:0 50%, 18% 0, 52% 0, 86% 0;
  transform-origin:left center;
}

/* Prefijo .js: sin JavaScript la línea nace trazada. */
.js .cobertura .cobertura__linea{transform:scaleX(0)}
.js .cobertura .cobertura__linea.is-in{
  transform:scaleX(1);
  transition:transform var(--d-largo) var(--e-revelado);
}

/* Columna derecha: prosa de coordinación + CTA.
   `> div` es el único hijo <div> del contenedor (los otros dos son
   <dl> y <i>), así que no necesita clase propia. */
.cobertura__cols > div{
  display:flex;
  flex-direction:column;
  align-items:flex-start;
  gap:var(--s-5);
}

.cobertura__cols > div .prosa{margin:0}
.cobertura__cols > div .btn{width:100%;justify-content:center}


/* ============================================================
   13 · CIERRE — .cierre
   «Hablemos.»
   EL ARCO DE CIERRE. El único arco eléctrico del sitio y llega al
   final. Deliberadamente MUDO: ni una cifra encima. El arco es
   puntuación, no lectura.
   ============================================================ */

.cierre{
  position:relative;
  isolation:isolate;
  overflow:clip;
  min-height:100svh;
  display:grid;
  align-content:center;
  background:var(--void);
  border-block-start:1px solid var(--linea);
  padding-block:var(--pad-seccion);
  /* Bajo 768px el dock es una barra fija: se reserva su alto más
     la barra de gestos del iPhone para que los datos de contacto
     nunca queden tapados. */
  padding-block-end:calc(var(--pad-seccion) + var(--s-8) + env(safe-area-inset-bottom,0px));
}

/* CANVAS DEL ARCO.
   Dimensiones CSS estables: caja absoluta al 100% de un padre con
   min-height declarada. El JS lee este box para dimensionar el
   backing store con DPR clamp; si el box respirara con el
   contenido, el canvas se re-escalaría en cada frame. */
.cierre__canvas{
  position:absolute;
  inset:0;
  display:block;
  width:100%;
  height:100%;
  z-index:var(--z-canvas);
  pointer-events:none;
}

.cierre > .wrap{
  position:relative;
  z-index:var(--z-contenido);
  text-align:center;
}

/* Scrim de legibilidad: el titular y el botón se leen igual en el
   fotograma de disparo del arco. Radial de --void, sin blend y sin
   filter — cero costo de composición. */
.cierre > .wrap::before{
  content:"";
  position:absolute;
  inset:calc(var(--s-8) * -1);
  z-index:-1;
  background:radial-gradient(ellipse 78% 62% at 50% 50%,
             var(--void) 0%, var(--void) 34%, transparent 76%);
  opacity:.82;
  pointer-events:none;
}

/* TERMINALES FIJOS a 12% / 88%, altura 50%: los dos electrodos
   entre los que salta el arco. Existen en CSS para que el encuadre
   sea real aunque el canvas nunca cargue.
   Solo ≥900px: bajo ese ancho caerían sobre el texto. */
.cierre::before,
.cierre::after{content:none}

.cierre__h2{
  font-size:var(--t-h1);
  line-height:var(--lh-h1);
  letter-spacing:var(--ls-h1);
  margin:0 0 var(--s-5);
}

.cierre .lead{
  margin-inline:auto;
  margin-block-end:var(--s-7);
}

.cierre__cta{margin-block-end:var(--s-6)}

/* Estado de atención en vivo (America/Santiago). El color NUNCA va
   solo: el texto dice «en línea» o «fuera de horario». */
.cierre__estado{
  display:inline-flex;
  align-items:center;
  gap:var(--s-2);
  color:var(--txt-3);
  margin:0 0 var(--s-5);
}

.cierre__led{
  flex:none;
  width:6px;
  height:6px;
  border-radius:50%;
  /* currentColor: js/whatsapp.js puede colorearlo con .is-activa
     o escribiendo color en línea. Fuera de horario queda --txt-3. */
  color:var(--txt-3);
  background:currentColor;
  transition:color var(--d-rele) var(--e-rele);
}

.cierre__led.is-activa{
  color:var(--ok);
  box-shadow:0 0 8px currentColor;
}

.cierre__datos{
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:var(--s-3);
  list-style:none;
  margin:0 0 var(--s-6);
  padding:0;
  color:var(--txt-2);
}

.cierre__datos li{margin:0}

.cierre__datos a{
  color:var(--txt-2);
  text-decoration:none;
  border-block-end:1px solid var(--linea);
  padding-block-end:2px;
  transition:color var(--d-hover) var(--e-micro),
             border-color var(--d-hover) var(--e-micro);
}

/* Nota de emergencia: «Si es una emergencia, llama.» */
.cierre > .wrap > .mono--s{
  display:block;
  max-width:var(--w-lead);
  margin-inline:auto;
  color:var(--txt-3);
}


/* ============================================================
   HOVER — solo con puntero fino. En táctil no existe :hover;
   en su lugar, :active discreto.
   ============================================================ */

@media (hover:hover) and (pointer:fine){
  .terreno__item:hover .terreno__img,
  .terreno__item:focus-within .terreno__img{filter:none}

  .terreno__item:hover .terreno__grado,
  .terreno__item:focus-within .terreno__grado{opacity:0}

  .terreno__item:hover .terreno__slug,
  .terreno__item:focus-within .terreno__slug{
    color:var(--txt-2);
    border-block-start-color:var(--linea-carga);
  }

  .acred__item:hover{border-color:var(--linea-viva)}

  .cierre__datos a:hover{
    color:var(--txt);
    border-block-end-color:var(--naranja);
  }
}

@media (hover:none){
  .cierre__datos a:active{transform:scale(.985);transition:transform 90ms var(--e-micro)}
}


/* ============================================================
   ≥560px — tablet chico
   ============================================================ */

@media (min-width:560px){
  .acred__grid{grid-template-columns:repeat(2,minmax(0,1fr))}
  .terreno__grid{grid-template-columns:repeat(2,minmax(0,1fr))}

  .acred__mail{width:auto}
  .cobertura__cols > div .btn{width:auto}
}


/* ============================================================
   ≥900px — corte de layout mayor
   ============================================================ */

@media (min-width:900px){
  .acred__grid{grid-template-columns:repeat(3,minmax(0,1fr))}

  .acred__vias{
    grid-template-columns:minmax(0,1fr) auto;
    gap:var(--s-7);
  }
  .acred__mail{justify-self:end}

  .metodo__pasos{
    grid-template-columns:repeat(4,minmax(0,1fr));
    gap:var(--s-5);
  }

  .terreno__grid{
    grid-template-columns:repeat(3,minmax(0,1fr));
    gap:var(--s-6);
  }

  /* dl · línea · prosa. La vertical vive ENTRE las dos columnas. */
  .cobertura__cols{
    grid-template-columns:minmax(0,1fr) 12px minmax(0,1fr);
    gap:var(--s-8);
    align-items:center;
  }

  .cobertura__linea{
    width:12px;
    height:400px;
    max-height:100%;
    align-self:center;
    background-image:
      linear-gradient(180deg,var(--linea-viva),var(--linea-viva)),
      linear-gradient(90deg,var(--naranja),var(--naranja)),
      linear-gradient(90deg,var(--naranja),var(--naranja)),
      linear-gradient(90deg,var(--naranja),var(--naranja));
    background-size:1px 100%, 12px 2px, 12px 2px, 12px 2px;
    background-position:50% 0, 0 18%, 0 52%, 0 86%;
    transform-origin:center top;
  }

  .js .cobertura .cobertura__linea{transform:scaleY(0)}
  .js .cobertura .cobertura__linea.is-in{transform:scaleY(1)}

  /* Los dos electrodos que enmarcan «Hablemos». */
  .cierre::before,
  .cierre::after{
    content:"";
    position:absolute;
    inset-block-start:50%;
    z-index:var(--z-grid);
    width:2px;
    height:56px;
    margin-block-start:-28px;
    background:linear-gradient(180deg,transparent,var(--linea-viva) 22%,var(--naranja-lo) 50%,var(--linea-viva) 78%,transparent);
    pointer-events:none;
  }
  .cierre::before{inset-inline-start:12%}
  .cierre::after{inset-inline-end:12%}

  .cierre__cta{width:auto;min-width:min(420px,100%);margin-inline:auto}

  .cierre__datos{
    flex-direction:row;
    flex-wrap:wrap;
    justify-content:center;
    gap:var(--s-3) var(--s-6);
  }
}


/* ============================================================
   ≥1200px — desktop pleno
   ============================================================ */

@media (min-width:1200px){
  .terreno__grid{gap:var(--s-7)}
  .metodo__pasos{gap:var(--s-6)}
  .cobertura__cols{gap:var(--s-9)}
}


/* ============================================================
   REDUCED MOTION
   Modo, no apagón. El bloque global ya lleva las duraciones a 1ms;
   aquí se garantiza además que ningún elemento de estas cinco
   secciones dependa de una clase que el JS podría no llegar a
   escribir: el unifilar nace dibujado y la línea nace trazada.
   ============================================================ */

@media (prefers-reduced-motion:reduce){
  .js .metodo .metodo__svg > path,
  .js .metodo .metodo__svg > line,
  .js .metodo .metodo__svg > polyline,
  .js .metodo .metodo__svg > circle,
  .js .metodo .metodo__svg > rect,
  .js .metodo .metodo__svg > g{
    stroke-dasharray:none;
    stroke-dashoffset:0;
  }

  .js .cobertura .cobertura__linea{transform:none}

  /* El grado fotográfico sigue cambiando en el ítem activo: es
     feedback funcional, no decoración. Solo deja de tardar. */
  .terreno__img,
  .terreno__grado,
  .terreno__slug{transition:none}
}


/* ============================================================
   ADENDA — PÁGINA DE CONTACTO (contacto.html)

   Tres bloques que la home no necesitaba y que el contrato de
   clases no cubría: el FORMULARIO de cotización, la FICHA DE MAPA
   y la LISTA DE PREGUNTAS FRECUENTES.

   Se escriben aquí, al final del último parcial, siguiendo el
   patrón bloque__elemento del contrato y usando EXCLUSIVAMENTE
   tokens del :root. Ningún literal de color.
   ============================================================ */

/* --- FORMULARIO -------------------------------------------------
   Panel denso sobre --panel, mismo bisel que .acred__item. Los
   controles nacen sin sombra de navegador: el foco lo da el anillo
   global (outline --arco-azul), y el borde inferior naranja marca
   el campo activo, igual que el subrayado de .enlace.
   ---------------------------------------------------------------- */

.form{
  background:var(--panel);
  box-shadow:var(--bisel);
  border:1px solid var(--linea);
  padding:var(--s-5);
  display:grid;
  gap:var(--s-5);
  margin-block-start:var(--s-7);
}

@media (min-width:768px){
  .form{padding:var(--s-7)}
}

.form__fila{
  display:grid;
  grid-template-columns:1fr;
  gap:var(--s-5);
}

@media (min-width:640px){
  .form__fila{grid-template-columns:1fr 1fr}
}

.form__campo{
  display:flex;
  flex-direction:column;
  gap:var(--s-2);
  min-width:0;
  /* Cada campo es un <p>: la regla global «p + p{margin-top:1em}» bajaba
     1em el segundo de cada fila y desalineaba las dos columnas. */
  margin:0;
}

.form__eti{
  font-family:var(--f-mono);
  font-size:var(--t-mono-s);
  letter-spacing:var(--ls-slug);
  text-transform:uppercase;
  color:var(--txt-3);
}

/* Asterisco de campo obligatorio. Naranja, pero acompañado
   SIEMPRE del atributo required: el color nunca es el único canal. */
.form__req{color:var(--naranja)}

.form__control{
  width:100%;
  background:var(--pozo);
  color:var(--txt);
  /* --txt-4 y no --linea: el borde es lo que dice «aquí se escribe».
     --linea daba 1,16:1 contra el --panel del formulario (WCAG 1.4.11
     pide 3:1); --txt-4 da 3,87:1 contra el panel y 4,34:1 contra el relleno. */
  border:1px solid var(--txt-4);
  border-radius:var(--r-1);
  padding:var(--s-3) var(--s-4);
  font-size:var(--t-body);
  line-height:var(--lh-body);
  transition:border-color var(--d-micro) var(--e-micro),
             background-color var(--d-micro) var(--e-micro);
  appearance:none;
}

/* --txt-4 daba 4,34:1 sobre --pozo y el placeholder es texto: pide 4,5. */
.form__control::placeholder{color:var(--txt-3)}
.form__control:hover{border-color:var(--txt-3)}
.form__control:focus{
  border-color:var(--naranja);
  background:var(--carbon);
  outline-offset:2px;
}

/* El textarea es el campo que más importa: ahí va el dato técnico. */
textarea.form__control{min-height:140px;resize:vertical}

/* select: la flecha nativa se pierde con appearance:none, así que
   se repone con un gradiente cónico — cero SVG externo, cero JS. */
select.form__control{
  padding-inline-end:var(--s-7);
  background-image:linear-gradient(45deg,transparent 50%,var(--txt-3) 50%),
                   linear-gradient(135deg,var(--txt-3) 50%,transparent 50%);
  background-position:calc(100% - 22px) calc(50% + 1px),calc(100% - 16px) calc(50% + 1px);
  background-size:6px 6px,6px 6px;
  background-repeat:no-repeat;
}
select.form__control option{background:var(--pozo);color:var(--txt)}

.form__acciones{
  display:grid;
  grid-template-columns:1fr;
  gap:var(--s-4);
}

@media (min-width:640px){
  .form__acciones{grid-template-columns:1fr 1fr}
}

.form__nota{
  font-size:var(--t-small);
  line-height:var(--lh-body);
  color:var(--txt-3);
  margin:0;
}

/* Mensaje de estado del envío. Nace vacío y sin caja: solo pinta
   cuando el script escribe texto dentro. */
.form__estado{
  font-family:var(--f-mono);
  font-size:var(--t-mono-s);
  letter-spacing:var(--ls-mono);
  color:var(--txt-3);
  margin:0;
  min-height:1.2em;
}

/* Resultado del envío. Sin verde ni rojo: --ok y --alarma están
   reservados (chip APROBADO y falla del método). Lo que distingue un
   estado del otro es la frase en negrita, no el color; la barra
   lateral solo le da peso visual. */
.form__estado.is-ok,
.form__estado.is-error,
.form__enviado{
  font-family:var(--f-texto);
  font-size:var(--t-small);
  letter-spacing:normal;
  line-height:var(--lh-body);
  color:var(--txt-2);
  /* .mono--s del elemento lo pone en MAYÚSCULAS: aquí es un párrafo. */
  text-transform:none;
  padding:var(--s-3) var(--s-4);
  background:var(--pozo);
  border-left:3px solid var(--naranja);
}
.form__estado.is-error{border-left-color:var(--naranja-ambar)}
.form__estado strong,
.form__enviado strong{color:var(--txt)}

/* Botón principal mientras viaja la solicitud. No se usa [disabled]:
   deshabilitar el botón con foco tira el foco al <body>. */
.form [aria-disabled="true"]{opacity:.6;cursor:progress}

/* Confirmación del envío SIN JavaScript: FormSubmit devuelve a
   contacto.html#enviado y :target la muestra. Con JS nunca se usa. */
.form__enviado{display:none;margin-block-start:var(--s-5)}
.form__enviado:target{display:block}

/* Trampa para bots. Fuera de pantalla y fuera del árbol accesible
   (aria-hidden en el HTML); tabindex=-1 la saca del teclado. */
.form__trampa{
  position:absolute;
  width:1px;height:1px;
  overflow:hidden;
  clip-path:inset(50%);
  white-space:nowrap;
  margin:0;
}


/* --- MAPA --------------------------------------------------------
   El iframe es de un tercero: se encierra en un marco propio con
   la misma hairline del sistema y una ficha de dirección debajo,
   para que la tarjeta siga siendo legible si el iframe no carga.
   ------------------------------------------------------------------ */

.mapa{
  margin-block-start:var(--s-7);
  border:1px solid var(--linea);
  background:var(--panel);
  box-shadow:var(--bisel);
}

.mapa__marco{
  position:relative;
  display:block;
  width:100%;
  aspect-ratio:16/9;
  background:var(--pozo);
  border-bottom:1px solid var(--linea);
}

@media (max-width:640px){
  .mapa__marco{aspect-ratio:4/3}
}

.mapa__iframe{
  display:block;
  width:100%;
  height:100%;
  border:0;
  /* El mapa de OSM llega en blanco puro y rompe la ambientación:
     se baja el brillo y se desatura para que se integre al panel.
     Sigue perfectamente legible. */
  filter:grayscale(.55) contrast(.92) brightness(.82);
}

.mapa__ficha{
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  gap:var(--s-3) var(--s-5);
  padding:var(--s-5);
}

.mapa__ficha > .mono--s{margin:0;color:var(--txt-2)}


/* --- FAQ ---------------------------------------------------------
   <details>/<summary> nativo: abre y cierra sin una línea de JS,
   es accesible por teclado de fábrica y el buscador lee el texto
   aunque esté plegado.
   ------------------------------------------------------------------ */

.faq{
  margin-block-start:var(--s-7);
  border-block-start:1px solid var(--linea);
}

.faq__item{
  border-block-end:1px solid var(--linea);
}

.faq__q{
  display:flex;
  align-items:baseline;
  gap:var(--s-4);
  padding:var(--s-5) 0;
  cursor:pointer;
  list-style:none;
  font-size:var(--t-h4);
  line-height:var(--lh-h3);
  color:var(--txt);
  transition:color var(--d-micro) var(--e-micro);
}
.faq__q::-webkit-details-marker{display:none}

/* Indicador de estado: un signo tipográfico, no un icono que gire.
   + cerrado, − abierto. Snap instantáneo, coherente con --e-rele. */
.faq__q::before{
  content:"+";
  flex:none;
  font-family:var(--f-mono);
  font-size:var(--t-mono);
  color:var(--naranja);
  transform:translateY(-.15em);
}
.faq__item[open] > .faq__q::before{content:"\2212"}
.faq__item[open] > .faq__q{color:var(--naranja-hot)}

@media (hover:hover) and (pointer:fine){
  .faq__q:hover{color:var(--naranja-hot)}
}

.faq__r{
  padding:0 0 var(--s-5) calc(var(--s-4) + 1ch);
  max-width:var(--w-medida);
  font-size:var(--t-small);
  line-height:var(--lh-body);
  color:var(--txt-2);
}
.faq__r > * + *{margin-top:var(--s-4)}


/* ============================================================
   LEGAL — páginas de cumplimiento (privacidad, términos)

   BLOQUE NUEVO: no figuraba en el CONTRATO DE CLASES original.
   Se añade con el patrón bloque__elemento y SOLO tokens de :root.
   Motivo: el reset del sistema quita padding a `ul` y list-style a
   todo `ul[class]`, así que un texto legal con listas queda sin
   marca de viñeta. El resto de la página se resuelve con
   .seccion, .wrap--angosto, .h2, .h3, .lead, .prosa y .mono--s.

   Sin animación propia: un texto de cumplimiento se lee, no se
   coreografía. Nada aquí se oculta, así que no necesita prefijo .js.
   ============================================================ */

.legal{max-width:var(--ancho-angosto)}
.legal > * + *{margin-top:var(--s-8)}

/* Par de salidas al pie de la página: WhatsApp + correo. */
.legal__vias{
  display:flex;
  flex-wrap:wrap;
  gap:var(--s-4);
  margin-block-start:var(--s-6);
}

/* Cada artículo numerado de la política. */
.legal__bloque > * + *{margin-top:var(--s-4)}
.legal__bloque > h2 + *,
.legal__bloque > h3 + *{margin-top:var(--s-5)}

/* Ficha del responsable del tratamiento: datos de contacto en mono. */
.legal__ficha{
  border:1px solid var(--linea);
  border-radius:var(--r-1);
  padding:var(--s-5);
  color:var(--txt-2);
}

/* Lista legal. Viñeta tipográfica: un guion de 1px en naranja,
   coherente con .norma__sep y con la regla del sistema. */
.legal__lista{
  max-width:var(--w-medida);
  font-size:var(--t-body);
  line-height:var(--lh-body);
  color:var(--txt-2);
}
.legal__lista > li{position:relative;padding-left:var(--s-5)}
.legal__lista > li + li{margin-top:var(--s-3)}
.legal__lista > li::before{
  content:"";
  position:absolute;
  left:0;
  top:calc(var(--lh-body) * .5em);
  width:10px;
  height:1px;
  background:var(--naranja);
}


/* --- LEGAL (páginas de pie: términos y condiciones, privacidad) ---
   CLASES NUEVAS, creadas con el patrón bloque__elemento del contrato
   porque no existía ningún bloque de documento de texto largo.
   Solo tokens del :root. Nada de movimiento: es un documento, no una
   pieza de marketing.
   .legal          columna de cláusulas
   .legal__indice  índice de anclas (reutiliza .chip en cada enlace)
   .legal__art     una cláusula, separada por hairline
   .legal__num     numeral mono en naranja
   .legal__lista   lista con guion naranja en vez de bullet
   .legal__item    ítem de esa lista
   .legal__nota    párrafo destacado dentro de una cláusula (panel)
   ------------------------------------------------------------------ */

.legal__indice{
  display:flex;
  flex-wrap:wrap;
  gap:var(--s-2);
  margin-block-start:var(--s-6);
}
.legal__indice .chip{
  transition:border-color var(--d-hover) var(--e-micro),color var(--d-hover) var(--e-micro);
}
.legal__indice .chip:focus-visible{border-color:var(--naranja);color:var(--txt)}

@media (hover:hover) and (pointer:fine){
  .legal__indice .chip:hover{border-color:var(--naranja);color:var(--txt)}
}

.legal{
  display:grid;
  gap:var(--s-7);
}

.legal__art{
  max-width:var(--w-medida);
  border-block-start:1px solid var(--linea);
  padding-block-start:var(--s-5);
  font-size:var(--t-body);
  line-height:var(--lh-body);
  color:var(--txt-2);
  text-wrap:pretty;
}
.legal__art > * + *{margin-top:var(--s-4)}

.legal__num{
  display:block;
  color:var(--naranja);
}

.legal__lista{
  list-style:none;
  display:grid;
  gap:var(--s-3);
}

.legal__item{
  position:relative;
  padding-inline-start:calc(var(--s-4) + var(--s-1));
}
.legal__item::before{
  content:"";
  position:absolute;
  inset-inline-start:0;
  inset-block-start:.7em;
  width:10px;
  height:1px;
  background:var(--naranja);
}

.legal__nota{
  border:1px solid var(--linea);
  border-inline-start:2px solid var(--naranja-lo);
  background:var(--panel);
  padding:var(--s-5);
  border-radius:var(--r-1);
  font-size:var(--t-small);
  color:var(--txt-2);
}

/* --- FACHADA DEL MAPA ---
   El iframe de OpenStreetMap ya no se carga solo: transmitía IP y
   User-Agent a un tercero sin que nadie lo pidiera. Este es el estado
   previo, con el botón centrado en el mismo marco que ocupará el mapa. */
.mapa__marco[data-mapa]{
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:center;
  gap:var(--s-3);
  min-height:clamp(220px,38vw,420px);
  background:var(--pozo);
  border:1px solid var(--linea);
  border-radius:var(--r-2);
}
.mapa__aviso{
  margin:0;
  color:var(--txt-3);
}
