@import url('../fuentes/fuentes.css');

/* ==========================================================================
   INVITREL — hoja de estilos única.
   Lenguaje editorial: radio cero en el contenido y pastilla en la acción.
   El color principal sale de --acento, que hoy es el azul. Ver
   DISENO-ALTERNATIVO.md.
   Sin librerías de terceros.
   ========================================================================== */

/* --- Tokens ------------------------------------------------------------- */

:root {
  color-scheme: light dark;

  /* Lienzo blanco, tinta negra y las superficies en azul claro. El azul
     tiene dos papeles distintos y conviene no mezclarlos: aqui es el NEUTRO
     (tarjetas, placas, bloques) y en --acento es el color PRINCIPAL. */
  --hielo:        #ffffff;
  --superficie:   #e8f1f7;
  --superficie-2: #d7e7f1;
  --tinta:        #111111;
  --tinta-suave:  #55636b;
  --borde:        #cbdfeb;
  --borde-fuerte: #111111;

  /* Paleta de la marca. El cian alimenta a --acento y ademas marca el rango
     de temperatura y WhatsApp; el verde sigue reservado al sello Clase A.
     OJO: al ser el azul el color principal, el chip de temperatura ya no
     destaca por color, solo por forma. Ver DISENO-ALTERNATIVO.md. */
  --frio:         #0d7490;
  --frio-vivo:    #0a5d74;
  --frio-tenue:   #e2f0f5;
  --verde:        #2f7d52;
  --verde-tenue:  #e4f1e9;

  /* Color principal. Aqui se decide si el sitio es azul o es tinta:
     --acento: var(--tinta) / --acento-texto: var(--hielo) lo devuelve
     al blanco y negro sin tocar una sola regla mas abajo. */
  --acento:        var(--frio);
  --acento-texto:  #ffffff;

  /* Fondo de la foto de producto. Las fotos ya vienen recortadas con canal
     alfa, así que el equipo se apoya en el azul claro y no en una caja. */
  --placa:        #e8f1f7;
  --placa-borde:  #cbdfeb;

  /* Sin sombras. La profundidad la dan el contraste de la foto contra el
     fondo neutro y la línea de 1 px de las barras fijas. Se dejan definidas
     en vez de borrarlas: hay reglas que todavía las referencian. */
  --sombra:       none;
  --sombra-alta:  none;

  --display: 'IBM Plex Sans Condensed', 'Arial Narrow', system-ui, sans-serif;
  --texto:   'IBM Plex Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --mono:    'IBM Plex Mono', ui-monospace, 'Cascadia Code', Consolas, monospace;

  --ancho: 1440px;

  /* Radio cero en el contenido, pastilla en la acción. */
  --radio: 0;
  --radio-g: 0;
  --pastilla: 999px;

  /* Solo lo usa la tarjeta-foto del carrusel, que es una prueba. Si
     convence y se lleva al catalogo, lo que se cambia es --radio-g. */
  --radio-foto: 16px;

  /* La tarjeta-foto no invierte con el tema: su tinta y su fondo se declaran
     una sola vez. El fondo es el lapislazuli al que muere la sombra; ya no es
     un negro, y por eso la variable no se llama --foto-oscuro. */
  --foto-tinta: #ffffff;
  --foto-fondo: #26619c;
  /* Verde del sello Clase A sobre la tarjeta azul: el --verde del tema
     no da contraste suficiente ahi. */
  --foto-verde: #b6ecce;

  /* Verde oscuro de WhatsApp. Con el fondo en lapislazuli, el verde claro de
     la marca (#25d366) dejaba el glifo blanco en 1,98:1; este lo sube a
     4,14:1. A cambio el circulo casi se funde con el fondo -- 1,55:1 -- y por
     eso lleva aro claro, que es lo que separa el boton.
     No choca con --verde (sello Clase A): aquel rotula texto, este solo pinta
     el circulo de un glifo. */
  --wasap: #128c7e;

  /* Rejilla de 8 px. Las tarjetas se separan lo justo para leerse como
     rejilla continua, no como fichas sueltas. */
  --u: 8px;
  --hueco-tarjeta: 8px;

  /* Alto de las barras fijas. Se usa para que las anclas (#congeladores,
     #principal) no aterricen tapadas: ver `scroll-margin-top` mas abajo. */
  --cabecera: 64px;
  /* Medido con herramientas/capturas.py, no estimado: con los filtros en
     pastilla y el contenedor a 1440 px, las seis familias caben en una sola
     fila y la barra bajo de 172 a 133 px. Si se cambia el alto del buscador
     o de los filtros, volver a medirlo: capturas.py lo comprueba. */
  --barra-catalogo: 133px;

  /* Objetivo tactil minimo. Un boton de 34px se falla con el pulgar. */
  --toque: 48px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --hielo:        #080d10;
    --superficie:   #101a20;
    --superficie-2: #17242c;
    --tinta:        #eef4f7;
    --tinta-suave:  #9aa9b2;
    --borde:        #23323b;
    --borde-fuerte: #eef4f7;
    --frio:         #3fb3d4;
    --frio-vivo:    #6acbe6;
    --frio-tenue:   #0f2f38;
    --verde:        #4caf7b;
    --verde-tenue:  #14301f;

    /* Ver la nota de --acento en el bloque claro. */
    --acento:        var(--frio);
    --acento-texto:  #08181e;
    --placa:        #101a20;
    --placa-borde:  #23323b;
    --sombra:       none;
    --sombra-alta:  none;
  }
}

/* El interruptor del visor debe ganarle a la consulta de medios, en ambos sentidos.
   `color-scheme` va aquí y no solo en :root: sin esto, quien fuerza el tema
   oscuro con el sistema en claro sigue viendo el desplegable nativo, las barras
   de desplazamiento y el autorrelleno en claro. */
:root[data-theme="dark"] {
  color-scheme: dark;

  --hielo:        #080d10;
  --superficie:   #101a20;
  --superficie-2: #17242c;
  --tinta:        #eef4f7;
  --tinta-suave:  #9aa9b2;
  --borde:        #23323b;
  --borde-fuerte: #eef4f7;
  --frio:         #3fb3d4;
  --frio-vivo:    #6acbe6;
  --frio-tenue:   #0f2f38;
  --verde:        #4caf7b;
  --verde-tenue:  #14301f;

  /* Ver la nota de --acento en el bloque claro. */
  --acento:        var(--frio);
  --acento-texto:  #08181e;
  --placa:        #101a20;
  --placa-borde:  #23323b;
  --sombra:       none;
  --sombra-alta:  none;
}

:root[data-theme="light"] {
  color-scheme: light;

  --hielo:        #ffffff;
  --superficie:   #e8f1f7;
  --superficie-2: #d7e7f1;
  --tinta:        #111111;
  --tinta-suave:  #55636b;
  --borde:        #cbdfeb;
  --borde-fuerte: #111111;
  --frio:         #0d7490;
  --frio-vivo:    #0a5d74;
  --frio-tenue:   #e2f0f5;
  --verde:        #2f7d52;
  --verde-tenue:  #e4f1e9;

  /* Color principal. Aqui se decide si el sitio es azul o es tinta:
     --acento: var(--tinta) / --acento-texto: var(--hielo) lo devuelve
     al blanco y negro sin tocar una sola regla mas abajo. */
  --acento:        var(--frio);
  --acento-texto:  #ffffff;
  --placa:        #e8f1f7;
  --placa-borde:  #cbdfeb;
  --sombra:       none;
  --sombra-alta:  none;
}

