/* =========================================================
   930 AUTOGEST — main.css
   Depende de tokens.css (cargado antes que este archivo).
   ========================================================= */

/* ---------- Reset ligero ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--bg-page);
  color: var(--text-body);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--lh-normal);
  -webkit-font-smoothing: antialiased;
  /* El carrusel de Fotografía profesional se sale a ancho completo de
     viewport con 100vw (ver .servicio-carrusel): en algunos navegadores
     100vw incluye el hueco de la barra de scroll y sobra por unos
     píxeles, lo que crearía un scroll horizontal fantasma. */
  overflow-x: hidden;
}
/* `height: auto` no es adorno: sin él, las fotos se DEFORMAN.
   WordPress imprime `width` y `height` en cada <img>. Cuando el hueco es
   más estrecho que la foto, `max-width: 100%` baja el ancho pero el alto
   se queda clavado en el atributo, así que la imagen se comprime a lo
   ancho sin que nadie lo note en el HTML.
   Medido el 2026-09-03 en un artículo del blog: una portada de 1200x630
   se estaba pintando a 712x630 — un 59 % de su ancho, con los coches
   estrechos y altos. Afectaba a las cuatro entradas publicadas y venía
   de antes de que hubiera fotos en el blog, por eso no se había visto.
   Las reglas que SÍ quieren un alto fijo (el logotipo de la cabecera,
   por ejemplo) lo declaran ellas y ganan por especificidad. */
img { max-width: 100%; height: auto; display: block; }
/* Las fotos del tema salen envueltas en <picture> para ofrecer WebP con
   respaldo JPEG (ver autogest930_imagen() en inc/imagenes.php). `picture`
   es un elemento EN LÍNEA, así que sin esto se interpondría como caja
   entre el contenedor y el <img>, y todos los `height: 100%` del sitio
   —.hero-media img, .split-hero__media img, .service-card-thumb img...—
   pasarían a resolverse contra el picture en vez de contra el
   contenedor. `display: contents` lo saca del árbol de cajas: el <img>
   vuelve a ser hijo directo a efectos de maquetado y el CSS de abajo
   sigue valiendo tal cual. */
picture { display: contents; }
a { color: inherit; text-decoration: none; }
ul { list-style: none; margin: 0; padding: 0; }
h1, h2, h3, h4 {
  font-family: var(--font-display);
  color: var(--text-strong);
  line-height: var(--lh-tight);
  margin: 0 0 var(--space-sm);
}
.container {
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--space-md);
}
.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}
a:focus-visible, button:focus-visible, input:focus-visible, textarea:focus-visible, select:focus-visible {
  outline: 2px solid var(--action);
  outline-offset: 2px;
}

/* ---------- Botones ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  padding: 0.85em 1.5em;
  border-radius: 4px;
  font-weight: 600;
  font-size: var(--fs-small);
  letter-spacing: 0.01em;
  border: 1px solid transparent;
  cursor: pointer;
  transition: background-color var(--transition-fast), border-color var(--transition-fast), color var(--transition-fast);
  white-space: nowrap;
  /* Un botón nunca puede ser más ancho que su hueco: sin esto, el
     `nowrap` de arriba lo deja crecer hasta empujar la página entera. */
  max-width: 100%;
}
/* Y por debajo de 480px se le permite partirse. El `nowrap` está para
   que los botones no queden en dos líneas feas, pero en una pantalla de
   320px se convierte en desbordamiento horizontal de TODA la página en
   cuanto el texto es un poco largo.

   Y no hace falta que el texto cambie para que ocurra: la tipografía
   del tema es una pila de fuentes del sistema ("Inter", "Public Sans",
   system-ui, "Segoe UI"...) y en Linux no existe ninguna de las
   primeras, así que se cae a DejaVu Sans, un 20% más ancha. Medido: el
   botón "Descubrir todos los servicios →" mide 245px con la fuente
   habitual y 293px con la sustituta, y a 320px eso desborda 13px. Le
   pasa a la CI y le pasaría a cualquier visitante en Linux o en un
   Android sin esas fuentes.

   Un botón de dos líneas es mejor que una web que se mueve de lado. */
@media (max-width: 480px) {
  .btn { white-space: normal; }
}
.btn-primary { background: var(--action); color: #fff; }
.btn-primary:hover { background: var(--action-hover); }
.btn-secondary { background: #fff; color: var(--text-strong); border-color: var(--border-plata); }
.btn-secondary:hover { border-color: var(--text-strong); }
.btn-ghost-dark { background: transparent; color: var(--text-on-dark); border-color: rgba(250,250,249,0.35); }
.btn-ghost-dark:hover { border-color: var(--text-on-dark); }
/* Llamada a la acción sobre fondo oscuro: sólido y en rojo de marca, no
   fantasma. Es el modificador del botón del bloque "Mucho más que
   trámites", que era un .btn-ghost-dark y desaparecía contra el fondo.

   VA APARTE, no sustituyendo a .btn-ghost-dark: el fantasma es el estilo
   correcto para un botón SECUNDARIO sobre oscuro, y dejarlo intacto
   permite que convivan los dos si algún día un bloque oscuro necesita
   dos botones.

   El rojo es --action (#D40000), el mismo token que .btn-primary; no se
   introduce ningún color nuevo. Y se usa el rojo de marca a secas y no
   --action-on-dark (#FF5A52): ese token existe para TEXTO rojo sobre
   fondo oscuro, donde el que tiene que contrastar es el propio rojo.
   Aquí el rojo es el fondo del botón y lo que tiene que leerse es el
   blanco de encima: #fff sobre #D40000 da 5,53:1 (AA para texto normal,
   que pide 4,5), y en hover #fff sobre #A90000 sube a 7,82:1.

   Esquinas de píldora (--radius-pill) en vez de los 4px de .btn: es el
   único botón del sitio que va solo en mitad de un bloque a toda
   anchura, y la forma redondeada es lo que lo separa del resto de
   botones cuadrados de la página. */
.btn-cta-dark {
  background: var(--action);
  color: #fff;
  border-color: var(--action);
  border-radius: var(--radius-pill);
  padding-inline: 1.9em;
}
.btn-cta-dark:hover { background: var(--action-hover); border-color: var(--action-hover); color: #fff; }
/* "Área privada": mismo tratamiento que un botón secundario — nunca azul,
   para no competir visualmente con el rojo de acción de la cabecera. */
/* CORRECCIÓN (auditoría, hallazgo #19): borde más marcado (antes
   --border-plata, el mismo gris casi imperceptible que cualquier botón
   secundario) para que se distinga mejor junto al rojo de "Solicita tu
   estudio" — sigue sin usar rojo ni azul, solo más contraste de borde. */
.btn-account { background: transparent; color: var(--text-strong); border-color: var(--text-strong); }
.btn-account svg { flex-shrink: 0; }
.btn-account:hover { border-color: var(--account-color); background: var(--bg-section-alt); }

/* Icono de carrito junto a "Solicita tu estudio": acceso directo al
   carrito desde cualquier página, sin depender del panel lateral. */
.btn-cart-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--nav-item-height);
  height: var(--nav-item-height);
  box-sizing: border-box;
  border: 1px solid var(--border-plata);
  border-radius: 4px;
  background: transparent;
  color: var(--text-strong);
  flex-shrink: 0;
}
.btn-cart-icon:hover { border-color: var(--action); color: var(--action); }

/* ---------- Cabecera ---------- */
/* Franja superior con el correo de contacto directo, por encima de la
   cabecera pegajosa (no lleva position:sticky propio: se desplaza fuera
   de la pantalla al hacer scroll, y el .site-header de abajo es el que
   se queda fijo). */
.header-topbar { background: var(--text-strong); color: var(--text-on-dark); }
.header-topbar .container {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  padding-block: 0.5em;
}
.header-topbar p {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 0.4em;
  font-size: var(--fs-small);
  text-align: right;
}
.header-topbar a { font-weight: 600; text-decoration: underline; text-underline-offset: 2px; }
.header-topbar a:hover { color: var(--action); }
@media (max-width: 640px) {
  .header-topbar .container { justify-content: center; }
  .header-topbar p { justify-content: center; text-align: center; }
}

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: rgba(250, 250, 249, 0.92);
  backdrop-filter: saturate(160%) blur(8px);
  border-bottom: 1px solid var(--border-subtle);
}
.site-header .container {
  display: grid;
  /* CORRECCIÓN (petición del cliente): antes era un flex con
     `.main-nav{margin-left:auto}`, que pega el menú contra los botones
     de la derecha dejando todo el hueco sobrante entre el logo y el
     menú — el conjunto queda descentrado. Con rejilla de 3 columnas
     (logo | menú | acciones) y el menú centrado en su columna, el menú
     queda repartido en el centro del hueco disponible entre el logo y
     los botones, sea cual sea el ancho real de cada uno. */
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: var(--space-md);
  height: var(--header-height);
}
.site-branding { display: flex; align-items: center; gap: var(--space-sm); }
/* El logo real (Apariencia → Personalizar → Identidad del sitio,
   logo-930-autogest-header-v2.png) es un logotipo muy panorámico
   (~2.52:1) — bastante más ancho en proporción que el archivo anterior
   para el que se afinaron estos valores. Con solo `width: auto` y sin
   más, la barra del menú (llena de sobra ya con el menú completo + los
   botones de la derecha) lo comprimía con flex-shrink por debajo de su
   ancho real, deformándolo (más cuanto más estrecha la ventana, hasta
   casi desaparecer entre 1024-1100px de ancho — bug real, verificado en
   producción). `min-width` evita esa desaparición en cualquier ancho.
   A partir de 1200px (contenedor ya a su max-width de 1200px, así que
   no gana más sitio por seguir ensanchando la ventana) sí hay hueco
   para protegerlo del todo con flex-shrink:0 y mostrarlo con su
   proporción real, más ancho y grande que antes, ligeramente movido
   hacia el borde izquierdo. Por debajo de 1200px sigue habiendo algo
   de compresión (no hay más sitio sin tocar el menú), pero nunca por
   debajo de min-width. */
/* `object-fit: contain` es la red de seguridad contra la DEFORMACIÓN.
   `height` va fijo y el reajuste global `img { max-width: 100% }` recorta
   el ancho cuando falta hueco: la caja se estrecha, el alto no cede y el
   logo se aplasta. `min-width` evitaba que desapareciera, no que saliera
   deformado. Con `contain`, si algún ancho vuelve a quedarse corto, el
   logo se ve más pequeño pero SIEMPRE con su proporción — que es
   justamente lo que hacía que se viera "raro". */
.site-branding img { height: 104px; width: auto; min-width: 28px; object-fit: contain; mix-blend-mode: multiply; }
@media (min-width: 1200px) {
  .site-branding { flex-shrink: 0; margin-left: -8px; }
  .site-branding img { height: 60px; }
}
/* La franja 1024-1199px: el bug que describe el comentario de arriba
   ("hasta casi desaparecer entre 1024-1100px"), aquí resuelto.
   Medido en producción antes de esto: 28x104 a 1024px, 63x104 a 1100px
   — ratios de 0.27 y 0.60 para un logo que es 2.52:1.

   Hacen falta las DOS reglas; ninguna basta sola, y está medido:
     - solo ocultar .eyebrow-tag  → 115x104 a 1024px (ratio 1.10)
     - solo bajar el alto         → 28x60  a 1024px (ratio 0.47)
     - las dos                    → 111x44 a 1024px (ratio 2.52) ✓

   Por qué el eyebrow: aparece desde 900px y se lleva 112-296px de la
   columna de la marca. Por debajo de 1200px no tiene sitio, cosa que ya
   dice su propio comentario más abajo — solo a partir de 1200px se le da
   un ancho pensado para que parta en dos líneas. En 900-1023px SÍ se
   queda: ahí no hay menú y el logo mide sus 262x104 sin estrujarse
   (comprobado a 1000px), así que no hay nada que arreglar.

   Por qué el alto variable: a 1024px la columna de marca topa en 115px y
   solo caben 44px de alto; a 1199px caben los 104px enteros. Un valor
   fijo o desperdicia sitio arriba o se aplasta abajo, así que interpola
   entre los dos extremos. Comprobado a 1024 (111x44), 1100 (177x70) y
   1199 (262x104): ratio 2.52 en los tres y cero desbordamiento.

   1199.98 y no 1199: el viewport real puede ser fraccionario (medido:
   1199.2px). Con `max-width:1199px` NO casaba esta regla y `min-width:
   1200px` tampoco casaba la de abajo — el logo se quedaba sin ninguna de
   las dos justo en ese punto. */
@media (min-width: 1024px) and (max-width: 1199.98px) {
  .site-branding img {
    height: clamp(44px, calc(44px + (100vw - 1024px) * 0.343), 104px);
  }
}
/* En móvil, además de no deformarlo, hay que darle un alto que quepa de
   verdad: 104px de alto son 262px de ancho, y en la fila de la cabecera
   a 375px solo hay 174px libres. De ahí el aplastamiento.
   `clamp` en vez de un valor fijo porque el ancho disponible cambia con
   la ventana: 40px a 320px (101px de ancho), ~45px a 375px (113px), y
   tope de 60px —el mismo valor que ya usa el escritorio ≥1200px— a
   partir de 500px. En ningún punto del rango llega a hacer falta el
   recorte de `max-width`, así que el logo nunca se aplasta.
   El comentario de header.php ya decía "104px de alto (60px en móvil)":
   el móvil se había quedado sin su regla. */
@media (max-width: 767px) {
  .site-branding img { height: clamp(40px, 12vw, 60px); }
}
.eyebrow-tag {
  font-size: var(--fs-eyebrow);
  color: var(--text-muted);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  border-left: 1px solid var(--border-plata);
  padding-left: var(--space-sm);
  display: none;
}
/* 1200px y no 900px: el eyebrow es la mitad del aplastamiento del logo.
   Con `width: auto` se lleva todo lo que puede de la columna de la marca
   —296px medidos a 1000px— y solo a partir de 1200px se le fija un ancho
   (164px, más abajo). Medido en producción con el eyebrow puesto: el
   logo salía 205x104 a 900px (ratio 1.97) y 28x104 a 1024px (0.27), para
   un logo que es 2.52:1. Ocultándolo hasta 1200px: 262x104 a 900px, ratio
   correcto.
   Es un cambio que se sostiene solo: por debajo de 1200px el eyebrow no
   tiene sitio, cosa que ya decía su propio comentario de aquí abajo.
   OJO: en RC61 esta regla se puso solo para 1024-1199 porque una única
   medida a 1000px salía bien. Era una generalización a partir de un solo
   punto: a 900px sí estaba roto. Medir los dos extremos de una franja,
   no uno. */
@media (min-width: 1200px) { .eyebrow-tag { display: block; } }
/* A 1024-1199px de ancho el menú completo ya compite por sitio con el
   logo (ver arriba) y no queda hueco para garantizar 2 líneas aquí sin
   tocar el menú; a partir de 1200px sí, así que solo ahí se fija un
   ancho pensado para partir el texto exactamente en "Especialistas en"
   / "vehículos históricos" (2 líneas) en vez de las 3-4 líneas sueltas
   que salían antes al no caber ninguna combinación de palabras. */
/* 164px y no 155, y 12px de fuente y no 13: los 155px de antes NO
   conseguían las 2 líneas que buscaba el comentario de arriba. Medido en
   producción, "VEHÍCULOS HISTÓRICOS" necesita 158px a 13px y solo tenía
   155 de caja —menos el borde y el relleno—, así que se partía en tres
   trozos sueltos. A 12px la línea mide 145 y con 164px de caja entra
   holgada. 12px es el mínimo que admite la prueba de accesibilidad
   ("no hay texto por debajo de 12px"), así que no se puede bajar más.

   Los tres ajustes de hueco de abajo no son estética: la cabecera
   necesitaba 1208px y solo tiene 1200 (--container-max menos el
   relleno). Esos -8px no se veían como barra de desplazamiento porque
   la rejilla los disimulaba apretando .main-nav —le daba 417px cuando
   pedía 420— y estrujando el logo a 142px cuando su tamaño natural es
   151. En la CI, con otro logo, sí desbordaba: 11px a 1280 y 13px a
   320. Recortando 8px del hueco del contenedor, 4px del de la marca y
   4px entre ítems del menú, la cuenta pasa a +14px de holgura, el logo
   recupera sus 151px y el menú deja de ir apretado. */
@media (min-width: 1200px) {
  .eyebrow-tag {
    flex-shrink: 0;
    width: 164px;
    max-width: 164px;
    font-size: 0.75rem;
    white-space: normal;
  }
  .site-header .container { gap: var(--space-sm); }
  .site-branding { gap: 0.75rem; }
}

/* Altura homogénea: enlaces del menú y botones de cabecera comparten la
   misma caja de 40px, así el conjunto queda alineado visualmente en
   vez de que los botones "floten" más altos que el texto del menú. */
:root { --nav-item-height: 40px; }

.main-nav { justify-self: center; display: none; align-items: center; gap: var(--space-md); }
@media (min-width: 1024px) { .main-nav { display: flex; } }
.main-nav > ul { display: flex; gap: var(--space-md); height: var(--nav-item-height); }
/* Los 4px que le faltaban a la cabecera para no ir apretada (ver el
   bloque de .eyebrow-tag, más arriba). Va AQUÍ y no allí a propósito:
   con la misma especificidad gana la regla que aparece más tarde en el
   archivo, así que puesto arriba no se aplicaba —comprobado en
   producción: el hueco seguía en 24px— y el menú se quedaba con 417px
   cuando pedía 420. */
@media (min-width: 1200px) {
  .main-nav { gap: 1.25rem; }
  .main-nav > ul { gap: 1.25rem; }
}
.main-nav li { position: relative; display: flex; align-items: center; }
.main-nav a {
  display: inline-flex;
  align-items: center;
  height: var(--nav-item-height);
  font-size: var(--fs-small);
  font-weight: 500;
  color: var(--text-body);
  border-bottom: 2px solid transparent;
}
.main-nav .current-menu-item > a {
  color: var(--action);
  border-bottom-color: var(--action);
}
/* Primer nivel (Inicio, Servicios, Precios…): al pasar por encima, el
   mismo efecto que los servicios del mega-menú —fondo gris, texto rojo y
   barra roja a la izquierda—. Se mantiene mientras el ratón o el foco
   están DENTRO de su desplegable, para ver de qué menú cuelga lo que se
   mira. El relleno lateral se compensa con margen negativo: el hueco
   entre ítems (16px como mínimo) cubre los 7+7px, así que el menú ocupa
   exactamente lo mismo que antes —la cabecera va justa, ver arriba—. La
   línea roja inferior queda solo para la página actual. */
.main-nav > ul > li > a {
  padding-inline: 0.5em;
  margin-inline: -0.5em;
  border-radius: 6px;
  transition: background var(--transition-fast), box-shadow var(--transition-fast), color var(--transition-fast);
}
.main-nav > ul > li:hover > a,
.main-nav > ul > li:focus-within > a {
  background: #F6F7F7;
  color: var(--action);
  box-shadow: inset 3px 0 0 var(--action);
}
.main-nav .menu-item-has-children > a::after {
  content: '';
  display: inline-block;
  width: 6px;
  height: 6px;
  margin-left: 0.4em;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg) translateY(-2px);
  opacity: 0.6;
}

/* Desplegable de "Servicios" y "Blog" (Eventos) */
.main-nav .sub-menu {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
  min-width: 220px;
  background: #fff;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  padding: 0.4em 0;
  z-index: 60;
}
.main-nav li:hover > .sub-menu,
.main-nav li:focus-within > .sub-menu {
  display: block;
}
.main-nav .sub-menu li { display: block; height: auto; }
.main-nav .sub-menu a {
  display: block;
  height: auto;
  padding: 0.6em 1.1em;
  border-bottom: none;
  white-space: nowrap;
}
.main-nav .sub-menu a:hover { background: var(--bg-section-alt); color: var(--action); border-bottom: none; }

/* Desplegables de una columna (Contacto, Blog): como los servicios del
   mega-menú, cada opción separada por una línea suave y, al pasar por
   encima, fondo gris, texto rojo y barra roja a la izquierda. El
   mega-menú se excluye: sus cabeceras de columna llevan otro estilo. */
.main-nav > ul > li:not(.menu-servicios-mega) > .sub-menu { padding: 0.4em; }
.main-nav > ul > li:not(.menu-servicios-mega) > .sub-menu > li + li {
  border-top: 1px solid #EEF0F1;
}
.main-nav > ul > li:not(.menu-servicios-mega) > .sub-menu a {
  padding: 0.6em 0.75em;
  font-size: 0.9rem;
  border-radius: 6px;
  transition: background var(--transition-fast), box-shadow var(--transition-fast), color var(--transition-fast);
}
.main-nav > ul > li:not(.menu-servicios-mega) > .sub-menu a:hover,
.main-nav > ul > li:not(.menu-servicios-mega) > .sub-menu a:focus-visible {
  background: #F6F7F7;
  color: var(--action);
  box-shadow: inset 3px 0 0 var(--action);
}

/* Mega-menú de "Servicios": su desplegable de nivel 2 (Servicios
   especializados / Trámites DGT) se pinta en 2 columnas lado a lado en
   vez de en vertical, y el nivel 3 de cada columna (los servicios
   concretos) se muestra siempre, sin necesitar su propio hover — así
   los dos bloques no se solapan ni se confunden entre sí. Solo afecta
   al ítem de menú marcado con esta clase (ver
   autogest930_menu_mega_servicios() en functions.php); el resto de
   desplegables del menú (Blog, Contacto) siguen con el comportamiento
   simple de una sola columna de arriba. */
/* Ancho justo para que ningún servicio se parta en dos líneas
   (tema RC108): el panel mide lo que mida su servicio más largo, en vez
   de los 520px fijos de antes, que partían siete de los diecinueve. */
.main-nav .menu-servicios-mega > .sub-menu {
  display: none;
  min-width: 0;
  width: max-content;
  max-width: calc(100vw - 2rem);
  padding: var(--space-md);
  gap: var(--space-lg);
}
.main-nav .menu-servicios-mega:hover > .sub-menu,
.main-nav .menu-servicios-mega:focus-within > .sub-menu {
  display: flex;
  flex-direction: row;
  align-items: flex-start;
}
.main-nav .menu-servicios-mega > .sub-menu > li {
  flex: 1 1 50%;
  display: block;
  padding: 0 var(--space-sm);
}
.main-nav .menu-servicios-mega > .sub-menu > li:first-child {
  border-right: 1px solid var(--border-subtle);
}
.main-nav .menu-servicios-mega > .sub-menu > li > a {
  font-weight: 700;
  padding: 0.4em 0;
  border-bottom: 1px solid var(--border-subtle);
  margin-bottom: 0.4em;
}
.main-nav .menu-servicios-mega .sub-menu .sub-menu {
  display: block;
  position: static;
  box-shadow: none;
  border: none;
  padding: 0;
  min-width: 0;
}
/* Cada servicio en una línea, separados por una línea suave, y al pasar
   por encima fondo gris, texto rojo y una barra roja a la izquierda. */
.main-nav .menu-servicios-mega .sub-menu .sub-menu li + li {
  border-top: 1px solid #EEF0F1;
}
.main-nav .menu-servicios-mega .sub-menu .sub-menu a {
  padding: 0.6em 0.75em;
  font-size: 0.9rem;
  white-space: nowrap;
  border-radius: 6px;
  transition: background var(--transition-fast), box-shadow var(--transition-fast), color var(--transition-fast);
}
.main-nav .menu-servicios-mega .sub-menu .sub-menu a:hover,
.main-nav .menu-servicios-mega .sub-menu .sub-menu a:focus-visible {
  background: #F6F7F7;
  color: var(--action);
  box-shadow: inset 3px 0 0 var(--action);
}

/* ---------- Buscador global (lupa a la izquierda de "Inicio") ---------- */
.ag930-search { position: relative; display: flex; align-items: center; flex-shrink: 0; }
.ag930-search-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  width: var(--nav-item-height);
  height: var(--nav-item-height);
  padding: 0;
  border: none;
  border-radius: 4px;
  background: transparent;
  color: var(--text-body);
  cursor: pointer;
  flex-shrink: 0;
}
.ag930-search-toggle:hover,
.ag930-search-toggle[aria-expanded="true"] {
  color: var(--action);
  background: var(--bg-section-alt);
}
.ag930-search-toggle-label { display: none; }

.ag930-search-panel {
  position: absolute;
  top: calc(100% + 0.5rem);
  left: 0;
  width: min(360px, calc(100vw - 2 * var(--space-md)));
  background: #fff;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  padding: var(--space-sm);
  z-index: 70; /* por encima de los desplegables del menú (60) y de la cabecera (50) */
}
.ag930-search-panel[hidden] { display: none; }

.ag930-search-input {
  display: block;
  width: 100%;
  height: var(--nav-item-height);
  box-sizing: border-box;
  padding: 0 0.9em;
  border: 1px solid var(--border-plata);
  border-radius: 4px;
  font-family: var(--font-body);
  font-size: var(--fs-small);
  color: var(--text-body);
  background: var(--bg-page);
}

.ag930-search-results {
  margin-top: var(--space-xs);
  max-height: min(60vh, 420px);
  overflow-y: auto;
}
.ag930-search-result + .ag930-search-result { border-top: 1px solid var(--border-subtle); }
.ag930-search-result a {
  display: block;
  padding: 0.65em 0.6em;
  border-radius: 4px;
  color: var(--text-body);
}
.ag930-search-result a:hover,
.ag930-search-result a.is-active {
  background: var(--bg-section-alt);
  color: var(--action);
}
.ag930-search-result-title {
  font-size: var(--fs-small);
  font-weight: 600;
  line-height: 1.3;
}
.ag930-search-result-title mark { background: transparent; color: var(--action); font-weight: 700; padding: 0; }
.ag930-search-message { padding: 0.6em 0.5em; font-size: var(--fs-small); color: var(--text-muted); }

/* Dentro del menú móvil el panel fluye con el resto de la lista en vez
   de superponerse en absoluto, para no desbordar ni recortarse en
   pantallas estrechas. */
.mobile-nav .ag930-search {
  display: block;
  padding: var(--space-sm) var(--space-md) 0;
  border-bottom: 1px solid var(--border-subtle);
}
.mobile-nav .ag930-search-toggle {
  width: 100%;
  height: auto;
  justify-content: flex-start;
  padding: 0.5em 0.2em 0.75em;
}
.mobile-nav .ag930-search-toggle-label {
  display: inline;
  font-size: var(--fs-small);
  font-weight: 500;
}
.mobile-nav .ag930-search-panel {
  position: static;
  width: 100%;
  box-shadow: none;
  border: none;
  padding: 0 0 var(--space-sm);
  z-index: auto;
}

.header-actions { display: flex; align-items: center; gap: var(--space-sm); }
.header-actions .btn { height: var(--nav-item-height); box-sizing: border-box; }

/* ---------- Lupa en la fila de la cabecera ---------- */
/* Va a la derecha del botón de menú. Es la misma pieza que ya usan el
   menú de escritorio y el desplegable (template-parts/search-widget.php),
   instanciada una tercera vez.

   La franja es 360-1023.98px, y los dos extremos están medidos:
     - Por DEBAJO de 360px no cabe. A 320px la columna de acciones tiene
       179px y cuatro iconos de 44 con sus huecos piden 200: se pasa 21px
       y la prueba de responsive lo marcaría como desbordamiento. Ahí el
       buscador se queda donde ya estaba, dentro del menú desplegable, así
       que no se pierde nada.
     - A partir de 1024px aparece .main-nav con su propia lupa.
   A 375px sobran 74px a la derecha del botón de menú, así que entra con
   holgura (medido en producción). */
.header-actions .ag930-search { display: none; }
/* Con cuatro iconos en la fila, el hueco de 16px ya no cabe por debajo de
   768px. Medido a 414px con la lupa puesta y `gap: var(--space-sm)`: las
   acciones pedían 224px y dejaban 94px al logo, que necesita 127 — no se
   deformaba (lo salva `object-fit: contain`) pero se dibujaba a 94x37,
   más pequeño de lo que toca. Con 8px las acciones bajan a 200 y el logo
   dispone de 142. Por encima de 767px sobra sitio y no hace falta: a
   768px la fila pide 510 de los 720 disponibles.
   El bloque de <=400px ya hacía esto; aquí solo se sube el techo. */
