/* ==========================================================================
   DCB Ingeniería y Consultoría S.A.S. — hoja de estilos única
   Réplica estática del sitio dcbingenieria.com

   Paleta y tipografías tomadas del sitio original (Elementor/Astra):
   rojo #A11C1B · oscuro #2B2B2B · texto #4B4F58 · Montserrat + Roboto
   Contenedor 1200px.

   Índice
   1. Variables y reset
   2. Tipografía base
   3. Utilidades y contenedores
   4. Botones
   5. Cabecera y navegación
   6. Portada (hero)
   7. Secciones de contenido
   8. Tarjetas de servicio
   9. Tarjetas de tecnología / metodología
  10. Listas técnicas
  11. Galerías y proyectos
  12. Carrusel de clientes
  13. Llamado a la acción
  14. Formulario de contacto
  15. Pie de página
  16. Botón flotante de WhatsApp
  17. Responsive
  ========================================================================== */

/* ------------------------------------------------ 1. Variables y reset --- */
:root {
  --rojo: #a11c1b;
  --rojo-oscuro: #8a0c0e;
  --rojo-hover: #7d1615;
  --oscuro: #2b2b2b;
  --oscuro-2: #1e1e1e;
  --negro: #121212;
  --texto: #4b4f58;
  --texto-fuerte: #2b2b2b;
  --gris-suave: #f5f5f5;
  --borde: #e5e5e5;
  --blanco: #fff;

  --titulo: "Montserrat", "Segoe UI", system-ui, sans-serif;
  --cuerpo: "Roboto", "Segoe UI", system-ui, sans-serif;

  --ancho: 1200px;
  --radio: 14px;
  --radio-lg: 28px;
  --sombra: 0 4px 18px rgb(0 0 0 / 8%);
  --sombra-fuerte: 0 12px 34px rgb(0 0 0 / 16%);
  --transicion: 0.25s ease;
}

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

html { scroll-behavior: smooth; }

body {
  margin: 0;
  font-family: var(--cuerpo);
  font-size: 17px;
  line-height: 1.7;
  color: var(--texto);
  background: var(--blanco);
  -webkit-font-smoothing: antialiased;
}

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

a { color: var(--rojo); text-decoration: none; transition: color var(--transicion); }
a:hover { color: var(--rojo-hover); }

/* Foco visible: el sitio original lo eliminaba y dejaba la web
   inmanejable con teclado. */
:focus-visible {
  outline: 3px solid var(--rojo);
  outline-offset: 3px;
  border-radius: 4px;
}

/* Enlace de salto para lectores de pantalla y navegación con teclado */
.salto-contenido {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 999;
  padding: 12px 22px;
  background: var(--rojo);
  color: #fff;
  font-family: var(--titulo);
  font-weight: 600;
}
.salto-contenido:focus {
  left: 12px;
  top: 12px;
  color: #fff;
}

/* ------------------------------------------------- 2. Tipografía base --- */
h1, h2, h3, h4, h5, h6 {
  font-family: var(--titulo);
  color: var(--texto-fuerte);
  line-height: 1.25;
  margin: 0 0 0.6em;
  font-weight: 600;
}

h1 { font-size: clamp(2rem, 4.4vw, 3.1rem); font-weight: 700; }
h2 { font-size: clamp(1.6rem, 3vw, 2.3rem); }
h3 { font-size: clamp(1.25rem, 2vw, 1.55rem); }
h4 { font-size: 1.2rem; }
h5 { font-size: 1.08rem; font-weight: 500; }

p { margin: 0 0 1.15em; }
p:last-child { margin-bottom: 0; }

strong { color: var(--texto-fuerte); font-weight: 600; }

/* ------------------------------------- 3. Utilidades y contenedores ------ */
.contenedor {
  width: 100%;
  max-width: var(--ancho);
  margin-inline: auto;
  padding-inline: 24px;
}
.contenedor-estrecho { max-width: 860px; }

.seccion { padding: 84px 0; }
.seccion-compacta { padding: 56px 0; }
.seccion-gris { background: var(--gris-suave); }
/* En el inicio, todos los fondos van del mismo blanco (sin alternar gris). */
.inicio .seccion-gris { background: var(--blanco); }
/* El inicio sigue el mismo ritmo que el resto del sitio: con 54px el hueco
   entre bloques llegaba a 108 y se leía como un salto en blanco. */
.inicio .seccion { padding: 32px 0; }
/* Páginas de servicio (LiDAR, hidrología, fotogrametría, consultoría): el
   ritmo va a la mitad del habitual, porque cada bloque ya trae su propio
   aire interno y de lo contrario los huecos entre secciones pesan más que
   el contenido. */