/* --- Base --------------------------------------------------------------- */

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

/* El atributo `hidden` tiene que ganar SIEMPRE. Va aqui arriba, antes que
   ninguna otra regla, porque es la que sostiene medio sitio.
   ==========================================================================
   `hidden` no lo aplica el HTML: lo aplica una regla de la hoja del
   navegador, [hidden] { display: none }. Y las reglas del navegador pierden
   contra CUALQUIER regla de autor que declare `display`, por poco especifica
   que sea. Basta un `.loquesea { display: grid }` en cualquier punto de este
   archivo para que un elemento con `hidden` puesto se siga viendo.

   No es teorico: paso dos veces en este sitio.

     - El bloque «Ningun equipo coincide con la busqueda» tiene
       `display: grid`, asi que salia SIEMPRE al pie del catalogo, incluso con
       los 25 equipos a la vista. js/catalogo.js hacia bien su trabajo --
       ponia el atributo -- y el CSS lo ignoraba.
     - El boton «Ver el mapa aqui» de contacto es un `.btn`, que lleva
       `display: inline-flex`. Sale del servidor con `hidden` justamente para
       que no aparezca si js/mapa.js no llega a ejecutarse, y aparecia igual:
       un boton que sin JavaScript no hace nada.

   Con `!important` el atributo vuelve a mandar sobre las clases, que es lo
   que todo el codigo de este sitio da por supuesto. herramientas/verificar.py
   comprueba en las cuatro paginas, con y sin JavaScript, que no quede ni un
   elemento con `hidden` visible. */
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    transition-duration: .01ms !important;
  }
}

body {
  margin: 0;
  background: var(--hielo);
  color: var(--tinta);
  font: 400 1rem/1.65 var(--texto);
  font-synthesis: none;
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; height: auto; display: block; }

/* Los enlaces van en el color principal, con su subrayado. */
a { color: var(--acento); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { color: var(--frio-vivo); }

:focus-visible {
  outline: 2px solid var(--frio);
  outline-offset: 2px;
  border-radius: 2px;
}

/* Nada de retardo de 300 ms al tocar, y el destello del toque en color de marca
   en vez del gris azulado que pone el sistema por su cuenta. */
a, button, summary, label, select, input[type="search"] {
  touch-action: manipulation;
  -webkit-tap-highlight-color: rgb(128 128 128 / 22%);
}

/* Las anclas caen debajo de la cabecera fija si no se les reserva el hueco.
   `.grupo` ademas convive con la barra de filtros del catalogo, que tambien
   es fija: por eso lleva su propio margen, mas alto. */
[id] { scroll-margin-top: calc(var(--cabecera) + 1rem); }
.grupo { scroll-margin-top: calc(var(--cabecera) + var(--barra-catalogo) + 1rem); }

/* Contraste tipografico extremo: el titular se comprime hasta rozar el
   solapamiento (0.9) y el texto se queda holgado en 1.65. Es lo que hace que
   la pagina se lea como valla arriba y catalogo abajo. */
h1, h2, h3, h4 {
  font-family: var(--display);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -.015em;
  text-wrap: balance;
  margin: 0;
}

/* Titular de portada. La MAYUSCULA la pone el CSS y no el HTML: escrita en el
   texto, algunos lectores de pantalla la deletrean letra a letra. */
.display {
  font-size: clamp(2.75rem, 9vw, 6.5rem);
  line-height: .9;
  letter-spacing: -.02em;
  text-transform: uppercase;
  text-wrap: balance;
}

p { margin: 0; }

.contenedor {
  width: 100%;
  max-width: var(--ancho);
  margin-inline: auto;
  padding-inline: clamp(1.25rem, 4vw, 2.5rem);
}

/* Etiqueta de sección: versalita espaciada y una regla de 1 px. Sin color y
   sin degradado: es un rótulo, no una señal. */
.eyebrow {
  font-family: var(--mono);
  font-size: .75rem;
  font-weight: 500;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--tinta-suave);
  display: flex;
  align-items: center;
  gap: .75rem;
  margin: 0 0 1rem;
}

.eyebrow::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--borde);
}

.seccion { padding-block: clamp(3.5rem, 8vw, 6rem); }
.seccion--alt { background: var(--hielo); border-block: 1px solid var(--borde); }

.plomo {
  color: var(--tinta-suave);
  font-size: 1.0625rem;
  max-width: 62ch;
}

/* --- Cabecera ----------------------------------------------------------- */

.cabecera {
  position: sticky;
  top: 0;
  z-index: 50;
  /* Opaco primero: si el navegador no entiende color-mix, la cabecera
     mantiene fondo y el contenido no se lee por debajo. */
  background: var(--hielo);
  background: color-mix(in srgb, var(--hielo) 88%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--borde);
}

.cabecera__fila {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  min-height: 64px;
}

.marca {
  display: flex;
  align-items: center;
  gap: .75rem;
  text-decoration: none;
  min-height: var(--toque);
}

.marca img {
  height: 26px;
  width: auto;
  /* El logo original es negro sobre transparente: se invierte en oscuro. */
  filter: none;
}

@media (prefers-color-scheme: dark) {
  .marca img { filter: invert(1) brightness(1.6); }
}
:root[data-theme="dark"] .marca img { filter: invert(1) brightness(1.6); }
:root[data-theme="light"] .marca img { filter: none; }

.marca__sub {
  font-family: var(--mono);
  font-size: .625rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--tinta-suave);
  border-left: 1px solid var(--borde-fuerte);
  padding-left: .75rem;
  line-height: 1.3;
}

.nav { margin-left: auto; }

.nav ul {
  display: flex;
  align-items: center;
  gap: clamp(.75rem, 2vw, 1.75rem);
  list-style: none;
  margin: 0;
  padding: 0;
}

.nav a {
  font-family: var(--display);
  font-size: 1rem;
  font-weight: 700;
  color: var(--tinta);
  text-decoration: none;
  padding-block: .35rem;
  border-bottom: 2px solid transparent;
  white-space: nowrap;
}

.nav a:hover { color: var(--acento); }
.nav a[aria-current="page"] { border-bottom-color: var(--acento); color: var(--acento); }

.tema {
  background: none;
  border: 1px solid var(--borde);
  border-radius: var(--pastilla);
  color: var(--tinta-suave);
  cursor: pointer;
  padding: .35rem .5rem;
  display: grid;
  place-items: center;
  line-height: 0;
  min-width: var(--toque);
  min-height: var(--toque);
}

.tema:hover { border-color: var(--acento); color: var(--acento); }
.tema svg { width: 16px; height: 16px; }