@media (max-width: 767px) {
  .header-actions { gap: var(--space-xs); }
  /* Y el de la rejilla de la cabecera. Ojo, son DOS huecos y no uno: la
     rejilla es `auto 1fr auto` y la tercera columna sigue ahí aunque mida
     0px (.main-nav está oculta), así que cada 24px cuesta 48. Con solo
     apretar el de las acciones el logo se quedaba en 118 de los 127 que
     pide; con este llega a 150 disponibles y ya no se recorta. */
  .site-header .container { gap: var(--space-xs); }
}
@media (min-width: 360px) and (max-width: 1023.98px) {
  .header-actions .ag930-search { display: flex; }
  /* Una sola lupa a la vez. Esta regla tiene que ir DESPUÉS del
     `.mobile-nav .ag930-search { display: block }` de más arriba: misma
     especificidad (0-2-0), gana la última. */
  .mobile-nav .ag930-search { display: none; }
  .header-actions .ag930-search-toggle {
    /* 44x44 y no --nav-item-height (40px): la prueba de responsive mide
       TODOS los <button> visibles a 375px y exige 44x44. Las otras dos
       instancias se libran porque a ese ancho están ocultas. */
    width: 44px;
    height: 44px;
  }
  .header-actions .ag930-search-panel {
    /* Anclado a la derecha. Con el `left: 0` de la regla base, un panel
       de ~327px que arranca en la lupa (x=303 a 375px) se saldría de la
       pantalla; `right: 0` lo hace crecer hacia dentro. */
    left: auto;
    right: 0;
  }
}
/* "Área privada" es visible en TODOS los anchos. Antes estaba en
   `display: none` con un único rescate a partir de 1024px, así que en
   móvil no había forma de llegar al área privada desde la cabecera: el
   enlace tampoco estaba en el menú desplegable.
   Por debajo de 1024px se queda en icono, sin rótulo: es lo único que
   cabe en la fila (ver el reparto de anchos más abajo) y es el mismo
   tratamiento que ya tiene el carrito. */
.header-actions .btn-account { display: inline-flex; }
@media (max-width: 1023px) {
  .header-actions .btn-account {
    /* 44px, no --nav-item-height (40px): la prueba de responsive exige
       zonas pulsables de 44x44 y aquí ya no hay texto que estire la caja. */
    width: 44px;
    padding-inline: 0;
    justify-content: center;
  }
  .btn-account__label { display: none; }
  .header-actions .btn-account svg { width: 20px; height: 20px; }
}

/* 44x44 medidos, no aproximados: con `padding: 0.5em 0.7em` a secas el
   botón se quedaba en 41x29 —comprobado a 768px—, por debajo del objetivo
   táctil mínimo. Y es el único acceso al menú en móvil y en tablet, o sea
   justo el botón que no puede fallar. */
.menu-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  background: none;
  border: 1px solid var(--border-plata);
  border-radius: 4px;
  padding: 0.5em 0.7em;
  cursor: pointer;
}
@media (min-width: 1024px) { .menu-toggle { display: none; } }

/* ---------- Cabecera en pantallas muy estrechas ---------- */
/* A 320px la fila de la cabecera pedía 274px solo para las acciones
   (CTA 161 + carrito 40 + menú 41 + huecos 32) cuando el hueco real
   era de 196px: la cabecera entera se salía 37px y el usuario veía la
   página desplazada nada más entrar.
   No se oculta nada — el CTA "Solicita tu estudio" y el carrito no
   están duplicados en el menú móvil, así que esconderlos quitaría
   funcionalidad. Lo que se hace es apretar huecos y reducir el CTA lo
   justo para que quepa, manteniéndolo por encima de 12px de texto. */
@media (max-width: 400px) {
  .site-header .container {
    gap: var(--space-xs);
    padding-inline: 0.75rem;
  }
  .header-actions { gap: var(--space-xs); }
  .header-actions .btn-primary {
    font-size: 0.8rem;
    padding-inline: 0.75em;
  }
}

.mobile-nav {
  display: none;
  border-top: 1px solid var(--border-subtle);
  background: var(--bg-page);
}
.mobile-nav.is-open { display: block; }

/* El CTA vive en la cabecera hasta 767px y en el menú por debajo (el
   porqué, en el comentario de header.php). Solo una de las dos copias
   se ve nunca: la que no toca está en `display: none`, así que ni se
   pinta ni la anuncia un lector de pantalla. */
/* `.mobile-nav .mobile-nav__cta` y no `.mobile-nav__cta` a secas: más
   abajo hay un `.mobile-nav a { display: block; padding: 0.75em 0 }`
   (0-1-1) que le gana a un selector de una sola clase y dejaba el CTA
   como una barra roja con el texto pegado a la izquierda y sin relleno
   lateral. Comprobado en el navegador: con 0-1-0 el `display` calculado
   salía `block`, no `flex`. */
.mobile-nav .mobile-nav__cta { display: none; }
@media (max-width: 767px) {
  .header-actions .btn-primary { display: none; }
  .mobile-nav .mobile-nav__cta {
    display: flex;
    justify-content: center;
    text-align: center;
    padding: 0.75em 1.25em;
    margin: var(--space-sm) var(--space-md) 0;
  }
}
/* El menú abierto se desplaza POR DENTRO, no estirando la cabecera.
   Sin esto, en un móvil de 812px de alto la cabecera pasaba a medir
   1.802px con el menú desplegado (31 enlaces, 1.681px de menú). Y como
   .site-header es `position: sticky`, un elemento más alto que la
   ventana se queda clavado arriba: los ~990px de menú que sobraban no
   había forma de alcanzarlos, solo reaparecían al llegar al final del
   documento, que es cuando el sticky se suelta.

   Se resta --header-height porque es la altura exacta de la barra
   (.site-header .container la fija con `height`), y 1px más por el
   `border-bottom` de .site-header: sin ese píxel la cabecera medía 813
   en una ventana de 812 y volvía a ser, por poco, más alta que la
   pantalla. Así cabecera + menú suman justo la ventana. Las dos
   declaraciones de max-height no sobran: la de `vh` es el respaldo, y
   `dvh` —que la pisa donde se entienda— descuenta la barra de
   direcciones del navegador móvil, que con `vh` quedaría por debajo del
   pliegue.

   `overscroll-behavior: contain` evita que, al llegar al final del
   menú, el gesto siga arrastrando la página de detrás. */
@media (max-width: 1023px) {
  .mobile-nav.is-open {
    max-height: calc(100vh - var(--header-height) - 1px);
    max-height: calc(100dvh - var(--header-height) - 1px);
    overflow-y: auto;
    overscroll-behavior: contain;
  }
}
.mobile-nav .sub-menu { padding-left: var(--space-md); }
.mobile-nav .sub-menu a { font-size: 0.9rem; color: var(--text-muted); }
.mobile-nav ul { padding: var(--space-sm) var(--space-md); display: flex; flex-direction: column; }
.mobile-nav a { display: block; padding: 0.75em 0; font-weight: 500; }

/* =========================================================
   .split-hero — bloque reutilizable "texto a un lado, imagen al
   otro, fundida con el fondo". Base del lenguaje visual de todas
   las cabeceras interiores y del hero de Inicio (ver más abajo,
   .fade-media-right).
   ========================================================= */
.split-hero {
  position: relative;
  display: grid;
  grid-template-columns: 1fr;
  align-items: center;
  gap: var(--space-lg);
}
@media (min-width: 960px) {
  /* La imagen ya no vive en su propia columna de rejilla: ocupa todo
     el bloque de lado a lado (position:absolute) y el texto flota
     por delante. Así la imagen funciona de verdad como fondo detrás
     del texto — fundida hasta quedar prácticamente invisible justo
     donde hay letras, pero sin un corte duro entre "zona de imagen"
     y "zona de texto". */
  .split-hero { display: block; min-height: 460px; }
  .split-hero__content { max-width: 48%; padding-block: var(--space-xl); }
}
.split-hero__content {
  position: relative;
  z-index: 2;
  max-width: 56ch;
  /* Mismo motivo que en .trust-bar y .newsletter-form: como hijo de una
     rejilla, su ancho mínimo es `auto` y no encogería por debajo del
     contenido más ancho que tenga dentro. Con esto, si algún día un
     titular o un botón se alarga, se parte en vez de desbordar la
     página. */
  min-width: 0;
  overflow-wrap: break-word;
  padding-block: var(--space-lg);
}
@media (min-width: 960px) { .split-hero__content { padding-block: var(--space-xl); } }
.split-hero__media {
  position: relative;
  z-index: 0;
  aspect-ratio: 4 / 3;
  overflow: hidden;
}
@media (min-width: 960px) {
  .split-hero__media {
    position: absolute;
    inset: 0;
    z-index: 0;
    aspect-ratio: auto;
    margin: 0;
  }
}
.split-hero__media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* ---------- Fundido imagen → fondo (reutilizable) ---------- */
/* Preferencia: mask-image real (recorta la imagen de verdad). El
   pseudo-elemento ::after es el refuerzo/fallback: reintroduce un
   degradado hacia el color de fondo de la sección para que el punto
   de fusión quede idéntico aunque el navegador no soporte máscaras. */