.servicio .seccion,
.contacto .seccion { padding: 32px 0; }
.seccion-oscura { background: var(--oscuro); color: #d8dade; }
.seccion-oscura h2,
.seccion-oscura h3,
.seccion-oscura h4 { color: #fff; }

.centrado { text-align: center; }
.solo-lectores {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* Título de sección con filete rojo */
.titulo-seccion { margin-bottom: 14px; }
.titulo-seccion::after {
  content: "";
  display: block;
  width: 68px;
  height: 4px;
  margin-top: 18px;
  background: var(--rojo);
  border-radius: 2px;
}
.centrado .titulo-seccion::after,
.titulo-seccion.centrado::after { margin-inline: auto; }

.entradilla {
  font-family: var(--titulo);
  font-weight: 300;
  font-size: 1.12rem;
  line-height: 1.6;
  max-width: 780px;
}
.centrado .entradilla { margin-inline: auto; }

/* Frase-lema (p. ej. la cita de «¿Quiénes somos?»): en el original aparece
   destacada y por encima del título de la sección. */
.lema {
  color: var(--rojo);
  font-weight: 500;
  font-style: italic;
  margin-bottom: 10px;
}

/* Declaración: frase de cierre de una sección. Va centrada y sin caja a
   propósito. El banner bicolor ya carga bastante peso visual, y cuando los dos
   caen en la misma página se estorban: dos bloques rojo-oscuro seguidos leen
   como un error de maquetación. Esta se apoya solo en el filete y el tamaño. */
.declaracion { margin-top: 54px; }
.declaracion p {
  font-family: var(--titulo);
  font-weight: 600;
  font-size: clamp(1.25rem, 2.6vw, 1.72rem);
  line-height: 1.35;
  color: var(--texto-fuerte);
  max-width: 760px;
  margin: 0 auto 14px;
}
.declaracion p::before {
  content: "";
  display: block;
  width: 68px;
  height: 4px;
  margin: 0 auto 24px;
  background: var(--rojo);
  border-radius: 2px;
}
.declaracion span {
  display: block;
  max-width: 620px;
  margin-inline: auto;
  font-size: 0.98rem;
  color: var(--texto);
}

/* Cifras: fila de datos destacados. El número manda y la etiqueta lo explica,
   así que el contraste de tamaño entre ambos hace todo el trabajo. */
.cifras {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 28px;
}
.cifra { text-align: center; }
.cifra strong {
  display: block;
  font-family: var(--titulo);
  font-weight: 700;
  font-size: clamp(2.1rem, 5vw, 3.1rem);
  line-height: 1;
  color: var(--rojo);
}
.cifra span {
  display: block;
  margin-top: 10px;
  font-size: 0.95rem;
  line-height: 1.4;
}

.rejilla { display: grid; gap: 32px; }
/* Última fila centrada: una rejilla deja las tarjetas sobrantes pegadas a la
   izquierda, y con 5 elementos en 3 columnas ese hueco a la derecha se lee
   como un error. Con flex, la fila incompleta se centra sola. Los anchos son
   los mismos que daría la rejilla de tres columnas. */
.rejilla-centrada {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
}
.rejilla-centrada > * { flex: 0 1 calc((100% - 64px) / 3); }
.rejilla-2 { grid-template-columns: repeat(2, 1fr); }
.rejilla-3 { grid-template-columns: repeat(3, 1fr); }
/* Cuatro en una fila: el hueco se acorta porque a este ancho cada columna ya
   va justa, y la tarjeta con foto pierde algo de alto para no quedar estrecha
   y larga. */
.rejilla-4 { grid-template-columns: repeat(4, 1fr); gap: 22px; }
.rejilla-4 .carta-foto { min-height: 390px; padding: 26px 22px; }
.rejilla-4 .carta-foto h3 { font-size: 1.28rem; }
.rejilla-4 .carta-foto p { font-size: 0.94rem; }
/* El botón conserva el tamaño estándar: aun en la columna más estrecha (1100px)
   le sobran 32px, y así todos los botones del sitio son el mismo. */
.rejilla-media { align-items: center; }

/* ------------------------------------------------------- 4. Botones ----- */
.boton {
  display: inline-block;
  font-family: var(--titulo);
  font-weight: 600;
  font-size: 0.95rem;
  letter-spacing: 0.02em;
  padding: 14px 32px;
  border: 2px solid var(--rojo);
  border-radius: 40px;
  background: var(--rojo);
  color: #fff;
  cursor: pointer;
  transition: background var(--transicion), border-color var(--transicion),
              color var(--transicion), transform var(--transicion);
}
.boton:hover {
  background: var(--rojo-hover);
  border-color: var(--rojo-hover);
  color: #fff;
  transform: translateY(-2px);
}

.boton-borde {
  background: transparent;
  color: var(--rojo);
}
.boton-borde:hover { background: var(--rojo); color: #fff; }

.boton-claro {
  background: #fff;
  border-color: #fff;
  color: var(--rojo);
}
.boton-claro:hover { background: transparent; color: #fff; border-color: #fff; }

/* --------------------------------------- 5. Cabecera y navegación ------- */
.cabecera {
  position: sticky;
  top: 0;
  z-index: 100;
  background: #fff;
  border-bottom: 1px solid var(--borde);
  box-shadow: 0 1px 12px rgb(0 0 0 / 6%);
}
.cabecera-interior {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  min-height: 92px;
  /* El logo es vertical (427×520): a 78px de ancho mide 95 de alto y superaba
     por sí solo el alto de la cabecera, quedando pegado arriba y abajo. Este
     relleno le reserva franja propia por encima y por debajo. */
  padding-block: 12px;
}
.logo { display: flex; align-items: center; flex-shrink: 0; }
.logo img { width: 78px; height: auto; }

.menu-boton {
  display: none;
  width: 46px; height: 46px;
  padding: 0;
  border: 1px solid var(--borde);
  border-radius: 8px;
  background: #fff;
  cursor: pointer;
}
.menu-boton span {
  display: block;
  width: 22px; height: 2px;
  margin: 4px auto;
  background: var(--oscuro);
  transition: transform var(--transicion), opacity var(--transicion);
}
.menu-boton[aria-expanded="true"] span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.menu-boton[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.menu-boton[aria-expanded="true"] span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

.menu, .submenu { list-style: none; margin: 0; padding: 0; }
.menu { display: flex; align-items: center; gap: 4px; }
.menu > li { position: relative; }

.menu a {
  display: block;
  padding: 12px 14px;
  font-family: var(--titulo);
  font-weight: 500;
  font-size: 0.9rem;
  color: var(--texto-fuerte);
  border-radius: 6px;
  white-space: nowrap;
}
.menu a:hover { color: var(--rojo); background: var(--gris-suave); }

/* Página actual: el original no marcaba en qué página estabas */
.menu a[aria-current="page"] { color: var(--rojo); }
.menu a[aria-current="page"]::after {
  content: "";
  display: block;
  height: 2px;
  margin-top: 4px;
  background: var(--rojo);
  border-radius: 2px;
}

/* Submenús: en el original, Topografía, Diseño de vías y Movimientos de
   tierra no estaban en el menú; sólo se llegaba por el pie de página. */
.tiene-submenu > a::before {
  content: "";
  float: right;
  width: 7px; height: 7px;
  margin: 6px 0 0 8px;
  border-right: 2px solid currentcolor;
  border-bottom: 2px solid currentcolor;
  transform: rotate(45deg);
}
.submenu {
  position: absolute;
  top: 100%;
  left: 0;
  min-width: 268px;
  padding: 8px;
  background: #fff;
  border: 1px solid var(--borde);
  border-radius: 12px;
  box-shadow: var(--sombra-fuerte);
  opacity: 0;
  visibility: hidden;
  transform: translateY(8px);
  transition: opacity var(--transicion), transform var(--transicion), visibility var(--transicion);
}
.tiene-submenu:hover > .submenu,
.tiene-submenu:focus-within > .submenu {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}
.submenu a { font-weight: 400; padding: 10px 14px; }

/* Segundo nivel: Cartografía y Consultoría técnica cuelgan de «Líneas de
   servicios», y sus servicios cuelgan a su vez de ellas.

   El panel hijo se abre hacia la IZQUIERDA. El menú está anclado a la derecha
   de la cabecera, así que a la derecha del segundo nivel no queda espacio: con
   etiquetas largas el tercer nivel se salía de la ventana y aparecía barra de
   desplazamiento horizontal. Hacia la izquierda siempre cabe. */
.submenu li { position: relative; }
.submenu .tiene-submenu > a::before {
  float: left;                 /* la flecha se va al lado por el que abre */
  margin: 6px 8px 0 0;
  transform: rotate(135deg);   /* y apunta hacia la izquierda */
}
/* 9px = los 8 de relleno del panel padre más 1 de borde: así el hijo queda
   pegado al borde del padre, sin taparlo ni dejar escalón. */
.submenu-anidado {
  top: -9px;
  left: auto;
  right: 100%;
  margin-right: 9px;
  transform: translateX(8px);
}
/* Puente invisible sobre esos 9px: sin él, el puntero sale del <li> al pasar
   del padre al hijo y el submenú se cierra a mitad de camino. */
.submenu-anidado::before {
  content: "";
  position: absolute;
  top: 0;
  left: 100%;
  width: 13px;
  height: 100%;
}
.submenu .tiene-submenu:hover > .submenu-anidado,
.submenu .tiene-submenu:focus-within > .submenu-anidado { transform: translateX(0); }

/* Accesos de cabecera: redes y botón de chat, a la derecha del menú. */
.navegacion { display: flex; align-items: center; gap: 20px; }
.cabecera-acciones { display: flex; align-items: center; gap: 9px; }
.icono-cabecera {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px; height: 34px;
  border: 1px solid var(--borde);
  border-radius: 8px;
  color: var(--texto-fuerte);
  transition: background var(--transicion), border-color var(--transicion), color var(--transicion);
}
.icono-cabecera:hover { background: var(--rojo); border-color: var(--rojo); color: #fff; }
.icono-cabecera svg { width: 17px; height: 17px; fill: currentcolor; }
.boton-chat { padding: 10px 26px; font-size: 0.88rem; }

/* ---------------------------------------------------- 6. Portada -------- */
.portada {
  position: relative;
  display: flex;
  align-items: center;
  min-height: 400px;
  padding: 76px 0;
  /* Degradado de marca. Es el mismo que usa la llamada a la acción, para que
     las dos bandas rojas del sitio compartan exactamente el mismo fondo. */
  background: linear-gradient(120deg, var(--rojo-oscuro) 0%, var(--rojo) 62%, #6d0f10 100%);
  color: #fff;
  overflow: hidden;
}
/* Veladura radial que da profundidad sin ensuciar: nada de fotografías ni
   siluetas detrás del texto. */
.portada::after,
.cta::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at 78% 30%, rgb(0 0 0 / 22%) 0%, transparent 60%);
  pointer-events: none;
}
.portada .contenedor { position: relative; z-index: 1; }
.portada h1 { color: #fff; margin-bottom: 18px; }
.portada .entradilla { color: #eceef1; margin-bottom: 32px; }
.portada .rotulo {
  display: inline-block;
  margin-bottom: 20px;
  padding: 7px 18px;
  border: 1px solid rgb(255 255 255 / 35%);
  border-radius: 40px;
  font-family: var(--titulo);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #fff;
}

/* Hero a dos columnas, como el original: texto a la izquierda y el modelo
   digital 3D del terreno (malla de colores por cota) a la derecha. */
.portada-grid {
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  gap: 40px;
  align-items: center;
  width: 100%;
}
.portada-texto { position: relative; z-index: 1; }
.portada-media { position: relative; z-index: 1; }
/* Halo detrás del modelo. El rojo de la portada es plano y la malla de color
   quedaba pegada a él; este resplandor abre un hueco de luz y la despega. */
.portada-media::before {
  content: "";
  position: absolute;
  left: 50%; top: 50%;
  width: 116%;
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  background: radial-gradient(circle,
    rgb(255 255 255 / 15%) 0%,
    rgb(255 255 255 / 6%) 40%,
    transparent 68%);
  z-index: -1;
  pointer-events: none;
}
.portada-media img {
  width: 100%;
  height: auto;
  /* Dos sombras en vez de una: la corta y densa asienta el modelo sobre el
     fondo y la ancha y difusa le da la altura. Se usa «drop-shadow» y no
     «box-shadow» porque la imagen tiene fondo transparente y la sombra debe
     seguir su silueta, no un rectángulo. */
  filter: drop-shadow(0 10px 18px rgb(0 0 0 / 45%))
          drop-shadow(0 34px 62px rgb(0 0 0 / 34%))
          saturate(1.08) contrast(1.04);
}

/* Dos llamadas en el hero: una lleva al catálogo de servicios y la otra al
   contacto. En pantalla estrecha se apilan a lo ancho. */
.portada-botones {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin-bottom: 0;
}

/* Botón del hero. Era translúcido, con texto blanco sobre un degradado que
   dejaba el contraste entre 3,75 y 4,47:1 según la altura de la pastilla; por
   debajo del 4,5:1 que pide la WCAG para texto de este tamaño. Con fondo
   blanco y texto rojo el contraste sube muy por encima del mínimo y además
   destaca más sobre el rojo de la portada. */
.boton-hero {
  background: #fff;
  border-color: #fff;
  color: var(--rojo);
}
.boton-hero:hover {
  background: transparent;
  border-color: #fff;
  color: #fff;
}
/* La segunda llamada del hero queda en segundo plano: contorno claro sobre el
   rojo, que también supera el mínimo de contraste. */
.boton-hero.boton-hero-alterno {
  background: transparent;
  border-color: rgb(255 255 255 / 75%);
  color: #fff;
}
.boton-hero.boton-hero-alterno:hover {
  background: #fff;
  border-color: #fff;
  color: var(--rojo);
}

/* Cabecera de página interior: en el original era un JPEG de 1600×1113
   con un color plano. Aquí es CSS. */
.portada-interior {
  min-height: 300px;
  padding: 76px 0;
}
.portada-interior h1 { margin-bottom: 10px; }

.miga {
  font-size: 0.85rem;
  font-family: var(--titulo);
  color: rgb(255 255 255 / 78%);
  margin-bottom: 14px;
}
.miga a { color: rgb(255 255 255 / 78%); }
.miga a:hover { color: #fff; }
.miga span { margin: 0 6px; }

/* -------------------------------------- 7. Secciones de contenido ------- */
.bloque-media {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 54px;
  align-items: center;
}
.bloque-media img { border-radius: var(--radio); box-shadow: var(--sombra); }
.bloque-media.invertido .bloque-texto { order: 2; }

.par-imagenes { display: grid; grid-template-columns: 1fr 1fr; gap: 22px; }
.par-imagenes img { border-radius: var(--radio); box-shadow: var(--sombra); }

/* Columna de figura de «¿Quiénes somos?»: el plano de curvas de nivel con la
   cita debajo, centrada (como el original). El plano es un dibujo de líneas,
   así que va sin marco ni sombra. */
.bloque-figura img { box-shadow: none; border-radius: 0; }
.bloque-figura .lema { text-align: center; margin-top: 20px; margin-bottom: 0; }

.figura { margin: 0; }
/* Las imágenes más estrechas que su columna se centran en lugar de quedar
   pegadas al borde (algunos originales son pequeños y no conviene ampliarlos). */
.figura img { border-radius: var(--radio); box-shadow: var(--sombra); margin-inline: auto; }

/* Figura a la altura del texto: la fila se estira y la imagen ocupa justo el
   alto de la columna contigua, así ambas empiezan y terminan a la misma
   altura. Útil cuando el original es vertical y, a su tamaño natural, se
   desborda muy por debajo del último párrafo. */
.bloque-media.bloque-parejo { align-items: stretch; }
/* La imagen va fuera del flujo: si midiera dentro, sería ella la que fijaría
   el alto de la fila (una foto vertical a todo el ancho de su columna mide
   más que el texto) y volveríamos a tener un bloque descompensado. Sacándola,
   manda el texto y la foto se recorta a esa altura. */
.bloque-parejo .figura {
  position: relative;
  min-height: 340px;
  border-radius: var(--radio);
  overflow: hidden;
  box-shadow: var(--sombra);
}
.bloque-parejo .figura img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  border-radius: 0;
  box-shadow: none;
}

/* El mapa es un diagrama sobre fondo transparente: sin marco ni sombra, que
   ahí marcarían un recuadro inexistente. */
.figura-mapa img {
  border-radius: 0;
  box-shadow: none;
  max-height: 460px;
  width: auto;
  margin-inline: auto;
}

/* Figura apaisada: fija la proporción horizontal y recorta al centro, para que
   el bloque conserve el equilibrio con la columna de texto aunque la foto de
   origen sea vertical o venga en otra relación. */
.figura-horizontal img {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  object-position: center;
}
.figura figcaption {
  margin-top: 10px;
  font-size: 0.85rem;
  color: #6d717a;
  font-style: italic;
}

/* ------------------------------------- 8. Tarjetas de servicio ---------- */
/* En el sitio original estas dos tarjetas eran una sola imagen JPEG con el
   texto incrustado: invisible para Google y para lectores de pantalla.
   Aquí están reconstruidas con HTML real. */
.tarjeta-servicio {
  display: grid;
  /* La columna de la foto mide media circunferencia más un respiro: la otra
     mitad del círculo vuela por fuera del panel. */
  grid-template-columns: 172px 1fr;
  gap: 0;
  align-items: center;
  background: var(--oscuro);
  /* El lado de la foto va a escuadra y los otros dos redondeados. El borde
     recto pasa exactamente por el diámetro vertical del círculo y lo toca en
     sus puntos más alto y más bajo; con la esquina redondeada, en cambio, el
     panel se curvaba justo ahí y dejaba la punta del círculo al aire. */
  border-radius: 0 var(--radio-lg) var(--radio-lg) 0;
  /* El panel no recorta: la foto circular sobresale por fuera y se ve
     completa, en lugar de quedar cortada por la esquina redondeada. */
  overflow: visible;
  box-shadow: var(--sombra-fuerte);
  /* El alto del panel es el diámetro del círculo, para que ambos empiecen y
     terminen a la misma altura y no asome gris por encima ni por debajo. */
  min-height: 300px;
  /* El panel cede el espacio que necesita el medio círculo que vuela fuera,
     de modo que este quede alineado con el borde del contenedor y no se salga
     de la pantalla. */
  margin-left: 150px;
}
.tarjeta-servicio.invertida {
  margin-left: 0; margin-right: 150px;
  border-radius: var(--radio-lg) 0 0 var(--radio-lg);
}
.tarjeta-servicio.invertida { grid-template-columns: 1fr 172px; }
.tarjeta-servicio.invertida .tarjeta-foto { order: 2; }

.tarjeta-foto {
  width: 300px;
  height: 300px;
  border-radius: 50%;
  overflow: hidden;
  /* Se desplaza medio diámetro: el borde del panel pasa justo por el centro
     del círculo, así que sus esquinas caen exactamente en los extremos
     superior e inferior de la circunferencia y no asoman por fuera. */
  margin: 0 0 0 -150px;
  /* Sin anillo exterior: los 6px que añadía hacían que el círculo midiera
     312px contra un panel de 300 y asomara por arriba y por abajo. */
  position: relative;
  z-index: 1;
}
/* En la invertida hay que anclar la foto al final de su celda: con un ancho
   fijo, el margen negativo por sí solo no la empuja hacia fuera. */
.tarjeta-servicio.invertida .tarjeta-foto {
  justify-self: end;
  margin: 0 -150px 0 0;
}
.tarjeta-foto img { width: 100%; height: 100%; object-fit: cover; }

.tarjeta-cuerpo { padding: 40px 44px; }
/* El título va en h2 o en h3 según el nivel que le corresponda en cada
   página (h3 en el inicio, h2 en Líneas de servicios, donde encabeza la
   sección). Ambos deben ir en blanco: sobre el fondo oscuro de la tarjeta,
   el color de titular por defecto es del mismo tono y se vuelve ilegible. */
.tarjeta-cuerpo h2,
.tarjeta-cuerpo h3 { color: #fff; font-size: 1.7rem; font-weight: 700; }
.tarjeta-cuerpo p { color: #cfd2d7; margin-bottom: 22px; }

/* ------------------------- 9. Tarjetas de tecnología / metodología ------ */
.tarjeta-tecnologia {
  position: relative;
  border-radius: var(--radio-lg);
  overflow: hidden;
  box-shadow: var(--sombra);
  aspect-ratio: 6 / 5;
}
.tarjeta-tecnologia img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.5s ease;
}
.tarjeta-tecnologia:hover img { transform: scale(1.05); }
.tarjeta-tecnologia .rotulo-foto {
  position: absolute;
  left: 0;
  bottom: 22px;
  padding: 9px 26px 9px 20px;
  border-radius: 0 40px 40px 0;
  background: var(--rojo);
  color: #fff;
  font-family: var(--titulo);
  font-weight: 600;
  font-size: 1rem;
}

/* Tarjeta simple con icono + texto */
.tarjeta {
  padding: 34px 30px;
  background: #fff;
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  box-shadow: var(--sombra);
  height: 100%;
  transition: transform var(--transicion), box-shadow var(--transicion);
}
.tarjeta:hover { transform: translateY(-4px); box-shadow: var(--sombra-fuerte); }
.tarjeta h3 { font-size: 1.22rem; margin-bottom: 10px; }
.tarjeta p { font-size: 0.97rem; }
.tarjeta .numero {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 46px; height: 46px;
  margin-bottom: 18px;
  border-radius: 50%;
  background: var(--rojo);
  color: #fff;
  font-family: var(--titulo);
  font-weight: 700;
}

/* Título en pastilla oscura (p. ej. «Soluciones precisas» en Cartografía) */
.titulo-pastilla {
  display: inline-block;
  margin: 0 0 22px;
  padding: 16px 46px;
  background: var(--oscuro);
  color: #fff;
  font-family: var(--titulo);
  font-weight: 700;
  font-size: clamp(1.3rem, 2.6vw, 1.9rem);
  border-radius: 60px;
}

/* Tarjeta con foto de fondo, overlay y botón (servicios de cartografía) */
.carta-foto {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  min-height: 430px;
  padding: 32px 30px;
  border-radius: 20px;
  overflow: hidden;
  color: #fff;
  background-color: var(--oscuro);
  background-size: cover;
  background-position: center;
  box-shadow: var(--sombra);
}
.carta-foto::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgb(0 0 0 / 10%) 0%, rgb(0 0 0 / 55%) 55%, rgb(0 0 0 / 85%) 100%);
}
.carta-foto > * { position: relative; z-index: 1; }
.carta-foto h3 { color: #fff; font-size: 1.55rem; margin: 0 0 12px; }
.carta-foto p { color: #e9e9e9; margin: 0 0 22px; }
.carta-foto .boton { align-self: flex-start; }

/* Textos generales justificados (con guionado automático para evitar
   espacios grandes). El idioma es-CO del <html> habilita el corte de sílabas. */
.bloque-texto p,
.tarjeta p,
.carta-foto p,
.contenedor-estrecho p { text-align: justify; hyphens: auto; }

/* «Soluciones precisas»: dos paneles equilibrados. La imagen llena la altura de
   su columna (queda a la par del texto) y comparte con la pastilla un lenguaje
   redondeado con sombra, para una composición más armónica. */
.bloque-armonico { align-items: center; gap: 56px; }
.bloque-armonico .titulo-pastilla { box-shadow: 0 10px 26px rgb(0 0 0 / 18%); }
.bloque-armonico .figura { margin: 0; }
.bloque-armonico .figura img {
  width: 100%;
  max-height: 440px;
  object-fit: cover;
  border-radius: 28px;
  box-shadow: var(--sombra-fuerte);
}
@media (max-width: 900px) {
  .bloque-armonico { gap: 32px; }
  .bloque-armonico .figura img { max-height: 340px; }
}

/* --------------------------------------------- 10. Listas técnicas ------ */
.lista-check { list-style: none; margin: 0 0 1.2em; padding: 0; }
/* Cuando la lista cierra su bloque, ese margen inferior ya no separa de nada:
   se suma al relleno de la sección y engorda el hueco con la sección
   siguiente. El último elemento nunca arrastra margen. */
.lista-check:last-child,
.bloque-texto > :last-child,
.contenedor > :last-child { margin-bottom: 0; }
.lista-check li {
  position: relative;
  padding: 7px 0 7px 34px;
}
.lista-check li::before {
  content: "";
  position: absolute;
  left: 4px;
  top: 16px;
  width: 8px; height: 14px;
  border-right: 3px solid var(--rojo);
  border-bottom: 3px solid var(--rojo);
  transform: rotate(45deg);
}
.seccion-oscura .lista-check li::before {
  border-color: #e8615f;
}

/* ---------------------------------------- 11. Galerías y proyectos ------ */
.proyecto {
  background: #fff;
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  overflow: hidden;
  box-shadow: var(--sombra);
  display: flex;
  flex-direction: column;
}
.proyecto img { width: 100%; aspect-ratio: 16 / 9; object-fit: cover; }
.proyecto-cuerpo { padding: 22px 24px; }
.proyecto-cuerpo h3 { font-size: 1.15rem; margin-bottom: 4px; }
.proyecto-cuerpo .dato {
  font-family: var(--titulo);
  font-size: 0.88rem;
  color: var(--rojo);
  font-weight: 600;
}

/* ------------------------------------- 12. Carrusel de clientes --------- */
/* Encabezado de clientes en banner bicolor (bloque rojo + bloque oscuro),
   igual que el sitio original. */
.banner-clientes {
  display: grid;
  grid-template-columns: 1fr 1fr;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: var(--sombra);
}
.banner-clientes-rojo,
.banner-clientes-oscuro {
  display: flex;
  align-items: center;
  padding: 22px 36px;
  min-height: 90px;
}
.banner-clientes-rojo { background: var(--rojo); }
.banner-clientes-oscuro { background: var(--oscuro); }
.banner-clientes-rojo h2 {
  margin: 0;
  color: #fff;
  font-size: clamp(1.2rem, 2.4vw, 1.6rem);
}
.banner-clientes-oscuro p {
  margin: 0;
  color: #c9ccd2;
  font-family: var(--titulo);
  font-weight: 300;
  font-size: 1.02rem;
  line-height: 1.4;
}

.clientes {
  position: relative;
  overflow: hidden;
  /* 24px: el logo mide 76 y al ampliarse llega a 106; con este relleno la
     pista alcanza 124 de alto y el aumento cabe entero. */
  padding: 24px 0;
  /* difuminado en los bordes */
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.clientes-pista {
  display: flex;
  align-items: center;
  width: max-content;
  animation: desfile 40s linear infinite;
}
.clientes:hover .clientes-pista { animation-play-state: paused; }
/* Los logotipos van siempre a color. Al pasar el ratón crecen un 40%; el
   relleno de la pista está calculado para que ese aumento quepa sin que
   «overflow: hidden» los recorte por arriba o por abajo. */
.clientes-pista img {
  width: auto;
  height: 76px;
  margin: 0 46px;
  object-fit: contain;
  transition: transform var(--transicion);
}
.clientes-pista img:hover { transform: scale(1.4); }

@keyframes desfile {
  from { transform: translateX(0); }
  to   { transform: translateX(-33.3333%); }
}

/* ------------------------------------------ 13. Llamado a la acción ----- */
/* Mismo degradado que las bandas de título. Antes llevaba una fotografía de
   fondo que se colaba como siluetas detrás del texto; ya no hay ninguna. */
.cta {
  position: relative;
  padding: 78px 0;
  background: linear-gradient(120deg, var(--rojo-oscuro) 0%, var(--rojo) 62%, #6d0f10 100%);
  color: #fff;
  text-align: center;
  overflow: hidden;
}
.cta .contenedor { position: relative; z-index: 1; }
.cta h2 { color: #fff; }
.cta p { color: #e6e8ea; max-width: 620px; margin-inline: auto; }
.cta .boton { margin-top: 12px; }

/* --------------------------------------- 14. Formulario de contacto ----- */
.caja-contacto {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 54px;
  align-items: start;
}

.foto-contacto { border-radius: 14px; margin-top: 8px; }

.datos-contacto { list-style: none; margin: 0 0 28px; padding: 0; }
.datos-contacto li {
  display: flex;
  gap: 14px;
  padding: 14px 0;
  border-bottom: 1px solid var(--borde);
}
.datos-contacto li:last-child { border-bottom: 0; }
.datos-contacto .etiqueta {
  font-family: var(--titulo);
  font-weight: 600;
  color: var(--texto-fuerte);
  min-width: 104px;
}

.formulario { display: grid; gap: 18px; }
.campo-trampa {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  padding: 0 !important;
  margin: -1px !important;
  overflow: hidden !important;
  clip: rect(0, 0, 0, 0) !important;
  white-space: nowrap !important;
  border: 0 !important;
}
.campo { display: grid; gap: 7px; }
.campo-doble { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }

/* El formulario ya separa sus filas con «gap»; los márgenes que traen los <p>
   se sumaban a ese hueco y, como el último no lo lleva, las dos columnas de
   «campo-doble» dejaban de cuadrar: el campo sin margen se estiraba para
   igualar la altura de la fila y con él crecían su etiqueta y su casilla. */
.formulario > *,
.campo-doble > * { margin: 0; }
.campo { align-content: start; }

.formulario label {
  font-family: var(--titulo);
  font-weight: 500;
  font-size: 0.92rem;
  color: var(--texto-fuerte);
}
.formulario .obligatorio { color: var(--rojo); }

.formulario input,
.formulario textarea,
.formulario select {
  width: 100%;
  padding: 13px 15px;
  font-family: var(--cuerpo);
  font-size: 1rem;
  color: var(--texto-fuerte);
  background: #fff;
  border: 1px solid #c8ccd2;
  border-radius: 8px;
  transition: border-color var(--transicion), box-shadow var(--transicion);
}
.formulario input:focus,
.formulario textarea:focus,
.formulario select:focus {
  outline: none;
  border-color: var(--rojo);
  box-shadow: 0 0 0 3px rgb(161 28 27 / 15%);
}
.formulario textarea { min-height: 148px; resize: vertical; }

.ayuda { font-size: 0.84rem; color: #6d717a; }

/* Datos de la empresa en banda propia: junto a la foto competían con el
   formulario por la misma columna y estrechaban los campos. En una fila de
   cuatro se leen de un vistazo y el formulario se queda con todo el ancho. */
.datos-contacto-fila {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 30px;
  margin: 0;
}
.datos-contacto-fila li {
  flex-direction: column;
  align-items: flex-start;
  gap: 5px;
  padding: 2px 0 2px 18px;
  border-bottom: 0;
  border-left: 3px solid var(--rojo);
}
.datos-contacto-fila .etiqueta {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  font-size: 0.85rem;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: #6d717a;
}
/* Iconos de la banda: trazo del mismo grosor y caja cuadrada para que los
   cuatro rótulos arranquen a la misma altura. El de WhatsApp es macizo
   —es su logotipo, no un pictograma— y por eso va sin trazo. */
.icono-dato {
  flex-shrink: 0;
  width: 19px;
  height: 19px;
  color: var(--rojo);
}
.icono-wa { fill: currentColor; stroke: none; }
/* El enlace a WhatsApp cuelga del teléfono: mismo dato, distinto canal. */
.datos-contacto-fila .dato-secundario {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin-top: 4px;
  font-size: 0.9rem;
}
.datos-contacto-fila .dato-secundario .icono-dato { width: 16px; height: 16px; }

/* Casilla de autorización: la ley pide consentimiento previo, expreso e
   informado, así que va sin marcar de origen y el envío no procede sin ella. */
.campo-consentimiento {
  display: flex;
  align-items: flex-start;
  gap: 11px;
}
.campo-consentimiento input {
  flex-shrink: 0;
  width: 18px;
  height: 18px;
  margin-top: 3px;
  accent-color: var(--rojo);
  cursor: pointer;
}
.campo-consentimiento label {
  font-family: var(--cuerpo);
  font-size: 0.9rem;
  line-height: 1.5;
  color: var(--texto);
  cursor: pointer;
}

.aviso-formulario {
  padding: 14px 18px;
  border-left: 4px solid var(--rojo);
  background: var(--gris-suave);
  border-radius: 0 8px 8px 0;
  font-size: 0.9rem;
}

/* Contacto del inicio (opción 2): la foto va como columna alta a la izquierda
   y los datos + formulario juntos a la derecha. Al ser retrato, la foto llena
   su columna casi sin recorte. */
.contacto-foto { margin: 0; }

/* La misma composición sirve para el bloque de contacto del inicio y para la
   página de contacto: foto alta a la izquierda, datos y formulario juntos a
   la derecha. */
@media (min-width: 901px) {
  .inicio .caja-contacto,
  .contacto .caja-contacto {
    grid-template-columns: 0.82fr 1.18fr;
    align-items: stretch;
    gap: 44px;
  }
  .inicio .contacto-foto,
  .contacto .contacto-foto { height: 100%; }
  .inicio .contacto-foto .foto-contacto,
  .contacto .contacto-foto .foto-contacto {
    width: 100%;
    height: 100%;
    min-height: 520px;
    object-fit: cover;
    object-position: center;
    margin-top: 0;
  }
}

/* En móvil, la foto (completa) se muestra al final del bloque de contacto. */
@media (max-width: 900px) {
  .inicio .contacto-foto,
  .contacto .contacto-foto { order: 2; margin-top: 6px; }
}

/* --------------------------------------------- 15. Pie de página -------- */
.pie {
  background: var(--oscuro-2);
  color: #b9bcc2;
  font-size: 0.95rem;
}
.pie-marca {
  padding: 34px 0;
  text-align: center;
  border-bottom: 1px solid rgb(255 255 255 / 8%);
}
.pie-marca img { width: 96px; margin-inline: auto; }

/* El ancho de cada columna sigue a su contenido: la marca lleva un párrafo y
   necesita espacio; «Servicios» son dos enlaces cortos y con una columna
   ancha quedaba medio vacía; contacto necesita lo justo para que el correo
   no se parta. */
.pie-cuerpo {
  display: grid;
  grid-template-columns: 1.5fr 0.8fr 1.1fr;
  gap: 48px;
  padding: 52px 0;
}
.pie h2, .pie h3 {
  font-size: 1.05rem;
  color: #fff;
  margin-bottom: 16px;
  letter-spacing: 0.02em;
}
.pie ul { list-style: none; margin: 0; padding: 0; }
.pie li { padding: 5px 0; }
.pie a { color: #b9bcc2; }
.pie a:hover { color: #fff; }
.pie .dato-pie { display: block; }
.pie .dato-pie .etiqueta {
  display: block;
  font-family: var(--titulo);
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: #85888e;
}

.redes { display: flex; gap: 12px; margin-top: 16px; }
.redes a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 42px; height: 42px;
  border: 1px solid rgb(255 255 255 / 18%);
  border-radius: 50%;
  transition: background var(--transicion), border-color var(--transicion);
}
.redes a:hover { background: var(--rojo); border-color: var(--rojo); }
/* El glifo oficial de WhatsApp llena el lienzo de 24×24 de borde a borde,
   sin el margen interno que traía el trazado anterior: por eso se dibuja
   algo más pequeño y así conserva el mismo aire dentro del círculo. */
.redes svg { width: 16px; height: 16px; fill: currentcolor; }

.pie-legal {
  padding: 22px 0;
  border-top: 1px solid rgb(255 255 255 / 8%);
  font-size: 0.86rem;
  color: #8d9096;
  display: flex;
  flex-wrap: wrap;
  gap: 10px 26px;
  justify-content: space-between;
  align-items: center;
}

/* ------------------------------- 16. Botón flotante de WhatsApp --------- */
.whatsapp-flotante {
  position: fixed;
  right: 22px;
  bottom: 22px;
  z-index: 90;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 58px; height: 58px;
  border-radius: 50%;
  background: #25d366;
  color: #fff;
  box-shadow: 0 6px 20px rgb(0 0 0 / 26%);
  transition: transform var(--transicion), background var(--transicion);
}
.whatsapp-flotante:hover { transform: scale(1.08); background: #1ebe5a; color: #fff; }
.whatsapp-flotante svg { width: 26px; height: 26px; fill: currentcolor; }

/* ----------------------------------------------------- 17. Responsive --- */
@media (max-width: 1080px) {
  /* Cuatro columnas no caben con holgura por debajo de este ancho: pasan a dos. */
  .rejilla-4 { grid-template-columns: repeat(2, 1fr); gap: 26px; }
  /* Entre 900 y 1080px el menú sigue siendo horizontal y con el espaciado
     de escritorio se salía 52px por la derecha, arrastrando el botón de chat
     fuera de la pantalla. Aquí se aprieta lo justo para que quepa. */
  .menu a { padding: 12px 6px; font-size: 0.84rem; }
  .menu { gap: 0; }
  .cabecera-acciones { gap: 6px; }
  .boton-chat { padding: 10px 18px; }

  /* Cuatro datos de contacto en fila parten el correo por la mitad. */
  .datos-contacto-fila { grid-template-columns: repeat(2, 1fr); }
  /* Por debajo de este ancho la tarjeta se apila. La composición lateral
     exige que el alto del panel sea exactamente el diámetro del círculo, y
     aquí el texto ya no cabe en esa altura: quedaría gris asomando por encima
     y por debajo, justo lo que se quiso evitar. */
  .tarjeta-servicio,
  .tarjeta-servicio.invertida {
    grid-template-columns: 1fr;
    text-align: center;
    min-height: 0;
    margin: 0;
    /* Apilada, el círculo va centrado dentro del panel y ya no hay ningún
       borde que deba quedar a escuadra contra él. */
    border-radius: var(--radio-lg);
  }
  .tarjeta-foto,
  .tarjeta-servicio.invertida .tarjeta-foto {
    width: 230px; height: 230px;
    margin: 32px auto 0;
    justify-self: center;
    /* Apiladas, todas las tarjetas llevan la foto arriba: alternar el orden
       solo tiene sentido en la composición lateral. */
    order: 0;
  }
}

/* El menú horizontal completo —tres niveles, redes y botón de chat— deja de
   caber por debajo de 1000px: el botón de chat se salía de la pantalla. Ahí
   pasa al panel desplegable, antes que el resto de la maqueta. */
@media (max-width: 1000px) {
  .menu-boton { display: block; }

  .navegacion {
    position: absolute;
    left: 0; right: 0;
    top: 100%;
    display: none;
    padding: 12px 24px 22px;
    background: #fff;
    border-top: 1px solid var(--borde);
    box-shadow: var(--sombra-fuerte);
    max-height: calc(100vh - 119px);
    overflow-y: auto;
  }
  .navegacion.abierto { display: block; }

  .menu { flex-direction: column; align-items: stretch; gap: 0; }
  .menu > li { border-bottom: 1px solid var(--borde); }
  .menu > li:last-child { border-bottom: 0; }
  .menu a { padding: 14px 4px; font-size: 0.98rem; }
  .menu a[aria-current="page"]::after { display: none; }

  .tiene-submenu > a::before { margin-top: 8px; }
  .submenu {
    position: static;
    min-width: 0;
    opacity: 1;
    visibility: visible;
    transform: none;
    border: 0;
    box-shadow: none;
    padding: 0 0 8px 16px;
    background: transparent;
  }
  .submenu a { font-size: 0.92rem; color: var(--texto); }

  /* Los nombres de servicio son largos y en escritorio van en una sola línea.
     En el panel móvil eso los empujaba fuera del ancho disponible: el menú
     medía 454px de contenido dentro de 390 y las etiquetas quedaban cortadas.
     Aquí se les permite partir en varias líneas y se recorta la indentación. */
  .menu a, .submenu a { white-space: normal; overflow-wrap: anywhere; }
  .submenu { padding-left: 12px; }
  .submenu-anidado { padding-left: 12px; }
  .navegacion { overflow-x: hidden; }
  /* El tercer nivel se indenta en lugar de abrirse al costado, así que la
     flecha vuelve a su sitio y apunta hacia abajo, como los demás niveles. */
  .submenu-anidado { margin-left: 0; margin-right: 0; }
  .submenu .tiene-submenu > a::before {
    float: right;
    margin: 8px 0 0 8px;
    transform: rotate(45deg);
  }

  /* Redes y chat: fila centrada bajo el menú desplegado. */
  .cabecera-acciones {
    justify-content: center;
    margin-top: 14px;
    padding-top: 16px;
    border-top: 1px solid var(--borde);
  }
}

@media (max-width: 900px) {
  .seccion { padding: 60px 0; }

  /* Ritmo vertical más corto: en pantalla estrecha, 84px entre secciones se
     leen como un salto en blanco y no como una separación. */
  .servicio .seccion,
  .contacto .seccion { padding: 32px 0; }

  .rejilla-2, .rejilla-3, .rejilla-4, .bloque-media, .caja-contacto,
  .par-imagenes, .campo-doble { grid-template-columns: 1fr; }
  /* Cuatro datos en fila no caben: la dirección partiría en tres líneas. */
  .datos-contacto-fila { grid-template-columns: repeat(2, 1fr); gap: 24px; }
  /* La rejilla centrada es flex, así que se apila cambiando la base. */
  .rejilla-centrada > * { flex-basis: 100%; }
  /* Las cifras bajan a dos por fila: en una columna quedarían demasiado altas
     y perderían la lectura de conjunto. */
  .cifras { grid-template-columns: repeat(2, 1fr); gap: 32px 20px; }
  .bloque-media { gap: 34px; }
  /* Apilado no hay columna que igualar: la imagen vuelve al flujo y recupera
     su alto natural, sin recorte. */
  .bloque-parejo .figura { position: static; min-height: 0; overflow: visible; box-shadow: none; }
  .bloque-parejo .figura img {
    position: static;
    height: auto;
    border-radius: var(--radio);
    box-shadow: var(--sombra);
  }

  /* Las dos columnas de lista se apilan una tras otra: sin el margen de la
     lista ni el hueco de la rejilla, para que se lean como una sola lista
     continua. Con ambos sumaban 51px, contra los 14px que separan a dos
     puntos de la misma lista: parecía un vacío, no una separación. */
  .rejilla-2 > .lista-check { margin-bottom: 0; }
  .rejilla-2:has(> .lista-check) { row-gap: 0; }

  /* Foto de contacto: en móvil se muestra completa pero con alto acotado y
     centrada, para que no ocupe toda la pantalla ni la tape el botón flotante. */
  .foto-contacto {
    max-height: 360px;
    width: auto;
    max-width: 100%;
    margin-inline: auto;
  }
  .bloque-media.invertido .bloque-texto { order: 0; }

  /* Hero: en pantallas medianas/pequeñas el modelo 3D se apila bajo el texto. */
  .portada-grid { grid-template-columns: 1fr; gap: 30px; }
  .portada-media { order: 2; }
  .portada-media img { max-width: 440px; margin-inline: auto; }

  .pie-cuerpo { grid-template-columns: 1fr 1fr; gap: 32px; }
}

@media (max-width: 640px) {
  body { font-size: 16px; }

  /* La tarjeta ya viene apilada desde 1080px; aquí solo se reduce la foto y
     el aire interior del panel para el ancho de móvil. */
  .tarjeta-foto,
  .tarjeta-servicio.invertida .tarjeta-foto {
    width: 210px; height: 210px;
    margin: 30px auto 0;
  }
  .tarjeta-cuerpo { padding: 28px 26px 34px; }

  .datos-contacto-fila { grid-template-columns: 1fr; gap: 20px; }

  .banner-clientes { grid-template-columns: 1fr; }
  .clientes-pista img { height: 58px; margin: 0 26px; }

  /* Apilado en una columna, el pie se lee mejor centrado: alineado a la
     izquierda dejaba tres bloques sueltos con mucho blanco a la derecha. */
  .pie-cuerpo { grid-template-columns: 1fr; text-align: center; }
  .pie-cuerpo .redes { justify-content: center; }
  .pie-cuerpo .dato-pie .etiqueta { text-align: center; }
  .pie-legal { flex-direction: column; text-align: center; }

  .portada { min-height: 380px; padding: 64px 0; }
}

/* --- Valores largos (p. ej. el correo) nunca se recortan (todas las páginas) */
.datos-contacto a,
.datos-contacto li > span:last-child { overflow-wrap: anywhere; }

/* --- Inicio: en móvil todo el contenido va centrado, texto e imágenes ----- */
@media (max-width: 900px) {
  .inicio .portada-texto,
  .inicio .bloque-texto,
  .inicio .bloque-figura,
  .inicio .caja-contacto > div,
  .inicio .campo,
  .inicio .aviso-formulario { text-align: center; }
  /* En el inicio móvil, los párrafos van centrados (no justificados). */
  .inicio .bloque-texto p { text-align: center; }

  /* Filete rojo de los títulos y entradillas, centrados */
  .inicio .titulo-seccion::after { margin-inline: auto; }
  .inicio .entradilla { margin-inline: auto; }

  /* Imágenes centradas y completas (sin recorte) */
  .inicio .portada-media img,
  .inicio .bloque-figura img,
  .inicio .bloque-texto img,
  .inicio .caja-contacto img { margin-inline: auto; }

  /* Banner de clientes: texto centrado en cada bloque */
  .inicio .banner-clientes-rojo,
  .inicio .banner-clientes-oscuro { justify-content: center; text-align: center; }

  /* Datos de contacto: centrados y con la etiqueta encima del valor,
     así el correo largo se ve completo y centrado, nunca cortado. */
  .inicio .datos-contacto li {
    flex-direction: column;
    align-items: center;
    gap: 2px;
  }
  .inicio .datos-contacto .etiqueta { min-width: 0; }

  /* El aviso del formulario, con su filete, centrado */
  .inicio .aviso-formulario { border-left: 0; border-radius: 8px; }
}

/* ------------------------------------ 18. Movimiento y aparición -------- */
/* Las animaciones de entrada solo se activan si el JS añade la clase
   «js-anim» al <html>. Sin JS —o con «reducir movimiento» activado— el
   contenido se ve completo desde el primer instante: nada queda oculto
   esperando a que una animación llegue a ejecutarse. */
.js-anim .revelar {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 0.75s cubic-bezier(0.22, 0.61, 0.36, 1),
              transform 0.75s cubic-bezier(0.22, 0.61, 0.36, 1);
}
.js-anim .revelar.visible {
  opacity: 1;
  transform: none;
}

/* El modelo 3D del hero entra con un acercamiento muy leve y algo después
   que el texto, para que la portada se lea de izquierda a derecha. */
.js-anim .portada-media.revelar {
  transform: translateY(22px) scale(0.97);
  transition-delay: 0.24s;
}
.js-anim .portada-media.revelar.visible { transform: none; }

/* Oscilación armónica del modelo 3D: lenta y de poca amplitud, para que
   sugiera un objeto suspendido sin llegar a distraer de la lectura. */
@keyframes flotacion {
  from { transform: translateY(-7px); }
  to   { transform: translateY(7px); }
}
.js-anim .portada-media.visible img {
  animation: flotacion 6.5s ease-in-out infinite alternate;
}

/* Botones: el realce se apoya en la sombra, no en un rebote. */
.boton { box-shadow: 0 2px 8px rgb(161 28 27 / 0%); }
.boton:hover { box-shadow: 0 10px 22px rgb(161 28 27 / 26%); }
.boton:active { transform: translateY(0); box-shadow: 0 2px 8px rgb(161 28 27 / 22%); }
/* Sobre fondo oscuro la sombra roja no se percibe: se usa uno neutro. */
.boton-claro:hover,
.boton-hero:hover { box-shadow: 0 10px 24px rgb(0 0 0 / 30%); }

/* Tarjetas de servicio del inicio */
.tarjeta-servicio { transition: transform 0.4s ease, box-shadow 0.4s ease; }
.tarjeta-servicio:hover { transform: translateY(-6px); box-shadow: 0 24px 48px rgb(0 0 0 / 24%); }
.tarjeta-foto img { transition: transform 0.6s cubic-bezier(0.22, 0.61, 0.36, 1); }
.tarjeta-servicio:hover .tarjeta-foto img { transform: scale(1.07); }

/* Tarjetas con foto de fondo y fichas de proyecto */
.carta-foto { transition: transform 0.4s ease, box-shadow 0.4s ease; }
.carta-foto:hover { transform: translateY(-6px); box-shadow: var(--sombra-fuerte); }
.proyecto { transition: transform 0.4s ease, box-shadow 0.4s ease; }
.proyecto:hover { transform: translateY(-5px); box-shadow: var(--sombra-fuerte); }
.proyecto img { transition: transform 0.6s cubic-bezier(0.22, 0.61, 0.36, 1); }
.proyecto:hover img { transform: scale(1.05); }

/* Imágenes de los bloques de contenido: un realce leve al pasar el cursor. */
.bloque-media .figura img,
.par-imagenes img {
  transition: transform 0.45s cubic-bezier(0.22, 0.61, 0.36, 1),
              box-shadow 0.45s ease;
}
.bloque-media .figura img:hover,
.par-imagenes img:hover { transform: translateY(-5px); box-shadow: var(--sombra-fuerte); }

/* Cabecera: al bajar se compacta para ganar altura de lectura. */
.cabecera { transition: box-shadow 0.3s ease; }
.cabecera-interior { transition: min-height 0.3s ease; }
.logo img { transition: width 0.3s ease; }
.cabecera.compacta .cabecera-interior { min-height: 70px; padding-block: 8px; }
.cabecera.compacta .logo img { width: 60px; }
.cabecera.compacta { box-shadow: 0 4px 18px rgb(0 0 0 / 12%); }

/* Respeta la preferencia del sistema de reducir animaciones */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}

/* ---------------------------- 18. Acordeones y bloques de servicio ------ */
/* Se usa <details>/<summary> nativo y no un acordeón hecho con JS: abre y
   cierra con Enter y con la barra espaciadora, anuncia solo su estado al
   lector de pantalla —sin ARIA añadido, que aquí sobra y puede estorbar— y
   sigue funcionando aunque el JavaScript falle o no cargue. */
.acordeon {
  margin-bottom: 14px;
  background: #fff;
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  box-shadow: var(--sombra);
}
.acordeon > summary {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 20px 24px;
  font-family: var(--titulo);
  font-weight: 600;
  font-size: 1.04rem;
  line-height: 1.4;
  color: var(--texto-fuerte);
  cursor: pointer;
  list-style: none;
  border-radius: var(--radio);
}
.acordeon > summary::-webkit-details-marker { display: none; }
/* Flecha construida con dos filetes: sin icono que descargar y gira al abrir. */
.acordeon > summary::after {
  content: "";
  flex-shrink: 0;
  width: 10px;
  height: 10px;
  margin-left: auto;
  border-right: 2px solid var(--rojo);
  border-bottom: 2px solid var(--rojo);
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform var(--transicion);
}
.acordeon[open] > summary::after { transform: rotate(-135deg) translate(-2px, -2px); }
.acordeon > summary:hover { background: var(--gris-suave); }
.acordeon > summary:focus-visible { outline: 3px solid var(--rojo); outline-offset: -3px; }
.acordeon-cuerpo { padding: 4px 24px 24px; }
.acordeon-cuerpo > :last-child { margin-bottom: 0; }

/* Separación estándar entre el encabezado de una sección y su rejilla. */
.bloque-separado { margin-top: 44px; }

/* Alternativa al canal principal bajo una llamada a la acción. Va como enlace
   y no como segundo botón: dos botones del mismo peso obligan a elegir, y aquí
   uno es el camino recomendado y el otro el de quien prefiere el formulario. */
.alterna-cta { margin: 16px 0 0; }
.enlace-alterno {
  font-family: var(--titulo);
  font-size: 0.92rem;
  color: rgb(255 255 255 / 88%);
  text-decoration: underline;
  text-underline-offset: 4px;
}
.enlace-alterno:hover { color: #fff; }
.enlace-alterno:focus-visible { outline: 3px solid #fff; outline-offset: 3px; }

/* Estado del envío del formulario. Lo anuncia aria-live, pero también tiene
   que verse: un aviso que solo existe para el lector de pantalla deja a
   oscuras a todos los demás. */
.estado-formulario { margin: 0; font-size: 0.94rem; }
.estado-formulario:empty { display: none; }
.estado-formulario[data-estado="error"] { color: var(--rojo); font-weight: 600; }
.estado-formulario[data-estado="exito"] { color: #1c6b3a; font-weight: 600; }

/* Salvedad al pie de una lista: matiza lo que se acaba de enumerar sin
   competir con ella. El filete la separa del listado. */
.nota-alcance {
  margin: 22px 0 0;
  padding-left: 16px;
  border-left: 3px solid var(--rojo);
  font-size: 0.95rem;
  color: var(--texto);
}

/* Resultados en cuadrícula abierta. Deliberadamente sin panel: en la misma
   página ya hay tres tarjetas con número en círculo, y repetir ese formato
   hacía que las dos secciones se confundieran. Aquí mandan la cifra grande y
   los filetes que dividen la cuadrícula. */
.rejilla-resultados {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0;
}
.resultado {
  display: grid;
  grid-template-columns: auto 1fr;
  column-gap: 24px;
  align-content: start;
  padding: 32px 36px;
  border-top: 1px solid var(--borde);
}
/* Filete vertical solo entre columnas, no al borde del bloque. */
.resultado:nth-child(odd) { border-right: 1px solid var(--borde); }
.resultado-numero {
  grid-row: span 2;
  margin: 0;
  font-family: var(--titulo);
  font-weight: 700;
  font-size: 2.1rem;
  line-height: 1;
  color: var(--rojo);
}
.resultado h3 { margin: 0 0 8px; font-size: 1.16rem; line-height: 1.3; }
/* Alineado a la izquierda y no justificado: con columnas estrechas, justificar
   abría calles blancas y partía palabras a cada línea. */
.resultado > p:not(.resultado-numero) {
  margin: 0;
  font-size: 0.97rem;
  text-align: left;
}

@media (max-width: 900px) {
  .rejilla-resultados { grid-template-columns: 1fr; }
  .resultado { padding: 26px 0; }
  .resultado:nth-child(odd) { border-right: 0; }
}

/* Tarjeta de alcance: el mismo panel de siempre, pero con una lista dentro en
   vez de un párrafo. Tres apiladas a lo largo de la página se leían como un
   documento; en paralelo se comparan de un vistazo. */
.tarjeta-alcance {
  display: flex;
  flex-direction: column;
  padding: 32px 28px 34px;
}
.tarjeta-alcance h3 { margin-bottom: 18px; line-height: 1.3; }
/* La lista hereda la escala de la tarjeta y se aprieta un punto: dentro de una
   columna estrecha, el aire de la lista a tamaño completo la alargaba de más. */
.tarjeta-alcance .lista-check {
  margin: 0;
  font-size: 0.95rem;
}
.tarjeta-alcance .lista-check li { padding: 5px 0 5px 30px; }
.tarjeta-alcance .lista-check li::before { top: 13px; }
/* La salvedad se ancla abajo, para que las tres tarjetas cierren parejas. */
.tarjeta-alcance .nota-alcance {
  margin-top: auto;
  padding-top: 18px;
  font-size: 0.86rem;
  line-height: 1.55;
}

/* Nota de respaldo al cierre de una sección. Va en gris y por debajo del
   cuerpo para no competir con él, pero con «ayuda» quedaba tan pequeña que
   se perdía. El ancho acotado le da una línea legible al ir centrada. */
.nota-metodo {
  max-width: 780px;
  margin-inline: auto;
  font-size: 1.02rem;
  line-height: 1.65;
  color: #6d717a;
}

/* Respaldo normativo bajo los botones de la portada. */
.respaldo-normativo {
  max-width: 660px;
  margin: 24px 0 0;
  font-size: 0.9rem;
  line-height: 1.6;
  color: rgb(255 255 255 / 82%);
}

/* La portada de amenaza prioriza la propuesta y la conversión. El respaldo
   normativo sale del fondo rojo para conservar su valor sin competir con el
   título, la entradilla y la llamada a la acción. */
body[data-servicio="amenaza_por_movimientos_en_masa"] .portada-interior {
  min-height: 0;
  padding: 56px 0;
}
body[data-servicio="amenaza_por_movimientos_en_masa"] .portada-interior h1 {
  max-width: 1050px;
  font-size: clamp(2rem, 3.6vw, 2.8rem);
  margin-bottom: 12px;
}
body[data-servicio="amenaza_por_movimientos_en_masa"] .portada-interior .entradilla {
  max-width: 760px;
  margin-bottom: 26px;
}

@media (max-width: 900px) {
  .acordeon > summary { padding: 17px 18px; font-size: 0.98rem; }
  .acordeon-cuerpo { padding: 2px 18px 20px; }
  body[data-servicio="amenaza_por_movimientos_en_masa"] .portada-interior {
    padding: 44px 0;
  }
}

/* Impresión: quita cromos y deja el contenido legible */
@media print {
  .cabecera, .whatsapp-flotante, .cta, .pie-marca { display: none; }
  /* La flecha no dice nada en papel. El contenido de un acordeón cerrado sí
     se pierde al imprimir, pero CSS no puede abrirlo: el navegador oculta el
     cuerpo por dentro y no hay selector que lo alcance. */
  .acordeon > summary::after { display: none; }
  body { font-size: 12pt; color: #000; }
  .portada { background: none; color: #000; padding: 0; min-height: 0; }
  .portada h1, .portada .entradilla { color: #000; }
}