/* Qué icono se ve lo decide solo el CSS: luna en claro (pulsar → oscuro), sol
   en oscuro. tema.js únicamente cambia data-theme; así el icono ya sale bien
   en el primer pintado, sin esperar a JavaScript. */
.tema .icono-luna { display: block; }
.tema .icono-sol { display: none; }

@media (prefers-color-scheme: dark) {
  .tema .icono-luna { display: none; }
  .tema .icono-sol { display: block; }
}

:root[data-theme="dark"] .tema .icono-luna { display: none; }
:root[data-theme="dark"] .tema .icono-sol { display: block; }
:root[data-theme="light"] .tema .icono-luna { display: block; }
:root[data-theme="light"] .tema .icono-sol { display: none; }

/* --- Botones ------------------------------------------------------------ */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  font-family: var(--display);
  font-size: 1rem;
  font-weight: 700;
  text-decoration: none;
  padding: .75rem 1.75rem;
  min-height: var(--toque);
  border-radius: var(--pastilla);
  border: 1px solid transparent;
  cursor: pointer;
  transition: background-color .15s, border-color .15s, color .15s;
}

/* Accion primaria: el color principal del sitio. */
.btn--primario {
  background: var(--acento);
  color: var(--acento-texto);
}

.btn--primario:hover {
  background: var(--frio-vivo);
  color: var(--acento-texto);
}

/* Seis reglas se fueron con --acento-texto: el color del texto sobre el cian
   cambia con el tema (blanco en claro, casi negro en oscuro, porque el cian
   del tema oscuro es claro) y eso antes se corregia tema por tema. */
.btn--frio { background: var(--frio); color: var(--acento-texto); }
.btn--frio:hover { background: var(--frio-vivo); color: var(--acento-texto); }

.btn--linea {
  border-color: var(--borde-fuerte);
  color: var(--tinta);
  background: transparent;
}
.btn--linea:hover { border-color: var(--acento); color: var(--acento); }

/* Botón de WhatsApp.
   Va en el acento del sitio, no en el verde de la marca: el verde queda
   reservado para el sello Clase A, y el glifo ya identifica el canal.
   Además el verde de WhatsApp no da contraste suficiente con texto blanco. */
.btn--wasap {
  background: var(--frio);
  color: var(--acento-texto);
  width: 100%;
  justify-content: center;
  font-size: .9375rem;
  padding: .6rem 1rem;
}

.btn--wasap:hover { background: var(--frio-vivo); color: var(--acento-texto); }
.btn--wasap svg { width: 16px; height: 16px; flex: none; }

/* En la franja y en el estado vacío el botón no ocupa todo el ancho. */
.franja .btn--wasap,
.sin-resultados .btn--wasap { width: auto; }

/* --- Portada ------------------------------------------------------------ */

.hero { padding-block: clamp(3rem, 7vw, 5.5rem) clamp(2.5rem, 6vw, 4.5rem); }

/* El titular va por encima de la rejilla, a todo el ancho. Encajonado en una
   columna de media pagina se partia en tres lineas y "FRÍO" quedaba solo. */
.hero__rejilla {
  display: grid;
  grid-template-columns: minmax(0, .85fr) minmax(0, 1.15fr);
  gap: clamp(2rem, 5vw, 4rem);
  align-items: end;
  margin-top: clamp(2rem, 4vw, 3rem);
}

/* Rotulo sobre el titular. Ya no lleva la cifra grande: los anos pasaron al
   titular y repetirlos aqui era decir dos veces lo mismo. */
.hero__anos {
  font-family: var(--mono);
  font-size: .75rem;
  font-weight: 500;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--acento);
  display: block;
  margin-bottom: 1.5rem;
}

.hero h1 { margin-bottom: 0; }

.hero__acciones { display: flex; flex-wrap: wrap; gap: .75rem; margin-top: 2rem; }

/* Placa de foto: clara en ambos temas. */
.placa {
  background: var(--placa);
  border: none;
  border-radius: var(--radio);
  display: grid;
  place-items: center;
  padding: clamp(1rem, 3vw, 2rem);
  overflow: hidden;
}

.hero .placa { aspect-ratio: 4 / 3; }
.hero .placa img { max-height: 100%; width: auto; object-fit: contain; }

/* Cifras del hero */
.cifras {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 1px;
  background: var(--borde);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  margin-top: clamp(2.5rem, 6vw, 4rem);
  overflow: hidden;
}

.cifra { background: var(--superficie); padding: 1.25rem 1.5rem; }

.cifra dt {
  font-family: var(--mono);
  font-size: .6875rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--tinta-suave);
  margin-bottom: .35rem;
}

.cifra dd {
  font-family: var(--display);
  font-size: 1.5rem;
  font-weight: 700;
  letter-spacing: -.02em;
  margin: 0;
  font-variant-numeric: tabular-nums;
}

/* --- Familias (categorías) --------------------------------------------- */

.familias {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr));
  gap: var(--hueco-tarjeta);
}

.familia {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--superficie);
  border-radius: var(--radio);
  padding: 1.75rem 1.5rem 1.5rem;
  text-decoration: none;
  color: inherit;
  overflow: hidden;
  outline: 1px solid transparent;
  outline-offset: -1px;
  transition: outline-color .15s;
}

.familia:hover { outline-color: var(--acento); }

/* La sigla real del código de producto, como marca de agua industrial. */
.familia__sigla {
  position: absolute;
  top: -.35rem;
  right: .75rem;
  font-family: var(--display);
  font-size: clamp(4rem, 9vw, 7rem);
  font-weight: 700;
  letter-spacing: -.04em;
  color: var(--acento);
  opacity: .13;
  pointer-events: none;
  user-select: none;
}

.familia h3 {
  font-size: clamp(1.2rem, 2vw, 1.5rem);
  text-transform: uppercase;
  margin-bottom: .5rem;
}
.familia p { color: var(--tinta-suave); font-size: .9375rem; }

.familia__pie {
  display: flex;
  align-items: center;
  gap: .75rem;
  flex-wrap: wrap;
  margin-top: auto;
  padding-top: 1rem;
  border-top: 1px solid var(--borde);
}

.familia__n {
  font-family: var(--mono);
  font-size: .75rem;
  color: var(--tinta-suave);
  margin-left: auto;
}

/* --- Carrusel de destacados (portada) -----------------------------------
   Contenedor con scroll-snap. Se mueve sin JavaScript: con el dedo, con la
   rueda horizontal y con el teclado gracias al tabindex del <ul>. Los botones
   son un extra que solo aparece si js/carrusel.js se ejecuta.
   ---------------------------------------------------------------------- */

.carrusel__cabeza {
  display: flex;
  align-items: flex-end;
  gap: 1.5rem;
  margin-bottom: 1.75rem;
}

.carrusel__cabeza .titulo-seccion { margin-bottom: 0; }

.carrusel__mandos { display: flex; gap: .5rem; margin-left: auto; flex: none; }
.carrusel__mandos[hidden] { display: none; }

.carrusel__boton {
  width: var(--toque);
  height: var(--toque);
  flex: none;
  border: 1px solid var(--borde-fuerte);
  border-radius: var(--pastilla);
  background: transparent;
  color: var(--tinta);
  cursor: pointer;
  display: grid;
  place-items: center;
  transition: background-color .15s, color .15s, opacity .15s;
}