.fade-media-right {
  --split-fade-color: var(--bg-page);

  /* Los dos puntos del fundido, medidos SIEMPRE DESDE LA DERECHA:
       --fade-solido : hasta aquí la foto se ve entera.
       --fade-fin    : aquí ya ha desaparecido del todo.

     Estaban en 42% y 82%, y eso dejaba un pasillo muerto: la foto no
     empezaba a verse hasta el 58% contando desde la izquierda, mientras
     que .split-hero__content nunca pasa del 48% (su `max-width`). Diez
     puntos de blanco entre el texto y la foto, unos 115px en una
     cabecera de 1152. Se notaba sobre todo en las páginas de título
     corto, como /fotografia-profesional/, donde el título acaba al 23%
     y quedaba media cabecera vacía.

     Con 52%, la foto pasa a estar entera justo donde termina la columna
     de texto, así que el pasillo desaparece sin que la foto llegue a
     meterse debajo de las letras. Y el 78% (en vez de 82%) hace que el
     fundido se complete antes de llegar a la zona escrita: por detrás
     del texto solo queda un velo, no la foto.

     Son variables a propósito: si alguna página concreta necesita otro
     encuadre, se redefinen en su modificador sin duplicar el degradado.
     Comprobado en el caso difícil (/vehiculos-historicos/: texto largo
     hasta el 40% sobre una foto oscura) y en el fácil
     (/fotografia-profesional/). */
  --fade-solido: 52%;
  --fade-fin: 78%;

  /* La máscara vivía en un segundo bloque `.fade-media-right` justo debajo,
     separado solo porque el comentario de aquí arriba es largo. Era el sexto
     aviso de selector duplicado de stylelint y no había ninguna propiedad
     repetida entre los dos, así que fusionarlos es cero píxeles de cambio. */
  -webkit-mask-image: linear-gradient(to left, #000 var(--fade-solido), transparent var(--fade-fin));
  mask-image: linear-gradient(to left, #000 var(--fade-solido), transparent var(--fade-fin));
}
.fade-media-right::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(to left, transparent var(--fade-solido), var(--split-fade-color) var(--fade-fin));
  pointer-events: none;
}
/* ---------- Móvil: la foto pasa a ser el FONDO del bloque ----------
   Antes, en móvil el bloque se apilaba (texto y debajo la foto como una
   tarjeta suelta) y el fundido iba hacia abajo. Eso no fundía nada:
   detrás de la foto no había nada con lo que fundirse, así que solo
   borraba el cuarto inferior contra el fondo de la página. Medido en
   producción a 375px: de 257px de alto, los 64 de abajo se disolvían.

   Ahora se replica el mecanismo de escritorio: la foto es una capa de
   fondo de verdad (`position: absolute`, z-index 0) y el texto flota por
   encima (z-index 2), disolviéndose la una en el otro. Lo único que
   cambia respecto a escritorio es el eje: allí el degradado es
   horizontal —el texto ocupa la columna izquierda— y aquí vertical.

   POR QUÉ UNA BANDA Y NO EL BLOQUE ENTERO. En escritorio el bloque es
   apaisado (~1200x460, 2.6:1) y la foto 1.5:1, así que la cubre sin
   despeinarse. En móvil el bloque es 343x840 — 0.41:1 — y para
   rellenarlo habría que ampliar la foto a 1259px de ancho sobre una caja
   de 343: se perdería el 73% del encuadre y el coche quedaría en una
   tira vertical. Medido. Por eso la capa de fondo ocupa una banda
   apaisada de 340px en la parte de arriba y se disuelve hacia el texto.

   LOS NÚMEROS EN PX Y NO EN %. El alto del texto cambia mucho de una
   página a otra (439px en /vehiculos-historicos/, más en /contacto/), y
   con porcentajes el punto de disolución se movería en cada una. En px
   el degradado acaba SIEMPRE en el mismo sitio: sólido hasta 180px
   —donde está el coche—, transparente del todo en 320px, y el texto
   empieza en 250px + el relleno propio de .split-hero__content. Medido
   en tres páginas: la opacidad de la foto justo detrás del h1 es 0, así
   que el texto es legible pase lo que pase. */
@media (max-width: 959px) {
  /* El hero de Inicio queda fuera a propósito (de ahí los `:not`): su
     texto mide 619px —eyebrow, titular, entradilla, dos botones y cuatro
     sellos de confianza— y una banda de 340px encima empujaría los
     botones de acción fuera de la primera pantalla. Se queda como se
     dejó en RC61: foto entera y sin fundido. */
  .split-hero { position: relative; }
  .split-hero__media:not(.hero-media) {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 340px;
    aspect-ratio: auto;
    margin: 0;
    z-index: 0;
  }
  /* 45% y no el centro: en estas fotos el coche está por debajo del eje,
     así que subir el encuadre lo deja entero dentro del tramo sólido. */
  .split-hero__media:not(.hero-media) img { object-position: center 45%; }
  .split-hero__content:not(.hero-text) {
    position: relative;
    z-index: 2;
    padding-top: 250px;
  }
  /* Los mismos dos puntos de la versión de escritorio, pero medidos
     desde arriba y en píxeles. Se redefinen las VARIABLES en vez de
     escribir otra vez el degradado, para que una página concreta pueda
     ajustar el fundido también en móvil con solo cambiar estos dos
     números — que es justo para lo que se hicieron las variables (ver el
     comentario de .fade-media-right). Antes iban incrustados en el
     `linear-gradient` y no había forma de tocarlos sin duplicar la regla
     entera. Los valores son los mismos: cero píxeles de cambio. */
  .fade-media-right:not(.hero-media) {
    --fade-solido: 180px;
    --fade-fin: 320px;

    -webkit-mask-image: linear-gradient(to bottom, #000 var(--fade-solido), transparent var(--fade-fin));
    mask-image: linear-gradient(to bottom, #000 var(--fade-solido), transparent var(--fade-fin));
  }
  .fade-media-right:not(.hero-media)::after {
    background: linear-gradient(to bottom, transparent var(--fade-solido), var(--split-fade-color) var(--fade-fin));
  }
}

/* ---------- Hero de Inicio (usa .split-hero por debajo) ---------- */
/* El hueco entre la línea divisoria de la cabecera y el hero era de
   64px (--space-xl) y dejaba una franja vacía nada más entrar. Baja a
   24px: un espacio leve, suficiente para que la foto no quede pegada a
   la línea. El de abajo no se toca — ahí sí hace falta separación con la
   sección siguiente. */
.hero {
  padding-block: var(--space-md) var(--space-lg);
}
/* Por debajo de 960px el hero se apila y el TEXTO es lo primero, así que
   a los 24px de arriba se les sumaban los 40 de relleno propio de
   .split-hero__content y el hueco real acababa siendo de 77px. Medido.
   Se quita ese relleno superior solo aquí: en las cabeceras interiores
   hace falta, porque ahí el texto va por debajo de la banda de foto. */
@media (max-width: 959px) {
  .hero .hero-text { padding-top: 0; }
}

/* PC (>=1200px): velo suave DEBAJO del texto del hero.
   Aquí la foto no llega a estar sólida detrás del texto —el degradado la
   deja al 78% en el borde derecho de la barra de confianza— pero ese 22%
   basta para que la rueda asome bajo "Seguridad" y moleste al leer.
   Medido a 1440px.
   En vez de mover o recortar la foto, se interpone un velo del color de
   la página que se desvanece hacia la derecha: donde hay letras el fondo
   queda limpio y donde no las hay la foto se ve intacta. El corte va al
   62% para que el velo muera dentro de la columna de texto (que nunca
   pasa del 48%) y no aparezca un borde recto en mitad de la foto.
   `z-index: -1` lo deja por detrás de las letras pero por delante de la
   imagen: .hero-text ya crea su propio contexto de apilado con
   `z-index: 2`, así que el -1 no se escapa por debajo de la foto. */
/* Velo SOLO bajo el último sello de confianza ("Seguridad").
   Es el único que cae sobre la parte sólida de la foto: la columna de
   texto acaba en el 48% y el degradado deja la foto entera desde el 52%
   contando por la derecha, así que justo ese ítem queda encima de la
   rueda. Medido a 1024px: opacidad 100% de la foto detrás del texto.
   El velo anterior cubría TODO el bloque de texto y aclaraba media
   cabecera sin necesidad; este solo toca donde hay problema, y el resto
   del degradado de la foto y del texto se queda exactamente como estaba.
   Solo desde 960px: por debajo la foto va apilada debajo del texto y no
   hay nada que tapar.
   `backdrop-filter` difumina la foto en ese recuadro en vez de solo
   blanquearla, así que el coche sigue intuyéndose. Si el navegador no lo
   soporta, el color de respaldo ya deja el texto legible por sí solo. */
/* SE PROBÓ A EXTENDER ESTE VELO A TODO EL BLOQUE DE TEXTO Y SE DESCARTÓ.
   El contraste medido decía que hacía falta —la entradilla se quedaba en
   1,1:1 a 960px— pero el resultado en pantalla era peor que el problema:
   un rectángulo claro sobre media cabecera que rompía el hero.
   Si algún día se retoma la legibilidad de la entradilla, el camino no es
   agrandar el velo: es mover la foto (`--fade-solido`, que pasó de 42% a
   52% el 2026-08-03 y es lo que la metió debajo del texto) o aclarar esa
   zona de la propia imagen.

   ── MEDIDO DE VERDAD EL 2026-08-30, y es peor de lo que decía la nota ──

   Muestreando los píxeles REALES de la foto contra producción (canvas
   sobre la imagen del hero, componiendo la opacidad que deja la máscara
   en cada x y calculando el contraste WCAG contra el color de cada
   párrafo, línea a línea):

     /vehiculos-historicos/  hoy 52%/85%  ->  2,44:1
     /fotografia-profesional/ hoy 66%/88% ->  1,02:1   ← texto invisible

   El peor punto de /vehiculos-historicos/ está en x=367 (a 1440px): la
   foto va al 70 % de opacidad y el píxel de debajo es rgb(10,8,7) —el
   coche, casi negro—, así que el compuesto sale rgb(81,80,79) y el texto
   es --text-muted rgb(90,95,102). Gris medio sobre gris medio.

   POR QUÉ NO SE ARREGLA CAMBIANDO EL COLOR DEL TEXTO: la zona de fundido
   va de casi blanco (izquierda) a casi negro (derecha) BAJO EL MISMO
   PÁRRAFO. Oscurecer el texto lo mejora a la izquierda y lo empeora a la
   derecha; aclararlo, al revés. No hay un color que valga para las dos
   mitades. Es estructural.

   BARRIDO DE VALORES, medido en /vehiculos-historicos/ a 1440px:

     52%/85% (hoy)  2,44    45%/72%   4,65   ← primero que pasa AA
     52%/78%        3,15    40%/68%   5,58
                            36%/64%  16,86

   Con 45%/72% la composición apenas cambia —comprobado en pantalla: el
   coche conserva su presencia y el fundido solo empieza un poco más a la
   derecha— y el texto se sale de la foto.

   NO SE HA APLICADO, y por un motivo concreto: el modelo de medida NO
   tiene en cuenta el velo extra de `.page-hero--historicos`, que llevan
   seis de las siete páginas con esta cabecera. Sus cifras salen
   pesimistas y no sirven para afinar una constante que vale para todas.
   Para cerrarlo hace falta o medir incluyendo ese velo, o decidir el
   valor mirando las siete páginas una a una. Es una línea de CSS cuando
   se decida.

   LO QUE SÍ SE HIZO (2026-08-06): dar la tarjeta a los CUATRO ítems, no
   solo al último. Que la tuviera uno de los cuatro se leía como un
   parche —y lo era—; con las cuatro iguales la barra se lee como una
   fila de tarjetas y no como tres rótulos sueltos más uno recuadrado.
   No es lo mismo que el velo descartado: aquello era UN rectángulo
   cubriendo media cabecera, esto son cuatro cajas del tamaño de su
   propio texto.

   Dos ajustes que salieron de medirlo, no de mirarlo:

   · La sangría horizontal baja de 0.7rem a 0.375rem. Las columnas miden
     122px con 24px de hueco: con 0.7rem cada tarjeta come 11,2px por
     lado y entre dos vecinas quedarían 1,6px — se verían pegadas. Con
     0.375rem quedan 12px de aire y las tarjetas miden 134px. Medido en
     producción a 1440px.
   · El filete. Sobre la parte clara de la cabecera, un fondo
     rgba(250,250,249,.78) es del mismo color que la página: los dos
     primeros ítems no mostraban tarjeta ninguna y la homogeneidad no
     llegaba. Un filete de 1px al 8% se ve sobre el fondo claro y
     desaparece sobre la foto, que es justo lo que hace falta.

   Solo desde 960px: por debajo la foto va apilada debajo del texto y no
   hay nada que tapar. `backdrop-filter` difumina la foto en el recuadro
   en vez de solo blanquearla, así que el coche se sigue intuyendo; si el
   navegador no lo soporta, el color de respaldo ya deja el texto
   legible por sí solo. */
@media (min-width: 960px) {
  .hero .trust-item {
    position: relative;
    isolation: isolate;
  }
  .hero .trust-item::before {
    content: '';
    position: absolute;
    inset: -0.5rem -0.375rem;
    z-index: -1;
    border-radius: 6px;
    pointer-events: none;
    background: rgba(250, 250, 249, 0.78);
    border: 1px solid rgba(23, 23, 23, 0.08);
    box-shadow: 0 1px 2px rgba(23, 23, 23, 0.04);
    -webkit-backdrop-filter: blur(7px);
    backdrop-filter: blur(7px);
  }
}
.hero-eyebrow {
  color: var(--action);
  font-weight: 700;
  font-size: var(--fs-eyebrow);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin-bottom: var(--space-sm);
}
.hero h1 { font-size: var(--fs-hero); }
.hero h1 em { color: var(--action); font-style: normal; }
.hero p.lead {
  font-size: 1.1rem;
  color: var(--text-muted);
  max-width: 42ch;
  margin-bottom: var(--space-md);
}
.hero-actions { display: flex; flex-wrap: wrap; gap: var(--space-sm); margin-bottom: var(--space-lg); }
.hero-actions--center { justify-content: center; margin-top: var(--space-lg); }

/* ---------- Utilidades compartidas (evitan repetir style="" inline) ---------- */
.page-header { margin-bottom: var(--space-lg); }
.lead-narrow { max-width: 60ch; margin-inline: auto; color: var(--text-muted); }
.text-center { text-align: center; }
.error-404-eyebrow { display: flex; justify-content: center; }
.error-404-search { max-width: 420px; margin: var(--space-xl) auto 0; }
/* position la fija .split-hero__media (misma clase en el elemento):
   no se repite aquí para que esta regla no gane por orden de cascada
   y deje la imagen fuera de sitio en escritorio. */
.hero-media {
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: linear-gradient(135deg, var(--color-zafiro), var(--color-carbon));
}
@media (min-width: 960px) { .hero-media { aspect-ratio: auto; min-height: 460px; height: 100%; } }
.hero-media img { display: block; width: 100%; height: 100%; object-fit: cover; }

/* En móvil el hero de Inicio NO lleva fundido.
   En escritorio la foto es un fondo a sangre por DETRÁS del texto y el
   degradado la funde con la página: ahí el efecto tiene sentido. Al
   apilarse (<960px) la foto pasa a ser una tarjeta suelta en su propia
   fila, sin nada detrás, así que el fundido no funde nada — solo borra
   el cuarto inferior contra el blanco de la página.
   Medido en producción a 375px: de los 257px de alto de la foto, los 64
   de abajo se disolvían en blanco.
   Hay que anular las DOS capas: .fade-media-right pinta el efecto con la
   máscara Y con el ::after (uno es el refuerzo del otro, ver el bloque de
   arriba), así que quitar solo una deja la mitad del degradado puesto.
   Estas reglas ganan por ORDEN, no por especificidad: `.hero-media` y
   `.fade-media-right` valen los dos 0-1-0 y el elemento lleva las dos
   clases, así que esto tiene que quedar por debajo del bloque de
   .fade-media-right en el archivo. */
@media (max-width: 959px) {
  .hero-media {
    /* 3/2 es la proporción nativa del archivo (1536x1024). Con 4/3 el
       `object-fit: cover` recortaba los laterales; a 3/2 se ve el
       encuadre completo, que además es más ancho y se parece más al
       recorte apaisado de escritorio. */
    aspect-ratio: 3 / 2;
    -webkit-mask-image: none;
    mask-image: none;
  }
  .hero-media::after { content: none; }
}

/* =========================================================
   HERO DE INICIO EN MÓVIL — «CARTEL»
   =========================================================
   Hasta aquí, en móvil la foto era una tarjeta de 343×229 al FINAL del
   hero, a 40px del texto y con el fundido apagado (el bloque de arriba).
   No acompañaba al mensaje: lo seguía. Medido: 938px de hero para dejar
   la foto de última, como si sobrara.

   Ahora la foto ocupa el bloque entero de borde a borde y el texto va
   encima, en claro, sobre un velo oscuro. El hero baja a 733px —el más
   corto de las cinco variantes que se probaron— y los botones se quedan
   en y=392, holgadamente por encima del pliegue.

   VA DESPUÉS del bloque que anula el fundido a propósito: `.hero-media` y
   `.fade-media-right` pesan lo mismo (0-1-0) y el elemento lleva las dos
   clases, así que aquí manda el ORDEN, no la especificidad. Si esto sube,
   deja de aplicarse.

   Solo móvil y solo la portada: todo va dentro de este `@media` y
   acotado a `.hero`, así que ni el escritorio ni las cabeceras interiores
   se enteran.
   ========================================================= */
@media (max-width: 959px) {

  .hero .split-hero {
    position: relative;
    gap: 0;
    isolation: isolate;
  }

  /* A sangre SIN margen negativo, y esto tiene truco: el elemento que hace
     de contenedor y el que hace de .split-hero SON EL MISMO (lleva las dos
     clases). Como `inset: 0` se mide contra la caja de RELLENO del ancestro
     posicionado, la foto ya llega sola a los dos bordes de la pantalla.
     Restarle además el relleno la sacaba 16px por lado: 32px de
     desbordamiento horizontal, medidos con window.scrollX. */
  .hero .hero-media {
    position: absolute;
    inset: 0;
    width: auto;
    height: auto;
    aspect-ratio: auto;
    z-index: 0;
    border-radius: 0;
  }

  .hero .hero-media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    /* El coche está por debajo del eje de la foto: subir el encuadre lo
       deja entero dentro del alto del bloque. Mismo valor que ya usan las
       cabeceras interiores. */
    object-position: center 45%;
  }

  /* El velo. Afloja en la franja del titular —ahí el texto es enorme y en
     negrita y aguanta— y cierra arriba y abajo, que es donde caen el
     eyebrow y los cuatro sellos. Con un velo plano habría que elegir entre
     matar el atardecer o perder los sellos sobre la carrocería roja, que
     es la parte más clara y saturada de la foto. */
  .hero .hero-media::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(
      to bottom,
      rgba(21, 23, 25, 0.90) 0%,
      rgba(21, 23, 25, 0.74) 38%,
      rgba(21, 23, 25, 0.84) 62%,
      rgba(21, 23, 25, 0.92) 100%
    );
  }

  .hero .hero-text {
    position: relative;
    z-index: 2;
    padding-block: var(--space-lg) var(--space-xl);
  }

  .hero h1 { color: var(--color-blanco); }
  .hero p.lead { color: rgba(250, 250, 249, 0.88); }

  /* LOS CUATRO SELLOS DE CONFIANZA, EN BLANCO SÓLIDO Y CON SOMBRA.
     Iban al 86% de opacidad y daban 9,9:1 —de sobra para AA— y aun así se
     leían mal. El problema no era el contraste medio sino que caen justo
     sobre los radios de la llanta y los cromados, y ahí lo que compite con
     la letra es el DETALLE, no la luminancia: un blanco translúcido deja
     que el dibujo de la rueda se transparente dentro de los trazos.
     Blanco sólido para que la letra no se mezcle, y una sombra corta que
     le da a cada trazo su propio borde oscuro contra lo que tenga detrás.
     La jerarquía con el título la sigue marcando el grosor, no el color.

     Y OJO CON EL SELECTOR, que es donde se pierde media hora: la
     descripción NO hereda el color del `.trust-item`. Es un `<span>` suelto
     dentro de un `div` sin clase, y tiene su propia regla en
     `--text-muted` (#5A5F66) que gana a cualquier herencia. Poner el color
     en `.trust-item` y dar el trabajo por hecho deja las cuatro
     descripciones en gris oscuro sobre la foto — que es exactamente como
     estaban. Hay que ir al span, y sin llevarse por delante el `.icon`,
     que es el punto rojo de la marca. */
  .hero .trust-item {
    color: var(--color-blanco);
    text-shadow: 0 1px 3px rgba(21, 23, 25, 0.85);
  }
  .hero .trust-item strong,
  .hero .trust-item span:not(.icon) {
    color: var(--color-blanco);
  }
  /* El punto rojo, aclarado igual que el eyebrow: mismo rojo, mismo fondo
     oscuro, mismo motivo. Es decorativo (`aria-hidden`), pero si los cuatro
     puntos se apagan la fila deja de leerse como una lista. */
  .hero .trust-item .icon { color: #FF6A6A; }

  /* El rojo de marca (#D40000) sobre el velo oscuro da 2,3:1 — no vale.
     Se aclara SOLO aquí; en el resto del sitio el rojo no se toca. */
  .hero .hero-eyebrow,
  .hero h1 em {
    color: #FF6A6A;
  }

  /* El botón secundario era blanco con borde: sobre fondo oscuro dejaría
     de leerse como botón y parecería una caja vacía. Se invierte. */
  .hero .hero-actions .btn-secondary,
  .hero .hero-actions a:not(.btn-primary) {
    background: transparent;
    color: var(--color-blanco);
    border-color: rgba(250, 250, 249, 0.55);
  }

  /* La línea que separa los sellos era gris claro sobre blanco. */
  .hero .trust-bar { border-top-color: rgba(250, 250, 249, 0.24); }
}

/* `1fr` es en realidad `minmax(auto, 1fr)`, y una pista `auto` no puede
   encoger por debajo del ancho de la palabra más larga de su celda. A
   320px las dos columnas sumaban 288px JUSTOS (142 + 24 de hueco + 122),
   sin un píxel de holgura: bastaba que una palabra midiera un poco más
   —otra versión de la tipografía, otro redondeo— para empujar la barra
   por encima del ancho de la pantalla y desbordar la página entera. Es lo
   que ocurría en integración continua, donde `.trust-bar` medía 305px y
   la portada se salía 13px, mientras en local pasaba por los pelos.
   `minmax(0, 1fr)` deja que la pista encoja, y `overflow-wrap` parte la
   palabra en lugar de dejar que se salga de su celda. */
.trust-bar {
  display: grid;
  gap: var(--space-md);
  grid-template-columns: repeat(2, minmax(0, 1fr));
  padding-top: var(--space-md);
  border-top: 1px solid var(--border-subtle);
}
/* Las cuatro columnas, solo a partir de 1100px.
   Estaban desde 720 y ahí no caben: a 768px cada celda se queda en
   ~150px, «Acompañamiento» mide 117 y «desplazamientos» más aún, así que
   el guionado de más abajo entraba en acción y la barra se llenaba de
   palabras partidas — «Acompaña-miento», «desplazamient os». Con dos
   columnas hasta 1099px cada celda pasa de 300px y no hay nada que
   partir. En escritorio ancho siguen las cuatro, que es donde el
   guionado sí hace falta (ver el comentario de .trust-item strong). */
@media (min-width: 1100px) { .trust-bar { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

/* "Acompañamiento" mide 117px y su columna 103: se salía 14px por encima
   del punto de "Seguridad", que es lo que se ve como si los dos ítems
   chocaran. Medido a 1200, 1280, 1366, 1440, 1600 y 1920px — pasa en
   todos, y es anterior a cualquier cambio de esta tanda.
   No se puede arreglar con el hueco: para que quepan 118px en cuatro
   columnas dentro de los 483px de la columna de texto, los huecos
   tendrían que bajar a 3px. Y encoger la letra descuadraría estos
   rótulos respecto al resto del hero. La palabra se parte con guion,
   que es lo que hace un tipógrafo con una palabra larga en una columna
   estrecha. Solo actúa cuando de verdad no cabe. */
.trust-item { display: flex; gap: 0.6em; align-items: flex-start; min-width: 0; overflow-wrap: break-word; }
.trust-item .icon { color: var(--action); flex-shrink: 0; }
/* El `min-width: 0` de arriba deja encoger a la CELDA, pero el guionado
   seguía sin dispararse: entre la celda y el texto hay este `div`, que
   como hijo de un flex vuelve a valer `min-width: auto` y por tanto no
   baja del ancho de "Acompañamiento". El div crecía hasta 117px dentro de
   una celda de 103 y el texto nunca llegaba a no caber, así que `hyphens`
   no tenía nada que partir. Medido en producción a 1440px: el
   `scrollWidth` del ítem pasa de 134 a 103 al añadir esta línea, y el
   título se parte en dos con guion.
   Sin esto, "Acompañamiento" se salía ~7px por encima del punto rojo de
   "Seguridad" en todos los anchos de 768 a 1920. */
.trust-item > div { min-width: 0; }
.trust-item strong { display: block; font-size: var(--fs-small); -webkit-hyphens: auto; hyphens: auto; }
/* La descripción también se guiona: sin esto, a 1440px «desplazamientos»
   se partía por `overflow-wrap` sin guion («desplazamient / os») en la
   primera tarjeta del hero (auditoría de apertura, 2026-09-25). Solo las
   palabras de 12 letras o más: sin el límite partía también «clási-cos» y
   «siem-pre», que sí caben. */
.trust-item span { font-size: 0.8rem; color: var(--text-muted); -webkit-hyphens: auto; hyphens: auto; hyphenate-limit-chars: 12 5 5; }

/* Última fila del buscador: la salida hacia la búsqueda completa del
   sitio (blog, noticias, eventos y FAQ, que no están en el índice del
   desplegable). Se separa con un filete y va en cuerpo menor para que se
   lea como una acción y no como un resultado más. */
.ag930-search-todos {
  border-top: 1px solid var(--border-subtle);
}
.ag930-search-todos a {
  display: block;
  padding: 0.6em 0.9em;
  font-size: var(--fs-small);
  color: var(--text-muted);
}
.ag930-search-todos a:hover,
.ag930-search-todos a:focus,
.ag930-search-todos a[aria-selected='true'] {
  color: var(--action);
}

/* ---------- Comprobador de matrícula ---------- */
/* Diseño «placa y semáforo», opción C (tema RC110, 2026-09-16): tarjeta
   oscura con las cuatro esquinas redondeadas y dos columnas en escritorio
   —texto y semáforo a la izquierda, placa y campos a la derecha—; en
   móvil, una columna con el año y la ITV en la misma fila. Los campos
   conservan name e id: el semáforo (functions.php) y plate-checker-v7.js
   no dependen del aspecto. Sobre fondo oscuro los rojos de error usan
   --action-on-dark: #A90000 no llega al 4,5:1 ahí. */
/* Fondo: carretera con doble línea amarilla (FOTOS/FONDO SEMAFORO.jpeg,
   1280 × 853, ampliada con Lanczos y un enfoque suave). `cover` con
   `center bottom`: si hay que recortar, se pierden los árboles de arriba y
   nunca el asfalto. En móvil, un recorte vertical propio centrado en las
   líneas. El velo oscuro es lo que mantiene el contraste del texto blanco
   y de los rótulos: sin él, el asfalto gris lo come. El color de fondo
   queda debajo por si la imagen no carga. */
.plate-checker {
  --plate-velo: linear-gradient(90deg, rgba(21, 23, 25, 0.9) 0%, rgba(21, 23, 25, 0.72) 42%, rgba(21, 23, 25, 0.62) 100%);
  background-color: var(--color-grafito);
  background-image: var(--plate-velo), url("../images/fondo-semaforo-1920w.jpg");
  background-image: var(--plate-velo), image-set(url("../images/fondo-semaforo-1920w.webp") type("image/webp"), url("../images/fondo-semaforo-1920w.jpg") type("image/jpeg"));
  background-size: cover;
  background-position: center bottom;
  background-repeat: no-repeat;
  color: var(--text-on-dark);
  border-radius: 20px;
  width: calc(100% - 2rem);
  max-width: 1240px;
  margin: var(--space-lg) auto 0;
  padding: clamp(2.5rem, 5vw, 4rem) clamp(1rem, 3vw, 2.5rem);
}
/* Sin esto, el margen del bloque y el relleno de la sección siguiente se
   sumaban en ~150px de hueco vacío antes de «Servicios especializados». */
.plate-checker + .section { padding-top: var(--space-xl); }
.plate-checker .container { max-width: 1140px; text-align: center; }
.plate-checker h2 { font-size: var(--fs-h2); color: var(--text-on-dark); margin-top: 1.25rem; }
.plate-checker p { color: #C9CDD1; margin-bottom: var(--space-md); }

.plate-luces {
  display: inline-flex;
  gap: 0.75rem;
  padding: 0.75rem 1.1rem;
  background: linear-gradient(#1C1E21, #0B0C0D);
  border-radius: var(--radius-pill);
  box-shadow: inset 0 0 0 2px #3A3E44, 0 10px 24px rgba(0, 0, 0, 0.45);
}
.plate-luces span { display: block; width: 26px; height: 26px; border-radius: 50%; }
.plate-luces span:nth-child(1) { background: var(--color-rojo); box-shadow: 0 0 16px 3px var(--color-rojo); }
.plate-luces span:nth-child(2) { background: #F2A900; box-shadow: 0 0 16px 3px #F2A900; }
.plate-luces span:nth-child(3) { background: #1FAE5B; box-shadow: 0 0 16px 3px #1FAE5B; }

.plate-ventajas {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 0.4rem;
  color: #C9CDD1;
  font-size: 0.95rem;
}
.plate-ventajas li::before { content: "✓"; color: #1FAE5B; font-weight: 700; margin-right: 0.5em; }

.plate-form { display: flex; flex-direction: column; align-items: center; gap: var(--space-md); }

/* Tipo de vehículo: siete radios con aspecto de botón encima de la
   placa. Compactos a propósito: lo que tiene que mandar es la placa. */
.plate-vehiculo { width: 100%; min-width: 0; margin: 0; padding: 0; border: 0; text-align: left; }
.plate-vehiculo legend {
  display: block;
  padding: 0;
  margin-bottom: 0.45em;
  font-size: 0.75rem;
  font-weight: 600;
  color: #C9CDD1;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.plate-vehiculo-opciones { display: grid; grid-template-columns: repeat(7, 1fr); gap: 0.45rem; }
/* `.plate-form` delante: la regla general `.plate-form label` (bloque,
   mayúsculas) también alcanza a estas etiquetas. */
.plate-form .plate-vehiculo-opcion {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.25rem;
  min-width: 0;
  padding: 0.5rem 0.15rem 0.4rem;
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.06);
  color: #E3E5E8;
  font-size: 0.75rem;
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: 0;
  text-transform: none;
  text-align: center;
  margin: 0;
  cursor: pointer;
  transition: background-color var(--transition-fast), border-color var(--transition-fast);
}
.plate-form .plate-vehiculo-opcion:hover { border-color: rgba(255, 255, 255, 0.35); }
/* El radio sigue ahí para el teclado y los lectores de pantalla. */
.plate-vehiculo-opcion input {
  position: absolute;
  inset: 0;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}
.plate-vehiculo-opcion svg { width: 26px; height: 26px; }
.plate-vehiculo-opcion span { max-width: 100%; hyphens: auto; }
.plate-form .plate-vehiculo-opcion:has(input:checked) {
  background: #F4F5F6;
  border-color: #fff;
  color: var(--color-carbon);
  box-shadow: 0 0 0 2px var(--action-on-dark);
}
.plate-vehiculo-opcion:has(input:focus-visible) {
  outline: 3px solid var(--action-on-dark);
  outline-offset: 2px;
}
/* La matrícula ocupa su propia fila y los otros cuatro campos van debajo.
   Los rótulos pueden partirse en dos líneas en vez de cortarse:
   `align-items: end` mantiene alineadas las casillas aunque un rótulo
   ocupe más que el de al lado. */
.plate-form-fields {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  align-items: end;
  gap: var(--space-sm);
  width: 100%;
}
.plate-form .field { text-align: left; min-width: 0; }
.plate-form .field:first-child { grid-column: 1 / -1; margin-bottom: 0.5rem; }
.plate-form label {
  display: block;
  font-size: 0.75rem;
  font-weight: 600;
  color: #C9CDD1;
  margin-bottom: 0.35em;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.plate-form input[type="text"],
.plate-form select {
  width: 100%;
  min-height: 48px;
  border: 1px solid transparent;
  border-radius: 10px;
  padding: 0.75em 0.8em;
  font-size: var(--fs-body);
  font-family: var(--font-body);
  color: var(--text-body);
  background-color: #F4F5F6;
}
/* Flecha propia: la del navegador era lo único «de serie» del bloque. */
.plate-form select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 2.4em;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%2334383E' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.9em center;
  background-size: 14px;
  cursor: pointer;
}
.plate-form input[type="text"]:not(#plate-input):focus-visible,
.plate-form select:focus-visible {
  outline: none;
  border-color: var(--action-on-dark);
  box-shadow: 0 0 0 3px rgba(255, 90, 82, 0.35);
}
.plate-form input[type="text"] { text-transform: uppercase; letter-spacing: 0.05em; }
.plate-form .plate-homologacion { margin-top: 0.4em; }
/* El campo del bastidor solo existe para los ciclomotores: lo enseña
   plate-checker-v7.js, y sin JavaScript se ve siempre (mejor una pregunta
   de más que un veredicto equivocado). */
.plate-form .plate-field-bastidor[hidden] { display: none; }
.plate-form .btn { min-height: 48px; padding-inline: 2.5rem; font-size: 1.05rem; justify-content: center; }

/* La placa. El marco (.plate-placa) lleva tres atributos que pone
   plate-checker-v7.js según lo escrito y el tipo elegido:
   · data-placa: provincial (por defecto; la de antes de 2000,
     «M-1234-AB», blanca y sin franja), actual (la de hoy, si se empieza
     por un número) o extranjera;
   · data-pais: el código ISO, que decide los colores;
   · data-sigla: las letras de la franja (E, D, NL…). Vacía, sin franja.
   La franja es un ::before del marco y no un fondo del campo: así una
   sola regla sirve para todos los países y las letras salen de
   `attr(data-sigla)` en vez de un SVG por país. Las estrellas sí son un
   SVG en data URI (con xmlns: sin él no se pinta).
   Tipografía de sistema gruesa, que es lo más parecido a la de una
   matrícula sin servir fuentes. */
.plate-placa {
  position: relative;
  --placa-fondo: #fff;
  --placa-tinta: var(--color-carbon);
  --franja: #039;
  --franja-marca: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3E%3Cg fill='%23FFCC00'%3E%3Ccircle cx='26' cy='15' r='1.6'/%3E%3Ccircle cx='24.5' cy='20.5' r='1.6'/%3E%3Ccircle cx='20.5' cy='24.5' r='1.6'/%3E%3Ccircle cx='15' cy='26' r='1.6'/%3E%3Ccircle cx='9.5' cy='24.5' r='1.6'/%3E%3Ccircle cx='5.5' cy='20.5' r='1.6'/%3E%3Ccircle cx='4' cy='15' r='1.6'/%3E%3Ccircle cx='5.5' cy='9.5' r='1.6'/%3E%3Ccircle cx='9.5' cy='5.5' r='1.6'/%3E%3Ccircle cx='15' cy='4' r='1.6'/%3E%3Ccircle cx='20.5' cy='5.5' r='1.6'/%3E%3Ccircle cx='24.5' cy='9.5' r='1.6'/%3E%3C/g%3E%3C/svg%3E");
}
.plate-form #plate-input {
  height: 84px;
  padding: 0 1rem;
  font-family: "Arial Black", "Segoe UI Black", system-ui, sans-serif;
  font-size: clamp(1.8rem, 4vw, 2.6rem);
  font-weight: 800;
  letter-spacing: 0.14em;
  text-align: center;
  color: var(--placa-tinta);
  border: 3px solid var(--color-carbon);
  border-radius: 10px;
  background: var(--placa-fondo);
  box-shadow: 0 0 0 4px var(--color-blanco), 0 14px 30px rgba(0, 0, 0, 0.4);
  transition: padding 0.2s ease, background-color 0.2s ease;
}
.plate-placa::before,
.plate-placa::after {
  position: absolute;
  top: 3px;
  bottom: 3px;
  width: 44px;
  pointer-events: none;
}
.plate-placa:not([data-sigla=""])::before {
  content: attr(data-sigla);
  left: 3px;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding-bottom: 10px;
  border-radius: 7px 0 0 7px;
  background: var(--franja) var(--franja-marca) no-repeat center 12px / 30px;
  color: #fff;
  font: 700 1.1rem/1 Arial, sans-serif;
}
.plate-placa:not([data-sigla=""]) #plate-input { padding-left: 60px; }
.plate-placa[data-sigla="NL"]::before,
.plate-placa[data-sigla="UK"]::before,
.plate-placa[data-sigla="CH"]::before { font-size: 0.95rem; }
.plate-placa[data-sigla="USA"]::before { font-size: 0.8rem; }

/* Colores por país: los rasgos que la hacen reconocible de un vistazo. */
.plate-placa[data-pais="NL"],
.plate-placa[data-pais="GB"] { --placa-fondo: #F7C600; }
.plate-placa[data-pais="GB"] { --franja: #012169; --franja-marca: none; }
.plate-placa[data-pais="BE"] { --placa-tinta: #A3141E; }
.plate-placa[data-pais="CH"] { --franja: #D52B1E; --franja-marca: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3E%3Cpath fill='%23fff' d='M12 5h6v7h7v6h-7v7h-6v-7H5v-6h7z'/%3E%3C/svg%3E"); }
.plate-placa[data-pais="US"] { --franja: #1B2A4A; --franja-marca: none; }
/* Colores por vehículo, los de la DGT para la placa española actual:
   ciclomotor, fondo amarillo; remolque (caravana), fondo rojo con letras
   negras; vehículo especial (agrícola), letras rojas. La provincial
   antigua se queda en blanco y negro: de esa no hay una norma de color
   que podamos citar. */
.plate-placa[data-pais="ES"][data-placa="actual"][data-vehiculo="ciclomotor"] { --placa-fondo: #F7C600; }
.plate-placa[data-pais="ES"][data-placa="actual"][data-vehiculo="caravana"] { --placa-fondo: #C8102E; }
.plate-placa[data-pais="ES"][data-placa="actual"][data-vehiculo="caravana"] #plate-input::placeholder { color: #4A0B16; }
.plate-placa[data-pais="ES"][data-placa="actual"][data-vehiculo="agricola"] { --placa-tinta: #C8102E; }
/* Francia, Italia y Portugal llevan también una franja a la derecha. */
.plate-placa[data-pais="FR"]::after,
.plate-placa[data-pais="IT"]::after,
.plate-placa[data-pais="PT"]::after {
  content: "";
  right: 3px;
  width: 30px;
  border-radius: 0 7px 7px 0;
  background: #039;
}
.plate-placa[data-pais="PT"]::after { background: #F7C600; }
.plate-placa[data-pais="FR"] #plate-input,
.plate-placa[data-pais="IT"] #plate-input,
.plate-placa[data-pais="PT"] #plate-input { padding-right: 42px; }

.plate-form #plate-input::placeholder { color: #8A8F96; }
.plate-form #plate-input:focus-visible {
  outline: 3px solid var(--action-on-dark);
  outline-offset: 6px;
}

/* Aviso bajo la placa: qué país se ha supuesto, o si es extranjera. */
.plate-aviso {
  margin: 0.9rem 0 0;
  color: #E3E5E8;
  font-size: 0.88rem;
  line-height: 1.45;
}
.plate-aviso-accion {
  margin-left: 0.4em;
  padding: 0;
  border: 0;
  background: none;
  color: var(--action-on-dark);
  font: inherit;
  font-weight: 600;
  text-decoration: underline;
  cursor: pointer;
}
.plate-form .plate-pais { margin-top: 0.4em; }
/* Con el país abierto, la casilla del tipo crece hacia abajo y el
   `align-items: end` de la rejilla bajaba el año a la altura del país. */
.plate-form-fields:has(#plate-pais:not([hidden])) .field:nth-child(3) { align-self: start; }

@media (min-width: 901px) {
  .plate-checker .container {
    display: grid;
    grid-template-columns: minmax(260px, 0.8fr) 1.4fr;
    column-gap: 3rem;
    align-items: center;
    text-align: left;
  }
  .plate-form .btn { align-self: stretch; }
  /* La columna izquierda ocupa la altura del formulario y reparte su
     contenido: con la fila de vehículos el formulario creció y el texto,
     centrado, dejaba dos huecos grandes arriba y abajo. */
  .plate-intro {
    align-self: stretch;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    gap: var(--space-md);
  }
  .plate-intro-texto p { margin-bottom: 0; }
  .plate-luces { align-self: flex-start; }
}
@media (max-width: 900px) {
  /* Una sola columna: el texto va encima del formulario, velo uniforme. */
  .plate-checker {
    --plate-velo: linear-gradient(rgba(21, 23, 25, 0.82), rgba(21, 23, 25, 0.7));
    background-image: var(--plate-velo), url("../images/fondo-semaforo-960w.jpg");
    background-image: var(--plate-velo), image-set(url("../images/fondo-semaforo-960w.webp") type("image/webp") 1x, url("../images/fondo-semaforo-1920w.webp") type("image/webp") 2x, url("../images/fondo-semaforo-960w.jpg") type("image/jpeg") 1x);
  }
  .plate-intro { text-align: center; }
  .plate-ventajas { display: none; }
}
@media (max-width: 600px) {
  .plate-checker {
    background-image: var(--plate-velo), url("../images/fondo-semaforo-movil-720w.jpg");
    background-image: var(--plate-velo), image-set(url("../images/fondo-semaforo-movil-720w.webp") type("image/webp"), url("../images/fondo-semaforo-movil-720w.jpg") type("image/jpeg"));
  }
}
@media (max-width: 480px) {
  .plate-checker { width: calc(100% - 1.5rem); padding: 1.75rem 1rem; margin-top: var(--space-md); }
  .plate-checker p { margin-bottom: var(--space-sm); }
  .plate-luces { gap: 0.7rem; padding: 0.6rem 1rem; }
  .plate-luces span { width: 24px; height: 24px; }
  .plate-form-fields { column-gap: 0.6rem; row-gap: 0.8rem; }
  /* Tipo, bastidor y cambios a lo ancho; año e ITV comparten fila.
     Por el campo que llevan dentro y no por posición: con `nth-child(5)`
     el bastidor (oculto, pero hijo igual) descolocaba la cuenta, la ITV
     salía a lo ancho y el año y los cambios a media anchura (auditoría
     integral 2026-09-28). */
  .plate-form .field:has(#plate-type),
  .plate-form .field:has(#plate-cambios),
  .plate-form .plate-field-bastidor { grid-column: 1 / -1; }
  .plate-form #plate-input { height: 72px; font-size: 1.7rem; letter-spacing: 0.1em; }
  .plate-placa::before { width: 38px; }
  .plate-placa:not([data-sigla=""])::before { padding-bottom: 7px; background-position: center 8px; background-size: 26px; }
  .plate-placa:not([data-sigla=""]) #plate-input { padding-left: 48px; }
  .plate-placa::after { width: 24px; }
  .plate-form .btn { width: 100%; }
  .plate-vehiculo-opciones { grid-template-columns: repeat(4, 1fr); gap: 0.35rem; }
  /* 12px como mínimo (test:responsive); las palabras largas se parten
     con guion (`hyphens`, con el `lang="es"` de la página). */
  .plate-form .plate-vehiculo-opcion { padding: 0.45rem 0.1rem 0.4rem; }
  .plate-vehiculo-opcion svg { width: 24px; height: 24px; }
}

/* Campo obligatorio sin rellenar al intentar avanzar al semáforo —
   marcado en rojo por plate-checker-v7.js sin recargar la página. La
   casilla sigue siendo clara, así que conserva el rojo oscuro; el rótulo
   está sobre el fondo oscuro y usa el rojo aclarado. */
.plate-form .field.is-invalido input,
.plate-form .field.is-invalido select {
  border-color: #A90000;
  background-color: #FDECEC;
}
.plate-form .field.is-invalido #plate-input { background-color: #FDECEC; }
.plate-form .field.is-invalido label { color: var(--action-on-dark); }

/* ---------- Grid de servicios ---------- */
.section { padding-block: var(--space-2xl); }
.section-alt { background: var(--bg-section-alt); }
.section-heading { text-align: center; margin-bottom: var(--space-lg); }
.section-heading--left { text-align: left; margin-bottom: var(--space-md); }
.section-heading .kicker {
  display: block;
  color: var(--action);
  font-size: var(--fs-eyebrow);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin-bottom: 0.4em;
}
.section-heading h2 { font-size: var(--fs-h2); }

.card-grid {
  display: grid;
  gap: var(--space-md);
  grid-template-columns: 1fr;
}
@media (min-width: 640px) { .card-grid { grid-template-columns: repeat(2, 1fr); } }
/* Las tarjetas de servicio llevan foto (ver .service-card-thumb): dos por
   línea las mantiene grandes y nítidas; en pantallas muy anchas pasan a
   tres para no dejar la sección demasiado larga. */
@media (min-width: 1240px) { .card-grid.cols-6 { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 960px) { .card-grid.cols-3 { grid-template-columns: repeat(3, 1fr); } }

.service-card {
  background: #fff;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-card);
  padding: var(--space-md);
  box-shadow: var(--shadow-card);
  transition: transform var(--transition-base), box-shadow var(--transition-base);
}
.service-card:hover { transform: translateY(-2px); box-shadow: 0 8px 24px rgba(21,23,25,0.08); }
.service-card-thumb {
  display: block;
  aspect-ratio: 3 / 2;
  margin: calc(var(--space-md) * -1) calc(var(--space-md) * -1) var(--space-sm);
  border-radius: var(--radius-card) var(--radius-card) 0 0;
  overflow: hidden;
}
.service-card-thumb img { display: block; width: 100%; height: 100%; object-fit: cover; }
.service-card-heading { display: flex; align-items: center; gap: 0.5em; margin-bottom: var(--space-sm); }
.service-card .icon {
  width: auto; height: auto;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 0.6em;
  color: var(--action);
  margin-bottom: 0;
}
.service-card h3 { font-size: var(--fs-h3); margin: 0; }
.service-card p { color: var(--text-muted); font-size: var(--fs-small); margin-bottom: var(--space-sm); }
.service-card .card-link { color: var(--action); font-weight: 600; font-size: var(--fs-small); }

/* Bloque separado de trámites DGT convencionales (fondo gris, deliberadamente
   distinto a las tarjetas de clásicos de arriba para no mezclarlos) */
.dgt-block { background: var(--bg-section-alt); }
/* El fundido de la imagen debe apagarse hacia el mismo gris que el
   fondo de esta sección (no hacia el blanco general de la página),
   si no se notaría una costura en el punto donde termina. */
.dgt-block .fade-media-right { --split-fade-color: var(--bg-section-alt); }
.dgt-block-hero { min-height: 320px; margin-bottom: var(--space-lg); }
.dgt-block .card-grid { grid-template-columns: 1fr; }
@media (min-width: 480px) { .dgt-block .card-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 960px) { .dgt-block .card-grid { grid-template-columns: repeat(4, 1fr); } }
.dgt-block .service-card { box-shadow: none; }

/* ---------- Testimonios (Inicio) ---------- */
.ag930-testimonios {
  display: grid;
  gap: var(--space-md);
  margin-top: var(--space-lg);
  grid-template-columns: 1fr;
}
@media (min-width: 640px) { .ag930-testimonios { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 960px) { .ag930-testimonios { grid-template-columns: repeat(3, 1fr); } }
.ag930-testimonio {
  background: #fff;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-card);
  padding: var(--space-md);
  box-shadow: var(--shadow-card);
  margin: 0;
}
.ag930-testimonio blockquote { margin: 0 0 var(--space-sm); color: var(--text-strong); }
.ag930-testimonio blockquote p:first-child::before { content: "\201C"; }
.ag930-testimonio blockquote p:last-child::after { content: "\201D"; }
.ag930-testimonio figcaption { display: flex; flex-direction: column; font-size: var(--fs-small); }
.ag930-testimonio figcaption strong { color: var(--text-strong); }
.ag930-testimonio figcaption span { color: var(--text-muted); }

/* ---------- Bloque oscuro premium ---------- */
/* Sin radio de esquina ni recorte en el bloque entero: la fusión de la
   imagen con el fondo oscuro (más abajo) hace innecesaria la caja. */
.dark-block {
  background: var(--bg-dark);
  color: var(--text-on-dark);
  display: grid;
}
@media (min-width: 900px) { .dark-block { grid-template-columns: 1fr 1fr; align-items: stretch; } }
/* `min-width: 0`: como hijo de rejilla, .content arrastra el
   `min-width:auto` por defecto y no puede encoger por debajo del ancho
   mínimo de su contenido. Con 40px de relleno a cada lado eso lo dejaba
   en 325px dentro de un contenedor de 288px a 320px de pantalla.
   Por debajo de 640px el bloque ya está apilado, así que se reduce el
   relleno lateral: a esa anchura, 40px se comen el 28% de la pantalla. */
.dark-block .content { padding: var(--space-xl) var(--space-lg); min-width: 0; }
@media (max-width: 640px) {
  .dark-block .content { padding: var(--space-lg) var(--space-md); }
}
.dark-block h2 { color: var(--text-on-dark); font-size: var(--fs-h2); }
.dark-block p { color: rgba(250,250,249,0.75); margin-bottom: var(--space-md); }
.dark-block ul { margin-bottom: var(--space-md); }
.dark-block li { display: flex; gap: 0.6em; margin-bottom: 0.6em; font-size: var(--fs-small); }
.dark-block li .icon { color: var(--action); }

/* ---------- Checklist "¿Qué nos hace diferentes?" (Nosotros) ---------- */
/* Mismo patrón visual que .dark-block li: icono de check en color de
   acento delante del texto, en vez del punto por defecto (ul ya tiene
   list-style:none global). */
.nosotros-intro li { display: flex; gap: 0.6em; margin-bottom: 0.6em; }
.nosotros-intro li .icon { color: var(--action); flex-shrink: 0; }
/* Entre 900 y 959px el bloque ya va a dos columnas pero manda el fundido
   vertical de más abajo; estas dos variables solo cuentan ahí si alguien
   quita esa regla. Desde 960px las sustituye la foto a sangre. */
@media (min-width: 900px) {
  .dark-block .media {
    --fade-solido: 70%;
    --fade-fin: 98%;
  }
}
.dark-block .media {
  position: relative;
  min-height: 280px;
  background-size: cover;
  background-position: center;
}
.dark-block .fade-media-right { --split-fade-color: var(--bg-dark); }
/* Escritorio: la foto ocupa TODO el bloque y un velo zafiro la tapa por
   detrás del texto (2026-10-05). Antes vivía en su media columna con un
   fundido de ~160px, y entre el final del texto y el principio de la
   foto quedaba media caja de panel liso.

   El velo hace de fondo del texto: liso hasta el 0, 93% de opacidad
   hasta el 36% (donde acaban las líneas más largas), 60% al 50% y
   transparente al 66%. Medido con el texto oculto, el píxel más claro
   (percentil 98) bajo cualquier línea deja el subtítulo —el peor, por
   su 0,75 de opacidad— en 5,2:1, frente a 7,1:1 sobre liso. Por debajo
   de ~0,9 en el 36% el respaldo del asiento se lee detrás de la lista:
   no bajes el velo sin volver a medir. La sombra del texto es margen,
   no lo que da el contraste.

   Se reutiliza el ::after de .fade-media-right como velo y se quita su
   máscara: los dos haciendo el mismo trabajo en sentidos opuestos
   dejaban la foto a medias. `70%` de encuadre lleva el asiento a la
   zona visible. Solo desde 960px, donde acaba el fundido vertical del
   móvil (más abajo). */
@media (min-width: 960px) {
  .dark-block { position: relative; }
  .dark-block .content { position: relative; z-index: 1; }
  .dark-block .media {
    position: absolute;
    inset: 0;
    min-height: 0;
    background-position: 70% center;
    -webkit-mask-image: none;
    mask-image: none;
  }
  .dark-block .media::after {
    background: linear-gradient(to right,
      var(--bg-dark) 0,
      color-mix(in srgb, var(--bg-dark) 93%, transparent) 36%,
      color-mix(in srgb, var(--bg-dark) 60%, transparent) 50%,
      transparent 66%);
  }
  .dark-block .content :is(h2, p, li) { text-shadow: 0 1px 12px rgb(0 0 0 / 45%); }
}
/* El bloque oscuro no entra en el tratamiento de "foto de fondo" de
   arriba, y por dos motivos:

   1. Su foto no es un <img> dentro de .split-hero__media, sino un `div`
      con `background-image` (ver dark-block.php), así que las reglas de
      posición de allí no le llegan. Lo que SÍ le llegaría es la máscara
      en px, y le sentaría mal: mide 280px de alto y el degradado
      genérico la dejaría al 29% de opacidad en su borde inferior.
   2. No es una cabecera. Subir la foto arriba invertiría el orden de una
      sección de mitad de página, que se lee texto → foto.

   Aquí basta con fundir el borde de ARRIBA de la foto contra el panel
   oscuro que tiene justo encima: desaparece el corte horizontal duro y
   la foto queda cosida al texto, que era el objetivo. Funciona
   precisamente aquí porque el color al que funde (--bg-dark) coincide
   con el tono de la foto; en las secciones claras con fotos oscuras el
   mismo degradado produce una neblina gris.
   Gana a la regla genérica por orden: las dos valen 0-2-0. */
@media (max-width: 959px) {
  .dark-block .fade-media-right {
    -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 90px);
    mask-image: linear-gradient(to bottom, transparent 0, #000 90px);
  }
  .dark-block .fade-media-right::after {
    background: linear-gradient(to bottom, var(--split-fade-color) 0, transparent 90px);
  }
}

/* ---------- Editorial + eventos ---------- */
/* CORRECCIÓN: sin align-items:start, el grid de 2 columnas estiraba la
   columna de tarjetas (izquierda) a la altura del panel de eventos
   (derecha) por el stretch por defecto de CSS Grid — y como las
   tarjetas no tenían ninguna regla para repartir ese espacio de más,
   se quedaba en blanco debajo del texto. Con align-items:start cada
   columna mide solo lo que necesita su propio contenido. */
.editorial-layout {
  display: grid;
  gap: var(--space-lg);
  align-items: start;
}
@media (min-width: 960px) { .editorial-layout { grid-template-columns: 2.2fr 1fr; } }
.article-card {
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-card);
  overflow: hidden;
  background: #fff;
}
/* CORRECCIÓN: .thumb es un <a>, inline por defecto — sin display:block
   el aspect-ratio no se aplicaba nunca (una caja inline no lo admite),
   así que la miniatura no reservaba alto ninguno. */
.article-card .thumb { display: block; aspect-ratio: 4/3; background: var(--color-zafiro); }
.article-card .thumb img { width: 100%; height: 100%; object-fit: cover; }
.article-card .body { padding: var(--space-sm); }
.article-card .cat {
  display: inline-block;
  color: var(--action);
  font-size: var(--fs-eyebrow);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 0.4em;
}
.article-card h3 { font-size: 1rem; margin-bottom: 0.4em; }
.article-card .meta { color: var(--text-muted); font-size: 0.75rem; }

/* "Actualidad para apasionados" (portada): con el estirado ya
   corregido arriba, solo faltaba una miniatura más baja y menos
   relleno para que la tarjeta no se quede más alta de lo que pide su
   propio contenido — de un vistazo real, esto deja la tarjeta en
   aproximadamente un 63% de su alto anterior. */
.editorial-layout .article-card .thumb { aspect-ratio: 16/9; }
.editorial-layout .article-card .body { padding: var(--space-xs) var(--space-sm); }
/* EL RECORTE DEL TITULAR, Y POR QUÉ EL CLAMP VA EN EL ENLACE Y NO AQUÍ.
   Medido el 2026-09-07: el h3 medía 44px de alto con 54px de contenido
   dentro, así que la tercera línea del título salía partida por la
   mitad — no escondida, PARTIDA, que se ve mucho peor.

   La causa es que `-webkit-line-clamp` cuenta LÍNEAS DE TEXTO, y el h3
   no tiene ninguna: su único hijo es el <a>, que es un bloque. Para el
   -webkit-box ese bloque es una caja hija, no una línea, así que el
   clamp no recorta nada; el alto lo acababa fijando el `min-height: 44px`
   del enlace y el `overflow: hidden` se comía el resto a media línea.

   Se arregla llevando el clamp al <a>, que es quien sí contiene las
   líneas.

   Y SON 4 LÍNEAS, NO 3, POR MEDIRLO CONTRA PRODUCCIÓN. Con las dos
   entradas del Docker local bastaban 3. Con las diez reales del sitio no:
   medido el 2026-09-08 a 1536px, TRES titulares ocupan cuatro líneas
   —"Caravanas históricas: los 750 kg que lo deciden todo, y qué pasa si
   la traes de fuera" es el más largo— y se quedaban con la última
   escondida. Con 4 no se recorta ninguno, y la pista entera crece 35px
   (17,6 por fila × dos filas): nada, a cambio de que el titular se lea.

   La leccion, que vale para la proxima: el contenido de local NO sirve
   para calibrar esto. Dos entradas de prueba no dicen cuanto miden diez
   titulares escritos de verdad.

   Un título de más de cuatro líneas (unos 90 caracteres a 3 columnas) sí
   se seguiría cortando — en línea entera y con puntos suspensivos, que es
   lo correcto. Si eso empieza a pasar a menudo, el arreglo es acortar
   titulares, no subir el número.

   La rejilla se encarga del resto: `grid-template-rows: repeat(2, auto)`
   da a las dos filas el alto de la tarjeta más alta de TODO el carrusel,
   así que dejar respirar al título sube la fila entera y ninguna tarjeta
   se queda corta. */
.editorial-layout .article-card h3 {
  overflow: hidden;
}
/* El titular es el enlace de la tarjeta, así que tiene que ser un
   objetivo táctil de verdad. Un título de una sola línea medía 21px de
   alto: la mitad de los 44 que pide la WCAG 2.5.8 para que un dedo
   acierte. Ocupa todo el ancho de la tarjeta —-webkit-box es de nivel
   bloque, igual que el `display: block` que había antes— y con
   min-height llega a los 44 sin mover nada de lo que ya se veía bien.
   Se nota en la prueba `test:responsive`, que cuenta cuántas zonas
   pulsables se quedan cortas: al pasar el carrusel de 4 tarjetas a 12,
   estas diez la hacían saltar. */
.editorial-layout .article-card h3 a {
  display: -webkit-box;
  -webkit-line-clamp: 4;
  -webkit-box-orient: vertical;
  overflow: hidden;
  min-height: 44px;
}

/* ------------------------------------------------------------------
   CARRUSEL HORIZONTAL COMPARTIDO (.ag930-carrusel)

   Nació para "Actualidad para apasionados" de Inicio y desde el
   2026-09-07 lo usan DOS sitios; de ahí el nombre neutro. Los dos
   consumidores, y en qué se diferencian:

     Inicio  → template-parts/editorial-events.php
               DOS filas de tarjetas .article-card (modificador
               --dos-filas). Como grid-auto-flow: column coloca las
               tarjetas de arriba abajo y luego a la derecha, cada
               columna son dos artículos: por eso allí el paso del
               carrusel avanza DOS y no uno.
     Blog    → page-templates/template-blog-hub.php
               UNA fila con las cuatro secciones (.services-hub-card).
               Antes era una parrilla de 3 columnas y la cuarta
               tarjeta se caía sola a una segunda fila.

   Lo que comparten es lo que importa: es un scroller nativo con
   scroll-snap, no un slider de translates. Sin JavaScript se sigue
   arrastrando con el dedo, con la rueda y con el teclado. Las flechas
   solo lo empujan.

   El JavaScript (assets/js/carrusel-v1.js) no sabe nada de esta
   distinción: mide el ancho real del primer hijo de la pista, así que
   funciona igual con una fila o con dos, y con las columnas que haya
   visibles en ese momento.
   ------------------------------------------------------------------ */
.ag930-carrusel { position: relative; }

.ag930-carrusel__pista {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 100%;
  gap: var(--space-md);
  align-items: start;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  /* La animación del carrusel vive AQUÍ, no en el JavaScript, y es a
     propósito. El JS se limita a asignar `scrollLeft`; quien lo anima es
     esta línea. Dos cosas se ganan con ello: el bloque de
     prefers-reduced-motion de más abajo apaga la animación por sí solo,
     sin que el JS tenga que consultar la preferencia por su cuenta y
     duplicar el criterio; y donde el desplazamiento suave no exista, el
     carrusel salta pero sigue funcionando, en vez de quedarse quieto —
     que es lo que pasaba pasando `behavior: "smooth"` desde el JS. */
  scroll-behavior: smooth;
  /* OJO CON EL RECORTE VERTICAL: `overflow-x: auto` obliga al eje Y a
     calcular `auto` también aunque no se declare, así que lo que sobresalga
     por arriba o por abajo se corta. Estos rellenos son los que dejan
     sitio al anillo de foco del teclado y —en el hub del blog— a la
     sombra de la tarjeta y a los 2px que sube al pasar el ratón. */
  padding-top: 2px;
  padding-bottom: 2px;
  /* La barra de scroll se esconde porque su papel lo hacen las flechas,
     que son mucho más visibles. El scroller sigue siendo scroller. */
  scrollbar-width: none;
}
.ag930-carrusel__pista::-webkit-scrollbar { display: none; }
/* `position: relative` NO es decorativo, y quitarlo rompe la página de
   una forma que no se parece en nada a su causa.
   
   Medido el 2026-09-07 en /blog-y-comunidad/: la página desbordaba 805px
   a lo ancho a 375px de ventana. El culpable eran los
   `<span class="visually-hidden">` que autogest930_enlace_destino() mete
   dentro del botón de cada tarjeta. Son `position: absolute`, y sin
   ningún ancestro posicionado DENTRO del scroller su bloque contenedor
   pasaba a ser `.ag930-carrusel` —que está fuera de la pista—, así que
   el `overflow-x: auto` de la pista no los recortaba y se llevaban el
   ancho del documento con ellos, tarjeta a tarjeta.
   
   Por eso no servía de nada subirle el overflow a la pista: lo que se
   escapaba nunca estuvo dentro de su área de recorte. Con la tarjeta
   como contexto de posicionamiento, el span se resuelve dentro de ella y
   la pista vuelve a contener todo lo suyo.
   
   Va en el carrusel y no en `.services-hub-card` a propósito: la misma
   tarjeta se usa en la parrilla de /servicios/, donde no hay scroller ni
   problema que resolver, y esto protege además a cualquier tarjeta que
   se meta en un carrusel en el futuro. */
.ag930-carrusel__pista > * { scroll-snap-align: start; position: relative; }

/* Inicio: dos filas. Sin el modificador, una. */
.ag930-carrusel__pista--dos-filas { grid-template-rows: repeat(2, auto); }

/* Hub del blog: las .services-hub-card llevan sombra y suben 2px al
   pasar el ratón, y ahí 2px de relleno no bastan (ver el aviso del
   recorte vertical, arriba). Y estiran a la altura de la fila para que
   los cuatro botones queden alineados, como en la parrilla de antes. */
.ag930-carrusel__pista--hub {
  padding-top: var(--space-xs);
  padding-bottom: var(--space-md);
  align-items: stretch;
}
/* La separación con la entradilla la daba `.services-hub-grid` con su
   margin-top; al dejar de haber parrilla hay que reponerla aquí o las
   tarjetas se pegan al título. */
.blog-hub-carrusel { margin-top: var(--space-lg); }

@media (min-width: 640px) {
  .ag930-carrusel__pista { grid-auto-columns: calc((100% - var(--space-md)) / 2); }
}
@media (min-width: 960px) {
  /* Tres columnas. En Inicio, × dos filas = los seis artículos que caben
     sin encoger la tarjeta; en el hub del blog, tres secciones a la vista
     y la cuarta a un clic de la flecha. */
  .ag930-carrusel__pista { grid-auto-columns: calc((100% - 2 * var(--space-md)) / 3); }
}

/* LAS FLECHAS. Rojas y macizas a propósito: el encargo era que se vieran
   claramente y que invitaran a pulsarse. Van en los huecos de los lados
   —el relleno del contenedor, y en Inicio además la separación con el
   panel de eventos— y NO encima de las tarjetas, que taparían un
   titular. Por eso los desplazamientos negativos solo entran a partir de
   960px, que es cuando ese hueco existe; por debajo el carrusel se
   arrastra con el dedo y las flechas no se pintan. */
.ag930-carrusel__flecha {
  display: none;
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 42px;
  height: 42px;
  padding: 0;
  border: 2px solid #fff;
  border-radius: 50%;
  background: var(--action);
  color: #fff;
  cursor: pointer;
  place-items: center;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.24);
  transition: background var(--transition-base), transform var(--transition-base);
  z-index: 2;
}
.ag930-carrusel__flecha:hover { background: var(--action-hover); }
.ag930-carrusel__flecha:active { transform: translateY(-50%) scale(0.94); }
.ag930-carrusel__flecha svg { display: block; }
.ag930-carrusel__flecha[hidden] { display: none; }

@media (min-width: 960px) {
  .ag930-carrusel__flecha { display: grid; }
  /* -24px NO es un número redondeado a ojo. La tarjeta empieza donde
     empieza la pista y su texto entra 16px (el relleno de .body), así
     que sacando el botón 24px de sus 42 quedan 18 dentro de la tarjeta:
     dos píxeles antes del texto. Medido: con 46px y -20px, la flecha
     mordía la fecha de la primera tarjeta. Y 24px es justo el
     `padding-inline` de .container (--space-md), así que el botón cae
     dentro del relleno de la página y no se sale por el borde. */
  .ag930-carrusel__flecha--anterior { left: -24px; }
  .ag930-carrusel__flecha--siguiente { right: -24px; }
  /* [hidden] tiene que seguir ganando después de reactivar el display. */
  .ag930-carrusel__flecha[hidden] { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .ag930-carrusel__pista { scroll-behavior: auto; }
  .ag930-carrusel__flecha { transition: none; }
  .ag930-carrusel__flecha:active { transform: translateY(-50%); }
}

/* Tarjetas de artículo dentro de una categoría de Blog (Noticias,
   Normativa y cambios — ver template-parts/blog-categoria.php): más
   grandes y con más presencia que las de portada, pensadas para
   invitar a pinchar — sombra, elevación al pasar el ratón y zoom suave
   de la foto, mismo lenguaje visual que .services-hub-card. */
.article-card--categoria {
  box-shadow: var(--shadow-card);
  transition: transform var(--transition-base), box-shadow var(--transition-base), border-color var(--transition-base);
}
.article-card--categoria:hover {
  transform: translateY(-4px);
  box-shadow: 0 12px 28px rgba(21,23,25,0.12);
  border-color: var(--action);
}
.article-card--categoria .thumb img { transition: transform var(--transition-base); }
.article-card--categoria:hover .thumb img { transform: scale(1.05); }
.article-card--categoria .body { padding: var(--space-md); }
.article-card--categoria h3,
.article-card--categoria h2 { font-size: 1.15rem; }
.article-card--categoria h3 a,
.article-card--categoria h2 a { transition: color var(--transition-base); }
.article-card--categoria:hover h3 a,
.article-card--categoria:hover h2 a { color: var(--action); }

/* ---------- Listado de /noticias/ y /normativa-y-cambios/ ----------
   Medido el 2026-09-06 en producción: la rejilla arrancaba a 0 px del
   borde inferior del hero —las tarjetas nacían pegadas a la foto— y a
   1536 px cada tarjeta medía 564x538, porque `.card-grid` se queda en
   dos columnas por ancho que sea la pantalla.

   Aquí se separa del hero y se pasa a tres columnas desde 1024 px, que
   deja la tarjeta en unos 370 px: más pequeña, y sobre todo más acorde
   con un listado que va a crecer. La miniatura pasa de 4/3 a 16/9 por
   lo mismo, que es lo que más alto quita.

   EL TÍTULO NO SE RECORTA. Nada de `line-clamp` ni de `overflow:
   hidden` aquí: al estrechar la tarjeta hay títulos que ocupan tres y
   cuatro líneas, y tienen que verse enteros. Las tarjetas se igualan
   en alto porque el grid las estira, no cortando texto. */
.card-grid--categorias { margin-top: var(--space-xl); }
@media (min-width: 1024px) {
  .card-grid--categorias { grid-template-columns: repeat(3, 1fr); }
}
.card-grid--categorias .article-card .thumb { aspect-ratio: 16/9; }
.card-grid--categorias .article-card--categoria .body { padding: var(--space-sm) var(--space-md) var(--space-md); }
/* El titular de estas tarjetas es un h2 desde el 2026-09-08 (ver
   template-parts/blog-categoria.php); el h3 se conserva en el selector
   porque la misma tarjeta se pinta en h3 donde cuelga de un h2. */
.card-grid--categorias .article-card--categoria h3,
.card-grid--categorias .article-card--categoria h2 { font-size: 1.05rem; line-height: 1.3; }
/* El pie de la tarjeta queda abajo aunque el título ocupe una línea
   menos que el de al lado: así las fechas se leen alineadas. */
.card-grid--categorias .article-card { display: flex; flex-direction: column; }
.card-grid--categorias .article-card .body { display: flex; flex-direction: column; flex: 1; }
.card-grid--categorias .article-card .meta { margin-top: auto; padding-top: 0.6em; }

/* ---------- Paginación (listados de categoría del blog) ---------- */
.blog-categoria-paginacion {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs);
  justify-content: center;
  margin-top: var(--space-lg);
}
.blog-categoria-paginacion .page-numbers {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 2.2em;
  height: 2.2em;
  padding-inline: 0.5em;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-card);
  color: var(--text-body);
  font-size: var(--fs-small);
}
.blog-categoria-paginacion .page-numbers.current { background: var(--action); border-color: var(--action); color: #fff; }
.blog-categoria-paginacion .page-numbers.dots { border-color: transparent; }

.events-panel {
  background: var(--bg-darker);
  color: var(--text-on-dark);
  border-radius: var(--radius-card);
  padding: var(--space-md);
}
.events-panel h3 { color: var(--text-on-dark); font-size: 1.1rem; margin-bottom: var(--space-sm); }
.events-panel-aviso { color: rgba(250,250,249,0.6); font-size: 0.85rem; }
.event-row { display: flex; gap: var(--space-sm); padding-block: var(--space-sm); border-top: 1px solid rgba(250,250,249,0.12); }
.event-row:first-of-type { border-top: none; }
.event-date { text-align: center; min-width: 46px; }
.event-date .day { font-weight: 700; color: var(--action-on-dark); font-size: 1.1rem; display: block; }
.event-date .month { font-size: var(--fs-eyebrow); text-transform: uppercase; color: rgba(250,250,249,0.6); }
.event-row .event-title { font-size: 0.875rem; }
.event-row .event-place { font-size: 0.75rem; color: rgba(250,250,249,0.6); }
.events-panel .see-all { display: inline-block; margin-top: var(--space-sm); color: var(--action-on-dark); font-weight: 600; font-size: var(--fs-small); }
.events-panel .ag930-sin-eventos { color: rgba(250,250,249,0.6) !important; }

/* ---------- Newsletter ---------- */
.newsletter {
  background: var(--bg-page);
  border-top: 1px solid var(--border-subtle);
  border-bottom: 1px solid var(--border-subtle);
}
.newsletter .container {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-md);
  align-items: center;
  justify-content: space-between;
  padding-block: var(--space-lg);
}
.newsletter-copy { display: flex; align-items: center; gap: var(--space-sm); max-width: 480px; }
.newsletter-copy .icon {
  width: 44px; height: 44px; border-radius: 50%;
  background: var(--bg-darker); color: #fff;
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.newsletter-copy h3 { font-size: 1rem; margin-bottom: 0.2em; }
.newsletter-copy p { font-size: var(--fs-small); color: var(--text-muted); margin: 0; }
/* `flex-wrap: wrap` no es decorativo: .newsletter-consent usa
   `flex-basis:100%` para ocupar su propia línea, y sin envoltura esa
   declaración no hace nada — los tres elementos se quedaban en una
   sola fila y el formulario no bajaba de 401px, desbordando la página
   a 375 y 414px (las dos anchuras de iPhone más comunes).
   `min-width: 0` permite además que el formulario, como hijo flexible
   que es, encoja por debajo del ancho intrínseco de su contenido. */
.newsletter-form {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs);
  flex: 1 1 320px;
  min-width: 0;
  max-width: 460px;
}
.newsletter-form input[type="email"] {
  flex: 1;
  /* Sin esto el campo impone su ancho por defecto (~170px) y vuelve a
     empujar el formulario por encima del ancho de la pantalla. */
  min-width: 0;
  padding: 0.85em 1em;
  border: 1px solid var(--border-plata);
  border-radius: 4px;
  font-family: var(--font-body);
}
.newsletter-consent { font-size: var(--fs-eyebrow); color: var(--text-muted); flex-basis: 100%; margin-top: 0.4em; }
/* Aviso del alta de newsletter: confirmación enviada, alta confirmada,
   baja hecha, o error. Es hijo directo de `.newsletter .container`, que
   es flex con envoltura, así que necesita `flex-basis: 100%` para ocupar
   su propia línea en lugar de competir por el ancho con el texto y el
   formulario (mismo motivo que .newsletter-consent, justo arriba).
   Solo tokens existentes: la franja lateral distingue acierto de error
   sin introducir ningún color nuevo en la paleta. */
.newsletter-aviso {
  flex-basis: 100%;
  margin: 0;
  padding: 0.8em 1em;
  background: var(--bg-section-alt);
  border-left: 3px solid var(--color-zafiro);
  border-radius: 4px;
  font-size: var(--fs-small);
  color: var(--text-body);
}
.newsletter-aviso.is-error { border-left-color: var(--color-rojo); }

/* ---------- Cabecera de página interior ---------- */
/* Las páginas con foto (Servicios 930, Trámites DGT, Profesionales,
   Nosotros) usan .split-hero + .page-hero directamente en page.php:
   título/resumen a un lado, imagen fundida con el fondo al otro — sin
   caja ni superposición de texto sobre la foto. */
.page-hero { padding-block: var(--space-lg) var(--space-xl); }

/* ---------- Título de las cabeceras interiores ---------- */
/* El título y el párrafo de entrada se distinguían solo por el tamaño
   de letra, y sobre una foto de fondo eso deja el conjunto plano. Se
   separan por tres cosas a la vez —cuerpo, color y un filete de marca—
   para que el título mande y el texto quede claramente subordinado.

   El filete va pegado al borde del contenedor y el título se
   "desangra" hacia la izquierda justo esos --space-md, de modo que el
   TEXTO del h1 siga alineado al milímetro con los párrafos de debajo:
   por eso el relleno es `--space-md menos el grosor del filete` y no
   un valor redondo. Sin esa compensación el título quedaba 5px
   desplazado respecto al resto de la columna.

   Solo a partir de 960px: por debajo la cabecera se apila y un filete
   colgando a la izquierda no aporta nada. */
@media (min-width: 960px) {
  .page-hero .split-hero__content h1 {
    font-size: clamp(2.2rem, 3.2vw + 1rem, 3.2rem);
    letter-spacing: -0.025em;
    line-height: 1.03;
    margin-left: calc(-1 * var(--space-md));
    padding-left: calc(var(--space-md) - 5px);
    border-left: 5px solid var(--action);
    margin-bottom: 0.55em;

    /* El título va en UNA línea. `max-content` le da exactamente el
       ancho que pide sin partirse, y para eso tiene que poder salirse
       de su columna: .split-hero__content está estrechada al 40-48%
       para proteger los PÁRRAFOS de la foto, pero el título se defiende
       solo con el velo de abajo.

       El tope en porcentaje (no en píxeles) es a propósito: se resuelve
       contra el ancho de la columna, así que acompaña al contenedor en
       cualquier viewport. 205% de una columna del 48% son ~98% de la
       cabecera; queda un margen para que nunca desborde la página.

       Los títulos que ni así caben en una línea siguen partiéndose, y
       está bien que lo hagan: el más largo es el de /nosotros/, que
       necesita bastante más de 1.230px a este cuerpo. Forzarlo con
       `nowrap` sería repetir el error de los botones: desbordar la
       página entera.

       (La medida original se tomó sobre «De apasionados por el motor a
       tu gestoría especializada». Ese título se cambió el 2026-09-04
       por otro más largo todavía, así que la conclusión vale igual.) */
    width: max-content;
    max-width: 215%;
    position: relative;
  }

  /* El velo. Al salirse de su columna, el título pasa por encima de la
     foto; este degradado le pone debajo el color de fondo, opaco donde
     están las letras y desvaneciéndose hacia la derecha para que no se
     vea un corte. Va en ::after con z-index negativo para quedar por
     detrás del texto pero por delante de la imagen.

     Se extiende 3em por la derecha —más allá de la última letra—
     porque si acaba justo en el borde del texto se nota el escalón.

     ESTUVO EN 8em Y ERA DEMASIADO. A 51px de cuerpo son 410px de velo
     colgando a la derecha del titular, y eso hacía dos cosas, las dos
     medidas en producción sobre 10 páginas:

       · El velo no llegaba a apagarse dentro de la foto. En el borde
         derecho de la imagen seguía al 17-29% de opacidad, o sea que
         aclaraba toda la mitad derecha de la cabecera — justo lo que se
         quiso evitar en el hero de Inicio al reducir el velo a un solo
         sello.
       · Inflaba el `scrollWidth` de la página entre 84 y 371px. No
         llegaba a producir barra horizontal (`body` lleva
         `overflow-x: hidden` y el desplazamiento real medido es 0), pero
         dejaba a la página recortando contenido en cada carga.

     Con 3em/5em, medido en /historico-grupo-a/, /nosotros/, /contacto/,
     /duplicado-permiso/ y /herencia/ a 1024, 1280 y 1440px: exceso 0 en
     todas salvo grupo-a a 1024 —donde el sobrante cae FUERA de la foto y
     es color de página sobre color de página, invisible—, el velo llega
     al borde de la foto al 0-2% y, lo que no era negociable, **el titular
     sigue en UNA línea en los tres anchos**. Se probó antes subir el
     relleno del h1 para acotar el velo a su propia caja: acotaba, sí,
     pero partía en dos el titular de grupo-a y el de /nosotros/ a 1280 y
     1440. Descartado por eso. */
  .page-hero .split-hero__content h1::after {
    content: '';
    position: absolute;
    /* Se estira bastante por arriba y por abajo (0.55em) para que el
       desvanecido vertical ocurra FUERA de las letras: si el velo
       empieza a apagarse a la altura del texto, las letras pierden
       fondo justo donde más lo necesitan. */
    inset: -0.55em -3em -0.5em calc(-1 * var(--space-md));
    z-index: -1;
    /* La parada va en `em`, NO en porcentaje. Con un porcentaje el
       desvanecido se reparte sobre el ancho del velo, así que en un
       título largo salía una transición larga y suave y en uno corto la
       misma transición comprimida en cuatro dedos: se veía el borde. Era
       la diferencia entre /historico-grupo-b/ (bien) y
       /fotografia-profesional/ (un rectángulo blanco recortado contra
       los árboles).

       Con `calc(100% - 5em)` el tramo de fundido mide siempre lo mismo
       —5em— mida lo que mida el título, así que todas las cabeceras se
       apagan igual. Y como el velo sobresale 3em por la derecha, la
       parte opaca termina 2em ANTES de la última letra: el final del
       título queda ya sobre el degradado, que es justo lo que hace que
       no se note dónde acaba.

       La diferencia entre los dos números es lo que hay que conservar si
       algún día se retocan: fundido − sobresaliente = 2em. Con eso la
       parte opaca siempre acaba a la misma distancia de la última letra,
       independientemente de lo largo que sea el título. */
    background: linear-gradient(to right, var(--bg-page) calc(100% - 5em), transparent 100%);
    /* Sin esto el velo es un RECTÁNGULO: se difumina hacia la derecha
       pero corta en seco arriba y abajo, y sobre una foto se ve la
       banda perfectamente (se notaba en /nosotros/, contra la roca del
       fondo). La máscara apaga esos dos bordes. */
    -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 30%, #000 72%, transparent 100%);
    mask-image: linear-gradient(to bottom, transparent 0%, #000 30%, #000 72%, transparent 100%);
  }

  .page-hero .split-hero__content .lead {
    font-size: 1.02rem;
    color: var(--text-muted);
    max-width: 46ch;
  }

  /* La columna de este grupo es más estrecha (40%), así que el título
     necesita un tope mayor para alcanzar el mismo ancho de cabecera. */
  /* 245% y no 235%: el `max-width` incluye el relleno y el filete
     (box-sizing: border-box), así que del tope se van 24px antes de
     llegar al texto. Con 235% el título de /nosotros/ se quedaba a
     18px de caber y seguía partiéndose. */
  .page-hero--historicos .split-hero__content h1 { max-width: 245%; }

  /* El título más largo del sitio, con diferencia: 54 caracteres que a
     51px piden 1.230 y no caben en la cabecera ni ocupándola entera.
     Baja a 2.8rem, el cuerpo justo con el que entra en una línea
     (medido: 1.076 sobre los 1.083 disponibles). Es la única página que
     necesita esta excepción. */
  [data-hero='nosotros'] .split-hero__content h1 { font-size: 2.8rem; }
}
/* Entre 960 y 1279px ese título ya va en dos líneas y ocupa casi toda
   la cabecera, así que los 3em que el velo sobresale por la derecha
   caían fuera de la página: 67px de scroll lateral a 1024
   (2026-09-17). Aquí el velo acaba donde acaba el título. */
@media (min-width: 960px) and (max-width: 1279px) {
  [data-hero='nosotros'] .split-hero__content h1::after { right: 0; }
}

/* Vehículos históricos, Servicios especializados y Transporte
   especializado: el vehículo del banner es oscuro (o el bloque de
   texto es más largo), así que estos heroes necesitan más margen de
   seguridad que el resto de cabeceras con .page-hero (que sí pueden
   dejar el texto más cerca del fundido). Solo afecta a estas páginas. */
@media (min-width: 960px) {
  .page-hero--historicos .split-hero__content {
    max-width: 40%;
    position: relative;
    z-index: 2;
  }
  /* El `:not(--fotografia)` no es un parche para una página: es la
     condición que este velo siempre tuvo implícita. Repinta el fondo
     detrás de TODO el bloque de texto, y eso solo hace falta cuando hay
     entradilla que proteger — el título ya se defiende solo con su
     propio velo en `em` (h1::after), que se desvanece y no se nota.

     Medido sobre las 15 cabeceras de producción: las siete páginas que
     llevan este velo tienen entradilla; Fotografía profesional era la
     única con velo y SIN entradilla, y justamente por eso se veía como
     un rectángulo blanco recortado contra los árboles: estaba dando
     fondo sólido a un bloque que solo contiene el h1. Y
     `.page-hero--fotografia` significa exactamente «sin resumen, solo
     título», así que la excepción se apoya en el significado de la
     clase y no en el slug.

     Con esto queda igual que /historico-grupo-a/ y /historico-grupo-b/,
     que no llevan este modificador y solo tienen el velo del título. */
  .page-hero--historicos:not(.page-hero--fotografia) .split-hero__content::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: -1;
    background: linear-gradient(to right, var(--bg-page) 80%, transparent 100%);
  }
  /* Este grupo NO redefine el degradado: solo mueve los dos puntos.
     Antes duplicaba el `mask-image` entero con 20%/55%, y eso hacía dos
     cosas malas: pisaba en silencio cualquier ajuste del fundido base
     (los valores de .fade-media-right no llegaban aquí), y dejaba la
     foto sin verse hasta el 80% contando desde la izquierda mientras el
     texto se corta al 40%. Cuarenta puntos de blanco en medio.

     Con 62% la foto sube hasta cerca del borde del texto conservando el
     margen de seguridad que justifica este grupo —el vehículo es oscuro
     o el texto es largo—, que además está reforzado por el
     .split-hero__content::before de arriba: ese repinta el fondo por
     detrás de las letras, así que la legibilidad no depende del
     fundido. */
  .page-hero--historicos .fade-media-right {
    --fade-solido: 52%;
    --fade-fin: 85%;
  }

  /* Ajustes por página. El encuadre bueno no depende solo del CSS: en
     una foto clara con un título de dos palabras se puede acercar mucho
     más que en una foto oscura con tres párrafos al lado. Por eso van
     uno a uno y medidos, no a ojo ni en bloque.

     Fotografía profesional es el caso extremo: el título acaba al 23% y
     la foto es clara y de fondo neblinoso, así que admite subir hasta
     el 66% sin que "Sesión fotográfica" pierda nada de legibilidad.
     Antes, con el 20% del grupo, la foto no aparecía hasta el 80% y
     quedaba media cabecera en blanco. */
  [data-hero='fotografia-profesional'] .fade-media-right {
    --fade-solido: 66%;
    --fade-fin: 88%;
  }

  /* Estudio de viabilidad: el 356 estaba justo debajo del título.
     Dos cosas, y la primera no es la obvia:

     `object-position` NO sirve aquí. La caja mide 1152x460 (2,5) y la
     foto es 3:2, así que `cover` la escala por el ancho y recorta SOLO
     en vertical: no hay sobrante horizontal que reencuadrar y cualquier
     valor de X da exactamente el mismo resultado. Medido en producción.
     Por eso el coche se mueve con un desplazamiento real de la imagen.

     El 9% deja el morro despejado a la derecha del título sin que el
     coche se salga por el otro lado; el hueco que queda a la izquierda
     mide justo ese 9% y cae dentro del 14% que la máscara ya borra del
     todo (--fade-fin: 86%), así que no se ve. Si algún día se toca uno
     de los dos números, hay que comprobar que el desplazamiento sigue
     siendo menor que 100% - --fade-fin, o aparecerá una banda vacía.

     Y el fundido empieza antes (52% → 62%): el título lleva su propio
     velo, así que no hace falta reservarle tanta foto desvanecida. La
     foto se ve entera desde el 38% de la caja, justo donde acaba el
     título. */
  [data-hero='estudio-viabilidad'] .fade-media-right {
    --fade-solido: 62%;
    --fade-fin: 86%;
  }
  [data-hero='estudio-viabilidad'] .split-hero__media img {
    transform: translateX(9%);
  }

  /* (Aquí hubo una excepción para el velo del título de esta página,
     que se veía como un rectángulo recortado contra los árboles. Ya no
     hace falta: el velo base mide el desvanecido en `em` en vez de en
     porcentaje, así que se apaga igual en un título de dos palabras que
     en uno de siete.) */
}

/* Páginas de servicio con varios párrafos en la cabecera (Vehículos
   históricos, Transporte, Seguros, Fotografía, Tasación...) en vez de
   una sola frase: necesitan interlineado y separación más compactos
   para no alargar la cabecera. Reglas vía .split-hero__lead-group, sin
   tocar el resto de heroes con .lead de una sola línea. */
/* En `em` y no en --space-xs: ese valor fijo eran 8px, pensados para un
   título de ~36px, y con el título a 51px el texto quedaba pegado
   —medido: 8px de hueco bajo un título de 53px de alto, una proporción
   de 0.16—. Al ir esta regla más abajo en el archivo y con la misma
   especificidad que la base, ganaba a su `margin-bottom` y lo dejaba
   sin efecto. En `em` la separación acompaña al cuerpo del título,
   incluida la excepción de /nosotros/, y sigue siendo más compacta que
   la base (0.42 frente a 0.55) que es lo que este modificador busca. */
.page-hero--transporte .split-hero__content h1 { margin-bottom: 0.42em; }

/* ---------- Bloque destacado, debajo de la cabecera ---------- */
/* Un texto corto que explica el MECANISMO del servicio, justo debajo de
   la cabecera y a lo ancho de la página (ver 'destacado' en
   autogest930_page_banners() y su renderizado en page.php). Hoy lo usa
   el hub de tasación para el párrafo de la videoperitación.

   FUERA DE LA CABECERA, Y AHÍ ESTÁ EL MOTIVO DE QUE NO LLEVE VELO. Este
   bloque estuvo dentro de .split-hero__content y hubo que recortarlo al
   76% para que sus líneas no cayeran sobre la parte de la fotografía
   donde el velo ya se transparenta. Al sacarlo del hero desaparecen las
   dos cosas: no hay foto detrás, así que no hay contraste que defender,
   y dispone del ancho entero, así que el mismo párrafo pasa de trece
   líneas a cinco y la cabecera recupera su altura de siempre.

   Centrado y en el color de acción, que es lo que pidió dirección. El
   color sale de la variable del tema y no de un rojo suelto: es el mismo
   que el filete del título de la cabecera, y así siguen cambiando los
   dos a la vez si algún día se retoca la paleta. Contraste medido sobre
   --bg-page: 5,9:1, por encima del 4,5:1 que pide WCAG AA. */
.page-destacado {
  margin-block: var(--space-md) var(--space-lg);
  text-align: center;
}
.page-destacado p {
  margin: 0 0 0.7em;
  color: var(--action);
  font-size: 1.05rem;
  line-height: 1.65;
  text-wrap: pretty;
}
.page-destacado p:last-child { margin-bottom: 0; }

@media (max-width: 599px) {
  /* A 375px el ancho de la página son 343: el mismo párrafo pasa de
     cinco líneas a doce, y centrado cada una empieza en un sitio. Se
     baja el cuerpo lo justo para recortar un par de líneas sin bajar de
     los 16px que pide la prueba de tamaño mínimo de texto. */
  .page-destacado p { font-size: 1rem; line-height: 1.6; }
}

/* ---------- Tasación y peritaje: encuadre propio de su cabecera ----------
   La cabecera de esta página se queda solo con el título y la
   entradilla —el párrafo de la videoperitación se pinta ya fuera, ver
   .page-destacado—, así que es más baja que aquellas sobre las que se
   calibraron los valores de .fade-media-right y con los de fábrica el
   fundido se comía foto que no hacía falta borrar. Se redefinen SOLO las
   dos variables del degradado, que es exactamente para lo que están.

   Va acotado con [data-hero] —el atributo que page.php ya escribe con el
   slug— y no tocando la regla general, que sirve a las otras trece
   cabeceras con foto.

   Escritorio: el fundido empieza más a la izquierda (55% en vez de 52%)
   y termina antes de la zona escrita (75% en vez de 78%), de modo que el
   tramo nítido crece por la derecha sin que la foto llegue a meterse
   bajo el texto: la columna de texto no pasa del 48%.

   Móvil: la banda de foto sigue midiendo 340px, pero ahora se ve entera
   hasta 220px en vez de 180. El punto final se deja donde estaba (320),
   porque el h1 empieza en 250px + relleno y alargarlo lo dejaría sobre
   la cola de la fotografía: la opacidad detrás de las letras es la
   condición que no se puede romper.

   CADA JUEGO DENTRO DE SU MEDIA QUERY, y eso no es un adorno: los dos
   redefinen la misma variable con más peso que las reglas de fábrica,
   así que un porcentaje suelto fuera de la consulta se aplicaría también
   en móvil —donde el degradado es vertical— y dejaría el fundido
   midiendo el 55% de la altura de la banda. */
@media (min-width: 960px) {
  .page-hero[data-hero='tasacion-y-valoracion'] .fade-media-right {
    --fade-solido: 55%;
    --fade-fin: 75%;
  }
}
@media (max-width: 959px) {
  .page-hero[data-hero='tasacion-y-valoracion'] .fade-media-right:not(.hero-media) {
    --fade-solido: 220px;
    --fade-fin: 320px;
  }
}

/* EL TÍTULO SUBE Y DEJA MÁS AIRE DEBAJO. Son las dos mitades del mismo
   ajuste y por eso van juntas: si solo se agranda el hueco, la cabecera
   crece; si solo se sube el título, el hueco se queda igual. Restando
   arriba lo que se suma abajo, el bloque conserva su altura y lo único
   que cambia es dónde cae la separación.

   Los números, medidos a 1440 con el título a 51px:

     · margen inferior 0.3em -> 0.5em, o sea de 15px a 26px de hueco
       entre el título y la entradilla. La regla general está en 0.55em y
       .page-hero--transporte en 0.42em, así que esto queda entre las
       dos: se nota, pero no abre un boquete.
     · relleno superior --space-xl (64px) -> --space-md (24px), que sube
       el título 40px. Bastante más que los 11 que se han sumado abajo,
       de modo que la cabecera no crece: se acorta.

   HASTA DÓNDE SE PUEDE SUBIR. El velo que hace legible este bloque
   (.page-hero--historicos ... ::before) va con `inset: 0` sobre la
   columna, así que NO se queda quieto: se encoge con el relleno y sigue
   sobresaliendo exactamente estos 24px por encima del título y los 64
   de --space-xl por debajo del último renglón. Por eso el texto nunca
   se queda fuera de él por mucho que se suba. El suelo lo pone otra
   cosa: por debajo de --space-md el título empieza a rozar el borde
   superior de la fotografía, y ahí ya no hay velo que valga porque el
   recorte de la propia imagen termina en ese mismo punto.

   En móvil solo se toca el margen inferior. El relleno superior de ahí
   son 250px puestos para que el texto empiece por debajo de la banda de
   fotografía (ver el bloque de max-width: 959px), y recortarlo metería
   el título sobre la cola del degradado.

   Acotado con [data-hero] y no tocando .page-hero--transporte, que lo
   comparten cinco páginas. */
.page-hero[data-hero='tasacion-y-valoracion'] .split-hero__content h1 { margin-bottom: 0.5em; }
@media (min-width: 960px) {
  .page-hero[data-hero='tasacion-y-valoracion'] .split-hero__content { padding-block: var(--space-md) var(--space-xl); }
}

/* Fotografía profesional: cabecera más baja que el resto (no lleva
   'resumen', solo título) y título centrado a la altura media de la
   foto, en vez de pegado arriba como el resto de .split-hero. Se
   convierte el bloque en flex solo para esta página — el resto de
   cabeceras con foto siguen igual — y .split-hero__media (position:
   absolute) no se ve afectado por el cambio de display del padre. */
@media (min-width: 960px) {
  .split-hero.page-hero--fotografia { display: flex; align-items: center; min-height: 340px; }
  .page-hero--fotografia .split-hero__content { padding-block: 0; }
}
.split-hero__lead-group .lead {
  line-height: 1.4;
  margin: 0 0 0.6em;
}
.split-hero__lead-group .lead:last-child { margin-bottom: 0; }

/* Franja decorativa sin texto (banner del producto "Estudio de
   viabilidad" en WooCommerce): la imagen se funde hacia abajo con el
   fondo de la página en vez de llevar un velo oscuro y texto encima. */
.page-banner-no-title {
  position: relative;
  min-height: 220px;
  margin-bottom: var(--space-lg);
  overflow: hidden;
  -webkit-mask-image: linear-gradient(to bottom, #000 65%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 65%, transparent 100%);
}
@media (min-width: 720px) { .page-banner-no-title { min-height: 320px; } }
.page-banner-no-title img { display: block; width: 100%; height: 100%; object-fit: cover; }
.page-banner-no-title::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom, transparent 65%, var(--bg-page) 100%);
  pointer-events: none;
}

/* ---------- Páginas legales ---------- */
.legal-pending-notice {
  background: #FFF4E5;
  border: 1px solid #F0B429;
  color: #7A4E00;
  border-radius: 6px;
  padding: 1em 1.25em;
  font-size: 0.875rem;
  margin-bottom: var(--space-lg);
}
.legal-page .entry-content { max-width: 72ch; }
.legal-page .entry-content p { margin-bottom: 1em; }
.legal-page .entry-content ul { margin: 0 0 1em 1.25em; list-style: disc; }

/* ---------- Artículo individual del blog ---------- */
.breadcrumbs { font-size: 0.8rem; color: var(--text-muted); margin-bottom: var(--space-md); }
.breadcrumbs a { color: var(--text-muted); }
.breadcrumbs a:hover { color: var(--action); }
.entry-article { max-width: 760px; margin-inline: auto; }
.entry-header { margin-bottom: var(--space-md); }
.entry-header h1 { font-size: var(--fs-h2); margin-top: 0.3em; }
.entry-meta { font-size: 0.8rem; color: var(--text-muted); }
.entry-thumbnail { margin-bottom: var(--space-lg); border-radius: var(--radius-card); overflow: hidden; }
.entry-content { font-size: 1.05rem; line-height: var(--lh-normal); }
.entry-content p { margin-bottom: 1.25em; }
.entry-content h2 { margin-top: 2em; }

/* Introducción de formulario de servicio (Grupo A, Grupo B, Estudio de
   viabilidad...): título corto + 2 párrafos + tiempo aproximado — ver
   autogest930_form_intro_html() en functions.php. Vive dentro de
   .entry-content (de ahí el margin-top:0 en el h2, que si no heredaría
   los 2em de la regla de arriba justo debajo de la cabecera h1 de la
   página) y siempre queda seguida por el <form> del shortcode, así que
   su margen inferior es también la separación con el primer campo. */
.ag930-form-intro { margin-bottom: var(--space-lg); }
.ag930-form-intro h2 { margin-top: 0; font-size: var(--fs-h3); }
.ag930-form-intro p { color: var(--text-muted); }
.ag930-form-intro-tiempo {
  display: inline-block;
  background: var(--bg-section-alt);
  color: var(--text-strong);
  border-radius: 4px;
  padding: 0.5em 1em;
  font-size: var(--fs-small);
  margin-bottom: 0;
}
/* Seis destinos y dos etiquetas no caben en una línea de 375 px, así que
   la fila envuelve. El margin-left del «Síguenos:» lo separa del último
   icono de compartir cuando sí caben todos en la misma línea. */
.entry-share { display: flex; flex-wrap: wrap; gap: var(--space-sm); align-items: center; margin: var(--space-xl) 0; font-size: 0.85rem; }
.entry-share-label { color: var(--text-muted); }
.entry-share-label--seguir { margin-left: var(--space-sm); }
@media (max-width: 560px) {
  /* En móvil, cada etiqueta abre su propia línea: si no, «Síguenos:»
     queda colgando al final de la fila de iconos de compartir y parece
     que se refiere a ellos. */
  .entry-share-label { flex-basis: 100%; margin-left: 0; }
}
/* Iconos, no nombres. El nombre sigue ahí para el lector de pantalla
   (.visually-hidden dentro del enlace y aria-label), así que el enlace
   no se queda sin nombre accesible por llevar solo un SVG. 44x44 es el
   objetivo táctil de la casa, y aquí se cumple en todos los tamaños:
   estos tres enlaces caben de sobra. */
.entry-share-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  color: var(--action);
  border: 1px solid var(--border-subtle);
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.entry-share-link:hover,
.entry-share-link:focus-visible { background: var(--action); border-color: var(--action); color: #fff; }
.entry-share-link:focus-visible { outline: 2px solid var(--action); outline-offset: 2px; }

.entry-related { margin-top: var(--space-2xl); border-top: 1px solid var(--border-subtle); padding-top: var(--space-lg); }
.entry-related h2 { font-size: var(--fs-h3); margin-bottom: var(--space-md); }

/* ---------- Buscador del blog ----------
   Va arriba del listado y de cada artículo. Es un formulario normal, sin
   JavaScript: el combobox con lupa de la cabecera es otra cosa y busca
   por todo el sitio. */
.blog-buscador {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  max-width: 760px;
  margin: 0 auto var(--space-lg);
  padding: 0.35rem 0.35rem 0.35rem 0.85rem;
  background: #fff;
  border: 1px solid var(--border-plata);
  border-radius: 999px;
}
.blog-buscador:focus-within { border-color: var(--action); box-shadow: 0 0 0 3px rgba(212, 0, 0, 0.15); }
.blog-buscador__icono { display: flex; color: var(--text-muted); flex-shrink: 0; }
.blog-buscador__campo {
  flex: 1;
  min-width: 0;
  border: 0;
  background: transparent;
  padding: 0.5rem 0;
  font: inherit;
  font-size: 0.95rem;
  color: var(--text-body);
}
.blog-buscador__campo:focus { outline: none; }
.blog-buscador__enviar {
  flex-shrink: 0;
  min-height: 40px;
  padding: 0 1.1rem;
  border: 0;
  border-radius: 999px;
  background: var(--action);
  color: #fff;
  font: inherit;
  font-weight: 600;
  font-size: 0.875rem;
  cursor: pointer;
}
.blog-buscador__enviar:hover { background: var(--action-hover); }
.blog-buscador__enviar:focus-visible { outline: 2px solid var(--action); outline-offset: 2px; }

/* ---------- Comentarios ----------
   La plantilla es comments.php, que el tema no tenía: los comentarios
   estaban abiertos y no se pintaban en ninguna parte. Sin avatares a
   propósito (una petición a Gravatar por comentario lleva la IP del
   lector a un tercero). */
.entry-comments { margin-top: var(--space-2xl); border-top: 1px solid var(--border-subtle); padding-top: var(--space-lg); }
.entry-comments__titulo { font-size: var(--fs-h3); margin-bottom: var(--space-md); }
.entry-comments__lista { list-style: none; margin: 0 0 var(--space-lg); padding: 0; }
.entry-comments__lista .children { list-style: none; margin: var(--space-sm) 0 0; padding-left: var(--space-md); border-left: 2px solid var(--border-subtle); }
.entry-comments__lista .comment-body {
  padding: var(--space-md);
  margin-bottom: var(--space-sm);
  background: var(--bg-section-alt);
  border-radius: var(--radius-card);
}
.entry-comments__lista .comment-meta { font-size: 0.8rem; color: var(--text-muted); margin-bottom: 0.5em; }
.entry-comments__lista .comment-author .fn { font-style: normal; font-weight: 700; }
.entry-comments__lista .reply { font-size: 0.85rem; }
.entry-comments__cerrados { color: var(--text-muted); font-size: 0.9rem; }
.entry-comments__aviso { color: var(--text-muted); font-size: 0.85rem; }
/* «Conectado como X.» o «Inicia sesión para dejar un comentario». */
.entry-comments__identidad { font-size: 0.9rem; margin-bottom: 1em; }
.entry-comments__identidad a { color: var(--action); font-weight: 600; }
.entry-comments .comment-form { max-width: 640px; }
.entry-comments .comment-form label { display: block; font-weight: 600; font-size: 0.9rem; margin-bottom: 0.35em; }
.entry-comments .comment-form input[type="text"],
.entry-comments .comment-form input[type="email"],
.entry-comments .comment-form textarea {
  width: 100%;
  padding: 0.6em 0.8em;
  border: 1px solid var(--border-plata);
  border-radius: var(--radius-card);
  font: inherit;
  background: #fff;
}
.entry-comments .comment-form textarea { resize: vertical; }
.entry-comments .comment-form input:focus,
.entry-comments .comment-form textarea:focus { outline: 2px solid var(--action); outline-offset: 1px; border-color: var(--action); }

/* ---------- Página de precios ---------- */
.pricing-grid {
  display: grid;
  gap: var(--space-md);
  grid-template-columns: 1fr;
  margin-top: var(--space-md);
}
/* Separación entre bloques de la página de Precios (Clásicos / DGT /
   Especializados): el primer h2 no la necesita porque ya viene detrás
   de .section-heading (con su propio margen), pero los siguientes sí,
   al venir justo después de un .pricing-grid sin margen inferior. */
.pricing-section-heading { margin-top: var(--space-2xl); }
@media (min-width: 640px) { .pricing-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 960px) { .pricing-grid { grid-template-columns: repeat(3, 1fr); } }
.pricing-card {
  background: #fff;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-card);
  padding: var(--space-md);
  box-shadow: var(--shadow-card);
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}
.pricing-card h3 { font-size: var(--fs-h3); margin-bottom: 0; }

.pricing-price { display: flex; align-items: baseline; gap: 0.3em; }
.pricing-price-desde { font-size: 0.85rem; color: var(--text-muted); margin-right: 0.15em; }
.pricing-price-amount { font-size: 2.25rem; font-weight: 700; font-family: var(--font-display); color: var(--action); line-height: 1; }
.pricing-price-currency { font-size: 1.1rem; font-weight: 600; color: var(--action); }
.pricing-price-marker { font-size: 1.1rem; font-weight: 700; color: var(--action); margin-left: 0.1em; }
/* Servicio publicado a la espera de tarifa: ocupa el sitio del importe y
   con el mismo peso visual, para que la rejilla no se descuadre ni la
   tarjeta parezca a medio hacer. Va a 1.5rem y no a los 2.25rem del
   número porque es una palabra larga y a ese tamaño rompe la línea a
   375 px. Ver 'precio_pendiente' en el catálogo del plugin Core. */
.pricing-price-consulta { font-size: 1.5rem; font-weight: 700; font-family: var(--font-display); color: var(--action); line-height: 1; }

.pricing-note { font-size: 0.8rem; color: var(--text-muted); margin: 0; }

/* CORRECCIÓN (auditoría, hallazgo #16): desglose de IVA/tasa DGT bajo el
   precio final, replegado por defecto — mismo patrón <details> discreto
   que ya usan las FAQ (.ag930-faq-item), sin competir visualmente con
   el precio ni con el botón "Más información". */
.pricing-desglose { font-size: 0.8rem; }
.pricing-desglose summary {
  /* 24 px de alto como mínimo (WCAG 2.5.8): medía 20. Se da con relleno y
     no con min-height para que el texto no se despegue de su línea
     (auditoría de apertura, 2026-09-25; TODO.md 7 bis). */
  padding-block: 0.25em;
  cursor: pointer;
  color: var(--text-muted);
  text-decoration: underline;
  text-underline-offset: 2px;
  list-style: none;
}
.pricing-desglose summary::-webkit-details-marker { display: none; }
.pricing-desglose summary:hover { color: var(--text-strong); }
.pricing-desglose-lista { margin: 0.5em 0 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 0.25em; }
.pricing-desglose-lista li { display: flex; justify-content: space-between; gap: var(--space-sm); color: var(--text-muted); }
/* Qué incluye la base imponible en los trámites con laboratorio (2026-09-25). */
.pricing-desglose-incluye { margin: 0.4em 0 0; color: var(--text-muted); }
.pricing-card .btn { margin-top: auto; align-self: flex-start; }
.pricing-disclaimer {
  margin-top: var(--space-xl);
  padding: var(--space-md);
  background: var(--bg-section-alt);
  border-radius: var(--radius-card);
  font-size: 0.8rem;
  color: var(--text-muted);
}

/* ---------- Página de un servicio especializado individual ---------- */
.servicio-especializado-descripcion { max-width: 68ch; font-size: 1.05rem; line-height: var(--lh-normal); }
.servicio-especializado-descripcion p { margin-bottom: 1.1em; }

/* Carrusel "Sesión fotográfica": una única fila horizontal a todo el
   ancho de la página (full bleed, 100vw + margen negativo — ver
   overflow-x:hidden en body arriba, necesario para que esto no cree
   scroll horizontal), deliberadamente bajo para no alargar la página:
   el formulario de reserva sigue visible justo debajo. flex-wrap:nowrap
   + overflow:hidden en el track: nunca hay más de una fila ni scroll
   nativo (ni con rueda, ni arrastrando, ni con el dedo) — el
   desplazamiento SIEMPRE lo decide assets/js/main-v3.js con
   requestAnimationFrame(): la velocidad es proporcional a la posición
   del cursor (o del dedo, vía Pointer Events — mismo código para
   ratón y táctil) dentro del carrusel, centro parado / bordes a
   velocidad máxima, con una interpolación hacia esa velocidad en cada
   fotograma que da la aceleración y el frenado suaves sin saltos. */
.servicio-carrusel {
  width: 100vw;
  position: relative;
  left: 50%;
  right: 50%;
  margin-left: -50vw;
  margin-right: -50vw;
  margin-block: var(--space-lg);
}
.servicio-carrusel-track {
  display: flex;
  flex-wrap: nowrap;
  gap: var(--space-sm);
  height: 180px;
  overflow: hidden;
  /* El JS es el único que mueve el track (ver main-v3.js): sin esto,
     en móvil/tablet el navegador intentaría además su propio gesto de
     "arrastrar para desplazar" con el dedo, compitiendo con el cálculo
     de velocidad por posición del puntero. */
  touch-action: none;
}
/* Ancho en porcentaje del propio carrusel (full bleed): el número de
   fotos visibles se mantiene aproximadamente constante en cualquier
   pantalla de un mismo rango, sin depender de un ancho fijo en px. */
.servicio-carrusel-slide {
  position: relative;
  flex: 0 0 19%;
  height: 100%;
  border-radius: var(--radius-card);
  overflow: hidden;
  box-shadow: var(--shadow-card);
}
/* ---------- Visor de las fotos del carrusel ---------- */
/* Las miniaturas miden ~220px: son un índice, no el catálogo. Al
   pulsarlas se abren en grande (ver carrusel-visor-v1.js). */
.servicio-carrusel-slide.is-ampliable { cursor: zoom-in; }
.servicio-carrusel-slide.is-ampliable:focus-visible {
  outline: 3px solid var(--action);
  outline-offset: 3px;
}

.ag930-visor {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: none;
  align-items: center;
  justify-content: center;
  padding: var(--space-lg);
}
.ag930-visor.is-open { display: flex; }
/* Con el visor abierto la página de detrás no se desplaza. */
.ag930-visor-abierto { overflow: hidden; }

/* El fondo: la página se sigue viendo, pero desenfocada. Es lo que da
   sensación de profundidad en vez de un simple telón negro. El color
   por debajo garantiza el contraste allí donde el navegador no soporte
   `backdrop-filter` (entonces se ve el velo oscuro, sin desenfoque, y
   funciona igual). */
.ag930-visor-fondo {
  position: absolute;
  inset: 0;
  background: rgba(21, 23, 25, 0.72);
  -webkit-backdrop-filter: blur(14px) saturate(120%);
  backdrop-filter: blur(14px) saturate(120%);
}

.ag930-visor-caja {
  position: relative;
  max-width: 90vw;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-sm);
}
/* 86vh y no 100vh: el aire de alrededor es donde se ve el desenfoque, y
   es lo que separa esto de "una foto a pantalla completa". */
.ag930-visor-picture img {
  display: block;
  max-width: 90vw;
  max-height: 86vh;
  max-height: 86dvh;
  width: auto;
  height: auto;
  border-radius: var(--radius-card);
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.45);
}
.ag930-visor-pie {
  margin: 0;
  color: rgba(250, 250, 249, 0.85);
  font-size: var(--fs-small);
  text-align: center;
  max-width: 60ch;
}
.ag930-visor-contador {
  position: absolute;
  top: var(--space-md);
  left: var(--space-md);
  margin: 0;
  color: rgba(250, 250, 249, 0.7);
  font-size: var(--fs-small);
}

.ag930-visor-cerrar,
.ag930-visor-nav {
  position: absolute;
  /* 44px: mínimo pulsable con el dedo, igual que el resto del sitio. */
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: 50%;
  background: rgba(250, 250, 249, 0.14);
  color: var(--text-on-dark);
  font-size: 1.5rem;
  line-height: 1;
  cursor: pointer;
  transition: background-color var(--transition-fast);
}
.ag930-visor-cerrar:hover,
.ag930-visor-nav:hover { background: rgba(250, 250, 249, 0.28); }
.ag930-visor-cerrar:focus-visible,
.ag930-visor-nav:focus-visible { outline: 3px solid var(--action); outline-offset: 2px; }

.ag930-visor-cerrar { top: var(--space-md); right: var(--space-md); }
.ag930-visor-nav { top: 50%; transform: translateY(-50%); }
.ag930-visor-anterior { left: var(--space-md); }
.ag930-visor-siguiente { right: var(--space-md); }

@media (max-width: 640px) {
  /* En móvil los laterales se comerían la foto: la navegación baja. */
  .ag930-visor-nav { top: auto; bottom: var(--space-md); transform: none; }
  .ag930-visor-anterior { left: calc(50% - 56px); }
  .ag930-visor-siguiente { right: calc(50% - 56px); }
  .ag930-visor-picture img { max-height: 70vh; max-height: 70dvh; }
}

.servicio-carrusel-slide img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 300ms ease;
}
.servicio-carrusel-slide:hover img { transform: scale(1.04); }

/* Crédito del fotógrafo, abajo a la derecha de cada foto: en la miniatura
   (decorativo, la lámina entera ya es el botón de ampliar) y en el visor
   (enlace a su Instagram). */
.servicio-carrusel-credito,
.ag930-visor-credito {
  position: absolute;
  right: 8px;
  bottom: 8px;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 8px 3px 6px;
  border-radius: 999px;
  background: rgba(21, 23, 25, 0.55);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  color: #fff;
  font-size: 0.6875rem;
  line-height: 1.2;
  text-decoration: none;
  pointer-events: none;
}
.servicio-carrusel-credito svg,
.ag930-visor-credito svg { width: 14px; height: 14px; flex: 0 0 auto; }
.ag930-visor-foto { position: relative; }
.ag930-visor-credito { right: 12px; bottom: 12px; font-size: 0.8125rem; pointer-events: auto; }
.ag930-visor-credito svg { width: 16px; height: 16px; }
.ag930-visor-credito:hover { background: rgba(21, 23, 25, 0.8); }
.ag930-visor-credito:focus-visible { outline: 3px solid var(--action); outline-offset: 2px; }
@media (max-width: 960px) {
  .servicio-carrusel-track { height: 140px; }
  .servicio-carrusel-slide { flex-basis: 30%; }
}
@media (max-width: 640px) {
  .servicio-carrusel-track { height: 100px; }
  .servicio-carrusel-slide { flex-basis: 44%; }
}
.pricing-grid--single { grid-template-columns: 1fr; max-width: 360px; margin-inline: 0; }
/* Fotografía profesional (2 variantes): con la rejilla genérica de 3
   columnas a partir de 960px, 2 tarjetas quedaban pegadas a la
   izquierda con un hueco vacío de tercio de ancho a la derecha. Con
   solo 2 columnas y un ancho máximo propio, centrado, no vuelve a pasar
   a ningún tamaño de pantalla. */
.pricing-grid--variantes { grid-template-columns: 1fr; max-width: 720px; margin-inline: auto; }
@media (min-width: 640px) { .pricing-grid--variantes { grid-template-columns: repeat(2, 1fr); } }
/* ---------- Semáforo de viabilidad (/resultado-viabilidad/) ---------- */
/* Pegado al límite inferior de la foto de fondo del hero: sin el
   padding-top habitual de .section, para que el bloque de texto
   aparezca justo al terminar la fotografía, no separado de ella. Todo
   el bloque (intro + tarjeta del semáforo + botón) se mantiene
   compacto a propósito, sin los espacios grandes por defecto entre
   título/párrafo/línea que trae el resto del sitio. */
.resultado-viabilidad-section { padding-top: 0.5em; padding-bottom: var(--space-lg); }
.resultado-viabilidad-lead { margin-block: 0 var(--space-md); }
.viabilidad-semaforo {
  max-width: 640px;
  margin-inline: auto;
  padding: var(--space-md) var(--space-lg);
  background: var(--bg-section-alt);
  border-radius: var(--radius-card);
  text-align: center;
}
.viabilidad-semaforo-luces {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 0.9em;
  margin-bottom: var(--space-md);
}
.viabilidad-semaforo-luz {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: #E3E5E6;
  opacity: 0.5;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.05);
  transition: opacity 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease;
}
.viabilidad-semaforo-luz.is-activa { opacity: 1; transform: scale(1.2); }
.viabilidad-semaforo-luz--verde.is-activa { background: #157A3D; box-shadow: 0 0 14px 2px rgba(21, 122, 61, 0.55); }
.viabilidad-semaforo-luz--ambar.is-activa { background: #A9670A; box-shadow: 0 0 14px 2px rgba(169, 103, 10, 0.55); }
.viabilidad-semaforo-luz--rojo.is-activa  { background: var(--action); box-shadow: 0 0 14px 2px rgba(212, 0, 0, 0.45); }
.viabilidad-semaforo-luz--azul.is-activa  { background: #1D4ED8; box-shadow: 0 0 14px 2px rgba(29, 78, 216, 0.5); }
.viabilidad-semaforo-resultado h2 { margin: 0 0 0.4em; font-size: var(--fs-h3); line-height: 1.25; }
.viabilidad-semaforo-resultado p { color: var(--text-muted); margin: 0 0 0.5em; }
.viabilidad-semaforo-resultado--verde h2 { color: #157A3D; }
.viabilidad-semaforo-resultado--ambar h2 { color: #A9670A; }
.viabilidad-semaforo-resultado--rojo h2  { color: var(--action); }
.viabilidad-semaforo-resultado--azul h2  { color: #1D4ED8; }
/* ETIQUETA DE RUTA. Es lo que distingue los tres caminos que comparten
   el verde ("Vía directa", "Vía con homologación", "Vía Grupo B"), así
   que tiene que leerse como una categoría y no como un título más: va
   arriba del todo, en versalitas y dentro de una píldora del color del
   semáforo. El color NUNCA es la única señal — el texto de la etiqueta
   dice lo mismo, y por eso las luces de arriba son aria-hidden. */
.viabilidad-semaforo-ruta { margin: 0 0 0.75em; }
.viabilidad-semaforo-ruta-etiqueta {
  display: inline-block;
  padding: 0.3em 0.9em;
  border: 1px solid currentcolor;
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  line-height: 1.3;
}
.viabilidad-semaforo-resultado--verde .viabilidad-semaforo-ruta-etiqueta { color: #157A3D; background: rgba(21, 122, 61, 0.08); }
.viabilidad-semaforo-resultado--ambar .viabilidad-semaforo-ruta-etiqueta { color: #A9670A; background: rgba(169, 103, 10, 0.08); }
.viabilidad-semaforo-resultado--rojo  .viabilidad-semaforo-ruta-etiqueta { color: var(--action); background: rgba(212, 0, 0, 0.07); }
.viabilidad-semaforo-resultado--azul  .viabilidad-semaforo-ruta-etiqueta { color: #1D4ED8; background: rgba(29, 78, 216, 0.08); }

/* Condiciones del estudio de viabilidad. Antes era una sola frase en
   negrita y en el color del semáforo, porque prometía un reembolso sin
   condiciones. Ahora cuenta también el caso desfavorable, así que son
   tres frases: en negrita y a todo color se leería como una advertencia
   legal metida con calzador. Se queda como letra pequeña separada por
   una línea, que es lo que es. */
.viabilidad-semaforo-reembolso {
  margin: var(--space-sm) 0 0;
  padding-top: 0.75em;
  border-top: 1px solid var(--border-plata);
  font-size: 0.88rem;
  line-height: 1.5;
}
@media (prefers-reduced-motion: reduce) {
  .viabilidad-semaforo-luz { transition: none; }
}

/* LO QUE CAMBIA POR EL TIPO DE VEHÍCULO. Son avisos concretos —el ROMA de
   un agrícola, la exención de ITV de un ciclomotor—, así que se leen como
   una lista de cosas a tener en cuenta y no como más párrafos del
   veredicto: alineados a la izquierda aunque la tarjeta esté centrada,
   que es como se lee una lista. */
.viabilidad-semaforo-notas {
  margin: var(--space-sm) 0 0;
  padding: 0.85em 1em 0.85em 2.1em;
  border-radius: var(--radius-card);
  background: var(--bg-page);
  text-align: left;
  font-size: 0.9rem;
  line-height: 1.55;
  color: var(--text-muted);
}
.viabilidad-semaforo-notas li + li { margin-top: 0.5em; }

/* BOTONES DEL RESULTADO. La vía directa trae dos (la guía gratuita y el
   servicio a precio cerrado) y el resto de casos uno solo, así que la
   caja tiene que aguantar las dos formas sin quedar coja: columna en
   móvil, y en pantalla ancha dos columnas de igual ancho que se centran
   solas cuando solo hay una. */
.viabilidad-semaforo-cta {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: center;
  gap: var(--space-md);
  margin: var(--space-md) auto 0;
  max-width: 640px;
  text-align: center;
}
/* flex-wrap + una base de 260px hace el trabajo de un `:has()` contando
   botones, y sin depender de él: con un botón la caja se queda en una
   columna centrada de 300px como máximo; con dos, se ponen al lado y
   caen una debajo de otra en cuanto no caben (móvil incluido). */
.viabilidad-semaforo-accion {
  display: flex;
  flex: 1 1 260px;
  flex-direction: column;
  align-items: center;
  gap: 0.6em;
  max-width: 300px;
}
/* Con el ancho fijo de la columna, el `nowrap` general de .btn sacaba
   «IVA incluido» por la derecha del botón de la vía directa, blanco
   sobre blanco. Aquí el texto lleva el precio y puede ir en dos líneas. */
.viabilidad-semaforo-accion .btn {
  width: 100%;
  justify-content: center;
  text-align: center;
  white-space: normal;
}
.viabilidad-semaforo-accion-nota {
  margin: 0;
  color: var(--text-muted);
  font-size: 0.88rem;
  line-height: 1.5;
}

.servicio-especializado-cta { margin: var(--space-lg) 0; }
.servicio-especializado-form {
  margin-top: var(--space-lg);
  margin-inline: auto;
  padding: var(--space-lg);
  background: var(--bg-section-alt);
  border-radius: var(--radius-card);
  max-width: 640px;
  /* Al pulsar "Contratar" el salto hasta aquí (ver assets/js/main-v3.js)
     no debe dejar el bloque justo debajo de la cabecera fija. */
  scroll-margin-top: 100px;
}
.servicio-especializado-form h2 { margin-top: 0; text-align: center; }
.servicio-especializado-form > p { color: var(--text-muted); margin-bottom: var(--space-md); }
/* El propio <form> (ag930-form) ya trae max-width:720px y margin-inline:auto
   de form.css, pero al vivir aquí dentro de un contenedor ya centrado y más
   estrecho (640px), se deja ocupar el ancho completo del contenedor en vez
   de aplicar su propio límite — evita un doble margen que lo desplazaba
   hacia la izquierda dentro de la caja. */
.servicio-especializado-form .ag930-form { max-width: none; margin-inline: 0; }

/* Foto decorativa sobre el formulario de reserva de sesión de fotos /
   solicitud de tasación (ver template-parts/servicio-especializado.php).
   Puramente ambiental, sin texto encima, por eso no necesita el
   oscurecido de .blur-hero. Mismo ancho máximo que el formulario y
   centrada igual, para que ambos bloques queden alineados como una
   única columna en vez de que el banner ocupe todo el ancho de la página.
*/
.ag930-form-banner {
  height: 180px;
  max-width: 640px;
  margin: var(--space-lg) auto 0;
  border-radius: var(--radius-card);
  background-size: cover;
  background-position: center;
}
@media (min-width: 720px) { .ag930-form-banner { height: 240px; } }

/* ---------- Footer ---------- */
.site-footer { background: var(--bg-darker); color: rgba(250,250,249,0.75); }
.site-footer .container { padding-block: var(--space-2xl) var(--space-lg); }
.footer-grid {
  display: grid;
  gap: var(--space-lg);
  grid-template-columns: 1fr;
}
@media (min-width: 620px) and (max-width: 959px) {
  .footer-grid { grid-template-columns: repeat(2, 1fr); }
  .footer-brand { grid-column: 1 / -1; }
}
@media (min-width: 960px) { .footer-grid { grid-template-columns: 1.3fr repeat(4, 1fr); } }
.footer-brand img { height: 30px; margin-bottom: var(--space-sm); }
/* width:auto es lo importante aquí: sin él, el navegador usaba el
   atributo width="708" del <img> (pensado para los 450px de alto
   originales) como ancho de facto, estirando el logo a ~4 veces su
   proporción real dentro de solo 40px de alto — de ahí el aspecto
   difuminado y alargado. height sube un poco (40→56px) para que se lea
   con más nitidez, ya proporcionado correctamente. */
.footer-brand img.footer-logo {
  height: 56px;
  width: auto;
  background: #fff;
  padding: 6px 10px;
  border-radius: 6px;
}
.footer-brand p { font-size: var(--fs-small); max-width: 32ch; }
/* h2, no h4: los títulos de columna del pie salen en TODAS las páginas, y
   en las que acaban en un H2 (p. ej. /servicios/) un H4 detrás era un
   salto de dos niveles. h2 es el único nivel que no puede saltar venga de
   donde venga el contenido de arriba. El tamaño lo fija esta regla, así
   que el pie se ve exactamente igual que antes. */
.footer-col h2 {
  color: var(--text-on-dark);
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin-bottom: var(--space-sm);
}
.footer-col li { margin-bottom: 0.5em; font-size: var(--fs-small); }
.footer-col a:hover { color: #fff; }
.footer-social { display: flex; flex-wrap: wrap; gap: var(--space-sm); margin-top: var(--space-sm); align-items: center; }
.footer-social a {
  width: 34px; height: 34px; border-radius: 50%;
  border: 1px solid rgba(250,250,249,0.25);
  display: flex; align-items: center; justify-content: center;
}

/* El enlace que además muestra el usuario (@930autogest) deja de ser un
   círculo: con texto dentro, un círculo de 34px o lo recorta o se
   deforma. Pasa a píldora, que es la forma que admite icono + texto sin
   que ninguno de los dos se estruje. El resto de redes, mientras sigan
   siendo dos letras, conservan su círculo. */
.footer-social a.footer-social-link--con-usuario {
  width: auto;
  height: auto;
  border-radius: 999px;
  gap: 0.45rem;
  padding: 0.35rem 0.8rem 0.35rem 0.6rem;
}

/* `display: flex` porque el icono ya no es el <svg> suelto sino un
   <span> que lo envuelve (ver footer.php): sin esto el span sería una
   caja en línea y arrastraría el espacio de línea base bajo el dibujo,
   descentrándolo dentro del círculo de 34px. */
.footer-social-icon { flex: 0 0 auto; display: flex; }

/* `currentColor` en el SVG: hereda el color del pie sin fijar ninguno,
   así que si algún día cambia el fondo oscuro el icono acompaña. */
.footer-social-usuario {
  font-size: 0.82rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  white-space: nowrap;
}
.footer-bottom {
  border-top: 1px solid rgba(250,250,249,0.12);
  margin-top: var(--space-lg);
  padding-top: var(--space-md);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm) var(--space-lg);
  justify-content: space-between;
  font-size: 0.75rem;
}
.footer-bottom .legal-links { display: flex; gap: var(--space-md); flex-wrap: wrap; }

/* ---------- Banner de consentimiento de cookies ---------- */
/*
 * CORRECCIÓN (auditoría del recorrido, hallazgo crítico): el aviso es una
 * caja fija de 640 px anclada abajo, y con `z-index: 100` se lleva los clics
 * de todo lo que quede debajo. Medido: el botón de enviar de los formularios
 * de servicio —que al terminar un formulario largo cae justo en esa franja—
 * no llegaba a recibir el clic, y tres servicios (149, 199 y 349 €) no
 * mandaban ni una sola petición al servidor, sin ningún mensaje. Aceptando
 * las cookies primero, los mismos formularios se envían sin problema.
 *
 * Se le reserva su hueco mientras esté en pantalla, para que el contenido
 * pueda desplazarse por encima de él. La clase la pone y la quita
 * cookie-consent-v4.js.
 */
body.ag930-con-cookie-banner {
  padding-bottom: 190px;
}

@media (max-width: 600px) {
  /* En móvil el aviso crece porque el texto se reparte en más líneas. */
  body.ag930-con-cookie-banner {
    padding-bottom: 260px;
  }
}

.ag930-cookie-banner {
  position: fixed;
  left: var(--space-md);
  right: var(--space-md);
  bottom: var(--space-md);
  max-width: 640px;
  margin-inline: auto;
  background: var(--color-carbon);
  color: var(--text-on-dark);
  border-radius: var(--radius-card);
  padding: 1.25rem 1.5rem;
  box-shadow: 0 12px 32px rgba(0,0,0,0.25);
  z-index: 100;
  font-size: 0.9rem;
}
.ag930-cookie-banner p { margin: 0 0 1em; }
.ag930-cookie-banner a { color: var(--color-plata); text-decoration: underline; }
.ag930-cookie-actions { display: flex; gap: var(--space-sm); justify-content: flex-end; flex-wrap: wrap; }

/* ---------- Segunda capa: "Personalizar" ---------- */
/* El panel puede crecer más que la pantalla en un móvil pequeño (tres
   categorías con su descripción, proveedor y duración), así que se
   desplaza por dentro en vez de estirar el banner fuera de la ventana
   —el mismo problema que tenía el menú móvil—. 60vh deja ver siempre
   los botones de guardar. */
.ag930-cookie-panel {
  max-height: 60vh;
  max-height: 60dvh;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.ag930-cookie-cat {
  padding-block: var(--space-sm);
  border-top: 1px solid rgba(250, 250, 249, 0.18);
}
.ag930-cookie-cat:first-child { border-top: 0; padding-top: 0; }
.ag930-cookie-cat-cabecera {
  display: flex;
  align-items: center;
  gap: 0.6em;
  cursor: pointer;
  /* 44px de alto real: es zona pulsable con el dedo y la prueba de
     responsive exige ese mínimo. */
  min-height: 44px;
}
.ag930-cookie-cat-cabecera input { width: 18px; height: 18px; flex-shrink: 0; }
.ag930-cookie-cat-cabecera input:disabled { cursor: not-allowed; }
.ag930-cookie-cat-nombre { font-weight: 600; }
.ag930-cookie-cat-fijo {
  margin-left: auto;
  font-size: 0.8rem;
  color: var(--color-plata);
  white-space: nowrap;
}
.ag930-cookie-banner .ag930-cookie-cat-detalle {
  margin: 0.2em 0 0.4em;
  color: rgba(250, 250, 249, 0.8);
}
.ag930-cookie-banner .ag930-cookie-cat-meta {
  margin: 0;
  font-size: 0.8rem;
  color: rgba(250, 250, 249, 0.6);
}
.ag930-cookie-panel .ag930-cookie-actions { margin-top: var(--space-md); }

/* ---------- Página "Servicios" (entrada a las dos ramas) ---------- */
.services-hub-grid {
  display: grid;
  gap: var(--space-lg);
  grid-template-columns: 1fr;
  margin-top: var(--space-lg);
}
@media (min-width: 720px) { .services-hub-grid { grid-template-columns: repeat(2, 1fr); } }
/* Aquí hubo un `--3col` para el hub del Blog cuando tenía 3 ramas. Se
   fue con él el 2026-09-07: al entrar la cuarta rama, esa página pasó a
   carrusel (.ag930-carrusel) y se quedó sin usar. El único consumidor
   de .services-hub-grid es hoy /servicios/, que tiene dos tarjetas y le
   basta el repeat(2, 1fr) de arriba. */
.services-hub-card {
  background: #fff;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-card);
  overflow: hidden;
  box-shadow: var(--shadow-card);
  display: flex;
  flex-direction: column;
  transition: transform var(--transition-base), box-shadow var(--transition-base);
}
.services-hub-card:hover { transform: translateY(-2px); box-shadow: 0 8px 24px rgba(21,23,25,0.08); }
.services-hub-card-media { aspect-ratio: 3 / 2; }
.services-hub-card-media img { display: block; width: 100%; height: 100%; object-fit: cover; }
.services-hub-card-body {
  padding: var(--space-lg);
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  flex: 1;
}
.services-hub-card-body h2 { font-size: var(--fs-h2); }
.services-hub-card-body p { color: var(--text-muted); flex: 1; }
.services-hub-card-body .btn { align-self: flex-start; }

/* ---------- Listado de catálogo (Servicios 930 / Trámites DGT) ---------- */
.services-catalog-lead {
  max-width: 72ch;
  color: var(--text-muted);
  font-size: 1.05rem;
  margin: var(--space-md) 0 0;
}
/* Introducción de varios párrafos (ver template-parts/servicios-especializados-grid.php):
   cada <p> lleva también la clase "lead" y el contenedor "split-hero__lead-group"
   — el mismo par de clases que ya usan de fábrica las cabeceras con
   resumen en varios párrafos (Vehículos históricos, Transporte...) — para
   heredar directamente su espaciado ya probado (línea 787) en vez de
   duplicar la regla: el selector de dos clases de .split-hero__lead-group
   .lead pesa más que esta única clase, así que gana siempre sin
   depender del orden de las reglas en la hoja de estilos.
*/
.services-catalog-lead-group {
  max-width: 72ch;
  margin: var(--space-md) 0 0;
}
.services-catalog-intro {
  display: grid;
  gap: var(--space-lg);
  grid-template-columns: 1fr;
  background: var(--bg-section-alt);
  border-radius: var(--radius-card);
  padding: var(--space-lg);
  margin: var(--space-lg) 0 var(--space-xl);
}
@media (min-width: 720px) { .services-catalog-intro { grid-template-columns: repeat(2, 1fr); } }
.services-catalog-intro h2 { font-size: var(--fs-h3); margin-bottom: var(--space-sm); }
.services-catalog-list { display: flex; flex-direction: column; gap: 0.6em; }
.services-catalog-list li { display: flex; gap: 0.6em; align-items: flex-start; font-size: var(--fs-small); }
.services-catalog-list li strong { display: block; color: var(--text-strong); }
.services-catalog-list .icon { color: var(--action); flex-shrink: 0; }
/* Variante con más ventajas (p. ej. Vehículos históricos, con 9 en vez
   de las 4 genéricas): se reparten en dos columnas para no alargar la
   tarjeta mucho más que la columna de "Cómo funciona el proceso". */
@media (min-width: 640px) {
  .services-catalog-list--grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    column-gap: var(--space-lg);
  }
}
.services-catalog-steps {
  margin: 0;
  padding-left: 1.25em;
  display: flex;
  flex-direction: column;
  gap: 0.6em;
  font-size: var(--fs-small);
  color: var(--text-body);
}
.services-catalog-steps-note { margin-top: var(--space-sm); }
.services-catalog-explicacion { color: var(--text-muted); font-size: var(--fs-small); margin: 0; }

/* ---------- Formularios .ag930-* del tema (contacto, seguros) ----------
   El plugin Core trae su propio CSS para estas mismas clases
   (public/assets/css/form.css), pero solo se carga en páginas que usan
   su shortcode [autogest930_form ...] — los formularios de contacto y
   seguros los renderiza el TEMA directamente con las mismas clases, sin
   pasar por ese shortcode, así que nunca cargaban ese CSS: el campo
   honeypot ("Deja este campo vacío") se veía en texto plano en vez de
   estar oculto. Base mínima aquí para que el tema no dependa de un
   archivo de otro plugin para verse bien. */
.ag930-form { max-width: 720px; margin-inline: auto; }
/* Recuadros del formulario/checkout más marcados: antes .ag930-fieldset y
   .ag930-resumen-precio no tenían ningún borde propio (heredaban el
   <fieldset>/<div> sin estilo del navegador), así que las secciones del
   formulario y el desglose de precio apenas se distinguían del resto de
   la página. */
.ag930-fieldset {
  border: 1px solid var(--border-plata);
  border-radius: var(--radius-card);
  padding: var(--space-md);
  margin-bottom: var(--space-md);
}
.ag930-fieldset legend {
  padding: 0 0.5em;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-small);
  color: var(--text-strong);
}
.ag930-resumen-precio {
  border: 1px solid var(--border-plata);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  padding: var(--space-md);
  margin-bottom: var(--space-md);
  background: var(--bg-page);
}
.ag930-honeypot {
  position: absolute !important;
  left: -9999px !important;
  width: 1px;
  height: 1px;
  overflow: hidden;
}
.ag930-field { margin-bottom: var(--space-sm); }
.ag930-field label { display: block; font-size: var(--fs-small); font-weight: 600; margin-bottom: 0.35em; }
.ag930-field input[type="text"],
.ag930-field input[type="email"],
.ag930-field input[type="tel"],
.ag930-field input[type="number"],
.ag930-field select,
.ag930-field textarea {
  width: 100%;
  padding: 0.7em 0.9em;
  border: 1px solid var(--border-plata);
  border-radius: 4px;
  font: inherit;
}
.ag930-field-checkbox label { display: flex; align-items: flex-start; gap: 0.5em; font-weight: 400; }
.ag930-consentimiento { font-size: var(--fs-small); margin-bottom: var(--space-md); }
.ag930-consentimiento label { display: flex; align-items: flex-start; gap: 0.5em; }

/* Casilla obligatoria de renuncia al desistimiento en el checkout de
   WooCommerce (ver Autogest930_Woocommerce::renderizar_casilla_desistimiento()).
   Recuadro deliberadamente marcado — borde de acento + fondo — porque es
   una declaración legal que el cliente debe leer con atención antes de
   poder finalizar la compra, no una casilla más entre otras. */
.ag930-desistimiento {
  border: 1px solid var(--action);
  border-radius: var(--radius-card);
  background: var(--bg-section-alt);
  padding: var(--space-sm) var(--space-md);
  margin: var(--space-md) 0;
  font-size: var(--fs-small);
}
.ag930-desistimiento label { font-weight: 600; color: var(--text-strong); }

/* ---------- Formularios de servicio por pasos (rediseño) ----------
   El plugin Core trae el diseño completo en public/assets/css/form.css.
   Aquí solo va lo que el TEMA tiene que ceder para que ese diseño se
   vea como está pensado: los formularios viven dentro de
   .entry-content, cuya tipografía editorial (h2 con margin-top:2em,
   listas con viñeta, ancho de artículo) chocaría con la cabecera, la
   barra de progreso y el bloque informativo del formulario. El orden de
   carga pone main-v40.css DESPUÉS de form-v6.css, así que sin estas reglas
   ganaría siempre el tema. */
.entry-content .ag930-servicio { max-width: 780px; margin-inline: auto; }
.entry-content .ag930-form-despues h3 { margin-top: 0; }
/* El primer párrafo de la descripción va justo debajo del <h1> de la
   página: sin margen superior extra heredado del contenido editorial. */
.entry-content .ag930-form-cabecera { margin-top: 0; }
.entry-content .ag930-form-cabecera > .ag930-form-descripcion > p:first-child { margin-top: 0; }
/* La nota legal de los plazos cierra la cabecera: no debe arrastrar el
   margen inferior de párrafo del contenido editorial (.entry-content p). */
.entry-content .ag930-form-nota-plazos { margin-bottom: 0; }
/* La cabecera de cada paso del acordeón es un <h3> que solo envuelve al
   botón: no debe heredar ni el margen ni el tamaño de un h3 editorial. */
.entry-content .ag930-paso-cabecera-wrap { margin: 0; font-size: 1rem; }
.entry-content .ag930-form-datos ul,
.entry-content .ag930-autorizacion-texto ul { list-style: disc; }
.entry-content .ag930-progreso-lista { list-style: none; }
.entry-content .ag930-form-despues p { font-size: var(--fs-body); }
/* La descripción del servicio es ahora el único texto explicativo bajo
   el <h1> de la página, y va destacada en el rojo de marca (ver
   .ag930-form-descripcion en form-v6.css, plugin Core). Como el tema se
   carga después que el plugin, hay que repetir aquí tamaño y color: de
   lo contrario ganarían la tipografía y el color editoriales de
   .entry-content y la descripción volvería a verse como texto normal. */
.entry-content .ag930-form-descripcion p {
  font-size: 1.03rem;
  color: var(--action-hover);
}
@media (max-width: 480px) {
  .entry-content .ag930-form-descripcion p { font-size: 1rem; }
}
/* La etiqueta de un campo dentro de la rejilla de dos columnas no debe
   heredar el margen inferior de párrafo del contenido editorial. */
.entry-content .ag930-campos-grid .ag930-field-help,
.entry-content .ag930-documento p { margin-bottom: 0.35em; }
/* Los dos enlaces legales de las declaraciones finales van en azul a
   propósito (fuera de la paleta de marca): deben leerse inequívocamente
   como enlaces a un documento legal, no como texto destacado. */
.entry-content .ag930-enlace-legal { color: #1155CC; }
.entry-content .ag930-enlace-legal:hover { color: #0B3D91; }

/* ---------- Campo "Fecha deseada" — calendario desplegable (calculadora
   de transporte, /transporte/, ver assets/js/transporte-v1.js) ---------- */
.ag930-datepicker { position: relative; }
.ag930-datepicker-input { cursor: pointer; background: #fff; }
.ag930-datepicker-panel {
  position: absolute;
  z-index: 20;
  top: calc(100% + 0.4em);
  left: 0;
  width: 280px;
  max-width: 90vw;
  background: #fff;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  padding: var(--space-sm);
}
.ag930-datepicker-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--space-xs);
}
.ag930-datepicker-label { font-weight: 600; font-size: var(--fs-small); text-transform: capitalize; }
.ag930-datepicker-nav {
  background: transparent;
  border: 1px solid var(--border-plata);
  border-radius: 4px;
  width: 2em;
  height: 2em;
  line-height: 1;
  font-size: 1rem;
  cursor: pointer;
  color: var(--text-strong);
}
.ag930-datepicker-nav:hover:not(:disabled) { border-color: var(--action); color: var(--action); }
.ag930-datepicker-nav:disabled { opacity: 0.35; cursor: not-allowed; }
.ag930-datepicker-weekdays,
.ag930-datepicker-days {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 0.2em;
  text-align: center;
}
.ag930-datepicker-weekdays {
  font-size: var(--fs-eyebrow);
  font-weight: 600;
  color: var(--text-muted);
  margin-bottom: 0.3em;
}
.ag930-datepicker-day {
  background: transparent;
  border: 1px solid transparent;
  border-radius: 4px;
  padding: 0.4em 0;
  font: inherit;
  font-size: var(--fs-small);
  cursor: pointer;
  color: var(--text-body);
}
.ag930-datepicker-day--vacio { visibility: hidden; cursor: default; }
.ag930-datepicker-day:hover:not(:disabled) { border-color: var(--action); }
.ag930-datepicker-day--hoy { font-weight: 700; color: var(--action); }
.ag930-datepicker-day--seleccionado { background: var(--action); border-color: var(--action); color: #fff; }
.ag930-datepicker-day--deshabilitado { color: var(--border-plata); cursor: not-allowed; }

/* ---------- Página de Contacto ---------- */
.contact-page { max-width: 780px; margin-inline: auto; padding-top: var(--space-lg); }
/* Velo bajo la entradilla de Contacto.
   La cabecera de esta página tiene la foto detrás del texto (como todas
   las .split-hero), y la entradilla —dos párrafos, uno de ellos largo—
   cae sobre la parte sólida del motor. El h1 ya se defiende con su
   propio velo degradado; estos párrafos no tenían ninguno.

   NO SE INVENTA UN TRATAMIENTO NUEVO: es el mismo patrón que ya se
   decidió para los sellos de confianza del hero de Inicio (ver
   `.hero .trust-item::before`), y por el mismo motivo que se explica
   allí. Se probó en su día un velo grande sobre media cabecera y se
   descartó a propósito porque en pantalla quedaba peor que el problema;
   lo que sí funcionó fue una tarjeta del tamaño del propio texto, con
   `backdrop-filter` para difuminar la foto en vez de solo blanquearla y
   un color de respaldo que ya deja el texto legible por sí solo donde
   el navegador no soporte el filtro.

   Solo desde 960px, otra vez por lo mismo: por debajo la foto va
   apilada encima del texto y no hay nada que tapar.

   La opacidad es 0,88 y no el 0,78 del hero de Inicio, y sale de medir
   y no de mirar: aquí el texto es --text-muted (#5A5F66), más flojo que
   los sellos, y la foto de fondo es un motor oscuro. Con 0,78 sobre la
   zona más oscura de la foto el respaldo se queda en 4,3:1 —por debajo
   del 4,5 que pide AA—; con 0,88 sube a 4,9:1 en ese mismo punto y a
   6,2:1 donde la foto ya está fundida. */
@media (min-width: 960px) {
  .contacto-hero-intro {
    position: relative;
    isolation: isolate;
  }
  .contacto-hero-intro::before {
    content: '';
    position: absolute;
    /* Sangría generosa por los lados: aquí las líneas son largas y una
       tarjeta pegada al texto se lee como un recuadro, no como fondo. */
    inset: -0.75rem -1rem;
    z-index: -1;
    border-radius: var(--radius-card);
    pointer-events: none;
    background: rgba(250, 250, 249, 0.88);
    border: 1px solid rgba(23, 23, 23, 0.08);
    box-shadow: 0 1px 2px rgba(23, 23, 23, 0.04);
    -webkit-backdrop-filter: blur(7px);
    backdrop-filter: blur(7px);
  }
}
/* El último párrafo de la entradilla no arrastra su margen inferior
   dentro de la tarjeta: si lo hiciera, el velo tendría un dedo de aire
   de más por debajo y se vería descentrado respecto al texto. */
.contacto-hero-intro > p:last-child { margin-bottom: 0; }

.contact-body { display: flex; flex-direction: column; gap: var(--space-xl); }
.contact-body-form .ag930-form { margin: 0; max-width: none; }
@media (max-width: 899px) {
  /* Datos esenciales (teléfono/email) antes que el formulario completo. */
  .contact-body-form { order: 2; }
  .contact-body-direct { order: 1; }
}
.contact-direct, .contact-social {
  text-align: center;
  padding-top: var(--space-xl);
  border-top: 1px solid var(--border-subtle);
}
.contact-social { margin-top: var(--space-xl); }
.contact-direct h2, .contact-social h2 { font-size: var(--fs-h3); margin-bottom: var(--space-md); }
.contact-direct-items { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--space-lg); }
.contact-direct-item { display: inline-flex; align-items: center; gap: 0.6em; font-weight: 600; color: var(--text-body); }
.contact-direct-item .icon { color: var(--action); display: flex; }
.contact-direct-item:hover { color: var(--action); }
.contact-social-icons { display: flex; justify-content: center; gap: var(--space-sm); }
.contact-social-icon {
  width: 44px; height: 44px; border-radius: 50%;
  border: 1px solid var(--border-plata);
  display: flex; align-items: center; justify-content: center;
  color: var(--text-body);
  transition: background-color var(--transition-fast), color var(--transition-fast), border-color var(--transition-fast);
}
.contact-social-icon:hover { background: var(--action); border-color: var(--action); color: #fff; }

/* =========================================================
   WooCommerce — mi cuenta, carrito, checkout, confirmación de
   pedido y producto ("Estudio de viabilidad"). Solo CSS sobre las
   clases estándar de WooCommerce: ninguna plantilla del plugin se
   sobrescribe, así que el checkout sigue funcionando exactamente
   igual, solo con la tipografía, los colores y los espaciados de
   930 Autogest en vez del estilo por defecto de WooCommerce.
   ========================================================= */
.woocommerce,
.woocommerce-page {
  color: var(--text-body);
  font-family: var(--font-body);
}
.woocommerce h1, .woocommerce h2, .woocommerce h3 { font-family: var(--font-display); color: var(--text-strong); }

/* Carrito, checkout, mi cuenta... son páginas de WordPress normales
   (con el shortcode de WooCommerce dentro), así que ya heredan el
   .container del tema vía page.php. La tienda y la ficha de producto
   NO — WooCommerce las sirve con su propia plantilla (#main, sin pasar
   por page.php), así que sin esto se pintaban a todo el ancho de la
   ventana, sin los márgenes laterales del resto del sitio (detectado
   al añadir descripción a los 5 productos de tasación, ver
   autogest930_producto_tasacion_resumen() en functions.php). */
#main.site-main {
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--space-md);
}
/* El CSS de fábrica de WooCommerce (woocommerce-layout.css, del
   plugin) fuerza el resumen del producto a flotar a la derecha al 48%
   de ancho, pensado para convivir con la galería de imágenes a la
   izquierda. Los productos "especializados" (tasación, transporte,
   fotografía...) no tienen galería
   (autogest930_quitar_galeria_producto_especializado()), así que sin
   esto el resumen quedaba descentrado y a menos de la mitad del ancho
   disponible. Selector con una clase más que el del plugin para ganar
   por especificidad sin necesidad de !important. */
.woocommerce div.product div.summary.entry-summary {
  float: none;
  width: 100%;
}

/* Botones: mismo tratamiento que .btn-primary — nunca gradientes,
   hover a rojo más oscuro, sin sombras agresivas. */
.woocommerce a.button,
.woocommerce button.button,
.woocommerce input.button,
.woocommerce #respond input#submit,
.woocommerce-page a.button,
.woocommerce-page button.button {
  background: var(--action);
  color: #fff;
  border: 1px solid transparent;
  border-radius: 4px;
  padding: 0.85em 1.5em;
  font-weight: 600;
  font-size: var(--fs-small);
  box-shadow: none;
  text-transform: none;
  transition: background-color var(--transition-fast);
}
.woocommerce a.button:hover,
.woocommerce button.button:hover,
.woocommerce input.button:hover,
.woocommerce #respond input#submit:hover {
  background: var(--action-hover);
  color: #fff;
}
.woocommerce a.button.alt,
.woocommerce button.button.alt,
.woocommerce input.button.alt { background: var(--action); }

/* CORRECCIÓN (petición del cliente): el botón "Realizar el pedido" es
   la acción final de toda la compra y debe notarse como tal — antes
   quedaba pegado al borde izquierdo de su fila (comportamiento por
   defecto de WooCommerce) con el mismo tamaño que un botón secundario
   cualquiera. Se centra en su fila y se agranda un poco. */
.woocommerce #payment .form-row.place-order { text-align: center; }
.woocommerce #payment .form-row.place-order .button {
  display: inline-block;
  padding: 1em 2.5em;
  font-size: 1.05rem;
}

.woocommerce table.shop_table {
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-card);
  border-collapse: separate;
  border-spacing: 0;
  overflow: hidden;
}
.woocommerce table.shop_table th { background: var(--bg-section-alt); font-weight: 600; }
.woocommerce table.shop_table th,
.woocommerce table.shop_table td { border-top: 1px solid var(--border-subtle); padding: 1em; }
.woocommerce-Price-amount { color: var(--action); font-weight: 700; }

/* Desglose informativo (base imponible + IVA 21% + tasa DGT si la hay)
   bajo cada artículo del carrito y del resumen de pedido en checkout —
   ver Autogest930_Woocommerce::render_desglose_linea(). Se calcula
   sobre el importe final ya cobrado de la línea, no solo sobre
   servicios del catálogo de trámites, así que funciona igual para el
   Estudio de Viabilidad y cualquier otro producto del carrito. */
.ag930-desglose-precio {
  list-style: none;
  margin: 0.6em 0 0;
  padding: 0.7em 0.9em;
  background: var(--bg-section-alt);
  border: 1px solid var(--border-plata);
  border-radius: var(--radius-card);
  font-size: 0.82rem;
  color: var(--text-muted);
  max-width: 100%;
}
.ag930-desglose-precio li { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 0.5em 1em; padding: 0.15em 0; }
.ag930-desglose-precio li span:last-child { font-weight: 600; color: var(--text-strong); white-space: nowrap; }
.ag930-desglose-precio li.ag930-desglose-nota { display: block; font-style: italic; margin-top: 0.3em; }

/* Totales agregados de IVA (base imponible + IVA + tasas exentas) en la
   tabla de totales del carrito/checkout — ver
   Autogest930_Woocommerce::mostrar_totales_iva(). Recuadro más marcado
   (fondo + franja de acento a la izquierda de la primera fila) para que
   el desglose honorarios/tasas DGT/IVA se distinga con claridad justo
   antes del total final, sin restarle peso visual a la fila
   .order-total (que sigue en negrita, ya por defecto de WooCommerce). */
.ag930-totales-iva th,
.ag930-totales-iva td {
  font-size: 0.85rem;
  font-weight: 400;
  color: var(--text-muted);
  background: var(--bg-section-alt);
}
.ag930-totales-iva .woocommerce-Price-amount { color: inherit; font-weight: 400; }
.ag930-totales-iva-base th,
.ag930-totales-iva-base td { border-left: 3px solid var(--action); }

.woocommerce-checkout input.input-text,
.woocommerce-checkout select,
.woocommerce-checkout textarea,
.woocommerce form .form-row input.input-text,
.woocommerce form .form-row select,
.woocommerce form .form-row textarea {
  border: 1px solid var(--border-plata);
  border-radius: 4px;
  padding: 0.7em 0.9em;
  font: inherit;
}
.woocommerce form .form-row label { font-weight: 600; font-size: 0.85rem; }

/* El bloque que había aquí estilando .woocommerce-MyAccount-* se ha
   fusionado con el del rediseño (más abajo, «Área privada v2»), que es el
   que manda por orden de cascada. Lo movía stylelint: eran CINCO de sus seis
   avisos de selector duplicado, y mientras estuvieran ese paso de la CI no
   podía ser bloqueante.
   NO era una fusión gratis: tres declaraciones de este bloque SEGUÍAN VIVAS
   porque el rediseño no las repetía —el borde, el redondeo y el `overflow`
   del `ul`, y la línea separadora de cada `li`—. Borrarlo sin más habría
   quitado esas líneas del menú. Se han llevado al bloque de abajo tal cual,
   así que esto no cambia ni un píxel. */

.woocommerce-message,
.woocommerce-info,
.woocommerce-error,
.woocommerce-noreviews,
.woocommerce-order {
  border-top-color: var(--action);
  border-radius: var(--radius-card);
}
.woocommerce-message::before,
.woocommerce-info::before { color: var(--action); }

.woocommerce div.product p.price,
.woocommerce div.product span.price { color: var(--action); font-family: var(--font-display); }

/* Resumen del producto (título, precio, formulario) centrado — pedido
   explícitamente para "Estudio de viabilidad". Acotado a esa página en
   concreto (clase de body añadida a mano en
   autogest930_body_class_estudio_viabilidad(), functions.php — este
   sitio no pinta de forma fiable la clase single-{post_type}-{slug}
   que WordPress añadiría por defecto) desde que hay más productos con
   página propia (los 5 de tasación, ver
   autogest930_producto_tasacion_resumen()): su bloque
   .servicio-especializado necesita el ancho normal del contenedor, no
   esta columna estrecha de 60ch pensada para un simple título+precio+botón. */
.single-product-estudio-de-viabilidad .woocommerce div.product .summary.entry-summary {
  text-align: center;
  max-width: 60ch;
  margin-inline: auto;
}
.single-product-estudio-de-viabilidad .woocommerce div.product .summary.entry-summary form.cart {
  display: flex;
  flex-direction: column;
  align-items: center;
}
.single-product-estudio-de-viabilidad .woocommerce div.product .summary.entry-summary .quantity { margin-inline: auto; }

/* Estudio de viabilidad: nota de precio + bloque "qué es / por qué /
   qué incluye". */
.estudio-viabilidad-nota-precio {
  font-size: var(--fs-small);
  color: var(--text-muted);
  max-width: 46ch;
  margin: -0.5em auto 1.5em;
}
.estudio-viabilidad-info {
  display: grid;
  gap: var(--space-lg);
  grid-template-columns: 1fr;
  max-width: 960px;
  margin: var(--space-2xl) auto 0;
  padding-top: var(--space-xl);
  border-top: 1px solid var(--border-subtle);
}
@media (min-width: 720px) { .estudio-viabilidad-info { grid-template-columns: repeat(3, 1fr); } }
.estudio-viabilidad-info h3 { font-size: var(--fs-h3); }
.estudio-viabilidad-info p { color: var(--text-muted); margin: 0; }

/* Limpieza visual del producto: sin buscador ni widgets de Páginas /
   Archivos / Categorías al final — no aportan nada en una tienda con
   un único producto oculto. En esta instalación ese bloque no lo
   pinta un widget de WordPress con sus clases estándar, sino un
   <div id="sidebar"> con buscador y listado de páginas/archivos/
   categorías (confirmado inspeccionando la página en directo), así
   que se oculta por ese id en vez de por clases de widget que aquí
   no existen. */
.single-product #sidebar,
.single-product .widget_search,
.single-product .widget_pages,
.single-product .widget_archive,
.single-product .widget_categories,
.single-product .widget_meta,
.single-product .widget_recent_entries,
.single-product .widget_recent_comments {
  display: none;
}

/* =========================================================
   .blur-hero — cabecera con foto de fondo DESENFOCADA (no un fundido
   direccional como .split-hero): pensada para Blog y Eventos, donde
   pedían expresamente un tratamiento distinto al del resto de
   páginas. La imagen entera queda borrosa y oscurecida de manera
   uniforme, con el texto centrado y siempre nítido encima — nunca
   una mitad nítida / mitad transparente como en .split-hero.
   ========================================================= */
.blur-hero {
  position: relative;
  overflow: hidden;
  min-height: 280px;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  border-radius: var(--radius-card);
  margin-bottom: var(--space-lg);
  isolation: isolate;
}
@media (min-width: 720px) { .blur-hero { min-height: 340px; } }
.blur-hero__bg {
  position: absolute;
  inset: -16px; /* algo más grande que el bloque: el desenfoque no deja ver el borde recortado */
  filter: blur(7px) brightness(0.55) saturate(1.05);
  z-index: -2;
}
/* La foto era un `background-image` en línea hasta el 2026-08-30 y ahora
   es un `<img>` de verdad (ver autogest930_imagen_fondo_hero()). El motivo
   no es estético: un fondo de CSS no lo descubre el escáner de precarga
   del navegador, y en /precios/ eso costaba 2.312 ms de «load delay» sobre
   un LCP de 4,0 s. `object-fit: cover` + `object-position: center` dan
   exactamente el mismo encuadre que daban `background-size: cover` y
   `background-position: center`. */
.blur-hero__img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}
.blur-hero::after {
  content: '';
  position: absolute;
  inset: 0;
  /* Antes 0.28: con fotos claras el contraste del texto quedaba al
     límite en algunas zonas de la imagen. Subido a 0.42 + una sombra de
     texto suave (más abajo) como margen de seguridad ante cualquier
     foto que se suba en el futuro. */
  background: rgba(21, 23, 25, 0.42);
  z-index: -1;
}
.blur-hero__content {
  position: relative;
  max-width: 620px;
  padding: var(--space-xl) var(--space-lg);
}
/* Cabeceras que llevan un párrafo explicativo completo sobre la foto
   (Precios, Calculadora de transporte) y no solo un título: el velo
   oscuro sube de 0.42 a 0.55 y el texto pasa a blanco pleno, para que
   varias líneas seguidas se lean con el mismo desahogo que si
   estuvieran sobre fondo blanco. El alto mínimo baja: con título y
   texto, la cabecera ya tiene cuerpo de sobra y reservar 340 px solo
   añadiría espacio muerto. */
.blur-hero--lead { min-height: 0; }
.blur-hero--lead::after { background: rgba(21, 23, 25, 0.55); }
.blur-hero--lead .blur-hero__content {
  max-width: 68ch;
  padding-block: var(--space-lg);
}
.blur-hero--lead .blur-hero__content p { color: var(--text-on-dark); }
@media (min-width: 720px) {
  .blur-hero--lead .blur-hero__content { padding-block: var(--space-xl); }
}

/* Una .section que arranca justo detrás de una cabecera con foto no
   necesita los 6 rem de aire con los que abre una sección normal: la
   cabecera ya aporta su propia separación. */
.blur-hero + .section { padding-top: var(--space-lg); }

.blur-hero__content .kicker { color: var(--text-on-dark); opacity: 0.85; text-shadow: 0 1px 3px rgba(0,0,0,0.4); }
.blur-hero__content h1,
.blur-hero__content h2 { color: var(--text-on-dark); margin-bottom: var(--space-sm); text-shadow: 0 1px 3px rgba(0,0,0,0.4); }
.blur-hero__content p { color: rgba(250, 250, 249, 0.9); margin: 0; text-shadow: 0 1px 3px rgba(0,0,0,0.4); }

/* ---------- Texto introductorio de Profesionales ---------- */
.profesionales-intro {
  max-width: 72ch;
  margin: 0 0 var(--space-xl);
  padding-bottom: var(--space-xl);
  border-bottom: 1px solid var(--border-subtle);
}
.profesionales-intro h2 { font-size: var(--fs-h2); }
.profesionales-intro p { color: var(--text-muted); margin-bottom: 1em; }
.profesionales-intro p:last-child { margin-bottom: 0; }

/* =========================================================
   Panel lateral del carrito (ver template-parts/cart-drawer.php).
   Oculto por defecto (translateX 100%); .is-open lo desliza a la
   vista. Un vistazo rápido sobre el carrito real de WooCommerce, sin
   sustituir el carrito ni el checkout habituales.
   ========================================================= */
.ag930-cart-drawer {
  position: fixed;
  inset: 0;
  z-index: 200;
  visibility: hidden;
  pointer-events: none;
}
.ag930-cart-drawer.is-open { visibility: visible; pointer-events: auto; }
.ag930-cart-drawer-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(21, 23, 25, 0.45);
  opacity: 0;
  transition: opacity var(--transition-base);
}
.ag930-cart-drawer.is-open .ag930-cart-drawer-backdrop { opacity: 1; }
.ag930-cart-drawer-panel {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: min(100%, 380px);
  background: var(--bg-page);
  box-shadow: -8px 0 32px rgba(21, 23, 25, 0.18);
  display: flex;
  flex-direction: column;
  transform: translateX(100%);
  transition: transform var(--transition-base);
}
.ag930-cart-drawer.is-open .ag930-cart-drawer-panel { transform: translateX(0); }
.ag930-cart-drawer-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-md);
  border-bottom: 1px solid var(--border-subtle);
}
.ag930-cart-drawer-header h2 { margin: 0; font-size: 1.1rem; }
.ag930-cart-drawer-close {
  background: none;
  border: none;
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  color: var(--text-muted);
  padding: 0.4em;
}
.ag930-cart-drawer-close:hover { color: var(--action); }
.ag930-cart-drawer-body { padding: var(--space-md); overflow-y: auto; flex: 1; display: flex; flex-direction: column; gap: var(--space-sm); }
.ag930-cart-drawer-empty { color: var(--text-muted); }
.ag930-cart-drawer-items { display: flex; flex-direction: column; gap: var(--space-sm); }
.ag930-cart-drawer-item {
  display: grid;
  grid-template-columns: 1fr auto auto;
  gap: var(--space-sm);
  align-items: baseline;
  padding-bottom: var(--space-sm);
  border-bottom: 1px solid var(--border-subtle);
  font-size: var(--fs-small);
}
.ag930-cart-drawer-item-qty { color: var(--text-muted); }
.ag930-cart-drawer-item-price { font-weight: 600; }
.ag930-cart-drawer-total {
  display: flex;
  justify-content: space-between;
  font-size: 1.05rem;
  padding-top: var(--space-sm);
}
.ag930-cart-drawer-total strong { color: var(--action); }
.ag930-cart-drawer-body .btn { width: 100%; justify-content: center; }

/* =========================================================
   Área privada (Mi cuenta / Mis expedientes / Portal de
   profesionales) — capa de diseño por encima de las clases
   estándar de WooCommerate y de .ag930-* del plugin Core (que
   solo traen estructura/espaciado básicos). Nada de esto cambia
   el HTML que genera WooCommerce o el plugin, ni el
   comportamiento del formulario: solo el aspecto visual.
   ========================================================= */
.woocommerce-account .entry-content,
.woocommerce-account .container.section {
  max-width: 1080px;
}
/* WooCommerce trae de fábrica (woocommerce-layout.css, sin que este
   tema la toque directamente):
     .woocommerce-account .woocommerce-MyAccount-navigation { float:left; width:30% }
     .woocommerce-account .woocommerce-MyAccount-content    { float:right; width:68% }
   Pensada para su maquetación clásica por flotantes. Al meter estos
   dos elementos en nuestra rejilla de 240px+1fr, la rejilla sí los
   coloca en su columna correcta, pero ese ancho en % de WooCommerce
   seguía aplicándose POR ENCIMA, encogiendo cada uno a un porcentaje
   de su propia columna (30% de 240px ≈ 72px) en vez de ocuparla
   entera — de ahí el menú lateral con el texto cortado. float:none +
   width:auto anula ese ancho heredado y deja que la rejilla mande. */
.woocommerce-account .woocommerce-MyAccount-navigation,
.woocommerce-account .woocommerce-MyAccount-content {
  float: none;
  width: auto;
}

@media (min-width: 800px) {
  /* :has() limita esta rejilla de 2 columnas a cuando de verdad hay
     menú lateral (sesión iniciada: Escritorio/Pedidos/...). Sin esto,
     la regla se aplicaba también a la pantalla de "Acceder/Registrarse"
     (sin sesión, .woocommerce solo contiene .u-columns como único
     hijo) y ese único hijo quedaba encajado dentro de la columna de
     240px pensada para el menú, aplastando todo el formulario de
     login/registro en una tira estrechísima. */
  .woocommerce-account .woocommerce:has(> .woocommerce-MyAccount-navigation) {
    display: grid;
    grid-template-columns: 240px 1fr;
    gap: var(--space-lg);
    align-items: start;
  }
  /* Columna fija por nombre de clase (no por orden de aparición): así
     el menú y el contenido siempre caen en su columna aunque
     WooCommerce u otro plugin añada algún elemento hermano extra
     (por ejemplo el propio aviso de abajo) entre medias. */
  .woocommerce-account .woocommerce-MyAccount-navigation { grid-column: 1; }
  .woocommerce-account .woocommerce-MyAccount-content { grid-column: 2; }
  /* Avisos ("mensaje enviado", errores...) ocupan las dos columnas en
     vez de colarse en el hueco del menú lateral. */
  .woocommerce-account .woocommerce-notices-wrapper { grid-column: 1 / -1; }
}
.woocommerce-MyAccount-navigation {
  background: #fff;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-card);
  padding: var(--space-sm);
  box-shadow: var(--shadow-card);
}
/* Las tres primeras declaraciones del `ul` y la línea separadora del `li`
   vienen del bloque anterior al rediseño, que estaba más arriba en el
   archivo y se ha fusionado aquí para quitar los cinco avisos de stylelint.
   Estaban VIVAS —el rediseño no las repetía— así que se conservan tal cual:
   el objetivo era callar a stylelint sin mover un píxel.
   OJO, y queda dicho aparte: ese borde del `ul` va DENTRO de
   .woocommerce-MyAccount-navigation, que ya tiene el suyo, así que el menú
   dibuja dos bordes concéntricos. Tiene pinta de resto del diseño anterior,
   pero quitarlo es un cambio visual y no le toca a esta limpieza. */
.woocommerce-MyAccount-navigation ul {
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-card);
  overflow: hidden;
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.2em;
}
.woocommerce-MyAccount-navigation li { border-bottom: 1px solid var(--border-subtle); margin: 0; }
.woocommerce-MyAccount-navigation li:last-child { border-bottom: 0; }
.woocommerce-MyAccount-navigation li a {
  display: block;
  padding: 0.75em 1em;
  border-radius: 6px;
  font-weight: 600;
  color: var(--text-strong);
  transition: background-color var(--transition-fast);
}
.woocommerce-MyAccount-navigation li a:hover { background: var(--bg-section-alt); }
.woocommerce-MyAccount-navigation li.is-active a { background: var(--action); color: #fff; }
.woocommerce-MyAccount-content {
  background: #fff;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-card);
  padding: var(--space-lg);
  box-shadow: var(--shadow-card);
  margin-top: var(--space-lg);
}
@media (min-width: 800px) { .woocommerce-MyAccount-content { margin-top: 0; } }

/* Acceder / Registrarse (sin sesión iniciada): dos tarjetas lado a lado
   en vez del formulario plano por defecto de WooCommerce, centradas en
   la página en vez de estirarse a los 1080px completos del contenedor
   — con solo dos tarjetas cortas, ese ancho completo se veía vacío y
   descentrado. */
.woocommerce-account .u-columns {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-lg);
  max-width: 760px;
  margin-inline: auto;
}
@media (min-width: 640px) { .woocommerce-account .u-columns { grid-template-columns: 1fr 1fr; } }
/* Mismo problema que con el menú de cuenta: WooCommerce trae de
   fábrica ".col2-set .col-1/.col-2 { float:left|right; width:48% }"
   para su maquetación clásica por flotantes — ese 48% se calculaba
   sobre el ancho de la columna del grid (no del total), encogiendo
   cada tarjeta a la mitad de lo que le correspondía. */
.woocommerce-account .u-columns .col-1,
.woocommerce-account .u-columns .col-2 {
  float: none;
  width: 100%;
}
/* El propio WooCommerce trae un clearfix en ".col2-set::before/::after"
   (content:" "; display:table) pensado para su maquetación con floats.
   Ese contenido generado sigue contando como una celda más dentro de
   nuestro grid: con 2 columnas y 4 "hijos" reales (::before, col-1,
   col-2, ::after) el orden de colocación automática deja a Acceder en
   la 2ª columna y a Registrarse en una fila aparte, en vez de los dos
   lado a lado. content:none quita esas cajas fantasma del grid — el
   clearfix no hace falta aquí porque el grid ya no depende de floats. */
.woocommerce-account .u-columns::before,
.woocommerce-account .u-columns::after {
  content: none;
}
.woocommerce-account .woocommerce-form-login,
.woocommerce-account .woocommerce-form-register {
  background: var(--bg-section-alt);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-card);
  padding: var(--space-lg);
}
.woocommerce-account .woocommerce-form-login h2,
.woocommerce-account .woocommerce-form-register h2,
.woocommerce-account h2.woocommerce-form-login-title,
.woocommerce-account h2.woocommerce-form-register-title { margin-top: 0; font-size: 1.2rem; }

/* Insignias de estado — Autogest930_Expediente::badge_estado_html(). */
.ag930-badge {
  display: inline-flex;
  align-items: center;
  font-size: var(--fs-eyebrow);
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  padding: 0.35em 0.85em;
  border-radius: 99px;
  white-space: nowrap;
}
.ag930-badge--neutro  { background: var(--bg-section-alt); color: var(--text-muted); }
.ag930-badge--aviso   { background: #FFF4E5; color: #A9670A; }
.ag930-badge--proceso { background: #E7F0FE; color: #1D4ED8; }
.ag930-badge--exito   { background: #E7F6EC; color: #157A3D; }
.ag930-badge--peligro { background: #FDECEC; color: var(--action); }

/* "Mis expedientes": tarjetas en vez de tabla plana. */
.ag930-expedientes-grid { display: grid; gap: var(--space-md); grid-template-columns: 1fr; }
@media (min-width: 560px) { .ag930-expedientes-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 900px) { .ag930-expedientes-grid { grid-template-columns: repeat(3, 1fr); } }
.ag930-expediente-card {
  background: #fff;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-card);
  padding: var(--space-md);
  box-shadow: var(--shadow-card);
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  transition: transform var(--transition-base), box-shadow var(--transition-base);
}
.ag930-expediente-card:hover { transform: translateY(-2px); box-shadow: 0 8px 24px rgba(21,23,25,0.08); }
.ag930-expediente-card-top { display: flex; justify-content: space-between; align-items: center; gap: var(--space-sm); }
.ag930-expediente-card-id { font-size: 0.8rem; color: var(--text-muted); font-weight: 700; }
.ag930-expediente-card-titulo { margin: 0; font-size: 1.05rem; }
.ag930-expediente-card-link { margin-top: auto; align-self: flex-start; }

/* Detalle de un expediente. */
.ag930-expediente-detalle { max-width: 780px; }
.ag930-volver { margin-bottom: var(--space-md); font-size: 0.9rem; }
.ag930-expediente-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  flex-wrap: wrap;
  gap: var(--space-sm);
  padding-bottom: var(--space-md);
  margin-bottom: var(--space-lg);
  border-bottom: 1px solid var(--border-subtle);
}
.ag930-expediente-header h2 { margin: 0.15em 0 0; }
.ag930-expediente-header-id { font-size: 0.85rem; color: var(--text-muted); font-weight: 700; letter-spacing: 0.03em; }
.ag930-panel {
  background: var(--bg-section-alt);
  border-radius: var(--radius-card);
  padding: var(--space-md) var(--space-lg);
  margin-bottom: var(--space-lg);
}
.ag930-panel h3 { margin-top: 0; }
.ag930-panel h4 { margin-top: var(--space-md); }
.ag930-lista-documentos-grupo { margin-bottom: 0.3em; }

/* ---------- Ritmo general de secciones ---------- */
/* No dejar contenido pegado a los bordes en pantallas muy estrechas. */
@media (max-width: 400px) {
  .container { padding-inline: var(--space-sm); }
}

/* =========================================================
   Área privada v2 — iconos de menú, timeline visual, hilo de
   mensajes tipo chat y estados vacíos elegantes. Todo por encima
   del grid sidebar+contenido que ya existía (líneas ~1436 y
   siguientes): ningún HTML de WooCommerce/plugin cambia aquí,
   solo aspecto.
   ========================================================= */

/* Iconos por pestaña — WooCommerce ya añade la clase
   .woocommerce-MyAccount-navigation-link--{endpoint} a cada <li>,
   así que no hace falta tocar ninguna plantilla para pintarlos. */
.woocommerce-MyAccount-navigation-link a { display: flex; align-items: center; gap: 0.6em; }
.woocommerce-MyAccount-navigation-link a::before { font-size: 1.05em; line-height: 1; }
.woocommerce-MyAccount-navigation-link--dashboard a::before { content: '🏠'; }
.woocommerce-MyAccount-navigation-link--orders a::before { content: '🧾'; }
.woocommerce-MyAccount-navigation-link--mis-expedientes a::before { content: '📁'; }
.woocommerce-MyAccount-navigation-link--downloads a::before { content: '📄'; }
.woocommerce-MyAccount-navigation-link--edit-account a::before { content: '👤'; }
.woocommerce-MyAccount-navigation-link--ag930-ayuda a::before { content: '💬'; }
.woocommerce-MyAccount-navigation-link--customer-logout a::before { content: '🚪'; }

/* "Necesitas ayuda" + "Cerrar sesión" quedan agrupados al final,
   separados del resto de pestañas por una línea. */
.woocommerce-MyAccount-navigation-link--ag930-ayuda { margin-top: 0.6em; padding-top: 0.6em; border-top: 1px solid var(--border-subtle); }

/* Estado vacío reutilizable — listados sin contenido (expedientes,
   descargas, novedades, mensajes) dejan de ser un simple <p>. */
.ag930-empty-state {
  text-align: center;
  padding: var(--space-xl) var(--space-md);
  color: var(--text-muted);
}
.ag930-empty-state .ag930-empty-state-icon { font-size: 2rem; display: block; margin-bottom: 0.4em; }
.ag930-empty-state p { margin: 0.2em 0; }

/* Timeline de seguimiento del expediente (Autogest930_Area_Privada::render_detalle()
   y el bloque "Novedades" del Escritorio comparten este mismo componente). */
.ag930-timeline {
  list-style: none;
  margin: 0;
  padding: 0 0 0 1.4em;
  position: relative;
}
.ag930-timeline::before {
  content: '';
  position: absolute;
  left: 0.35em;
  top: 0.4em;
  bottom: 0.4em;
  width: 2px;
  background: var(--border-subtle);
}
.ag930-timeline li {
  position: relative;
  padding-bottom: var(--space-md);
  font-size: var(--fs-small);
}
.ag930-timeline li:last-child { padding-bottom: 0; }
.ag930-timeline li::before {
  content: '';
  position: absolute;
  left: -1.4em;
  top: 0.3em;
  width: 0.6em;
  height: 0.6em;
  border-radius: 50%;
  background: var(--action);
  box-shadow: 0 0 0 3px #fff;
}
.ag930-timeline .fecha { display: block; font-weight: 700; color: var(--text-strong); font-size: 0.78rem; margin-bottom: 0.15em; }

/* Hilo de mensajes con el equipo, en burbujas. */
.ag930-hilo-cliente { display: flex; flex-direction: column; gap: var(--space-sm); margin-bottom: var(--space-md); max-height: 360px; overflow-y: auto; }
.ag930-mensaje {
  max-width: 80%;
  padding: 0.7em 1em;
  border-radius: var(--radius-card);
  background: var(--bg-section-alt);
}
.ag930-mensaje strong { display: block; font-size: 0.8rem; }
.ag930-mensaje p { margin: 0.25em 0 0; }
.ag930-mensaje-fecha { font-size: var(--fs-eyebrow); color: var(--text-muted); }
.ag930-mensaje-cliente { align-self: flex-end; background: #FDECEC; }
.ag930-mensaje-equipo { align-self: flex-start; }

/* Listas de documentos descargables (Documentos del expediente y Descargas). */
.ag930-lista-documentos { list-style: none; margin: 0 0 var(--space-md); padding: 0; }
.ag930-lista-documentos li { padding: 0.3em 0; }
.ag930-lista-documentos a { display: inline-flex; align-items: center; gap: 0.4em; }

/* En móvil, el menú lateral pasa a franja horizontal desplazable en
   vez de columna de una sola línea por ítem, para no consumir media
   pantalla de scroll antes de llegar al contenido real. */
@media (max-width: 799px) {
  .woocommerce-MyAccount-navigation ul { flex-direction: row; flex-wrap: wrap; }
  .woocommerce-MyAccount-navigation li { flex: 1 1 auto; }
  .woocommerce-MyAccount-navigation-link--ag930-ayuda { margin-top: 0; padding-top: 0; border-top: 0; }
}

/* =========================================================
   Escritorio (woocommerce/myaccount/dashboard.php del tema).
   ========================================================= */
.ag930-dashboard { display: flex; flex-direction: column; gap: var(--space-lg); }
.ag930-dashboard-saludo h2 { margin: 0; }
.ag930-dashboard-expediente-top { display: flex; justify-content: space-between; align-items: flex-start; gap: var(--space-sm); flex-wrap: wrap; }
.ag930-dashboard-expediente-titulo { margin: 0.2em 0 0; font-weight: 600; font-size: 1.05rem; }
.ag930-dashboard-expediente-fecha { color: var(--text-muted); font-size: var(--fs-small); }
.ag930-dashboard-expediente-siguiente { margin-bottom: var(--space-sm); }

.ag930-dashboard-accesos { display: grid; gap: var(--space-sm); grid-template-columns: repeat(2, 1fr); }
@media (min-width: 560px) { .ag930-dashboard-accesos { grid-template-columns: repeat(4, 1fr); } }
.ag930-quick-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.4em;
  padding: var(--space-md);
  background: #fff;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  text-align: center;
  font-weight: 600;
  font-size: var(--fs-small);
  color: var(--text-strong);
  transition: transform var(--transition-base), box-shadow var(--transition-base);
}
.ag930-quick-card:hover { transform: translateY(-2px); box-shadow: 0 8px 24px rgba(21,23,25,0.08); color: var(--action); }
.ag930-quick-card-icon { font-size: 1.6rem; }

.ag930-novedades-lista { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-sm); }
.ag930-novedad-item {
  display: flex;
  align-items: baseline;
  gap: 0.6em;
  padding: 0.6em 0.8em;
  border-radius: 6px;
  background: #fff;
}
.ag930-novedad-item--nuevo { background: #FDECEC; }
.ag930-novedad-index { font-weight: 700; color: var(--action); flex-shrink: 0; }
.ag930-novedad-texto { flex: 1; }
.ag930-novedad-fecha { font-size: 0.75rem; color: var(--text-muted); white-space: nowrap; }

/* =========================================================
   Descargas (woocommerce/myaccount/downloads.php del tema).
   ========================================================= */
.ag930-descargas-lista { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-sm); }
.ag930-descargas-item {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding: 0.7em 1em;
  background: #fff;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-card);
}
.ag930-descargas-icono { font-size: 1.3rem; }
.ag930-descargas-nombre { flex: 1; font-weight: 600; }
.ag930-descargas-expediente { display: block; font-weight: 400; font-size: 0.75rem; color: var(--text-muted); }
.ag930-descargas-fecha { font-size: 0.8rem; color: var(--text-muted); white-space: nowrap; }
@media (max-width: 480px) {
  .ag930-descargas-item { flex-wrap: wrap; }
  .ag930-descargas-fecha { order: 3; }
}

/* =========================================================
   Detalles de cuenta — campos extra + resumen de solo lectura
   (Autogest930_Cuenta_Detalles).
   ========================================================= */
.woocommerce-EditAccountForm fieldset {
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-card);
  padding: var(--space-md) var(--space-lg);
  margin-bottom: var(--space-lg);
}
.woocommerce-EditAccountForm fieldset legend { font-weight: 700; padding: 0 0.4em; }
.ag930-cuenta-resumen-grid { display: grid; gap: var(--space-md); grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); margin-bottom: var(--space-sm); }
.ag930-cuenta-resumen-item { text-align: center; }
.ag930-cuenta-resumen-valor { display: block; font-size: 1.3rem; font-weight: 700; color: var(--action); }
.ag930-cuenta-resumen-label { display: block; font-size: var(--fs-small); color: var(--text-muted); }
.ag930-cuenta-resumen-historial { font-size: var(--fs-small); color: var(--text-muted); margin: 0; }

/* =========================================================
   Página FAQ ([autogest930_faq], acordeón nativo <details>/<summary>).
   ========================================================= */
.ag930-faq { display: flex; flex-direction: column; gap: var(--space-sm); max-width: 780px; margin-inline: auto; }
.ag930-faq-item {
  background: #fff;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-card);
  padding: var(--space-sm) var(--space-md);
  box-shadow: var(--shadow-card);
}
.ag930-faq-item summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-weight: 600;
  padding: 0.4em 0;
}
.ag930-faq-item summary::-webkit-details-marker { display: none; }
.ag930-faq-item summary::after {
  content: '+';
  font-size: 1.2rem;
  color: var(--action);
  transition: transform var(--transition-fast);
  flex-shrink: 0;
  margin-left: 1em;
}
.ag930-faq-item[open] summary::after { transform: rotate(45deg); }
.ag930-faq-answer { padding-top: 0.4em; color: var(--text-muted); }
.ag930-faq-answer p:last-child { margin-bottom: 0; }

/* ---------- Calendario de eventos: mini calendario + lista ---------- */
.ag930-calendario-layout {
  display: flex;
  align-items: flex-start;
  gap: var(--space-lg);
}
.ag930-calendario-layout .ag930-calendario {
  flex: 1 1 auto;
  min-width: 0;
}
.ag930-mini-calendario {
  flex: 0 0 auto;
  width: 260px;
  padding: var(--space-md);
  background: #fff;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
}
/* Cabecera del mini calendario: mes en el centro y, a los lados, los
   controles para moverse un mes o un año completo (ver eventos-v2.js,
   plugin Core). Los botones solo se muestran cuando hay JavaScript
   —"ag930-js" en <html>—, porque sin él no harían nada; el hueco que
   ocupan está reservado con min-height, así que la cabecera mide lo
   mismo en los dos casos y el calendario no se mueve al cargar. */
.ag930-mini-calendario-cab {
  display: flex;
  align-items: center;
  gap: 0.1rem;
  min-height: 30px;
  margin-bottom: var(--space-sm);
}
.ag930-mini-calendario-mes {
  flex: 1 1 auto;
  text-align: center;
  font-family: var(--font-display);
  font-weight: 600;
  color: var(--text-strong);
  text-transform: capitalize;
  margin-bottom: 0;
}
.ag930-mini-calendario-nav {
  display: none;
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  padding: 0;
  border: 1px solid var(--border-subtle);
  border-radius: 50%;
  background: #fff;
  color: var(--text-muted);
  font: inherit;
  font-size: 0.9rem;
  line-height: 1;
  cursor: pointer;
  transition: background var(--transition-fast), color var(--transition-fast), border-color var(--transition-fast);
}
.ag930-js .ag930-mini-calendario-nav { display: inline-flex; align-items: center; justify-content: center; }
.ag930-mini-calendario-nav:hover {
  background: var(--action);
  border-color: var(--action);
  color: #fff;
}
.ag930-mini-calendario-pie {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
}
.ag930-mini-calendario-hoy {
  flex: 0 0 auto;
  margin-top: var(--space-sm);
  padding: 0;
  border: 0;
  background: transparent;
  font: inherit;
  font-size: var(--fs-eyebrow);
  font-weight: 600;
  color: var(--action);
  text-decoration: underline;
  cursor: pointer;
}
.ag930-mini-calendario-hoy[hidden] { display: none; }
.ag930-mini-calendario-hoy:hover { color: var(--action-hover); }
.ag930-mini-calendario-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 0.25rem;
  text-align: center;
}
.ag930-mini-calendario-cabecera {
  font-size: var(--fs-eyebrow);
  font-weight: 600;
  color: var(--text-muted);
  padding-bottom: 0.35rem;
}
.ag930-mini-calendario-dia,
.ag930-mini-calendario-vacio {
  aspect-ratio: 1 / 1;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--fs-small);
  border-radius: 50%;
}
.ag930-mini-calendario-dia { color: var(--text-body); }
.ag930-mini-calendario-dia.is-today {
  background: var(--bg-section-alt);
  font-weight: 600;
  color: var(--text-strong);
}
.ag930-mini-calendario-dia.has-event {
  background: var(--action);
  color: #fff;
  font-weight: 600;
}
/* El día en sí solo es pulsable de verdad con JavaScript (eventos-v2.js
   es quien lleva hasta la tarjeta correspondiente): igual que los
   controles de mes/año de arriba, el cursor y el estado de foco solo se
   muestran con la clase "ag930-js" puesta en <html>. */
.ag930-js .ag930-mini-calendario-dia.has-event {
  cursor: pointer;
  position: relative;
  transition: transform 0.15s ease, background-color 0.15s ease;
}
/* Círculo más grande al pasar el ratón o llegar con teclado: la única
   pista de que ese día concreto lleva a algo (el resto del calendario no
   reacciona al hover). transform no afecta al layout, así que puede
   crecer sin desplazar el resto de la rejilla; z-index lo mantiene por
   encima de los días vecinos mientras dura el efecto. */
.ag930-js .ag930-mini-calendario-dia.has-event:hover,
.ag930-js .ag930-mini-calendario-dia.has-event:focus-visible {
  background: var(--action-hover);
  transform: scale(1.35);
  z-index: 1;
}
.ag930-js .ag930-mini-calendario-dia.has-event:focus-visible {
  outline: 2px solid var(--action-hover);
  outline-offset: 2px;
}
.ag930-mini-calendario-leyenda {
  display: flex;
  align-items: center;
  gap: 0.5em;
  margin: var(--space-sm) 0 0;
  font-size: var(--fs-eyebrow);
  color: var(--text-muted);
}
.ag930-mini-calendario-punto {
  width: 0.6em;
  height: 0.6em;
  border-radius: 50%;
  background: var(--action);
  flex-shrink: 0;
}
@media (max-width: 782px) {
  .ag930-calendario-layout { flex-direction: column; }
  .ag930-mini-calendario { width: 100%; }
}


/* =========================================================
   Zonas pulsables en pantallas táctiles (WCAG 2.5.8)
   ---------------------------------------------------------
   La recomendación es 44x44 px CSS para que un dedo acierte.
   En la portada a 375px había 56 controles por debajo de esa
   medida: los enlaces "Saber más" de las tarjetas (82x19), los
   del pie (19px de alto), el botón de menú (41x29) y el del
   carrito (40x40).

   Todo va dentro de una media query: en escritorio, donde se
   apunta con ratón, el diseño se queda EXACTAMENTE igual.
   ========================================================= */
@media (max-width: 640px) {
  /* Botones: les faltaban 2px para llegar a 44. */
  .btn {
    min-height: 44px;
  }

  /* Controles de icono de la cabecera. */
  .menu-toggle,
  .btn-cart-icon {
    min-width: 44px;
    min-height: 44px;
    justify-content: center;
  }

  /* "Saber más →" de las tarjetas de servicio: el texto se queda
     igual, lo que crece es el área que responde al dedo. */
  .card-link {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }

  /* Enlaces del pie. Se anula el margen del <li> porque la altura
     mínima del enlace ya aporta la separación: sin esto el pie
     crecería el doble de lo necesario. */
  .footer-col li {
    margin-bottom: 0;
  }
  .footer-col li a,
  .footer-bottom a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }

  /* Cerrar el cajón del carrito: 28x32 es difícil de acertar
     justo cuando el usuario quiere volver a la compra. */
  .ag930-cart-drawer-close {
    min-width: 44px;
    min-height: 44px;
  }
}

/* ------------------------------------------------------------------
 * SERVICIO EN PREPARACION
 *
 * Seguros para historicos y transporte especializado siguen contados
 * enteros, pero sin formulario: no se recoge una solicitud que no
 * podemos servir (ver 'en_preparacion' en inc/page-config.php). Este
 * aviso ocupa el sitio del boton rojo, arriba del todo.
 *
 * Es un aviso, no una alarma: fondo suave y una barra roja a la
 * izquierda, el mismo lenguaje que el resto de bloques destacados del
 * sitio. Nada de amarillo de advertencia — el servicio no esta roto,
 * esta llegando.
 * ---------------------------------------------------------------- */
.servicio-preparacion {
  margin: 0 0 var(--space-lg);
  padding: var(--space-lg);
  background: var(--bg-section-alt);
  border-left: 4px solid var(--action);
  border-radius: var(--radius-card);
}
.servicio-preparacion__rotulo {
  margin: 0 0 0.4em;
  color: var(--action);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.servicio-preparacion__titulo {
  margin: 0 0 0.6em;
  font-size: clamp(1.25rem, 2.4vw, 1.6rem);
  line-height: 1.25;
  color: var(--text-strong);
}
.servicio-preparacion p {
  margin: 0 0 0.8em;
  color: var(--text-muted);
  line-height: 1.6;
}
.servicio-preparacion p:last-child { margin-bottom: 0; }
.servicio-preparacion__cta { margin-top: var(--space-md); }

/* El botón «Mostrar contraseña» de WooCommerce en el acceso del área
   privada medía 22x22, por debajo de los 24 px de la WCAG 2.5.8 (target-size
   de Lighthouse en /area-privada/). Auditoría de apertura, 2026-09-25. */
.woocommerce form .show-password-input {
  min-width: 24px;
  min-height: 24px;
}

/* Plazos reales (plugin: Autogest930_Plazos_Reales). Solo aparecen con
   datos suficientes: una tabla en Precios y una línea sobre el formulario. */
.ag930-plazos-reales {
  margin: var(--space-xl) 0 var(--space-lg);
}
.ag930-plazos-reales table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-small);
}
.ag930-plazos-reales th,
.ag930-plazos-reales td {
  padding: 0.6rem 0.75rem;
  border-bottom: 1px solid var(--border-subtle);
  text-align: left;
}
.ag930-plazos-reales thead th {
  color: var(--text-muted);
  font-weight: 600;
}
.ag930-plazo-real {
  max-width: 780px;
  margin: 0 auto var(--space-sm);
  font-size: var(--fs-small);
  color: var(--text-muted);
}

/* Opiniones verificadas (plugin: Autogest930_Testimonios; lugares en
   inc/resenas.php). Todo apagado hasta que se activa desde el panel. */
.ag930-estrellas {
  color: #8a6508;
  letter-spacing: 0.08em;
}
.ag930-resenas-resumen {
  margin: var(--space-xs) 0;
  font-size: var(--fs-small);
}
.ag930-resenas-resumen a {
  color: inherit;
  text-decoration: none;
}
.ag930-resenas-resumen a:hover strong,
.ag930-resenas-resumen a:focus-visible strong {
  text-decoration: underline;
}
.ag930-resenas-seccion {
  margin: var(--space-xl) 0;
}
.ag930-resenas-ficha {
  max-width: 780px;
  margin: 0 auto var(--space-md);
}
.ag930-testimonio-fuente {
  display: block;
  font-size: var(--fs-small);
}
.ag930-testimonios-verificacion {
  margin-top: var(--space-sm);
  color: var(--text-muted);
  font-size: 0.8125rem;
}
.footer-bottom .ag930-resenas-resumen {
  margin: 0;
}

/* ------------------------------------------------------------------
   Arreglos de la auditoría integral del 2026-09-28 (tema RC131+)
   ------------------------------------------------------------------ */

/* «Actualidad» con 1 o 2 artículos: una fila de columnas a la mitad, en
   vez de una columna de un tercio y el resto en blanco hasta el panel de
   eventos. La clase la pone template-parts/editorial-events.php según
   cuántos artículos hay. */
@media (min-width: 960px) {
  .ag930-carrusel__pista--cuenta-1,
  .ag930-carrusel__pista--cuenta-2 { grid-auto-columns: calc((100% - var(--space-md)) / 2); }
}

/* Formulario de servicio de vuelta de un envío con errores: los archivos
   no se conservan, y se dice junto a cada campo (class-form-shortcode.php,
   render_aviso_reintento()). */
.ag930-aviso-reintento {
  margin: 0.4rem 0 0;
  padding: 0.45rem 0.7rem;
  border-left: 3px solid var(--action);
  background: #FFF4F4;
  color: var(--text-body);
  font-size: 0.875rem;
  line-height: 1.45;
}
.ag930-form-errores .ag930-form-errores-archivos { margin: 0.6rem 0 0; }
.ag930-info-privacidad { margin-top: 0.5rem; font-size: 0.8125rem; line-height: 1.5; }

/* Área privada a 375 px: la caja de «Mi cuenta» (40 px de relleno) y el
   panel del expediente (otros 40 px) dejaban 181 px para los campos, y
   el desplegable de subida se leía «Documento nuev» y el selector de
   archivo «N…n». La etiqueta de estado, que no parte línea, se salía
   del panel. En móvil los rellenos bajan y la etiqueta puede partirse. */
@media (max-width: 480px) {
  .woocommerce-MyAccount-content { padding: var(--space-sm) 0.75rem; }
  .woocommerce-MyAccount-content .ag930-panel { padding: var(--space-sm) 0.75rem; }
  .woocommerce-MyAccount-content .ag930-badge { white-space: normal; max-width: 100%; }
  .woocommerce-MyAccount-content .ag930-form select,
  .woocommerce-MyAccount-content .ag930-form input[type="file"] { width: 100%; max-width: 100%; }
}
.ag930-subida-nota,
.ag930-subida-plazo { margin: 0.25rem 0 var(--space-sm); font-size: var(--fs-small); }
