:root{
  --bg:#fbf7f0;
  --panel:#f5efe4;
  --panel-2:#eee5d4;
  --ink:#1c1a16;
  --ink-2:#665f52;
  --ink-3:#948c7c;
  --hair:#e5dcc8;
  --hair-2:#d3c6a8;
  --green:#e8930f;
  --green-dim:#f3c877;
  --amber:#c2410c;
  --cyan:#8a5a1f;
}
/* === Fuentes en local (licencia OFL) ===
   Antes se cargaban desde Google Fonts, lo que enviaba la IP del visitante a
   Google en cada petición. Sirviéndolas en local se elimina esa cesión de datos
   a terceros y se gana en rendimiento (una conexión menos al cargar la página).
   Unicode-range idéntico al de Google Fonts, para que el navegador cargue solo
   el subset necesario. */
@font-face{
  font-family:'Instrument Sans';
  font-style:normal;
  font-weight:400 700;          /* variable font: un solo archivo, todos los pesos */
  font-display:swap;
  src:url(../fonts/instrument-sans-latin-ext.woff2) format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face{
  font-family:'Instrument Sans';
  font-style:normal;
  font-weight:400 700;
  font-display:swap;
  src:url(../fonts/instrument-sans-latin.woff2) format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:'IBM Plex Mono';
  font-style:normal;
  font-weight:400;
  font-display:swap;
  src:url(../fonts/ibm-plex-mono-400-latin-ext.woff2) format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face{
  font-family:'IBM Plex Mono';
  font-style:normal;
  font-weight:400;
  font-display:swap;
  src:url(../fonts/ibm-plex-mono-400-latin.woff2) format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:'IBM Plex Mono';
  font-style:normal;
  font-weight:500;
  font-display:swap;
  src:url(../fonts/ibm-plex-mono-500-latin-ext.woff2) format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face{
  font-family:'IBM Plex Mono';
  font-style:normal;
  font-weight:500;
  font-display:swap;
  src:url(../fonts/ibm-plex-mono-500-latin.woff2) format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:'IBM Plex Mono';
  font-style:normal;
  font-weight:600;
  font-display:swap;
  src:url(../fonts/ibm-plex-mono-600-latin-ext.woff2) format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face{
  font-family:'IBM Plex Mono';
  font-style:normal;
  font-weight:600;
  font-display:swap;
  src:url(../fonts/ibm-plex-mono-600-latin.woff2) format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
/* Playfair Display (OFL), servida en local como las otras dos. Es la única
   serif del sitio y se usa SOLO en el bloque de últimas noticias de la home:
   es lo que le da el aire de cabecera de periódico. Variable (400–900) en un
   solo archivo, así que el titular a 900 no cuesta una descarga aparte.
   Si algún día deja de usarse ese bloque, borrar también los dos .woff2. */
@font-face{
  font-family:'Playfair Display';
  font-style:normal;
  font-weight:400 900;
  font-display:swap;
  src:url(../fonts/playfair-display-latin-ext.woff2) format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face{
  font-family:'Playfair Display';
  font-style:normal;
  font-weight:400 900;
  font-display:swap;
  src:url(../fonts/playfair-display-latin.woff2) format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
*{margin:0;padding:0;box-sizing:border-box}
/* overflow-x:clip corta cualquier desbordamiento lateral en seco: sin él, un
   solo elemento que se pase unos píxeles deja la página moviéndose de lado en
   móvil, con una franja en blanco a la derecha. Se pone en html y body porque
   los navegadores propagan el overflow del body al viewport y, si solo se pone
   en uno, el efecto depende del navegador.
   `clip` y no `hidden`: `hidden` crea un contenedor de scroll y rompería el
   `position:sticky` del header. */
html,body{overflow-x:clip;max-width:100%}
html{scroll-behavior:smooth}
body{background:var(--bg);color:var(--ink);font-family:'Instrument Sans',system-ui,sans-serif;line-height:1.55;-webkit-font-smoothing:antialiased}
a{color:inherit;text-decoration:none}
.mono{font-family:'IBM Plex Mono',monospace}
.wrap{max-width:1300px;margin:0 auto;padding:0 26px}
/* iframe de respaldo de Google Tag Manager (sin JS): nunca se ve */
.gtm-frame{display:none;visibility:hidden}

/* ===== ops strip ===== */
.ops{background:var(--panel-2);border-bottom:1px solid var(--hair);font-family:'IBM Plex Mono',monospace;font-size:14px;letter-spacing:.02em;color:var(--ink-3)}
.ops .wrap{display:flex;justify-content:space-between;align-items:center;height:40px;gap:18px}
.ops .l{display:flex;gap:20px;align-items:center;min-width:0}
.ops .dot{width:7px;height:7px;border-radius:50%;background:var(--green);box-shadow:0 0 8px var(--green);display:inline-block;margin-right:6px}
.ops b{color:var(--green)}
.ops a:hover{color:var(--ink)}
/* El teléfono y el email no se encogen: son los datos de contacto y un número
   recortado a media cifra no sirve de nada. Lo que sobra se va quitando por
   orden de menor valor a medida que baja el ancho. */
.ops .l a{flex:none;white-space:nowrap}
/* Los dos teléfonos van juntos en .tels con un punto central, para que el separador
   quede pegado a los números y no reparta el gap de 20px del strip. */
.ops .tels{display:flex;gap:10px;align-items:center;flex:none}
@media(max-width:900px){
  .ops .cif{display:none}                          /* fuera el CIF */
}
@media(max-width:760px){
  .ops{font-size:13px}
  .ops .wrap{gap:12px}
  .ops .l{gap:14px}
  .ops .horario{display:none}                      /* fuera el horario de atención */
}
@media(max-width:520px){
  .ops .ubi{display:none}                          /* fuera la ubicación: quedan teléfonos y email */
  .ops .wrap{justify-content:flex-end}
}
@media(max-width:380px){
  .ops .l a[href^="mailto:"]{display:none}         /* en pantallas muy estrechas, solo los teléfonos */
}

/* ===== header ===== */
header{border-bottom:1px solid var(--hair);position:sticky;top:0;z-index:50;background:rgba(251,247,240,.82);backdrop-filter:blur(10px)}
.head{display:flex;justify-content:space-between;align-items:center;height:88px;gap:24px}
.logo{display:flex;align-items:center;gap:11px;flex-shrink:0}
.logo img{height:54px;width:auto;display:block}
/* Estas reglas son del menú de escritorio, el que va dentro del header. Se
   acotan con `header nav` porque el menú de móvil también usa un <nav>, y sin
   acotar heredaba el display:flex y, peor, el display:none de ≤900px, que lo
   dejaba invisible justo donde tiene que verse. */
header nav{display:flex;gap:2px;font-size:16.5px}
header nav ul{list-style:none}
header nav>ul{display:flex;gap:2px}
header nav>ul>li{position:relative}
header nav>ul>li>a,nav>ul>li>.has-sub{padding:10px 15px;color:var(--ink-2);border-radius:5px;display:flex;align-items:center;gap:6px;cursor:default}
header nav>ul>li>a{cursor:pointer}
header nav>ul>li>a:hover,nav>ul>li:hover>.has-sub{color:var(--ink);background:var(--panel-2)}
header nav>ul>li.on>a,nav>ul>li.on>.has-sub{color:var(--ink);font-weight:600}
header nav .caret{width:10px;height:10px;stroke:currentColor;stroke-width:2;fill:none}
header nav .sub-menu{position:absolute;top:100%;left:0;min-width:262px;background:var(--bg);border:1px solid var(--hair);border-radius:8px;padding:6px;box-shadow:0 12px 28px rgba(28,26,22,.1);opacity:0;visibility:hidden;transform:translateY(4px);transition:.15s;z-index:60}
/* Solo el submenú directo del ítem sobre el que se está: con un descendiente
   cualquiera (` .sub-menu`) se abrirían a la vez todos los de tercer nivel. */
header nav>ul>li:hover>.sub-menu{opacity:1;visibility:visible;transform:translateY(0)}
header nav .sub-menu li a{padding:10px 13px;border-radius:6px;color:var(--ink-2);font-size:15px;display:block;white-space:nowrap}
header nav .sub-menu li a:hover{background:var(--panel-2);color:var(--ink)}

/* --- Tercer nivel: Servicios → Categoría → Producto ---------------------- */
/* La categoría que tiene productos abre su submenú al lado, no debajo. */
header nav .sub-menu li{position:relative}
header nav .sub-menu li a{display:flex;align-items:center;justify-content:space-between;gap:10px}
header nav .sub-menu .caret{width:11px;height:11px;stroke:currentColor;stroke-width:2;fill:none;flex-shrink:0;opacity:.55}
header nav li.tiene-sub:hover>a{background:var(--panel-2);color:var(--ink)}
/* El puente cubre el hueco entre el segundo y el tercer nivel: sin él, al
   cruzarlo con el ratón se pierde el :hover y el submenú se cierra. */
header nav li.tiene-sub::after{content:"";position:absolute;top:0;left:100%;width:12px;height:100%}
header nav .sub-menu-3{top:-7px;left:100%;margin-left:5px;transform:translateX(-4px)}
header nav .sub-menu li:hover>.sub-menu-3{opacity:1;visibility:visible;transform:translateX(0)}
/* Cerca del borde derecho el tercer nivel se sale de la pantalla, así que hasta
   1400px se despliega hacia la izquierda del segundo. El límite no es estético:
   el menú está pegado a la derecha y el submenú mide 262px, así que por debajo
   de ese ancho no cabe abriéndose hacia fuera (a 1280px se salía 123px). */
@media(max-width:1400px){
  header nav .sub-menu-3{left:auto;right:100%;margin-left:0;margin-right:5px;transform:translateX(4px)}
  header nav li.tiene-sub::after{left:auto;right:100%}
}
.kit{margin-left:8px;font-family:'IBM Plex Mono';font-size:14px;padding:10px 18px;border:1px solid var(--green-dim);color:var(--green)}
.kit:hover{background:var(--green);color:#04120a}
@media(max-width:1280px){
  .head{height:80px}
  .logo img{height:46px}
  header nav{font-size:15px}
  header nav>ul>li>a{padding:9px 11px}
  .kit{padding:9px 13px;font-size:13px;margin-left:4px}
}
@media(max-width:1080px){
  header nav{font-size:13.8px}
  header nav>ul>li>a{padding:8px 8px;gap:4px}
  .kit{padding:8px 11px;font-size:12px}
}
@media(max-width:900px){header nav{display:none}.head{height:72px}.logo img{height:44px}}

/* ===== hero ===== */
.hero{padding:72px 0 30px;border-bottom:1px solid var(--hair);position:relative;overflow:hidden}
.hero::before{content:"";position:absolute;inset:0;background-image:linear-gradient(var(--hair) 1px,transparent 1px);background-size:100% 46px;opacity:.4;mask-image:linear-gradient(180deg,transparent,#000 40%,transparent)}
.hero .wrap{position:relative}

/* --- hero de la home, con foto (05/08/2026) ---
   Variante acotada con .hero-home: el 404 usa el mismo .hero y debe seguir con
   la trama sobre fondo crema. La foto va en un ::before que sustituye a la
   trama, así que no hace falta ningún <div> extra en el HTML.
   El degradado de encima es el mismo recurso que .hero-photo .bg::after, pero
   más marcado por la izquierda: aquí el texto es más largo (h1 a 3 líneas más
   el lede) y cae sobre el cielo claro del amanecer, no sobre una zona oscura. */
.hero.hero-home{background:#14120e;border-bottom-color:rgba(255,255,255,.12)}
.hero.hero-home::before{
  background-image:
    linear-gradient(90deg,rgba(20,18,14,.92) 0%,rgba(20,18,14,.78) 38%,rgba(20,18,14,.42) 68%,rgba(20,18,14,.3) 100%),
    linear-gradient(180deg,rgba(20,18,14,.55) 0%,rgba(20,18,14,.3) 45%,rgba(20,18,14,.75) 100%),
    url(../img/hero-home.jpg);
  background-size:auto,auto,cover;
  background-position:center,center,center 62%;
  background-repeat:no-repeat;
  opacity:1;
  mask-image:none;
}
.hero.hero-home h1{color:#fff}
.hero.hero-home h1 em{color:var(--green-dim)}
.hero.hero-home .lede{color:rgba(255,255,255,.88)}
/* Las celdas de datos pasan a oscuro translúcido: en crema tapaban la foto con
   cuatro rectángulos claros y rompían el hero por la mitad. */
.hero.hero-home .board{background:rgba(255,255,255,.14);border-color:rgba(255,255,255,.14)}
.hero.hero-home .cell{background:rgba(20,18,14,.58);backdrop-filter:blur(3px)}
.hero.hero-home .cell .v{color:#fff}
.hero.hero-home .cell .k,
.hero.hero-home .cell .foot{color:rgba(255,255,255,.62)}
/* ⚠️ En estrecho hay que aflojar el degradado horizontal y encuadrar la foto a
   la derecha. El 92% de negro de la izquierda está pensado para que el texto
   caiga sobre el cielo claro teniendo la ciudad a la derecha; a 390px el
   viewport *es* la izquierda, así que la foto quedaba tapada del todo y el hero
   volvía a ser un rectángulo liso, justo lo que se quería evitar. Se sube al
   62% (sigue habiendo contraste de sobra sobre el cielo) y el encuadre se
   desplaza a la derecha, que es donde están los rascacielos. */
@media(max-width:760px){
  .hero.hero-home::before{
    background-image:
      linear-gradient(180deg,rgba(20,18,14,.5) 0%,rgba(20,18,14,.62) 55%,rgba(20,18,14,.8) 100%),
      url(../img/hero-home.jpg);
    background-size:auto,cover;
    background-position:center,72% 62%;
  }
}

.tag{font-family:'IBM Plex Mono';font-size:12px;letter-spacing:.16em;text-transform:uppercase;color:var(--green);margin-bottom:22px}
h1{font-size:clamp(2.6rem,6vw,4.5rem);line-height:1.03;letter-spacing:-.025em;font-weight:700;max-width:17ch}
h1 em{font-style:normal;color:var(--ink-3)}
.lede{margin-top:22px;font-size:1.32rem;color:var(--ink-2);max-width:56ch}
.actions{margin-top:30px;display:flex;gap:12px;flex-wrap:wrap}
.btn{font-size:14.5px;font-weight:600;padding:13px 22px;border-radius:7px;display:inline-flex;align-items:center;gap:9px;transition:.18s}
.btn.p{background:var(--green);color:#04120a}
.btn.p:hover{box-shadow:0 0 0 3px rgba(232,147,15,.25)}
.btn.s{border:1px solid var(--hair-2);color:var(--ink)}
.btn.s:hover{border-color:var(--ink-3);background:var(--panel)}

/* live board */
.board{margin-top:52px;display:grid;grid-template-columns:repeat(4,1fr);gap:1px;background:var(--hair);border:1px solid var(--hair)}
.cell{background:var(--panel);padding:18px 18px 14px}
.cell .k{font-family:'IBM Plex Mono';font-size:10.5px;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-3);display:flex;justify-content:space-between;align-items:center}
.cell .k .st{width:6px;height:6px;border-radius:50%;background:var(--green);box-shadow:0 0 6px var(--green)}
.cell .v{font-family:'IBM Plex Mono';font-size:2rem;font-weight:500;letter-spacing:-.02em;margin-top:10px;line-height:1}
.cell .v.v-sm{font-size:1.4rem}
.cell .v small{font-size:1rem;color:var(--ink-2)}
.cell svg{margin-top:12px;width:100%;height:34px;display:block}
.cell .foot{font-family:'IBM Plex Mono';font-size:11px;color:var(--ink-3);margin-top:8px}
.cell .foot b{color:var(--green)}
@media(max-width:900px){.board{grid-template-columns:1fr 1fr}}
@media(max-width:520px){.board{grid-template-columns:1fr}}

/* ===== services ===== */
.sec{padding:70px 0;border-bottom:1px solid var(--hair)}
.sec-h{display:flex;align-items:baseline;justify-content:space-between;margin-bottom:34px;gap:20px}
.sec-h h2{font-size:2.2rem;font-weight:700;letter-spacing:-.015em}
.sec-h .k{font-family:'IBM Plex Mono';font-size:12px;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3)}
.grid{display:grid;grid-template-columns:repeat(4,1fr);gap:1px;background:var(--hair);border:1px solid var(--hair)}
.svc{background:var(--panel);padding:24px 22px 26px;position:relative;transition:background .15s;min-height:172px;display:flex;flex-direction:column}
.svc:hover{background:var(--panel-2)}
.svc .top{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:16px}
.svc .ic{width:40px;height:40px;background:var(--green);border-radius:9px;display:flex;align-items:center;justify-content:center;padding:8px;transition:background .15s}
.svc .ic img{width:100%;height:100%;object-fit:contain;filter:brightness(0) invert(1)}
.svc:hover .ic{background:var(--amber)}
.svc .no{font-family:'IBM Plex Mono';font-size:11px;color:var(--ink-3)}
.svc h3{font-size:1.16rem;font-weight:600;margin-bottom:6px}
.svc p{font-size:1.02rem;color:var(--ink-2);line-height:1.45}
.svc .go{margin-top:auto;font-family:'IBM Plex Mono';font-size:11.5px;color:var(--ink-3);padding-top:14px}
.svc:hover .go{color:var(--green)}
.svc:hover .go::after{content:" →"}
svg.i{width:22px;height:22px;stroke:currentColor;stroke-width:1.5;fill:none;stroke-linecap:round;stroke-linejoin:round;display:block}
@media(max-width:900px){.grid{grid-template-columns:1fr 1fr}}
@media(max-width:520px){.grid{grid-template-columns:1fr}}

/* ===== últimas noticias (solo en la home) =====
   Maquetado como la portada de un periódico: cabecera con filete doble y fecha
   de edición, titular en serif (Playfair Display, la única del sitio) y noticia
   principal a dos columnas con su foto y pie. El aire de prensa lo dan los
   filetes, la serif y las versales en monoespaciada; no hay ni una imagen
   decorativa de adorno. */
.news-sec{padding:70px 0;border-bottom:1px solid var(--hair)}

/* Cabecera: filete grueso arriba y fino debajo, el recurso clásico de un
   masthead. El nombre va centrado y con mucho tracking, como un rótulo
   impreso. */
.news-masthead{border-top:3px solid var(--ink);border-bottom:1px solid var(--ink);padding:14px 0 12px;margin-bottom:8px;text-align:center}
.news-masthead h2{font-family:'Playfair Display',Georgia,serif;font-size:2.9rem;font-weight:900;letter-spacing:.02em;line-height:1;margin-bottom:8px}
.news-masthead .linea{display:flex;align-items:center;justify-content:center;gap:12px;font-family:'IBM Plex Mono';font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:var(--ink-2)}
.news-masthead .linea i{width:4px;height:4px;border-radius:50%;background:var(--green);display:inline-block}
/* Filete fino separado del doble de arriba: es la tercera raya del masthead. */
.news-rule{border-bottom:1px solid var(--hair-2);margin-bottom:34px}

/* Noticia de portada: texto a la izquierda, foto a la derecha. La columna de
   texto va primero en el HTML para que el titular sea lo primero que se lee
   con lector de pantalla y al apilarse en móvil. */
.news-lead{display:grid;grid-template-columns:1.15fr 1fr;gap:44px;align-items:start}
.news-lead .kicker{display:flex;align-items:baseline;gap:14px;flex-wrap:wrap;margin-bottom:14px;font-family:'IBM Plex Mono';font-size:11px;letter-spacing:.12em;text-transform:uppercase}
.news-lead .kicker .et{color:#fff;background:var(--green);padding:4px 10px;border-radius:3px}
.news-lead .kicker time{color:var(--ink-3);letter-spacing:.08em}
.news-lead h3{font-family:'Playfair Display',Georgia,serif;font-size:2.5rem;font-weight:800;line-height:1.08;letter-spacing:-.01em;margin-bottom:16px}
/* Entradilla: el sumario en negrita bajo el titular, a mayor cuerpo que el
   cuerpo de texto. */
.news-lead .entradilla{font-size:1.2rem;font-weight:600;line-height:1.45;margin-bottom:16px}
/* Capitular: la letra inicial a tres líneas, como en un diario. Va solo en la
   noticia de portada; en los breves quedaría ridícula. */
.news-lead .cuerpo{font-size:1.06rem;color:var(--ink-2);line-height:1.62}
.news-lead .cuerpo::first-letter{font-family:'Playfair Display',Georgia,serif;font-size:3.4rem;font-weight:700;line-height:.82;float:left;padding:4px 10px 0 0;color:var(--ink)}
.news-lead .mas{display:inline-block;margin-top:20px;font-family:'IBM Plex Mono';font-size:12px;letter-spacing:.06em;text-transform:uppercase;color:var(--amber);border-bottom:1px solid var(--hair-2);padding-bottom:3px;transition:color .15s,border-color .15s}
.news-lead .mas:hover{color:var(--green);border-color:var(--green)}
.news-lead .mas:focus-visible{outline:2px solid var(--green);outline-offset:3px}

/* Foto con filete y pie en cursiva, como un pie de prensa. La captura va
   completa (contain habría dejado franjas): estas son 1700×1065, así que
   cover a 16:10 no recorta nada apreciable. */
.news-foto{margin:0}
/* El `height:auto` es imprescindible: la imagen lleva width/height en el HTML
   (para que el navegador reserve el hueco y no salte la página al cargar), y
   sin anularlo el atributo height=1065 gana y la foto sale de 1065px de alto a
   cualquier ancho.
   Sin `aspect-ratio` ni `object-fit`: la imagen se muestra completa, con su
   propia proporción. Es una captura de pantalla, y recortarla —aunque sea
   poco— corta filas de la tabla o la barra de herramientas. */
.news-foto img{width:100%;height:auto;display:block;border:1px solid var(--hair-2);background:#fff}
.news-foto figcaption{font-size:.92rem;font-style:italic;color:var(--ink-3);line-height:1.45;padding-top:10px;border-top:1px solid var(--hair);margin-top:10px}

/* Breves: las noticias 2 y 3, en columnas separadas por filete vertical, sin
   foto y con titular más pequeño. */
.news-breves{display:grid;grid-template-columns:1fr 1fr;gap:30px;margin-top:40px;padding-top:32px;border-top:1px solid var(--hair-2)}
/* Con un solo breve (dos noticias en total) la rejilla de dos columnas lo
   dejaba en la mitad izquierda y media fila vacía a la derecha. Se pasa a una
   columna, y el texto se limita en medida para que no salga una línea de 1200px
   imposible de leer. */
.news-breves.uno{grid-template-columns:1fr}
.news-breves.uno .news-breve p{max-width:75ch}
.news-breve + .news-breve{border-left:1px solid var(--hair);padding-left:30px}
.news-breve .kicker{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;margin-bottom:8px;font-family:'IBM Plex Mono';font-size:10.5px;letter-spacing:.12em;text-transform:uppercase;color:var(--cyan)}
.news-breve .kicker time{color:var(--ink-3)}
.news-breve h3{font-family:'Playfair Display',Georgia,serif;font-size:1.4rem;font-weight:700;line-height:1.18;margin-bottom:8px}
.news-breve p{font-size:1rem;color:var(--ink-2);line-height:1.55}
.news-breve .mas{display:inline-block;margin-top:12px;font-family:'IBM Plex Mono';font-size:11.5px;text-transform:uppercase;letter-spacing:.06em;color:var(--amber);transition:color .15s}
.news-breve .mas:hover{color:var(--green)}

@media(max-width:900px){
  /* La foto pasa arriba: en una columna, el pie de foto entre el texto y el
     enlace cortaba la lectura de la noticia. */
  .news-lead{grid-template-columns:1fr;gap:28px}
  .news-lead .texto{order:2}
  .news-foto{order:1}
  .news-masthead h2{font-size:2.2rem}
  .news-lead h3{font-size:1.9rem}
  /* La línea de edición se apila: en una sola fila, sus tres rótulos partían
     cada uno en dos líneas y quedaban tres columnas desiguales con los puntos
     naranjas descolgados. */
  .news-masthead .linea{flex-direction:column;gap:5px;line-height:1.4}
  .news-masthead .linea i{display:none}
  .news-breves{grid-template-columns:1fr;gap:26px}
  .news-breve + .news-breve{border-left:none;padding-left:0;border-top:1px solid var(--hair);padding-top:26px}
}
@media(max-width:400px){
  /* A 320px «Últimas noticias» a 2,2rem se partía en tres líneas y la
     capitular se comía media columna. */
  .news-masthead h2{font-size:1.75rem}
  .news-lead h3{font-size:1.6rem}
  .news-lead .cuerpo::first-letter{font-size:2.8rem;padding-right:8px}
}

/* ===== featured ===== */
.feat{padding:70px 0}
.feat .wrap{display:grid;grid-template-columns:1fr 1.05fr;gap:56px;align-items:center}
.feat .k{font-family:'IBM Plex Mono';font-size:12px;letter-spacing:.14em;text-transform:uppercase;color:var(--cyan);margin-bottom:14px}
.feat h3{font-size:2.1rem;font-weight:700;letter-spacing:-.02em;margin-bottom:16px;line-height:1.08}
.feat p{color:var(--ink-2);max-width:46ch;margin-bottom:22px}
.feat ul{list-style:none;display:grid;gap:11px;margin-bottom:26px}
.feat li{display:flex;gap:12px;font-size:1.08rem}
.feat li svg{width:18px;height:18px;stroke:var(--green);stroke-width:2;fill:none;flex-shrink:0;margin-top:3px}
.console{background:var(--panel);border:1px solid var(--hair);border-radius:10px;overflow:hidden}
.console-media{background:#fff;padding:32px;display:flex;align-items:center;justify-content:center;min-height:160px}
.console-media-img{max-width:100%;max-height:160px;object-fit:contain}
.console .bar{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid var(--hair);font-family:'IBM Plex Mono';font-size:12px;color:var(--ink-3)}
.console .bar .live{color:var(--green);display:flex;align-items:center;gap:7px}
.console .bar .live i{width:7px;height:7px;border-radius:50%;background:var(--green);box-shadow:0 0 6px var(--green)}
.console .rows{padding:8px 0}
/* gap + text-align: el valor puede ser largo (el nombre de un producto) y sin
   separación se pega al rótulo al partirse en dos líneas en móvil. */
.console .cr{display:flex;justify-content:space-between;gap:14px;padding:11px 16px;font-family:'IBM Plex Mono';font-size:12.5px;border-bottom:1px solid var(--hair)}
.console .cr b{text-align:right}
.console .cr span{flex-shrink:0}
.console .cr:last-child{border-bottom:none}
.console .cr span{color:var(--ink-2)}
.console .cr b{color:var(--ink)}
.console .cr .ok{color:var(--green)}
@media(max-width:820px){.feat .wrap{grid-template-columns:1fr;gap:36px}}

/* ===== page hero con foto (páginas interiores) ===== */
.hero-photo{position:relative;padding:56px 0 48px;border-bottom:1px solid var(--hair);overflow:hidden;background:#1c1a16}
.hero-photo .bg{position:absolute;inset:0;background-size:cover;background-position:center 18%}
.bg-sobre-servitux{background-image:url(../img/empresa/foto-gerentes-servitux.jpg)}
.bg-telefonia{background-image:url(../img/servicios/hero-telefonia.jpg)}
.bg-whatsapp{background-image:url(../img/servicios/whatsapp-hero.jpeg)}
.bg-telefonia-movil{background-image:url(../img/servicios/telefonia-movil-hero.jpg)}
/* La foto es 1536x1024 (3:2), no panorámica como las demás: necesita su propio
   encuadre. El selector va con dos clases para poder ganar a .hero-photo .bg */
.hero-photo .bg-ia{background-image:url(../img/servicios/ia-hero.jpg);background-position:center 30%}
.bg-centralita{background-image:url(../img/servicios/centralita-hero.png)}
.bg-fibra{background-image:url(../img/servicios/telefonia-movil-hero.jpg)}
.bg-desarrollo{background-image:url(../img/servicios/desarrollo-hero.jpg)}
/* la foto es panorámica (1920x550) y el móvil queda centrado en vertical, no en
   la franja superior: necesita anular el 'center 18%' de .hero-photo .bg, así
   que el selector va con la misma especificidad (dos clases) para poder ganar */
.hero-photo .bg-fichaje{background-image:url(../img/servicios/fichaje/fichaje-hero.png);background-position:center center}
/* foto ya recortada a 1920x760: se centra, no hay franja que priorizar */
.hero-photo .bg-st-gestion{background-image:url(../img/servicios/st-gestion/st-gestion-hero.jpg);background-position:center center}
/* La agente está a la derecha y ese lado es casi blanco: se encuadra a la
   izquierda, donde va el titular, para que el texto caiga sobre la zona oscura
   del mosaico de caras y no sobre el fondo claro. */
.hero-photo .bg-click2call{background-image:url(../img/servicios/click2call/click2call-hero.jpg);background-position:left center}
/* Las cinco fotos de la sección de línea IP son panorámicas (1920x550): el
   motivo queda centrado en vertical, no en la franja superior, así que anulan
   el 'center 18%' de .hero-photo .bg (mismo criterio que .bg-fichaje). */
.hero-photo .bg-linea-ip{background-image:url(../img/servicios/linea-ip/hero-linea-ip.jpg);background-position:center center}
.hero-photo .bg-bono{background-image:url(../img/servicios/linea-ip/hero-bono.jpg);background-position:center center}
.hero-photo .bg-sms{background-image:url(../img/servicios/linea-ip/hero-sms.jpg);background-position:center center}
.hero-photo .bg-internacionales{background-image:url(../img/servicios/linea-ip/hero-internacionales.jpg);background-position:center center}
.hero-photo .bg-900{background-image:url(../img/servicios/linea-ip/hero-900.jpg);background-position:center center}
.hero-photo .bg-consultoria-asterisk{background-image:url(../img/servicios/asterisk/hero-consultoria-asterisk.jpg);background-position:center center}
/* Reutiliza la foto de la página de agentes IA, de la que ésta es continuación.
   Se encuadra más abajo que .bg-ia (que va al 30%): el titular de esta página
   ocupa dos líneas y al 30% caía justo sobre el rótulo «VIRTUAL AGENT» de la
   propia imagen, que además quedaba recortado a media altura. Al 62% el texto
   apoya sobre la zona oscura del traje y ese rótulo sale del encuadre. */
.hero-photo .bg-voz-ia{background-image:url(../img/servicios/ia-hero.jpg);background-position:center 62%}
.hero-photo .bg-sistemas{background-image:url(../img/servicios/sistemas/hero-sistemas.jpg);background-position:center center}
.hero-photo .bg-servidores-linux{background-image:url(../img/servicios/sistemas/hero-servidores-linux.jpg);background-position:center center}
/* Las caras quedan en la mitad inferior, así que se encuadra más abajo que el
   18% por defecto para que no las corte el borde del hero. */
.hero-photo .bg-contacto{background-image:url(../img/contacto-hero.jpg);background-position:center 62%}
.hero-photo .bg-seguridad{background-image:url(../img/servicios/seguridad/hero-seguridad.jpg);background-position:center center}
.hero-photo .bg-antivirus{background-image:url(../img/servicios/seguridad/hero-antivirus.jpg);background-position:center center}
/* Foto sin personas: no hay cara que encuadrar, así que va centrada como las
   demás panorámicas del sitio en vez de al 18% por defecto. */
.hero-photo .bg-auditorias{background-image:url(../img/servicios/seguridad/hero-auditorias.jpg);background-position:center center}
.hero-photo .bg-servidores-virtuales{background-image:url(../img/servicios/sistemas/hero-servidores-virtuales.jpg);background-position:center center}
.hero-photo .bg-backup-hibrido{background-image:url(../img/servicios/seguridad/backup/hero-backup-hibrido.jpg);background-position:center center}
.hero-photo .bg-infraestructuras{background-image:url(../img/servicios/sistemas/hero-infraestructuras.jpg);background-position:center center}
.hero-photo .bg-consultoria-tecnologica{background-image:url(../img/servicios/sistemas/hero-consultoria.jpg);background-position:center center}
.hero-photo .bg-st-calzado{background-image:url(../img/servicios/st-calzado/st-calzado-hero.jpg);background-position:center center}
/* El monitor con el esquema de ST-PrestaComm cae justo en el centro de la foto,
   que es donde va el h1: a tamaño 'cover' el titular tapaba el diagrama, que es
   lo único informativo de la imagen. Se amplía al 150% y se ancla a la
   izquierda, así el esquema se desplaza a la derecha —donde el overlay es más
   claro y se lee entero— y el titular cae sobre la zona oscura. Es el mismo
   criterio de .bg-click2call, que aparta a la agente del texto. */
.hero-photo .bg-prestacomm{background-image:url(../img/servicios/prestacomm/prestacomm-hero.jpg);background-size:150% auto;background-position:0% center}
/* Foto ya recortada a 1920x550: el motivo (llave y casas) queda centrado en
   vertical, así que anula el 'center 18%' por defecto como las demás
   panorámicas. La mitad izquierda es la más clara de la foto —el billete y la
   calculadora— y ahí caen el h1 y el lede, así que lleva su propio overlay
   reforzado en el degradado horizontal (ver .bg-laravance::after). */
.hero-photo .bg-laravance{background-image:url(../img/servicios/laravance/hero-laravance.jpg);background-position:center center}
.hero-photo .bg-laravance::after{background:linear-gradient(180deg,rgba(20,18,14,.42) 0%,rgba(20,18,14,.56) 42%,rgba(20,18,14,.85) 100%),linear-gradient(90deg,rgba(20,18,14,.82) 0%,rgba(20,18,14,.5) 55%,rgba(20,18,14,.2) 100%)}
.hero-photo .bg::after{content:"";position:absolute;inset:0;background:linear-gradient(180deg,rgba(20,18,14,.35) 0%,rgba(20,18,14,.5) 42%,rgba(20,18,14,.82) 100%),linear-gradient(90deg,rgba(20,18,14,.72) 0%,rgba(20,18,14,.35) 55%,rgba(20,18,14,.15) 100%)}
.hero-photo .wrap{position:relative;z-index:2}
.hero-photo .crumb{font-family:'IBM Plex Mono';font-size:12px;color:rgba(255,255,255,.6);margin-bottom:18px}
/* Migas clicables (05/08/2026): los niveles con página detrás son <a>; el nivel
   actual y «Servicios» (que no existe) van como texto. Como la regla global es
   `a{color:inherit;text-decoration:none}`, sin esto un enlace sería
   indistinguible del texto que no lleva enlace. Se resalta en blanco y se
   subraya al pasar o al enfocar, no en reposo: en reposo la miga tiene que
   seguir leyéndose como una ruta, no como una fila de enlaces. */
.hero-photo .crumb a{color:rgba(255,255,255,.82);text-decoration:underline;text-decoration-color:rgba(255,255,255,.28);text-underline-offset:3px;transition:color .15s,text-decoration-color .15s}
.hero-photo .crumb a:hover,
.hero-photo .crumb a:focus-visible{color:#fff;text-decoration-color:#fff}
.hero-photo .tag{color:var(--green-dim)}
.hero-photo h1{color:#fff;max-width:22ch;text-shadow:0 2px 18px rgba(0,0,0,.55)}
.hero-photo .lede{color:rgba(255,255,255,.88);margin-top:18px;max-width:52ch;font-size:1.22rem;text-shadow:0 1px 12px rgba(0,0,0,.6)}
@media(max-width:760px){
  .hero-photo{padding:44px 0 36px}
  .hero-photo .bg{background-position:center 12%}
  .hero-photo .bg-ia{background-position:center 30%}
  .hero-photo .bg-fichaje{background-position:center center}
  .hero-photo .bg-st-gestion{background-position:center center}
  .hero-photo .bg-click2call{background-position:left center}
  .hero-photo .bg-linea-ip,
  .hero-photo .bg-bono,
  .hero-photo .bg-sms,
  .hero-photo .bg-internacionales,
  .hero-photo .bg-900,
  .hero-photo .bg-consultoria-asterisk,
  .hero-photo .bg-sistemas,
  .hero-photo .bg-servidores-linux,
  .hero-photo .bg-seguridad,
  .hero-photo .bg-antivirus,
  .hero-photo .bg-st-calzado,
  .hero-photo .bg-laravance,
  .hero-photo .bg-auditorias,
  .hero-photo .bg-backup-hibrido,
  .hero-photo .bg-servidores-virtuales,
  .hero-photo .bg-infraestructuras,
  .hero-photo .bg-consultoria-tecnologica{background-position:center center}
  /* En móvil el hero es alto y estrecho: el 150% del escritorio repetía el
     dibujo en vertical, así que se vuelve a 'cover' centrado. */
  .hero-photo .bg-prestacomm{background-size:cover;background-position:center center}
  .hero-photo .bg-contacto{background-position:center 62%}
  .hero-photo .bg-voz-ia{background-position:center 62%}
  .hero-photo .bg::after{background:linear-gradient(180deg,rgba(20,18,14,.45) 0%,rgba(20,18,14,.62) 45%,rgba(20,18,14,.88) 100%)}
  .hero-photo .lede{max-width:none}
}
@media(max-width:520px){.article-full h2{margin:40px 0 8px;font-size:1.45rem}}

/* ===== hero sin foto (páginas de trámite: declaraciones, textos legales) =====
   Mismo bloque de migas + tag + h1 que .hero-photo, pero sobre el fondo crema:
   una foto de cabecera en un documento con valor legal no aporta nada. */
.hero-plain{padding:44px 0 32px;border-bottom:1px solid var(--hair);background:var(--panel-2)}
.hero-plain .crumb{font-family:'IBM Plex Mono';font-size:12px;color:var(--ink-3);margin-bottom:16px}
/* Mismo criterio que en .hero-photo .crumb a, en versión clara. */
.hero-plain .crumb a{color:var(--ink-2);text-decoration:underline;text-decoration-color:var(--hair-2);text-underline-offset:3px;transition:color .15s,text-decoration-color .15s}
.hero-plain .crumb a:hover,
.hero-plain .crumb a:focus-visible{color:var(--amber);text-decoration-color:var(--amber)}
.hero-plain .tag{font-family:'IBM Plex Mono';font-size:12px;letter-spacing:.1em;text-transform:uppercase;color:var(--green);margin-bottom:10px}
.hero-plain h1{font-size:2.1rem;line-height:1.14;letter-spacing:-.02em;max-width:30ch}
@media(max-width:760px){.hero-plain{padding:34px 0 26px}.hero-plain h1{font-size:1.7rem}}

/* ===== declaración responsable (documento de apartados numerados) ===== */
.declaracion{max-width:82ch}
.declaracion p{color:var(--ink-2);font-size:1.06rem;line-height:1.6;margin-bottom:14px}
/* El rótulo de cada apartado (1.a, 2.b…) es la etiqueta del formulario oficial:
   se resalta para poder localizar un apartado concreto de un vistazo. */
.declaracion .dr-campo{color:var(--ink);font-weight:600;font-size:1rem;margin:26px 0 8px}
.declaracion .dr-campo:first-child{margin-top:0}
.declaracion h2{font-family:'IBM Plex Mono';font-size:13px;letter-spacing:.12em;text-transform:uppercase;color:var(--green);margin:44px 0 18px;padding-top:20px;border-top:1px solid var(--hair)}
/* Subtítulo dentro de un apartado numerado (en el aviso legal, los epígrafes
   del punto 5): es un nivel por debajo de .dr-campo, así que no lleva el filete
   ni la caja alta del h2 de sección, que lo harían parecer un apartado nuevo. */
.declaracion h2.dr-sub{font-family:inherit;font-size:1.06rem;letter-spacing:normal;text-transform:none;color:var(--ink);font-weight:600;margin:30px 0 10px;padding-top:0;border-top:0}
.declaracion ul{list-style:none;display:grid;gap:7px;margin:0 0 14px}
.declaracion li{font-size:1.06rem;color:var(--ink);line-height:1.5;padding-left:16px;position:relative}
.declaracion li::before{content:"";position:absolute;left:0;top:9px;width:5px;height:5px;border-radius:50%;background:var(--green)}
/* Las URLs del apartado 2.b son largas y sin espacios: hay que permitir el
   corte en cualquier punto, o desbordan la pantalla en móviles estrechos. */
.declaracion,.declaracion p,.declaracion li,.declaracion a{overflow-wrap:anywhere}
.declaracion a{color:var(--amber);text-decoration:underline;text-decoration-color:var(--hair-2);text-underline-offset:2px}
.declaracion a:hover{text-decoration-color:var(--amber)}
.dr-nota{margin-top:40px;padding-top:20px;border-top:1px solid var(--hair);font-size:.95rem;color:var(--ink-3);max-width:82ch}
/* Enlace discreto a un documento legal al final de una página de producto:
   tiene que estar accesible, pero sin competir con la llamada a la acción. */
.nota-legal{margin-top:28px;font-family:'IBM Plex Mono';font-size:12px;color:var(--ink-3)}
.nota-legal a{color:var(--ink-3);text-decoration:underline;text-decoration-color:var(--hair-2);text-underline-offset:3px}
.nota-legal a:hover{color:var(--green);text-decoration-color:var(--green)}

/* Fila de logos de certificación ajenos (los centros de datos donde se alojan
   las copias de ST-Backup). Se usa flex con wrap y no una rejilla porque el
   número de logos no es fijo y no debe quedar ninguna celda vacía si se añade
   o se quita uno. Conservan sus colores, como .ic.brand: son marcas de terceros. */
.cert-row{display:flex;flex-wrap:wrap;justify-content:center;gap:14px;margin-top:22px}
.cert{background:#fff;border:1px solid var(--hair);border-radius:8px;padding:10px;display:flex;align-items:center;justify-content:center}
.cert img{width:78px;height:78px;object-fit:contain;display:block}
@media(max-width:560px){.cert-row{gap:10px}.cert img{width:62px;height:62px}}
/* Variante para logotipos de marca (Fortinet, MikroTik, Google Workspace…), que
   no son sellos cuadrados sino rótulos muy alargados —hasta 8:1—. Con el
   78x78 de .cert img el nombre quedaba en una franja ilegible dentro de una caja
   cuadrada, el mismo caso que resolvió .ic.brand.tall. Aquí se fija solo la
   ALTURA y el ancho lo pone la proporción de cada logo, así que conviven un
   rótulo alargado y un icono cuadrado en la misma fila. */
.cert-row.marcas .cert{padding:12px 18px;min-height:64px}
.cert-row.marcas .cert img{width:auto;height:30px;max-width:210px}
/* Logo pensado para fondo oscuro (el de CIMA es blanco): sobre la caja blanca de
   .cert era invisible —un cuadro vacío—. Con .oscuro la caja se pinta en tinta,
   que es como lo presenta el propio fabricante. Comprobado abriendo el PNG: su
   canal alfa cubre el 11% y todo el trazo es blanco. */
.cert-row.marcas .cert.oscuro{background:var(--ink);border-color:var(--ink)}

@media(max-width:560px){
  .cert-row.marcas .cert{padding:10px 14px;min-height:54px}
  .cert-row.marcas .cert img{height:24px;max-width:170px}
}

/* ===== article layout (contenido + sidebar) ===== */
.article-layout{padding:64px 0 80px}
.article-layout .wrap{display:grid;grid-template-columns:1fr 300px;gap:56px;align-items:start}
/* La sidebar de 300px es fija: por debajo de ~900px no cabe junto al texto y la
   rejilla desbordaba la pantalla. Pasa a una columna, con la sidebar debajo. */
@media(max-width:900px){.article-layout .wrap{grid-template-columns:1fr;gap:40px}}
/* Un elemento de rejilla no baja de la anchura mínima de su contenido
   (min-width:auto). Con URLs largas sin espacios —las de ICANN en
   sobre-servitux miden 464px— la columna se ensanchaba hasta esa palabra y
   arrastraba toda la página fuera de la pantalla en móviles estrechos. */
.article-layout .wrap > *{min-width:0}
.article-body{overflow-wrap:break-word}
.article-body p{color:var(--ink-2);margin-bottom:20px;font-size:1.16rem}
.article-body p:last-child{margin-bottom:0}
/* Enlaces dentro del texto del artículo: ámbar y subrayados para que se
   distingan del cuerpo.
   ⚠️ Los tres contenedores de contenido van juntos en la misma regla. Estaba
   solo `.article-body`, que lo usan 2 páginas, mientras que `.article-full` lo
   usan 33 y `.declaracion` las legales: en todas ellas los enlaces de texto
   heredaban el `a{color:inherit;text-decoration:none}` global y **no se
   distinguían del texto** (54 enlaces en 28 páginas, corregido el 05/08/2026).
   Al añadir una página nueva basta con usar uno de estos tres contenedores.
   Se excluyen los elementos que ya son un bloque con su propio aspecto y que no
   deben pintarse como enlace de texto: las tarjetas-enlace (.tel, .svc, .app,
   .spec), los botones (.btn), las capturas del visor (.cap) y los enlaces
   externos de la barra lateral (.link-out). También la nota legal al pie de una
   tabla de precios, que va en gris apagado a propósito y cuya regla —de una sola
   clase— perdería por especificidad contra estos selectores. */
.article-body a:not(.spec):not(.tel):not(.svc):not(.app):not(.btn):not(.cap):not(.link-out),
.article-full a:not(.spec):not(.tel):not(.svc):not(.app):not(.btn):not(.cap):not(.link-out),
.declaracion a:not(.spec):not(.tel):not(.svc):not(.app):not(.btn):not(.cap):not(.link-out){color:var(--amber);text-decoration:underline;text-decoration-color:var(--hair-2);text-underline-offset:2px}
.article-body a:not(.spec):not(.tel):not(.svc):not(.app):not(.btn):not(.cap):not(.link-out):hover,
.article-full a:not(.spec):not(.tel):not(.svc):not(.app):not(.btn):not(.cap):not(.link-out):hover,
.declaracion a:not(.spec):not(.tel):not(.svc):not(.app):not(.btn):not(.cap):not(.link-out):hover{text-decoration-color:var(--amber)}
.article-body em{font-style:italic;color:inherit}
.article-body strong{color:var(--ink);font-weight:600}
.article-body .lead{font-size:1.3rem;color:var(--ink);font-weight:500;line-height:1.5}
.article-body h2{font-size:1.7rem;margin:44px 0 4px;line-height:1.2}
.article-body h2:first-child{margin-top:0}
@media(max-width:520px){.article-body h2{margin:34px 0 4px;font-size:1.45rem}}

/* bloques de especialidades (tarjetas con icono) */
.spec-grid{margin:36px 0 40px;display:grid;grid-template-columns:repeat(3,1fr);gap:1px;background:var(--hair);border:1px solid var(--hair)}
.spec{background:var(--panel);padding:22px 20px;display:flex;flex-direction:column;gap:10px}
.spec .ic{width:34px;height:34px;background:var(--green);border-radius:8px;display:flex;align-items:center;justify-content:center;padding:7px}
.spec .ic img{width:100%;height:100%;object-fit:contain;filter:brightness(0) invert(1)}
.spec .ic.brand{background:#fff;border:1px solid var(--hair);padding:5px}
.spec .ic.brand img{filter:none}
/* Logotipo de marca que es un RÓTULO alargado (Google Workspace, ~8:1) y no una
   marca cuadrada como la de WhatsApp: en la caja de 34x34 el nombre quedaba en
   22px de ancho, ilegible. Con .wide la caja crece a lo ancho y el logo se lee.
   Mismo criterio que .ic.brand.tall en los callout. */
.spec .ic.brand.wide{width:fit-content;max-width:100%;height:38px;padding:6px 10px}
.spec .ic.brand.wide img{width:auto;max-width:100%;height:100%}
/* Solo las .spec que son enlace reaccionan al pasar por encima: las que son
   descriptivas (la mayoría) no deben dar a entender que se puede pinchar. */
a.spec{transition:background .15s}
a.spec:hover{background:var(--panel-2)}
.spec h3{font-size:1.08rem;font-weight:600}
.spec p{font-size:.98rem;color:var(--ink-2);line-height:1.4;margin:0}
.spec a{color:inherit}
/* Variante de 2 columnas: con 4 tarjetas, la rejilla de 3 por defecto deja dos
   celdas grises en la última fila. Como el resto de variantes .cols-*, hay que
   repetirla en cada breakpoint que reduzca columnas o la más específica gana. */
.spec-grid.cols-2{grid-template-columns:repeat(2,1fr)}
@media(max-width:760px){.spec-grid,.spec-grid.cols-2{grid-template-columns:1fr 1fr}}
@media(max-width:520px){.spec-grid,.spec-grid.cols-2{grid-template-columns:1fr}}

/* citas / bloques de marca */
.callout{background:var(--panel);border:1px solid var(--hair);border-left:3px solid var(--green);border-radius:6px;padding:18px 22px;margin:28px 0;display:flex;gap:14px;align-items:flex-start}
.callout svg{width:20px;height:20px;stroke:var(--green);stroke-width:2;fill:none;flex-shrink:0;margin-top:2px}
.callout p{margin:0;font-size:1.06rem;color:var(--ink-2)}
.callout strong{color:var(--ink)}
/* Variante con logo de marca ajena en lugar del icono de trazo: el logo conserva
   sus colores (no se recolorea a blanco) sobre una caja blanca. */
.callout .ic.brand{flex-shrink:0;background:#fff;border:1px solid var(--hair);border-radius:6px;padding:8px 10px;display:flex;align-items:center;height:46px}
.callout .ic.brand img{max-height:100%;width:auto;display:block}
/* Modificador para los logos poco apaisados (2:1 o menos) que además llevan texto
   dentro, como el badge MTCNA: a los 46px de alto de .brand su rótulo queda
   ilegible, y es justo lo que acredita el logo. Se le da más alto, no más ancho,
   porque lo que limita es la altura. */
.callout .ic.brand.tall{height:74px}
@media(max-width:560px){.callout{flex-direction:column;gap:12px}}

/* sidebar */
.side{display:flex;flex-direction:column;gap:1px;background:var(--hair);border:1px solid var(--hair);position:sticky;top:112px}
.side-card{background:var(--panel);padding:20px}
.side-card .k{font-family:'IBM Plex Mono';font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3);margin-bottom:12px}
.side-card ul{list-style:none;display:grid;gap:11px}
.side-card li{display:flex;justify-content:space-between;gap:10px;font-size:.94rem;color:var(--ink-2)}
.side-card li b{color:var(--ink);font-weight:600;font-family:'IBM Plex Mono';font-size:.82rem}
.side-card a.link-out{display:flex;align-items:center;gap:8px;font-size:.94rem;color:var(--ink-2);padding:2px 0}
.side-card a.link-out:hover{color:var(--amber)}
.side-card a.link-out svg{width:14px;height:14px;stroke:currentColor;stroke-width:2;fill:none;flex-shrink:0}
.side-cta{background:var(--green);padding:22px 20px;color:#04120a}
.side-cta h2{font-size:1.1rem;margin-bottom:8px}
.side-cta p{font-size:.94rem;margin-bottom:14px;opacity:.85}
.side-cta .btn{background:#04120a;color:var(--green);font-size:13px;padding:10px 16px;width:100%;justify-content:center}
@media(max-width:900px){.article-layout .wrap{grid-template-columns:1fr}.side{position:static}}

/* ===== article ancho completo (sin sidebar), para páginas de catálogo ===== */
.article-full{padding:64px 0 80px}
.article-full .wrap{max-width:1100px}
.article-full .intro{color:var(--ink-2);font-size:1.22rem;margin-bottom:8px}
.article-full h2{font-size:1.7rem;margin:56px 0 8px;line-height:1.2}
.article-full h2 .k{display:block;font-family:'IBM Plex Mono';font-size:12px;letter-spacing:.1em;text-transform:uppercase;color:var(--green);margin-bottom:8px}
.article-full .sub{color:var(--ink-2);max-width:64ch;margin-bottom:28px}
/* Los párrafos de cuerpo no llevan margen (el ritmo lo marcan .intro, .sub y los
   h2). Cuando van dos o más seguidos sí hace falta separarlos, o se leen como un
   único bloque. Solo aplica a partir del segundo, así que no altera las páginas
   que tienen un párrafo suelto entre bloques. */
.article-full > .wrap > p + p{margin-top:14px}
/* Subapartado dentro de una sección: un h3 suelto en la columna, no el de una
   tarjeta. main.css solo estilaba los h3 de dentro de los bloques (.tel h3,
   .perk h3…), así que al primer h3 de este nivel le salía margen 0 por todos
   lados y quedaba pegado al párrafo anterior y a la rejilla siguiente. Se estila
   acotado con '>' para no alcanzar los h3 de las tarjetas, que van dentro de sus
   propios contenedores. */
.article-full > .wrap > h3{font-size:1.28rem;margin:36px 0 10px;line-height:1.25}
@media(max-width:520px){.article-full > .wrap > h3{margin:28px 0 8px}}

/* desplegable de condiciones / detalles legales */
.legal-details{margin-top:40px;border:1px solid var(--hair);border-radius:8px;background:var(--panel)}
.legal-details summary{cursor:pointer;list-style:none;padding:16px 20px;font-family:'IBM Plex Mono';font-size:12.5px;letter-spacing:.04em;color:var(--ink-2);display:flex;align-items:center;justify-content:space-between;gap:12px}
.legal-details summary::-webkit-details-marker{display:none}
.legal-details summary:hover{color:var(--ink)}
.legal-details summary .chev{width:16px;height:16px;stroke:currentColor;stroke-width:2;fill:none;flex-shrink:0;transition:transform .18s}
.legal-details[open] summary .chev{transform:rotate(180deg)}
.legal-details .legal-body{padding:0 20px 22px;border-top:1px solid var(--hair)}
.legal-details .legal-body p{font-size:.92rem;color:var(--ink-3);line-height:1.6;margin-top:16px}

/* ===== política de cookies =====
   Cada proveedor es un .legal-details; dentro, los rótulos del original (Uso,
   Compartir datos, categoría) son h3 y las cookies van en tabla. */
.ck-fecha{color:var(--ink-3);font-size:.98rem;margin-bottom:26px}
/* Nombres de clave técnica dentro del texto (servitux-cookies, servitux-mapa-ok). */
.declaracion code{font-family:'IBM Plex Mono';font-size:.9em;background:var(--panel-2);border:1px solid var(--hair);border-radius:4px;padding:1px 5px;color:var(--ink)}
/* El nombre del proveedor no se parte: es el rótulo por el que se busca el
   apartado. Las categorías van a su derecha y, si no caben, debajo. */
.legal-details summary{flex-wrap:wrap}
.legal-details summary .ck-nombre{color:var(--ink)}
.legal-details summary .ck-cats{margin-left:auto;font-size:11.5px;color:var(--ink-3);text-transform:none;letter-spacing:.02em}
@media(max-width:620px){
  /* El nombre y el chevron comparten la primera línea; las categorías bajan
     enteras a la segunda (order las manda al final del flex). */
  .legal-details summary .ck-nombre{flex:1}
  .legal-details summary .ck-cats{order:3;margin-left:0;flex-basis:100%;margin-top:4px}
}
.legal-details .legal-body h3{font-family:'IBM Plex Mono';font-size:11.5px;letter-spacing:.1em;text-transform:uppercase;color:var(--green);margin:22px 0 0}
.legal-details .legal-body .ck-ambito{font-family:'IBM Plex Mono';font-size:11.5px;color:var(--ink);margin-top:16px}
/* La tabla se hace scrollable en su propio contenedor: con tres columnas de
   texto no cabe en un móvil estrecho, y encogerla dejaría la función ilegible.
   Mismo criterio que .esquema y el visor de capturas. */
.ck-tabla{width:100%;border-collapse:collapse;margin-top:10px;font-size:.88rem}
/* En pantallas estrechas la tabla no se encoge: se arrastra. Sin el min-width
   la columna «Función» bajaba a cuatro caracteres y partía las palabras por la
   mitad, que es justo lo que la tabla tiene que dejar leer. */
@media(max-width:620px){
  .ck-tabla-scroll{overflow-x:auto}
  .ck-tabla{min-width:420px}
}
.ck-tabla th,.ck-tabla td{text-align:left;padding:8px 12px 8px 0;border-bottom:1px solid var(--hair);vertical-align:top}
.ck-tabla th{font-family:'IBM Plex Mono';font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-3);font-weight:500;white-space:nowrap}
.ck-tabla td{color:var(--ink-2);line-height:1.45}
.ck-tabla td:first-child{font-family:'IBM Plex Mono';font-size:.82rem;color:var(--ink);white-space:nowrap}
.ck-tabla td:nth-child(2){white-space:nowrap}
.ck-tabla tr:last-child td{border-bottom:0}

/* rejilla de servicios (catálogo de telefonía, etc.) */
.tel-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;background:var(--hair);border:1px solid var(--hair)}
.tel{background:var(--panel);padding:26px 22px;display:flex;flex-direction:column;gap:12px;transition:background .15s}
.tel:hover{background:var(--panel-2)}
.tel .ic{width:44px;height:44px;background:var(--green);border-radius:10px;display:flex;align-items:center;justify-content:center;padding:9px}
.tel .ic img{width:100%;height:100%;object-fit:contain;filter:brightness(0) invert(1)}
.tel h3{font-size:1.1rem;font-weight:600}
.tel p{font-size:.98rem;color:var(--ink-2);line-height:1.45;margin:0}
.tel .go{margin-top:auto;font-family:'IBM Plex Mono';font-size:11px;color:var(--ink-3);padding-top:10px}
.tel:hover .go{color:var(--green)}
.tel:hover .go::after{content:" →"}
/* Tarjetas que enlazan a otra página: el elemento clicable es la tarjeta entera
   (`<a class="tel">`), no solo el título, para no obligar a apuntar al texto. El
   `a{color:inherit;text-decoration:none}` global ya evita que hereden aspecto de
   enlace, así que solo hace falta el anillo de foco: al ser el elemento navegable
   principal de estas rejillas, sin él no se ve por dónde va el tabulador. */
a.tel:focus-visible,a.spec:focus-visible,a.svc:focus-visible,a.app:focus-visible{outline:2px solid var(--green);outline-offset:-2px}
/* Lista de funciones dentro de una tarjeta .tel, cuando la tarjeta enumera
   prestaciones en vez de llevar un párrafo descriptivo. */
.tel-list{list-style:none;display:grid;gap:8px;margin:2px 0 0}
.tel-list li{font-size:.98rem;color:var(--ink-2);line-height:1.4;padding-left:15px;position:relative}
.tel-list li::before{content:"";position:absolute;left:0;top:8px;width:5px;height:5px;border-radius:50%;background:var(--green)}
/* Variante de 2 columnas: para 4 tarjetas, que en 3 columnas dejarían un hueco. */
.tel-grid.cols-2{grid-template-columns:repeat(2,1fr)}
/* Última fila incompleta: la última tarjeta se ensancha en vez de dejar una
   celda gris vacía. Mismo recurso que .lic-grid y .app-grid. Hizo falta al
   retirar «Cableado estructurado certificado» de infraestructuras-de-red
   (05/08/2026), que dejó la rejilla en 5 tarjetas sobre 3 columnas. */
/* ⚠️ Solo en la rejilla de 3 columnas: `:not(.cols-2)` es imprescindible. El
   `nth-child(3n+…)` cuenta de tres en tres al margen de las columnas que haya,
   así que sin excluirla una rejilla .cols-2 con 4 tarjetas (2×2 completa)
   ensanchaba la última a `span 3` y rompía la fila. */
.tel-grid:not(.cols-2) > :last-child:nth-child(3n+1){grid-column:span 3}
.tel-grid:not(.cols-2) > :last-child:nth-child(3n+2){grid-column:span 2}
/* El span hay que anularlo en cada tramo que reduzca columnas: un `span 3`
   sobre una rejilla de 1 columna crea columnas implícitas y desborda la página. */
@media(max-width:760px){
  .tel-grid,.tel-grid.cols-2{grid-template-columns:1fr 1fr}
  .tel-grid:not(.cols-2) > :last-child:nth-child(3n+1),
  .tel-grid:not(.cols-2) > :last-child:nth-child(3n+2){grid-column:auto}
  .tel-grid:not(.cols-2) > :last-child:nth-child(odd){grid-column:span 2}
}
@media(max-width:520px){
  .tel-grid,.tel-grid.cols-2{grid-template-columns:1fr}
  .tel-grid:not(.cols-2) > :last-child:nth-child(3n+1),
  .tel-grid:not(.cols-2) > :last-child:nth-child(3n+2),
  .tel-grid:not(.cols-2) > :last-child:nth-child(odd){grid-column:auto}
  .tel{padding:20px 18px}
}

/* rejilla de ventajas numeradas (texto descriptivo, sin icono) */
.perk-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:1px;background:var(--hair);border:1px solid var(--hair)}
.perk{background:var(--panel);padding:24px 22px;display:flex;flex-direction:column;gap:9px;transition:background .15s}
.perk:hover{background:var(--panel-2)}
.perk .n{font-family:'IBM Plex Mono';font-size:11px;letter-spacing:.1em;color:var(--green);font-weight:500}
.perk h3{font-size:1.08rem;font-weight:600;line-height:1.3}
.perk p{font-size:.97rem;color:var(--ink-2);line-height:1.5;margin:0}
/* Variante de 3 columnas: para un número de tarjetas que en 4 columnas dejaría
   la última fila incompleta (18 → 6 filas de 3, sin huecos). */
.perk-grid.cols-3{grid-template-columns:repeat(3,1fr)}
@media(max-width:1080px){.perk-grid,.perk-grid.cols-3{grid-template-columns:repeat(2,1fr)}}
@media(max-width:560px){.perk-grid,.perk-grid.cols-3{grid-template-columns:1fr}.perk{padding:20px 18px}}

/* casos de uso (lista con numeración destacada) */
.cases{display:grid;gap:1px;background:var(--hair);border:1px solid var(--hair)}
.case{background:var(--panel);padding:22px 24px;display:grid;grid-template-columns:auto 1fr;gap:20px;align-items:start;transition:background .15s}
.case:hover{background:var(--panel-2)}
.case .num{width:34px;height:34px;border-radius:50%;background:var(--green);color:#04120a;font-family:'IBM Plex Mono';font-size:13px;font-weight:600;display:flex;align-items:center;justify-content:center;flex-shrink:0}
.case h3{font-size:1.1rem;font-weight:600;margin-bottom:5px}
.case p{font-size:1rem;color:var(--ink-2);line-height:1.5;margin:0}
@media(max-width:560px){.case{padding:18px 18px;gap:14px}.case .num{width:28px;height:28px;font-size:12px}}

/* bloque de dos columnas: texto + imagen ilustrativa */
.split{display:grid;grid-template-columns:1fr 340px;gap:48px;align-items:center;margin:40px 0}
.split-text p{color:var(--ink-2);margin-bottom:16px;font-size:1.16rem}
.split-text p:last-child{margin-bottom:0}
.split-text strong{color:var(--ink);font-weight:600}
.split-media{background:var(--panel);border:1px solid var(--hair);border-radius:10px;padding:28px;display:flex;align-items:center;justify-content:center}
.split-media img{max-width:100%;height:auto;display:block}
@media(max-width:860px){.split{grid-template-columns:1fr;gap:28px}.split-media{order:-1}}

/* Esquema técnico a ancho completo (diagrama SVG propio, no una foto). Se usa en
   infraestructuras-de-red para resumir de un vistazo lo que las rejillas explican
   después. El SVG es vectorial, así que escala sin perder nitidez y pesa 8 KB. */
.esquema{margin:32px 0 8px;background:var(--panel);border:1px solid var(--hair);border-radius:10px;padding:24px}
.esquema img{width:100%;height:auto;display:block}
.esquema figcaption{margin-top:16px;color:var(--ink-3);font-family:'IBM Plex Mono',monospace;font-size:12px;line-height:1.5;text-align:center}
/* Por debajo de 760px el diagrama encogido al ancho de la pantalla deja los
   rótulos ilegibles (a 336px de ancho, el texto de 10px del SVG baja a ~3,4px).
   Se le da un ancho mínimo y se desplaza en horizontal, el mismo criterio que el
   visor de capturas en móvil: mejor arrastrar que no poder leer nada. */
@media(max-width:760px){
  .esquema{padding:16px 0 18px;overflow-x:auto;-webkit-overflow-scrolling:touch}
  .esquema img{min-width:720px;padding:0 16px}
  .esquema figcaption{padding:0 16px}
}

/* tarjetas de aplicación con imagen de cabecera */
.app-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:1px;background:var(--hair);border:1px solid var(--hair)}
/* Variante de 3 columnas: con 3 aplicaciones, la rejilla de 4 dejaba una celda
   gris vacía al final de la fila. Como el resto de variantes de rejilla, hay que
   repetirla en los breakpoints que reducen columnas o la regla base vuelve a ganar. */
.app-grid.cols-3{grid-template-columns:repeat(3,1fr)}
/* Variante de 5 columnas: con 5 aplicaciones destacadas ni la rejilla base de 4
   (deja una tarjeta sola en la segunda fila) ni .cols-3 (deja dos) llenan filas
   completas. Con 5 columnas la fila es exacta. En los breakpoints de abajo cae a
   2 y a 1 columna junto a las demás variantes, así que no necesita reglas propias
   de ensanchado: 5 en 2 columnas deja la última sola y para eso está la regla
   general de :last-child de más abajo. */
.app-grid.cols-5{grid-template-columns:repeat(5,1fr)}
.app-grid.cols-5 .body{padding:16px 14px 18px}
.app-grid.cols-5 .body h3{font-size:1rem}
.app{background:var(--panel);display:flex;flex-direction:column;transition:background .15s}
.app:hover{background:var(--panel-2)}
.app .shot{aspect-ratio:4/3;overflow:hidden;background:#fff;border-bottom:1px solid var(--hair)}
.app .shot img{width:100%;height:100%;object-fit:cover;display:block;transition:transform .3s}
.app:hover .shot img{transform:scale(1.04)}
.app .body{padding:20px 20px 22px;display:flex;flex-direction:column;flex:1;gap:7px}
.app h3{font-size:1.1rem;font-weight:600}
.app p{font-size:.98rem;color:var(--ink-2);line-height:1.45;margin:0}
.app .go{margin-top:auto;font-family:'IBM Plex Mono';font-size:11px;color:var(--ink-3);padding-top:12px}
.app:hover .go{color:var(--green)}
.app:hover .go::after{content:" →"}
@media(max-width:1080px){.app-grid,.app-grid.cols-3,.app-grid.cols-5{grid-template-columns:1fr 1fr}
  /* Con 3 tarjetas en 2 columnas la última fila queda a medias, así que la
     tercera ocupa el ancho completo en vez de dejar una celda gris al lado.
     Y pasa a dos columnas internas —captura a la izquierda, texto al lado—:
     manteniendo la imagen arriba, el 4:3 sobre el doble de ancho la estiraba
     hasta 770px de alto, una captura gigante junto a dos pequeñas. */
  .app-grid.cols-3>.app:last-child,
  .app-grid.cols-5>.app:last-child{grid-column:span 2;display:grid;grid-template-columns:1fr 1fr;align-items:center}
  .app-grid.cols-3>.app:last-child .shot,
  .app-grid.cols-5>.app:last-child .shot{border-bottom:none;border-right:1px solid var(--hair)}}
/* A 1 columna hay que anular el span: un "span 2" en una rejilla de una sola
   columna crea una columna implícita y saca la página de la pantalla. */
@media(max-width:560px){.app-grid,.app-grid.cols-3,.app-grid.cols-5{grid-template-columns:1fr}
  .app-grid.cols-3>.app:last-child,
  .app-grid.cols-5>.app:last-child{grid-column:auto;display:flex;grid-template-columns:none;align-items:stretch}
  .app-grid.cols-3>.app:last-child .shot,
  .app-grid.cols-5>.app:last-child .shot{border-bottom:1px solid var(--hair);border-right:none}}

/* ===== galería de capturas de pantalla =====
   Para las capturas reales de una aplicación (16:9). A diferencia de .app-grid,
   la tarjeta no es un enlace y la imagen se muestra completa (object-fit
   contain sobre fondo blanco): en una captura, recortar los bordes se come la
   barra de menú o las columnas de la tabla y deja de leerse qué hace. */
.shot-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;background:var(--hair);border:1px solid var(--hair);margin:36px 0 0}
/* Con un número de capturas que no llena la última fila (7 en 3 columnas), la
   última ocupa el hueco restante en vez de dejar celdas vacías. */
/* Variante de 2 columnas para galerías de 2 capturas. Sin ella, la segunda cae en
   :nth-child(3n+2), se ensancha y pasa a dos columnas internas —título al lado de
   la imagen— mientras la primera lo lleva debajo: las dos quedan distintas. Se ve
   en la captura, no midiendo. */
.shot-grid.cols-2{grid-template-columns:repeat(2,1fr)}
.shot-grid.cols-2 > .shot-card:last-child:nth-child(3n+2){grid-column:auto;display:block}
@media(max-width:620px){.shot-grid.cols-2{grid-template-columns:1fr}}
.shot-grid > .shot-card:last-child:nth-child(3n+1){grid-column:span 3}
.shot-grid > .shot-card:last-child:nth-child(3n+2){grid-column:span 2}
/* La tarjeta ensanchada pasa a dos columnas: la captura a la izquierda con su
   alto normal y el texto al lado. Así una captura vertical (la de la app móvil)
   no queda flotando en medio de una banda blanca de 1200px de ancho.
   Va dentro de un min-width para que en una sola columna no se aplique nunca:
   la tarjeta vuelve a ser la de siempre (imagen arriba, texto debajo). */
@media(min-width:621px){
  .shot-grid > .shot-card:last-child:nth-child(3n+1),
  .shot-grid > .shot-card:last-child:nth-child(3n+2),
  .shot-grid > .shot-card:last-child:nth-child(2n+1){display:grid;grid-template-columns:1fr 1fr;align-items:center}
  .shot-grid > .shot-card:last-child:nth-child(3n+1) .cap,
  .shot-grid > .shot-card:last-child:nth-child(3n+2) .cap,
  .shot-grid > .shot-card:last-child:nth-child(2n+1) .cap{border-bottom:none;border-right:1px solid var(--hair);aspect-ratio:16/10;height:auto}
}
.shot-card{background:var(--panel);display:flex;flex-direction:column}
.shot-card .cap{aspect-ratio:16/10;background:#fff;border-bottom:1px solid var(--hair);overflow:hidden;display:flex;align-items:center;justify-content:center}
.shot-card .cap img{width:100%;height:100%;object-fit:contain;display:block}
.shot-card .body{padding:16px 18px 18px;display:flex;flex-direction:column;gap:6px}
.shot-card h3{font-size:1.04rem;font-weight:600;line-height:1.3}
.shot-card p{font-size:.96rem;color:var(--ink-2);line-height:1.45;margin:0}
/* Al bajar de columnas hay que anular el 'span 3'/'span 2' de la última
   tarjeta: un span mayor que el número de columnas crea columnas implícitas y
   la rejilla se sale de la pantalla. Se recalcula para cada breakpoint. */
@media(max-width:1080px){
  .shot-grid{grid-template-columns:1fr 1fr}
  .shot-grid > .shot-card:last-child:nth-child(3n+1),
  .shot-grid > .shot-card:last-child:nth-child(3n+2){grid-column:auto}
  /* con 2 columnas, la última ocupa el hueco solo si queda impar */
  .shot-grid > .shot-card:last-child:nth-child(2n+1){grid-column:span 2}
}
@media(max-width:620px){
  .shot-grid{grid-template-columns:1fr}
  .shot-grid > .shot-card:last-child:nth-child(3n+1),
  .shot-grid > .shot-card:last-child:nth-child(3n+2),
  .shot-grid > .shot-card:last-child:nth-child(2n+1){grid-column:auto}
}

/* La captura es un enlace al fichero: se marca como pulsable y se avisa con una
   lupa al pasar por encima. Sin JS el enlace abre la imagen; con JS, el visor. */
.shot-card a.cap{cursor:zoom-in;position:relative}
.shot-card a.cap::after{content:"";position:absolute;right:10px;bottom:10px;width:30px;height:30px;border-radius:50%;background:rgba(20,18,14,.62) center/15px 15px no-repeat url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2.2' stroke-linecap='round'%3E%3Ccircle cx='10.5' cy='10.5' r='6.5'/%3E%3Cpath d='M15.5 15.5 21 21M10.5 7.5v6M7.5 10.5h6'/%3E%3C/svg%3E");opacity:0;transition:opacity .18s}
.shot-card a.cap:hover::after,.shot-card a.cap:focus-visible::after{opacity:1}
.shot-card a.cap:focus-visible{outline:2px solid var(--green);outline-offset:-2px}

/* ===== carrusel de capturas ===== */
/* Para galerías largas (24 capturas en ST-Gestión Calzado): una rejilla de 24
   miniaturas deja un bloque larguísimo, así que las capturas van en una pista
   deslizable de 3 en 3. Las tarjetas siguen siendo .shot-card y la pista lleva
   además .shot-grid, así que el visor (lightbox.js) las recoge sin cambios.
   El desplazamiento es scroll nativo con scroll-snap: funciona sin JavaScript
   —se arrastra— y los botones solo lo hacen más cómodo. */
.carrusel{position:relative;margin:36px 0 0}
.carrusel .car-pista{display:grid;grid-auto-flow:column;grid-auto-columns:calc((100% - 2px)/3);grid-template-columns:none;overflow-x:auto;scroll-snap-type:x mandatory;scroll-behavior:smooth;overscroll-behavior-x:contain}
.carrusel .car-pista > .shot-card{scroll-snap-align:start;min-width:0}
/* La pista es un contenedor de scroll enfocable con el teclado: sin anillo no
   se ve dónde está el tabulador. */
.carrusel .car-pista:focus-visible{outline:2px solid var(--green);outline-offset:2px}
/* Barra de desplazamiento discreta pero visible: es la pista la que indica que
   hay más capturas a la derecha. */
.carrusel .car-pista{scrollbar-width:thin;scrollbar-color:var(--green) var(--hair)}
.carrusel .car-pista::-webkit-scrollbar{height:8px}
.carrusel .car-pista::-webkit-scrollbar-track{background:var(--hair)}
.carrusel .car-pista::-webkit-scrollbar-thumb{background:var(--green);border-radius:4px}
/* Las variantes de ensanchado de .shot-grid no valen aquí: en una pista
   horizontal, un 'span' rompe el ancho de las columnas automáticas, y las dos
   columnas internas que la rejilla da a la última tarjeta dejaban su captura sin
   altura calculable (colapsaba a 1px, medido con 19 capturas: la última cae en
   :nth-child(3n+1)). La anulación va dentro del mismo @media que la origina,
   porque si no, gana la regla de .shot-grid por orden en el fichero. */
@media(min-width:621px){
  .carrusel .car-pista > .shot-card:last-child:nth-child(3n+1),
  .carrusel .car-pista > .shot-card:last-child:nth-child(3n+2),
  .carrusel .car-pista > .shot-card:last-child:nth-child(2n+1){display:flex;flex-direction:column;grid-template-columns:none;align-items:stretch;grid-column:auto}
  .carrusel .car-pista > .shot-card:last-child:nth-child(3n+1) .cap,
  .carrusel .car-pista > .shot-card:last-child:nth-child(3n+2) .cap,
  .carrusel .car-pista > .shot-card:last-child:nth-child(2n+1) .cap{border-bottom:1px solid var(--hair);border-right:none;aspect-ratio:16/10;height:auto}
}
.carrusel .car-pista > .shot-card:last-child:nth-child(3n+1),
.carrusel .car-pista > .shot-card:last-child:nth-child(3n+2),
.carrusel .car-pista > .shot-card:last-child:nth-child(2n+1){grid-column:auto;display:flex}
/* Botones fuera de la pista, centrados en vertical sobre el borde. */
.car-nav{position:absolute;top:calc(50% - 34px);transform:translateY(-50%);z-index:2;width:44px;height:44px;border-radius:50%;border:1px solid var(--hair);background:var(--panel);box-shadow:0 2px 10px rgba(20,18,14,.14);cursor:pointer;display:flex;align-items:center;justify-content:center;transition:background .15s,border-color .15s}
.car-nav:hover{background:var(--green);border-color:var(--green)}
.car-nav svg{width:20px;height:20px;fill:none;stroke:var(--ink);stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.car-nav:hover svg{stroke:#fff}
.car-nav[disabled]{opacity:.32;cursor:default}
.car-nav[disabled]:hover{background:var(--panel);border-color:var(--hair)}
.car-nav[disabled]:hover svg{stroke:var(--ink)}
.car-prev{left:-22px}
.car-sig{right:-22px}
@media(max-width:1080px){
  .carrusel .car-pista{grid-auto-columns:calc((100% - 1px)/2)}
  /* Con la pista a todo el ancho de la columna, los botones ya no caben fuera:
     se meten dentro, sobre la propia captura. */
  .car-prev{left:8px}
  .car-sig{right:8px}
}
@media(max-width:620px){
  .carrusel .car-pista{grid-auto-columns:100%}
}

/* ===== visor de capturas a tamaño grande ===== */
/* Fondo casi opaco: con una capa translúcida, el menú y las tarjetas de detrás
   se transparentaban sobre la captura y competían con ella. */
.lightbox{position:fixed;inset:0;z-index:100;background:rgba(11,10,8,.975);display:flex;align-items:center;justify-content:center;padding:56px 72px}
.lightbox[hidden]{display:none}
body.lb-abierto{overflow:hidden}
.lb-figura{margin:0;display:flex;flex-direction:column;gap:14px;max-width:100%;max-height:100%}
.lb-figura img{max-width:100%;max-height:calc(100vh - 130px);object-fit:contain;display:block;margin:auto;background:#fff;border-radius:6px}
.lb-figura figcaption{display:flex;justify-content:space-between;align-items:baseline;gap:20px;color:rgba(255,255,255,.9);font-size:1rem}
.lb-contador{font-family:'IBM Plex Mono';font-size:12px;color:rgba(255,255,255,.55);flex-shrink:0}
.lightbox button{position:absolute;background:rgba(255,255,255,.1);border:1px solid rgba(255,255,255,.22);border-radius:50%;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:background .15s,border-color .15s}
.lightbox button:hover{background:var(--green);border-color:var(--green)}
.lightbox button svg{stroke:#fff;stroke-width:2;fill:none;stroke-linecap:round;stroke-linejoin:round}
.lightbox button:hover svg{stroke:#04120a}
.lb-cerrar{top:16px;right:16px;width:42px;height:42px}
.lb-cerrar svg{width:20px;height:20px}
.lb-nav{top:50%;transform:translateY(-50%);width:46px;height:46px}
.lb-nav svg{width:22px;height:22px}
.lb-prev{left:14px}
.lb-sig{right:14px}
@media(max-width:760px){
  .lightbox{padding:52px 0 76px}
  /* En una pantalla estrecha, ajustar una captura apaisada al ancho la deja
     igual de pequeña que la miniatura y no se lee nada. Se deja crecer en alto
     y el contenedor se desplaza en horizontal para recorrer el detalle. */
  .lightbox{overflow:auto;-webkit-overflow-scrolling:touch;display:block}
  .lb-figura{min-height:100%;justify-content:center;padding:0 12px;box-sizing:border-box}
  /* 900px de ancho mínimo: es el punto en el que el texto de las capturas de la
     plataforma (cabeceras de tabla, campos de formulario) se lee en un móvil.
     La imagen se recorre arrastrando en horizontal. */
  .lb-figura img{max-width:none;max-height:none;width:900px;height:auto;flex:none}
  .lb-figura figcaption{position:fixed;left:0;right:0;bottom:70px;padding:0 14px;flex-direction:column;gap:2px;align-items:flex-start;text-shadow:0 1px 8px rgba(0,0,0,.9);font-size:.94rem}
  /* En móvil las flechas irían encima de la imagen: se bajan a una barra. */
  .lb-nav{position:fixed;top:auto;bottom:14px;transform:none}
  .lb-prev{left:calc(50% - 56px)}
  .lb-sig{right:calc(50% - 56px)}
  .lb-cerrar{position:fixed}
}

/* rejilla de dos acordeones de características, en paralelo */
.feat-accordions{display:grid;grid-template-columns:1fr 1fr;gap:20px;margin-top:28px}
@media(max-width:860px){.feat-accordions{grid-template-columns:1fr}}
.legal-details ul{list-style:none;display:grid;gap:9px;margin-top:16px}
.legal-details li{font-size:.96rem;color:var(--ink-2);line-height:1.45;padding-left:16px;position:relative}
.legal-details li::before{content:"";position:absolute;left:0;top:7px;width:5px;height:5px;border-radius:50%;background:var(--green)}
.legal-details .legal-body p a{color:var(--amber);text-decoration:underline;text-decoration-color:var(--hair-2);text-underline-offset:2px}
.legal-details .legal-body p a:hover{text-decoration-color:var(--amber)}

/* tarifas / planes con precio */
.pricing-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:1px;background:var(--hair);border:1px solid var(--hair)}
.plan{background:var(--panel);padding:28px 24px;display:flex;flex-direction:column}
.plan .name{font-family:'IBM Plex Mono';font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:var(--ink-3);margin-bottom:14px}
.plan .price{font-size:2rem;font-weight:700;color:var(--ink);margin-bottom:2px}
.plan .price small{font-size:.95rem;font-weight:500;color:var(--ink-2)}
.plan ul{list-style:none;display:grid;gap:10px;margin:22px 0 24px;flex:1}
.plan li{font-size:.98rem;color:var(--ink-2);padding-left:18px;position:relative;line-height:1.4}
.plan li::before{content:"";position:absolute;left:0;top:7px;width:7px;height:7px;border-radius:50%;background:var(--green)}
.plan .btn{width:100%;justify-content:center;background:var(--green);color:#04120a;font-size:13px;padding:11px 0}
.plan .btn:hover{background:var(--amber);color:#fff}
/* Variante de 1 columna: para una tarifa única. Sin ella, usar .cols-2 con un
   solo .plan deja media rejilla vacía (una celda gris al lado de la tarjeta). */
.pricing-grid.cols-1{grid-template-columns:1fr;max-width:420px;margin-left:auto;margin-right:auto}
.pricing-grid.cols-2{grid-template-columns:repeat(2,1fr);max-width:760px;margin-left:auto;margin-right:auto}
.pricing-grid.cols-3{grid-template-columns:repeat(3,1fr);max-width:1000px;margin-left:auto;margin-right:auto}
@media(max-width:900px){
  .pricing-grid{grid-template-columns:1fr 1fr}
  .pricing-grid.cols-3{grid-template-columns:1fr 1fr;max-width:680px}
}
@media(max-width:520px){
  .pricing-grid,.pricing-grid.cols-1,.pricing-grid.cols-2,.pricing-grid.cols-3{grid-template-columns:1fr;max-width:420px;margin-left:auto;margin-right:auto}
  .plan{padding:22px 20px}
  .plan .price{font-size:1.7rem}
}

/* callout de puntos / programa fidelización */
.points{margin-top:56px;background:var(--panel);border:1px solid var(--hair);border-radius:10px;padding:32px 34px;display:grid;grid-template-columns:auto 1fr auto;gap:26px;align-items:center}
.points .badge{width:52px;height:52px;border-radius:50%;background:var(--green);display:flex;align-items:center;justify-content:center;flex-shrink:0}
.points .badge svg{width:26px;height:26px;stroke:#04120a;stroke-width:2;fill:none}
.points h3{font-size:1.2rem;margin-bottom:6px}
.points p{color:var(--ink-2);font-size:1.04rem;max-width:60ch}
@media(max-width:760px){.points{grid-template-columns:1fr;text-align:center;padding:28px 24px}.points .badge{margin:0 auto}.points p{max-width:none}}

/* footer */
footer{border-top:1px solid var(--hair);padding:32px 0;font-family:'IBM Plex Mono';font-size:12px;color:var(--ink-3)}
footer .wrap{display:flex;justify-content:space-between;flex-wrap:wrap;gap:14px;align-items:center}
footer a:hover{color:var(--green)}
footer .fl{display:flex;gap:18px;flex-wrap:wrap;align-items:center}
footer .social{display:flex;gap:6px}
footer .social a{display:inline-flex;width:26px;height:26px;align-items:center;justify-content:center;border:1px solid var(--hair-2)}
footer .social a:hover{border-color:var(--green);color:var(--green)}
footer .social svg{width:12px;height:12px;fill:currentColor}

/* ===== página de contacto ===== */
/* Dato destacado dentro de una tarjeta .tel (teléfono, correo, WhatsApp). */
.tel .dato{font-family:'IBM Plex Mono';font-size:1.02rem;color:var(--green);margin:0}
/* El icono de marca ajena (WhatsApp, AnyDesk) conserva sus colores en vez de
   recolorearse a blanco, mismo criterio que .spec .ic.brand. */
.tel .ic.brand{background:#fff;border:1px solid var(--hair);padding:7px}
.tel .ic.brand img{filter:none}

/* Aviso de resultado del envío (éxito o error). */
.aviso{display:flex;gap:12px;align-items:flex-start;padding:16px 20px;border-radius:6px;margin:28px 0;border:1px solid var(--hair);border-left:3px solid var(--green);background:var(--panel)}
.aviso svg{width:20px;height:20px;flex-shrink:0;margin-top:2px;stroke:var(--green);stroke-width:2;fill:none;stroke-linecap:round}
.aviso p{margin:0;color:var(--ink-2);font-size:1.06rem}
.aviso.error{border-left-color:var(--amber);background:#fdf3ee}
.aviso.error svg{stroke:var(--amber)}

/* Formulario. Dos columnas en escritorio; los campos largos ocupan la fila. */
.form-contacto{display:grid;grid-template-columns:1fr 1fr;gap:18px 20px;margin:8px 0 8px}
.form-contacto .campo-ancho{grid-column:1 / -1}
.form-contacto .campo{display:flex;flex-direction:column;gap:7px;min-width:0}
.form-contacto label{font-size:.96rem;font-weight:600;color:var(--ink)}
.form-contacto abbr{color:var(--amber);text-decoration:none;border:0}
.form-contacto input[type=text],.form-contacto input[type=email],.form-contacto textarea{
  font:inherit;font-size:1.02rem;color:var(--ink);background:var(--panel);
  border:1px solid var(--hair-2);border-radius:6px;padding:12px 14px;width:100%;
  transition:border-color .15s,box-shadow .15s}
.form-contacto textarea{resize:vertical;min-height:150px;line-height:1.5}
.form-contacto input:focus,.form-contacto textarea:focus{
  outline:none;border-color:var(--green);box-shadow:0 0 0 3px rgba(232,147,15,.16)}
/* Campo inválido, solo una vez que el visitante ha intentado enviar: marcar en
   rojo mientras aún está escribiendo sería avisar de un error que no ha
   cometido todavía. */
.form-contacto input:user-invalid,.form-contacto textarea:user-invalid{border-color:var(--amber)}
.form-contacto .btn{background:var(--green);color:#04120a;border:0;cursor:pointer;font-family:inherit}
.form-contacto .btn:hover{background:var(--amber);color:#fff}

/* Trampa anti-spam: fuera de la pantalla, no `display:none` — algunos robots
   ignoran los campos ocultos con display/visibility, y así el campo sigue
   siendo un campo normal para ellos. aria-hidden lo retira de los lectores. */
.form-contacto .trampa{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}

/* Bloque de información básica de protección de datos (RGPD). */
.rgpd{background:var(--panel-2);border:1px solid var(--hair);border-radius:8px;padding:20px 22px}
.rgpd h3{font-size:1.02rem;margin-bottom:12px}
.rgpd dl{display:grid;grid-template-columns:auto 1fr;gap:6px 14px;margin:0}
.rgpd dt{font-weight:600;color:var(--ink);font-size:.94rem;white-space:nowrap}
.rgpd dd{margin:0;color:var(--ink-2);font-size:.94rem;line-height:1.45}
.rgpd p{margin:12px 0 0;color:var(--ink-2);font-size:.94rem}
.rgpd a{color:var(--amber);text-decoration:underline;text-decoration-color:var(--hair-2);text-underline-offset:2px}

/* Casillas de consentimiento. */
.consentimientos{display:grid;gap:10px}
.consentimientos .check{display:flex;gap:10px;align-items:flex-start;font-weight:400;cursor:pointer}
.consentimientos input{margin-top:3px;width:17px;height:17px;flex-shrink:0;accent-color:var(--green)}
.consentimientos span{font-size:.98rem;color:var(--ink-2);line-height:1.45}
.consentimientos a{color:var(--amber);text-decoration:underline;text-decoration-color:var(--hair-2);text-underline-offset:2px}
.recaptcha-nota{margin:12px 0 0;font-size:.86rem;color:var(--ink-3);line-height:1.45}
.recaptcha-nota a{color:var(--ink-3);text-decoration:underline;text-decoration-color:var(--hair-2)}

/* Mapa. El alto se fija con aspect-ratio para que no dé saltos al cargar. */
.mapa{border:1px solid var(--hair);border-radius:8px;overflow:hidden;background:var(--panel-2);aspect-ratio:16/7}
.mapa iframe{width:100%;height:100%;border:0;display:block}
/* Aviso previo: el mapa no se carga hasta que el visitante acepta, porque
   Google instala cookies de terceros. Ocupa el mismo hueco que el mapa, así
   que al aceptar no se mueve nada de la página. */
.mapa-consent{height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;text-align:center;padding:28px 24px}
.mapa-consent svg{width:30px;height:30px;stroke:var(--green);stroke-width:1.6;fill:none;margin-bottom:2px}
.mapa-consent p{margin:0;color:var(--ink-2);font-size:1.02rem;max-width:52ch}
.mapa-consent .mapa-consent-txt{font-size:.94rem;color:var(--ink-3)}
.mapa-consent a{color:var(--amber);text-decoration:underline;text-decoration-color:var(--hair-2);text-underline-offset:2px}
.mapa-consent .btn{margin-top:8px;cursor:pointer;font-family:inherit}
.mapa-pie{margin:16px 0 0;text-align:center}
.btn-linea{border:1px solid var(--green);color:var(--green);background:transparent}
.btn-linea:hover{background:var(--green);color:#04120a}

@media(max-width:760px){
  .form-contacto{grid-template-columns:1fr}
  .rgpd dl{grid-template-columns:1fr;gap:2px}
  .rgpd dt{margin-top:8px}
  .mapa{aspect-ratio:4/3}
}

/* ===== catálogo de licencias (antivirus) ===== */
/* Tarjetas de licencia dentro de un desplegable.
   Ninguno de los tres grupos (7, 10 y 2 licencias) llena la última fila de 3,
   así que la última tarjeta se ensancha hasta el final en lugar de dejar
   celdas grises. `auto-fit` no sirve aquí: solo colapsa pistas cuando sobra
   ancho, y con las columnas ya en su mínimo el hueco se queda igual. */
.lic-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;background:var(--hair);border:1px solid var(--hair);margin-top:18px}
.lic-grid > :last-child:nth-child(3n+1){grid-column:span 3}
.lic-grid > :last-child:nth-child(3n+2){grid-column:span 2}
.lic{background:var(--panel);padding:18px 18px 20px;display:flex;flex-direction:column;gap:8px;min-width:0}
.lic h3{font-size:1rem;font-weight:600;line-height:1.3}
.lic p{font-size:.94rem;color:var(--ink-2);line-height:1.45;margin:0}
.lic .btn{margin-top:auto;align-self:flex-start;font-size:12.5px;padding:8px 16px}
/* El span hay que anularlo en cada breakpoint que reduzca columnas: un
   `span 3` en una rejilla de 1 columna crea columnas implícitas y saca la
   página de la pantalla. Se recalcula para 2 columnas y se anula en 1. */
@media(max-width:900px){
  .lic-grid{grid-template-columns:repeat(2,1fr)}
  .lic-grid > :last-child:nth-child(3n+1),
  .lic-grid > :last-child:nth-child(3n+2){grid-column:auto}
  .lic-grid > :last-child:nth-child(odd){grid-column:span 2}
}
@media(max-width:560px){
  .lic-grid{grid-template-columns:1fr}
  .lic-grid > :last-child:nth-child(3n+1),
  .lic-grid > :last-child:nth-child(3n+2),
  .lic-grid > :last-child:nth-child(odd){grid-column:auto}
}

/* ===== menú de móvil ===== */
/* Botón de las tres rayas. Solo existe por debajo de 900px, que es donde el
   menú de escritorio se oculta. 44px de lado: es la medida mínima recomendada
   para un objetivo táctil. */
.nav-btn{display:none;width:44px;height:44px;flex-shrink:0;align-items:center;justify-content:center;
  flex-direction:column;gap:5px;background:none;border:0;cursor:pointer;padding:0;border-radius:7px}
.nav-btn:hover{background:var(--panel-2)}
.nav-btn:focus-visible{outline:2px solid var(--green);outline-offset:2px}
.nav-btn-l{display:block;width:22px;height:2px;background:var(--ink);border-radius:2px;transition:transform .2s,opacity .15s}
/* Abierto, las tres rayas se convierten en una X. */
.nav-btn[aria-expanded=true] .nav-btn-l:nth-child(1){transform:translateY(7px) rotate(45deg)}
.nav-btn[aria-expanded=true] .nav-btn-l:nth-child(2){opacity:0}
.nav-btn[aria-expanded=true] .nav-btn-l:nth-child(3){transform:translateY(-7px) rotate(-45deg)}

/* Panel desplegable. Va por debajo del header, que es sticky, así que se
   coloca con `top` a su altura y se desplaza con el scroll bloqueado. */
.menu-movil{display:none;position:fixed;left:0;right:0;top:112px;bottom:0;z-index:45;
  background:var(--bg);border-top:1px solid var(--hair);overflow-y:auto;overscroll-behavior:contain;
  padding:8px 0 40px}
.menu-movil.abierto{display:block}
.menu-movil ul{list-style:none}
.menu-movil a,.menu-movil summary{display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:14px 26px;color:var(--ink-2);font-size:1.06rem;cursor:pointer}
.menu-movil summary{list-style:none}
.menu-movil summary::-webkit-details-marker{display:none}
.menu-movil a:hover,.menu-movil summary:hover{background:var(--panel-2);color:var(--ink)}
.menu-movil .n1{font-weight:600;color:var(--ink);border-bottom:1px solid var(--hair)}
.menu-movil .n2{padding-left:42px;font-size:1.02rem}
.menu-movil .n3{padding-left:58px;font-size:.99rem;color:var(--ink-3)}
/* «Ver toda la categoría» cierra la lista de productos, así que se separa con
   un filete para que no se lea como uno más. */
.menu-movil .n3-cat{color:var(--green);border-top:1px solid var(--hair);font-family:'IBM Plex Mono';font-size:.88rem}
.menu-movil .on{color:var(--green)}
.menu-movil .destacado{color:var(--green)}
.menu-movil .caret{width:14px;height:14px;stroke:currentColor;stroke-width:2;fill:none;flex-shrink:0;transition:transform .18s}
.menu-movil details[open]>summary .caret{transform:rotate(180deg)}
.menu-movil a:focus-visible,.menu-movil summary:focus-visible{outline:2px solid var(--green);outline-offset:-2px}

/* Con el menú abierto no se desplaza la página de debajo. Solo se bloquea el
   eje vertical: `overflow:hidden` a secas pisaría el `overflow-x:clip` global
   y devolvería el desplazamiento lateral mientras el menú está abierto. */
body.menu-abierto{overflow-y:hidden}

@media(max-width:900px){
  .nav-btn{display:flex}
  .menu-movil{top:72px}      /* el header baja a 72px en este breakpoint */
}

/* ---------------------------------------------------------------------------
   Transiciones y movimiento
   --------------------------------------------------------------------------- */

/* El color del «explorar» y del título ya cambian en :hover, pero lo hacían de
   golpe. Con la transición el resaltado de la tarjeta y su texto viajan juntos.
   La flecha se emite con content:" →", que no es animable: eso no cambia. */
.tel .go,.svc .go,.app .go,.spec h3,.tel h3,.app h3{transition:color .15s}
.callout a,.article-body a,.nota-legal a,.side-card a{transition:color .15s,text-decoration-color .15s}

/* ===== aviso de cookies =====
   Barra inferior a todo el ancho. Va por debajo del visor de capturas
   (z-index:100) y por encima del menú de móvil (45), y deja libre la esquina
   inferior derecha, donde click2call.es pinta su botón flotante. */
.ck-aviso{position:fixed;left:0;right:0;bottom:0;z-index:60;background:var(--panel);border-top:1px solid var(--hair-2);box-shadow:0 -6px 24px rgba(11,10,8,.10)}
.ck-aviso[hidden]{display:none}
.ck-aviso-in{max-width:1240px;margin:0 auto;padding:16px 24px;display:flex;align-items:center;gap:22px}
.ck-aviso p{font-size:.94rem;color:var(--ink-2);line-height:1.55;margin:0;max-width:80ch}
.ck-aviso a{color:var(--amber);text-decoration:underline;text-decoration-color:var(--hair-2);text-underline-offset:2px}
.ck-aviso a:hover{text-decoration-color:var(--amber)}
.ck-aviso-btn{display:flex;gap:10px;flex-shrink:0}
.ck-aviso .btn{padding:11px 18px;font-size:14px;white-space:nowrap}
/* Hasta 900px el texto y los botones se apilan: en una sola fila, los dos
   botones dejaban al párrafo tres palabras por línea. Y se reserva sitio
   abajo a la derecha para no tapar el botón de Click2Call. */
@media(max-width:900px){
  .ck-aviso-in{flex-direction:column;align-items:flex-start;gap:14px;padding:16px 18px 18px}
  .ck-aviso p{font-size:.9rem}
  .ck-aviso-btn{width:100%;padding-right:76px}
  .ck-aviso .btn{flex:1;justify-content:center}
}
/* En los móviles más estrechos los dos botones siguen en una fila (caben: son
   «Aceptar» y «Solo lo necesario»), porque apilarlos hacía que el aviso ocupara
   un tercio de la pantalla. Aquí no cabe reservar 76px a la derecha sin dejar
   los botones inservibles, así que el hueco para el botón flotante de
   Click2Call no se reserva. ⚠️ Queda por comprobar en producción si a este
   ancho el botón flotante cae sobre los del aviso: aquí no se puede, porque el
   entorno de desarrollo tiene bloqueado click2call.es. Si se solapan, la salida
   es subir el botón desde el panel de click2call.es, no engordar el aviso: con
   padding inferior pasaba de 179px a 225px de alto, un tercio de la pantalla. */
@media(max-width:400px){
  .ck-aviso-btn{padding-right:0}
  .ck-aviso .btn{padding:11px 10px;font-size:13.5px}
}

/* Desplazamiento suave al pulsar un enlace interno con ancla. */
html{scroll-behavior:smooth}

/* ⚠️ OBLIGATORIO al añadir cualquier movimiento: quien haya pedido en su sistema
   que se reduzca el movimiento (mareo, vértigo, migrañas o simple preferencia)
   no debe recibirlo. Se anulan todas las transiciones y animaciones en lugar de
   ir recordándolo caso por caso, y también el scroll suave, que es movimiento
   igualmente. No se elimina ningún cambio de color ni de estado: el :hover
   sigue funcionando, solo deja de interpolarse. */
@media(prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.01ms !important;animation-iteration-count:1 !important;transition-duration:.01ms !important;scroll-behavior:auto !important}
  html{scroll-behavior:auto}
}