.carrusel__boton:hover:not(:disabled) { background: var(--acento); color: var(--acento-texto); }
.carrusel__boton:disabled { opacity: .3; cursor: default; }
.carrusel__boton svg { width: 18px; height: 18px; }

.carrusel {
  display: grid;
  grid-auto-flow: column;
  /* Mas anchas que antes (240-300): con tres a la vista en vez de cinco,
     el texto respira y el nombre cabe en una linea. */
  grid-auto-columns: clamp(270px, 30vw, 400px);
  gap: var(--hueco-tarjeta);
  list-style: none;
  margin: 0;
  padding: 0;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}

.carrusel::-webkit-scrollbar { display: none; }

/* display:grid en el <li> para que la tarjeta se estire: si no, cada una mide
   lo que mide su texto y la fila queda con los pies a distinta altura. */
.carrusel > li { scroll-snap-align: start; display: grid; }

/* El <ul> recibe foco a proposito: sin tabindex, quien no usa raton no puede
   desplazar un contenedor con scroll. El contorno va separado para que no
   pise el borde de la primera tarjeta. */
.carrusel:focus-visible { outline: 2px solid var(--frio); outline-offset: 4px; }

@media (max-width: 640px) {
  /* En movil el carrusel se arrastra: los botones estorban mas que ayudan. */
  .carrusel__mandos { display: none; }
  .carrusel__cabeza { display: block; }
}

/* --- Tarjeta-foto del carrusel ------------------------------------------
   El equipo sobre un campo azul y, bajo el, una sombra que se oscurece hasta
   el negro. Los datos van ENCIMA de esa sombra: la foto es un recorte sobre
   color plano, y sin el degradado no habria zona oscura donde apoyar el texto
   blanco. La tarjeta es un objeto oscuro por si misma, igual en los dos temas.
   ---------------------------------------------------------------------- */

.tarjeta-foto {
  position: relative;
  display: flex;
  flex-direction: column;
  height: 100%;
  border-radius: var(--radio-foto);
  overflow: hidden;
  color: var(--foto-tinta);
  /* Opaco primero, por si el navegador no entiende color-mix. */
  background: var(--frio);
  background: linear-gradient(180deg,
              color-mix(in srgb, var(--frio) 45%, var(--foto-tinta)) 0%,
              var(--frio) 100%);
}

.tarjeta-foto__lienzo {
  position: relative;
  aspect-ratio: 1 / 1;
  display: grid;
  place-items: center;
  padding: 1.5rem 1.25rem 0;
}

.tarjeta-foto__lienzo img {
  max-height: 100%;
  max-width: 100%;
  width: auto;
  object-fit: contain;
}

/* El propio bloque de datos lleva la sombra y sube a pisar la base de la
   foto: por eso el degradado arranca transparente y no hay costura visible. */
.tarjeta-foto__datos {
  position: relative;
  /* Crece hasta el fondo de la tarjeta y el contenido se alinea abajo: el
     texto queda hundido en la zona ya negra, que es para lo que esta la
     sombra. Con `start` flotaba a media altura, sobre el degradado. */
  flex: 1;
  align-content: end;
  margin-top: -5.5rem;
  padding: 5.5rem 1.5rem 1.6rem;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: end;
  column-gap: 1rem;
  background: linear-gradient(180deg,
              transparent 0%,
              color-mix(in srgb, var(--foto-fondo) 70%, transparent) 34%,
              var(--foto-fondo) 58%);
}

/* El texto va agrupado en su propio bloque y no suelto en la rejilla: con los
   parrafos como hijos directos, el boton tenia que abarcar filas implicitas y
   `grid-row: 1 / -1` no llega ahi -- la linea -1 es la del final del grid
   EXPLICITO, asi que el circulo acababa arriba del todo. */
.tarjeta-foto__texto { display: grid; gap: .3rem; }

/* Solo el glifo y en el verde de WhatsApp, sin texto. El circulo se apoya en
   la esquina, alineado con la ultima linea de datos. */
.tarjeta-foto__wasap {
  align-self: end;
  width: var(--toque);
  height: var(--toque);
  border-radius: 50%;
  background: var(--wasap);
  color: var(--foto-tinta);
  /* Aro, no sombra: el verde oscuro sobre el lapislazuli da 1,55:1 y el
     circulo se perderia contra el fondo. Con el aro claro el borde del boton
     se ve siempre. Va en `border` y no en `box-shadow` para no reabrir la
     puerta a las sombras, que este diseno no usa. */
  border: 2px solid var(--foto-tinta);
  display: grid;
  place-items: center;
  flex: none;
  text-decoration: none;
  transition: transform .15s;
}

.tarjeta-foto__wasap:hover { color: var(--foto-tinta); transform: scale(1.06); }
.tarjeta-foto__wasap svg { width: 26px; height: 26px; }

.tarjeta-foto h3 {
  font-size: clamp(1.25rem, 2.2vw, 1.6rem);
  color: var(--foto-tinta);
  margin-bottom: .15rem;
}

.tarjeta-foto__dato {
  font-size: .875rem;
  color: var(--foto-tinta);
}

/* La seccion se tinta para que la tarjeta se recorte contra ella. */
.seccion--carrusel { background: var(--superficie); }

/* --- Utilidades --------------------------------------------------------- */

/* Se oculta a la vista pero sigue ahi para el lector de pantalla y para el
   buscador del catalogo.

   SIN `position: absolute`, a proposito. La receta habitual lo lleva, y dentro
   del carrusel rompia la pagina: un elemento absoluto cuyo bloque contenedor
   queda FUERA del contenedor con scroll no lo recorta ese contenedor, asi que
   se iba a su posicion estatica -- la de las tarjetas 5 a 8, ya fuera de la
   pantalla -- y la pagina entera ganaba 776 px de desplazamiento horizontal.
   Ocupando 1x1 en el flujo no puede escaparse de ningun sitio. */
