/* ============================================================
   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);
  /* El fondo reserva el alto del dock de WhatsApp (fixed). Sin esto, en
     teléfono la barra de 56px tapaba para siempre la última línea del pie
     (no hay más página para bajar), y en escritorio la pastilla tapaba la
     esquina derecha. Barra: 48px + 2×4px de relleno + zona segura. */
  padding-block:var(--s-9) calc(var(--s-7) + 56px + env(safe-area-inset-bottom,0px));
}
@media (min-width:768px){
  /* Pastilla: 56px de alto, despegada clamp(16px,3vw,32px) del borde. */
  .pie{padding-bottom:calc(var(--s-7) + 56px + clamp(16px,3vw,32px))}
}

.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)}

/* Crédito de diseño: tercera columna de la grilla (logo · razón social ·
   firma). Antes compartía columna con un colofón de tipografías, que se
   retiró a pedido del dueño (octubre 2026). */
.pie__firma{display:grid;gap:var(--s-2)}
.pie__firma p{margin:0}
@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__credito{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;
}

/* UNIFILAR SEGÚN ANCHO.
   El horizontal (1200×120) escala 10:1: a 390 px sus rótulos quedaban en
   3 px. Bajo 768 px se muestra la versión vertical (360×560). Entre 768 y
   1199 px los rótulos del horizontal suben a 17 unidades (≈10-15 px reales);
   a ese tamaño todavía no chocan entre sí ni con los símbolos. */
.metodo__svg--v{display:none}
@media (max-width:767px){
  .metodo__svg--h{display:none}
  .metodo__svg--v{
    display:block;
    aspect-ratio:360 / 560;
    max-width:360px;
    margin-inline:auto;
  }
  .metodo__svg--v text{font-size:15px}
}
@media (min-width:768px) and (max-width:1199px){
  .metodo__svg--h text{font-size:17px}
}

/* 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);
}