.oculto-visual {
  display: block;
  width: 1px;
  height: 1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* --- Piezas de la tarjeta que solo trae el catalogo ----------------------
   Chips, ficha PDF y panel de especificaciones. Todo va con colores propios y
   no con los del tema: la tarjeta es azul en claro y en oscuro, asi que un
   chip que siguiera al tema se veria de un color distinto en cada uno.
   ---------------------------------------------------------------------- */

.tarjeta-foto__chips {
  display: flex;
  flex-wrap: wrap;
  gap: .4rem;
  margin-top: .5rem;
}

.tarjeta-foto__chips .chip,
.tarjeta-foto__chips .chip--frio,
.tarjeta-foto__chips .chip--neutro {
  background: rgb(255 255 255 / 10%);
  color: var(--foto-tinta);
  border: 1px solid rgb(255 255 255 / 26%);
}

/* La barrita del chip de temperatura, en blanco sobre el azul. */
.tarjeta-foto__chips .chip--frio::before {
  background: var(--foto-tinta);
}

/* El sello Clase A conserva su verde: es la unica senal que queda por color. */
.tarjeta-foto__chips .chip--verde {
  background: rgb(76 175 123 / 24%);
  color: var(--foto-verde);
  border: 1px solid rgb(76 175 123 / 55%);
}

/* Pie de la tarjeta: fondo solido, ya fuera del degradado. */
.tarjeta-foto__pie {
  background: var(--foto-fondo);
  color: var(--foto-tinta);
  display: grid;
}

.tarjeta-foto__pie .enlace-ficha {
  color: var(--foto-tinta);
  justify-content: center;
  border-top: 1px solid rgb(255 255 255 / 16%);
}

.tarjeta-foto__pie .especificaciones {
  border-top: 1px solid rgb(255 255 255 / 16%);
}

.tarjeta-foto__pie .especificaciones summary {
  color: var(--foto-tinta);
}

.tarjeta-foto__pie .especificaciones summary:hover {
  color: var(--foto-tinta);
  background: rgb(255 255 255 / 8%);
}

.tarjeta-foto__pie .tabla-especificaciones th,
.tarjeta-foto__pie .tabla-especificaciones td {
  border-top: 1px solid rgb(255 255 255 / 14%);
  color: var(--foto-tinta);
}

/* Hueco de los equipos sin fotografia. */
/* Placa para los equipos que aun no tienen foto.
   Va sobre el lapislazuli de la propia tarjeta y NO suelta sobre el campo
   azul: arriba la tarjeta es azul palido -- #92c0cd -- y el rotulo blanco al
   80 % daba 1,74:1 sobre el. No es que se leyera mal: no se veia, y las seis
   tarjetas sin foto parecian rotas. Sobre la placa son 6,42:1, el mismo par
   que ya usa el titulo. herramientas/verificar.py lo fija. */
.tarjeta-foto__sin-foto {
  display: grid;
  place-items: center;
  gap: .5rem;
  padding: 1.25rem 1.5rem;
  border-radius: var(--radio-foto);
  background: var(--foto-fondo);
  color: var(--foto-tinta);
  font-family: var(--mono);
  font-size: .6875rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  text-align: center;
}

.tarjeta-foto__sin-foto svg { width: 32px; height: 32px; }

/* --- Chips ------------------------------------------------------------- */

.chip {
  display: inline-flex;
  align-items: center;
  gap: .375rem;
  font-family: var(--mono);
  font-size: .75rem;
  font-weight: 500;
  padding: .25rem .625rem;
  border-radius: var(--pastilla);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.chip--frio { background: var(--frio-tenue); color: var(--frio); }
.chip--verde { background: var(--verde-tenue); color: var(--verde); }
.chip--neutro {
  background: var(--superficie-2);
  color: var(--tinta-suave);
  border: 1px solid var(--borde);
}

/* Marca de temperatura: barrita fría antes del valor. */
.chip--frio::before {
  content: '';
  width: 3px;
  height: 11px;
  border-radius: 2px;
  background: linear-gradient(180deg, var(--frio), color-mix(in srgb, var(--frio) 30%, transparent));
}

/* --- Catálogo ----------------------------------------------------------- */

/* Barra de filtros: acompaña al visitante mientras recorre el catálogo.
   Se cuelga justo debajo de la cabecera, que también es sticky. El -1px evita
   que se vea una rendija del contenido entre los dos bordes. */
.barra-catalogo {
  position: sticky;
  top: calc(var(--cabecera) - 1px);
  z-index: 40;
  background: var(--hielo);
  background: color-mix(in srgb, var(--hielo) 94%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--borde);
  padding-block: .75rem;
}

/* El buscador va en su propia fila y a todo el ancho: es lo primero que
   usa quien ya sabe qué modelo busca. */
.buscador {
  position: relative;
  margin-bottom: .75rem;
}

.buscador__icono {
  position: absolute;
  left: .6rem;
  top: 50%;
  transform: translateY(-50%);
  width: 16px;
  height: 16px;
  color: var(--tinta-suave);
  pointer-events: none;
}

.buscador input {
  width: 100%;
  font: 400 .9375rem/1.4 var(--texto);
  color: var(--tinta);
  background: var(--superficie);
  border: 1px solid var(--borde-fuerte);
  border-radius: var(--pastilla);
  padding: .5rem 1rem .5rem 2.4rem;
  min-height: var(--toque);
}

.buscador input::placeholder { color: var(--tinta-suave); opacity: .8; }

.buscador input:focus {
  outline: 2px solid var(--frio);
  outline-offset: 1px;
  border-color: var(--frio);
}

/* Quita la X propia de Chrome, que descuadra el campo. */
.buscador input::-webkit-search-cancel-button { -webkit-appearance: none; }

.conteo {
  font-family: var(--mono);
  font-size: .75rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--tinta-suave);
  margin-bottom: 1.75rem;
}

/* --- Catálogo: barra lateral de familias -------------------------------
   Deja saltar de una familia a otra sin volver arriba. Sin JavaScript son
   simples anclas a cada grupo, que siguen funcionando.
   ---------------------------------------------------------------------- */

.catalogo-cuerpo {
  display: grid;
  grid-template-columns: 232px minmax(0, 1fr);
  gap: clamp(1.5rem, 4vw, 2.75rem);
  align-items: start;
}

.lado {
  position: sticky;
  top: calc(var(--cabecera) + var(--barra-catalogo) + 1rem);
}

.lado__titulo {
  font-family: var(--mono);
  font-size: .6875rem;
  font-weight: 500;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--tinta-suave);
  margin-bottom: .85rem;
}

.lado__lista {
  display: grid;
  gap: 1px;
  background: var(--borde);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  overflow: hidden;
}

.familia-lado {
  background: var(--superficie);
  padding: .8rem .9rem;
  text-decoration: none;
  color: inherit;
  display: grid;
  gap: .5rem;
  border-left: 2px solid transparent;
  transition: background-color .15s, border-color .15s;
}

.familia-lado:hover {
  background: var(--superficie-2);
  border-left-color: var(--acento);
  color: inherit;
}

.familia-lado[hidden] { display: none; }

.familia-lado__nombre {
  font-family: var(--display);
  font-size: .9375rem;
  font-weight: 700;
  line-height: 1.25;
}

.familia-lado__pie {
  display: flex;
  align-items: center;
  gap: .5rem;
  flex-wrap: wrap;
}

.familia-lado__n {
  font-family: var(--mono);
  font-size: .6875rem;
  color: var(--tinta-suave);
  margin-left: auto;
  font-variant-numeric: tabular-nums;
}

.sin-resultados {
  text-align: center;
  padding: clamp(2.5rem, 7vw, 4.5rem) 1.5rem;
  border: 1px dashed var(--borde-fuerte);
  border-radius: var(--radio-g);
  display: grid;
  gap: 1rem;
  justify-items: center;
}

.sin-resultados h2 { font-size: 1.35rem; }
.sin-resultados p { color: var(--tinta-suave); max-width: 46ch; }

.filtros {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
}

.filtro__n {
  font-family: var(--mono);
  font-size: .75rem;
  font-weight: 400;
  opacity: .65;
  font-variant-numeric: tabular-nums;
}

.filtro {
  font-family: var(--display);
  font-size: .9375rem;
  font-weight: 700;
  background: var(--superficie);
  color: var(--tinta);
  border: 1px solid var(--borde);
  border-radius: var(--pastilla);
  padding: .45rem 1.1rem;
  cursor: pointer;
  transition: border-color .15s, background-color .15s, color .15s;
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  min-height: var(--toque);
}

.filtro:hover { border-color: var(--acento); color: var(--acento); }

/* El filtro activo se rellena con el color principal, sin estados
   intermedios. */
.filtro[aria-pressed="true"] {
  background: var(--acento);
  border-color: var(--acento);
  color: var(--acento-texto);
}

.grupo { margin-bottom: clamp(2.5rem, 6vw, 4rem); }
.grupo[hidden] { display: none; }

.grupo__cabeza {
  display: flex;
  align-items: flex-end;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1.5rem;
  padding-bottom: .85rem;
  border-bottom: 1px solid var(--acento);
}

.grupo__cabeza h2 {
  font-size: clamp(1.5rem, 3vw, 2.1rem);
  text-transform: uppercase;
}
.grupo__cabeza p { color: var(--tinta-suave); font-size: .9375rem; max-width: 58ch; }

/* 260 px de minimo, no 300: es lo que hace que a 1440 entren cuatro
   columnas en vez de tres, con el hueco de 8 px ya descontado. */
.rejilla {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 260px), 1fr));
  gap: var(--hueco-tarjeta);
  /* Cada tarjeta mide lo suyo. Estiradas a la altura de la fila, abrir las
     especificaciones de una deformaba a las otras dos: la foto se quedaba
     arriba y debajo aparecia medio metro de azul vacio. */
  align-items: start;
}

/* Oculto por el buscador; sin él, todas las tarjetas se ven. */
.equipo[hidden] { display: none; }

.equipo {
  display: flex;
  flex-direction: column;
  background: var(--superficie);
  border-radius: var(--radio);
  overflow: hidden;
  transition: outline-color .15s;
  outline: 1px solid transparent;
  outline-offset: -1px;
}

/* Contorno y no borde: un borde de 1 px al pasar el raton desplazaria la
   tarjeta un pixel y la rejilla entera temblaria. */
.equipo:hover { outline-color: var(--acento); }

/* Placa cuadrada y generosa: el equipo es lo que hay que ver. */
.equipo__placa {
  background: var(--placa);
  aspect-ratio: 1 / 1;
  display: grid;
  place-items: center;
  padding: 1.25rem;
}

/* Las fotos originales varían mucho de tamaño: se contienen, nunca se estiran. */
.equipo__placa img {
  max-height: 100%;
  max-width: 100%;
  width: auto;
  object-fit: contain;
}

.equipo__placa--vacia {
  color: #8fa3ad;
  font-family: var(--mono);
  font-size: .6875rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  text-align: center;
  gap: .5rem;
}

.equipo__placa--vacia svg { width: 28px; height: 28px; opacity: .5; }

.equipo__cuerpo {
  display: flex;
  flex-direction: column;
  gap: .75rem;
  padding: 1.1rem 1.25rem 1.5rem;
  flex: 1;
}

/* Familia del equipo: útil al buscar, cuando los resultados cruzan grupos. */
.equipo__familia {
  display: block;
  font-family: var(--mono);
  font-size: .625rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--tinta-suave);
  margin-bottom: .35rem;
}

.equipo h3 { font-size: 1.0625rem; line-height: 1.25; }

.equipo__modelo {
  font-family: var(--mono);
  font-size: .75rem;
  color: var(--tinta-suave);
  letter-spacing: .04em;
}

.equipo__chips { display: flex; flex-wrap: wrap; gap: .4rem; }

.equipo__datos {
  font-size: .875rem;
  color: var(--tinta-suave);
  display: grid;
  gap: .2rem;
}

.equipo__pie {
  display: grid;
  gap: .6rem;
  justify-items: center;
  margin-top: auto;
  padding-top: .5rem;
}

.enlace-ficha {
  font-family: var(--display);
  font-size: .875rem;
  font-weight: 700;
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  text-decoration: none;
  min-height: var(--toque);
  padding-inline: .5rem;
}

.enlace-ficha:hover { text-decoration: underline; }
.enlace-ficha svg { width: 14px; height: 14px; }

/* Panel de especificaciones: <details> nativo, sin JavaScript. */
.especificaciones { border-top: 1px solid var(--borde); }

.especificaciones summary {
  font-family: var(--mono);
  font-size: .6875rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--tinta-suave);
  cursor: pointer;
  padding: .75rem 1.25rem;
  list-style: none;
  display: flex;
  align-items: center;
  gap: .5rem;
  min-height: var(--toque);
}

.especificaciones summary::-webkit-details-marker { display: none; }
.especificaciones summary:hover { color: var(--acento); }

.especificaciones summary::after {
  content: '+';
  margin-left: auto;
  font-size: 1rem;
  line-height: 1;
}

.especificaciones[open] summary::after { content: '−'; }

.tabla-especificaciones {
  width: 100%;
  border-collapse: collapse;
  font-size: .8125rem;
}

.tabla-especificaciones th,
.tabla-especificaciones td {
  text-align: left;
  padding: .45rem 1.25rem;
  border-top: 1px solid var(--borde);
  vertical-align: top;
}

.tabla-especificaciones th {
  font-weight: 400;
  color: var(--tinta-suave);
  width: 48%;
}

.tabla-especificaciones td {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
}

.envoltorio-tabla { overflow-x: auto; }

/* --- Bloques de texto -------------------------------------------------- */

.prosa { max-width: 68ch; display: grid; gap: 1.1rem; }
.prosa h2 { font-size: clamp(1.5rem, 3.5vw, 2rem); margin-top: 1.25rem; }
.prosa h3 { font-size: 1.2rem; margin-top: .75rem; }
.prosa p { color: var(--tinta-suave); }
.prosa strong { color: var(--tinta); font-weight: 600; }

/* Prosa a dos columnas (politica de calidad). Son bloques independientes,
   no texto que fluye de una columna a otra: un parrafo partido a media pagina
   obliga a subir la vista para seguir leyendo. */
.dos-columnas--prosa .prosa h2:first-child { margin-top: 0; }

.dos-columnas {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
  gap: clamp(1.5rem, 4vw, 3rem);
}

.tarjeta {
  background: var(--superficie);
  border: none;
  border-top: 2px solid var(--acento);
  border-radius: var(--radio);
  padding: 1.5rem;
  display: grid;
  gap: .6rem;
}

.tarjeta h3 { font-size: 1.15rem; }
.tarjeta p { color: var(--tinta-suave); font-size: .9375rem; }

.lista-limpia { list-style: none; margin: 0; padding: 0; display: grid; gap: .6rem; }

.lista-limpia li {
  padding-left: 1.5rem;
  position: relative;
  color: var(--tinta-suave);
  font-size: .9375rem;
}

.lista-limpia li::before {
  content: '';
  position: absolute;
  left: 0;
  top: .55em;
  width: 8px;
  height: 2px;
  background: var(--acento);
}

/* --- Contacto ---------------------------------------------------------- */

.contacto-rejilla {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
  gap: clamp(2rem, 5vw, 3.5rem);
  align-items: start;
}

.vias { display: grid; gap: 1px; background: var(--borde); border: 1px solid var(--borde); border-radius: var(--radio); overflow: hidden; }

/* Icono a la izquierda, rotulo y valor a la derecha. El icono ocupa las dos
   filas con `span 2` y no con `1 / -1`: las filas son implicitas y la linea
   -1 solo llega al final del grid explicito. */
.via {
  background: var(--superficie);
  padding: 1.1rem 1.35rem;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  column-gap: 1rem;
  row-gap: .3rem;
  align-items: center;
  text-decoration: none;
  color: inherit;
}

.via__icono {
  grid-row: 1 / span 2;
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  color: var(--acento);
}

.via__icono svg { width: 22px; height: 22px; }

.via:hover { background: var(--superficie-2); }

.via dt,
.via__rotulo {
  font-family: var(--mono);
  font-size: .6875rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--tinta-suave);
}

.via__valor {
  font-family: var(--display);
  font-size: 1.0625rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.via--enlace .via__valor { color: var(--acento); }

/* --- Mapa (bloque «Cómo llegar» de contacto) ----------------------------
   Dos estados en la misma caja: la fachada propia y, tras pulsar, el marco de
   Google. La caja se dimensiona sola en cada uno porque la fachada es texto
   —crece con la pantalla estrecha, no se aplasta— y el marco necesita una
   proporción fija, que un <iframe> no tiene por su cuenta.
   ---------------------------------------------------------------------- */

.mapa {
  display: grid;
  place-items: center;
  min-height: clamp(280px, 32vw, 420px);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  background: var(--superficie);
}

.mapa--cargado {
  display: block;
  min-height: 0;
  aspect-ratio: 16 / 9;
  overflow: hidden;
}

.mapa iframe {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}

.mapa__fachada {
  display: grid;
  justify-items: center;
  gap: 1rem;
  max-width: 46ch;
  padding: clamp(1.5rem, 4vw, 3rem);
  text-align: center;
}

.mapa__marca { color: var(--acento); }
.mapa__marca svg { width: 40px; height: 40px; }

.mapa__direccion {
  font-family: var(--display);
  font-size: clamp(1.0625rem, 2.4vw, 1.375rem);
  font-weight: 700;
  line-height: 1.3;
}

.mapa__acciones {
  display: flex;
  flex-wrap: wrap;
  gap: .75rem;
  justify-content: center;
}

.mapa__nota {
  font-size: .8125rem;
  line-height: 1.5;
  color: var(--tinta-suave);
}

.formulario { display: grid; gap: 1rem; }

.campo { display: grid; gap: .4rem; }

.campo label {
  font-family: var(--mono);
  font-size: .6875rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--tinta-suave);
}

.campo input,
.campo textarea,
.campo select {
  font: 400 .9375rem/1.5 var(--texto);
  color: var(--tinta);
  background: var(--superficie);
  border: 1px solid var(--borde-fuerte);
  border-radius: var(--radio);
  padding: .65rem .75rem;
  width: 100%;
}

.campo input:focus,
.campo textarea:focus,
.campo select:focus {
  outline: 2px solid var(--frio);
  outline-offset: 1px;
  border-color: var(--frio);
}

.campo textarea { resize: vertical; min-height: 120px; }

/* --- Errores del formulario ---------------------------------------------
   El error se dice AL LADO del campo que falla, no solo en un aviso general
   arriba: con seis campos, "revise los datos" obliga a adivinar cuál.
   ---------------------------------------------------------------------- */

.campo__error {
  font-size: .8125rem;
  line-height: 1.4;
  color: #8f3323;
  display: flex;
  align-items: flex-start;
  gap: .35rem;
}

.campo__error::before {
  content: '!';
  flex: 0 0 auto;
  width: 1.05em;
  height: 1.05em;
  margin-top: .15em;
  border-radius: 50%;
  background: #8f3323;
  color: #fff;
  font-family: var(--mono);
  font-size: .7em;
  font-weight: 500;
  line-height: 1.5;
  text-align: center;
}

.campo__error[hidden] { display: none; }

.campo input[aria-invalid="true"],
.campo textarea[aria-invalid="true"],
.campo select[aria-invalid="true"] {
  border-color: #b4442f;
}

.campo input[aria-invalid="true"]:focus,
.campo textarea[aria-invalid="true"]:focus,
.campo select[aria-invalid="true"]:focus {
  outline-color: #b4442f;
}

@media (prefers-color-scheme: dark) {
  .campo__error { color: #f0a394; }
  .campo__error::before { background: #f0a394; color: #2c1512; }
}
:root[data-theme="dark"] .campo__error { color: #f0a394; }
:root[data-theme="dark"] .campo__error::before { background: #f0a394; color: #2c1512; }
:root[data-theme="light"] .campo__error { color: #8f3323; }
:root[data-theme="light"] .campo__error::before { background: #8f3323; color: #fff; }

.aviso {
  border-radius: var(--radio);
  padding: .85rem 1rem;
  font-size: .9375rem;
  border: 1px solid var(--borde);
  background: var(--superficie-2);
}

.aviso[data-estado="ok"] { border-color: var(--verde); background: var(--verde-tenue); color: var(--verde); }
.aviso[data-estado="error"] { border-color: #b4442f; background: #fbeae6; color: #8f3323; }

@media (prefers-color-scheme: dark) {
  .aviso[data-estado="error"] { background: #2c1512; color: #f0a394; border-color: #7d3325; }
}
:root[data-theme="dark"] .aviso[data-estado="error"] { background: #2c1512; color: #f0a394; border-color: #7d3325; }

.mapa {
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  width: 100%;
  aspect-ratio: 16 / 10;
  filter: saturate(.85);
}

/* --- Pie --------------------------------------------------------------- */

.pie {
  background: var(--superficie);
  border-top: 1px solid var(--borde);
  padding-block: clamp(2.5rem, 5vw, 3.5rem) 1.5rem;
  margin-top: clamp(3rem, 7vw, 5rem);
}

.pie__rejilla {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr;
  gap: clamp(1.75rem, 4vw, 3rem);
}

.pie h4 {
  font-family: var(--mono);
  font-size: .6875rem;
  font-weight: 500;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--tinta-suave);
  margin-bottom: .9rem;
}

.pie ul { list-style: none; margin: 0; padding: 0; display: grid; gap: .25rem; }

.pie a {
  color: var(--tinta);
  text-decoration: none;
  font-size: .9375rem;
  display: inline-flex;
  align-items: center;
  min-height: 28px;
}
.pie a:hover { color: var(--acento); text-decoration: underline; }
.pie p { color: var(--tinta-suave); font-size: .9375rem; }

.pie__legal {
  margin-top: clamp(2rem, 4vw, 2.75rem);
  padding-top: 1.25rem;
  border-top: 1px solid var(--borde);
  display: flex;
  flex-wrap: wrap;
  gap: .75rem 1.5rem;
  align-items: center;
  font-size: .8125rem;
  color: var(--tinta-suave);
}

.pie__legal .mono { font-family: var(--mono); }

/* --- Franja de llamada ------------------------------------------------- */

/* Bloque invertido: el color principal a sangre, con su texto de contraste.
   Como --acento y --acento-texto son variables de tema, la banda se ajusta
   sola en claro y en oscuro sin las siete reglas de correccion de antes. */
.franja {
  background: var(--acento);
  color: var(--acento-texto);
  border-radius: var(--radio-g);
  padding: clamp(2rem, 5vw, 3.5rem);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1.5rem;
}

.franja h2 {
  font-size: clamp(1.7rem, 4vw, 2.8rem);
  line-height: .95;
  text-transform: uppercase;
  color: inherit;
}
.franja p { color: inherit; opacity: .78; max-width: 48ch; margin-top: .5rem; }
.franja__acciones { display: flex; flex-wrap: wrap; gap: .75rem; margin-left: auto; }

.franja .btn--claro { background: var(--acento-texto); color: var(--acento); }
.franja .btn--claro:hover { background: var(--acento-texto); color: var(--acento); opacity: .85; }
.franja .btn--fantasma { border-color: currentColor; color: inherit; }
.franja .btn--fantasma:hover { color: inherit; background: rgb(128 128 128 / 25%); }

/* --- Piezas de composición ---------------------------------------------
   Reemplazan los atributos style en línea, para que el CSP pueda prohibir
   estilos incrustados y la cascada quede en un solo sitio.
   ---------------------------------------------------------------------- */

/* Titulo de pagina y de seccion: versalita y linea comprimida. La caja
   normal se reserva para nombres de equipo, donde la mayuscula estorba
   la lectura del modelo. */
.titulo-pagina {
  font-size: clamp(2.25rem, 6vw, 4rem);
  line-height: .92;
  text-transform: uppercase;
  margin-bottom: 1.25rem;
}

.titulo-seccion {
  font-size: clamp(1.75rem, 4vw, 3rem);
  line-height: .95;
  text-transform: uppercase;
  margin-bottom: .75rem;
}
.titulo-bloque { font-size: 1.4rem; margin-bottom: 1.25rem; }

.plomo--espaciado { margin-bottom: clamp(2.5rem, 6vw, 3.5rem); }
.plomo--grande { font-size: 1.125rem; }
.separa-familias { margin-bottom: 2.5rem; }
.cifras--separadas { margin-bottom: clamp(2.5rem, 6vw, 4rem); }
.chips--derecha { margin-left: auto; }
.seccion--cabecera { padding-bottom: 0; }
.seccion--continua { padding-top: 2.5rem; }
.via__valor--direccion { font-size: .9375rem; line-height: 1.5; font-weight: 700; }

/* El campo trampa antispam no debe verse ni recibir foco. */
.trampa {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* --- Salto de accesibilidad -------------------------------------------- */

.salto {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--acento);
  color: var(--acento-texto);
  padding: .6rem 1rem;
  z-index: 100;
  border-radius: 0 0 var(--radio) 0;
}

.salto:focus { left: 0; }

/* --- Adaptación a pantallas menores ------------------------------------ */

@media (max-width: 980px) {
  /* La barra lateral pasa arriba y en horizontal: en pantalla estrecha no
     hay sitio para una columna fija, pero el salto entre familias se conserva. */
  .catalogo-cuerpo { grid-template-columns: 1fr; }

  /* min-width:0 no es decorativo: sin el, el <aside> es un hijo de rejilla que
     no puede encogerse por debajo del contenido de la tira de familias (seis
     columnas de 180px = 1080px). El aside se estiraba a 1087px en una pantalla
     de 380 y la mitad de las familias quedaban fuera, sin forma de alcanzarlas
     porque quien desbordaba era el contenedor, no su contenido. */
  .lado { position: static; top: auto; min-width: 0; }
  .lado__lista {
    grid-auto-flow: column;
    grid-auto-columns: minmax(180px, 1fr);
    overflow-x: auto;
    overscroll-behavior-x: contain;
    gap: 1px;
  }
  .familia-lado { border-left: none; border-top: 2px solid transparent; }
  .familia-lado:hover { border-left-color: transparent; border-top-color: var(--acento); }

  /* Los filtros pasan a una sola fila que se desliza. Envueltos ocuparían
     cuatro líneas de 44px y la barra fija se comería media pantalla. */
  .filtros {
    flex-wrap: nowrap;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
    padding-bottom: 2px;
  }
  .filtros::-webkit-scrollbar { display: none; }
  .filtro { flex: 0 0 auto; }

  :root { --barra-catalogo: 135px; }   /* medido: buscador + una fila */
}

@media (max-width: 880px) {
  .hero__rejilla,
  .contacto-rejilla { grid-template-columns: 1fr; }
  .hero .placa { order: -1; aspect-ratio: 16 / 10; }
  .pie__rejilla { grid-template-columns: 1fr 1fr; }
  .franja__acciones { margin-left: 0; }
}

@media (max-width: 640px) {
  .pie__rejilla { grid-template-columns: 1fr; }

  /* 16/9 en un móvil son 200px de alto: un mapa en el que no cabe ni la
     manzana. Se le da más altura que ancho, que es como se mira un plano
     de calles en la mano. */
  .mapa--cargado { aspect-ratio: 3 / 4; }

  .pie a { min-height: var(--toque); }
  .marca__sub { display: none; }
  .grupo__cabeza { align-items: flex-start; flex-direction: column; gap: .5rem; }

  /* La navegación no se esconde ni se cambia por un desplegable: son los
     mismos enlaces, que se pueden abrir en otra pestaña, copiar y que el
     lector de pantalla anuncia como enlaces. Un <select> que navega no permite
     nada de eso.

     Los cuatro no caben junto al logo en 380px, así que pasan a su propia
     fila. Para que eso no cueste una cabecera fija de 100px, en móvil la
     cabecera deja de ser fija: en el catálogo la barra de filtros ya cumple
     esa función y con las dos encima quedaba un tercio de pantalla ocupado. */
  .cabecera { position: static; }
  .barra-catalogo { top: 0; }
  :root { --cabecera: 0px; }

  .cabecera__fila { flex-wrap: wrap; gap: .75rem; row-gap: 0; }

  /* Sin `order`, la navegación al 100% empuja el botón de tema a una tercera
     fila para él solo. Va arriba, a la derecha del logo. */
  .marca { order: 1; }
  .tema { order: 2; margin-left: auto; }

  .nav {
    order: 3;
    flex-basis: 100%;
    min-width: 0;
    margin-left: 0;
    border-top: 1px solid var(--borde);
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
  }

  .nav::-webkit-scrollbar { display: none; }

  .nav ul { gap: .25rem; justify-content: space-between; }

  .nav a {
    display: inline-flex;
    align-items: center;
    min-height: var(--toque);
    padding: 0 .35rem;
  }
}

@media print {
  .cabecera, .franja, .filtros, .tema, .salto { display: none; }
  body { background: #fff; color: #000; }
  .especificaciones[open] summary::after { content: ''; }
}
