:root {
  /* Alto de la cabecera fija. Lo usan la propia barra y el hero de la
     portada, que tiene que restarlo para caber en la primera pantalla. Se
     redefine en los dos cortes; antes eran tres números sueltos. */
  --alto-cabecera: 104px;

  --navy-primary: #0a1230;
  --deep-blue: #101b3d;
  --turquoise: #19e0c2;
  --cyan: #00b4ff;
  --electric-blue: #2962ff;
  --soft-white: #f7f9fa;
  --dark-gray: #1f2933;
  --brand-gradient: linear-gradient(90deg, var(--turquoise), var(--cyan), var(--electric-blue));
  --quiet-gradient: linear-gradient(90deg, rgba(25,224,194,.55), rgba(0,180,255,.5), rgba(41,98,255,.45));

  --primary-950: var(--navy-primary);
  --primary-900: var(--deep-blue);
  --primary-800: var(--electric-blue);
  --accent-700: var(--turquoise);
  --accent-600: var(--cyan);
  --accent-500: var(--electric-blue);
  --surface: var(--soft-white);
  --soft: var(--soft-white);
  --muted-surface: rgba(16, 27, 61, .06);
  --text: var(--dark-gray);
  --muted: rgba(31, 41, 51, .72);
  --border: rgba(16, 27, 61, .16);
  --shadow: 0 10px 24px rgba(10, 18, 48, .07);
  /* Estaba en uso y sin definir: `.contact-aside`, `.contact-demo-badge` y
     `.staff-card` lo pedian y no existia, asi que esas tarjetas salian sin
     sombra. El valor es el que ya estaba repetido a mano en las tarjetas de
     Formaciones y de las cinco areas. */
  --soft-shadow: 0 12px 28px rgba(10, 18, 48, .045);
  --header-shadow: 0 4px 16px rgba(10, 18, 48, .06);
  --radius-sm: 8px;
  --radius-md: 14px;
  --radius-lg: 22px;
  --radius-pill: 999px;

  /* ── La respuesta al pasar por encima ──────────────────────────────
     Estaba escrita a mano en cada componente y cada uno decidio lo suyo: el
     salto iba de **1 a 6 pixeles**, el borde tenia cinco opacidades distintas
     y la sombra cinco redacciones. Con veinte tarjetas repartidas por el
     sitio, eso se nota al recorrerlo aunque ninguna pantalla parezca mal.

     Dos escalones y no uno: una tarjeta grande puede levantarse mas que un
     boton sin que se lea raro, pero dentro de cada escalon el valor es el
     mismo en todas partes. */
  --alza-control: -1px;   /* botones, filas, controles pequenos */
  --alza-tarjeta: -3px;   /* tarjetas y bloques pulsables */
  --borde-hover: rgba(0, 180, 255, .45);
  --sombra-hover: 0 18px 40px rgba(10, 18, 48, .12);
}

/* Quien pide menos movimiento no recibe ninguno.

   Se apaga **en el token**, no componente a componente: todo lo que se eleva
   lo hace con `translateY(var(--alza-…))`, asi que ponerlo a cero lo para
   entero de una vez —y lo que se anada manana nace ya cubierto—. El sitio
   tenia estas guardas escritas una por una y por eso las piezas nuevas se
   quedaban fuera sin que nadie lo notara.

   El color del borde y la sombra se quedan: informan de que algo responde sin
   moverse, que es justo lo que esta preferencia pide. */
@media (prefers-reduced-motion: reduce) {
  :root {
    --alza-control: 0;
    --alza-tarjeta: 0;
  }
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  color: var(--text);
  background: var(--surface);
  font-family: Manrope, system-ui, sans-serif;
  line-height: 1.55;
}
img { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button, input, select, textarea { font: inherit; }
:focus-visible { outline: 3px solid rgba(25,224,194,.36); outline-offset: 3px; }
.skip-link { position: absolute; left: 16px; top: -80px; z-index: 20; background: var(--primary-950); color: white; padding: 10px 14px; border-radius: var(--radius-sm); }
.skip-link:focus { top: 12px; }

h1, h2 {
  margin: 0;
  color: var(--primary-950);
  font-family: Manrope, system-ui, sans-serif;
  font-weight: 800;
  line-height: 1.02;
  letter-spacing: 0;
}
h1 { font-size: clamp(40px, 4vw, 64px); max-width: 720px; }
h2 { font-size: clamp(26px, 2.7vw, 40px); }
h3 { margin: 0; color: var(--primary-950); line-height: 1.15; }
p { color: var(--dark-gray); margin: 0; }
.lead { font-size: 17px; }
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 14px;
  color: var(--primary-900);
  font-size: 12px;
  font-weight: 900;
  letter-spacing: .16em;
  text-transform: uppercase;
}
.eyebrow::after { content: ""; width: 46px; height: 2px; background: var(--quiet-gradient); }
.section {
  width: min(1580px, calc(100% - 96px));
  margin: 0 auto;
  padding: 54px 0;
}
.section.soft {
  width: 100%;
  max-width: none;
  padding-inline: max(48px, calc((100vw - 1580px) / 2));
  background: var(--soft);
}
.section-header { max-width: 720px; margin-bottom: 26px; }
.section-header.center { margin-inline: auto; text-align: center; }
.section-header.center .eyebrow { justify-content: center; }
.section-header p { margin-top: 12px; font-size: 16px; }

.site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 50;
  display: grid;
  grid-template-columns: 380px 1fr;
  align-items: center;
  gap: 22px;
  /* El logotipo mide 63,5px de alto a 286px de ancho. Con 88px de barra y
     12px de relleno quedaba una caja de 64px: el logo la llenaba justa y
     tocaba los dos bordes. Con 104px le quedan 20px por arriba y por abajo,
     y el relleno lateral sube de 38 a 48px. */
  min-height: var(--alto-cabecera);
  padding: 16px max(48px, 5vw);
  /* Cristal oscuro.
     El tinte plano no bastaba: navy al 70% sobre contenido blanco da un
     gris pizarra apagado, no un cristal. La clave es `brightness`, que
     oscurece de verdad lo que pasa por detrás en vez de lavarlo. Así el
     tinte puede bajar al 46% —se transparenta mucho más— y la barra sale
     a la vez más oscura y más azul que antes.
     `saturate` alto mantiene el color de lo que hay debajo, que es lo que
     hace que se lea como cristal y no como pintura. */
  /* Sin filete en el canto inferior.

     Un borde claro al 14 % sobre la barra oscura es una línea brillante, y
     debajo empieza contenido claro: quedaba encajada entre dos tonos oscuros
     —la barra y su desvanecido— y era justo lo que se veía como un corte.

     La separación la da el desvanecido de `::after`, que es continuo. Un
     borde de 1 px nunca puede serlo. */
  border-bottom: 0;
  border-radius: 0;
  /* Azul Profundo del manual, #0A1230. Antes era #101B3D, que es el «Deep
     Blue» del checklist de assets y NO está en el manual; el resto del sitio
     ya usaba el correcto, así que la cabecera era la excepción.

     El tinte sube de 0,46 a 0,90 y el brillo baja de 0,40 a 0,30. El motivo
     es medible: con los valores anteriores la barra se pintaba #404655 —gris
     pizarra— porque el 54 % restante lo ponía el fondo blanco oscurecido por
     `brightness`. El color de marca no mandaba; lo hacía lo que hubiera
     detrás. Con 0,90 el resultado queda en #111833, a 7 por canal del hex
     del manual.

     La contrapartida está asumida: con el tinte tan alto la barra deja de
     ser cristal y pasa a ser azul de marca con un punto de transparencia. Es
     lo que exige que la barra TENGA el color del manual en vez de heredarlo
     del contenido. */
  background: #0A1230;
  /* Se queda el brillo interior de arriba, que da el canto de cristal. La
     sombra proyectada baja mucho: con el desvanecido debajo, las dos juntas
     creaban una banda gris entre la barra y el contenido. */
  box-shadow:
    0 6px 22px rgba(2,8,28,.08),
    inset 0 1px 0 rgba(255,255,255,.16);
  /* Sin `backdrop-filter`. Con el fondo opaco no se ve nada de lo que hay
     detrás, así que desenfocarlo es trabajo que el navegador hace en cada
     fotograma de scroll para un resultado que nadie percibe. En la portada
     sí se conserva, porque allí la barra sí es translúcida mientras baja. */
  isolation: isolate;
  transform: translateY(0);
  /* Se transicionan todas las que cambian entre los dos temas, no sólo el
     fondo: si el desenfoque y el filete saltan mientras el color se funde,
     el conjunto se lee como un corte aunque el fondo esté animado. */
  transition:
    transform .26s ease,
    background .38s cubic-bezier(.22,.61,.36,1),
    box-shadow .38s cubic-bezier(.22,.61,.36,1),
    -webkit-backdrop-filter .38s cubic-bezier(.22,.61,.36,1),
    backdrop-filter .38s cubic-bezier(.22,.61,.36,1),
    min-height .38s cubic-bezier(.22,.61,.36,1),
    padding .38s cubic-bezier(.22,.61,.36,1);
  will-change: transform;
}
/* Sin `backdrop-filter` no hay oscurecimiento y el tinte del 46% deja pasar
   el contenido claro: el menú se vuelve ilegible. Ahí la barra vuelve a ser
   maciza, que es feo pero legible. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .site-header {
    background: linear-gradient(180deg, rgba(10,18,48,.97) 0%, rgba(10,18,48,.93) 100%);
  }
}

/* El brillo de cristal de la barra, retirado.
   Eran cuatro centesimas y media de blanco por encima del Azul Profundo, y
   bastaban para que la barra pintara rgb(13,21,50) mientras el pie pintaba
   rgb(10,18,48). Medido sobre la pagina servida, no leido de la hoja: con
   transparencias el color declarado no es el que se ve.
   Tres puntos son casi nada por separado, pero cabecera y pie son los dos
   bloques de marca de la pagina y tienen que ser el mismo azul. Ahora los dos
   pintan el #0A1230 del manual. */
.site-header::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}
/* Desvanecido bajo la barra.

   El cambio de color no era lo brusco: lo brusco era el canto. Una barra
   oscura sobre un hero claro termina en una línea recta a media pantalla, y
   eso se lee como un recorte por mucho que el fondo esté animado.

   Este degradado continúa el tono de la barra unos píxeles por debajo y lo
   apaga. Va fuera del elemento —`bottom` negativo— para no comerle alto al
   contenido, y sin puntero para no tapar nada.

   Sólo aparece con la barra sólida: sobre el hero es transparente y no hay
   canto que disimular. */
.site-header::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -64px;
  height: 64px;
  z-index: -1;
  pointer-events: none;
  opacity: 0;
  /* Arranca en el tono con el que termina la barra y se apaga en tres
     tramos, no en dos: con una rampa lineal el final del degradado deja un
     canto tenue pero visible. La curva lo reparte. */
  /* Mismo hex que la barra: era #0E1732, que no está en ningún documento
     del proyecto —ni en el manual ni en el checklist—. */
  background: linear-gradient(180deg,
    rgba(10,18,48,.38) 0%,
    rgba(10,18,48,.18) 38%,
    rgba(10,18,48,.06) 68%,
    rgba(10,18,48,0) 100%);
  transition: opacity .34s ease;
}

.site-header.header-solido::after,
body:not(.con-cabecera-clara) .site-header::after {
  opacity: 1;
}

/* Sobre el hero no, que ahí la barra ya es transparente. */
body.con-cabecera-clara .site-header:not(.header-solido)::after {
  opacity: 0;
}
.site-header.header-hidden {
  transform: translateY(-110%);
}
.brand {
  position: relative;
  z-index: 2;
  display: inline-flex;
  flex-direction: column;
  gap: 4px;
  width: fit-content;
  line-height: 1;
}
.brand img {
  display: block;
  height: auto;
}
.site-header .brand img {
  width: 286px;
  max-width: calc(100vw - 170px);
}
.brand-line {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  white-space: nowrap;
}
.brand-line span {
  color: var(--primary-950);
  font-size: 23px;
  font-weight: 900;
  letter-spacing: .13em;
}
.brand-line strong {
  color: var(--primary-900);
  font-size: 23px;
  font-weight: 500;
  letter-spacing: .13em;
}
.brand-tagline {
  display: block;
  color: rgba(255,255,255,.58);
  font-size: 7px;
  font-weight: 800;
  line-height: 1.2;
  letter-spacing: .1em;
  text-transform: uppercase;
  white-space: nowrap;
}
.site-header .brand-tagline {
  display: none;
}
.main-nav { position: relative; z-index: 2; display: flex; justify-content: flex-end; gap: 20px; }
.main-nav a {
  position: relative;
  padding: 10px 0;
  /* El color cambia entre los dos temas de la cabecera; sin esto salta. */
  transition: color .38s cubic-bezier(.22,.61,.36,1);
  color: rgba(255,255,255,.9);
  font-size: 12px;
  font-weight: 900;
  text-transform: uppercase;
  border-bottom: 0;
  text-shadow: 0 1px 12px rgba(2,8,28,.34);
}
.main-nav a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 3px;
  height: 2px;
  border-radius: var(--radius-pill);
  background: linear-gradient(90deg, var(--turquoise), var(--electric-blue));
  opacity: 0;
  transform: scaleX(.55);
  transition: opacity .18s ease, transform .18s ease;
}
.main-nav a:hover,
.main-nav a.active {
  color: white;
}
.main-nav a:hover::after,
.main-nav a.active::after {
  opacity: 1;
  transform: scaleX(1);
}
.menu-toggle { position: relative; z-index: 2; display: none; }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  min-height: 42px;
  padding: 10px 16px;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  font-size: 14px;
  font-weight: 850;
  cursor: pointer;
}
/* La respuesta al pasar por encima.

   `.btn-outline` **no tenía ninguna**: el botón se quedaba igual y parecía un
   recuadro pintado, no algo que se pueda pulsar. Y el primario sí cambiaba de
   fondo, pero de golpe, porque `.btn` no declaraba transición.

   Va en la clase base y no en el hero: son los botones de todo el sitio y el
   problema era de todos. El desplazamiento es de un píxel —lo justo para que
   se note que responde— y el canto se tiñe del cian de marca. */
.btn {
  transition:
    background-color .18s ease,
    border-color .18s ease,
    color .18s ease,
    box-shadow .22s ease,
    transform .18s ease;
}

.btn:hover,
.btn:focus-visible { transform: translateY(var(--alza-control)); }
.btn:active { transform: translateY(0); }

.btn-primary { background: var(--primary-950); color: white; box-shadow: 0 10px 22px rgba(10,18,48,.16); }
.btn-primary:hover,
.btn-primary:focus-visible {
  background: var(--primary-900);
  filter: none;
  box-shadow: 0 14px 26px rgba(10, 18, 48, .22);
}
.btn-navy { background: var(--primary-950); color: white; }
.btn-outline { background: white; color: var(--primary-950); border-color: var(--border); }
.btn-outline:hover,
.btn-outline:focus-visible {
  /* Azul eléctrico y no cian. Los dos son del manual, pero un borde es un
     componente de interfaz y pide 3:1: el cian sobre blanco da **2,34:1** y el
     teal 1,68:1; el azul eléctrico, 4,90:1. Calculado, no elegido a ojo — y a
     ojo el cian era más bonito, que es justo por lo que hay que medirlo. */
  border-color: var(--primary-800);
  box-shadow: 0 10px 22px rgba(10, 18, 48, .12);
}
.btn-outline.light { color: white; background: transparent; border-color: rgba(255,255,255,.4); }
/* Sobre fondo oscuro el cian no se ve contra el borde blanco: ahí lo que
   responde es el propio borde, que se hace opaco. */
.btn-outline.light:hover,
.btn-outline.light:focus-visible {
  border-color: rgba(255, 255, 255, .85);
  background: rgba(255, 255, 255, .08);
  box-shadow: none;
}

/* Quien pide menos movimiento no recibe ninguno: el desplazamiento se quita
   entero, no se hace más lento. El cambio de color se queda, que informa sin
   moverse. */
@media (prefers-reduced-motion: reduce) {
  .btn { transition: background-color .18s ease, border-color .18s ease, color .18s ease; }
  .btn:hover, .btn:focus-visible, .btn:active { transform: none; }
}
.btn-icon { background: var(--soft); color: var(--primary-950); border-color: var(--border); }
.actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 28px; }
.site-header .header-cta {
  background: rgba(255,255,255,.96);
  color: var(--primary-950);
  box-shadow: none;
}
.site-header .header-cta:hover {
  background: white;
}

.hero {
  display: grid;
  grid-template-columns: minmax(390px, .82fr) 1.18fr;
  min-height: 500px;
  border-bottom: 1px solid var(--border);
}
.hero-copy {
  align-self: center;
  padding: 50px 36px 50px max(42px, calc((100vw - 1240px) / 2));
}
.hero-copy h1 span { color: var(--primary-900); }
.hero-copy p { max-width: 580px; margin-top: 15px; }
.hero-image {
  min-height: 460px;
  background:
    linear-gradient(90deg, rgba(255,255,255,.98), rgba(255,255,255,.55), rgba(255,255,255,.04)),
    var(--hero);
  background-size: cover;
  background-position: center right;
}
.compact-hero { min-height: 460px; }
.home-main-hero {
  position: relative;
  display: block;
  min-height: 560px;
  overflow: hidden;
}
.home-main-hero h1 {
  max-width: 650px;
  font-size: clamp(44px, 4.05vw, 62px);
}
.home-main-hero .hero-copy {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: 560px;
  width: min(700px, 58vw);
  padding: 56px 28px 56px clamp(34px, 4.2vw, 72px);
}
.home-main-hero .hero-copy p { max-width: 560px; }
.home-main-hero .actions {
  gap: 10px;
}
.home-main-hero .btn {
  min-height: 40px;
  padding: 9px 13px;
  font-size: 13px;
  white-space: nowrap;
}
.home-main-hero .hero-image {
  position: absolute;
  inset: 0;
  z-index: 0;
  min-height: 100%;
  background:
    linear-gradient(90deg, #fff 0%, rgba(255,255,255,.98) 25%, rgba(255,255,255,.78) 43%, rgba(255,255,255,.26) 65%, rgba(255,255,255,0) 100%),
    var(--hero);
  background-size: cover;
  background-position: center right;
}
.home-training-hero {
  grid-template-columns: minmax(420px, .74fr) 1.26fr;
  min-height: 460px;
}
.home-training-hero h1 {
  max-width: 560px;
  font-size: clamp(40px, 4vw, 58px);
}
.home-training-hero .hero-copy p {
  max-width: 560px;
  font-size: 16px;
}
.home-training-hero .hero-image {
  min-height: 460px;
  background:
    linear-gradient(90deg, rgba(255,255,255,.98), rgba(255,255,255,.70), rgba(255,255,255,.05)),
    var(--hero);
  background-position: center right;
}

.inner-hero, .detail-hero, .talent-hero {
  display: grid;
  grid-template-columns: 1fr .85fr;
  gap: 36px;
  align-items: center;
  width: min(1580px, calc(100% - 96px));
  margin: 0 auto;
  padding: 48px 0;
}
main > .inner-hero:first-child,
main > .detail-hero:first-child,
main > .talent-hero:first-child,
main > .editorial-hero:first-child,
main > .contact-hero:first-child,
main > .portal-hero:first-child,
main > .error-pagina:first-child,
main > .portal-acceso:first-child,
main > .portal-perfil:first-child,
main > .cv-pagina:first-child {
  /* La cabecera fija pasó de 88 a 104px y este despeje se quedaba en 28px. */
  padding-top: 148px;
}
main > .home-main-hero:first-child,
main > .portal-hero-presenta:first-child {
  margin-top: var(--alto-cabecera);
}

/* El hero de la portada resta el alto de la barra.

   Con la cabecera opaca deja de ser parte del dibujo: el hero empieza por
   debajo. Si además mide `100svh`, la portada pasa a medir una pantalla más
   el alto de la barra y hay que hacer scroll para ver el final del hero, que
   es justo lo que no debe pasar. Restándolo, el hero termina exactamente en
   el borde inferior de la primera pantalla. */
main > .home-main-hero.hero-animado:first-child {
  min-height: calc(100svh - var(--alto-cabecera));
}
.inner-hero.small { display: block; max-width: 900px; }
.inner-hero p, .detail-hero p, .talent-hero p { margin-top: 16px; max-width: 660px; font-size: 16px; }
.inner-hero img, .detail-hero img, .talent-hero img {
  width: 100%;
  height: 280px;
  object-fit: cover;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
}
.about-hero {
  grid-template-columns: minmax(500px, .92fr) minmax(380px, .62fr);
  gap: clamp(44px, 6.5vw, 108px);
}
.about-hero h1 {
  max-width: 760px;
  font-size: clamp(38px, 3.9vw, 60px);
  line-height: 1.06;
}

/*
 * «Internacionalizamos», con el degradado de marca.
 *
 * No es el `--brand-gradient` tal cual: sobre este fondo —#F7F9FA medido— el
 * teal del manual da **1,59:1** y el cian **2,22:1**, y un titular de 56 px
 * necesita 3:1. Un degradado en el texto tiene que pasar el mínimo en su punto
 * más claro, no de media: si una parada falla, esa parte de la palabra no se
 * lee.
 *
 * Se conserva el recorrido del manual —teal, cian, azul eléctrico— con los dos
 * primeros oscurecidos hasta que pasan, y el tercero es el del manual sin tocar:
 *
 *     #0D9384  teal oscurecido ....... 3,60:1
 *     #0079BC  cian oscurecido ....... 4,46:1
 *     #2962FF  azul electrico ........ 4,64:1
 *
 * Medido sobre la página servida, no sobre la hoja de estilos.
 *
 * El color de respaldo es el azul y no `transparent`: si algún navegador no
 * recorta el fondo al texto, la palabra sale azul maciza en vez de invisible.
 */
.about-hero h1 span {
  color: var(--electric-blue);
  background: linear-gradient(90deg, #0d9384 0%, #0079bc 46%, #2962ff 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}
.about-hero > div:first-child p {
  max-width: 700px;
  font-size: 17px;
  line-height: 1.68;
}
.about-hero-panel {
  position: relative;
  display: grid;
  align-content: center;
  gap: 22px;
  min-height: 292px;
  padding: clamp(28px, 3vw, 40px);
  border: 1px solid rgba(16,27,61,.1);
  border-radius: var(--radius-lg);
  background:
    radial-gradient(circle at 94% 2%, rgba(25,224,194,.14), transparent 34%),
    linear-gradient(135deg, rgba(255,255,255,.96), rgba(244,249,252,.86));
  color: var(--primary-950);
  box-shadow: 0 20px 48px rgba(10,18,48,.07);
  overflow: hidden;
}
.about-hero-panel::before {
  content: "";
  position: absolute;
  inset: 18px;
  border: 1px solid rgba(16,27,61,.06);
  border-radius: calc(var(--radius-lg) - 8px);
  pointer-events: none;
}
.inner-hero .about-panel-logo {
  position: relative;
  z-index: 1;
  width: min(300px, 100%);
  height: auto;
  max-height: 78px;
  object-fit: contain;
  border-radius: 0;
  box-shadow: none;
  justify-self: start;
}
.about-panel-line {
  position: relative;
  z-index: 1;
  width: min(280px, 64%);
  height: 1px;
  background: linear-gradient(90deg, var(--accent-700), rgba(38,110,255,.38), transparent);
}
.about-panel-points {
  position: relative;
  z-index: 1;
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}
.about-panel-points span {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 38px;
  padding: 8px 13px;
  border: 1px solid rgba(16,27,61,.09);
  border-radius: var(--radius-pill);
  background: rgba(255,255,255,.78);
  color: var(--primary-950);
  font-size: 12px;
  font-weight: 850;
  box-shadow: 0 8px 20px rgba(10,18,48,.045);
}
.about-panel-points i {
  color: var(--accent-700);
}
.about-hero-panel p {
  position: relative;
  z-index: 1;
  max-width: 440px;
  margin: 0;
  color: var(--muted);
  font-size: 15px;
  line-height: 1.55;
}
.about-logo-strip {
  width: 100%;
  max-width: none;
  padding: 6px max(48px, calc((100vw - 1580px) / 2)) 18px;
}
.logo-band.about-logo-band {
  display: block;
  width: 100%;
  padding: 18px 0;
  border: 0;
  border-top: 1px solid rgba(16,27,61,.08);
  border-bottom: 1px solid rgba(16,27,61,.08);
  border-radius: 0;
  background: transparent;
  box-shadow: none;
}
.logo-band.about-logo-band .logo-carousel-window {
  width: 100%;
}
.logo-band.about-logo-band .logo-carousel-track {
  gap: clamp(16px, 1.8vw, 28px);
  animation-duration: 68s;
}
.logo-band.about-logo-band .logo-carousel-track .logo-tile {
  flex-basis: clamp(210px, 15vw, 270px);
  min-height: 82px;
  background: rgba(255,255,255,.72);
}
.logo-band.about-logo-band .logo-carousel-track .logo-tile img {
  max-width: 190px;
  max-height: 56px;
}

.stats-strip {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  border-bottom: 1px solid var(--border);
  background: var(--soft);
}
.stats-strip div { padding: 18px; text-align: center; border-right: 1px solid var(--border); }
.stats-strip strong { display: block; color: var(--primary-950); font-family: Manrope, system-ui, sans-serif; font-size: 27px; font-weight: 800; line-height: 1; }
.stats-strip span { display: block; color: var(--muted); font-size: 13px; }
.stats-strip.compact div { display: grid; gap: 6px; }
.stats-strip i { color: var(--primary-900); font-size: 30px; }

.audience-grid, .value-grid, .training-grid, .article-grid, .job-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
}
.audience-card, .value-grid article, .training-card, .article-card, .job-card, .form-card, .detail-panel {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: white;
  box-shadow: var(--shadow);
}
.audience-card { padding: 19px; }
.audience-heading {
  display: flex;
  align-items: center;
  gap: 22px;
  min-height: 58px;
  margin-bottom: 22px;
}
.audience-heading i {
  color: var(--primary-900);
  font-size: 48px;
  line-height: 1;
}
.audience-svg-icon {
  width: 54px;
  height: 54px;
  color: var(--primary-900);
  fill: none;
  stroke: currentColor;
  stroke-width: 1.45;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.audience-card h3 {
  color: var(--primary-950);
  font-size: 18px;
  font-weight: 900;
  letter-spacing: .02em;
  text-transform: uppercase;
}
.audience-card ul, .role-grid ul, .content-grid ul { padding-left: 18px; color: var(--dark-gray); }
.audience-card a { color: var(--primary-900); font-weight: 800; }

.split, .two-columns {
  display: grid;
  grid-template-columns: .8fr 1.2fr;
  gap: 28px;
  align-items: center;
}
.logo-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
}
.logo-tile {
  /* La transicion va en la base y no en el `:hover`: puesta solo ahi, la
     vuelta —al apartar el raton— es instantanea y se nota. */
  transition: transform .18s ease, border-color .18s ease, box-shadow .22s ease;
  min-height: 88px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background:
    linear-gradient(135deg, rgba(247,249,250,.98), rgba(16,27,61,.045));
  color: var(--primary-950);
  text-align: center;
}
/* Sólo el que es un enlace.

   `.logo-tile` se usa de dos formas en la misma rejilla: como `<a>` cuando el
   colaborador tiene web y como `<div>` cuando no. Se veían idénticos, así que
   la mitad de los logotipos parecían pulsables y no llevaban a ningún sitio.
   El selector `a.` es lo que los separa. */
a.logo-tile:hover,
a.logo-tile:focus-visible {
  transform: translateY(var(--alza-tarjeta));
  border-color: var(--borde-hover);
  box-shadow: var(--sombra-hover);
}

.logo-tile-image {
  padding: 12px 18px;
}
.logo-tile-image img {
  width: 100%;
  max-width: 270px;
  max-height: 76px;
  object-fit: contain;
}
.logo-tile-dark {
  background: var(--primary-950);
  border-color: rgba(255,255,255,.14);
}
.mock-logo-mark {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  min-width: 42px;
  height: 42px;
  padding: 0 8px;
  border: 1px solid rgba(25,224,194,.24);
  border-radius: 50%;
  color: var(--primary-900);
  font-family: Manrope, system-ui, sans-serif;
  font-size: 13px;
  font-weight: 900;
  letter-spacing: .06em;
}
.mock-logo-name {
  color: var(--primary-950);
  font-family: Manrope, system-ui, sans-serif;
  font-size: 18px;
  font-weight: 800;
  line-height: 1;
  white-space: nowrap;
}
.logo-tile:nth-child(2n) .mock-logo-mark {
  border-radius: var(--radius-sm);
  color: var(--primary-900);
  border-color: rgba(10,18,48,.18);
}
.logo-tile:nth-child(3n) .mock-logo-mark {
  border-radius: 14px 4px 14px 4px;
}
.logo-tile:nth-child(4n) .mock-logo-name {
  font-family: Manrope, system-ui, sans-serif;
  font-size: 17px;
  font-weight: 900;
  letter-spacing: 0;
}
.section.group-backing {
  width: 100%;
  max-width: none;
  padding: 64px 48px;
  background: linear-gradient(180deg, var(--surface), #eef3f6);
}
.group-backing {
  display: grid;
  gap: 0;
  border: 0;
  border-radius: 0;
  box-shadow: none;
}
.backing-card {
  position: relative;
  width: min(1580px, 100%);
  margin: 0 auto;
  display: grid;
  grid-template-columns: minmax(420px, .9fr) minmax(320px, .55fr);
  gap: clamp(24px, 4vw, 64px);
  align-items: end;
  overflow: hidden;
  padding: clamp(34px, 4.2vw, 64px);
  border: 1px solid rgba(255,255,255,.1);
  border-radius: 18px;
  background:
    radial-gradient(circle at 86% 18%, rgba(25,224,194,.16), transparent 24%),
    radial-gradient(circle at 12% 84%, rgba(41,98,255,.16), transparent 26%),
    var(--primary-950);
  box-shadow: 0 28px 70px rgba(10,18,48,.18);
}
.backing-card::before {
  content: "";
  position: absolute;
  inset: 22px;
  border: 1px solid rgba(255,255,255,.08);
  border-radius: 14px;
  pointer-events: none;
}
.backing-copy {
  position: relative;
  z-index: 1;
  padding: 0;
}
.backing-copy .eyebrow {
  color: rgba(255,255,255,.82);
}
.backing-copy h2 {
  max-width: 760px;
  color: white;
  font-size: clamp(34px, 3.4vw, 56px);
}
.backing-copy p {
  max-width: 720px;
  margin-top: 16px;
  color: rgba(255,255,255,.76);
  font-size: clamp(16px, 1.35vw, 21px);
  line-height: 1.5;
}
/* Cuadro de firma: solo el logotipo, centrado en su caja.
   Llevaba debajo la bajada de marca, que repetia lo que ya dice el parrafo
   grande de al lado. Sin ella el logotipo manda, y por eso se centra en los
   dos ejes en vez de quedar arriba a la izquierda esperando un texto que ya
   no esta. */
.backing-signature {
  position: relative;
  z-index: 1;
  display: grid;
  place-items: center;
  min-height: 190px;
  padding: 36px 24px;
  border: 1px solid rgba(255,255,255,.12);
  border-radius: var(--radius-md);
  background: rgba(255,255,255,.06);
  backdrop-filter: blur(16px);
}
.backing-signature img {
  width: min(400px, 88%);
}
/* Cinco columnas es lo que hay hoy, pero no está clavado a cinco.
   `auto-fit` reparte las que haya: con seis cifras y cinco columnas fijas, la
   sexta caía sola en una segunda fila ocupando un quinto del ancho y con
   cuatro huecos al lado. Medido antes de cambiarlo. Con cinco el resultado es
   exactamente el mismo de antes. */
.backing-metrics {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 12px;
  margin-top: 2px;
  background: transparent;
}
.backing-metrics div {
  min-height: 126px;
  display: grid;
  align-content: center;
  gap: 6px;
  padding: 20px;
  border: 1px solid rgba(255,255,255,.1);
  border-radius: var(--radius-md);
  background: rgba(255,255,255,.07);
  backdrop-filter: blur(12px);
}
.backing-metrics i {
  color: var(--accent-700);
  font-size: 20px;
}
.backing-metrics strong {
  color: white;
  font-family: Manrope, system-ui, sans-serif;
  font-weight: 800;
  font-size: clamp(26px, 2.2vw, 34px);
  line-height: 1;
}
.backing-metrics span {
  color: rgba(255,255,255,.68);
  font-size: 12px;
  line-height: 1.3;
}
.about-intro .split {
  align-items: start;
}
.about-intro .split p + p {
  margin-top: 14px;
}
/* Mismo motivo que en la portada: se reparten las que haya. */
.about-metrics {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 12px;
  margin-top: 30px;
  padding-top: 24px;
  border-top: 1px solid var(--border);
}
.about-metrics div {
  display: grid;
  min-height: 132px;
  align-content: center;
  gap: 8px;
  padding: 18px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: linear-gradient(180deg, var(--surface), #eef3f6);
}
.about-metrics i {
  color: var(--primary-900);
  font-size: 25px;
}
.about-metrics strong {
  color: var(--primary-950);
  font-family: Manrope, system-ui, sans-serif;
  font-weight: 800;
  font-size: 32px;
  line-height: 1;
}
.about-metrics span {
  color: var(--muted);
  font-size: 13px;
}
.about-values-section {
  margin-top: 12px;
}
.about-value-grid {
  grid-template-columns: repeat(5, minmax(0, 1fr));
}
.about-value-grid article {
  display: grid;
  align-content: start;
  gap: 12px;
  min-height: 264px;
  padding: 20px;
  border-radius: var(--radius-sm);
}
.value-card-top {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 0;
}
.value-card-top span {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  margin-left: -8px;
  align-self: flex-start;
  border-radius: 50%;
  border: 2px solid white;
  background: #e8fbf8;
  color: var(--primary-950);
  font-family: Manrope, system-ui, sans-serif;
  font-size: 11px;
  font-weight: 900;
  box-shadow: 0 6px 14px rgba(10,18,48,.08);
}
.about-value-grid article i {
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  order: -1;
  border: 3px solid #00b8ef;
  border-radius: 50%;
  background: var(--primary-950);
  color: white;
  font-size: 22px;
  box-shadow: 0 8px 18px rgba(10,18,48,.1);
}
.about-value-grid article h3 {
  font-size: 17px;
  line-height: 1.18;
}
.about-value-grid article p {
  font-size: 14px;
  line-height: 1.55;
}
.logo-showcase {
  width: min(1580px, 100%);
  margin: 24px auto 0;
  display: grid;
  gap: 14px;
}
/* Los logos cierran la portada, justo debajo del CTA y encima del pie. Antes
   iban dentro del bloque del Grupo y heredaban su fondo; ahora necesitan
   sección propia. El degradado va al revés que el de arriba para entrar desde
   el bloque oscuro del CTA sin corte. */
.section.logo-closing {
  width: 100%;
  max-width: none;
  padding: 56px 48px 64px;
  background: linear-gradient(180deg, #eef3f6, var(--surface));
}
.logo-closing .logo-showcase {
  margin-top: 0;
}
.logo-band {
  width: 100%;
  display: grid;
  grid-template-columns: minmax(240px, 330px) minmax(0, 1fr);
  gap: 22px;
  align-items: center;
  overflow: hidden;
  padding: 22px 24px;
  border: 1px solid rgba(16,27,61,.12);
  border-radius: var(--radius-md);
  background: rgba(255,255,255,.88);
  box-shadow: 0 14px 36px rgba(10,18,48,.05);
}
.logo-band:last-child {
  border-bottom: 1px solid rgba(16,27,61,.12);
}
.logo-band-copy span {
  display: block;
  margin-bottom: 8px;
  color: var(--primary-900);
  font-size: 11px;
  font-weight: 900;
  letter-spacing: .15em;
  text-transform: uppercase;
}
.logo-band-copy p {
  max-width: 360px;
  margin-top: 8px;
  color: var(--muted);
  font-size: 14px;
}
.logo-carousel-window {
  position: relative;
  min-width: 0;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
}
.logo-carousel-track {
  display: flex;
  width: max-content;
  gap: 14px;
  animation: logo-carousel 24s linear infinite;
}
.logo-carousel:nth-child(2) .logo-carousel-track { animation-duration: 29s; }
.logo-carousel:nth-child(3) .logo-carousel-track { animation-duration: 34s; }
.logo-carousel:hover .logo-carousel-track {
  animation-play-state: paused;
}

/* Con teclado tambien se para, pero por `:focus-visible` y no por
   `:focus-within`. Ver la nota larga de la tira de colaboradores: con
   `focus-within`, un clic de raton dejaba la cinta parada para siempre.
   En regla aparte para que, si un navegador no entiende `:has()`, se pierda
   solo esto y no la pausa al pasar por encima. */
.logo-carousel:has(:focus-visible) .logo-carousel-track {
  animation-play-state: paused;
}
.logo-carousel-track .logo-tile {
  flex: 0 0 clamp(190px, 17vw, 250px);
  min-height: 82px;
  background: white;
  border-color: rgba(16,27,61,.12);
  box-shadow: none;
}
.logo-carousel-track .logo-tile img {
  max-width: 190px;
  max-height: 58px;
}
@keyframes logo-carousel {
  from { transform: translateX(0); }
  to { transform: translateX(calc(-50% - 7px)); }
}
@media (prefers-reduced-motion: reduce) {
  .logo-carousel-track {
    width: auto;
    overflow-x: auto;
    animation: none;
    scroll-snap-type: x proximity;
  }
  .logo-carousel-track .logo-tile { scroll-snap-align: start; }
}
.portal-banner {
  display: grid;
  grid-template-columns: .86fr 1.14fr;
  gap: 28px;
  align-items: center;
  overflow: hidden;
  padding: 24px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: linear-gradient(135deg, white, #f3f8f8);
  box-shadow: var(--shadow);
}
.portal-banner img { height: 260px; object-fit: cover; border-radius: var(--radius-md); }
.metric-inline { display: flex; gap: 28px; margin: 22px 0; color: var(--muted); }
.metric-inline strong { display: block; color: var(--primary-950); font-size: 24px; }

.talent-cta {
  width: min(1580px, calc(100% - 96px));
  padding-top: 58px;
  padding-bottom: 58px;
}
.talent-cta-card {
  position: relative;
  display: grid;
  grid-template-columns: minmax(420px, .92fr) minmax(520px, 1.08fr);
  gap: clamp(46px, 5vw, 86px);
  align-items: center;
  overflow: hidden;
  min-height: 350px;
  padding: clamp(28px, 3vw, 46px);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background:
    linear-gradient(105deg, rgba(255,255,255,.98) 0%, rgba(255,255,255,.96) 44%, rgba(241,248,247,.92) 100%),
    radial-gradient(circle at 88% 16%, rgba(25,224,194,.14), transparent 34%);
  box-shadow: var(--shadow);
}
.talent-cta-card::after {
  content: "";
  position: absolute;
  right: -120px;
  bottom: -170px;
  width: 430px;
  height: 430px;
  border-radius: 50%;
  border: 1px solid rgba(0,180,255,.12);
  pointer-events: none;
}
.talent-cta-copy {
  position: relative;
  z-index: 1;
  max-width: 680px;
}
.talent-cta-copy h2 {
  font-size: clamp(42px, 4.1vw, 64px);
}
.talent-cta-lead {
  max-width: 620px;
  margin-top: 16px;
  color: var(--primary-950);
  font-size: clamp(18px, 1.45vw, 22px);
  font-weight: 850;
  line-height: 1.45;
}
.talent-cta-copy p:not(.talent-cta-lead) {
  max-width: 590px;
  margin-top: 18px;
  font-size: 17px;
  line-height: 1.55;
}
.talent-cta-button {
  margin-top: 34px;
  min-height: 48px;
  padding-inline: 20px;
  box-shadow: 0 12px 26px rgba(10,18,48,.12);
}
.talent-cta-device {
  position: relative;
  z-index: 1;
  display: block;
  /* El banner del Portal en la portada del sitio es un enlace: se eleva como
     cualquier otra pieza pulsable, y la transicion va aqui para que la vuelta
     no sea instantanea. */
  transition: transform .18s ease;
  justify-self: end;
  width: min(720px, 100%);
  overflow: visible;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
}
.device-bar {
  display: flex;
  gap: 6px;
  padding: 0 0 10px 4px;
}
.device-bar span {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: rgba(255,255,255,.42);
}
.talent-cta-device img {
  width: 100%;
  height: clamp(300px, 27vw, 430px);
  border-radius: 0;
  object-fit: contain;
  object-position: center;
  background: transparent;
  box-shadow: none;
}
.device-base {
  position: absolute;
  left: 13%;
  right: 13%;
  bottom: 7px;
  height: 6px;
  border-radius: var(--radius-pill);
  background: rgba(255,255,255,.28);
}
.talent-cta-device:hover {
  transform: translateY(var(--alza-tarjeta));
}

.training-page-hero {
  min-height: 560px;
}
.training-page-hero h1 {
  max-width: 980px;
  font-size: clamp(40px, 3vw, 54px);
  line-height: 1.04;
}
.training-page-hero .hero-copy {
  min-height: 560px;
  width: min(980px, 63vw);
  padding: 50px 28px 54px clamp(34px, 4.2vw, 72px);
}
.training-page-hero .hero-copy p {
  max-width: 540px;
  font-size: 16px;
  line-height: 1.56;
}
.training-page-hero .hero-copy .hero-lead {
  max-width: 560px;
  color: var(--primary-950);
  font-size: 19px;
  font-weight: 850;
  line-height: 1.38;
}
.training-hero-points {
  display: flex;
  flex-wrap: wrap;
  gap: 9px;
  margin-top: 18px;
}
.training-hero-points span {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 36px;
  padding: 7px 12px;
  border: 1px solid rgba(16,27,61,.1);
  border-radius: var(--radius-pill);
  background: rgba(255,255,255,.72);
  color: var(--primary-950);
  font-size: 12px;
  font-weight: 850;
  box-shadow: 0 8px 18px rgba(10,18,48,.045);
}
.training-hero-points i {
  color: var(--primary-900);
}
.training-page-hero .hero-image {
  position: absolute;
  inset: 0;
  z-index: 0;
  min-height: 100%;
  background:
    linear-gradient(90deg, #fff 0%, rgba(255,255,255,.98) 31%, rgba(255,255,255,.84) 51%, rgba(255,255,255,.30) 70%, rgba(255,255,255,.04) 100%),
    var(--hero);
  background-size: cover;
  background-position: center right;
}
.training-why {
  padding-top: 58px;
  padding-bottom: 28px;
}
.training-why .section-header {
  max-width: 860px;
}
.training-reason-grid {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 16px;
}
.training-reason-grid article {
  display: grid;
  align-content: start;
  gap: 12px;
  min-height: 272px;
  padding: 22px;
  border: 1px solid rgba(16,27,61,.1);
  border-radius: var(--radius-sm);
  background: rgba(255,255,255,.86);
  box-shadow: 0 12px 28px rgba(10,18,48,.045);
}
.training-reason-grid i,
.formation-type-grid i,
.strategic-media span {
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  border: 3px solid #00b4ff;
  border-radius: 50%;
  background: var(--primary-950);
  color: white;
  font-size: 22px;
  box-shadow: 0 8px 18px rgba(10,18,48,.1);
}
.training-reason-grid h3 {
  font-size: 17px;
  line-height: 1.18;
}
.training-reason-grid p {
  color: var(--dark-gray);
  font-size: 14px;
  line-height: 1.55;
}
.training-featured {
  width: min(1320px, calc(100% - 96px));
  padding-top: 46px;
  padding-bottom: 30px;
}
.formation-type-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 24px;
}
.formation-type-grid article {
  display: grid;
  grid-template-columns: .9fr 1fr;
  overflow: hidden;
  min-height: 245px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: linear-gradient(135deg, white, #f4f8f8);
  box-shadow: var(--shadow);
}
.formation-type-grid img {
  width: 100%;
  height: 100%;
  min-height: 245px;
  object-fit: cover;
}
.formation-type-grid article > div {
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 24px 26px;
}
.formation-type-grid i {
  margin-bottom: 16px;
}
.formation-type-grid article:nth-child(2) i {
  border-color: #19e0c2;
}
.formation-type-grid h2 {
  max-width: 340px;
  font-size: clamp(23px, 1.9vw, 30px);
}
.formation-type-grid p {
  margin: 13px 0 18px;
  max-width: 400px;
  font-size: 16px;
}
.formation-type-grid .btn {
  width: fit-content;
}
.training-services {
  width: min(1320px, calc(100% - 96px));
  padding-top: 26px;
  padding-bottom: 56px;
  text-align: center;
}
.training-services-heading {
  max-width: 720px;
  margin: 0 auto 24px;
  text-align: center;
}
.training-services-heading h2 {
  font-size: clamp(30px, 2.7vw, 44px);
  line-height: .98;
}
.training-services-heading::after {
  content: "";
  display: block;
  width: 42px;
  height: 2px;
  margin: 12px auto 0;
  background: var(--primary-900);
}
.training-services-heading p {
  margin-top: 8px;
}
.strategic-card-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 22px;
}
.strategic-card {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  min-height: 272px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: white;
  text-align: left;
  box-shadow: 0 8px 18px rgba(10,18,48,.035);
  transition: transform .18s ease, border-color .18s ease, box-shadow .18s ease;
}
.strategic-card:hover {
  transform: translateY(var(--alza-tarjeta));
  border-color: var(--borde-hover);
  box-shadow: var(--sombra-hover);
}
.strategic-media {
  display: grid;
  grid-template-columns: 76px minmax(0, 1fr);
  height: 96px;
  border-bottom: 1px solid var(--border);
  background: #eef3f6;
}
.strategic-media span {
  align-self: center;
  justify-self: center;
  background: var(--primary-900);
}
.strategic-card:nth-child(2n) .strategic-media span {
  border-color: #19e0c2;
  background: var(--primary-950);
}
.strategic-media img {
  display: block;
  width: 100%;
  height: 96px;
  object-fit: cover;
}
.strategic-body {
  flex: 1;
  padding: 20px 22px 24px;
}
.strategic-card h3 {
  font-family: Manrope, system-ui, sans-serif;
  font-weight: 800;
  font-size: 23px;
  line-height: 1.05;
  letter-spacing: 0;
}
.strategic-card p {
  margin-top: 12px;
  font-size: 14px;
  line-height: 1.55;
  color: var(--dark-gray);
}
.training-portal-banner {
  width: min(1320px, 100%);
  margin-inline: auto;
  grid-template-columns: .9fr 1.1fr;
  padding: 28px;
}
.training-portal-banner h2 {
  font-size: clamp(34px, 3vw, 48px);
}
.training-portal-banner img {
  height: 300px;
  object-position: center;
}
.training-commitment {
  width: min(1320px, calc(100% - 96px));
  padding-top: 10px;
  padding-bottom: 58px;
}
.training-commitment h2 {
  max-width: 720px;
  margin-top: 12px;
  font-size: clamp(32px, 3.2vw, 50px);
}
.training-commitment p {
  max-width: 900px;
  margin-top: 16px;
  color: var(--dark-gray);
  font-size: 18px;
  line-height: 1.65;
}
.training-meeting-cta {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 28px;
  align-items: center;
  width: min(1320px, calc(100% - 96px));
  margin-bottom: 20px;
  padding: 32px 34px;
  border: 1px solid rgba(16,27,61,.1);
  border-radius: var(--radius-lg);
  background:
    radial-gradient(circle at 92% 18%, rgba(25,224,194,.16), transparent 30%),
    linear-gradient(135deg, #fff, #f3f8fa);
  box-shadow: 0 18px 44px rgba(10,18,48,.06);
}
.training-meeting-cta h2 {
  max-width: 720px;
  margin-top: 10px;
  font-size: clamp(30px, 2.8vw, 46px);
}
.training-meeting-cta p {
  max-width: 820px;
  margin-top: 12px;
  color: var(--dark-gray);
  font-size: 16px;
  line-height: 1.62;
}
.training-meeting-cta .btn {
  white-space: nowrap;
}

.sector-grid, .service-icons {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  gap: 1px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--border);
}
.sector-grid a, .service-icons div {
  display: grid;
  place-items: center;
  gap: 10px;
  min-height: 86px;
  padding: 12px;
  background: white;
  color: var(--primary-950);
  font-size: 13px;
  font-weight: 800;
  text-align: center;
}
.sector-grid i, .service-icons i { color: var(--primary-900); font-size: 24px; }
.home-services {
  grid-template-columns: repeat(6, 1fr);
  border-left: 0;
  border-right: 0;
  border-radius: 0;
}
.mini-sector-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
}
.mini-sector-grid a {
  padding: 14px 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: white;
  color: var(--primary-950);
  font-weight: 850;
}

.card-row, .news-list { display: grid; gap: 14px; }
.feature-card {
  display: grid;
  grid-template-columns: 160px 1fr;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: white;
}
.feature-card img { height: 100%; object-fit: cover; }
.feature-card div, .article-card div, .training-card div { padding: 18px; }
.feature-card span, .article-card span, .training-card span, .job-card span { color: var(--primary-900); font-size: 12px; font-weight: 900; text-transform: uppercase; }
.feature-card p, .article-card p, .training-card p, .job-card p { margin: 10px 0 14px; }
.feature-card a, .article-card a, .news-list a { color: var(--primary-900); font-weight: 850; }
.news-list a { display: grid; padding: 16px 0; border-bottom: 1px solid var(--border); }
.news-list small { color: var(--muted); }

.home-editorial {
  display: grid;
  grid-template-columns: 1.15fr .85fr;
  gap: 46px;
  align-items: start;
}
/* ── Bloque editorial de la portada ───────────────────────────────────
   Proyectos destacados y Actualidad.

   Rehecho el 21/08/2026: era lo unico de la portada que no seguia el lenguaje
   del resto. Concretamente le faltaban las tres cosas que definen una tarjeta
   en este sitio — el antetitulo con el degradado de marca, el canto de color
   al pasar por encima y la flecha circular— y llevaba en su lugar un guion
   gris y un enlace de texto plano.

   Contraste sobre el fondo de la tarjeta (blanco):
     - titulo   #0A1230 .......... 18,4:1
     - etiqueta #101B3D .......... 15,8:1
     - texto    var(--muted) ......  5,9:1
   Los tres por encima de 4,5:1, el minimo para texto normal. */

.editorial-heading {
  margin-bottom: 26px;
}
.editorial-heading h2 {
  font-size: clamp(28px, 2.7vw, 42px);
}

.project-card-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 20px;
}

.project-card {
  position: relative;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: white;
  box-shadow: var(--soft-shadow);
  transition: transform .2s ease, box-shadow .2s ease, border-color .2s ease;
}

/* El canto de marca, el mismo remate que el bloque de cierre. Aparece al
   pasar por encima en vez de estar siempre: con tres tarjetas seguidas, tres
   degradados fijos compiten entre si y con el resto de la pagina. */
.project-card::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  z-index: 2;
  height: 3px;
  background: var(--brand-gradient);
  opacity: 0;
  transition: opacity .2s ease;
}

.project-card:hover {
  transform: translateY(var(--alza-tarjeta));
  border-color: var(--borde-hover);
  box-shadow: var(--sombra-hover);
}
.project-card:hover::before { opacity: 1; }

.project-card img {
  width: 100%;
  height: 200px;
  object-fit: cover;
  transition: transform .45s ease;
}
.project-card:hover img { transform: scale(1.04); }

.project-card > div {
  display: flex;
  flex: 1;
  flex-direction: column;
  padding: 22px;
}

.project-card span,
.news-media-list span {
  color: var(--primary-900);
  font-size: 11px;
  font-weight: 900;
  letter-spacing: .1em;
  text-transform: uppercase;
}

.project-card h3 {
  margin-top: 10px;
  font-size: 19px;
  line-height: 1.3;
}
.project-card p {
  margin: 12px 0 22px;
  color: var(--muted);
  font-size: 15px;
  line-height: 1.65;
}

/* `margin-top: auto` alinea los enlaces de las tres tarjetas aunque los
   textos tengan distinto largo. Sin eso, cada flecha quedaba a una altura. */
.project-card a,
.news-all-link {
  display: inline-flex;
  gap: 10px;
  align-items: center;
  align-self: flex-start;
  margin-top: auto;
  color: var(--primary-900);
  font-weight: 850;
  text-decoration: none;
}

/* La flecha, en circulo: es como el sitio remata sus enlaces de tarjeta. */
.project-card a i,
.news-all-link i {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border: 1.5px solid rgba(0, 180, 255, .5);
  border-radius: 50%;
  font-size: 13px;
  transition: background .18s ease, border-color .18s ease, color .18s ease, transform .18s ease;
}
.project-card a:hover i,
.project-card a:focus-visible i,
.news-all-link:hover i,
.news-all-link:focus-visible i {
  border-color: var(--primary-950);
  background: var(--primary-950);
  color: white;
  transform: translateX(2px);
}

.editorial-news {
  padding-left: 38px;
  border-left: 1px solid var(--border);
}

.news-media-list {
  display: grid;
  gap: 10px;
}

/* Cada noticia es una zona pulsable entera, no solo el titular: el margen
   negativo compensa el relleno para que la reticula no se mueva. */
.news-media-list a {
  display: grid;
  grid-template-columns: 118px 1fr;
  gap: 8px 18px;
  align-items: start;
  margin: 0 -12px;
  padding: 12px;
  border-radius: var(--radius-md);
  text-decoration: none;
  transition: background .18s ease;
}
.news-media-list a:hover,
.news-media-list a:focus-visible {
  background: rgba(0, 180, 255, .06);
}

/*
 * La miniatura y el texto son los dos unicos hijos de la reticula.
 *
 * Antes los cuatro elementos del texto eran hijos directos y la imagen tenia
 * que abarcarlos con `grid-row: span 4`. Eso obligaba a ajustar el numero cada
 * vez que se anadia una linea, y una noticia sin bajada dejaba la imagen mas
 * alta que su texto. `1 / -1` tampoco sirve: con filas implicitas resuelve a
 * una sola fila y el titular se cuela en la columna de la miniatura.
 *
 * Con el texto envuelto no hace falta ningun `span`: la reticula tiene dos
 * columnas y dos hijos, y da igual cuantas lineas lleve dentro.
 */
.news-media-list img {
  align-self: stretch;
  width: 118px;
  height: 100%;
  min-height: 92px;
  object-fit: cover;
  border-radius: var(--radius-sm);
}

.news-media-texto {
  display: grid;
  gap: 6px;
  align-content: start;
}

/*
 * Noticia sin imagen: una sola columna.
 *
 * Sin esto el texto se metia en la columna reservada a la miniatura —118 px— y
 * salia comprimido contra el borde. Pasa en cuanto alguien publica una noticia
 * sin foto desde el CRM, que es algo perfectamente normal.
 */
.news-media-list a.sin-imagen {
  grid-template-columns: 1fr;
}

.news-media-list strong {
  color: var(--primary-950);
  font-size: 16px;
  line-height: 1.3;
}
.news-media-list a:hover strong { color: var(--electric-blue); }

/* La bajada, recortada: da contexto sin competir con el titular, igual que
   en las tarjetas de proyecto. */
.news-media-list p {
  margin: 0;
  color: var(--muted);
  font-size: 14px;
  line-height: 1.5;
}

.news-media-list small {
  color: var(--muted);
  font-weight: 750;
}

.news-all-link {
  margin-top: 24px;
}

/* Por debajo de 1180 la columna de Actualidad pasa debajo, y el borde
   izquierdo que la separaba deja de tener sentido. */
@media (max-width: 1180px) {
  .project-card-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .editorial-news {
    padding-left: 0;
    padding-top: 34px;
    border-left: 0;
    border-top: 1px solid var(--border);
  }
}
@media (max-width: 720px) {
  .project-card-grid { grid-template-columns: 1fr; }
}

.editorial-hero {
  display: grid;
  grid-template-columns: minmax(520px, 1fr) minmax(320px, 480px);
  gap: 42px;
  align-items: end;
  width: min(1580px, calc(100% - 96px));
  margin: 0 auto;
  padding: 72px 0 44px;
}
.editorial-hero h1 {
  max-width: 850px;
  font-size: clamp(48px, 4.7vw, 76px);
}
.editorial-hero p {
  max-width: 720px;
  margin-top: 18px;
  font-size: 17px;
}

/* Los heros que no llevan cuadro lateral —Actualidad y Preguntas frecuentes—
   reparten titular y entrada en dos columnas, alineadas por abajo.

   En una sola columna el titular se comia cuatro lineas y quedaba media
   pantalla vacia a la derecha. Asi la pieza se lee en horizontal y ocupa el
   ancho que ocupa el resto de la pagina. */
.editorial-hero.ancho {
  /* Centradas entre si, y contra el TITULAR.
   *
   * Heredaba `align-items: end` y el parrafo quedaba colgando abajo; por
   * arriba tampoco cuadraba, porque el titular ocupa dos lineas y la entrada
   * tres. Centradas comparten eje.
   *
   * El antetitulo va en su propia fila —`grid-column: 1 / -1` mas abajo— para
   * que ese centrado sea contra el `h1` y no contra antetitulo + titular:
   * agrupados, el eje comun subia y la entrada quedaba alta. */
  align-items: center;
  grid-template-columns: minmax(0, 1.25fr) minmax(0, .75fr);
  gap: 56px;
}
.editorial-hero.ancho > .eyebrow {
  grid-column: 1 / -1;
  margin-bottom: 0;
}
.editorial-hero.ancho h1 {
  max-width: none;
  font-size: clamp(40px, 4vw, 62px);
}

/* El filete de marca delante de la entrada la ata al titular en vez de
   dejarla suelta en el aire. `border-image` porque un borde solido no admite
   degradado. */
.editorial-hero.ancho > p {
  max-width: 480px;
  margin-top: 0;
  padding: 0 0 0 22px;
  border-left: 3px solid transparent;
  border-image: linear-gradient(180deg, var(--turquoise), var(--cyan) 55%, var(--electric-blue)) 1;
}

/* Por debajo de 1180 vuelven a apilarse: dos columnas de texto en una
   tableta dejan cinco palabras por linea. */
@media (max-width: 1180px) {
  .editorial-hero.ancho {
    grid-template-columns: 1fr;
    gap: 20px;
  }
  .editorial-hero.ancho > p { margin-top: 0; }
}
.editorial-hero-panel {
  padding: 24px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background:
    linear-gradient(135deg, rgba(255,255,255,.96), rgba(241,248,247,.86)),
    radial-gradient(circle at 90% 12%, rgba(25,224,194,.12), transparent 32%);
  box-shadow: var(--shadow);
}
.editorial-hero-panel span {
  color: var(--primary-900);
  font-size: 11px;
  font-weight: 900;
  letter-spacing: .12em;
  text-transform: uppercase;
}
.editorial-hero-panel strong {
  display: block;
  margin-top: 10px;
  color: var(--primary-950);
  font-size: 20px;
  line-height: 1.25;
}
.editorial-hero-panel p {
  margin-top: 10px;
  font-size: 14px;
}
.editorial-page-section {
  padding-top: 28px;
}
.editorial-section-heading {
  display: flex;
  justify-content: space-between;
  gap: 24px;
  align-items: end;
  margin-bottom: 24px;
}
.editorial-section-heading p {
  max-width: 720px;
  margin-top: 10px;
}
.editorial-card-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 22px;
}

/* Página de categoría de Actualidad (§3.7 del alcance).
   La etiqueta de categoría pasó a ser un enlace a su página: se subraya al
   pasar por encima y nada más, porque va dentro de la tarjeta y no puede
   competir con el titular, que es lo que hay que pulsar. */
.categoria-etiqueta {
  color: inherit;
  text-decoration: none;
}
.categoria-etiqueta:hover,
.categoria-etiqueta:focus-visible {
  text-decoration: underline;
}

/* Las demás categorías, al pie de la página. Son enlaces sueltos y sin
   separación se leían como una sola frase: «Extranjería Empleo Movilidad». */
.categoria-lista {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 12px;
}
.categoria-lista > * {
  padding: 6px 14px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  font-size: 0.92rem;
}

.categoria-volver {
  margin-top: 28px;
}
.categoria-volver a {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.editorial-card {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  min-height: 420px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: white;
  box-shadow: var(--shadow);
  transition: transform .18s ease, border-color .18s ease, box-shadow .18s ease;
}
.editorial-card:hover {
  transform: translateY(var(--alza-tarjeta));
  border-color: var(--borde-hover);
  box-shadow: var(--sombra-hover);
}
.editorial-card img {
  width: 100%;
  height: 210px;
  object-fit: cover;
}
.editorial-card > div {
  display: flex;
  flex: 1;
  flex-direction: column;
  padding: 22px;
}
.editorial-card span {
  color: var(--primary-900);
  font-size: 11px;
  font-weight: 900;
  letter-spacing: .1em;
  text-transform: uppercase;
}
.editorial-card h3 {
  margin-top: 10px;
  font-size: 22px;
}
.editorial-card p {
  margin-top: 12px;
}
.editorial-card footer {
  display: flex;
  justify-content: space-between;
  gap: 14px;
  align-items: center;
  margin-top: auto;
  padding-top: 18px;
}
.editorial-card small {
  color: var(--muted);
  font-size: 12px;
  font-weight: 750;
}
.editorial-card a {
  display: inline-flex;
  gap: 8px;
  align-items: center;
  color: var(--primary-900);
  font-weight: 850;
}
.projects-page-section {
  padding-top: 34px;
  padding-bottom: 68px;
}
.project-editorial-card {
  background: linear-gradient(180deg, white, #f8fbfb);
}

.category-cards, .role-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 18px;
  margin-bottom: 24px;
}
.category-cards article, .role-grid article {
  display: grid;
  grid-template-columns: .9fr 1fr;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: white;
  box-shadow: var(--shadow);
}
.category-cards img { height: 100%; object-fit: cover; }
.category-cards div, .role-grid article { padding: 20px; }
.category-cards i { color: var(--primary-900); font-size: 30px; }
.home-categories article {
  grid-template-columns: .72fr 1fr;
  min-height: 300px;
}
.home-categories div {
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.home-categories .btn {
  width: fit-content;
  margin-top: 14px;
}

/* ── Buscador de formaciones ────────────────────────────────────────────
   Rehecho el 22/08/2026.

   Contraste sobre el Azul Profundo de la barra:
     etiquetas  blanco ................. 18,4:1
     boton      --primary-950 sobre blanco 18,4:1
     limpiar    blanco ................. 18,4:1
     foco       teal a plena opacidad ... 10,9:1
   El anillo de foco general del sitio es teal al 36 %, que sobre este fondo
   se queda en 2,4:1 —por debajo del 3:1 que pide un indicador de foco—, asi
   que aqui va a plena opacidad. */

.filters, .search-band form {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 220px 220px auto auto;
  gap: 14px;
  align-items: end;
  margin-bottom: 24px;
  padding: 18px;
  border-radius: var(--radius-md);
  box-shadow: 0 14px 30px rgba(10, 18, 48, .16);

  /* El degradado del manual, en el canto superior: la barra era un bloque
     plano y es lo primero que se ve del catalogo.

     **Va como fondo de la propia barra y no como pseudoelemento.** Antes era
     una banda de 3 px flotando encima, con su propio redondeo: y un redondeo
     de 14 px en una caja de 3 de alto el navegador lo recorta a 3, asi que la
     franja seguia recta justo donde la barra empezaba a curvarse. El teal
     sobresalia por la izquierda y quedaba una cuna de fondo entre los dos.
     Visto a ocho aumentos, no leyendo la hoja de estilos.

     Como fondo lo recorta el `border-radius` de la barra, asi que la franja
     sigue la curva sola. Y no hace falta `overflow: hidden`, que aqui no se
     puede poner: el desplegable propio se abre por debajo del campo y tiene
     que poder salirse de la barra. */
  background-color: var(--primary-950);
  background-image: var(--brand-gradient);
  background-repeat: no-repeat;
  background-size: 100% 3px;
  background-position: 0 0;
}

.filters label {
  display: block;
  color: white;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .06em;
  text-transform: uppercase;
}

/* El campo con su icono dentro. El icono es decoracion —la etiqueta de
   encima ya dice que es cada cosa—, por eso lleva `aria-hidden`. */
.filters-campo {
  position: relative;
  display: block;
  margin-top: 8px;
}
.filters-campo i {
  position: absolute;
  left: 15px;
  top: 50%;
  z-index: 1;
  color: var(--primary-900);
  font-size: 15px;
  transform: translateY(-50%);
  pointer-events: none;
}
.filters-campo input,
.filters-campo select {
  margin-top: 0;
  padding-left: 42px;
}

input, select, textarea {
  width: 100%;
  /* 48 px es el objetivo tactil minimo. */
  min-height: 48px;
  margin-top: 6px;
  padding: 11px 13px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: white;
  color: var(--text);
}

/* La flecha del desplegable la pinta el sistema operativo y no se parece a
   nada del sitio: en Windows sale un triangulo gris de Chrome. Se sustituye
   por una propia. La lista desplegada sigue siendo del sistema —eso no se
   puede estilar— y esta bien que asi sea: es el control que la persona ya
   sabe usar. */
select {
  appearance: none;
  padding-right: 40px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%230a1230' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 6.5l4 4 4-4'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  background-size: 15px;
  cursor: pointer;
}

.filters :focus-visible,
.search-band form :focus-visible {
  outline: 3px solid var(--turquoise);
  outline-offset: 2px;
}

/* El boton de aplicar: blanco sobre la barra oscura. Es la unica forma de
   que el primario se distinga aqui, porque el primario del sitio comparte
   color con el fondo de esta barra. */
.btn-claro {
  background: white;
  color: var(--primary-950);
  box-shadow: 0 8px 18px rgba(0, 0, 0, .18);
  transition: background .18s ease, transform .18s ease;
}
.btn-claro:hover,
.btn-claro:focus-visible {
  background: var(--soft);
  transform: translateY(var(--alza-control));
}
.btn-claro i { font-size: 15px; }

.filters .btn {
  min-height: 48px;
  padding-inline: 20px;
}

@media (prefers-reduced-motion: reduce) {
  .btn-claro { transition: none; }
  .btn-claro:hover, .btn-claro:focus-visible { transform: none; }
}

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

/* Texto solo para lector de pantalla. Se aparta de la vista sin salir del
   arbol de accesibilidad: `display: none` lo borraria tambien de ahi. */
.solo-lector {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ── Desplegable propio ─────────────────────────────────────────────────
   La lista de un <select> la dibuja el sistema operativo y no admite CSS.
   Esta la monta `app.js` encima del campo nativo, que sigue en el documento
   y es el que se envia: si el script no arranca, se ve el de siempre.

   Contraste sobre el panel blanco:
     opcion            --text ................. 14,8:1
     opcion elegida    --primary-950 .......... 18,4:1
     opcion enfocada   blanco sobre navy ...... 18,4:1
   El foco de una opcion no puede ser el anillo teal general del sitio: al
   36 % sobre blanco se queda en 1,2:1 y no se ve. Se marca invirtiendo la
   fila entera. */

.desplegable {
  position: relative;
  display: block;
}

/* El nativo no se puede ocultar con `display: none`: hay navegadores que no
   envian un campo oculto de esa forma dentro de algunos flujos. Se aparta. */
.desplegable-nativo {
  position: absolute;
  width: 1px;
  height: 1px;
  min-height: 0;
  margin: 0;
  padding: 0;
  border: 0;
  opacity: 0;
  pointer-events: none;
}

.desplegable-boton {
  display: flex;
  gap: 10px;
  align-items: center;
  width: 100%;
  min-height: 48px;
  padding: 11px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: white;
  color: var(--text);
  font-weight: 500;
  text-align: left;
  cursor: pointer;
}
.desplegable-boton .desplegable-valor {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.desplegable-boton i {
  color: var(--primary-950);
  font-size: 13px;
  transition: transform .18s ease;
}
.desplegable-boton[aria-expanded="true"] {
  border-color: var(--electric-blue);
}
.desplegable-boton[aria-expanded="true"] i {
  transform: rotate(180deg);
}

/* Con un valor elegido, el rotulo se pone en negrita y en Azul Profundo: a
   simple vista hay que poder saber si un filtro esta puesto. */
.desplegable.con-valor .desplegable-valor {
  color: var(--primary-950);
  font-weight: 800;
}

.desplegable-lista {
  position: absolute;
  z-index: 30;
  /* La lista cuelga dentro de la <label> del buscador, que va en mayusculas,
     en negrita y con espaciado entre letras. Sin este corte, las opciones
     salian gritando: «HOSTELERIA», «TECNOLOGIA». El <button> no lo heredaba
     porque `font: inherit` no arrastra `text-transform`, asi que el campo
     cerrado se veia bien y la lista no: solo se notaba al abrirla. */
  font-weight: 500;
  letter-spacing: normal;
  text-transform: none;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  max-height: 280px;
  overflow-y: auto;
  margin: 0;
  padding: 6px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: white;
  box-shadow: 0 18px 36px rgba(10, 18, 48, .18);
  list-style: none;
}

.desplegable-opcion {
  display: flex;
  gap: 10px;
  align-items: center;
  /* 44 px: la lista tambien se usa con el dedo. */
  min-height: 44px;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  color: var(--text);
  font-size: 15px;
  font-weight: 500;
  cursor: pointer;
}
.desplegable-opcion:hover {
  background: rgba(0, 180, 255, .08);
}

/* La elegida, con su marca. No solo en negrita: quien no distingue bien los
   pesos tipograficos necesita algo mas que el grosor. */
.desplegable-opcion[aria-selected="true"] {
  color: var(--primary-950);
  font-weight: 800;
}
.desplegable-opcion[aria-selected="true"]::after {
  content: "\F26E";
  margin-left: auto;
  color: var(--electric-blue);
  font-family: "bootstrap-icons";
  font-size: 15px;
}

/* La fila enfocada se invierte entera. Es la unica marca que se ve sin
   depender del color, y no se confunde con la elegida. */
.desplegable-opcion:focus {
  outline: none;
  background: var(--primary-950);
  color: white;
}
.desplegable-opcion:focus::after {
  color: var(--turquoise);
}

/* Dentro del buscador, el boton deja sitio al icono del campo, igual que
   hacia el <select> al que sustituye. */
.filters-campo .desplegable-boton {
  padding-left: 42px;
}

@media (prefers-reduced-motion: reduce) {
  .desplegable-boton i { transition: none; }
}
.training-grid { grid-template-columns: repeat(3, 1fr); }
.training-card, .article-card { overflow: hidden; }
.training-card img, .article-card img { width: 100%; height: 176px; object-fit: cover; }
.training-card dl, .facts {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px;
}
.training-card dt, .facts span { color: var(--muted); font-size: 12px; }
.training-card dd { margin: 0; font-weight: 800; }
/* ── Tarjeta de destino ─────────────────────────────────────────────────
   Cada destino con su fotografía, sus motivos y sus formaciones.

   Rehecha el 22/08/2026. Tenía tres problemas: el enlace «Conocer Madrid»
   era texto plano pegado al último motivo y no se leía como acción; las
   formaciones eran filas separadas por una línea, sin ninguna señal de que
   fueran pulsables; y la flecha flotaba suelta arriba a la derecha.

   Usa el mismo vocabulario que el resto del sitio: el degradado del manual
   como canto, la ficha pulsable con su cambio de borde, y la flecha dentro
   de un círculo que se rellena al pasar por encima.

   Contraste (WCAG AA pide 4,5:1 en texto normal y 3:1 en componentes):
     titular   --primary-950 sobre blanco ....... 18,4:1
     motivos   --text sobre blanco .............. 14,8:1
     bajada    --muted sobre blanco .............  5,9:1
     categoría --primary-900 sobre blanco ....... 16,9:1
     check     --electric-blue sobre blanco .....  4,9:1
     botón     blanco sobre --primary-950 ....... 18,4:1
   El cian de marca queda en 1,6:1 y por eso no se usa para nada que haya que
   distinguir: sólo aparece dentro del degradado, que es decoración. */

/* Dos destinos con los mismos cursos miden lo mismo.

   Maude lo pidió el 28/08/2026: Jerez medía 433 px y Málaga 478 teniendo un
   curso cada uno, y la diferencia se veía sobre todo en la fotografía, que
   ocupa su columna de arriba abajo.

   **Se probó igualarlas a todas con `grid-auto-rows: 1fr` y se descartó**: el
   alto de la más alta —la del destino con seis cursos— se lo llevaban también
   las otras dos, y la tarjeta de un solo curso quedaba con 230 px de blanco
   debajo de su única ficha. Peor que la diferencia que venía a arreglar. Y
   apilada era ruinoso: en un móvil de 390 px la de Jerez pasaba a medir
   1.339 px, con setecientos de hueco.

   Lo que se iguala es lo que se puede igualar **en su origen**, y son dos
   cosas, las dos más abajo en este archivo: la bajada del destino, acotada a
   dos líneas, y el título de cada ficha de formación, que reserva siempre dos
   aunque quepa en una. Con eso Jerez y Málaga miden exactamente igual a
   cualquier ancho, y Móstoles mide más porque tiene seis cursos. */
.destination-list {
  display: grid;
  gap: 28px;
}

/*
 * Fotografía a un lado, ocupando su columna de arriba abajo; al otro, el
 * destino y su catálogo.
 *
 * Las formaciones estuvieron en una tercera columna —y con seis estiraban la
 * tarjeta a dos mil píxeles— y después en una fila propia debajo, que dejó la
 * fotografía convertida en una banda. Aquí caben las dos cosas.
 */
.destination-card {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, .42fr) minmax(0, 1fr);
  min-width: 0;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: white;
  box-shadow: var(--soft-shadow);
}

/* Un elemento de rejilla no baja de su ancho mínimo de contenido salvo que se
   le indique: sin esto, al apilarse en el móvil el texto se salía del recuadro
   y `overflow: hidden` lo cortaba a media palabra. */
.destination-card > *,
.destination-body > * {
  min-width: 0;
}

/* El degradado del manual, en el canto superior. Aquí es fijo y no al pasar
   por encima como en la portada: son dos tarjetas grandes y separadas, no
   tres seguidas compitiendo entre sí. */
.destination-card::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  z-index: 3;
  height: 3px;
  background: var(--brand-gradient);
}

.destination-media {
  position: relative;
  min-height: 340px;
}

/* La fotografía, **fuera del flujo**.

   Estaba en flujo con `height: 100%`, y ese 100 % se mide contra una altura
   que la propia fotografía está ayudando a decidir: la columna es un elemento
   de rejilla que se estira a lo que mida la fila, y la fila la marca su
   contenido. Cuando la resolución es circular cada motor la rompe por donde
   quiere. En este Chrome medía lo que el texto de al lado; en el de Maude, la
   de Málaga —1280 × 1920, vertical— estiraba su tarjeta por encima incluso de
   la de Móstoles, que tiene seis cursos y ella uno.

   Colocada en absoluto no participa en el cálculo: la tarjeta la mide su
   texto, la columna se estira hasta ahí, y la fotografía la rellena recortada.
   Con eso dos destinos con los mismos cursos miden igual en cualquier
   navegador, y da lo mismo si la foto es apaisada o vertical. */
.destination-media img,
.destination-media-vacia {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Velo inferior: la píldora se apoya sobre una fotografía que carga el
   cliente y que no controlamos. Sin el velo, su legibilidad depende de que
   la imagen sea oscura justo ahí. */
.destination-media::after {
  content: "";
  position: absolute;
  inset: auto 0 0;
  height: 45%;
  background: linear-gradient(to top, rgba(10, 18, 48, .58), transparent);
}

/* El hueco de la fotografía cuando el destino todavía no tiene ninguna.
   Un tinte de marca muy bajo y el icono centrado: se lee como «aún sin foto»
   en vez de como un recuadro roto. */
.destination-media-vacia {
  display: grid;
  place-items: center;
  background: linear-gradient(160deg, rgba(25, 224, 194, .14), rgba(41, 98, 255, .12));
  color: rgba(10, 18, 48, .28);
  font-size: 46px;
}

.destination-count {
  position: absolute;
  z-index: 2;
  left: 18px;
  bottom: 18px;
  display: inline-flex;
  gap: 8px;
  align-items: center;
  padding: 9px 15px;
  border-radius: var(--radius-pill);
  background: rgba(10, 18, 48, .92);
  color: white;
  font-size: 12px;
  font-weight: 850;
}
.destination-count i { font-size: 14px; }

/* La columna del destino: su texto arriba y el catálogo debajo. */
.destination-body {
  display: grid;
  align-content: start;
  min-width: 0;
}

/* Apretado el 28/08/2026: Maude las veía demasiado largas. Se recortó el
   relleno de las tres capas —encabezado, catálogo y cada ficha— antes que
   quitar contenido, que es a lo que la tarjeta viene. */
.destination-content {
  padding: clamp(22px, 1.8vw, 28px) clamp(26px, 2.6vw, 40px) 0;
}
.destination-content .eyebrow {
  margin-bottom: 10px;
}
.destination-content h3 {
  margin: 0;
  color: var(--primary-950);
  font-size: clamp(24px, 2.1vw, 32px);
  line-height: 1.15;
}
/* La bajada, a dos líneas. Sale del CRM y no tiene tope: la de Málaga ocupaba
   tres y su tarjeta salía 24 px más alta que la de Jerez, que fue lo primero
   que se notó al ponerlas todas del mismo alto. */
.destination-content > p {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  max-width: 62ch;
  margin: 10px 0 0;
  color: var(--muted);
  font-size: 15.5px;
  line-height: 1.6;
}

/* El botón del destino.

   Sólido y en el Azul Profundo del manual desde el 26/08/2026, a pedido de
   Maude: «que resalte». Estuvo contorneado mientras convivía en la misma
   columna con las fichas de formación —así no competía con ellas—, pero desde
   que el catálogo bajó a su propio bloque este botón es lo único que se pulsa
   en el encabezado y tiene que leerse como la acción que es.

   El disco de la flecha va en teal, que es lo que lo distingue del botón de
   agendar —también navy— sin salirse de la paleta. La flecha, en navy sobre
   el teal: 11,4:1. Blanca sobre teal daría 1,6:1 y no se vería. */
.destination-cta {
  padding-top: 16px;
}

.btn-destino {
  gap: 12px;
  /* El rótulo lleva el nombre del destino, que sale del CRM: «Conocer Jerez
     de la Frontera, Cádiz» ya ocupa 316 px de los 348 que quedan en un móvil
     de 390. Uno más largo tiene que partirse dentro de la píldora, no
     salirse de la tarjeta. */
  max-width: 100%;
  /* 48px es el objetivo táctil mínimo; el `.btn` general se queda en 42 y
     esta tarjeta se usa mucho desde el móvil. */
  min-height: 48px;
  padding: 8px 8px 8px 22px;
  border-color: transparent;
  border-radius: var(--radius-pill);
  background: var(--primary-950);
  color: white;
  font-weight: 800;
  box-shadow: 0 10px 24px rgba(10, 18, 48, .18);
  transition: transform .18s ease, box-shadow .18s ease, background-color .18s ease;
}

.btn-destino i {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--turquoise);
  color: var(--primary-950);
  font-size: 14px;
  transition: background .18s ease, transform .18s ease;
}
.btn-destino:hover,
.btn-destino:focus-visible {
  transform: translateY(var(--alza-control));
  box-shadow: 0 16px 32px rgba(10, 18, 48, .26);
}
.btn-destino:hover i,
.btn-destino:focus-visible i {
  background: var(--cyan);
  transform: translateX(3px);
}

/* Quien haya pedido menos movimiento no ve el desplazamiento: el cambio de
   sombra y del disco ya distingue el botón apuntado. */
@media (prefers-reduced-motion: reduce) {
  .btn-destino,
  .btn-destino i { transition-duration: .01ms; }

  .btn-destino:hover,
  .btn-destino:focus-visible { transform: none; }

  .btn-destino:hover i,
  .btn-destino:focus-visible i { transform: none; }
}

/* El catálogo, sobre fondo suave: separa las formaciones del discurso del
   destino sin necesitar otra línea divisoria. */
.destination-catalogo {
  margin-top: clamp(16px, 1.6vw, 22px);
  padding: clamp(14px, 1.4vw, 18px) clamp(26px, 2.6vw, 40px);
  border-top: 1px solid var(--border);
  background: var(--soft);
}

.destination-trainings,
.destino-ofertas {
  display: grid;
  /* `auto-fill` y no `auto-fit`: con una sola formación —Jerez— `auto-fit`
     colapsa las columnas vacías y esa ficha se estira a todo el ancho, con el
     resumen en una línea interminable. Con `auto-fill` mide lo mismo tenga
     compañía o no. */
  /* El mínimo es ancho a propósito: en esta columna entran dos por fila, así
     que las cuatro que se enseñan forman un bloque de 2×2. A 280 entraban
     tres y la cuarta caía sola en una segunda fila, con el hueco al lado.
   
     `min(340px, 100%)` y no `340px` a secas: un mínimo fijo es también el
     ancho mínimo de la rejilla, así que en un móvil de 360 la tarjeta medía
     432 px y `overflow: hidden` cortaba el texto por la derecha sin que la
     página llegara a desplazarse. Medido: `.destination-content` acababa en
     el píxel 449 con la ventana en 360. Con `min()` el mínimo cede cuando no
     cabe. */
  grid-template-columns: repeat(auto-fill, minmax(min(340px, 100%), 1fr));
  align-items: stretch;
  gap: 12px;
}

.destination-training-item,
.destino-oferta-item {
  position: relative;
  display: grid;
  align-content: start;
  min-width: 0;
  gap: 6px;
  overflow: hidden;
  /* El hueco de la derecha lo reserva el relleno: la flecha va colocada
     encima. Estaba como segunda columna de la rejilla con `grid-row: 1 / -1`
     y ese `-1` apunta al final de la rejilla **explicita**, que aqui no
     existe —las filas son implicitas—, asi que se quedaba en la primera y la
     flecha aparecia arriba en vez de centrada. */
  padding: 14px 56px 14px 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: white;
  transition: transform .18s ease, border-color .18s ease, box-shadow .18s ease;
}

/* El canto de marca, vertical. El token `--brand-gradient` va a 90 grados y
   sobre tres píxeles de ancho sólo se vería uno de los tres colores. */
.destination-training-item::before,
.destino-oferta-item::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 3px;
  background: linear-gradient(180deg, var(--turquoise), var(--cyan), var(--electric-blue));
  opacity: 0;
  transition: opacity .18s ease;
}
.destination-training-item:hover,
.destination-training-item:focus-visible,
.destino-oferta-item:hover,
.destino-oferta-item:focus-visible {
  transform: translateY(var(--alza-tarjeta));
  border-color: var(--borde-hover);
  box-shadow: var(--sombra-hover);
}
.destination-training-item:hover::before,
.destination-training-item:focus-visible::before,
.destino-oferta-item:hover::before,
.destino-oferta-item:focus-visible::before {
  opacity: 1;
}

.destination-training-item span,
.destino-oferta-item > span {
  color: var(--primary-900);
  font-size: 11px;
  font-weight: 900;
  letter-spacing: .08em;
  text-transform: uppercase;
}
/* El título, a dos líneas como mucho. Los del CRM llegan a «Grado Superior en
   Desarrollo de Aplicaciones Web y Multiplataforma»: a tres líneas cada ficha
   crece veinte píxeles y las cuatro de la tarjeta, ochenta. */
.destination-training-item strong,
.destino-oferta-item strong {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  /* Y **siempre** dos, aunque el título quepa en una: así todas las fichas
     miden lo mismo y dos destinos con un curso cada uno salen con la misma
     tarjeta. Era la diferencia entre Jerez —«Dirección de Cocina», una
     línea— y Málaga —«Desarrollo de Aplicaciones Multiplataforma», dos—. En
     `em` y no en píxeles, para que siga cuadrando si cambia el cuerpo. */
  min-height: 2.6em;
  color: var(--primary-950);
  font-size: 15.5px;
  line-height: 1.3;
}

/* El resumen, recortado a una línea con puntos suspensivos.

   Los escribe el cliente y van de una línea a cinco. En la tarjeta del destino
   el resumen sólo tiene que dar una pista de qué es; quien quiera leerlo entra
   en la ficha. Con tres líneas cada tarjeta ocupaba casi el doble y el bloque
   de cuatro se comía la pantalla.

   El recorte lo pone el navegador, así que no hay que contar caracteres ni
   cortar a media palabra: el punto de corte se calcula sobre el texto ya
   compuesto, con su tipografía y su ancho reales. */
.destination-training-item small,
.destino-oferta-item small {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 1;
  line-clamp: 1;
  overflow: hidden;
  color: var(--muted);
  font-size: 13px;
  line-height: 1.45;
}

/* La flecha, dentro de un círculo. Suelta arriba a la derecha no decía que
   la ficha entera fuera pulsable; centrada y con fondo, sí. El círculo es
   decoración —quien lo lee es el glifo, que va en --primary-900 sobre un
   tinte del 6 %—, así que no depende del contraste del propio círculo. */
.destination-training-item i,
.destino-oferta-item > i {
  position: absolute;
  right: 16px;
  top: 50%;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--muted-surface);
  color: var(--primary-900);
  font-size: 14px;
  transform: translateY(-50%);
  transition: background .18s ease, color .18s ease, transform .18s ease;
}
.destination-training-item:hover i,
.destination-training-item:focus-visible i,
.destino-oferta-item:hover > i,
.destino-oferta-item:focus-visible > i {
  background: var(--primary-950);
  color: white;
  transform: translateY(var(--alza-tarjeta)) translateX(2px);
}

/*
 * El desplegable con las formaciones que no caben.
 *
 * Se enseñan cuatro y el resto se pide. Sin esto Móstoles abría con seis
 * fichas y empujaba el destino siguiente fuera de la pantalla; con cuatro, los
 * dos destinos entran de un vistazo y quien quiere la lista entera la abre.
 */
.destination-mas {
  margin-top: 14px;
}

.destination-mas summary {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 48px;
  padding: 0 20px;
  border: 1px dashed var(--border);
  border-radius: var(--radius-md);
  color: var(--primary-900);
  font-size: 14px;
  font-weight: 800;
  list-style: none;
  cursor: pointer;
  transition: border-color .18s ease, background-color .18s ease, color .18s ease;
}

/* Safari pinta su propio triángulo con un pseudoelemento propio. */
.destination-mas summary::-webkit-details-marker { display: none; }

.destination-mas summary:hover,
.destination-mas summary:focus-visible {
  border-style: solid;
  border-color: rgba(41, 98, 255, .42);
  background: white;
  color: var(--primary-950);
}

.destination-mas summary i {
  font-size: 13px;
  transition: transform .2s ease;
}

.destination-mas[open] summary {
  margin-bottom: 14px;
}

.destination-mas[open] summary i {
  transform: rotate(180deg);
}

@media (prefers-reduced-motion: reduce) {
  .destination-mas summary i { transition: none; }
}

/* Quien haya pedido menos movimiento no ve ninguno: los desplazamientos son
   decoración y el cambio de borde ya distingue el elemento apuntado. */
@media (prefers-reduced-motion: reduce) {
  .destination-training-item,
  .destination-training-item i,
  .btn-destino,
  .btn-destino i {
    transition: none;
  }
  .destination-training-item:hover,
  .destination-training-item:focus-visible {
    transform: none;
  }
  .destination-training-item:hover i,
  .destination-training-item:focus-visible i {
    transform: translateY(-50%);
  }
  .btn-destino:hover i,
  .btn-destino:focus-visible i {
    transform: none;
  }
}

/* ── Ficha de destino ───────────────────────────────────────────────────
   `/formaciones/destino/{slug}`.

   Rehecha el 22/08/2026: era la unica vista de Formaciones que se habia
   quedado con el aspecto generico. Los motivos salian con los puntos grises
   del navegador, el recuento era un `<small>` suelto, y los dos bloques de
   texto iban en tarjetas blancas iguales dentro de una reticula compartida
   que dejaba media pagina vacia.

   Reutiliza lo que ya existe —`.destination-benefits` para los motivos y
   `.destination-training-item` para las fichas— para que el destino se vea
   igual desde el listado y desde su propia pagina.

   Contraste sobre blanco:
     titulares  --primary-950 ....... 18,4:1
     texto      --text ............... 14,8:1
     entrada    --muted ..............  5,9:1
     datos      --primary-900 ....... 16,9:1
     check      --electric-blue ......  4,9:1 */

/* La panoramica manda mas que en otras fichas: es lo que vende el destino. */
.destino-hero img {
  height: 380px;
}

/* Los datos del destino: cuantas formaciones hay y de que tipo. */
.destino-datos {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin: 24px 0 0;
  padding: 0;
  list-style: none;
}
.destino-datos li {
  display: inline-flex;
  gap: 9px;
  align-items: center;
  padding: 9px 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: white;
  color: var(--primary-900);
  font-size: 13px;
  font-weight: 800;
}
.destino-datos li i {
  color: var(--electric-blue);
  font-size: 15px;
}

.destino-columnas {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, .9fr);
  gap: 48px;
  align-items: start;
}

/* Los apoyos a la izquierda y el texto a la derecha, cuando hay vídeo.

   Se coloca con `order` y no reordenando el HTML **a propósito**: apilado, el
   orden que queda es el del documento, o sea el titular de la sección y su
   texto antes que el vídeo. Al revés, en un móvil aparecería un vídeo suelto
   sin nada encima que dijera de qué sección es.

   Por eso vive dentro de la consulta de dos columnas: donde no hay dos
   columnas, no hay nada que intercambiar. */
@media (min-width: 1181px) {
  .destino-columnas[data-medios="izquierda"] {
    grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr);
  }
  .destino-columnas[data-medios="izquierda"] > .destino-lateral { order: -1; }
}

.destino-texto h2,
.destino-motivos h2,
.destino-calidad h2 {
  margin: 0 0 16px;
  font-size: clamp(24px, 2.2vw, 34px);
}

/* El texto del destino sale de un textarea del CRM y puede ser largo. A
   ancho completo daba lineas de ciento veinte caracteres: se pierde el
   renglon al saltar. */
.destino-texto p {
  max-width: 62ch;
  margin: 0 0 16px;
  color: var(--text);
  font-size: 16.5px;
  line-height: 1.7;
}
.destino-texto p:last-child { margin-bottom: 0; }

.destino-motivos {
  position: relative;
  overflow: hidden;
  padding: 30px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: white;
  box-shadow: var(--soft-shadow);
}

/* El degradado del manual, como en las tarjetas del listado. */
.destino-motivos::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 3px;
  background: var(--brand-gradient);
}

/* La lista de motivos, con la marca de verificación de marca.

   Vivía con la tarjeta del listado y se quedó huérfana el 26/08/2026 al
   quitarlos de allí —Maude los pidió fuera porque se repetían aquí—. Se
   trae a su único usuario en vez de dejarla suelta en un bloque que ya no
   la usa. */
.destination-benefits {
  display: grid;
  gap: 11px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.destination-benefits li {
  position: relative;
  padding-left: 28px;
  color: var(--text);
  font-size: 14.5px;
  line-height: 1.5;
}
.destination-benefits li::before {
  content: "\F26A";
  position: absolute;
  left: 0;
  top: 0;
  color: var(--accent-500);
  font-family: "bootstrap-icons";
  font-size: 15px;
  line-height: 1.45;
}

/* Cierra el texto de la provincia, separada por una línea. Estuvo suelta y a
   todo lo ancho, entre el texto y los bloques, y ahí no se sabía si era el
   final de lo anterior o el principio de lo siguiente. */
.destino-calidad {
  margin-top: 30px;
  padding-top: 26px;
  border-top: 1px solid var(--border);
}
.destino-calidad h2 { font-size: clamp(20px, 1.6vw, 24px); }
.destino-calidad p {
  max-width: 62ch;
  margin: 0;
  color: var(--text);
  font-size: 16.5px;
  line-height: 1.7;
}

/* El nombre de la ciudad, cuando la provincia tiene mas de una. Era un `h3`
   sin estilo, del tamano de un parrafo en negrita. */
.destino-ciudad {
  margin: 32px 0 14px;
  color: var(--primary-950);
  font-size: 20px;
}
.destino-ciudad:first-of-type { margin-top: 0; }

/* Lo que matiza la ciudad dentro de la provincia. Va pegado a su nombre —de
   ahi el margen negativo contra el que trae `.destino-ciudad`— y con el ancho
   de lectura del resto del texto corrido. */
.destino-ciudad-texto {
  max-width: 62ch;
  margin: -6px 0 18px;
  color: var(--muted);
}

/* Las fichas a dos columnas: a ancho completo, una linea de titulo con un
   resumen de doce palabras y un circulo al final dejaba un vacio enorme en
   el medio. */
.destino-formaciones {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
}

@media (max-width: 1180px) {
  .destino-columnas {
    grid-template-columns: 1fr;
    gap: 32px;
  }
  .destino-hero img { height: 300px; }
}

@media (max-width: 720px) {
  .destino-formaciones { grid-template-columns: 1fr; }
  .destino-motivos { padding: 22px; }
}

/* ── Paginas legales ────────────────────────────────────────────────────
   Privacidad, cookies y proteccion de datos.

   Se leen, no se escanean: una sola columna con medida de lectura, jerarquia
   clara y nada que distraiga. Es lo contrario del resto del sitio, y a
   proposito.

   Contraste sobre blanco:
     titulares  --primary-950 ....... 18,4:1
     cuerpo     --text ............... 14,8:1
     fecha      --muted ..............  5,9:1 */

.legal-cuerpo {
  display: grid;
  gap: 34px;
  max-width: 74ch;
}

/* Las secciones tienen que poder encogerse por debajo de su contenido: la
   tabla de cookies mide ~620 px de minimo y, sin esto, arrastraba la columna
   entera fuera de la pantalla en movil. El desplazamiento lo pone la tabla,
   no la pagina. */
.legal-cuerpo > * { min-width: 0; }

.legal-fecha {
  margin: 0;
  color: var(--muted);
  font-size: 14px;
}

/* El aviso de borrador. Ambar y no el azul de marca: es una advertencia, y
   un color de acento no puede significar «enlace» y «cuidado» a la vez.
   #8a5200 sobre su propio tinte da 6,1:1. */
.legal-borrador {
  padding: 18px 20px;
  border: 1px solid rgba(138, 82, 0, .28);
  border-left: 3px solid #8a5200;
  border-radius: var(--radius-md);
  background: rgba(138, 82, 0, .06);
}
.legal-borrador strong {
  display: block;
  margin-bottom: 4px;
  color: #8a5200;
  font-size: 14px;
  letter-spacing: .04em;
  text-transform: uppercase;
}
.legal-borrador p {
  margin: 0;
  color: var(--text);
  font-size: 15px;
}

.legal-seccion h2 {
  margin-bottom: 14px;
  font-size: clamp(21px, 2.1vw, 27px);
}
.legal-seccion p {
  margin: 0 0 14px;
  color: var(--text);
  font-size: 16.5px;
  line-height: 1.75;
}
.legal-seccion p:last-child { margin-bottom: 0; }

.legal-lista {
  display: grid;
  gap: 10px;
  margin: 0 0 16px;
  padding-left: 22px;
}
.legal-lista li {
  color: var(--text);
  font-size: 16.5px;
  line-height: 1.7;
}
.legal-lista li::marker { color: var(--electric-blue); }

/* Los datos del titular. En rejilla de dos columnas para que la etiqueta y
   el valor se lean de un vistazo, como una ficha. */
.legal-identificacion {
  display: grid;
  gap: 1px;
  margin: 0 0 16px;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--border);
}
.legal-identificacion > div {
  display: grid;
  grid-template-columns: minmax(140px, 220px) 1fr;
  gap: 4px 20px;
  padding: 14px 18px;
  background: white;
}
.legal-identificacion dt {
  color: var(--muted);
  font-size: 13px;
  font-weight: 750;
  letter-spacing: .04em;
  text-transform: uppercase;
}
.legal-identificacion dd {
  margin: 0;
  color: var(--primary-950);
  font-weight: 500;
}

/* Lo que falta se marca. No se deja en blanco ni se inventa: quien lo lea
   tiene que ver que falta, y quien lo complete, encontrarlo. */
.legal-identificacion dd.pendiente {
  color: #8a5200;
  font-style: italic;
  font-weight: 400;
}

.legal-tabla {
  overflow-x: auto;
  margin: 0 0 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
.legal-tabla table {
  width: 100%;
  border-collapse: collapse;
  font-size: 15px;
}
.legal-tabla th,
.legal-tabla td {
  padding: 12px 16px;
  text-align: left;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}
.legal-tabla tr:last-child td { border-bottom: 0; }
.legal-tabla th {
  color: var(--muted);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .07em;
  text-transform: uppercase;
  white-space: nowrap;
}
.legal-tabla td:first-child {
  color: var(--primary-950);
  font-weight: 600;
  white-space: nowrap;
}

.legal-nota {
  padding-left: 14px;
  border-left: 2px solid var(--border);
  color: var(--muted);
  font-size: 15px;
}
.legal-prevalece { margin-top: 10px; }

@media (max-width: 720px) {
  .legal-identificacion > div { grid-template-columns: 1fr; }

  /* La tabla se apila: cada fila es una ficha y cada dato lleva delante su
     cabecera, que la plantilla copia a `data-etiqueta`. Con desplazamiento
     horizontal se leia, pero la columna en prosa envolvia fuera de pantalla y
     dejaba filas de 250 px casi vacias. */
  .legal-tabla { overflow-x: visible; border: 0; border-radius: 0; }
  .legal-tabla thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .legal-tabla table,
  .legal-tabla tbody,
  .legal-tabla tr,
  .legal-tabla td { display: block; }

  .legal-tabla tr {
    margin-bottom: 12px;
    padding: 4px 0;
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
  }
  .legal-tabla tr:last-child { margin-bottom: 0; }

  .legal-tabla td {
    padding: 8px 16px;
    border-bottom: 0;
  }
  .legal-tabla td::before {
    content: attr(data-etiqueta);
    display: block;
    margin-bottom: 2px;
    color: var(--muted);
    font-size: 11px;
    font-weight: 800;
    letter-spacing: .07em;
    text-transform: uppercase;
  }
  .legal-tabla td:first-child { white-space: normal; }
}

.empty-state {
  display: grid;
  place-items: center;
  min-height: 180px;
  text-align: center;
  border: 1px dashed var(--border);
  border-radius: var(--radius-lg);
  background: var(--soft);
}

.detail-hero { grid-template-columns: 1fr .65fr; }
.breadcrumbs { display: flex; gap: 8px; margin-bottom: 18px; color: var(--muted); font-size: 13px; }
.breadcrumbs a { color: var(--primary-900); font-weight: 800; }
/* ── Ficha de formación ─────────────────────────────────────────────────
   Rehecha el 25/08/2026. Se veía como una pila de cajas blancas sobre fondo
   casi blanco, y con tres defectos concretos:

   · **Los márgenes no coincidían.** Eran cuatro `.content-grid` seguidos, cada
     uno con su hueco interno y ninguno con hueco entre sí: 22 px, 0 y 18 según
     qué bloque tocara. Ahora `.ficha` es una sola retícula con un `gap` único.

   · **Cajas medio vacías.** La propuesta de valor es una frase y ocupaba una
     tarjeta de 1.344 px de ancho; la institución, un nombre y un enlace, otra.
     Ninguna de las dos es un bloque de contenido: una es el argumento y la
     otra una atribución. Salen de la caja y toman la forma que les toca.

   · **Tarjetas hermanas de distinta altura.** `align-items: start` dejaba la
     fila dentada y las tres dejaban de leerse como un conjunto.

   Regla de fondo: la tarjeta blanca se reserva para lo que de verdad es un
   elemento de un conjunto. Si todo es tarjeta, nada lo es. */
.ficha {
  display: grid;
  gap: 24px;
}

/* La ficha de datos, como una sola banda y no cinco cajas sueltas.
   Los filetes se dibujan con el fondo asomando por un `gap` de 1 px, así valen
   igual cuando la banda envuelve a dos filas o se apila en móvil. */
.facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 1px;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--border);
}
.facts div {
  padding: 16px 20px;
  border: 0;
  background: white;
}
.facts span { display: block; margin-bottom: 4px; }
.facts strong { display: block; color: var(--primary-950); font-size: 16px; }

/* El argumento de venta: lo más alto de la página después del título. */
.ficha-lede {
  position: relative;
  max-width: 940px;
  padding-left: 26px;
}
.ficha-lede::before {
  content: "";
  position: absolute;
  left: 0;
  top: 3px;
  bottom: 3px;
  width: 3px;
  border-radius: 999px;
  /* Vertical, no el `--brand-gradient` horizontal: en una barra de 3 px de
     ancho un degradado a 90° sólo enseña el primer color. */
  background: linear-gradient(180deg, var(--turquoise), var(--cyan), var(--electric-blue));
}
.ficha-lede .eyebrow { margin-bottom: 10px; }
.ficha-lede p {
  color: var(--primary-950);
  font-size: clamp(19px, 1.5vw, 23px);
  font-weight: 600;
  line-height: 1.45;
}

/* Quién imparte: una franja de una línea, en tono apagado. Es metadato. */
.ficha-institucion {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 24px;
  padding: 16px 24px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--muted-surface);
}
.ficha-institucion .eyebrow { margin-bottom: 0; }
.ficha-institucion .eyebrow::after { display: none; }
.ficha-institucion img { height: 40px; width: auto; object-fit: contain; }
.ficha-institucion p {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px 10px;
}
.ficha-institucion strong { color: var(--primary-950); font-size: 17px; }
.ficha-institucion p span { color: var(--muted); font-size: 14px; }
.ficha-institucion > a {
  margin-left: auto;
  /* El azul eléctrico de marca sobre la franja apagada da 4,12:1 medido, y a
     14 px en negrita hacen falta 4,5. Este es el mismo azul oscurecido que ya
     usa el encabezado de preguntas frecuentes: 5,58:1 medido. */
  color: #1e4fd8;
  font-size: 14px;
  font-weight: 700;
}
.ficha-institucion > a:hover { text-decoration: underline; }

/*
 * Las tres listas: competencias, salidas y requisitos.
 *
 * `auto-fit` y no dos columnas fijas: los bloques que se pintan dependen de lo
 * que tenga cargado cada formación, y con dos fijas el tercero caía solo en una
 * fila ocupando media pantalla, con el hueco al lado.
 *
 * Estiradas a la misma altura. Son hermanas y con altura libre la fila queda
 * dentada; el enlace de cierre baja al pie con `margin-top: auto`.
 */
.content-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 18px;
}

.content-grid article {
  display: flex;
  flex-direction: column;
  padding: 28px 28px 30px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: white;
  box-shadow: var(--shadow);
}

/* El destino habla de la ciudad, no de la formación: panel aparte y en tono
   apagado, para que no se lea como una cuarta competencia. */
.ficha-destino {
  padding: 28px 30px 30px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--muted-surface);
}

/*
 * El título de bloque, a escala de bloque.
 *
 * Son `h2` y heredaban el tamaño de los titulares de sección: a 1.440 px eso
 * son 39 px, o sea que «Competencias» gritaba lo mismo que el título de la
 * formación. Con seis bloques seguidos la página no tenía jerarquía.
 *
 * Se les da tamaño propio y un filete de marca encima, que es lo que los ata
 * al resto del sitio sin necesidad de más peso.
 */
.content-grid h2,
.ficha-destino h2 {
  position: relative;
  padding-top: 16px;
  font-size: 21px;
  line-height: 1.25;
}

.content-grid h2::before,
.ficha-destino h2::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 36px;
  height: 3px;
  border-radius: 999px;
  background: var(--brand-gradient);
}

.content-grid h2 + *,
.ficha-destino h2 + * { margin-top: 16px; }

.content-grid ul,
.ficha-destino ul {
  display: grid;
  gap: 10px;
  margin: 0;
  padding-left: 20px;
  color: var(--muted);
}

/* Los motivos del destino, en dos columnas: en una sola, seis frases cortas
   dejaban vacía la mitad derecha del panel.

   Columnas de texto y no retícula: con `grid` las filas se alinean entre sí, y
   basta que un motivo ocupe dos líneas para que al de al lado le quede un hueco
   debajo. El texto en columnas fluye y las llena parejas. */
.ficha-destino ul {
  display: block;
  columns: 2;
  column-gap: 56px;
}
.ficha-destino li {
  margin-bottom: 12px;
  break-inside: avoid;
}

.content-grid p, .ficha-destino p { color: var(--muted); }

/* El enlace que cierra un bloque: en bloque, al pie y separado.
   Detrás de una lista quedaba pegado a la última viñeta y parecía un elemento
   más de ella. */
.content-grid article > a,
.ficha-destino > a {
  display: inline-flex;
  align-self: flex-start;
  align-items: center;
  gap: 8px;
  margin-top: auto;
  padding-top: 20px;
  font-weight: 600;
}

.talent-hero {
  width: min(1580px, calc(100% - 96px));
  grid-template-columns: .75fr 1.25fr;
}
.search-band {
  width: min(1320px, calc(100% - 96px));
  margin: -34px auto 0;
  position: relative;
  z-index: 2;
}
.search-band form { grid-template-columns: 180px 1fr 260px auto; margin: 0; }
.search-band strong { color: white; align-self: center; font-size: 20px; }
.steps {
  display: grid;
  grid-template-columns: 1.2fr repeat(4, 1fr);
  gap: 12px;
  margin-top: 22px;
  padding: 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
.steps div { display: flex; align-items: center; gap: 12px; }
.steps strong { display: grid; place-items: center; width: 34px; height: 34px; border-radius: 50%; background: var(--primary-900); color: white; }

.talent-hero-public {
  position: relative;
  display: grid;
  grid-template-columns: .78fr 1.22fr;
  gap: 44px;
  align-items: center;
  overflow: hidden;
  width: min(1580px, calc(100% - 96px));
  min-height: 530px;
  padding: 56px 0 36px;
}
.talent-hero-copy {
  position: relative;
  z-index: 1;
}
.talent-hero-public h1 {
  max-width: 650px;
  font-size: clamp(46px, 4.4vw, 70px);
}
.talent-hero-public p {
  max-width: 620px;
}
.talent-hero-benefits {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 28px;
}
.talent-hero-benefits span {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  min-height: 38px;
  padding: 7px 12px;
  border: 1px solid rgba(16,27,61,.1);
  border-radius: var(--radius-pill);
  background: rgba(255,255,255,.76);
  color: var(--primary-950);
  font-size: 13px;
  font-weight: 850;
  box-shadow: 0 8px 18px rgba(10,18,48,.04);
}
.talent-hero-benefits i {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: rgba(25,224,194,.12);
  color: var(--primary-900);
  font-size: 13px;
}
.talent-hero-preview {
  position: relative;
  justify-self: end;
  width: min(820px, 100%);
  overflow: visible;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
}
.talent-hero-preview::before {
  display: none;
}
.talent-hero-preview img {
  position: relative;
  z-index: 0;
  width: 100%;
  height: clamp(390px, 34vw, 560px);
  border-radius: 0;
  object-fit: contain;
  object-position: center;
  background: transparent;
  box-shadow: none;
}
.talent-hero-ui {
  position: absolute;
  left: clamp(18px, 3vw, 42px);
  right: clamp(18px, 3vw, 42px);
  bottom: clamp(18px, 3vw, 38px);
  z-index: 2;
  max-width: 520px;
  padding: 22px;
  border: 1px solid rgba(255,255,255,.42);
  border-radius: var(--radius-md);
  background: rgba(255,255,255,.92);
  box-shadow: 0 18px 34px rgba(10,18,48,.18);
  backdrop-filter: blur(12px);
}
.talent-hero-ui span {
  color: var(--primary-900);
  font-size: 11px;
  font-weight: 900;
  letter-spacing: .12em;
  text-transform: uppercase;
}
.talent-hero-ui strong {
  display: block;
  max-width: 360px;
  margin-top: 7px;
  color: var(--primary-950);
  font-family: Manrope, system-ui, sans-serif;
  font-weight: 800;
  font-size: clamp(24px, 2.2vw, 34px);
  line-height: 1;
}
.talent-hero-ui div {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 9px;
  align-items: center;
  margin-top: 16px;
  padding: 8px 8px 8px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: white;
  color: var(--muted);
  font-size: 13px;
}
.talent-hero-ui button {
  min-height: 34px;
  padding: 7px 14px;
  border: 0;
  border-radius: 7px;
  background: var(--primary-900);
  color: white;
  font-weight: 850;
}
.talent-hero-ui small {
  display: block;
  margin-top: 12px;
  color: var(--muted);
  font-size: 12px;
}
.talent-hero-ui b {
  color: var(--primary-950);
}
.talent-search-band {
  width: min(1440px, calc(100% - 96px));
  margin-top: -18px;
}
.talent-search-band form {
  grid-template-columns: 170px 1fr 1fr auto;
  gap: 12px;
  padding: 16px;
  box-shadow: 0 14px 28px rgba(10,18,48,.12);
}
.talent-search-band label {
  position: relative;
  color: inherit;
}
.talent-search-band label i {
  position: absolute;
  left: 14px;
  top: 50%;
  z-index: 1;
  color: var(--muted);
  transform: translateY(-50%);
}
.talent-search-band input,
.talent-search-band select {
  margin-top: 0;
  padding-left: 40px;
}
.talent-metrics-strip {
  grid-template-columns: repeat(4, minmax(0, 1fr));
  width: min(1440px, calc(100% - 96px));
  margin: 22px auto 0;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: white;
}
.talent-metrics-strip div {
  min-height: 112px;
  background: white;
}
.talent-metrics-strip i {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  margin-bottom: 2px;
  border: 3px solid #00b4ff;
  border-radius: 50%;
  background: var(--primary-950);
  color: white;
  font-size: 20px;
  box-shadow: 0 8px 18px rgba(10,18,48,.1);
}
.talent-access-section {
  padding-top: 34px;
}
.talent-access-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 24px;
}
.talent-access-card {
  position: relative;
  overflow: hidden;
  display: grid;
  grid-template-columns: 230px 1fr;
  min-height: 300px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: white;
  box-shadow: var(--shadow);
}
.talent-access-card > img {
  width: 100%;
  height: 100%;
  min-height: 300px;
  object-fit: cover;
}
.talent-access-card .path-icon {
  position: absolute;
  left: 202px;
  top: 28px;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 54px;
  height: 54px;
  border: 3px solid #00b4ff;
  border-radius: 50%;
  background: var(--primary-950);
  color: white;
  font-size: 22px;
  box-shadow: 0 10px 22px rgba(10,18,48,.18);
}
.talent-access-card:nth-child(2) .path-icon {
  border-color: #19e0c2;
  background: var(--primary-950);
  color: white;
}
.talent-access-card .path-content {
  padding: 30px 32px 30px 52px;
}
.talent-access-card h2 {
  max-width: 430px;
  font-size: clamp(27px, 2.2vw, 36px);
}
.talent-access-card p {
  max-width: 480px;
  margin-top: 10px;
}
.talent-access-card ul {
  columns: 2;
  gap: 28px;
  margin: 20px 0 22px;
  padding: 0;
  list-style: none;
}
.talent-access-card li {
  position: relative;
  break-inside: avoid;
  margin-bottom: 8px;
  padding-left: 22px;
  color: var(--dark-gray);
}
.talent-access-card li::before {
  content: "\F26A";
  position: absolute;
  left: 0;
  top: 1px;
  color: var(--accent-700);
  font-family: "bootstrap-icons";
  font-size: 13px;
}
.talent-steps {
  grid-template-columns: .9fr repeat(4, 1fr);
  margin-top: 26px;
  padding: 18px;
  background: white;
}
.talent-steps h2 {
  align-self: center;
  font-size: 28px;
}
.talent-steps div {
  min-height: 74px;
  padding: 10px;
}
.talent-steps strong {
  border: 3px solid #00b4ff;
  background: var(--primary-950);
  color: white;
  box-shadow: 0 8px 18px rgba(10,18,48,.08);
}
.talent-steps span {
  display: grid;
  gap: 3px;
}
.talent-steps small {
  color: var(--muted);
  font-size: 12px;
  line-height: 1.3;
}
.talent-services-section {
  padding-top: 26px;
  padding-bottom: 36px;
}
.talent-services-section .strategic-card-grid {
  grid-template-columns: repeat(4, minmax(0, 1fr));
}
.talent-services-section .strategic-card {
  min-height: 292px;
}
.talent-services-section .strategic-media span {
  border-color: #00b4ff;
  background: var(--primary-950);
}
.talent-trust-section {
  padding-top: 20px;
  padding-bottom: 34px;
}
.talent-logo-panel {
  overflow: hidden;
  padding: 28px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: white;
  text-align: center;
  box-shadow: var(--shadow);
}
.talent-logo-panel h2 {
  margin-bottom: 24px;
  font-size: clamp(26px, 2.4vw, 36px);
}
.talent-logo-carousel {
  margin-top: 24px;
}
.talent-logo-carousel.logo-carousel .logo-carousel-track {
  gap: 18px;
  animation-duration: 240s;
}
.talent-logo-carousel .logo-tile {
  flex: 0 0 clamp(210px, 15vw, 270px);
  min-height: 92px;
  border-color: rgba(10,18,48,.1);
  box-shadow: none;
}
.talent-logo-carousel .logo-tile img {
  max-width: 178px;
  max-height: 54px;
}
.carousel-dots {
  display: flex;
  justify-content: center;
  gap: 9px;
  margin-top: 22px;
}
.carousel-dots span {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: #d7dfe5;
}
.carousel-dots span:first-child {
  background: var(--primary-900);
}
.talent-success-section {
  margin-top: 18px;
  background:
    linear-gradient(90deg, rgba(10,18,48,.96), rgba(10,18,48,.92)),
    url("/assets/images/stock/terminal-moderna.jpg");
  background-size: cover;
  background-position: center;
}
.talent-success-inner {
  width: min(1320px, calc(100% - 96px));
  padding-top: 44px;
  padding-bottom: 48px;
  color: white;
  text-align: center;
}
.talent-success-inner h2 {
  color: white;
  font-size: clamp(28px, 2.6vw, 40px);
}
.success-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0;
  max-width: 1180px;
  margin: 28px auto 0;
}
.success-grid article {
  display: grid;
  grid-template-columns: 72px 1fr;
  gap: 4px 18px;
  align-items: center;
  min-height: 118px;
  padding: 8px 42px;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  text-align: left;
  backdrop-filter: none;
}
.success-grid article + article {
  border-left: 1px solid rgba(255,255,255,.2);
}
.success-grid img {
  grid-row: span 3;
  width: 72px;
  height: 72px;
  border-radius: 50%;
  object-fit: cover;
}
.success-grid blockquote {
  margin: 0;
  color: white;
  font-size: 16px;
  font-weight: 750;
  line-height: 1.45;
}
.success-grid p {
  color: rgba(255,255,255,.8);
  font-size: 14px;
}
.success-grid span {
  color: #f4c95d;
  font-size: 13px;
}
.talent-next-step {
  position: relative;
  display: grid;
  grid-template-columns: minmax(420px, 1fr) auto;
  gap: 34px;
  align-items: center;
  justify-content: space-between;
  overflow: hidden;
  width: 100%;
  min-height: 170px;
  margin-top: 0;
  padding: 28px max(48px, calc((100vw - 1580px) / 2));
  border-top: 1px solid rgba(255,255,255,.14);
  background: #071d3c;
  color: white;
}
.talent-next-step::before {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(90deg, rgba(10,18,48,.62) 0%, rgba(10,18,48,.56) 36%, rgba(10,18,48,.78) 100%),
    url('/assets/images/portal-globe-network.jpg');
  background-size: cover;
  background-repeat: no-repeat;
  background-position: center;
  pointer-events: none;
}
.talent-next-step::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(0deg, rgba(10,18,48,.24), rgba(10,18,48,.08) 46%),
    radial-gradient(circle at 18% 52%, rgba(255,255,255,.08), transparent 34%);
  pointer-events: none;
}
.talent-next-step-copy,
.talent-next-step .actions,
.talent-globe {
  position: relative;
  z-index: 2;
}
.talent-globe {
  display: none;
}
.talent-next-step .eyebrow,
.talent-next-step h2,
.talent-next-step p {
  color: white;
}
.talent-next-step .eyebrow {
  color: rgba(25,224,194,.95);
}
.talent-next-step h2 {
  max-width: 660px;
  font-size: clamp(27px, 2.5vw, 38px);
}
.talent-next-step p {
  max-width: 660px;
  margin-top: 6px;
  color: rgba(255,255,255,.78);
  font-size: 14px;
}
.talent-next-step .actions {
  justify-content: flex-end;
  min-width: 420px;
}

.job-grid { grid-template-columns: repeat(3, 1fr); }
.job-card { padding: 20px; }
.tags { display: flex; flex-wrap: wrap; gap: 8px; margin: 14px 0; }
.tags small { padding: 5px 9px; border-radius: var(--radius-pill); background: var(--soft); color: var(--muted); font-weight: 750; }
.detail-panel { display: grid; gap: 10px; padding: 24px; }
.profile-demo, .form-card {
  max-width: 860px;
  padding: 22px;
}
.progress { height: 12px; overflow: hidden; border-radius: var(--radius-pill); background: var(--muted-surface); }
.progress span { display: block; height: 100%; background: var(--primary-900); }
.form-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 14px; }

/* Las etiquetas de una fila reservan dos lineas.

   Con una columna estrecha, una etiqueta larga —«Repite la nueva contraseña»—
   ocupa dos lineas y su vecina una, asi que los dos campos quedaban
   escalonados: el de la derecha arrancaba mas abajo que el de la izquierda.
   Reservando la altura de dos lineas coinciden siempre.

   Y se resuelve aqui, en la etiqueta, y no alineando la pareja por abajo, que
   es el apano evidente y falla justo cuando mas se nota: con un error debajo de
   uno de los dos campos, alinear por el final baja el campo vecino hasta la
   altura del mensaje de error.

   `lh` —la altura de una linea— y no un valor en `em` a ojo. Medido sobre la
   pagina servida: el `line-height` heredado aqui es 24,8 px sobre una letra de
   16, asi que dos lineas son 49,6 px y un `2.6em` se quedaba en 41,6. La
   diferencia son ocho pixeles, suficiente para que los dos campos siguieran
   escalonados y poco para verlo sin medir. Con `lh` no hay que acertar el
   numero: si cambia el interlineado, la reserva cambia con el. */
.form-grid > label > span { display: block; min-height: 2lh; }

.form-card label { display: block; margin-bottom: 14px; color: var(--primary-950); font-weight: 800; }
/* La pista de un campo. Peso normal y en gris: es ayuda, no etiqueta, y en
   negrita competiria con el nombre del campo. El `small` de los errores va
   aparte y en rojo, asi que no se confunden. */
.form-card label .campo-pista {
  display: block;
  margin-top: 5px;
  font-size: 12.5px;
  font-weight: 500;
  line-height: 1.45;
  color: var(--muted);
}

.checkbox { display: flex !important; gap: 10px; align-items: start; font-weight: 600 !important; }
.checkbox input { width: auto; min-height: auto; margin-top: 6px; }

.contact-hero {
  display: grid;
  grid-template-columns: minmax(520px, 1fr) minmax(320px, 440px);
  align-items: end;
  gap: 42px;
  width: min(1580px, calc(100% - 96px));
  margin: 0 auto;
  padding: 66px 0 34px;
}
.contact-hero h1 {
  max-width: 720px;
  margin-top: 14px;
}
.contact-hero p {
  max-width: 680px;
  margin-top: 16px;
  font-size: 18px;
}
.contact-demo-badge {
  display: grid;
  grid-template-columns: 42px 1fr;
  gap: 4px 14px;
  padding: 22px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: linear-gradient(135deg, rgba(0,180,255, .08), rgba(255,255,255,.96));
  box-shadow: var(--soft-shadow);
}
.contact-demo-badge i {
  grid-row: span 2;
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  background: rgba(0,180,255, .11);
  color: var(--primary-900);
  font-size: 20px;
}
.contact-demo-badge strong {
  color: var(--primary-950);
  font-size: 18px;
}
.contact-demo-badge p {
  margin: 0;
  color: var(--muted);
  font-size: 14px;
}
/* La columna del formulario **llena lo que queda**, no 900px fijos.

   Con el tope fijo, en una pantalla ancha el formulario terminaba 214px antes
   que la banda de arriba y que el resto de la seccion: dos bordes derechos
   distintos en la misma pagina, que es de esas cosas que se ven raras sin que
   uno sepa senalar por que. Medido a 1830px de ancho: la banda acababa en
   1705 y el formulario en 1491.

   A anchos normales no cambia nada -a 1400px lo que queda son los mismos
   838px de antes-; solo deja de sobrar sitio cuando lo hay. */
.contact-layout {
  display: grid;
  grid-template-columns: minmax(300px, 430px) minmax(0, 1fr);
  align-items: start;
  gap: 36px;
  padding-top: 34px;
}
/* Cuando la solicitud ya se envio, el lateral desaparece y esto se queda solo.

   Sin esto la confirmacion caia en la primera columna de la rejilla -la
   estrecha, la del lateral- y salia espachurrada contra el borde izquierdo con
   media pantalla vacia al lado. */
.contact-layout-sola {
  grid-template-columns: minmax(0, 720px);
  justify-content: center;
}
/* El calendario pide mas sitio que un mensaje de confirmacion: a 720px las
   columnas de dias quedan estrechas y las horas se apilan de una en una, que es
   justo la lista larga que el calendario venia a evitar. */
.contact-layout-agenda { grid-template-columns: minmax(0, 1040px); }

.contact-aside {
  position: sticky;
  top: 104px;
  padding: 28px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: white;
  box-shadow: var(--soft-shadow);
}
.contact-aside h2 {
  margin-top: 12px;
  font-size: clamp(30px, 3vw, 44px);
}
.contact-aside p { margin-top: 12px; }
.contact-aside ul {
  display: grid;
  gap: 12px;
  margin-top: 20px;
  padding: 0;
  list-style: none;
}
.contact-aside li {
  display: grid;
  grid-template-columns: 24px 1fr;
  gap: 10px;
  color: var(--primary-800);
  font-weight: 700;
}

/* El correo protegido se pinta igual que el enlace que sustituye: hereda del
   contexto -pie, tarjeta de staff, fila de redes- y no trae estilo propio. Lo
   unico suyo es que el texto de la direccion no se parta por cualquier sitio. */
.correo-protegido [data-correo-texto] { overflow-wrap: anywhere; }

/* La banda de «pedir una reunion», encima del formulario de contacto.

   Horizontal a proposito: separa dos caminos -escribir o sentarse a hablar-
   sin robarle la pantalla al formulario, que es lo que la mayoria viene a
   rellenar. En movil se apila, que es lo unico que cabe.

   El fondo es el azul de marca con el degradado como filo superior, igual que
   la tarjeta del calendario: la misma familia visual para las dos pantallas
   del mismo circuito. */
.agenda-banda-seccion { padding-top: 34px; padding-bottom: 0; }

.agenda-banda {
  position: relative;
  overflow: hidden;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 28px;
  padding: 26px 30px;
  border-radius: var(--radius-lg);
  background: var(--primary-950);
  box-shadow: var(--shadow);
}
.agenda-banda::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 4px;
  background: var(--brand-gradient);
}

/* Un resplandor teal en la esquina, muy suave. Es lo que separa la banda de un
   rectangulo azul cualquiera; con mas opacidad compite con el texto. */
.agenda-banda::after {
  content: "";
  position: absolute;
  right: -80px;
  top: -120px;
  width: 320px;
  height: 320px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(25, 224, 194, .22), transparent 68%);
  pointer-events: none;
}

.agenda-banda-texto { position: relative; z-index: 1; }
.agenda-banda-texto .eyebrow { color: var(--turquoise); }
.agenda-banda-texto h2 {
  margin: 8px 0 6px;
  font-size: clamp(22px, 2.4vw, 27px);
  line-height: 1.2;
  color: white;
  letter-spacing: -.01em;
}
/* Blanco al 82 % y no un gris: sobre el azul de marca da 12,7:1, de sobra para
   texto pequeno, y no ensucia el color del fondo. */
.agenda-banda-texto p {
  margin: 0;
  max-width: 62ch;
  font-size: 15px;
  line-height: 1.6;
  color: rgba(255, 255, 255, .82);
}

.agenda-banda-accion {
  position: relative;
  z-index: 1;
  display: flex;
  justify-content: flex-end;
}
/* El boton, con el degradado de la marca.

   Sobre el azul de la banda, el primario del sitio es invisible -comparte
   color con el fondo- y uno blanco se lee bien pero no dice nada: es el mismo
   boton que en cualquier otra web. El degradado es lo unico de la identidad
   que se reconoce a un metro.

   **Teal a cian, sin llegar al azul electrico.** El texto va en Azul Profundo,
   y un degradado no tiene un unico contraste: se mide a lo largo y manda el
   peor punto. Teal 10,93:1, cian 7,86:1, y nada por debajo entre medias. Con
   el azul electrico del gradiente completo caeria a 3,75:1, por debajo del
   4,5 que pide un texto de 15px. */
.btn-agendar {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 15px 26px;
  background: linear-gradient(100deg, var(--turquoise), var(--cyan));
  color: var(--primary-950);
  font-weight: 800;
  border: 0;
  border-radius: var(--radius-pill);
  white-space: nowrap;
  box-shadow: 0 10px 26px rgba(25, 224, 194, .28);
  transition: transform .18s ease, box-shadow .18s ease, filter .18s ease;
}
.btn-agendar:hover,
.btn-agendar:focus-visible {
  color: var(--primary-950);
  transform: translateY(var(--alza-control));
  box-shadow: 0 14px 32px rgba(25, 224, 194, .38);
  /* Un punto mas de saturacion en vez de otro color: el degradado sigue
     siendo el de la marca y el boton responde igual. */
  filter: saturate(1.08);
}
/* El foco, visible sobre fondo oscuro: el contorno del sitio es azul marino y
   aqui se perderia contra la banda. */
.btn-agendar:focus-visible { outline: 2px solid white; outline-offset: 3px; }
.btn-agendar:active { transform: translateY(0); box-shadow: 0 6px 16px rgba(25, 224, 194, .3); }

.btn-agendar i { font-size: 15px; transition: transform .18s ease; }
.btn-agendar:hover i { transform: translateX(4px); }
@media (max-width: 1180px) {
  .agenda-banda { padding: 24px 26px; }
}

@media (max-width: 720px) {
  /* Apilada, y el boton a lo ancho: en movil un boton estrecho al final de un
     bloque oscuro se pierde. */
  .agenda-banda { grid-template-columns: 1fr; gap: 20px; padding: 24px 20px; }
  .agenda-banda-accion .btn { justify-content: center; width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  .btn-agendar, .btn-agendar i { transition: none; }
  .btn-agendar:hover, .btn-agendar:hover i, .btn-agendar:active { transform: none; }
}

/* Elegir dia y hora, desde el enlace del correo.

   Es un calendario por semana y no una lista larga: con veinte horas abiertas,
   la lista obligaba a bajar y bajar sin ver nunca la semana entera, que es la
   pregunta que uno se hace -"que dia me viene bien"- antes que la hora.

   Cada hora es un boton de envio y no una opcion de un desplegable: elegir la
   hora **es** la decision, y con un `select` hay que elegir y despues confirmar
   en otro sitio. Un clic, una reunion. */

/* La tarjeta del calendario, con la marca encima.

   El degradado va en un `::before` de 4px pegado al borde superior y no en el
   `border-image`: asi respeta el radio de la tarjeta, que con un borde de
   degradado se pierde en las esquinas. */
.calendario-card {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
}
.calendario-card::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 4px;
  background: var(--brand-gradient);
}

/* Tres columnas y no `space-between`: con una sola flecha -la primera semana no
   tiene anterior- el rotulo se iba de centro y la barra parecia mal alineada. */
.semana-barra {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 12px;
  margin: 4px 0 22px;
  padding-bottom: 18px;
  border-bottom: 1px solid var(--border);
}
.semana-barra > :last-child { justify-self: end; }

.semana-rotulo {
  margin: 0;
  font-size: 17px;
  font-weight: 800;
  letter-spacing: -.01em;
  color: var(--primary-950);
  text-align: center;
  font-variant-numeric: tabular-nums;
}

.semana-mover {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 9px 16px;
  font-size: 14px;
  font-weight: 700;
  color: var(--primary-950);
  text-decoration: none;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: white;
  white-space: nowrap;
  transition: border-color .15s, box-shadow .15s, transform .15s;
}
.semana-mover:hover {
  border-color: var(--turquoise);
  box-shadow: 0 6px 16px rgba(10, 18, 48, .08);
  transform: translateY(var(--alza-control));
}
.semana-mover:focus-visible { outline: 2px solid var(--primary-950); outline-offset: 2px; }

/* El hueco de la flecha que no existe, para que el rotulo de la semana no se
   descoloque cuando solo hay una de las dos. */
.semana-mover-vacio { border-color: transparent; background: transparent; min-width: 44px; }

.semana-rejilla {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(124px, 1fr));
  gap: 14px;
}

/* Cada dia, una columna con su propia tarjeta.

   El degradado tenue del borde superior las ata a la marca sin competir con
   las horas, que es lo que hay que leer. */
.semana-dia {
  position: relative;
  overflow: hidden;
  padding: 16px 12px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--soft);
  transition: border-color .15s, box-shadow .15s;
}
.semana-dia::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 3px;
  background: var(--quiet-gradient);
  opacity: .8;
}
.semana-dia:hover {
  border-color: rgba(0, 180, 255, .45);
  box-shadow: var(--soft-shadow);
}

/* El dia de hoy, marcado con el teal y **tambien con la palabra**: un dia que
   solo se distingue por el color no lo distingue quien no separa los colores. */
.semana-dia-hoy { border-color: rgba(25, 224, 194, .55); }
.semana-dia-hoy::before { background: var(--brand-gradient); opacity: 1; }

.semana-dia-nombre {
  margin: 0 0 14px;
  font-size: 13px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--primary-950);
  text-align: center;
}
/* La fecha debajo del dia: apilado en movil, "Mie." solo no situa a nadie. */
.semana-dia-nombre span {
  display: block;
  margin-top: 3px;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
/* Con la clase dentro del selector del rotulo: `.semana-dia-nombre span` pesa
   mas que `.semana-dia-cuenta` a secas, y la cuenta salia con el tamano de la
   fecha en vez del suyo. */
.semana-dia-nombre .semana-dia-cuenta {
  display: block;
  margin-top: 4px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  color: var(--muted);
}

.semana-dia-nombre em {
  display: block;
  margin-top: 6px;
  font-size: 11px;
  font-style: normal;
  font-weight: 800;
  letter-spacing: .08em;
  color: var(--primary-800);
}

/* Las horas en rejilla y no en columna: con seis o siete por dia, una debajo de
   otra obliga a recorrer la pagina entera para ver una semana. */
.semana-dia-horas {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(88px, 1fr));
  gap: 8px;
}

/* Las horas, en cifras tabulares para que la columna no baile: sin esto el
   ancho cambia segun los digitos y los botones quedan desiguales. */
.franja {
  width: 100%;
  padding: 12px 8px;
  font: inherit;
  font-size: 15px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--primary-950);
  background: white;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  cursor: pointer;
  transition: background .15s, border-color .15s, color .15s, box-shadow .15s, transform .15s;
}
.franja:hover {
  background: var(--primary-950);
  border-color: var(--primary-950);
  color: white;
  box-shadow: 0 8px 18px rgba(10, 18, 48, .18);
  transform: translateY(var(--alza-control));
}
.franja:focus-visible {
  outline: 2px solid var(--primary-950);
  outline-offset: 2px;
}
.franja:active { transform: translateY(1px); box-shadow: none; }

/* La hora ya elegida, en la confirmacion. */
.franja-elegida {
  margin-top: 14px;
  font-size: 19px;
  font-weight: 800;
  color: var(--primary-950);
}
.franja-elegida small {
  display: block;
  margin-top: 2px;
  font-size: 13px;
  font-weight: 500;
  color: var(--muted);
}

/* En movil las columnas se apilan solas por el `auto-fit`, y el texto de las
   flechas sobra: el icono ya lo dice y ocupa la mitad. Las horas pasan a dos o
   tres por fila, que es lo que cabe sin que el dedo falle el objetivo. */
@media (max-width: 720px) {
  .semana-mover span { display: none; }
  .semana-mover { padding: 9px 13px; }
  .semana-rotulo { font-size: 15px; }
  .semana-dia { padding: 14px 10px 12px; }

  /* Un dia por fila y las horas en tres columnas dentro.
     Dos columnas de dias con las horas en fila unica dejaban la pantalla
     larguisima -1.300px de scroll para tres dias- y con un hueco raro cuando
     el tercero se quedaba solo. Asi cada dia se lee entero de un vistazo. */
  .semana-rejilla { grid-template-columns: 1fr; }
  .semana-dia-horas { grid-template-columns: repeat(auto-fit, minmax(84px, 1fr)); }

  /* 48px de alto minimo: es lo que pide un objetivo tactil, y esta pantalla se
     usa con el movil en la mano. */
  .franja { min-height: 48px; }
}

@media (prefers-reduced-motion: reduce) {
  .franja, .semana-mover, .semana-dia { transition: none; }
  .franja:hover, .semana-mover:hover { transform: none; }
  .franja:active { transform: none; }
}

/* La confirmacion de `/agenda`, cuando la solicitud entra.

   **Sustituye al formulario, no se pone encima.** Antes convivian y quien
   enviaba veia una tarjeta pequena y su formulario otra vez, vacio: la duda era
   razonable -se ha mandado o se ha borrado?-. Un formulario visible es una
   invitacion a volver a rellenarlo.

   La entrada es suave a proposito. Es un cambio de pantalla completo tras un
   envio, y aparecer de golpe se lee como un error mas que como un exito. */
.solicitud-exito {
  padding: 40px 34px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: white;
  box-shadow: var(--soft-shadow);
  text-align: center;
  animation: solicitud-entra .45s ease-out both;
}
.solicitud-exito:focus { outline: none; }
.solicitud-exito h2 { margin-top: 18px; font-size: clamp(26px, 2.6vw, 34px); }
.solicitud-exito > p { margin-top: 12px; }

/* La marca de visto, en el idioma de iconos del sitio.

   Estaba con el degradado de marca de fondo y el glifo oscuro encima, y se
   salia del resto: los iconos del sitio -las tarjetas de areas- son circulo de
   Azul Profundo, aro de cian y glifo blanco. Aqui va igual, y mas grande,
   porque es el remate de la pagina y no una vineta de una tarjeta.

   El aro se queda en cian y el disco oscuro a proposito: el contraste lo da el
   glifo blanco encima, no el color del aro. */
.solicitud-exito-marca {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 72px;
  height: 72px;
  border: 3px solid var(--cyan);
  border-radius: 50%;
  background: var(--primary-950);
  color: white;
  font-size: 32px;
  box-shadow: 0 0 0 8px rgba(0, 180, 255, .12);
}

.solicitud-exito-correo { margin-top: 16px; }
.solicitud-exito-correo strong { display: block; margin-top: 4px; word-break: break-all; }

/* Los tres pasos, con el primero ya cumplido. Alineados a la izquierda dentro
   de una tarjeta centrada: una lista centrada no se lee de un vistazo. */
.solicitud-exito-pasos {
  display: grid;
  gap: 10px;
  max-width: 460px;
  margin: 26px auto 0;
  padding-left: 22px;
  text-align: left;
  color: var(--primary-800);
}
.solicitud-exito-pasos li.hecho { color: var(--muted); text-decoration: line-through; }
.solicitud-exito .btn { margin-top: 26px; }

@keyframes solicitud-entra {
  from { opacity: 0; transform: translateY(14px); }
  to { opacity: 1; transform: none; }
}

/* Quien pide movimiento reducido suele tener un motivo medico. El contenido
   aparece igual, sin desplazarse. */
@media (prefers-reduced-motion: reduce) {
  .solicitud-exito { animation: none; }
}

/* Los pasos de `/agenda`: una lista numerada dentro del mismo aside.

   `.contact-aside li` es una rejilla de dos columnas —24px de icono y el
   texto— pensada para la lista de tipos de `/contacto`. Sin icono, el texto
   caia en la columna de 24px y salia **a una palabra por linea**. Es el mismo
   fallo que tuvo el telefono del pie: una rejilla de dos columnas heredada por
   un contenido que solo trae una.

   Y aqui la numeracion significa algo: no se puede elegir hora antes de que
   Maude revise, asi que el orden es el del proceso y no decoracion. */
.contact-aside ol {
  display: grid;
  gap: 12px;
  margin-top: 20px;
  padding-left: 20px;
}
.contact-aside ol li {
  display: list-item;
  grid-template-columns: none;
  color: var(--primary-800);
}
.contact-aside li i {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: rgba(0,180,255, .1);
  color: var(--primary-900);
}
.contact-form-card {
  width: 100%;
  max-width: none;
  padding: 30px;
}

/* El botón de envío, despegado del aviso de datos.

   Iban pegados —cero píxeles entre el último párrafo y el botón—, y era el
   único sitio del formulario sin aire: los campos se separan con el `gap` de
   la rejilla y el aviso queda fuera de ella, así que nadie le ponía margen.

   Se separa más de lo que separa a dos campos entre sí, y a propósito:
   enviar es la única acción irreversible de la página, y no tiene que
   parecer la continuación del párrafo que hay encima. */
/* `.contact-form-card` **es** el `<form>`, no lo envuelve: con
   `.contact-form-card form >` esto buscaba un formulario dentro de otro y no
   aplicaba nada. */
form.contact-form-card > p {
  margin-top: 12px;
}
form.contact-form-card > button[type="submit"] {
  margin-top: 26px;
}

/* El reto de Turnstile: su propio paso, no un apéndice del aviso de datos.
   Cloudflare fija el alto del recuadro, así que aquí sólo se coloca. */
form.contact-form-card > .cf-turnstile {
  margin-top: 20px;
}
form.contact-form-card > .cf-turnstile + button[type="submit"] {
  margin-top: 20px;
}
.form-heading {
  margin-bottom: 22px;
  padding-bottom: 18px;
  border-bottom: 1px solid var(--border);
}
.form-heading span {
  color: var(--primary-900);
  font-size: 12px;
  font-weight: 900;
  letter-spacing: .12em;
  text-transform: uppercase;
}
.form-heading h2 {
  margin-top: 8px;
  font-size: clamp(30px, 3vw, 42px);
}
.form-heading p {
  max-width: 620px;
  margin-top: 8px;
  color: var(--muted);
}

/* ══ Boletín ═══════════════════════════════════════════════════════
   La misma pieza en dos sitios y con dos vestidos: `compacto` en el pie de
   las trece páginas, sobre el azul profundo, y `destacado` al final de cada
   noticia, sobre el fondo claro de la página.

   Comparten estructura y formulario; lo único que cambia es el fondo y
   quién manda el color del texto. Se escriben juntas a propósito: separadas,
   la de arriba se toca y la de abajo se queda vieja. */

.boletin {
  display: grid;
  gap: clamp(20px, 2.4vw, 40px);
  align-items: center;
}

.boletin .eyebrow {
  margin-bottom: 10px;
}
.boletin h2 {
  margin: 0;
  font-size: clamp(22px, 2vw, 30px);
  line-height: 1.2;
}
.boletin-texto p {
  max-width: 52ch;
  margin: 10px 0 0;
  font-size: 15px;
  line-height: 1.6;
}

.boletin-form {
  display: grid;
  gap: 12px;
  /* Un elemento de rejilla no baja de su ancho mínimo de contenido salvo que
     se le diga, y el aviso de consentimiento es una línea larga: sin esto,
     en el móvil empujaba el formulario fuera del pie. */
  min-width: 0;
}

.boletin-campo {
  display: grid;
  gap: 6px;
  font-size: 13px;
  font-weight: 800;
}
.boletin-campo input {
  width: 100%;
  min-height: 48px;
}

.boletin-consentimiento {
  display: flex;
  gap: 10px;
  align-items: start;
  font-size: 13px;
  line-height: 1.5;
}
.boletin-consentimiento input {
  width: auto;
  min-height: auto;
  margin-top: 3px;
}
.boletin-consentimiento a {
  text-decoration: underline;
}

.boletin-nota {
  font-size: 12px;
  line-height: 1.5;
}

.boletin-aviso {
  display: flex;
  gap: 10px;
  align-items: start;
  margin: 0;
  padding: 14px 16px;
  border-radius: var(--radius-md);
  font-size: 14px;
  line-height: 1.5;
}
.boletin-aviso i {
  margin-top: 2px;
  font-size: 16px;
}

/* ── Al final de una noticia ───────────────────────────────────────
   Aquí sí es una pieza con cuerpo: es el sitio donde de verdad convierte y
   tiene que verse como una invitación, no como un pie de página. */

.boletin-destacado {
  grid-template-columns: minmax(0, 1fr) minmax(0, 420px);
  width: min(1180px, calc(100% - 96px));
  margin: 0 auto;
  padding: clamp(28px, 3vw, 44px);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--soft);
}
.boletin-destacado h2 {
  color: var(--primary-950);
}
.boletin-destacado .boletin-texto p,
.boletin-destacado .boletin-nota,
.boletin-destacado .boletin-consentimiento {
  color: var(--muted);
}
.boletin-destacado .boletin-campo {
  color: var(--primary-950);
}
.boletin-destacado .boletin-campo input {
  background: white;
}
.boletin-destacado .boletin-form .btn-primary {
  justify-self: start;
}

/*
 * ══ La piel de marca ═══════════════════════════════════════════════
 *
 * Pedido de Maude: que se vea más atractivo. Dos capas dentro del mismo
 * `background`, para no añadir pseudoelementos que compitan con el filete:
 *
 * 1. Dos **lóbulos del degradado de marca**, teal y cian, muy diluidos y en la
 *    mitad derecha, que es donde está el formulario: dan color sin pasar por
 *    detrás del texto, que es justo donde el color cuesta contraste.
 *
 * 2. El fondo claro de siempre, debajo.
 *
 * El Azul Eléctrico se queda fuera a propósito: es el más oscuro de los seis y
 * sobre fondo claro ensucia en vez de aportar.
 *
 * **Hubo un motivo de líneas y se quitó**, a petición de Maude el 29/08/2026.
 * Era el del dossier, el mismo que lleva `.final-cta`, pero allí va en blanco
 * sobre azul profundo y aquí quedaba en azul sobre fondo claro: en negativo se
 * lee como textura y en positivo como un rayado. Si vuelve a plantearse, ése
 * es el motivo por el que no funcionó.
 */
.boletin-destacado {
  position: relative;
  overflow: hidden;
  background:
    radial-gradient(58% 90% at 92% 12%, rgba(0, 180, 255, .10), transparent 70%),
    radial-gradient(52% 80% at 74% 104%, rgba(25, 224, 194, .12), transparent 72%),
    var(--soft);
}

/* El canto superior con el degradado del manual, igual que remata el bloque
   de cierre. Es lo que hace que la pieza se lea como parte del sistema y no
   como una caja gris con un formulario dentro. */
.boletin-destacado::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  z-index: 1;
  height: 3px;
  background: var(--brand-gradient);
}

/* El contenido, por encima de las capas de fondo. */
.boletin-destacado > * {
  position: relative;
  z-index: 2;
}

/*
 * Como pieza de cierre, antes del pie y en todas las vistas.
 *
 * Al salir del pie ya no hereda el aire de la sección que lo envolvía, así que
 * se lo pone él. Y al ancho de las demás secciones del sitio: con sus 1180 px
 * fijos no cuadraba con nada -por encima de 1180 quedaba más estrecho que el
 * contenido y por debajo más ancho-.
 */
.boletin-destacado.boletin-ancho {
  width: min(1580px, calc(100% - 96px));
  margin: 0 auto 54px;

  /* Llenar la caja, no sólo estirarla.
     Con la tipografía y el relleno de la versión de 1180 px, la misma pieza a
     1580 dejaba un hueco de más de 400 px entre el final del párrafo y el
     formulario: se leía como una tarjeta a medio hacer. Los números salen de
     `.final-cta`, la otra pieza de cierre a todo el ancho del sitio, que ya
     resolvió esto: más relleno, titular más grande y el texto con sitio para
     respirar. En el listado el boletín **es** el cierre de la página —no hay
     `.final-cta` detrás—, así que puede permitírselo sin competir con nada. */
  padding: clamp(32px, 3.6vw, 60px);
  grid-template-columns: minmax(0, 1fr) minmax(0, 480px);
  gap: clamp(24px, 3vw, 56px);
}
.boletin-ancho h2 {
  font-size: clamp(24px, 2.4vw, 36px);
}
.boletin-ancho .boletin-texto p {
  max-width: 62ch;
  font-size: clamp(15px, 1.05vw, 17px);
}

/* El aviso, en los dos sitios. El verde y el rojo de estado no salen del
   manual —no los tiene— así que se usan los mínimos que pasan contraste
   sobre su propio fondo. */
.boletin-aviso-ok {
  background: rgba(25, 224, 194, .14);
  color: #0b5d51;
}
.boletin-aviso-error {
  background: rgba(200, 40, 40, .10);
  color: #a11d1d;
}

@media (max-width: 1180px) {
  .boletin-destacado,
  .boletin-destacado.boletin-ancho {
    grid-template-columns: minmax(0, 1fr);
    width: min(1580px, calc(100% - 32px));
    margin-bottom: 34px;
  }
  .boletin-destacado {
    width: min(1180px, calc(100% - 44px));
  }
}

/* ══ Bloque de cierre ═══════════════════════════════════════════════
   Antes era una banda a todo el ancho con el mismo azul que el pie, así
   que los dos se leían como una sola mancha oscura de media pantalla: no
   había forma de saber dónde acababa uno y empezaba el otro.

   Ahora es una pieza contenida, con su radio y su margen. El fondo de la
   página vuelve a aparecer por debajo y el pie queda claramente separado.
   Vale igual en la portada, donde lo que sigue son los logos.

   Y el fondo deja de ser una fotografía de archivo —un apretón de manos,
   el cliché de la categoría— para usar el lenguaje de la marca: el azul
   profundo, los lóbulos del degradado y el motivo de líneas del dossier,
   que el cliente pidió expresamente mantener. Además no descarga nada. */

.final-cta {
  position: relative;
  width: min(1580px, calc(100% - 96px));
  margin: 0 auto;
  display: block;
  overflow: hidden;
  /* Mas alto por pedido de Maude (20/08/2026): la pieza cierra la pagina y
     con 320px quedaba baja al lado del resto de secciones. */
  min-height: 400px;
  padding: 0;
  border-radius: var(--radius-lg);
  background: var(--primary-950);
  color: white;
  box-shadow: 0 30px 70px rgba(10,18,48,.22);
}

/* El canto superior, con el degradado de marca. Es lo que remata la pieza
   y la separa de lo que viene encima. */
.final-cta::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  z-index: 5;
  height: 3px;
  background: var(--brand-gradient);
}

/* El motivo de líneas y los lóbulos de color, los dos en el mismo
   pseudoelemento para no añadir otra capa al apilado. */
.final-cta-image {
  position: absolute;
  inset: 0;
  z-index: 0;
  background:
    repeating-linear-gradient(115deg,
      rgba(255,255,255,.045) 0 1px,
      transparent 1px 22px),
    radial-gradient(52% 78% at 88% 18%, rgba(0,180,255,.30), transparent 68%),
    radial-gradient(46% 70% at 68% 96%, rgba(25,224,194,.20), transparent 70%),
    radial-gradient(70% 90% at 8% 30%, rgba(41,98,255,.16), transparent 72%);
}

/* Velo que despeja la zona del texto. El degradado del fondo es fuerte a la
   derecha y el titular vive a la izquierda. */
.final-cta::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background:
    linear-gradient(90deg, rgba(10,18,48,.94) 0%, rgba(10,18,48,.86) 34%, rgba(10,18,48,.52) 62%, rgba(10,18,48,.24) 100%);
}

/* El lienzo del motivo animado. Va por encima del degradado de respaldo y
   por debajo del velo y del texto. */
.final-cta-lienzo {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: block;
  width: 100%;
  height: 100%;
}

.final-cta-copy {
  position: relative;
  z-index: 3;
  max-width: 820px;
  padding: clamp(52px, 6vw, 80px);
  background: transparent;
}

/* Un velo oscuro por detras del texto, degradado hacia la derecha.
 *
 * Hace falta porque la malla animada se subio de intensidad (20/08/2026) y
 * las lineas mas claras llegan a una luminancia de 0,25: donde una pasa por
 * detras de una letra, el blanco baja a 3,47:1. Alcanza para el titular, que
 * es grande, pero no para el parrafo de 19px, que pide 4,5:1.
 *
 * Se resuelve aqui y no bajando la intensidad de la malla porque el pedido
 * era justamente que se viera mas movimiento: el velo protege la mitad
 * izquierda, donde esta el texto, y deja el motivo entero a la vista en la
 * derecha, que es donde se aprecia.
 *
 * Y lo hace sin depender del fotograma: por muy claro que pase el motivo por
 * debajo, el suelo de contraste esta garantizado.
 *
 * Las opacidades salen de un calculo, no de mirar: se compone el tono mas
 * claro de la paleta negativa —`claro: [150, 226, 255]`, que sin velo da
 * 1,44:1 contra el blanco— con el velo, y se busca el alfa minimo que deja el
 * resultado por encima de 4,5:1, el minimo para texto normal:
 *
 *     alfa 0,44 -> 4,08:1     no alcanza
 *     alfa 0,50 -> 4,85:1     justo
 *     alfa 0,52 -> 5,15:1     el que se usa, con margen
 *
 * Se calcula en vez de medirse en una captura porque el fondo se mueve: una
 * captura dice lo que pasaba en ese fotograma, no lo que puede pasar. El
 * calculo acota el peor caso posible.
 *
 * El 82% es donde termina la linea de texto mas larga; a partir de ahi el velo
 * cae y el motivo se ve entero. */
.final-cta-copy::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: 0 auto 0 0;
  width: min(100%, 900px);
  background: linear-gradient(
    90deg,
    rgba(6, 11, 30, .62) 0%,
    rgba(6, 11, 30, .54) 60%,
    rgba(6, 11, 30, .52) 82%,
    rgba(6, 11, 30, 0) 100%
  );
  pointer-events: none;
}
.final-cta-copy > * {
  position: relative;
  z-index: 4;
}
.final-cta h2, .final-cta p { color: white; }

/* Tipografia propia y no la del `h2` general: esta pieza es el cierre de la
   pagina y Maude la pidio mas grande. Arriba llega a 50px contra los 40 del
   resto. */
.final-cta h2 {
  max-width: 720px;
  margin-top: 16px;
  font-size: clamp(32px, 3.4vw, 50px);
  line-height: 1.14;
}

/* El `p` global lleva `margin: 0`, asi que el parrafo salia pegado al
   titular: era lo que Maude marcaba como «la pregunta y el parrafo estan
   bastante juntos». */
.final-cta p {
  max-width: 640px;
  margin-top: 20px;
  font-size: clamp(17px, 1.25vw, 19px);
  line-height: 1.7;
  opacity: .84;
}

.final-cta .eyebrow { color: rgba(255,255,255,.9); }
.final-cta .actions { margin-top: 34px; }

/* El aire alrededor.

   Va en la propia pieza y no en quien la usa, porque el bloque se reutiliza
   en el pie de todas las secciones y en medio de la portada: si el margen
   dependiera del contexto, cada sitio tendría que acordarse de ponerlo. */
.final-cta {
  margin-block: clamp(48px, 6vw, 88px);
}

/* En el pie no hace falta el de abajo: el propio pie ya trae su relleno y
   se acumularían los dos. */
.final-cta + .site-footer {
  margin-top: 0;
}
.site-footer {
  padding: 44px max(48px, calc((100vw - 1580px) / 2)) 30px;
  background: var(--primary-950);
  color: rgba(255,255,255,.72);
}
/*
 * La marca a la izquierda y las columnas de enlaces a su derecha.
 *
 * `auto-fit` y no `repeat(5, ...)`: eran cinco pistas contadas a mano cuando
 * Servicios estaba en el menú, y desde que se escondió —19/08/2026— sólo hay
 * cuatro columnas para cinco huecos. La quinta se quedaba vacía y dejaba un
 * boquete de 213 px a la derecha del pie, que es lo que se veía. Con `auto-fit`
 * las pistas vacías se colapsan y las que hay reparten el ancho, así que el
 * día que Servicios vuelva al menú tampoco hay que tocar nada.
 */
.footer-grid {
  display: grid;
  grid-template-columns: minmax(240px, 1.15fr) repeat(auto-fit, minmax(132px, 1fr));
  gap: 38px;
}
.footer-brand {
  display: inline-flex;
  width: fit-content;
  margin-bottom: 16px;
}
.footer-brand img {
  width: 220px;
}
.footer-brand .brand-tagline {
  margin-top: 7px;
  color: rgba(255,255,255,.48);
  line-height: 1.35;
}
.site-footer h3 { color: white; margin-bottom: 13px; font-size: 13px; text-transform: uppercase; }
.site-footer a, .site-footer p { display: block; margin-bottom: 9px; color: rgba(255,255,255,.72); font-size: 13px; }
.site-footer p { max-width: 310px; }
/* Al pie de la columna de contacto, alineadas a la izquierda como el resto de
   esa columna. Se probaron colgando del logotipo —desequilibraban la fila— y en
   una fila propia centrada, que alargaba el pie. Aqui aprovechan el alto que
   las otras columnas ya ocupan y no suman ninguno. */
.social-links {
  display: flex;
  gap: 10px;
  margin-top: 16px;
}
.social-links a {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  margin: 0;
  border: 1px solid rgba(255,255,255,.24);
  border-radius: 50%;
  color: white;
}
.social-links a:hover {
  background: rgba(255,255,255,.08);
}

/* Red sin direccion todavia. Se ve para poder revisar el bloque, pero apagada
   y sin cursor de enlace: no promete un clic que no existe. Solo aparece
   fuera de produccion. */
.social-links .sin-direccion {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border: 1px dashed rgba(255, 255, 255, .18);
  border-radius: 50%;
  color: rgba(255, 255, 255, .38);
}
.footer-contact p {
  display: grid;
  grid-template-columns: 18px 1fr;
  gap: 8px;
  max-width: 330px;
}
.footer-contact i {
  color: rgba(255,255,255,.78);
}
/* Tres bloques en una linea: copyright, quien lo desarrolla y las politicas.
   Las columnas de los lados miden lo mismo —`flex: 1`— para que el credito
   quede centrado de verdad en la fila y no en el hueco que le dejen. Con
   `space-between` a secas se corria hacia el lado del texto mas corto. */
.legal-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  margin-top: 42px;
  padding-top: 22px;
  border-top: 1px solid rgba(255,255,255,.14);
  font-size: 12px;
}
.legal-row > span { flex: 1; }
.legal-row nav { display: flex; flex: 1; justify-content: flex-end; gap: 24px; }

/* El credito de quien desarrolla.
   La etiqueta va encima y muy pequena: lo que tiene que leerse es el
   logotipo, no la palabra. */
.footer-autoria {
  display: grid;
  justify-items: center;
  gap: 4px;
  text-align: center;
}

/* En caja normal, no en versalitas: en mayusculas y con letra espaciada
   ocupaba mas y pesaba mas que el logotipo que va debajo, que es lo que tiene
   que leerse. Se sube algo la opacidad porque a nueve pixeles y en gris se
   perdia. */
.footer-autoria span {
  color: rgba(255, 255, 255, .45);
  font-size: 9px;
  letter-spacing: .01em;
}

.footer-autoria a {
  display: inline-flex;
  align-items: center;
  color: rgba(255, 255, 255, .72);
  text-decoration: none;
}

/* A color, pero bajado de tono; a color entero al pasar por encima.
   Se probo antes apagarlo a gris del todo y a veintiseis pixeles el logotipo
   perdia sus dos colores y quedaba como una mancha ilegible. Con la saturacion
   al 55 % se sigue leyendo que es verde y magenta, sin gritar al lado de la
   marca del cliente, que es de quien es el sitio. */
.footer-autoria img {
  display: block;
  height: 30px;
  width: auto;
  filter: saturate(.55);
  opacity: .82;
  transition: filter .25s ease, opacity .25s ease;
}

.footer-autoria a:hover img,
.footer-autoria a:focus-visible img {
  filter: saturate(1);
  opacity: 1;
}

/* En pantalla estrecha la fila se apila y el credito queda en medio igual.

   Desde 1180 y no desde 720: a 1000 px los tres bloques —copyright, credito y
   politicas— suman mas que el ancho disponible, y como las columnas de los
   lados miden lo mismo por `flex: 1`, lo que cedia era el hueco de las
   politicas: los tres enlaces se partian en dos lineas cada uno. */
@media (max-width: 1180px) {
  .legal-row {
    flex-direction: column;
    align-items: center;
    gap: 18px;
    text-align: center;
  }

  .legal-row > span,
  .legal-row nav { flex: none; }

  .legal-row nav { justify-content: center; flex-wrap: wrap; }
}
.legal-row a { margin: 0; }

/* ══ Vídeo de YouTube con carátula ═════════════════════════════════
   No se carga YouTube hasta que alguien pulsa: ni cookies de Google para
   quien no mira el vídeo, ni medio megabyte de reproductor en cada visita.
   El botón es un enlace de verdad, así que sin JavaScript lleva a YouTube
   en vez de dejar un hueco. */

.video-yt {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius-lg);
  background: var(--primary-950);
  box-shadow: var(--soft-shadow);
  /* Reservado antes de que llegue la miniatura: sin esto el texto de debajo
     salta cuando carga, que es CLS puro. */
  aspect-ratio: 16 / 9;
}

.video-yt-caratula {
  display: block;
  width: 100%;
  height: 100%;
}

.video-yt img {
  width: 100%;
  height: 100%;
  /* La miniatura de YouTube viene en 4:3 con dos bandas negras. Recortada al
     16:9 del contenedor se ven sólo los píxeles del vídeo. */
  object-fit: cover;
  transition: transform .4s ease, filter .3s ease;
}

.video-yt-play {
  position: absolute;
  z-index: 2;
  top: 50%;
  left: 50%;
  display: grid;
  place-items: center;
  width: 74px;
  height: 74px;
  border-radius: 50%;
  background: var(--brand-gradient);
  color: var(--primary-950);
  font-size: 34px;
  transform: translate(-50%, -50%);
  transition: transform .25s ease, box-shadow .25s ease;
  box-shadow: 0 12px 30px rgba(10, 18, 48, .38);
}

.video-yt-etiqueta {
  position: absolute;
  z-index: 2;
  left: 18px;
  bottom: 18px;
  padding: 8px 14px;
  border-radius: var(--radius-pill);
  background: rgba(10, 18, 48, .82);
  color: white;
  font-size: 12px;
  font-weight: 850;
}

.video-yt-caratula:hover img,
.video-yt-caratula:focus-visible img {
  transform: scale(1.03);
  filter: brightness(.92);
}
.video-yt-caratula:hover .video-yt-play,
.video-yt-caratula:focus-visible .video-yt-play {
  transform: translate(-50%, -50%) scale(1.08);
}

/* Cuando el script sustituye la carátula por el reproductor. */
.video-yt iframe {
  width: 100%;
  height: 100%;
  border: 0;
}

@media (prefers-reduced-motion: reduce) {
  .video-yt img,
  .video-yt-play { transition: none; }
}

/* ══ Galería que pasa sola ═════════════════════════════════════════
   Maude la pidió girando sola. Lo hace CSS y no JavaScript: son tres
   imágenes como mucho y basta una animación de opacidad con los turnos
   escalonados. Así funciona aunque el script falle, no ocupa el hilo
   principal y `prefers-reduced-motion` la para sin una línea de código.

   El número de fotos va en `data-fotos` y no sólo en una variable CSS
   porque **un selector de fotograma no admite `calc()`**: los porcentajes
   de un `@keyframes` tienen que ser literales, así que hace falta un juego
   por cada cantidad. Como el tope son tres, son dos juegos. */

.galeria-destino {
  position: relative;
  display: grid;
  margin-top: clamp(24px, 3vw, 40px);
  overflow: hidden;
  border-radius: var(--radius-lg);
  background: var(--muted-surface);
  box-shadow: var(--soft-shadow);
  aspect-ratio: 3 / 2;
}

/* Todas apiladas en la misma celda: la rejilla de una sola área las
   superpone sin sacarlas del flujo, así que el contenedor sigue midiendo lo
   que mide una foto. */
.galeria-destino img {
  grid-area: 1 / 1;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* El turno de cada una: cinco segundos por foto. */
.galeria-destino[data-fotos="2"] img,
.galeria-destino[data-fotos="3"] img {
  opacity: 0;
  animation-delay: calc(var(--turno) * 5s);
  animation-iteration-count: infinite;
}

.galeria-destino[data-fotos="2"] img {
  animation-name: galeria-de-dos;
  animation-duration: 10s;
}

.galeria-destino[data-fotos="3"] img {
  animation-name: galeria-de-tres;
  animation-duration: 15s;
}

/* Visible su mitad del ciclo, con el cruce corto a cada lado. */
@keyframes galeria-de-dos {
  0%   { opacity: 0; }
  4%   { opacity: 1; }
  46%  { opacity: 1; }
  50%  { opacity: 0; }
  100% { opacity: 0; }
}

/* Y su tercio, cuando son tres. */
@keyframes galeria-de-tres {
  0%   { opacity: 0; }
  3%   { opacity: 1; }
  30%  { opacity: 1; }
  33%  { opacity: 0; }
  100% { opacity: 0; }
}

/* La primera se ve fija: quien pide menos movimiento no se queda mirando un
   recuadro vacío ni recibe una imagen que cambia sola.

   Los selectores repiten el `[data-fotos]` **a propósito**. Sin él esto pesa
   menos que la regla que enciende la animación —una clase con atributo gana a
   una clase sola— y el `animation: none` no se aplicaba: la galería seguía
   girando para quien había pedido que no se moviera nada. Se veía midiendo el
   `animation-name` sobre la página servida, no mirándola: la opacidad inicial
   es la misma en los dos casos y el fallo sólo aparece cinco segundos
   después. */
@media (prefers-reduced-motion: reduce) {
  .galeria-destino[data-fotos] img { animation: none; opacity: 0; }
  .galeria-destino[data-fotos] img:first-child { opacity: 1; }
}

/* La columna de apoyo de un destino: sus ventajas y su vídeo.

   El vídeo iba debajo del texto, centrado y solo a mitad de página, y partía
   la lectura en dos: había que pasarlo de largo para seguir leyendo. Al lado
   del texto acompaña, que es lo que un vídeo hace en una ficha. Lo pidió
   Maude el 28/08/2026 mirando la página de Málaga. */
.destino-lateral {
  display: grid;
  align-content: start;
  gap: clamp(18px, 2vw, 26px);
}

/* Las fotografías dentro de esa columna.

   Ocupaban el ancho entero de la página en 3:2: en un portátil son casi
   ochocientos píxeles de alto, una sola foto llenando la pantalla y
   empujando las formaciones —que es a lo que se viene— fuera del alcance.
   Y encima dejaban el hueco de al lado del texto en blanco.

   4:3 y no 3:2 porque dos de las tres fotos que subió Maude para Málaga son
   verticales: en una caja más apaisada se recortaban a una franja del centro. */
.destino-lateral .galeria-destino {
  margin-top: 0;
  aspect-ratio: 4 / 3;
}

/* Apilada, la misma forma que los vídeos de la página.

   Al lado del texto va en 4:3 porque dos de las tres fotos de Málaga son
   verticales y una caja apaisada las recorta más. Apilada esa razón desaparece
   —ocupa el ancho entero— y lo que se nota es lo otro: en 4:3 medía 678 px de
   alto mientras el vídeo de justo arriba medía 509, y las dos piezas seguidas
   se veían de distinto tamaño. */
@media (max-width: 1180px) {
  .destino-lateral .galeria-destino { aspect-ratio: 16 / 9; }
}

/* Los motivos a todo lo ancho, debajo de la fila.

   Es donde los quiso Maude el 28/08/2026: en la columna estrecha eran una
   lista larga y fina al lado de un texto que ya había terminado, con media
   fila en blanco. */
/* La fila que cierra la ciudad: sus ventajas y su vídeo.

   El vídeo estuvo debajo de la galería, en la columna de la derecha, y esa
   columna acababa midiendo casi el doble que el texto: media página en blanco
   a la izquierda. Aquí ocupa el hueco que dejaban las ventajas.

   El número de columnas lo decide el HTML y no `:has()`: es el mismo recurso
   que usan la galería con `data-fotos` y los bloques con `data-bloques`, y no
   depende de que el navegador soporte el selector. */
.destino-cierre {
  display: grid;
  align-items: start;
  gap: clamp(18px, 2vw, 28px);
  margin-top: clamp(28px, 3vw, 44px);
}

/* El vídeo a la izquierda y las ventajas a la derecha, como las quiso Maude
   el 28/08/2026. La lista se queda con casi el doble, que es lo que necesita
   para ir a dos columnas sin partir cada ventaja en tres renglones.

   `stretch` es lo que hace que las dos piezas empiecen y acaben a la misma
   altura: la tarjeta manda —mide lo que mide su texto— y el vídeo se estira
   hasta ella. Por eso pierde aquí su proporción fija: la miniatura ya está
   recortada con `object-fit`, así que se adapta sin deformarse, y el hueco lo
   sigue reservando la tarjeta de al lado. */
.destino-cierre[data-cierre="video-y-ventajas"] {
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.85fr);
  align-items: stretch;
}

.destino-cierre[data-cierre="video-y-ventajas"] .video-yt {
  aspect-ratio: auto;
  min-height: 240px;
}

/* Un vídeo sin ventajas al lado no se estira a toda la fila: en una pantalla
   ancha ocuparía media página, y un vídeo es un apoyo del texto. */
.destino-cierre[data-cierre="solo-video"] {
  justify-items: center;
}
.destino-cierre[data-cierre="solo-video"] .video-yt {
  width: 100%;
  max-width: 560px;
}

/* Apilados, el vídeo recupera su proporción y su tope de ancho.

   El `min-height` hay que quitarlo aquí, y no es un detalle: con la proporción
   16:9 puesta otra vez, una altura mínima de 240 px obliga a un ancho de 427,
   y en un móvil de 390 eso es la página entera desbordada hacia el lado. Se
   vio midiendo el documento a 390 px, no mirando la página. */
@media (max-width: 1180px) {
  .destino-cierre[data-cierre="video-y-ventajas"] {
    grid-template-columns: 1fr;
    align-items: start;
    justify-items: center;
  }
  /* Sin tope de ancho: apilado va debajo de la tarjeta de ventajas, que ocupa
     la columna entera, y a 560 px se quedaba corto y descentrado respecto a
     ella y respecto al resto de piezas de la página. */
  .destino-cierre[data-cierre="video-y-ventajas"] .video-yt {
    width: 100%;
    min-height: 0;
    aspect-ratio: 16 / 9;
  }
}

/* Dos columnas, y con `columns` en vez de una rejilla.

   Dos son las mismas dos mitades que la fila de arriba —el texto y la
   fotografía—, que es lo que Maude pidió que se cubriera. Con `auto-fit` se
   partía en tres en un portátil y en cuatro en un monitor grande, y a esa
   anchura cada ventaja son dos palabras y un salto de línea.

   Y no es una rejilla porque en una rejilla la fila entera mide lo que su
   elemento más alto: una ventaja de dos líneas a la derecha abría un hueco a
   la izquierda enfrente de ella. `columns` reparte el texto seguido, sin
   filas, así que no hay huecos. Se lee hacia abajo y luego a la derecha, que
   es como se lee una lista a dos columnas. */
/* Un poco más de aire abajo que a los lados: la lista acaba a distinta altura
   en cada columna y sin ese margen el renglón más largo quedaba pegado al
   borde de la tarjeta. */
.destino-motivos-ancho {
  padding-bottom: clamp(30px, 3vw, 44px);
}

.destino-motivos-ancho .destination-benefits {
  display: block;
  columns: 2;
  column-gap: clamp(28px, 4vw, 64px);
}

/* Una ventaja no se parte entre las dos columnas. */
.destino-motivos-ancho .destination-benefits li {
  margin-bottom: 12px;
  break-inside: avoid;
}
.destino-motivos-ancho .destination-benefits li:last-child { margin-bottom: 0; }

@media (max-width: 720px) {
  .destino-motivos-ancho .destination-benefits { columns: 1; }
}

/* Con el título centrado sobre las dos columnas se leería como una portada;
   alineado a la izquierda sigue siendo el encabezado de una lista. */
.destino-motivos-ancho h2 {
  font-size: clamp(22px, 1.8vw, 28px);
}

/* La provincia, encabezando la página de una de sus ciudades.

   Sobre fondo suave y con la marca al canto para que se lea como contexto
   —dónde está esta ciudad— y no como el texto de la ciudad. Si fuese igual
   que el resto, quien llega no sabría cuál de los dos está leyendo. */
.destino-provincia-caja {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, .38fr) minmax(0, 1fr);
  gap: clamp(20px, 3vw, 44px);
  overflow: hidden;
  padding: clamp(26px, 3vw, 40px);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--soft);
}

.destino-provincia-caja::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 4px;
  background: linear-gradient(180deg, var(--turquoise), var(--cyan), var(--electric-blue));
}

.destino-provincia-caja h2 {
  margin: 6px 0 0;
  color: var(--primary-950);
  font-size: clamp(24px, 2.2vw, 34px);
  line-height: 1.15;
}

.destino-provincia-caja p {
  margin: 0 0 20px;
  max-width: 68ch;
  color: var(--muted);
  font-size: 15.5px;
  line-height: 1.65;
}

/* Las fotografías dentro de la banda: pegadas al titular y más contenidas
   que en una sección propia, que aquí acompañan al texto y no lo encabezan. */
.destino-provincia-caja .galeria-destino {
  margin-top: 18px;
  aspect-ratio: 4 / 3;
}

@media (max-width: 1180px) {
  .destino-provincia-caja { grid-template-columns: minmax(0, 1fr); }
  .destino-provincia-caja .galeria-destino { aspect-ratio: 16 / 9; }
}

/* Las otras ciudades de la provincia. */
.destino-hermanas-lista {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 20px;
}

/* La cabecera de un destino reparte sus dos columnas igual que el cuerpo.

   El resto de fichas usa `1fr .65fr` con 36 px de hueco, y el cuerpo de un
   destino `1.1fr .9fr` con 48. Al apilarse la página quedaban dos anchos
   distintos: la fotografía de la cabecera empezaba 58 px más a la derecha que
   el vídeo de la provincia justo debajo, y se leía como un descuadre. Lo vio
   Maude el 28/08/2026. Sólo se toca la cabecera del destino: las de noticia,
   proyecto y formación no tienen debajo una columna con la que cuadrar. */
.destino-hero {
  grid-template-columns: minmax(0, 1.1fr) minmax(0, .9fr);
  gap: 48px;
}

/* La galería cuando hace de cabecera: ocupa el hueco de la imagen a la que
   sustituye, con el mismo encuadre panorámico del resto de fichas. */
.detail-hero .galeria-destino {
  margin-top: 0;
  height: 100%;
  aspect-ratio: auto;
  min-height: 320px;
}

/* Apilada, con la forma del vídeo que va justo debajo.

   Al lado del texto se estira para llenar la fila, que es lo que hacía la
   imagen a la que sustituye. Apilada no hay fila que llenar: la altura salía
   de la proporción de la propia fotografía y cambiaba con el ancho —a 1000 px
   quedaba más alta que el vídeo y a 720 más baja—. Con el 16:9 del vídeo las
   dos piezas miden exactamente lo mismo a cualquier ancho, que es lo que
   pidió Maude el 28/08/2026. */
@media (max-width: 1180px) {
  .detail-hero .galeria-destino {
    height: auto;
    min-height: 0;
    aspect-ratio: 16 / 9;
  }
}

/* La provincia dentro de la ficha de la ciudad: se separa de lo que viene
   debajo con una línea, para que se lea dónde acaba lo de la provincia y
   empieza lo de la ciudad. */
.provincia-completa {
  padding-bottom: clamp(28px, 3vw, 44px);
  border-bottom: 1px solid var(--border);
}

.provincia-descubre-titulo {
  margin: clamp(28px, 3vw, 44px) 0 0;
  color: var(--primary-950);
  font-size: clamp(22px, 2vw, 30px);
  line-height: 1.2;
}

/* Los bloques de «descubre la provincia». */
.provincia-bloques {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr));
  gap: clamp(18px, 2vw, 28px);
  margin-top: clamp(20px, 2.4vw, 32px);
}

/* Cuatro en una rejilla de tres dejaban el cuarto solo en su fila, y se leía
   como si faltara uno. De dos en dos se lee como lo que es. */
.provincia-bloques[data-bloques="4"] {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (max-width: 720px) {
  .provincia-bloques[data-bloques="4"] { grid-template-columns: 1fr; }
}

.provincia-bloque {
  position: relative;
  overflow: hidden;
  padding: clamp(22px, 2.2vw, 30px);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: white;
  transition: transform .18s ease, border-color .18s ease, box-shadow .18s ease;
}

/* El filete de marca del canto superior, que nace al pasar por encima.

   Es el gesto que ya hacen las tarjetas de audiencia de la portada, y aquí
   cumple lo mismo: señalar cuál de las cuatro se está leyendo en una rejilla
   donde todas se parecen. Va con el degradado del manual —teal, cian, azul
   eléctrico— que es lo que las ata al resto del sitio.

   **Se queda en resaltado y no promete un enlace**: estas tarjetas no llevan
   a ninguna parte, así que ni cambian el cursor ni suben lo que sube una
   tarjeta que sí se puede pulsar. */
.provincia-bloque::before {
  content: "";
  position: absolute;
  inset: 0 auto auto 0;
  width: 0;
  height: 3px;
  background: var(--brand-gradient);
  transition: width .38s cubic-bezier(.22, .61, .36, 1);
}

.provincia-bloque:hover {
  transform: translateY(var(--alza-tarjeta));
  border-color: var(--borde-hover);
  box-shadow: var(--sombra-hover);
}
.provincia-bloque:hover::before { width: 100%; }

@media (prefers-reduced-motion: reduce) {
  .provincia-bloque,
  .provincia-bloque::before { transition: none; }
  .provincia-bloque:hover { transform: none; }
}
.provincia-bloque h3 {
  margin: 0 0 10px;
  color: var(--primary-950);
  font-size: 19px;
  line-height: 1.25;
}
.provincia-bloque p {
  margin: 0;
  color: var(--muted);
  font-size: 15px;
  line-height: 1.65;
}

/* ══ Cuerpo de artículo ═══════════════════════════════════════════════
   Lo que escribe el editor enriquecido del CRM: fichas de noticia, de
   proyecto, de formación y de servicio. Hasta ahora no tenía ni una regla,
   así que salía con los estilos por defecto del navegador y a 1.580px de
   ancho, que son unos 190 caracteres por línea. Se lee fatal.

   No se puede poner clases a estas etiquetas: las genera el editor. Todo
   va por selector de descendencia. */

/* La ficha en dos columnas.

   El contenedor es más estrecho que el de la cabecera —1.180 frente a
   1.580— a propósito: con el ancho de la cabecera, el texto de 780px se
   quedaba solo en medio de un campo enorme. Aquí el par texto + lateral lo
   llena entero. */
/* El mismo contenedor que el resto de la pagina.
 *
 * Medía 1180px centrados mientras la migaja, el titular y «Otras
 * publicaciones» usaban el contenedor de 1580: dos alineaciones distintas en
 * la misma pagina. El cuerpo del articulo arrancaba unos 160px a la derecha de
 * todo lo demas y se leia como si algo lo estuviera cortando.
 *
 * La medida de lectura la sigue poniendo `.article-body` con su `max-width`;
 * lo que cambia es donde empieza esa columna. */
.article-layout {
  width: min(1580px, calc(100% - 96px));
  display: grid;
  grid-template-columns: minmax(0, 1fr) 300px;
  gap: clamp(48px, 6vw, 100px);
  align-items: start;
}

/* Dentro de la maqueta el cuerpo va pegado a la izquierda, no centrado en su
   columna: es lo que lo alinea con el titular de arriba. Suelto —en las fichas
   de formacion y de servicio, que no llevan columna lateral— sigue centrado. */
.article-layout > .article-body {
  margin-inline: 0;
}
.article-aside {
  /* Acompaña la lectura en lugar de perderse arriba. El desplazamiento
     suave ya está activado en `html`. */
  position: sticky;
  top: 132px;
  display: grid;
  gap: 26px;
  font-size: 14px;
}
.article-index h2 {
  margin: 0 0 12px;
  color: var(--muted);
  font-size: 11px;
  font-weight: 900;
  letter-spacing: .16em;
  text-transform: uppercase;
}
.article-index ol {
  margin: 0;
  padding: 0;
  list-style: none;
  border-left: 1px solid var(--border);
}
.article-index li { margin: 0; }
.article-index a {
  display: block;
  padding: 8px 0 8px 16px;
  margin-left: -1px;
  border-left: 2px solid transparent;
  color: var(--muted);
  line-height: 1.4;
  text-decoration: none;
  transition: color .16s ease, border-color .16s ease;
}
.article-index a:hover {
  border-left-color: var(--accent-600);
  color: var(--primary-950);
}
.article-facts {
  display: grid;
  gap: 14px;
  margin: 0;
  padding: 20px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: white;
}
.article-facts dt {
  color: var(--muted);
  font-size: 11px;
  font-weight: 900;
  letter-spacing: .14em;
  text-transform: uppercase;
}
.article-facts dd {
  margin: 4px 0 0;
  color: var(--primary-950);
  font-weight: 800;
}
.article-back {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--primary-900);
  font-weight: 800;
  text-decoration: none;
}
.article-back:hover { color: var(--electric-blue); }

.article-body {
  /* Medida de lectura: entre 65 y 75 caracteres por línea. Alineado a la
     izquierda y no centrado: en la ficha de formación arranca justo debajo de
     unas tarjetas que ocupan todo el ancho, y centrado se leía como un bloque
     descolgado, con trescientos píxeles de sangría que no tenía nada de
     arriba. Dentro de `.article-layout` su columna mide justo esto, así que
     allí no cambia nada. */
  max-width: 780px;
  color: var(--text);
  font-size: 17px;
  line-height: 1.75;
}
/*
 * Cuando el cuerpo es la propia seccion, se alinea a la izquierda.
 *
 * `.section` centra con `margin: 0 auto` y `.article-body` limita el ancho a la
 * medida de lectura: juntas dejaban el texto centrado en la pagina, con
 * trescientos pixeles de sangria que no tenia nada de arriba. En la ficha de
 * formacion eso cae justo debajo de unas tarjetas a todo el ancho y se leia
 * como un bloque descolgado.
 *
 * El margen izquierdo es el mismo calculo que usa `.section.soft`, asi que el
 * texto arranca exactamente donde arranca el resto de la pagina.
 */
.section.article-body {
  width: min(780px, calc(100% - 96px));
  margin-left: max(48px, calc((100vw - 1580px) / 2));
  margin-right: auto;
}

.article-body > :first-child { margin-top: 0; }
.article-body > :last-child { margin-bottom: 0; }
.article-body p {
  margin: 0 0 20px;
}
.article-body h2 {
  margin: 44px 0 14px;
  color: var(--primary-950);
  font-size: clamp(23px, 2.2vw, 28px);
  font-weight: 800;
  line-height: 1.25;
}
.article-body h3 {
  margin: 32px 0 10px;
  color: var(--primary-950);
  font-size: 20px;
  font-weight: 800;
  line-height: 1.3;
}
.article-body ul,
.article-body ol {
  margin: 0 0 20px;
  padding-left: 24px;
}
.article-body li {
  margin-bottom: 10px;
  padding-left: 4px;
}
.article-body li::marker {
  color: var(--accent-600);
  font-weight: 800;
}
.article-body strong {
  color: var(--primary-950);
  font-weight: 800;
}
.article-body a {
  color: var(--electric-blue);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.article-body a:hover { text-decoration-thickness: 2px; }
.article-body blockquote {
  margin: 28px 0;
  padding: 4px 0 4px 22px;
  border-left: 3px solid var(--accent-700);
  color: var(--primary-950);
  font-size: 19px;
  font-style: normal;
  line-height: 1.6;
}
.article-body img {
  max-width: 100%;
  height: auto;
  margin: 28px 0;
  border-radius: var(--radius-md);
}
.article-body hr {
  margin: 36px 0;
  border: 0;
  border-top: 1px solid var(--border);
}
/* El aviso emergente.

   Se escondia solo con `translateY(140%)`, y ese 140 % es de su propia
   altura: vacio mide 28 px, asi que bajaba 39 px cuando necesitaba bajar 50
   —su alto mas los 22 px que lo separan del borde— y asomaba una franja por
   la esquina inferior derecha. No se veia en la portada por casualidad: alli
   el fondo de esa esquina es el mismo Azul Profundo que el aviso. En
   Formaciones, sobre claro, se veia perfectamente.

   Ahora la opacidad hace el trabajo y el desplazamiento solo acompana, asi
   que da igual cuanto mida el contenido. */
/* ── Aviso de cookies ────────────────────────────────────────────

   Va en posicion fija y nunca en el flujo: un aviso que empuja la pagina hacia
   abajo al aparecer es desplazamiento de contenido puro, y es de las cosas que
   Google mide.

   Fondo azul profundo de marca. Contraste sobre el:
     texto blanco ........ 18,4:1
     enlace turquesa ..... 10,9:1
     boton claro ......... 18,4:1 (navy sobre blanco)

   `padding-bottom` con `safe-area-inset` para los telefonos con barra de
   gestos: sin eso el boton queda debajo de la franja del sistema. */

.aviso-cookies {
  position: fixed;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 60;
  padding: 16px;
  padding-bottom: calc(16px + env(safe-area-inset-bottom, 0px));
  pointer-events: none;
}

.aviso-cookies__caja {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px 22px;
  max-width: 1180px;
  margin: 0 auto;
  padding: 18px 22px;
  border-radius: var(--radius-md);
  background: var(--primary-950);
  box-shadow: 0 18px 40px rgba(10, 18, 48, .28);
  pointer-events: auto;

  /* Estado de partida de la entrada. El elemento sale con `hidden`, asi que
     esto solo se ve durante la transicion. */
  transform: translateY(calc(100% + 24px));
  opacity: 0;
  transition: transform .32s cubic-bezier(.22, .68, .36, 1), opacity .32s ease;
}

.aviso-cookies.visible .aviso-cookies__caja {
  transform: translateY(0);
  opacity: 1;
}

.aviso-cookies__texto {
  flex: 1 1 460px;
  margin: 0;
  color: white;
  font-size: 14.5px;
  line-height: 1.6;
}

.aviso-cookies__texto a {
  color: var(--turquoise);
  text-decoration: underline;
  text-underline-offset: 3px;
  white-space: nowrap;
}
.aviso-cookies__texto a:hover { color: white; }

.aviso-cookies__acciones {
  display: flex;
  flex: 0 0 auto;
  gap: 10px;
}

/* Mismo ancho minimo en los dos botones: en modo consentimiento, rechazar y
   aceptar tienen que costar lo mismo, y un boton mas estrecho ya es una
   diferencia de coste. */
.aviso-cookies__accion { min-width: 130px; }

/* Quien tiene el aviso abierto no puede recibir un toast encima. El alto real
   lo mide el JavaScript, y 96px es solo el valor de respaldo. */
.con-aviso-cookies .toast {
  bottom: calc(22px + var(--alto-aviso, 96px));
}

@media (max-width: 720px) {
  .aviso-cookies { padding: 12px; padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px)); }
  .aviso-cookies__caja { padding: 16px 18px; gap: 14px; }
  .aviso-cookies__texto { flex-basis: 100%; font-size: 14px; }

  /* A ancho completo y repartidos: en un telefono es el pulgar el que decide,
     y dos botones del mismo tamano son dos opciones del mismo peso. */
  .aviso-cookies__acciones { flex: 1 1 100%; }
  .aviso-cookies__accion { flex: 1; min-width: 0; min-height: 48px; }
}

/* Quien pide movimiento reducido lo recibe puesto, no deslizandose. */
@media (prefers-reduced-motion: reduce) {
  .aviso-cookies__caja { transition: opacity .01ms; transform: none; }
  .aviso-cookies.visible .aviso-cookies__caja { transform: none; }
}

.toast {
  position: fixed;
  right: 22px;
  bottom: 22px;
  transform: translateY(140%);
  max-width: 360px;
  padding: 14px 16px;
  border-radius: var(--radius-sm);
  background: var(--primary-950);
  color: white;
  opacity: 0;
  box-shadow: var(--shadow);
  pointer-events: none;
  transition: transform .2s ease, opacity .2s ease;
}
.toast.show {
  transform: translateY(0);
  opacity: 1;
  pointer-events: auto;
}


/* ══ Líneas de negocio, plegables ═════════════════════════════════════
   `details` nativo: el plegado funciona sin JavaScript y el teclado lo
   maneja solo. Lo único que hay que hacer a mano es quitar el triángulo
   que pinta el navegador, que va distinto en cada uno. */

.about-lines-lead {
  max-width: 720px;
  margin: 0 auto 28px;
  color: var(--muted);
  font-size: 17px;
  text-align: center;
}
/* Ancho completo de página y en dos columnas.
 *
 * Pedido por Maude el 20/08/2026: la sección estaba a 920px dentro de una
 * página de 1580px y se veía desencajada respecto a todo lo que tiene encima
 * y debajo.
 *
 * Dos columnas y no una estirada: a 1580px de ancho, cada párrafo quedaría en
 * una sola línea de unos 200 caracteres, y lo legible son 45-75. Así el
 * bloque llena la página y el texto se sigue leyendo. */
.about-lines,
.faq-lines {
  width: 100%;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  align-items: start;
  gap: 16px;
}

@media (max-width: 1180px) {
  .about-lines,
  .faq-lines { grid-template-columns: 1fr; }
}
.line-item {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: white;
  overflow: hidden;
  transition: border-color .18s ease, box-shadow .18s ease;
}
.line-item[open] {
  border-color: rgba(0,180,255,.42);
  box-shadow: var(--shadow);
}
.line-item summary {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 24px 26px;
  cursor: pointer;
  /* El triángulo por defecto: Chrome y Safari lo pintan distinto y ninguno
     encaja con el diseño. Se sustituye por el galón de la derecha. */
  list-style: none;
}
.line-item summary::-webkit-details-marker { display: none; }
.line-item summary:focus-visible {
  outline: 2px solid var(--electric-blue);
  outline-offset: -2px;
}
.line-item summary i {
  flex: none;
  color: var(--accent-600);
  font-size: 22px;
}
.line-item summary h3 {
  flex: 1;
  margin: 0;
  color: var(--primary-950);
  font-size: 19px;
  font-weight: 800;
  line-height: 1.3;
}
/* El galón. Va con bordes en lugar de un icono de la fuente para poder
   girarlo sin depender de que Bootstrap Icons haya cargado. */
.line-chevron {
  flex: none;
  width: 10px;
  height: 10px;
  margin-right: 4px;
  border-right: 2px solid var(--primary-900);
  border-bottom: 2px solid var(--primary-900);
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform .2s ease;
}
.line-item[open] .line-chevron {
  transform: rotate(225deg) translate(-2px, -2px);
}
/* El padding de arriba separa la respuesta de la pregunta: pegadas se leian
   como un solo bloque. La linea fina remata la separacion sin meter ruido. */
.line-item > p {
  margin: 0 26px 0 64px;
  padding: 16px 0 26px;
  border-top: 1px solid var(--border);
  color: var(--muted);
  font-size: 16px;
  line-height: 1.75;
}

/* Sin icono delante, la respuesta no tiene por que ir sangrada. */
.line-item.faq-item > p { margin-left: 26px; }

@media (max-width: 720px) {
  .about-lines-lead { font-size: 16px; text-align: left; }
  .line-item summary { gap: 12px; padding: 16px; }
  .line-item summary h3 { font-size: 16px; }
  .line-item > p { padding: 0 16px 18px; }
}

@media (prefers-reduced-motion: reduce) {
  .line-chevron { transition: none; }
}


/* ══ Quiénes somos: profundidad y ritmo ══════════════════════════════
   El problema era estructural, no de adornos: la columna izquierda del
   bloque de intro se quedaba vacía de arriba abajo mientras la derecha
   acumulaba seis párrafos. Aquí la izquierda pasa a ser una columna fija
   que acompaña la lectura, y el fondo deja de ser blanco plano. */

/* ── Fondo de ambiente ───────────────────────────────────────────────
   Dos lóbulos del degradado de marca, muy diluidos. Van en un
   pseudoelemento y no en el `background` de la sección para poder
   ponerlos detrás del contenido sin tocar el apilado del resto. */
/* El fondo va a todo el ancho de la ventana, no al del contenedor.

   Atado al contenedor se veía como un rectángulo recortado, con un canto
   vertical a media pantalla. Y estirar un pseudoelemento con `-50vw` lo
   arregla en apariencia pero mete barra de scroll horizontal.

   La salida es la que ya usa este proyecto en el bloque del Grupo y en la
   fila de logos: la sección ocupa el 100 % y alinea su contenido con el
   relleno lateral, en vez de estrecharse. Sin `vw` negativos y sin
   `overflow`, que rompería el `sticky` de la columna izquierda. */
.section.about-intro,
.section.about-lines-section {
  position: relative;
  isolation: isolate;
  width: 100%;
  max-width: none;
  padding-inline: max(48px, calc((100vw - 1580px) / 2));
}
.about-intro::before,
.about-lines-section::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(46% 62% at 6% 4%, rgba(0,180,255,.11), transparent 68%),
    radial-gradient(42% 58% at 94% 88%, rgba(25,224,194,.10), transparent 70%);
}

/* El corte entre las dos secciones se difumina: si las dos traen su lóbulo
   y se tocan, se ve la costura. */
.about-intro::before { mask-image: linear-gradient(180deg, transparent, #000 12%, #000 88%, transparent); }
.about-lines-section::before { mask-image: linear-gradient(180deg, transparent, #000 14%, #000 86%, transparent); }

/* ── La columna que acompaña ─────────────────────────────────────────
   `sticky` con el despeje de la cabecera fija. El titular deja de
   perderse arriba y la mancha blanca desaparece sin inventar relleno. */
.about-intro .split {
  grid-template-columns: .78fr 1.22fr;
  gap: clamp(32px, 5vw, 72px);
}
.about-intro-aside {
  position: sticky;
  top: 132px;
  align-self: start;
}
.about-intro-aside h2 {
  margin: 0;
  font-size: clamp(30px, 3vw, 42px);
  line-height: 1.1;
}
.about-intro-regla {
  width: 84px;
  height: 4px;
  margin: 24px 0 22px;
  border-radius: 999px;
  background: var(--brand-gradient);
}

/* ── Jerarquía en el texto ───────────────────────────────────────────
   Seis párrafos idénticos se leen como un muro. El primero entra más
   grande y en tono oscuro: da un punto de entrada. */
.about-intro-texto > p:first-child {
  color: var(--primary-950);
  font-size: clamp(19px, 1.5vw, 22px);
  font-weight: 500;
  line-height: 1.55;
}
.about-intro-texto > p {
  color: var(--muted);
  font-size: 17px;
  line-height: 1.75;
}
.about-intro-texto > p + p { margin-top: 18px; }

/* ── Cifras con más presencia ────────────────────────────────────────
   Antes eran cinco cajas planas con un borde. Ahora tienen fondo, un
   filete de marca arriba y un número que pesa. */
.about-metrics div {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius-md);
  background: linear-gradient(180deg, #fff, #f4f8fb);
  box-shadow: 0 10px 30px rgba(10,18,48,.05);
  transition: transform .22s ease, box-shadow .22s ease;
}
.about-metrics div::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 3px;
  background: var(--brand-gradient);
}
.about-metrics div:hover {
  transform: translateY(var(--alza-tarjeta));
  box-shadow: var(--sombra-hover);
}
.about-metrics strong {
  font-size: clamp(28px, 2.4vw, 38px);
  letter-spacing: -.02em;
}

/* ── La cabecera, con algo detrás ────────────────────────────────────
   La fotografía flotaba como un rectángulo suelto. Se le pone un canto
   de marca y una sombra que la asienta. */
.about-hero img {
  border-radius: var(--radius-lg);
  box-shadow: 0 30px 70px rgba(10,18,48,.18);
}
.about-hero {
  position: relative;
  isolation: isolate;
}
.about-hero::before {
  content: "";
  position: absolute;
  z-index: -1;
  /* Mismo criterio: sin `vw` negativos. La cabecera ya ocupa el ancho de
     su contenedor y el lóbulo se coloca por posición, no por tamaño. */
  inset: -120px 0 auto;
  height: 130%;
  pointer-events: none;
  background: radial-gradient(46% 54% at 88% 34%, rgba(41,98,255,.11), transparent 70%);
}


/* ══ Revelado al entrar en pantalla ═══════════════════════════════════
   El estado inicial lo pone el JavaScript con la clase `revelar-listo`
   sobre `html`, no el CSS por su cuenta. Si el script no llega a
   ejecutarse —error, navegador antiguo, bloqueador—, el contenido se ve
   normal en lugar de quedarse invisible para siempre.

   Es el mismo criterio que la cabecera animada: el diseño nunca depende
   de que un script funcione. */
/* La entrada al aparecer en pantalla.

   **Repartido en tres reglas y no en dos.** Antes el estado revelado fijaba
   `transform: none`, y ese selector —clase, atributo y clase— gana a cualquier
   `:hover` de una tarjeta. El resultado es que **toda pieza con `data-revelar`
   se quedaba sin elevarse al pasar por encima**, que son casi todas: unas se
   movían y otras no, según llevaran el atributo. Se veía recorriendo el sitio
   y no leyendo una pantalla suelta.

   Ahora el desplazamiento sólo existe mientras la pieza **no** se ha revelado.
   Revelada, la regla no declara ningún `transform`, así que el de su `:hover`
   se aplica sin pelear. La transición vive en la regla que siempre aplica, o
   la aparición se quedaría sin animar. */
.revelar-listo [data-revelar] {
  transition: opacity .55s cubic-bezier(.22,.61,.36,1),
              transform .55s cubic-bezier(.22,.61,.36,1);
}
.revelar-listo [data-revelar]:not(.visible) {
  opacity: 0;
  transform: translateY(18px);
}
.revelar-listo [data-revelar].visible {
  opacity: 1;
}
/* Escalonado dentro de una rejilla: las tarjetas no entran todas a la vez.
   Se limita a seis porque más allá el retardo se nota como lentitud. */
.revelar-listo [data-revelar]:nth-child(2) { transition-delay: .07s; }
.revelar-listo [data-revelar]:nth-child(3) { transition-delay: .14s; }
.revelar-listo [data-revelar]:nth-child(4) { transition-delay: .21s; }
.revelar-listo [data-revelar]:nth-child(5) { transition-delay: .28s; }
.revelar-listo [data-revelar]:nth-child(6) { transition-delay: .35s; }

@media (prefers-reduced-motion: reduce) {
  .revelar-listo [data-revelar] {
    opacity: 1;
    transform: none;
    transition: none;
  }
}


/* ══ Tira de colaboradores ═══════════════════════════════════════════
   Una sola banda a todo el ancho, sin contenedor. Sustituye a las tres
   tarjetas apiladas que había (punto B4 del documento de revisión). */

.section.franja-colaboradores {
  width: 100%;
  max-width: none;
  padding: clamp(52px, 6vw, 78px) 0;
  background: linear-gradient(180deg, #eef3f6, var(--surface));
}

/* El antetítulo, alineado al margen izquierdo como el resto del sitio.

   Usa `.eyebrow` tal cual, que ya trae el filete de marca a la derecha del
   texto. Antes era un titular centrado con la línea debajo: quedaba bien por
   sí solo, pero era el único sitio de la página que lo hacía así, y la
   consistencia pesa más que el acierto suelto.

   El relleno lateral es el mismo que usan las secciones a todo el ancho, así
   que el antetítulo cae en la misma vertical que los de arriba. */
.colaboradores-titulo {
  margin-bottom: clamp(26px, 3vw, 40px);
  padding-inline: max(48px, calc((100vw - 1580px) / 2));
}

/* La ventana. El desvanecido de los cantos evita que los logotipos entren
   y salgan cortados en seco; sin él, la tira parece recortada por una
   tijera en los dos extremos. */
.colaboradores-pista {
  overflow: hidden;
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}

.colaboradores-cinta {
  display: flex;
  align-items: center;
  width: max-content;
  /* El hueco va en variable porque la animación tiene que descontarlo: si
     los dos valores se separan, el bucle da un tirón en cada vuelta. */
  --hueco-colaboradores: clamp(56px, 5vw, 96px);
  gap: var(--hueco-colaboradores);
  animation: correr-colaboradores 88s linear infinite;
}

/* Al pasar por encima se detiene, para poder mirar un logotipo concreto. */
.colaboradores-pista:hover .colaboradores-cinta {
  animation-play-state: paused;
}

/*
 * Y con teclado, pero por `:focus-visible` y no por `:focus-within`.
 *
 * **`focus-within` dejaba la tira parada para siempre.** Los logotipos son
 * enlaces que abren en pestana nueva: al pulsar uno, el enlace se queda con el
 * foco y nadie se lo quita —la pestana nueva se lleva la atencion, y al volver
 * el foco sigue ahi—. La condicion seguia cumpliendose con el raton lejos, asi
 * que la cinta no volvia a arrancar hasta recargar. Lo vio Maude en produccion
 * el 01/09/2026.
 *
 * `:focus-visible` solo se activa cuando el navegador decide que el foco debe
 * verse, que en la practica es al navegar con teclado. Un clic de raton no lo
 * activa, asi que quien pulsa un logotipo no deja la tira colgada, y quien
 * llega tabulando la sigue parando para poder leerla.
 *
 * En regla aparte y no en la misma lista que el `:hover`: si un navegador no
 * entendiera `:has()`, una lista con un selector invalido tira la regla
 * entera y se perderia tambien la pausa al pasar por encima.
 */
.colaboradores-pista:has(:focus-visible) .colaboradores-cinta {
  animation-play-state: paused;
}

/* Sin caja: el logotipo va sobre el fondo de la página. Un borde alrededor
   compite con el encuadre del propio logotipo.

   El hueco es de ancho automático, no fijo: con un ancho fijo, un logotipo
   apaisado y uno cuadrado se pintan a tamaños muy distintos dentro de la
   misma caja y la tira se ve desigual. */
.colaborador {
  position: relative;
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 104px;
  padding-inline: 26px;
  text-decoration: none;
}

/* La clave de que se vean parejos: **misma altura para todos**, y el ancho
   que salga de su proporción.

   Con `max-width` y `max-height` a la vez, a cada logotipo lo frena una cosa
   distinta —los apaisados chocan con el ancho, los cuadrados con el alto— y
   unos acaban pintándose mucho más pequeños que otros. Fijando la altura,
   todos comparten la línea óptica, que es lo que el ojo lee como parejo.

   Sin esta regla cada logotipo se pinta a su tamaño real: el de Maude mide
   1.955 px de ancho y se comía la tira entera.

   `max-width` es sólo un tope de seguridad para un archivo desproporcionado
   que pudiera cargarse desde el CRM. */
.colaborador img {
  height: 62px;
  width: auto;
  max-width: 340px;
  object-fit: contain;
  transition:
    transform .38s cubic-bezier(.22,.61,.36,1),
    filter .38s ease;
}

/* El efecto sobre el propio logotipo: crece muy poco y gana algo de peso.
   Va en la imagen y no en el hueco, así que no empuja a los vecinos. */
a.colaborador:hover img,
a.colaborador:focus-visible img {
  transform: scale(1.05);
  filter: drop-shadow(0 6px 14px rgba(10, 18, 48, .16));
}

/* El filete de marca, igual que en las tarjetas de audiencias.

   Antes había un halo desenfocado detrás y un aumento de escala: el halo se
   salía del hueco y se leía como un recuadro de color cortado, y la escala
   empujaba a los logotipos vecinos. Se quitan los dos.

   Queda sólo la línea, que crece desde el centro. Es el mismo gesto que ya
   usa la sección de audiencias, así que el sitio dice «esto responde al
   clic» siempre de la misma forma. */
.colaborador::after {
  content: "";
  position: absolute;
  left: 26px;
  right: 26px;
  bottom: 16px;
  height: 2px;
  border-radius: 999px;
  background: var(--brand-gradient);
  transform: scaleX(0);
  transform-origin: center;
  transition: transform .38s cubic-bezier(.22,.61,.36,1);
}

/* Sólo donde hay a dónde ir: una línea que se enciende sobre algo que no
   responde al clic promete una interacción que no existe. */
a.colaborador:hover::after,
a.colaborador:focus-visible::after {
  transform: scaleX(1);
}

/* El foco del teclado necesita su propio contorno: la línea es decorativa y
   no basta para saber dónde se está. */
a.colaborador:focus-visible {
  outline: 2px solid var(--electric-blue);
  outline-offset: 4px;
  border-radius: var(--radius-sm);
}

.colaborador span {
  color: var(--muted);
  font-size: 16px;
  font-weight: 800;
  text-align: center;
}

/* La cinta lleva la lista dos veces, así que recorre la mitad y vuelve al
   origen sin que se vea el corte. Se descuenta medio hueco: entre las dos
   copias hay uno más que dentro de cada una, y sin restarlo el bucle salta
   ese ancho en cada vuelta. */
@keyframes correr-colaboradores {
  from { transform: translateX(0); }
  to { transform: translateX(calc(-50% - var(--hueco-colaboradores) / 2)); }
}

@media (max-width: 720px) {
  .colaborador { height: 78px; }
  .colaborador img { height: 46px; max-width: 240px; }
  .colaboradores-cinta { --hueco-colaboradores: 44px; }
}

/* Quien pide menos movimiento recibe una tira que se puede desplazar a
   mano, no una animación más lenta. */
@media (prefers-reduced-motion: reduce) {
  .colaboradores-pista {
    overflow-x: auto;
    mask-image: none;
    -webkit-mask-image: none;
  }
  .colaboradores-cinta {
    animation: none;
    scroll-snap-type: x proximity;
  }
  .colaborador img { transition: none; }
  .colaborador::after { transition: none; }
}


/* ══ Soluciones para cada audiencia ══════════════════════════════════
   Cuatro tarjetas blancas con un borde fino, un icono pequeño y una lista
   con la viñeta del navegador. Se leía como una tabla, no como la sección
   que abre la propuesta de la portada.

   Se le aplica el mismo criterio que al resto: sección a todo el ancho con
   fondo de ambiente, tarjetas con profundidad y filete de marca, y el
   revelado al entrar. */

.section.franja-audiencias {
  position: relative;
  isolation: isolate;
  width: 100%;
  max-width: none;
  padding-inline: max(48px, calc((100vw - 1580px) / 2));
}
.franja-audiencias::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(44% 58% at 92% 6%, rgba(41,98,255,.09), transparent 68%),
    radial-gradient(40% 54% at 4% 92%, rgba(25,224,194,.08), transparent 70%);
  mask-image: linear-gradient(180deg, transparent, #000 12%, #000 88%, transparent);
}

/* Las tarjetas dejan de ser cajas planas. */
.franja-audiencias .audience-card {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  padding: 30px 26px 26px;
  border-color: rgba(16,27,61,.10);
  background: linear-gradient(180deg, #fff 0%, #f7fafc 100%);
  box-shadow: 0 12px 34px rgba(10,18,48,.06);
  transition:
    transform .32s cubic-bezier(.22,.61,.36,1),
    box-shadow .32s cubic-bezier(.22,.61,.36,1),
    border-color .32s ease;
}

/* El filete de marca del canto superior nace corto y se completa al pasar
   por encima: da una señal de que la tarjeta es interactiva sin añadir
   ningún elemento. */
.franja-audiencias .audience-card::before {
  content: "";
  position: absolute;
  inset: 0 auto auto 0;
  width: 46px;
  height: 3px;
  background: var(--brand-gradient);
  transition: width .38s cubic-bezier(.22,.61,.36,1);
}
.franja-audiencias .audience-card:hover {
  transform: translateY(var(--alza-tarjeta));
  border-color: var(--borde-hover);
  box-shadow: var(--sombra-hover);
}
.franja-audiencias .audience-card:hover::before { width: 100%; }

/* El icono, dentro de una pastilla con el tinte de marca. Antes iba suelto
   a 48px y se leía como un adorno, no como parte de un sistema. */
.franja-audiencias .audience-heading {
  display: grid;
  gap: 16px;
  min-height: 0;
  margin-bottom: 18px;
}
.franja-audiencias .audience-heading i {
  display: grid;
  place-items: center;
  width: 54px;
  height: 54px;
  border-radius: 15px;
  background: linear-gradient(140deg, rgba(25,224,194,.16), rgba(41,98,255,.14));
  color: var(--primary-900);
  font-size: 25px;
}
.franja-audiencias .audience-card h3 {
  font-size: 15px;
  letter-spacing: .12em;
}

/* La lista: fuera la viñeta del navegador, entra un punto de marca. */
.franja-audiencias .audience-card ul {
  flex: 1;
  margin: 0 0 22px;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 10px;
}
.franja-audiencias .audience-card li {
  position: relative;
  padding-left: 20px;
  color: var(--muted);
  font-size: 15px;
  line-height: 1.45;
}
.franja-audiencias .audience-card li::before {
  content: "";
  position: absolute;
  top: .55em;
  left: 0;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--cyan);
}

/* El enlace se separa del texto y su flecha avanza con el gesto. */
.franja-audiencias .audience-card a {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  margin-top: auto;
  padding-top: 16px;
  border-top: 1px solid rgba(16,27,61,.08);
  color: var(--primary-900);
  font-size: 14px;
  text-decoration: none;
}
.franja-audiencias .audience-card a i {
  transition: transform .3s cubic-bezier(.22,.61,.36,1);
}
.franja-audiencias .audience-card:hover a i { transform: translateX(5px); }

@media (max-width: 1180px) {
  .franja-audiencias .audience-card { padding: 24px 20px 20px; }
}

@media (prefers-reduced-motion: reduce) {
  .franja-audiencias .audience-card,
  .franja-audiencias .audience-card::before,
  .franja-audiencias .audience-card a i { transition: none; }
  .franja-audiencias .audience-card:hover { transform: none; }
}

@media (max-width: 1180px) {
  .about-intro .split { grid-template-columns: 1fr; }
  .about-intro-aside { position: static; }
}

@media (prefers-reduced-motion: reduce) {
  .about-metrics div { transition: none; }
  .about-metrics div:hover { transform: none; }
}

@media (max-width: 1180px) {
  /* La marca arriba, a todo el ancho, y los enlaces de dos en dos.
     Eran tres columnas para cuatro bloques, así que Contacto se descolgaba
     solo a una segunda fila con 623 px de hueco al lado. Emparejados no sobra
     ninguno, y es el mismo reparto al que llega el móvil: la pieza cambia de
     tamaño, no de forma. */
  .footer-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 34px 30px;
  }
  .footer-grid > div:first-child { grid-column: 1 / -1; }
  /* Mismo criterio que en escritorio: el logo mide 55,5px a 250px de ancho,
     así que 96px de barra le dejan 20px de aire. */
  :root { --alto-cabecera: 96px; }
  .site-header { grid-template-columns: 1fr auto; left: 0; right: 0; min-height: var(--alto-cabecera); padding-inline: max(28px, 3.5vw); }
  .site-header .brand img { width: 250px; max-width: calc(100vw - 140px); }
  main > .inner-hero:first-child,
  main > .detail-hero:first-child,
  main > .talent-hero:first-child,
  main > .editorial-hero:first-child,
  main > .contact-hero:first-child,
  main > .portal-hero:first-child,
  main > .error-pagina:first-child,
  main > .portal-acceso:first-child,
  main > .portal-perfil:first-child,
  main > .cv-pagina:first-child { padding-top: 138px; }
  /* Por debajo de 1.180 la columna lateral se queda en 300px junto a un
     texto ya estrecho. Se apilan y la lateral queda debajo, en su orden del
     documento: ahí el enlace de vuelta cae donde se necesita, al final. */
  .article-layout { grid-template-columns: 1fr; gap: 38px; }
  .article-aside { position: static; width: 100%; max-width: 780px; margin-inline: auto; }
  .article-index ol { columns: 2; column-gap: 28px; }
  .menu-toggle { display: inline-flex; align-items: center; gap: 8px; justify-self: end; border: 1px solid rgba(255,255,255,.22); background: rgba(255,255,255,.1); color: white; padding: 10px 12px; border-radius: var(--radius-sm); font-weight: 850; box-shadow: inset 0 1px 0 rgba(255,255,255,.1); }
  /* El botón de menú es un control y su borde tiene que llegar a 3:1 contra
     la barra. Al 22% se quedaba en 2:1, y con la barra traslúcida hace falta
     más.

     La condición va por el estado de la barra, no por la página. Antes era
     `body:not(.con-cabecera-clara)`, que dejaba fuera la portada entera; eso
     funcionaba mientras su cabecera se volvía blanca al bajar, pero ahora se
     vuelve cristal oscuro y allí también hace falta el borde fuerte. */
  .site-header .menu-toggle { border-color: rgba(255,255,255,.48); background: rgba(255,255,255,.14); }

  /* Sobre el hero, con la barra transparente y el fondo claro, un borde
     blanco no se vería: ahí va en tinta oscura. */
  body.con-cabecera-clara .site-header:not(.header-solido) .menu-toggle {
    border-color: rgba(16,27,61,.30);
    background: rgba(255,255,255,.58);
  }
  .main-nav {
    position: fixed;
    left: 12px;
    right: 12px;
    /* Justo debajo de la barra, que ahora mide 96px. */
    top: 104px;
    display: none;
    flex-direction: column;
    padding: 18px;
    border: 1px solid rgba(255,255,255,.14);
    border-radius: var(--radius-md);
    background: linear-gradient(180deg, rgba(6,12,32,.9), rgba(6,12,32,.76));
    box-shadow: 0 24px 48px rgba(2,8,28,.24);
    -webkit-backdrop-filter: blur(22px) saturate(150%);
    backdrop-filter: blur(22px) saturate(150%);
  }
  .main-nav a { color: rgba(255,255,255,.84); }
  .main-nav a.active { color: white; }
  .main-nav.open { display: flex; }
  .header-cta { display: none; }
  main > .home-main-hero:first-child { margin-top: 96px; }
  .hero, .inner-hero, .detail-hero, .talent-hero, .editorial-hero, .contact-hero, .contact-layout, .split, .two-columns, .portal-banner, .talent-cta-card, .backing-card, .logo-band, .home-editorial, .formation-type-grid, .formation-type-grid article, .destination-card { grid-template-columns: 1fr; }
  .contact-demo-badge { max-width: 620px; }
  .contact-aside { position: static; }
  .talent-cta-card { gap: 30px; }
  .talent-cta-device { justify-self: start; }
  .hero-copy { padding: 48px 32px; }
  .home-main-hero .hero-copy {
    min-height: 560px;
    width: min(680px, 70vw);
    padding-left: 34px;
  }
  .training-page-hero .hero-copy {
    min-height: 520px;
    width: min(820px, 74vw);
    padding: 48px 32px;
  }
  .training-page-hero h1 { max-width: 820px; font-size: clamp(38px, 4.8vw, 52px); }
  .hero-image { min-height: 360px; }
  .audience-grid, .training-grid, .article-grid, .job-grid, .value-grid, .backing-metrics, .about-metrics, .training-reason-grid { grid-template-columns: repeat(2, 1fr); }
  .backing-signature { max-width: 520px; }
  /* La regla de arriba manda las cifras a dos columnas junto con el resto de
     rejillas, y aquí todavía sobra ancho para las cinco: a 1180px la tarjeta
     deja unos 985px de contenido, 185px por celda. Se rompen más abajo. */
  .backing-metrics { grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }
  .sector-grid, .service-icons { grid-template-columns: repeat(4, 1fr); }
  .strategic-card-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .talent-services-section .strategic-card-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .training-meeting-cta { grid-template-columns: 1fr; }
  .destination-media { min-height: 280px; }
  .home-services { grid-template-columns: repeat(3, 1fr); }
  /* A dos columnas, el buscador ocupa la fila entera y los dos botones
     caen juntos en la ultima: repartidos de cinco en dos columnas, el
     de limpiar quedaba solo y a media anchura. */
  .filters { grid-template-columns: 1fr 1fr; }
  .filters > label:first-of-type { grid-column: 1 / -1; }
  .search-band { margin-top: 0; padding-top: 18px; }
  .search-band form { grid-template-columns: 1fr; }
  .talent-hero-public,
  .talent-access-grid,
  .success-grid,
  .talent-next-step {
    grid-template-columns: 1fr;
  }
  .talent-hero-preview {
    justify-self: start;
  }
  .talent-next-step {
    grid-template-columns: 1fr;
    padding: 30px 32px;
  }
  .talent-next-step::before {
    background-size: cover;
    background-position: center;
  }
  .talent-next-step .actions {
    grid-column: auto;
    justify-content: flex-start;
    min-width: 0;
  }
  .talent-metrics-strip {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .talent-access-card {
    grid-template-columns: 210px 1fr;
  }
  .talent-access-card .path-icon {
    left: 182px;
  }
  .talent-steps {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .talent-steps h2 {
    grid-column: 1 / -1;
  }
  .steps { grid-template-columns: repeat(2, 1fr); }
  .steps h2 { grid-column: 1 / -1; }
  .project-card-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .editorial-card-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .editorial-news {
    padding-left: 0;
    border-left: 0;
  }
  /* La pieza se estrecha con el resto del contenido. El velo pasa a ir de
     arriba abajo: en una columna el texto ocupa todo el ancho y un velo
     lateral no protege nada. */
  .final-cta { width: min(1580px, calc(100% - 32px)); min-height: 280px; }
  .final-cta-copy { padding: 40px 30px; max-width: none; }
  .final-cta::after {
    background: linear-gradient(180deg, rgba(10,18,48,.90) 0%, rgba(10,18,48,.72) 62%, rgba(10,18,48,.52) 100%);
  }
}

/* Las cinco cifras del bloque del Grupo aguantan en fila hasta unos 1000px:
   por debajo la celda ya no da para «20.000+» y el número se desborda.
   Pasan a dos columnas, y la quinta ocupa la fila entera para no dejar un
   hueco a la derecha. */
@media (max-width: 1000px) {
  .backing-metrics { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .backing-metrics div:last-child:nth-child(odd) { grid-column: 1 / -1; }
}

@media (max-width: 720px) {
  h1 { font-size: clamp(36px, 11vw, 52px); }
  h2 { font-size: clamp(25px, 8vw, 36px); }
  .section, .inner-hero, .detail-hero, .talent-hero, .editorial-hero, .contact-hero, .search-band, .talent-cta { width: min(100% - 32px, 1240px); }
  .section { padding: 44px 0; }
  .section.soft { padding-inline: 16px; }
  .section.group-backing { padding: 44px 16px; }
  .section.logo-closing { padding: 32px 16px 40px; }
  /* El logo mide 45,5px a 205px de ancho: 82px de barra le dejan 18px. */
  :root { --alto-cabecera: 82px; }
  .site-header { grid-template-columns: 1fr auto; min-height: var(--alto-cabecera); padding: 12px 18px; border-radius: 0; }
  main > .inner-hero:first-child,
  main > .detail-hero:first-child,
  main > .talent-hero:first-child,
  main > .editorial-hero:first-child,
  main > .contact-hero:first-child,
  main > .portal-hero:first-child,
  main > .error-pagina:first-child,
  main > .portal-acceso:first-child,
  main > .portal-perfil:first-child,
  main > .cv-pagina:first-child { padding-top: 118px; }
  .main-nav { top: 92px; }
  .article-aside { gap: 20px; }
  .article-facts { padding: 16px; }
  .site-header::after { bottom: -34px; height: 34px; }
  .site-header .brand img { width: 205px; max-width: calc(100vw - 108px); }
  .brand-tagline { font-size: 8px; letter-spacing: .12em; }
  main > .home-main-hero:first-child { margin-top: 86px; }
  .hero { min-height: 0; }
  .hero-copy { padding: 42px 16px; }
  .home-main-hero { min-height: 620px; }
  .home-main-hero h1 { font-size: clamp(40px, 12vw, 56px); }
  .home-main-hero .hero-copy {
    min-height: 620px;
    width: min(100% - 32px, 620px);
    padding: 44px 16px;
  }
  .home-main-hero .hero-image {
    background:
      linear-gradient(90deg, rgba(255,255,255,.98), rgba(255,255,255,.88), rgba(255,255,255,.52)),
      var(--hero);
    background-position: 62% center;
  }
  .training-page-hero .hero-copy {
    min-height: 560px;
    width: min(100% - 32px, 620px);
    padding: 44px 16px;
  }
  .training-page-hero h1 { font-size: clamp(38px, 10vw, 50px); }
  .training-page-hero .hero-copy .hero-lead { font-size: 17px; }
  .training-hero-points span { width: 100%; }
  .contact-hero { padding: 44px 0 24px; }
  .contact-demo-badge { grid-template-columns: 1fr; }
  .contact-demo-badge i { grid-row: auto; }
  .contact-aside, .contact-form-card { padding: 22px; }
  .stats-strip, .audience-grid, .training-grid, .article-grid, .job-grid, .value-grid, .category-cards, .role-grid, .facts, .content-grid, .logo-grid, .backing-metrics, .about-metrics, .training-reason-grid, .form-grid { grid-template-columns: 1fr; }
  .form-grid > label > span { min-height: 0; }
  /* Ficha de formación en pantalla estrecha. */
  .ficha { gap: 18px; }
  .facts div { padding: 14px 18px; }
  .ficha-lede { padding-left: 20px; }
  .ficha-institucion { padding: 18px 20px; }
  .ficha-institucion > a { margin-left: 0; }
  .content-grid article { padding: 24px 22px 26px; }
  .ficha-destino { padding: 24px 22px 26px; }
  .ficha-destino ul { columns: 1; }
  .audience-heading { gap: 16px; min-height: 48px; margin-bottom: 16px; }
  .audience-heading i { font-size: 38px; }
  .audience-svg-icon { width: 44px; height: 44px; }
  .group-backing { padding: 0; }
  .backing-card { padding: 28px 20px; border-radius: 16px; }
  /* El filete decorativo va a 22px del borde y aquí el relleno baja a 20px:
     la línea cruzaba el texto. */
  .backing-card::before { inset: 12px; border-radius: 10px; }
  .backing-copy { padding: 0; }
  /* Sin esto el titular se queda en 34px mientras el resto de la página baja
     a ~28px, y en una tarjeta estrecha se come cuatro líneas. */
  .backing-copy h2 { font-size: clamp(28px, 8vw, 36px); }
  .backing-signature { padding: 18px; }
  .logo-showcase { margin-top: 16px; }
  .logo-band { padding: 20px; }
  .logo-carousel-track .logo-tile { flex-basis: 220px; }
  .about-logo-strip { padding: 0 16px 8px; }
  .logo-band.about-logo-band { padding: 14px 0; }
  .logo-band.about-logo-band .logo-carousel-track .logo-tile { flex-basis: 210px; min-height: 70px; }
  .logo-band.about-logo-band .logo-carousel-track .logo-tile img { max-width: 165px; max-height: 48px; }
  /* En una sola columna las cinco cifras son medio metro de tarjetas
     apiladas. Dos columnas entran desde 360px; por debajo `auto-fit` vuelve
     solo a una. */
  .backing-metrics { grid-template-columns: repeat(auto-fit, minmax(132px, 1fr)); }
  .backing-metrics div { min-height: 104px; padding: 16px 12px; }
  /* La regla que había aquí pintaba un borde oscuro sobre la tarjeta azul
     marino: se arrastraba de cuando esta tira iba sobre fondo claro. */
  .backing-metrics strong { font-size: 24px; }
  .backing-metrics i { font-size: 18px; }
  .article-body { font-size: 16px; line-height: 1.7; }
  .article-body h2 { margin-top: 34px; }
  .article-body h3 { margin-top: 26px; }
  .inner-hero, .detail-hero, .talent-hero { padding: 38px 0; }
  .inner-hero img, .detail-hero img, .talent-hero img { height: 220px; }
  /* La escala se ajusta a la palabra más larga, no al revés.
     «Internacionalizamos» son diecinueve caracteres sin sitio por donde
     partir: a 10vw mide 392px en una pantalla de 390 y **la página desbordaba
     18px**, con la última letra del titular y el final de cada línea del
     párrafo cortados. Medido, no deducido: `scrollWidth` 408 con la ventana en
     390. Venía de antes; se destapó al mirar el titular de cerca.
     A 8,7vw la palabra entra hasta los 320px de ancho, que es el suelo real
     de un teléfono. */
  .about-hero h1 { font-size: clamp(26px, 8.7vw, 48px); }
  .about-hero > div:first-child p { font-size: 16px; }
  .about-hero-panel { min-height: 250px; padding: 24px; }
  .inner-hero .about-panel-logo { width: min(250px, 100%); max-height: 66px; }
  .about-panel-points span { width: 100%; }
  .about-value-grid article {
    min-height: 0;
    padding: 20px;
  }
  .category-cards img, .feature-card img { height: 220px; width: 100%; object-fit: cover; }
  .formation-type-grid img { height: 220px; min-height: 220px; }
  .formation-type-grid article > div { padding: 24px; }
  .training-featured,
  .training-services { width: min(100% - 32px, 1320px); }
  .training-why,
  .training-commitment,
  .training-meeting-cta { width: min(100% - 32px, 1320px); }
  .strategic-card-grid { grid-template-columns: 1fr; }
  .talent-services-section .strategic-card-grid { grid-template-columns: 1fr; }
  .training-portal-banner { padding: 22px; }
  .training-portal-banner img { height: 220px; }
  .training-meeting-cta { padding: 24px; }
  .training-meeting-cta .btn { width: fit-content; }
  .talent-cta { padding-top: 44px; padding-bottom: 44px; }
  .talent-cta-card {
    min-height: 0;
    padding: 28px 18px;
    border-radius: var(--radius-md);
  }
  .talent-cta-copy h2 { font-size: clamp(38px, 11vw, 52px); }
  .talent-cta-button { margin-top: 28px; }
  .talent-cta-device { border-radius: 0; }
  .talent-cta-device img { height: 260px; border-radius: 0; }
  .destination-media { min-height: 220px; }
  .destination-content,
  .destination-trainings { padding: 20px; }
  .category-cards article, .home-categories article, .feature-card { grid-template-columns: 1fr; }
  .sector-grid, .service-icons { grid-template-columns: repeat(2, 1fr); }
  .home-services, .mini-sector-grid { grid-template-columns: 1fr; }
  .talent-hero-public {
    width: min(100% - 32px, 1240px);
    min-height: 0;
    padding-top: 38px;
  }
  .talent-hero-public h1 {
    font-size: clamp(40px, 12vw, 56px);
  }
  .talent-hero-preview {
    border-radius: 0;
  }
  .talent-hero-preview img {
    height: 330px;
    border-radius: 0;
  }
  .talent-hero-ui {
    left: 14px;
    right: 14px;
    bottom: 14px;
    padding: 16px;
  }
  .talent-hero-ui div {
    grid-template-columns: auto 1fr;
  }
  .talent-hero-ui button {
    grid-column: 1 / -1;
    width: 100%;
  }
  .talent-next-step {
    grid-template-columns: 1fr;
    padding: 28px 18px;
  }
  .talent-next-step::before {
    width: 100%;
    min-width: 0;
    background-size: cover;
    background-position: 30% center;
  }
  .success-grid article {
    padding: 14px 0;
  }
  .success-grid article + article {
    border-left: 0;
    border-top: 1px solid rgba(255,255,255,.18);
  }
  .talent-globe {
    display: none;
  }
  .talent-next-step .actions {
    width: 100%;
  }
  .talent-next-step .btn {
    width: 100%;
  }
  .talent-search-band,
  .talent-metrics-strip {
    width: min(100% - 32px, 1240px);
  }
  .talent-metrics-strip {
    grid-template-columns: 1fr;
  }
  .talent-access-card {
    grid-template-columns: 1fr;
  }
  .talent-access-card > img {
    height: 220px;
    min-height: 220px;
  }
  .talent-access-card .path-icon {
    left: 22px;
    top: 190px;
  }
  .talent-access-card .path-content {
    padding: 42px 20px 24px;
  }
  .talent-access-card ul {
    columns: 1;
  }
  .talent-steps {
    grid-template-columns: 1fr;
  }
  .success-grid article {
    grid-template-columns: 1fr;
    text-align: left;
  }
  .project-card-grid { grid-template-columns: 1fr; }
  .editorial-card-grid { grid-template-columns: 1fr; }
  .editorial-hero {
    padding: 44px 0 28px;
  }
  .editorial-hero h1 {
    font-size: clamp(40px, 11vw, 56px);
  }
  .editorial-section-heading {
    display: block;
  }
  .editorial-card {
    min-height: 0;
  }
  .editorial-card img {
    height: 210px;
  }
  .editorial-card footer {
    align-items: flex-start;
    flex-direction: column;
  }
  .news-media-list a { grid-template-columns: 90px 1fr; }
  .news-media-list img { width: 90px; height: 72px; }
  .filters { grid-template-columns: 1fr; }
  .final-cta { min-height: 0; border-radius: var(--radius-md); }
  .final-cta-copy { padding: 32px 20px; }
  /* ── El pie, centrado en pantalla estrecha ──────────────────────
     Con una sola columna, el contenido alineado a la izquierda deja una
     franja de aire a la derecha que crece con cada título corto y el pie
     se lee descolgado. Centrado, cada bloque se sostiene solo.

     El crédito de Artisans ya se centraba **dentro de sí mismo** y aun así
     aparecía a la izquierda: la fila legal apilada tenía
     `align-items: flex-start`, así que centraba su texto y colocaba la caja
     entera pegada al margen. Se veía como un logotipo centrado en el sitio
     equivocado. */
  .site-footer {
    text-align: center;

    /* El margen lateral baja de 48 a 22 px, que es el que usa el resto del
       sitio en móvil —la tarjeta de contacto, el cierre, la pieza del
       boletín—. El pie era el único que se quedaba con el del escritorio, y
       en un teléfono de 360 px eso se comía 96 de 360: al pasar a dos
       columnas, «Todas las formaciones», «Portal de Talento» y «Preguntas
       frecuentes» se partían en dos líneas. */
    padding: 44px 22px 30px;
  }

  /* Dos columnas, no una.
     Apilado a una columna el pie medía más de mil píxeles y había que
     arrastrar medio teléfono para pasarlo. Emparejadas —Formaciones con
     Portal de Talento, Sobre Maude con Contacto— ocupa la mitad y se lee de
     un vistazo.

     La marca cruza las dos: es la firma del pie y partida por la mitad no
     sería una firma. */
  .footer-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 30px 18px;
  }

  .footer-grid > div:first-child {
    grid-column: 1 / -1;
  }

  /* El párrafo de marca tiene ancho máximo propio; sin margen automático se
     queda pegado al margen izquierdo aunque su texto vaya centrado. */
  .site-footer p {
    margin-inline: auto;
  }

  /* Icono y dato son dos columnas de una rejilla: centrar el texto del pie
     no mueve la rejilla, que sigue ocupando su ancho desde la izquierda. Con
     las columnas al ancho de su contenido y `justify-content`, la pareja
     queda centrada dentro de la fila.

     `grid` y no `inline-grid`: en línea, dos teléfonos cortos caben en el
     mismo renglón y se leen como un solo número larguísimo. Cada dato de
     contacto es una línea. */
  .footer-contact p {
    grid-template-columns: auto auto;
    justify-content: center;
  }

  .social-links {
    justify-content: center;
  }

  /* El logotipo se centra con margen y no con `justify-content`.
     `.footer-brand` se declara `inline-flex` —que se centraría solo dentro de
     un padre con el texto centrado— pero `.site-footer a { display: block }`
     le gana por especificidad y lo deja en bloque. Un bloque con ancho de
     contenido se queda pegado a la izquierda: se medía a 37 px del centro. */
  .footer-brand {
    margin-inline: auto;
  }


}

/* ── Selector de idioma ───────────────────────────────────────────
   Se separa del menú con una línea vertical para que no se lea como
   una sección más de navegación. */
.lang-switch {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  margin-left: 6px;
  padding-left: 18px;
  border-left: 1px solid rgba(255,255,255,.34);
}
.main-nav .lang-switch a {
  padding: 6px 10px;
  border-radius: var(--radius-pill);
  /* Al 62% no llegaba a 4,5:1 sobre la barra de cristal. Es texto de 11px,
     así que se le exige el umbral de texto pequeño. */
  color: rgba(255,255,255,.72);
  font-size: 11px;
  letter-spacing: .06em;
  line-height: 1;
  transition: color .18s ease, background-color .18s ease;
}
/* El subrayado animado del menú no aplica acá */
.main-nav .lang-switch a::after { display: none; }
.main-nav .lang-switch a:hover { color: white; }
.main-nav .lang-switch a.active {
  color: var(--primary-950);
  background: var(--turquoise);
}

@media (max-width: 1180px) {
  .lang-switch {
    margin: 10px 0 0;
    padding: 12px 0 0;
    border-left: 0;
    border-top: 1px solid rgba(255,255,255,.14);
  }
}

/* ══ Cabecera de la portada, con fondo dibujado ═══════════════════════
   El fondo lo pinta `assets/js/hero.js` sobre un canvas. Aquí queda el
   degradado de respaldo: si el canvas no llega a dibujar, la cabecera
   sigue presentable y el texto legible. */

.home-main-hero.hero-animado {
  min-height: 100svh;
  border-bottom: 0;
  /* Respaldo del canvas, con el mismo criterio: el azul sólido anclado en
     la esquina inferior derecha y abriéndose hacia arriba y hacia la
     izquierda. Radial y no lineal, porque un lineal solo tiene una
     dirección y no puede degradar hacia los dos lados a la vez. */
  /* El radio va cerca del tamaño del lienzo a propósito: más grande, el
     arco cruza tan abierto que el borde se lee como un corte recto en vez
     de como una curva. */
  background:
    radial-gradient(86% 96% at 100% 104%,
      #0A1230 0%, #123258 18%, #3E6E9E 36%, #6FA9D0 52%, #DCECF7 74%, #F6FAFE 88%, #FFFFFF 100%);
}

.hero-lienzo {
  position: absolute;
  inset: 0;
  z-index: 0;
  display: block;
  width: 100%;
  height: 100%;
}

.hero-animado .hero-copy {
  position: relative;
  z-index: 1;
  min-height: 100svh;
  /* Hasta el 45 %: es la zona que el fondo mantiene despejada. */
  width: min(680px, 45vw);
}

.hero-animado .eyebrow {
  /* El teal de marca da 1,59:1 sobre este fondo y el texto pequeño pide
     4,5:1. Este cian oscurecido da 5,55:1 y mantiene la familia. */
  color: #0069A8;
  letter-spacing: .24em;
}

.hero-animado h1 { color: var(--primary-900); }

/* El remate del titular arranca en un teal oscurecido, 4,79:1, en lugar
   del de marca: así el degradado se lee sobre fondo claro. */
.hero-animado h1 span {
  background: linear-gradient(96deg, #0B7D6A, #2962FF 76%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.hero-animado .hero-filete {
  width: 96px;
  height: 4px;
  margin: 30px 0 26px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--brand-teal, #19E0C2), var(--brand-blue, #2962FF));
}

@media (max-width: 1180px) {
  .hero-animado .hero-copy { width: min(680px, 72vw); }
}

@media (max-width: 720px) {
  /* Un 13 % menos que la ventana. A pantalla completa sobraba blanco entre
     el párrafo y la franja, y el aire de más no aportaba nada: solo
     retrasaba la primera sección. Al acortarlo, el texto pasa a ocupar
     hasta el 75 % del hero en el caso más justo, todavía por encima de
     donde arranca la franja. */
  .home-main-hero.hero-animado,
  .hero-animado .hero-copy { min-height: 87svh; }

  /* Anclado arriba y no centrado. Centrado, el bloque bajaba hasta el 80 %
     del alto y la franja azul le cortaba las últimas líneas; arriba, el
     texto termina antes y la franja tiene su sitio debajo. */
  .hero-animado .hero-copy {
    width: auto;
    justify-content: flex-start;
    padding-top: 132px;
    padding-bottom: 0;
  }

  /* El respaldo sigue la misma composición que el lienzo: en vertical el
     azul es una franja a todo el ancho abajo, no un lóbulo de esquina. Una
     composición apaisada recortada a pantalla alta deja el color como una
     mancha en un rincón. */
  .home-main-hero.hero-animado {
    background:
      linear-gradient(180deg,
        #FFFFFF 0%, #FFFFFF 62%, #F6FAFE 72%, #DCECF7 80%, #6FA9D0 89%, #123258 96%, #0A1230 100%);
  }
}

/* ══ Cabecera de la portada ═══════════════════════════════════════════
   En la portada la cabecera es siempre de tema claro: tinta oscura,
   logotipo de fondo claro, sin la sombra de texto que existe para
   despegar los enlaces del fondo oscuro.

   Lo único que cambia al hacer scroll es el fondo. Sobre el hero va
   transparente; fuera de él, blanco — sin fondo, los enlaces se
   superpondrían al contenido de las secciones y no habría forma de
   leerlos. */

body.con-cabecera-clara .site-header:not(.header-solido) {
  background: none;
  box-shadow: none;
  border-bottom: 0;
  /* Sin desenfoque: es lo que producía el efecto de cristal esmerilado
     sobre la malla del fondo. */
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

/* El velo interior se quita del todo, no se le baja la opacidad: con
   `opacity: 0` el elemento sigue creando capa y en algunos navegadores
   deja un canto visible. */
body.con-cabecera-clara .site-header:not(.header-solido)::before { content: none; }

body.con-cabecera-clara .site-header:not(.header-solido) .main-nav a,
body.con-cabecera-clara .site-header:not(.header-solido) .menu-toggle {
  color: var(--primary-900);
}

body.con-cabecera-clara .site-header:not(.header-solido) .main-nav a.active { color: #0069A8; }

/* La sombra de los enlaces existe para separarlos del fondo oscuro. Aquí
   no separa de nada: solo emborrona el texto. */
body.con-cabecera-clara .site-header:not(.header-solido) .main-nav a { text-shadow: none; }

/* El descriptor junto al logotipo no está en el diseño de la portada y
   compite con el titular, que dice lo mismo con más fuerza. */
body.con-cabecera-clara .site-header .brand-tagline { display: none; }

body.con-cabecera-clara .site-header:not(.header-solido) .lang-switch { border-left-color: rgba(10, 18, 48, .18); }
body.con-cabecera-clara .site-header:not(.header-solido) .lang-switch a { color: rgba(31, 41, 51, .66); }

body.con-cabecera-clara .site-header:not(.header-solido) .lang-switch a.active {
  color: #fff;
  background: var(--primary-900);
}

/* Dos logotipos y no uno con filtro: el de fondo claro tiene tinta oscura
   y el de fondo oscuro va en negativo. Un filtro no convierte uno en otro
   sin ensuciar el degradado del isotipo.

   Se cruzan con opacidad, no con `display`. Con `display` el logotipo
   cambiaba de golpe mientras el fondo sí transicionaba, y ese desfase era lo
   que hacía que el cambio se leyera brusco: una propiedad no se puede
   animar, la otra sí.

   Para superponerlos, el claro se posiciona sobre el oscuro. Los dos son el
   mismo archivo en dos versiones, así que ocupan exactamente lo mismo. */
.site-header .brand { position: relative; }

.site-header .brand img.brand-oscuro,
.site-header .brand img.brand-claro {
  transition: opacity .38s cubic-bezier(.22,.61,.36,1);
}
.site-header .brand img.brand-claro {
  position: absolute;
  top: 0;
  left: 0;
  opacity: 0;
}
.site-header .brand img.brand-oscuro { opacity: 1; }

body.con-cabecera-clara .site-header:not(.header-solido) .brand img.brand-oscuro { opacity: 0; }
body.con-cabecera-clara .site-header:not(.header-solido) .brand img.brand-claro { opacity: 1; }

/* ── Fuera del hero: la misma cabecera que el resto del sitio ─────────

   Antes pasaba a fondo blanco. Ahora no hace falta ninguna regla: todo el
   tema claro de arriba está acotado con `:not(.header-solido)`, así que al
   volverse sólida deja de aplicarse y reaparece el cristal oscuro base —el
   mismo de todas las demás vistas— con su logotipo, sus enlaces claros y su
   desenfoque.

   Es mejor que el blanco por dos motivos: la cabecera queda igual en todo el
   sitio, y el salto de transparente a blanco sobre el hero animado era un
   corte mucho más brusco que el de transparente a cristal oscuro. */

/* Aire en la cabecera de la portada.
   Sobre un hero a pantalla completa, los 88 px de la cabecera compacta
   dejaban el logotipo pegado al borde. Al salir del hero vuelve a la
   altura compacta: ahí se está leyendo contenido y una cabecera fija
   alta se come demasiada pantalla. */

body.con-cabecera-clara .site-header:not(.header-solido) {
  min-height: 118px;
  padding-top: 26px;
  padding-bottom: 22px;
}

@media (max-width: 720px) {
  body.con-cabecera-clara .site-header:not(.header-solido) {
    min-height: 92px;
    padding-top: 16px;
    padding-bottom: 14px;
  }
}

/* La portada con cabecera animada empieza en el borde de la pantalla: el
   menú va transparente por encima del propio diseño. El margen de 104 px
   que separaba el hero de la cabecera fija dejaba una banda del fondo del
   body arriba, y esa banda es lo que parecía un fondo del navbar. */
body.con-cabecera-clara main > .home-main-hero.hero-animado:first-child {
  margin-top: 0;
}

/* Escala de la cabecera animada.
   El hero ocupa la pantalla entera y con los tamaños heredados el bloque
   de texto se quedaba flotando en el tercio central. Se sube la escala y
   se ensancha la columna a la vez: con más cuerpo y el mismo ancho, el
   titular se partiría en cuatro líneas en lugar de tres. */

.hero-animado .hero-copy {
  width: min(820px, 52vw);
  gap: 0;
}

.hero-animado .eyebrow {
  margin-bottom: 22px;
  font-size: 14px;
}

.hero-animado .eyebrow::after { width: 62px; }

.home-main-hero.hero-animado h1 {
  max-width: 820px;
  font-size: clamp(46px, 5vw, 78px);
  line-height: 1.04;
  letter-spacing: -.03em;
}

.hero-animado .hero-filete {
  width: 118px;
  margin: 34px 0 28px;
}

.home-main-hero.hero-animado .hero-copy p {
  max-width: 640px;
  font-size: clamp(17px, 1.22vw, 20px);
  line-height: 1.62;
}

@media (max-width: 1180px) {
  .hero-animado .hero-copy { width: min(820px, 74vw); }
}

@media (max-width: 720px) {
  .home-main-hero.hero-animado h1 { font-size: clamp(38px, 11vw, 54px); }
  .home-main-hero.hero-animado .hero-copy p { font-size: 17px; }
}

/* ══ Menú desplegable en móvil ════════════════════════════════════════
   El panel tiene fondo azul muy oscuro, así que el tema claro de la
   portada no puede alcanzarlo: el texto quedaba en #101B3D sobre #1F2436,
   1,09:1 cuando el mínimo para texto pequeño es 4,5:1. Prácticamente
   invisible.

   Dentro del panel el texto vuelve a blanco, 15,4:1. */

@media (max-width: 1180px) {
  body.con-cabecera-clara .site-header .main-nav.open a,
  body.con-cabecera-clara .site-header .main-nav.open .lang-switch a {
    color: #fff;
  }

  body.con-cabecera-clara .site-header .main-nav.open a.active { color: var(--turquoise, #19E0C2); }

  body.con-cabecera-clara .site-header .main-nav.open .lang-switch {
    border-left-color: rgba(255, 255, 255, .22);
  }

  body.con-cabecera-clara .site-header .main-nav.open .lang-switch a { color: rgba(255, 255, 255, .7); }

  /* El idioma activo se invierte: sobre el panel oscuro, la píldora va
     clara con tinta oscura. Al revés no se distinguiría del fondo. */
  body.con-cabecera-clara .site-header .main-nav.open .lang-switch a.active {
    color: var(--primary-900);
    background: #fff;
  }

  /* El botón del menú vive fuera del panel, sobre la cabecera, así que
     sigue el tema de la cabecera y no el del panel. */
  body.con-cabecera-clara .site-header:not(.header-solido) .menu-toggle { color: var(--primary-900); }
}

/* Pantallas verticales cortas.
   El texto ocupa proporcionalmente más y llegaría a la franja azul, así
   que se compacta: menos aire arriba y un titular algo menor. El fondo
   hace lo suyo por su lado, retirando la franja. */
@media (max-width: 720px) and (max-height: 700px) {
  .hero-animado .hero-copy { padding-top: 104px; }
  .home-main-hero.hero-animado h1 { font-size: clamp(34px, 9.4vw, 44px); }
  .home-main-hero.hero-animado .hero-copy p { font-size: 16px; line-height: 1.55; }
  .hero-animado .hero-filete { margin: 24px 0 20px; }

  .home-main-hero.hero-animado {
    background:
      linear-gradient(180deg,
        #FFFFFF 0%, #FFFFFF 72%, #F6FAFE 80%, #DCECF7 87%, #6FA9D0 93%, #123258 97%, #0A1230 100%);
  }
}

/* ══ Cabecera de la portada: solidez continua ═════════════════════════
   `--cabecera-solidez` va de 0 a 1 y lo escribe `app.js` en cada fotograma
   de scroll. Todo lo que cambiaba entre los dos temas se interpola con esa
   variable, así que la barra no conmuta: se oscurece.

   Estas reglas van DESPUÉS de las del tema claro a propósito. Aquellas
   siguen ahí para el caso de que el script no llegue a ejecutarse: sin
   variable, la portada se queda con su cabecera transparente, que es el
   estado en el que nace y el que corresponde arriba del todo.

   Las transiciones no hacen falta —y estorban—: el valor ya cambia de forma
   continua, y una transición encima lo retrasaría respecto del scroll. */

body.con-cabecera-clara .site-header {
  --cabecera-solidez: 0;

  transition: transform .26s ease;

  /* Del transparente al cristal oscuro, en el mismo tono que el resto del
     sitio. */
  background:
    linear-gradient(180deg,
      rgba(10, 18, 48, var(--cabecera-solidez)) 0%,
      rgba(10, 18, 48, var(--cabecera-solidez)) 100%);

  /* El desenfoque y el oscurecido arrancan en neutro: `blur(0)` y
     `brightness(1)` no tocan nada, así que sobre el hero el fondo se ve
     limpio. */
  -webkit-backdrop-filter:
    blur(calc(28px * var(--cabecera-solidez)))
    saturate(calc(100% + 90% * var(--cabecera-solidez)))
    brightness(calc(1 - 0.7 * var(--cabecera-solidez)));
  backdrop-filter:
    blur(calc(28px * var(--cabecera-solidez)))
    saturate(calc(100% + 90% * var(--cabecera-solidez)))
    brightness(calc(1 - 0.7 * var(--cabecera-solidez)));

  box-shadow:
    0 6px 22px rgba(2, 8, 28, calc(0.08 * var(--cabecera-solidez))),
    inset 0 1px 0 rgba(255, 255, 255, calc(0.16 * var(--cabecera-solidez)));
}

/* La altura NO se interpola con la variable.

   Estaba con `min-height` y los rellenos calculados desde `--cabecera-solidez`,
   y eso obliga al navegador a rehacer el diseño de la página entera en cada
   fotograma de scroll. Es carísimo y era la causa del tirón.

   El reparto correcto es: lo que sólo pinta —fondo, desenfoque, sombra,
   color— puede ir por fotograma; lo que mueve cajas va por clase, una sola
   vez, con su transición.

   La clase la conmuta el script al pasar de la mitad del recorrido. */
body.con-cabecera-clara .site-header:not(.header-solido) {
  min-height: 118px;
  padding-top: 26px;
  padding-bottom: 22px;
  transition:
    transform .26s ease,
    min-height .38s cubic-bezier(.22,.61,.36,1),
    padding .38s cubic-bezier(.22,.61,.36,1);
}
body.con-cabecera-clara .site-header.header-solido {
  transition:
    transform .26s ease,
    min-height .38s cubic-bezier(.22,.61,.36,1),
    padding .38s cubic-bezier(.22,.61,.36,1);
}

/* El velo interior vuelve a hacer falta, pero sólo a medida que la barra se
   oscurece. */
body.con-cabecera-clara .site-header::before {
  content: "";
  opacity: var(--cabecera-solidez);
  transition: none;
}

/* Y el desvanecido de debajo aparece con ella. */
body.con-cabecera-clara .site-header::after {
  opacity: var(--cabecera-solidez);
  transition: none;
}

/* Los colores se mezclan entre los dos temas con `color-mix`, que es lo que
   permite interpolar un color con un escalar. */
body.con-cabecera-clara .site-header .main-nav a {
  color: color-mix(
    in srgb,
    rgba(255, 255, 255, .9) calc(var(--cabecera-solidez) * 100%),
    var(--primary-900)
  );
  transition: none;
}

body.con-cabecera-clara .site-header .main-nav a.active {
  color: color-mix(in srgb, #fff calc(var(--cabecera-solidez) * 100%), #0069A8);
}

body.con-cabecera-clara .site-header .lang-switch {
  border-left-color: color-mix(
    in srgb,
    rgba(255, 255, 255, .34) calc(var(--cabecera-solidez) * 100%),
    rgba(10, 18, 48, .18)
  );
}

body.con-cabecera-clara .site-header .lang-switch a {
  color: color-mix(
    in srgb,
    rgba(255, 255, 255, .72) calc(var(--cabecera-solidez) * 100%),
    rgba(31, 41, 51, .66)
  );
}

/* Los dos logotipos se cruzan con el mismo valor. */
body.con-cabecera-clara .site-header .brand img.brand-oscuro {
  opacity: var(--cabecera-solidez);
  transition: none;
}
body.con-cabecera-clara .site-header .brand img.brand-claro {
  opacity: calc(1 - var(--cabecera-solidez));
  transition: none;
}

/* El botón de menú, igual. */
body.con-cabecera-clara .site-header .menu-toggle {
  color: color-mix(in srgb, #fff calc(var(--cabecera-solidez) * 100%), var(--primary-900));
  border-color: color-mix(
    in srgb,
    rgba(255, 255, 255, .48) calc(var(--cabecera-solidez) * 100%),
    rgba(10, 18, 48, .30)
  );
  background: color-mix(
    in srgb,
    rgba(255, 255, 255, .14) calc(var(--cabecera-solidez) * 100%),
    rgba(255, 255, 255, .58)
  );
}

/* Salvo cuando el menú está abierto: ese panel es oscuro siempre y sus
   enlaces tienen que ir claros pase lo que pase con la barra. */
@media (max-width: 1180px) {
  body.con-cabecera-clara .site-header .main-nav.open a {
    color: rgba(255, 255, 255, .92);
  }
}

/* ── Preguntas frecuentes ─────────────────────────────────────────────
   Reutiliza `.line-item` de las lineas de negocio: es el mismo plegable y no
   tenia sentido un segundo juego de estilos para lo mismo. Aqui va solo el
   titulo de cada grupo. */
/* Aire entre bloques: de 40 a 76 px.
   Con 40 las preguntas del segundo bloque quedaban casi pegadas a las del
   primero y los dos grupos se leian como una sola lista larga. */
.faq-section .faq-lines + .faq-grupo { margin-top: 76px; }

/*
 * Encabezado de bloque: centrado y en Azul Electrico.
 *
 * Estaba en Azul Profundo, el mismo color del titular de las preguntas, asi
 * que no separaba nada: era otro texto oscuro mas.
 *
 * Se probo el Azul Electrico del manual a secas y gritaba: esta al 100 % de
 * saturacion y se comia la atencion de las propias preguntas, que son lo que
 * hay que leer. Este es el mismo azul bajado de saturacion al 76 %, el que ya
 * usa el panel de administracion. Sigue siendo otro azul de verdad —a 180 de
 * distancia del Azul Profundo— y encima contrasta mejor: 6,28:1 sobre el fondo
 * de la seccion, frente a los 4,64:1 del electrico puro.
 *
 * El Cian tambien se probo y se cae a 2,34:1: no sirve para leer.
 *
 * Debajo va el filete del gradiente de marca, que es como el sitio marca los
 * encabezados en el resto de las secciones.
 */
.faq-grupo {
  display: grid;
  justify-items: center;
  gap: 12px;
  width: 100%;
  margin: 0 0 26px;
  color: #1e4fd8;
  font-size: 21px;
  font-weight: 800;
  text-align: center;
}

.faq-grupo::after {
  content: "";
  width: 54px;
  height: 2px;
  border-radius: 999px;
  background: var(--brand-gradient);
}
/* Sin icono a la izquierda, el titulo puede ocupar todo el ancho de la fila. */
.faq-item summary { gap: 20px; }

/* ── Equipo ───────────────────────────────────────────────────────────
   Sustituye a «Por que Maude Mobility?» en Quienes somos.

   El retrato va redondo con el degradado de marca como anillo: es el mismo
   teal -> cian -> azul electrico del manual, y resuelve de paso el caso de
   que todavia no haya fotografia.

   Contraste calculado sobre el fondo de la tarjeta, que es blanco puro:
     - nombre  #0A1230 ..................... 18,4:1
     - cargo   #0069A8 .....................  5,9:1
     - bio     rgba(31,41,51,.72) ..........  5,9:1
   Los tres pasan 4,5:1, el minimo para texto normal. El cargo va en 13px y
   mayusculas, que es donde mas facil es quedarse corto: por eso no usa el
   teal de marca, que sobre blanco da 1,6:1 y seria ilegible. */
/* `align-items: start` para que cada tarjeta conserve su alto.
   Por defecto la reticula las estira a la altura de la fila, y al desplegarse
   una la otra crecia con ella dejando medio metro de blanco debajo de su
   texto. Recortadas miden lo mismo igualmente, que es de lo que se trataba. */
.staff-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
  align-items: start;
  gap: 24px;
}

.staff-card {
  display: grid;
  grid-template-columns: 132px minmax(0, 1fr);
  align-items: start;
  gap: 26px;
  padding: 30px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: white;
  box-shadow: var(--soft-shadow);
  transition: transform .18s ease, box-shadow .18s ease;
}
.staff-card:hover,
.staff-card:focus-within,
.staff-card:focus-visible {
  transform: translateY(var(--alza-tarjeta));
  border-color: var(--borde-hover);
  box-shadow: var(--sombra-hover);
  outline: none;
}

/* El filete de marca, como en las tarjetas de area: es el gesto que dice
   «esta es la que estas mirando» sin mover nada de sitio. */
.staff-card {
  position: relative;
  overflow: hidden;
}

.staff-card::before {
  content: "";
  position: absolute;
  inset-inline: 0;
  top: 0;
  height: 3px;
  background: var(--brand-gradient);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .3s cubic-bezier(.22,.61,.36,1);
}

.staff-card:hover::before,
.staff-card:focus-within::before,
.staff-card:focus-visible::before {
  transform: scaleX(1);
}

/* El anillo es el degradado; el hueco interior lo hace el `padding` mas el
   fondo blanco del `img`, sin recortes ni mascaras.

   `.marco-retrato` lo comparte: la foto del perfil y la del CV del Portal usan
   el mismo tratamiento. Declarado aqui una sola vez a proposito, porque dos
   degradados escritos aparte se separan al primer retoque de la paleta. El
   tamano si lo pone cada uno. */
.staff-retrato,
.marco-retrato {
  display: block;
  padding: 3px;
  border-radius: 50%;
  background: linear-gradient(135deg, #19E0C2, #00B4FF 46%, #2962FF);
}
.staff-retrato {
  width: 132px;
  height: 132px;
}
.staff-retrato img,
.marco-retrato img,
.marco-retrato > span,
.staff-iniciales {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
  background: white;
}
.staff-iniciales {
  display: grid;
  place-items: center;
  color: var(--primary-950);
  font-size: 38px;
  font-weight: 800;
  letter-spacing: .02em;
}

.staff-nombre {
  margin: 2px 0 0;
  color: var(--primary-950);
  font-size: 22px;
  font-weight: 800;
  line-height: 1.25;
}
.staff-cargo {
  display: block;
  margin-top: 6px;
  color: #0069a8;
  font-size: 13px;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
}
/*
 * La biografia: recortada, y entera al pasar por encima.
 *
 * Las que entrega Maude tienen cinco o seis parrafos y son de largo distinto,
 * asi que sin recortar las dos tarjetas quedaban de alturas muy diferentes.
 * Recortadas a siete lineas se ven iguales, y quien quiera leerla entera pasa
 * por encima —o tabula, o la toca en un movil, porque la tarjeta es enfocable.
 *
 * El recorte es por alto y no con `line-clamp` porque son varios parrafos y
 * `line-clamp` solo sabe recortar un bloque. El degradado del final y los tres
 * puntos son lo que avisa de que hay mas.
 *
 * **Se despliega con la fila de la rejilla, no con `max-height`.** El primer
 * intento animaba `max-height` de 7 lineas a un techo de 90 em, porque
 * `max-height: none` no se puede animar y hacia falta un numero. Pero el
 * navegador reparte la duracion sobre el recorrido *declarado*, no sobre el que
 * se ve: el texto llega a su alto real —51 em la biografia mas larga, medido— y
 * ahi se para, con el 49 % restante del recorrido consumiendose sin que pase
 * nada. De 450 ms solo se veian 175. Y encima la curva es de salida rapida, asi
 * que lo unico visible era el tramo veloz. De ahi el golpe.
 *
 * Con la fila en `minmax(<7 lineas>, 0fr)` y el envoltorio de dentro recortando,
 * `1fr` resuelve al alto exacto del contenido: el recorrido declarado y el que
 * se ve son el mismo, y la duracion es la que dice. Comprobado midiendo el alto
 * cada 100 ms — llega a 448 px de 448 reales, sin sobrar recorrido.
 *
 * `--lineas` esta aqui arriba para poder cambiarlo en un sitio.
 */
.staff-bio {
  --lineas: 7;

  position: relative;
  display: grid;
  grid-template-rows: minmax(calc(var(--lineas) * 1.7em), 0fr);
  margin: 14px 0 0;
  color: var(--muted);
  font-size: 15.5px;
  line-height: 1.7;
  /* Arranca despacio y frena al final. Con una curva de salida rapida el
     primer tercio se comia media biografia y volvia a parecer un golpe, aunque
     el recorrido ya fuera el correcto. */
  transition: grid-template-rows .55s cubic-bezier(.4, 0, .2, 1);
}

/* Este es el que recorta: la fila le da el alto y el sobrante se esconde. */
.staff-bio-texto {
  overflow: hidden;
}

/* El degradado tapa la ultima linea a medias en vez de cortarla en seco, y los
   puntos suspensivos dicen que sigue. */
.staff-bio::after {
  content: "…";
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  padding-top: 26px;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0), #fff 62%);
  color: var(--muted);
  text-align: right;
  /* Se va antes de que el texto termine de crecer, y no al reves: si el velo
     sigue puesto mientras se despliega, tapa las lineas que van apareciendo. */
  transition: opacity .22s ease;
}

.staff-card:hover .staff-bio,
.staff-card:focus-within .staff-bio,
.staff-card:focus-visible .staff-bio {
  grid-template-rows: minmax(calc(var(--lineas) * 1.7em), 1fr);
}

.staff-card:hover .staff-bio::after,
.staff-card:focus-within .staff-bio::after,
.staff-card:focus-visible .staff-bio::after {
  opacity: 0;
}

/* En una columna las tarjetas no compiten en alto, asi que no hay nada que
   igualar: la biografia va entera desde el principio. */
@media (max-width: 720px) {
  .staff-bio {
    grid-template-rows: auto;
  }

  .staff-bio::after {
    display: none;
  }
}

/* Movimiento reducido: se despliega igual, pero sin animar el alto. */
@media (prefers-reduced-motion: reduce) {
  .staff-bio {
    transition: none;
  }
}

.staff-bio p {
  margin: 0;
}

.staff-bio p + p {
  margin-top: 12px;
}

/* Los enlaces se envuelven: con LinkedIn y correo juntos, en una tarjeta
   estrecha el segundo se salia. */
.staff-enlaces {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 12px;
}

/* ── Organigrama ────────────────────────────────────────────────────────
   Las áreas del grupo, debajo de las dos direcciones. No es una tabla de
   datos ni una lista más: es el nivel siguiente del esquema, y tiene que
   leerse como que cuelga de lo de arriba.

   Lo que lo ata: el mismo filete de marca que llevan las tarjetas del equipo,
   y la misma retícula de dos columnas. */
.organigrama {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
  gap: 24px;
  margin: 40px 0 0;
}

.organigrama-bloque {
  position: relative;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: white;
  box-shadow: var(--soft-shadow);
}

/* El canto de marca, arriba y a todo el ancho. Fijo y no al pasar por
   encima: aquí no hay nada que pulsar. */
.organigrama-bloque::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 3px;
  background: var(--brand-gradient);
}

.organigrama dt {
  padding: 22px 26px 16px;
  color: var(--primary-950);
  font-size: 13px;
  font-weight: 900;
  /* Las mayúsculas las pone el CSS y no el archivo de idioma: escritas allí
     serían irreversibles y algunos lectores de pantalla las deletrean. */
  text-transform: uppercase;
  letter-spacing: .16em;
}

.organigrama dd {
  margin: 0;
  padding: 13px 26px;
  border-top: 1px solid var(--border);
  color: var(--text);
  font-size: 15.5px;
  line-height: 1.4;
}

@media (max-width: 720px) {
  .organigrama { gap: 16px; margin-top: 28px; }
  .organigrama dt { padding: 18px 20px 14px; }
  .organigrama dd { padding: 12px 20px; font-size: 15px; }
}

/* 48x48 minimo de area tactil, aunque el icono se vea mas pequeno: por debajo
   de eso falla en un movil. */
.staff-enlace {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 48px;
  padding: 0 16px 0 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  color: var(--primary-900);
  font-size: 14px;
  font-weight: 750;
  text-decoration: none;
  transition: border-color .18s ease, color .18s ease;
}
.staff-enlace i { flex: none; font-size: 18px; }

/* El correo puede ser largo; que corte antes de desbordar la tarjeta. */
.staff-enlace span { overflow-wrap: anywhere; }

.staff-enlace:hover,
.staff-enlace:focus-visible {
  border-color: rgba(0,180,255,.5);
  color: var(--electric-blue);
}

/* Por debajo de 720 la tarjeta se apila y el retrato se centra: a dos
   columnas en un movil el texto queda en cuatro palabras por linea. */
@media (max-width: 720px) {
  .staff-card {
    grid-template-columns: 1fr;
    justify-items: center;
    text-align: center;
    gap: 18px;
  }
}

/* ── Portal de Empleo: listado y ficha de oferta ─────────────────────
   Reutiliza el lenguaje de tarjeta del resto del sitio —fondo blanco, borde
   fino, radio medio, filete de marca al pasar por encima— para que el portal
   se vea parte de la web y no un injerto.

   Contraste medido sobre el fondo de la tarjeta:
     titulo  #0A1230 ..... 18,4:1
     empresa var(--muted)   5,9:1
     enlace  #2258E0 ...... 5,1:1  (el azul de marca da 4,9 y tambien pasa;
                                    este se usa por continuidad con el resto) */
/* Estas dos paginas no llevan hero, asi que el despeje de la cabecera fija lo
   pone la propia seccion. Es el mismo valor que usan los heros interiores: la
   barra mide 104px y el aire de arriba, el resto. */
main > .oportunidades-listado:first-child,
main > .oferta-detalle:first-child {
  padding-top: 148px;
}

.ofertas-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 18px;
  margin-top: 26px;
}

.oferta-card {
  position: relative;
  display: grid;
  align-content: start;
  gap: 10px;
  padding: 24px 22px 22px;
  overflow: hidden;
  border: 1px solid rgba(16, 27, 61, .1);
  border-radius: var(--radius-md);
  background: rgba(255, 255, 255, .92);
  box-shadow: var(--soft-shadow);
  transition: transform .24s cubic-bezier(.22,.61,.36,1), box-shadow .24s ease, border-color .24s ease;
}

.oferta-card::before {
  content: "";
  position: absolute;
  inset-inline: 0;
  top: 0;
  height: 3px;
  background: var(--brand-gradient);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .3s cubic-bezier(.22,.61,.36,1);
}

.oferta-card:hover,
.oferta-card:focus-within {
  transform: translateY(var(--alza-tarjeta));
  border-color: var(--borde-hover);
  box-shadow: var(--sombra-hover);
}

.oferta-card:hover::before,
.oferta-card:focus-within::before { transform: scaleX(1); }

/* El logotipo, con alto fijo y ancho automatico: con ancho fijo, uno apaisado
   y uno cuadrado se pintan a tamanos muy distintos y la rejilla se ve
   desigual. Es la misma regla que la tira de colaboradores. */
.oferta-empresa img {
  height: 34px;
  width: auto;
  max-width: 140px;
  object-fit: contain;
}

.oferta-empresa-nombre,
.oferta-empresa-linea {
  margin: 0;
  color: var(--muted);
  font-size: 14px;
  font-weight: 600;
}

.oferta-card h3 {
  margin: 0;
  font-size: 19px;
  line-height: 1.25;
  text-wrap: balance;
}

.oferta-card h3 a { color: var(--primary-950); }

.oferta-card h3 a:hover,
.oferta-card h3 a:focus-visible { color: #2258e0; }

.oferta-datos {
  display: grid;
  gap: 6px;
  margin: 4px 0 0;
  padding: 0;
  list-style: none;
  color: var(--muted);
  font-size: 14.5px;
}

.oferta-datos li {
  display: flex;
  align-items: center;
  gap: 8px;
}

.oferta-datos i { color: #2258e0; font-size: 15px; }

.oferta-ver {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 6px;
  padding-top: 14px;
  border-top: 1px solid rgba(16, 27, 61, .08);
  color: #2258e0;
  font-weight: 700;
  font-size: 15px;
}

.oferta-ver i { transition: transform .24s cubic-bezier(.22,.61,.36,1); }
.oferta-card:hover .oferta-ver i { transform: translateX(4px); }

.resultado-cuenta { margin: 22px 0 0; color: var(--muted); font-size: 14.5px; }
.aviso-vacio { margin: 26px 0; color: var(--muted); }

/* ── La ficha ─────────────────────────────────────────────────────── */
.migas { margin: 0 0 18px; font-size: 14px; }
.migas a { color: #2258e0; font-weight: 600; }

.oferta-cabecera {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 20px;
  padding-bottom: 22px;
  border-bottom: 1px solid var(--border);
}

.oferta-logo { height: 46px; width: auto; max-width: 170px; object-fit: contain; }
.oferta-titular { min-width: 0; }
.oferta-cabecera h1 { margin: 6px 0 0; font-size: clamp(28px, 3.2vw, 40px); }
.oferta-cabecera .oferta-empresa-linea { margin-top: 8px; font-size: 15.5px; }
.oferta-cabecera .oferta-empresa-linea span { font-weight: 500; }

/* El aviso de oferta cerrada: en ambar y no en rojo. No es un error, es un
   estado, y el rojo en una pagina publica se lee como que algo se ha roto. */
.oferta-cerrada {
  margin: 0;
  margin-left: auto;
  padding: 8px 14px;
  border-radius: var(--radius-pill);
  background: rgba(180, 120, 10, .12);
  color: #8a5a06;
  font-size: 14px;
  font-weight: 700;
}

/* La ficha se lee centrada y no ocupando toda la pantalla.

   `.section` mide hasta 1.580 px, que esta bien para una rejilla de tarjetas y
   mal para leer: el texto se corta a 70 caracteres —el limite de linea legible,
   que no se toca— y en un monitor ancho quedaban dos columnas separadas por un
   hueco enorme. Con el tope aqui, las dos columnas viajan juntas y centradas.

   1.140 px es el ancho al que la columna de texto llega a sus 70 caracteres
   con la tarjeta al lado: mas seria hueco otra vez. */
.oferta-detalle > * {
  max-width: 1140px;
  margin-inline: auto;
}

/* Dos columnas: el texto a la izquierda y los datos a la derecha.

   Con una sola, el texto se quedaba en un tercio del ancho y la mitad derecha
   de la pagina estaba vacia. La tarjeta de la derecha no es relleno: lleva el
   salario, los datos y el boton, que es lo que se consulta mientras se lee la
   oferta. */
.oferta-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: 40px;
  align-items: start;
  margin-top: 30px;
}

.oferta-cuerpo { max-width: 70ch; }
.oferta-cuerpo h2 { margin: 30px 0 10px; font-size: 21px; }
.oferta-cuerpo h2:first-child { margin-top: 0; }
.oferta-cuerpo p { margin: 0; color: var(--text); }

.oferta-web { color: #2258e0; font-weight: 700; }

/* La tarjeta acompana al desplazarse: la oferta es larga y el boton no puede
   quedarse arriba del todo. `top` descuenta la cabecera fija. */
.oferta-resumen { position: sticky; top: calc(var(--alto-cabecera) + 20px); }

.oferta-resumen-caja {
  padding: 24px 22px;
  border: 1px solid rgba(16, 27, 61, .1);
  border-radius: var(--radius-md);
  background: rgba(255, 255, 255, .94);
  box-shadow: var(--soft-shadow);
}

/* El salario primero y en grande: es el dato que mas se busca de una oferta. */
.oferta-salario {
  margin: 0 0 18px;
  color: var(--primary-950);
  font-size: 21px;
  font-weight: 800;
  line-height: 1.25;
}

.oferta-ficha {
  display: grid;
  gap: 14px;
  margin: 0 0 22px;
  padding: 22px 0 0;
  border-top: 1px solid rgba(16, 27, 61, .08);
}

.oferta-ficha dt {
  display: flex;
  align-items: center;
  gap: 7px;
  color: var(--muted);
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
}

.oferta-ficha dt i { color: #2258e0; font-size: 14px; }
.oferta-ficha dd { margin: 3px 0 0 21px; color: var(--text); font-size: 15px; }

.oferta-boton { width: 100%; justify-content: center; }
.oferta-publicada { margin: 16px 0 0; color: var(--muted); font-size: 13px; }

/* ── Compartir ─────────────────────────────────────────────────────── */
.oferta-compartir { margin-top: 22px; }

.oferta-compartir-titulo {
  margin: 0 0 10px;
  color: var(--muted);
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
}

.oferta-compartir-botones { display: flex; gap: 10px; }

.oferta-compartir-botones a,
.oferta-compartir-botones button {
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  padding: 0;
  border: 1px solid rgba(16, 27, 61, .12);
  border-radius: 50%;
  background: white;
  color: var(--primary-950);
  font-size: 17px;
  cursor: pointer;
  transition: transform .2s ease, border-color .2s ease, color .2s ease;
}

.oferta-compartir-botones a:hover,
.oferta-compartir-botones button:hover,
.oferta-compartir-botones a:focus-visible,
.oferta-compartir-botones button:focus-visible {
  transform: translateY(var(--alza-tarjeta));
  border-color: var(--borde-hover);
  color: #2258e0;
}

/* Confirmar que se copio: sin esto, pulsar no dice nada y se pulsa otra vez. */
.oferta-copiar.copiado {
  border-color: #0d8474;
  color: #0d8474;
}

@media (prefers-reduced-motion: reduce) {
  .oferta-compartir-botones a,
  .oferta-compartir-botones button { transition-duration: .01ms; }
  .oferta-compartir-botones a:hover,
  .oferta-compartir-botones button:hover { transform: none; }
}

@media (max-width: 1180px) {
  .oferta-layout { grid-template-columns: minmax(0, 1fr); gap: 34px; }
  /* Sin `sticky` en una columna: la tarjeta iria persiguiendo al texto. */
  .oferta-resumen { position: static; }
}

.oferta-cuerpo .oferta-lista {
  display: grid;
  gap: 6px;
  margin: 10px 0 0;
  padding-left: 20px;
}

.oferta-cuerpo .oferta-lista li { color: var(--text); }
.oferta-cuerpo p + p { margin-top: 10px; }

.oferta-cierre {
  margin-top: 34px;
  padding-top: 24px;
  border-top: 1px solid var(--border);
}

.oferta-nota { margin: 12px 0 0; color: var(--muted); font-size: 14px; }

@media (prefers-reduced-motion: reduce) {
  .oferta-card,
  .oferta-card::before,
  .oferta-ver i { transition-duration: .01ms; }

  .oferta-card:hover,
  .oferta-card:focus-within { transform: none; }
}

@media (max-width: 720px) {
  .ofertas-grid { grid-template-columns: minmax(0, 1fr); }
  .oferta-cerrada { margin-left: 0; }
}

/* ── La marca de campo obligatorio ───────────────────────────────────
   Un asterisco junto al rotulo, y la leyenda que lo explica encima de la
   rejilla.

   Rojo de la familia «esto lo tienes que atender», no uno nuevo. Medido
   sobre el fondo de la tarjeta: 5,42:1, por encima del 4,5 que pide el
   texto pequeno. */
.campo-obligatorio {
  margin-left: 2px;
  color: #c2334d;
  font-weight: 800;
}

.form-leyenda {
  margin: 0 0 18px;
  color: var(--muted);
  font-size: 13.5px;
}

/* ── Las cuatro puertas de entrada ────────────────────────────────────
   «Quiero estudiar», «Quiero trabajar», «Soy una empresa» y «Quiero
   desarrollar un proyecto», bajo el titular de la portada.

   Cada tarjeta lleva uno de los colores del manual —teal, cian, azul
   electrico y azul profundo— en una sola variable, `--acento`, de la que
   cuelgan el disco del icono, la segunda linea del titulo, el filete de
   arriba y el enlace. Cambiar el color de una tarjeta desde el CRM es
   cambiar esa variable y nada mas.

   ⚠ La referencia que llego del cliente traia un violeta. **No esta en el
   manual** (§ paleta: azul profundo, teal, cian, azul electrico, gris claro
   y grafito), asi que las cuatro salen del gradiente de marca.

   Contraste calculado sobre el fondo blanco de la tarjeta:
     - titulo   #0A1230 ........ 18,4:1
     - texto    var(--muted) ... 5,9:1
   **El aro del disco lleva el hex exacto del manual en las cuatro.** Es donde
   el color de marca se puede usar tal cual, porque el contraste que importa
   ahi es el del glifo blanco sobre el relleno azul profundo: 18,4:1.

   Para **texto** solo dos de los cuatro aguantan, medido sobre blanco:
         azul electrico #2962FF ... 4,90:1  ✔ el hex del manual, tal cual
         azul profundo  #0A1230 .. 18,39:1  ✔ el hex del manual, tal cual
         cian           #00B4FF ... 2,34:1  ✘
         teal           #19E0C2 ... 1,68:1  ✘

   Los dos que no llegan usan la variante **mas viva que sigue pasando** 4,5,
   no una cualquiera mas oscura:
         cian  -> #0077B6 ... 4,87:1
         teal  -> #0D8474 ... 4,60:1

   Es la regla de siempre: no se cambia el color de marca, se le agrega una
   variante para texto y se anota el ratio aqui para que quien lo toque tenga
   que recalcularlo.
   El color de marca se conserva en el disco del icono, que es donde funciona:
   relleno azul profundo y el glifo en blanco, 18,4:1. */
.soluciones-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 18px;
}

/*
 * Tarjeta-puerta.
 *
 * **Es un enlace entero**, no un `<article>` con un renglon pulsable al pie:
 * el objetivo tactil es la tarjeta completa. De ahi que aqui si haya flecha y
 * si haya `cursor: pointer`, al reves que en las areas, que no llevan a ningun
 * sitio.
 *
 * El `grid` con la fila del enlace en `auto` y el texto empujando hace que las
 * cuatro flechas queden a la misma altura aunque los textos midan distinto.
 */
.solucion-card {
  --acento: #0d8474;
  --acento-marca: var(--turquoise);
  position: relative;
  display: grid;
  grid-template-rows: auto auto auto 1fr auto;
  gap: 10px;
  padding: 28px 24px 26px;
  overflow: hidden;
  border: 1px solid rgba(16, 27, 61, .1);
  border-radius: var(--radius-md);
  background: rgba(255, 255, 255, .92);
  box-shadow: var(--soft-shadow);
  color: inherit;
  transition:
    transform .24s cubic-bezier(.22,.61,.36,1),
    box-shadow .24s ease,
    border-color .24s ease;
}

.solucion-card.acento-teal     { --acento: #0d8474; --acento-marca: var(--turquoise); }
.solucion-card.acento-cian     { --acento: #0077b6; --acento-marca: var(--cyan); }
.solucion-card.acento-azul     { --acento: #2962ff; --acento-marca: var(--electric-blue); }
.solucion-card.acento-profundo { --acento: #0a1230; --acento-marca: var(--electric-blue); }

/* El filete de marca, arriba. Entra desde la izquierda al pasar por encima:
   tres pixeles, y no mueve nada de sitio. */
.solucion-card::before {
  content: "";
  position: absolute;
  inset-inline: 0;
  top: 0;
  height: 3px;
  background: var(--brand-gradient);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .3s cubic-bezier(.22,.61,.36,1);
}

.solucion-card:hover,
.solucion-card:focus-visible {
  transform: translateY(var(--alza-tarjeta));
  border-color: var(--borde-hover);
  box-shadow: var(--sombra-hover);
}

.solucion-card:hover::before,
.solucion-card:focus-visible::before {
  transform: scaleX(1);
}

/* El distintivo circular de marca, el mismo de las areas y del resto de
   tarjetas del sitio: relleno azul profundo, borde del acento y glifo blanco.
   El borde es lo unico que cambia entre las cuatro. */
.solucion-icono {
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  border: 3px solid var(--acento-marca);
  border-radius: 50%;
  background: var(--primary-950);
  color: white;
  font-size: 21px;
  transition: transform .24s cubic-bezier(.22,.61,.36,1), box-shadow .24s ease;
}

.solucion-card:hover .solucion-icono {
  transform: scale(1.08);
  box-shadow: 0 0 0 6px color-mix(in srgb, var(--acento-marca) 16%, transparent);
}

/* El cuarto lleva el gradiente de marca en el aro.
   Su acento es el azul profundo, que es justo el relleno del disco: el aro
   quedaba invisible. Se pinta con dos fondos —relleno hasta el borde interior,
   gradiente en el borde— que es la unica forma de degradar un `border` sin
   meter un elemento de mas. */
.solucion-card.acento-profundo .solucion-icono {
  border-color: transparent;
  background:
    linear-gradient(var(--primary-950), var(--primary-950)) padding-box,
    var(--brand-gradient) border-box;
}

/* El titular parte solo. Sin esto la ultima palabra caia sola en su linea. */
.soluciones-section .section-header h2 {
  text-wrap: balance;
}

.solucion-etiqueta {
  color: var(--acento);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .14em;
  text-transform: uppercase;
}

.solucion-card h3 {
  margin: 0;
  color: var(--primary-950);
  font-size: 22px;
  font-weight: 800;
  line-height: 1.2;
  text-wrap: balance;
}

/* La segunda linea, en color. Es la que separa «Quiero estudiar» de «en
   Espana», y va en bloque para que caiga siempre debajo aunque quepa al lado:
   la referencia del cliente son dos lineas y con `inline` el corte dependeria
   del ancho de la columna. */
.solucion-card h3 span {
  display: block;
  color: var(--acento);
}

.solucion-card p {
  margin: 0;
  color: var(--muted);
  font-size: 15px;
}

.solucion-cta {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 4px;
  padding-top: 14px;
  border-top: 1px solid rgba(16, 27, 61, .08);
  color: var(--acento);
  font-weight: 700;
  font-size: 15px;
}

.solucion-cta i {
  transition: transform .24s cubic-bezier(.22,.61,.36,1);
}

.solucion-card:hover .solucion-cta i {
  transform: translateX(4px);
}

/* Movimiento reducido: se quedan el color y el filete, se va el
   desplazamiento. Lo que informa el realce no depende de que algo se mueva. */
@media (prefers-reduced-motion: reduce) {
  .solucion-card,
  .solucion-card::before,
  .solucion-icono,
  .solucion-cta i {
    transition-duration: .01ms;
  }

  .solucion-card:hover,
  .solucion-card:focus-visible {
    transform: none;
  }

  .solucion-card:hover .solucion-icono,
  .solucion-card:hover .solucion-cta i {
    transform: none;
  }
}

@media (max-width: 1180px) {
  .soluciones-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 720px) {
  .soluciones-grid { grid-template-columns: minmax(0, 1fr); }
  .solucion-card { padding: 24px 20px; }
  .solucion-card h3 { font-size: 20px; }
}

/* ── Las cinco areas ──────────────────────────────────────────────────
   Formacion, talento, movilidad, empresas y alianzas, en la portada.

   Reutiliza el distintivo circular de marca del resto de tarjetas del sitio
   —52px, relleno azul profundo y borde cian— en vez de estrenar otro estilo
   de icono. Aqui va mas chico porque son cinco en una franja.

   Contraste calculado sobre el fondo de la tarjeta:
     - titulo  #0A1230 ..... 18,4:1
     - texto   var(--muted) . 5,9:1
   Los dos por encima de 4,5:1, el minimo para texto normal. */
.areas-grid {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 16px;
}

/*
 * Tarjeta de area.
 *
 * **No son enlaces.** Son `<article>`, no se pulsan ni se enfocan, asi que el
 * efecto tiene que decir «esto esta vivo» y no «esto se clica»: de ahi que no
 * lleve `cursor: pointer` ni flecha. Lo que sube es la presencia, no la
 * promesa.
 *
 * El realce se reparte en cuatro cosas pequenas en vez de una grande, que es
 * lo que hace que se note sin gritar: el filete de marca que aparece arriba,
 * un lavado de color muy tenue, la sombra que se tine de azul y el icono que
 * se enciende.
 */
.areas-grid article {
  position: relative;
  display: grid;
  align-content: start;
  gap: 12px;
  /* En variables porque el reverso, al salir del flujo, tiene que replicarlo
     exacto: si no coincide, la parte que sobresale sale más estrecha que la
     tarjeta y hace un escalón. */
  --area-pad-y: 26px;
  --area-pad-x: 22px;
  --area-pad-b: 28px;
  padding: var(--area-pad-y) var(--area-pad-x) var(--area-pad-b);
  overflow: hidden;
  border: 1px solid rgba(16, 27, 61, .1);
  border-radius: var(--radius-md);
  background: rgba(255, 255, 255, .9);
  box-shadow: 0 12px 28px rgba(10, 18, 48, .045);
  transition:
    transform .24s cubic-bezier(.22,.61,.36,1),
    box-shadow .24s ease,
    border-color .24s ease,
    background-color .24s ease;
}

/* El filete de marca, que entra desde la izquierda. Es el gesto que mas se ve
   y el que menos molesta: ocupa tres pixeles y no mueve nada de sitio. */
.areas-grid article::before {
  content: "";
  position: absolute;
  inset-inline: 0;
  top: 0;
  height: 3px;
  background: var(--brand-gradient);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .3s cubic-bezier(.22,.61,.36,1);
}

.areas-grid article:hover {
  transform: translateY(var(--alza-tarjeta));
  border-color: var(--borde-hover);
  background-color: #fbfeff;
  box-shadow: var(--sombra-hover);
}

.areas-grid article:hover::before {
  transform: scaleX(1);
}

/* Sólo el icono del frente. Era `.areas-grid i` y desde que la tarjeta tiene
   reverso eso alcanzaba también la flecha del enlace, que salía convertida en
   un disco de 46 px con borde de tres. */
.area-frente > i {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  border: 3px solid #00b4ff;
  border-radius: 50%;
  background: var(--primary-950);
  color: white;
  font-size: 19px;
  transition: transform .24s cubic-bezier(.22,.61,.36,1), box-shadow .24s ease;
}

/* El icono se enciende con un halo del cian de marca. El circulo se queda
   oscuro a proposito: es el contraste del glifo blanco encima. */
.areas-grid article:hover .area-frente > i {
  transform: scale(1.08);
  box-shadow: 0 0 0 6px rgba(0, 180, 255, .14);
}

/* Movimiento reducido: se quedan el color y el filete, se va el desplazamiento.
   La informacion del realce no depende de que algo se mueva. */
@media (prefers-reduced-motion: reduce) {
  .areas-grid article,
  .areas-grid article::before,
  .area-frente > i {
    transition-duration: .01ms;
  }

  .areas-grid article:hover {
    transform: none;
  }

  .areas-grid article:hover .area-frente > i {
    transform: none;
  }
}

/* ── El reverso de la tarjeta de área ───────────────────────────────────
   Al pasar por encima la tarjeta se voltea y enseña los servicios del área.

   **El color es el Azul Profundo del manual, no el teal.** La referencia que
   trajo el cliente es una tarjeta de color con texto blanco, y de los seis
   colores del manual sólo dos aguantan texto blanco encima: el Azul Profundo
   —17,4:1— y el Azul Eléctrico —4,6:1—. El teal da 1,6:1 y el cian 2,2:1: en
   esos dos el texto no se lee. El teal se queda para los iconos de la lista,
   que sobre el azul profundo sí resaltan.

   Rota `.area-giro` y no el `article`: la sombra y el borde son del `article`
   y voltearlos los pondría del revés. */
.areas-grid article.tiene-reverso {
  perspective: 1200px;
  /* No es un enlace, pero sí es enfocable y tiene algo debajo. */
  cursor: pointer;
}

.area-giro {
  position: relative;
  display: grid;
  transform-style: preserve-3d;
  transition: transform .55s cubic-bezier(.4, 0, .2, 1);
}

/* Las dos caras ocupan la misma celda de la rejilla: así la tarjeta mide lo
   que mida la más alta y las cinco de la fila quedan iguales, sin fijar un
   alto a ojo que se rompa al añadir un servicio desde el CRM. */
/*
 * Las dos caras ocupan la misma celda de la rejilla.
 *
 * Arriba y no centradas: al centrarlas, cada icono caía a una altura distinta
 * —cada tarjeta tiene otro texto— y la fila de cinco quedaba escalonada. Que el
 * icono de las cinco esté en la misma línea vale más que repartir el aire.
 */
.area-cara {
  grid-area: 1 / 1;
  display: grid;
  align-content: start;
  gap: 12px;
  backface-visibility: hidden;
}

/* El frente, centrado. El reverso no: una lista de servicios centrada obliga a
   buscar dónde empieza cada línea. */
.area-frente {
  justify-items: center;
  text-align: center;
}

.area-reverso {
  transform: rotateY(180deg);
  align-content: start;
}

.areas-grid article.tiene-reverso:hover .area-giro,
.areas-grid article.tiene-reverso:focus-visible .area-giro,
.areas-grid article.tiene-reverso:focus-within .area-giro {
  transform: rotateY(180deg);
}

/* El fondo azul lo pinta el `article`, no la cara: si lo pintara la cara, al
   girar se vería el blanco de debajo asomando por los bordes. */
.areas-grid article.tiene-reverso:hover,
.areas-grid article.tiene-reverso:focus-visible,
.areas-grid article.tiene-reverso:focus-within {
  border-color: var(--primary-950);
  background-color: var(--primary-950);
}

.area-reverso h3 {
  color: white;
  font-size: 15px;
  font-weight: 900;
  letter-spacing: .14em;
  text-transform: uppercase;
}

/* Apretado a propósito. Las dos caras comparten celda, así que la más alta
   marca el alto de las cinco tarjetas de la fila: el reverso de Talento son
   seis servicios que ocupan trece líneas y estiraba la fila a 444 px, con el
   frente de las demás flotando en medio de un metro de blanco. */
.area-reverso ul {
  display: grid;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.area-reverso li {
  position: relative;
  padding-left: 22px;
  color: rgba(255, 255, 255, .92);
  font-size: 12.5px;
  line-height: 1.32;
}

/* La marca de verificación de Bootstrap Icons, en teal. Aquí sí: sobre el azul
   profundo da 12,4:1. */
.area-reverso li::before {
  content: "\F26A";
  position: absolute;
  left: 0;
  top: 0;
  color: var(--turquoise);
  font-family: "bootstrap-icons";
  font-size: 13px;
  line-height: 1.4;
}

.area-consultar {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 4px;
  color: var(--turquoise);
  font-size: 13.5px;
  font-weight: 800;
}

.area-consultar i {
  font-size: 14px;
  transition: transform .18s ease;
}

.area-consultar:hover i,
.area-consultar:focus-visible i {
  transform: translateX(3px);
}

.area-consultar:hover,
.area-consultar:focus-visible {
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* El realce del frente sobra cuando la tarjeta se voltea: el filete de marca
   quedaría flotando sobre el azul y el icono se agranda detrás de la cara que
   ya no se ve. */
.areas-grid article.tiene-reverso:hover::before,
.areas-grid article.tiene-reverso:focus-within::before {
  transform: scaleX(0);
}

.areas-grid article.tiene-reverso:hover,
.areas-grid article.tiene-reverso:focus-within {
  transform: none;
}

/*
 * Sin volteo cuando no hay con qué voltearla.
 *
 * En un móvil no existe el `hover`, y una tarjeta que sólo se abre al pasar el
 * cursor esconde su contenido a quien la toca. Por debajo del corte se muestran
 * las dos caras apiladas: el reverso queda debajo del texto, en su panel azul.
 *
 * Lo mismo con «reducir movimiento»: un giro en 3D es exactamente lo que esa
 * preferencia pide evitar. Ahí no se apila —la tarjeta cabe— sino que se cambia
 * de cara sin animación.
 */
@media (max-width: 1180px) {
  .areas-grid article.tiene-reverso { perspective: none; cursor: auto; }

  .area-giro { transform: none !important; }

  .area-cara { grid-area: auto; backface-visibility: visible; }

  .area-reverso {
    transform: none;
    margin-top: 18px;
    padding: 18px;
    border-radius: var(--radius-sm);
    background: var(--primary-950);
  }

  .areas-grid article.tiene-reverso:hover,
  .areas-grid article.tiene-reverso:focus-within {
    background-color: rgba(255, 255, 255, .9);
    border-color: rgba(0, 180, 255, .55);
  }
}

@media (prefers-reduced-motion: reduce) {
  .area-giro { transition-duration: .01ms; }
}

/* En versalitas y con letra espaciada, como los antetitulos del sitio: son
   nombres de area, no titulares. */
.areas-grid h3 {
  color: var(--primary-950);
  font-size: 15px;
  font-weight: 800;
  letter-spacing: .1em;
  text-transform: uppercase;
}

.areas-grid p {
  color: var(--muted);
  font-size: 15px;
  line-height: 1.65;
}

/* Cinco columnas solo caben de verdad en pantalla ancha. Debajo se reparten
   en tres y luego en una: apretarlas deja tres palabras por linea. */
/* ── El reverso crece al voltearse, la tarjeta no ───────────────────────
   Sólo de 1181 px para arriba, que es donde existe el volteo: por debajo las
   dos caras se apilan y nada de esto aplica.

   **El problema.** Las dos caras compartían celda, así que el alto de la
   tarjeta era el de la cara más alta, y el de la fila entera el del reverso
   más largo -Talento, seis servicios-. Resultado medido a 1920: tarjetas de
   272 px con el reverso ocupando 216 sobre 218 de interior, o sea llenándolo
   de borde a borde, y las otras cuatro caras frontales flotando en un palmo de
   blanco. Apretado por un lado y vacío por el otro, a la vez.

   Darle relleno tampoco lo arreglaba: como la caja mide lo que su contenido,
   crecían las cinco tarjetas y las frontales quedaban todavía más vacías.

   **La salida.** Sacar el reverso del flujo. La tarjeta pasa a medir lo que su
   cara frontal -corta- y el reverso, ya sin ese techo, crece lo que necesite
   por encima de lo que haya debajo. No empuja nada: la rejilla no se entera de
   que ha crecido, así que la sección de abajo no se mueve.

   Y como el reverso ya no marca el alto de nadie, puede respirar: la lista
   sube de 12,5 a 13,5 px y su separación de 6 a 9. Los 12,5 no eran una
   decisión de diseño, eran consecuencia de tener que caber. */
@media (min-width: 1181px) {
  .areas-grid {
    gap: 20px;
  }

  /*
   * Fuera del flujo, anclado arriba y creciendo hacia abajo.
   *
   * Los `inset` negativos no son un truco: un hijo absoluto se posiciona contra
   * la **caja de relleno**, así que con `inset: 0` el reverso quedaba metido
   * dentro del relleno de la tarjeta y la parte que sobresalía salía más
   * estrecha, con un escalón a media altura. Sacándolo hasta el borde y
   * dándole el mismo relleno, la pieza que crece tiene el ancho de la tarjeta.
   *
   * `min-height` para que en las tarjetas de reverso corto siga cubriendo la
   * cara frontal entera.
   */
  .area-reverso {
    position: absolute;
    top: calc(var(--area-pad-y) * -1);
    right: calc(var(--area-pad-x) * -1);
    bottom: auto;
    left: calc(var(--area-pad-x) * -1);
    height: auto;
    min-height: calc(100% + var(--area-pad-y) + var(--area-pad-b));
    padding: var(--area-pad-y) var(--area-pad-x) var(--area-pad-b);
    border-radius: var(--radius-md);
    background: var(--primary-950);
  }

  /* La tarjeta deja de recortar para que el reverso pueda asomar. */
  .areas-grid article.tiene-reverso {
    overflow: visible;
  }

  /* Por encima de lo que venga debajo mientras está girada, y sólo entonces:
     un `z-index` permanente la pondría por delante de la cabecera. */
  .areas-grid article.tiene-reverso:hover,
  .areas-grid article.tiene-reverso:focus-within {
    z-index: 3;
  }

  .area-reverso ul {
    gap: 9px;
  }

  .area-reverso li {
    font-size: 13.5px;
    line-height: 1.45;
  }
}

@media (max-width: 1180px) {
  .areas-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 720px) {
  .areas-grid { grid-template-columns: 1fr; }
}

/* ── Paginacion ───────────────────────────────────────────────────────
   Reemplaza a la vista por defecto de Laravel, que trae clases de Tailwind y
   el sitio publico no lo usa: sus chevrones eran SVG sin ancho y se expandian
   al 100 % del contenedor.

   Contraste sobre el fondo de la pagina:
     - numero        #101B3D ..... 15,8:1
     - activo blanco sobre #0A1230  18,4:1
     - deshabilitado var(--muted) .. 5,9:1 */
.paginacion {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 16px;
  align-items: center;
  justify-content: space-between;
  margin-top: 44px;
  padding-top: 28px;
  border-top: 1px solid var(--border);
}

.paginacion-numeros {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
  order: 2;
}

/* 44px de area tactil: por debajo de eso falla en un movil. */
.paginacion-numero,
.paginacion-paso {
  display: inline-flex;
  gap: 10px;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  padding: 0 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  color: var(--primary-900);
  font-size: 15px;
  font-weight: 800;
  text-decoration: none;
  transition: border-color .18s ease, background .18s ease, color .18s ease;
}
.paginacion-paso { order: 1; }
.paginacion-paso:last-child { order: 3; }

a.paginacion-numero:hover,
a.paginacion-paso:hover,
a.paginacion-numero:focus-visible,
a.paginacion-paso:focus-visible {
  border-color: rgba(0, 180, 255, .5);
  color: var(--electric-blue);
}

.paginacion-numero.activo {
  border-color: var(--primary-950);
  background: var(--primary-950);
  color: white;
}

/* Los pasos sin destino no son enlaces: se pintan apagados y no reaccionan. */
span.paginacion-paso {
  border-color: transparent;
  color: var(--muted);
  cursor: default;
}

.paginacion-salto {
  padding: 0 4px;
  color: var(--muted);
}

@media (max-width: 720px) {
  .paginacion { justify-content: center; }
  .paginacion-paso span { display: none; }
  .paginacion-paso { padding: 0; }
}

/* El área de la que viene la consulta, encima del formulario. Se enseña porque
   viaja escondida: un dato que se manda sin que el visitante lo vea es un dato
   que no dio. */
.form-tema {
  margin: 10px 0 0;
  color: var(--muted);
  font-size: 14px;
}

.form-tema strong { color: var(--primary-900); }

/* El acceso al perfil desde la cabecera, con sesión de profesional. */
.nav-perfil {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

/* El botón de salir se ve como un enlace más de la barra: es un formulario
   sólo porque salir no puede ir por GET, no porque sea una acción destacada. */
.nav-salir {
  margin: 0;
  display: inline-flex;
}

/* Blanco explícito y no `inherit`: el botón heredaba el color del formulario
   que lo envuelve, no el de la barra, y salía casi negro sobre el azul de la
   cabecera. Blanco sobre #0A1230 da 18,4:1, y al 80 % sigue muy por encima
   del mínimo. Se vio en la captura, no leyendo la hoja de estilos. */
.nav-salir button {
  background: none;
  border: 0;
  padding: 0;
  color: #fff;
  font: inherit;
  cursor: pointer;
  opacity: .8;
}

.nav-salir button:hover,
.nav-salir button:focus-visible { opacity: 1; }

/* ── Qué falta en el perfil ────────────────────────────────────────

   Estaba esto justo: alguien subía su currículum, guardaba sus datos y se
   quedaba mirando, sin saber si eso era todo. */
.perfil-progreso {
  margin: 20px 0 0;
  padding: 18px 20px;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 14px;
}

.perfil-progreso-titulo {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin: 0 0 14px;
  font-weight: 700;
  color: var(--primary-900);
}

/* El contador, en tono menor: lo que importa es el paso, no la cifra. */
.perfil-progreso-titulo span {
  margin-left: auto;
  color: var(--muted);
  font-weight: 400;
  font-size: 14px;
  font-variant-numeric: tabular-nums;
}

.perfil-pasos {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 9px;
}

.perfil-pasos li {
  display: grid;
  grid-template-columns: 20px 1fr;
  gap: 9px;
  align-items: baseline;
  color: var(--muted);
  font-size: 15px;
}

/* Hecho: el tick en el azul de marca y el texto apagado. Apagar el texto de lo
   ya hecho es lo que hace que el que falta salte a la vista sin colorearlo. */
.perfil-pasos li.hecho i { color: var(--primary-900); }
.perfil-pasos li.hecho > span { text-decoration: line-through; opacity: .65; }

/* El que toca ahora, en negrita y con su etiqueta. Se distingue por peso y por
   texto, no sólo por color: quien no distingue colores lo lee igual. */
.perfil-pasos li.ahora > span {
  color: var(--primary-900);
  font-weight: 700;
}

.perfil-pasos li.ahora em {
  display: inline-block;
  margin-left: 8px;
  padding: 2px 9px;
  border-radius: 999px;
  background: var(--primary-950);
  color: #fff;
  font-size: 12px;
  font-style: normal;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
}

/* El último paso no lo hace el candidato. Se enseña igual, en cursiva, para que
   sepa que hay una revisión por medio y que no está circulando entre empresas
   desde el minuto uno. */
.perfil-pasos li.ajeno > span { font-style: italic; }

/* La foto del perfil. */
/* La foto va fuera de la rejilla de dos columnas y encima.

   Con tres tarjetas en una rejilla de dos, la tercera se quedaba sola en una
   segunda fila y estrecha. Y la foto no es un bloque de trabajo como el
   currículum o los datos: es identidad, y eso va arriba. */
.perfil-foto-bloque { margin-top: 26px; }

.perfil-foto {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 22px;
}

.perfil-foto-marco {
  flex: none;
  width: 126px;
  height: 126px;
}

.perfil-foto img,
.perfil-foto-hueco {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
}

/* El hueco cuando no hay foto: una silueta, no un rectángulo vacío. */
.perfil-foto-hueco {
  display: grid;
  place-items: center;
  background: var(--muted-surface);
  color: var(--muted);
  font-size: 46px;
}

.perfil-foto-acciones {
  flex: 1 1 320px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 16px;
}

.perfil-foto-acciones form { margin: 0; }

/* La etiqueta hace de botón: es lo que abre el diálogo, así que tiene que
   verse y comportarse como uno. El campo de verdad está escondido pero sigue
   en el recorrido del teclado, y el foco se pinta aquí. */
.perfil-foto-acciones label.btn {
  cursor: pointer;
  gap: 8px;
}

.campo-archivo-real:focus-visible + label.btn {
  outline: 3px solid rgba(25, 224, 194, .36);
  outline-offset: 2px;
}

/* El peso admitido y el «es opcional», juntos y en su línea: son la letra
   pequeña, no una decisión. */
.perfil-foto-nota {
  flex-basis: 100%;
  margin: 0;
  color: var(--muted);
  font-size: 13px;
}

.perfil-foto-error { flex-basis: 100%; }

.perfil-foto-nota {
  margin: 0;
  color: var(--muted);
  font-size: 13px;
}

/* ── El selector de archivo propio ─────────────────────────────────

   El nativo pinta «Choose File» en el idioma del navegador y eso no se puede
   traducir. Se esconde el campo real y se enseña una etiqueta nuestra. */
.campo-archivo {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 14px;
}

/* Escondido pero **no** con `display:none`: eso lo sacaría del recorrido del
   teclado y del árbol de accesibilidad, y entonces no habría forma de elegir
   archivo sin ratón. */
.campo-archivo-real {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
}

.campo-archivo-boton {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 11px 18px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: #fff;
  font-weight: 700;
  cursor: pointer;
}

.campo-archivo-boton:hover { border-color: var(--primary-900); }

/* El foco se pinta sobre la etiqueta, porque el campo real está escondido: sin
   esto, quien navega con teclado no ve dónde está. */
.campo-archivo-real:focus-visible + .campo-archivo-boton {
  outline: 3px solid rgba(25, 224, 194, .36);
  outline-offset: 2px;
}

.campo-archivo-nombre {
  color: var(--muted);
  font-size: 14px;
  /* Un nombre de archivo largo no puede empujar la caja. */
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.campo-archivo-ayuda {
  flex-basis: 100%;
  color: var(--muted);
  font-size: 13px;
}

.portal-cv-acciones .btn { gap: 7px; }

/* ══ Mi trayectoria ════════════════════════════════════════════════

   Los cuatro bloques que llenan el CV normalizado. Cada entrada se corrige
   dentro de un `<details>` del propio navegador: sin JavaScript, con teclado y
   con lector de pantalla. */

.trayectoria-acciones {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin: 0 0 8px;
}

.trayectoria-acciones .btn { gap: 8px; }

/* El atajo: rellenar desde el currículum. Va arriba, antes de los
   formularios: ofrecerlo después de que alguien haya tecleado tres puestos a
   mano sería una burla. */
.trayectoria-leer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 14px;
  margin: 0 0 4px;
  padding: 16px 18px;
  background: var(--muted-surface);
  border-radius: 12px;
}

.trayectoria-leer .btn { gap: 8px; }
.trayectoria-leer small { color: var(--muted); font-size: 13px; }

/* ── La revisión de lo que entendió la máquina ────────────────────── */

.revision-aviso {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  margin: 0;
  padding: 14px 16px;
  background: rgba(0, 180, 255, .08);
  border-radius: 12px;
  color: var(--primary-900);
  font-size: 15px;
}

.revision-entrada {
  display: grid;
  gap: 13px;
  margin: 0 0 16px;
  padding: 18px;
  border: 1px solid var(--border);
  border-radius: 12px;
}

/* La casilla de incluir, arriba y destacada: es la decisión que se toma en
   cada entrada, y enterrada entre los campos no se ve. */
.revision-incluir {
  padding-bottom: 12px;
  border-bottom: 1px solid var(--border);
  font-weight: 700;
}

.revision-linea {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  padding: 10px 0;
  border-bottom: 1px solid var(--border);
}

.revision-linea label { display: grid; gap: 4px; min-width: 170px; }

.revision-competencias {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 18px;
}

.revision-pie {
  margin-top: 26px;
  display: flex;
  justify-content: flex-end;
}

.revision-pie .btn { gap: 8px; }

.revision-descartar {
  margin: 10px 0 0;
  text-align: right;
}

.trayectoria-bloque {
  margin-top: 26px;
  padding: 24px;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 16px;
}

.trayectoria-bloque > h2 {
  margin: 0 0 16px;
  font-size: 19px;
}

.trayectoria-vacio {
  margin: 0 0 16px;
  padding: 16px;
  background: var(--muted-surface);
  border-radius: 12px;
  color: var(--muted);
  font-size: 15px;
}

/* Una entrada ya guardada: el resumen a la izquierda y el desplegable de
   corregir a la derecha. */
.trayectoria-entrada {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  padding: 16px 0;
  border-bottom: 1px solid var(--border);
}

.trayectoria-entrada h3 {
  margin: 0;
  font-size: 17px;
}

.trayectoria-entrada p {
  margin: 3px 0 0;
  color: var(--muted);
  font-size: 15px;
}

.trayectoria-fechas { font-variant-numeric: tabular-nums; }

/* El desplegable de corregir y el de añadir. `summary` con aspecto de botón y
   sin el triangulito del navegador, que en cada sistema se pinta distinto. */
.trayectoria-editar > summary,
.trayectoria-anadir > summary {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 9px 15px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--primary-900);
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
  list-style: none;
}

.trayectoria-editar > summary::-webkit-details-marker,
.trayectoria-anadir > summary::-webkit-details-marker { display: none; }

.trayectoria-editar > summary:hover,
.trayectoria-anadir > summary:hover { border-color: var(--primary-900); }

.trayectoria-anadir { margin-top: 18px; }

/* Abierto, el formulario se separa del botón para que se lea como un panel y
   no como texto que brotó del botón. */
.trayectoria-form {
  display: grid;
  gap: 14px;
  margin-top: 16px;
  padding: 18px;
  background: var(--muted-surface);
  border-radius: 12px;
}

.trayectoria-form-pie {
  display: flex;
  justify-content: flex-end;
}

.trayectoria-borrar {
  margin: 8px 0 0;
  text-align: right;
}

/* Idiomas y competencias: pastillas con su aspa. Son datos de una línea y un
   formulario entero por cada uno sería desproporcionado. */
.trayectoria-pastillas {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 9px;
  margin: 0 0 18px;
  padding: 0;
}

.trayectoria-pastillas li {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 8px 7px 14px;
  background: var(--muted-surface);
  border-radius: 999px;
  font-size: 15px;
}

.trayectoria-pastillas form { margin: 0; display: inline-flex; }

.trayectoria-pastillas button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgba(10, 18, 48, .08);
  color: var(--primary-900);
  cursor: pointer;
  font-size: 15px;
}

.trayectoria-pastillas button:hover {
  background: rgba(161, 29, 29, .12);
  color: #a11d1d;
}

/* La línea de añadir un idioma o una competencia. */
.trayectoria-linea {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 12px;
}

.trayectoria-linea label {
  display: grid;
  gap: 5px;
  min-width: 170px;
}

.trayectoria-linea label.crece { flex: 1 1 240px; }

.trayectoria-linea > .btn { flex: none; }

/* ── Los pasos del perfil, ahora enlazados ─────────────────────────

   Antes eran texto: decían «te toca» y no llevaban a ninguna parte, que es
   peor que no enseñarlos. */
.perfil-pasos a {
  color: inherit;
  text-decoration: none;
}

.perfil-pasos a:hover > span,
.perfil-pasos a:focus-visible > span { text-decoration: underline; }

/* ══ El CV normalizado ═════════════════════════════════════════════

   La misma ficha para todos los candidatos, que es lo que permite compararlos.
   Se ve en pantalla y se imprime: el navegador genera el PDF con el bloque
   `@media print` de más abajo, sin nada instalado en el servidor. */

.cv-pagina {
  max-width: 880px;
  margin-inline: auto;
}

.cv-acciones {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  margin-bottom: 22px;
}

.cv-acciones .btn { gap: 8px; }

/* La hoja. Proporción y márgenes de un A4 para que lo que se ve en pantalla
   sea lo que sale por la impresora. */
.cv-hoja {
  padding: clamp(28px, 4vw, 52px);
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: 0 24px 60px rgba(10, 18, 48, .10);
}

.cv-cabecera {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 24px;
  padding-bottom: 22px;
  border-bottom: 2px solid var(--primary-950);
}

.cv-cabecera h1 {
  margin: 0;
  font-size: clamp(26px, 3.4vw, 34px);
  line-height: 1.15;
}

.cv-titular {
  margin: 4px 0 0;
  color: var(--muted);
  font-size: 17px;
}

/* La foto en la hoja del CV. Redonda y a la izquierda del nombre, que es como
   se lee un currículum español. */
.cv-foto-marco {
  flex: none;
  width: 106px;
  height: 106px;
  margin-right: 22px;
}

.cv-foto {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
}

.cv-logo {
  flex: none;
  width: 150px;
  height: auto;
}

/* Los datos de cabecera: nacionalidad, residencia, permiso. Lo que una empresa
   de movilidad mira antes que nada. */
.cv-datos {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 6px 18px;
  margin: 14px 0 0;
  padding: 0;
  color: var(--muted);
  font-size: 14px;
}

.cv-datos li {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.cv-bloque { margin-top: 30px; }

.cv-bloque > h2 {
  margin: 0 0 16px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border);
  font-size: 15px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--primary-900);
}

/* Cada entrada: las fechas en su columna, a la izquierda. Alineadas en una
   columna propia se leen de un vistazo; metidas en el texto hay que buscarlas
   entrada por entrada. */
.cv-entrada {
  display: grid;
  grid-template-columns: 130px minmax(0, 1fr);
  gap: 18px;
  margin-bottom: 20px;
}

.cv-entrada:last-child { margin-bottom: 0; }

.cv-entrada-fechas {
  margin: 2px 0 0;
  color: var(--muted);
  font-size: 14px;
  font-variant-numeric: tabular-nums;
}

.cv-entrada h3 {
  margin: 0;
  font-size: 17px;
}

.cv-entrada-donde {
  margin: 2px 0 8px;
  color: var(--muted);
  font-size: 15px;
}

.cv-entrada .oferta-lista,
.cv-entrada p { font-size: 15px; }

.cv-homologacion {
  margin: 6px 0 0;
  font-size: 14px;
  color: var(--muted);
}

/* Idiomas y competencias, en dos columnas: son los dos bloques cortos del
   currículum y uno debajo del otro dejaban media hoja en blanco entre la
   formación y el pie. */
.cv-columnas {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 0 34px;
  align-items: start;
}

.cv-idiomas,
.cv-competencias {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 10px 14px;
}

.cv-idiomas li {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 8px 14px;
  background: var(--muted-surface);
  border-radius: 999px;
  font-size: 15px;
}

.cv-idiomas span { color: var(--muted); font-size: 14px; }

.cv-competencias li {
  padding: 7px 13px;
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: 14px;
}

.cv-pie {
  margin-top: 34px;
  padding-top: 16px;
  border-top: 1px solid var(--border);
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 8px;
  color: var(--muted);
  font-size: 13px;
}

.cv-pie p { margin: 0; }

.cv-vacio {
  margin: 30px 0 0;
  padding: 22px;
  background: var(--muted-surface);
  border-radius: 12px;
  color: var(--muted);
  text-align: center;
}

.portal-perfil-vercv { margin: 18px 0 0; }
.portal-perfil-vercv .btn { gap: 8px; }

@media (max-width: 720px) {
  .cv-cabecera { flex-direction: column-reverse; }
  .cv-entrada { grid-template-columns: minmax(0, 1fr); gap: 4px; }
}

/* ── En papel ────────────────────────────────────────────────────

   Imprimir **es** la descarga: el navegador genera el PDF y no hace falta
   ningún generador en el servidor para producir exactamente esta página.

   Se quita todo lo que no es el documento —cabecera, pie del sitio, botones,
   WhatsApp flotante, aviso de cookies—: son de la web, no del currículum, y en
   papel sólo gastan tinta. */
@media print {
  @page {
    size: A4;
    margin: 14mm;
  }

  body { background: #fff; }

  .site-header,
  .site-footer,
  .final-cta,
  .no-imprimir,
  .whatsapp-flotante,
  .aviso-cookies,
  .toast { display: none !important; }

  /* La hoja pierde su sombra y su borde: en papel serían una caja dibujada
     alrededor del texto. */
  .cv-pagina,
  main > .cv-pagina:first-child {
    max-width: none;
    width: auto;
    padding: 0;
    margin: 0;
  }

  .cv-hoja {
    padding: 0;
    border: 0;
    border-radius: 0;
    box-shadow: none;
  }

  /* Que un bloque no se parta entre dos hojas dejando el titular solo al final
     de una y su contenido al principio de la siguiente. */
  .cv-bloque,
  .cv-entrada,
  .cv-columnas { break-inside: avoid; }

  .cv-bloque > h2 { break-after: avoid; }

  /* Los fondos de color no se imprimen por defecto en muchos navegadores, así
     que las pastillas de idiomas quedarían como texto suelto. Con borde se ven
     igual en papel y en pantalla. */
  .cv-idiomas li {
    background: none;
    border: 1px solid #ccc;
  }

  /* Y el anillo de la foto, por lo mismo: sin fondo impreso desaparecería y la
     cara quedaría flotando contra el papel. Un filete fino la sostiene. */
  .cv-foto-marco {
    background: none;
    border: 1px solid #ccc;
    border-radius: 50%;
  }
}

/* ══ Mi perfil ═════════════════════════════════════════════════════

   Columna estrecha, como el registro: es una pantalla de gestión y se lee de
   arriba abajo. */

.portal-perfil-caja {
  width: 100%;
  max-width: 1040px;
  margin-inline: auto;
}

/* Los dos bloques, uno al lado del otro.

   Apilados en una columna estrecha dejaban dos palmos de blanco a cada lado en
   una pantalla ancha, y obligaban a bajar hasta el final para llegar a unos
   campos que caben de sobra al lado. `align-items: start` para que el bloque
   corto no se estire hasta el alto del largo. */
.portal-perfil-rejilla {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
  gap: 22px;
  align-items: start;
}

.portal-perfil-rejilla > .portal-perfil-bloque { margin-top: 26px; }

.portal-perfil-caja h1 {
  margin: 6px 0 0;
  font-size: clamp(28px, 4vw, 36px);
}

.portal-perfil-estado {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin: 16px 0 0;
  padding: 6px 13px;
  border-radius: 999px;
  background: var(--muted-surface);
  color: var(--primary-900);
  font-size: 14px;
  font-weight: 600;
}

.portal-perfil-bloque {
  margin-top: 30px;
  padding: 26px;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 18px;
}

.portal-perfil-bloque h2 {
  margin: 0 0 18px;
  font-size: 20px;
}

/* El aviso de que algo se guardó. Mismos colores que el del boletín: el verde
   de estado no sale del manual —no lo tiene— así que se usa el mínimo que
   pasa contraste sobre su propio fondo, y se usa el mismo en todo el sitio. */
.aviso-ok {
  margin: 18px 0 0;
  padding: 12px 16px;
  border-radius: 12px;
  background: rgba(25, 224, 194, .14);
  color: #0b5d51;
  font-size: 15px;
}

/* El CV que ya está subido. */
.portal-cv-actual {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0 0 16px;
  padding: 14px 16px;
  background: var(--muted-surface);
  border-radius: 12px;
}

.portal-cv-actual i {
  font-size: 26px;
  color: var(--primary-900);
}

.portal-cv-actual span {
  display: grid;
  /* El nombre de archivo puede ser larguísimo y no debe empujar la caja. */
  min-width: 0;
}

.portal-cv-actual strong {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.portal-cv-actual small { color: var(--muted); }

.portal-cv-acciones {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin: 0 0 22px;
}

.portal-cv-acciones form { margin: 0; }

/* Borrar es destructivo, así que no se le da el peso de un botón: se ve como
   un enlace y sólo se tiñe de rojo al apuntarlo. Un botón rojo grande al lado
   de «Descargar» se pulsa por error. */
.btn-texto {
  background: none;
  border: 0;
  padding: 10px 4px;
  color: var(--muted);
  font: inherit;
  text-decoration: underline;
  cursor: pointer;
}

.btn-texto:hover,
.btn-texto:focus-visible { color: #a11d1d; }

/* El bloque de consentimiento, separado del resto del formulario: lo que se
   acepta tiene que verse como una cosa aparte y no como un campo más. */
.portal-consentimiento {
  padding: 18px;
  background: var(--muted-surface);
  border-radius: 12px;
}

.portal-consentimiento h3 {
  margin: 0 0 8px;
  font-size: 16px;
}

.portal-consentimiento p {
  margin: 0 0 14px;
  color: var(--muted);
  font-size: 14px;
  line-height: 1.6;
}

@media (max-width: 720px) {
  .portal-perfil-bloque { padding: 20px; }
}

/* ══ Portada del Portal de Talento ═════════════════════════════════

   Estructura del alcance §4.6: hero con buscador y cifras, los dos lados
   enfrentados, los cuatro pasos y el diferenciador. */

/* El hero, sobre el motivo oscuro de marca — el mismo preajuste que el bloque
   de cierre del sitio, para que el Portal se vea parte de la casa.

   Contraste calculado sobre el fondo real, no a ojo: el titular y el texto van
   en blanco puro y en blanco al 82 % sobre `--primary-950` (#0A1230), que dan
   17,4:1 y 12,1:1. El eyebrow va en teal claro, no en el teal de marca: ése da
   1,59:1 sobre blanco y aquí, sobre oscuro, sube de sobra. */
.portal-hero,
.error-hero {
  position: relative;
  overflow: hidden;
  padding: clamp(56px, 7vw, 92px) clamp(24px, 4vw, 56px);
  border-radius: var(--radius-lg);
  background: var(--primary-950);
  color: #fff;
  text-align: center;
  box-shadow: 0 30px 70px rgba(10, 18, 48, .22);
}

/* La franja de marca arriba, como en el cierre. */
.portal-hero::before,
.error-hero::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  z-index: 5;
  height: 3px;
  background: var(--brand-gradient);
}

.portal-hero-lienzo,
.error-hero-lienzo {
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
}

/* El respaldo. Si el lienzo no dibuja —script bloqueado, contexto perdido— el
   hero se ve igual de bien y el texto sigue legible. Nunca depende del canvas. */
.portal-hero-fondo,
.error-hero-fondo {
  position: absolute;
  inset: 0;
  z-index: 0;
  background:
    repeating-linear-gradient(115deg,
      rgba(255, 255, 255, .045) 0 1px,
      transparent 1px 22px),
    radial-gradient(52% 78% at 88% 18%, rgba(0, 180, 255, .30), transparent 68%),
    radial-gradient(46% 70% at 68% 96%, rgba(25, 224, 194, .20), transparent 70%),
    radial-gradient(70% 90% at 8% 30%, rgba(41, 98, 255, .16), transparent 72%);
}

.portal-hero-copy,
.error-hero-copy {
  position: relative;
  z-index: 2;
  max-width: 780px;
  margin-inline: auto;
}

.portal-hero .eyebrow,
.error-hero .eyebrow { color: var(--brand-teal, #19E0C2); }

.portal-hero h1,
.error-hero h1 {
  margin: 8px 0 0;
  font-size: clamp(32px, 5vw, 48px);
  color: #fff;
}

.portal-hero-lead,
.error-hero-lead {
  margin: 14px 0 0;
  font-size: clamp(18px, 2.2vw, 22px);
  font-weight: 600;
  color: #fff;
}

.portal-hero-texto {
  margin: 12px auto 0;
  max-width: 62ch;
  color: rgba(255, 255, 255, .82);
}

/* El buscador. En una línea desde 560 px y apilado por debajo: un campo de
   búsqueda estrecho al lado de un botón es peor que los dos a lo ancho. */
.portal-buscador {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  /* A la izquierda: vive dentro de una banda alineada con el resto de la
     pagina, no centrado en un hero. */
  margin-top: 0;
}

.portal-buscador-campo {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1 1 320px;
  max-width: 420px;
  padding: 0 14px;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 999px;
}

.portal-buscador-campo i { color: var(--muted); }

.portal-buscador-campo input {
  flex: 1;
  border: 0;
  background: none;
  padding: 13px 0;
  font: inherit;
  outline: none;
}

.portal-buscador .btn { border-radius: 999px; }

/* El botón de instalar. Con `hidden` de por medio: el guion lo enseña sólo si
   el navegador avisa de que se puede instalar, así que aquí no se fuerza
   ningún `display` que lo dejaría visible siempre. */
.portal-instalar {
  margin: 20px 0 0;
}

.portal-instalar .btn { gap: 8px; }

.portal-cifras {
  margin: 20px 0 0;
  color: rgba(255, 255, 255, .78);
  font-size: 15px;
}

.portal-cifras strong {
  color: var(--brand-teal, #19E0C2);
  font-size: 18px;
  /* Los números en columna no bailan al cambiar de cifra. */
  font-variant-numeric: tabular-nums;
}



/* ── Los dos lados ─────────────────────────────────────────────── */

.portal-lados {
  display: grid;
  gap: 22px;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  align-items: start;
}

.portal-lado {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 30px;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 18px;
}

/* El lado de empresa, sobre el gris de marca. Distingue los dos destinatarios
   sin usar sólo color: cambian el fondo y el botón a la vez. */
.portal-lado-empresa { background: var(--muted-surface); }

.portal-lado h2 {
  margin: 0;
  font-size: clamp(20px, 2.4vw, 26px);
  line-height: 1.3;
}

.portal-lista {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 9px;
  color: var(--muted);
  font-size: 15px;
}

.portal-lista li {
  display: grid;
  grid-template-columns: 20px 1fr;
  gap: 8px;
  align-items: start;
}

/* El tick, en el azul de marca y no en el teal: el teal del manual da 1,59:1
   sobre blanco y un icono pide 3:1. Ver la nota de contraste al inicio. */
.portal-lista i { color: var(--primary-900); }

/* El botón se pega abajo para que las dos tarjetas los alineen aunque una
   lista tenga un punto más que la otra. */
.portal-lado .btn {
  margin-top: auto;
  align-self: start;
}

.portal-lado-pie {
  margin: 0;
  color: var(--muted);
  font-size: 14px;
}

/* ── Los cuatro pasos ──────────────────────────────────────────── */

.portal-pasos-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 20px;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  counter-reset: paso;
}

.portal-pasos-grid li {
  position: relative;
  padding: 24px;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 16px;
}

/* La línea que une un paso con el siguiente.

   No es decoración: estos cuatro **son** una secuencia, y sin nada que los
   una se leen como cuatro apartados sueltos que dan igual en cualquier orden.
   Sale del número y llega al del paso siguiente, así que desaparece sola en
   el último y cuando la rejilla se apila.

   `aria-hidden` no hace falta: es un pseudoelemento y los lectores de
   pantalla no lo anuncian. El orden ya lo dice la lista numerada. */
@media (min-width: 721px) {
  .portal-pasos-grid li:not(:last-child)::after {
    content: "";
    position: absolute;
    top: 41px;
    left: calc(24px + 42px);
    right: -22px;
    height: 1px;
    background: linear-gradient(90deg, var(--border), transparent);
  }
}

/* El número, en el azul profundo de marca. Blanco sobre #0A1230 da 18,4:1.
   No sobre el teal del manual, que con blanco encima da 1,59:1. */
.portal-paso-numero {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--primary-950);
  color: #fff;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.portal-pasos-grid h3 {
  margin: 14px 0 6px;
  font-size: 18px;
}

.portal-pasos-grid p {
  margin: 0;
  color: var(--muted);
  font-size: 15px;
}

/* ── Últimas ofertas y diferenciador ───────────────────────────── */

.portal-ultimas-pie {
  margin: 26px 0 0;
  text-align: center;
}

/* El diferenciador, en dos columnas: la ilustración a la izquierda y el texto
   a la derecha. Antes era un párrafo centrado en una caja gris y se leía como
   una nota al pie de la página. */
/* La caja va sobre el azul profundo, y no sobre el gris claro que tenía.

   No es gusto: **la ilustración está trazada en cianes**. Medidos los píxeles
   del propio archivo, sus tonos dominantes van del #2070E0 al #40D0F0, y sobre
   el gris de antes el más brillante daba **1,6:1** — se veía lavada, casi un
   fantasma. Sobre `--primary-950` el trazo más oscuro sube a 4,2:1 y el más
   claro pasa de 8:1; el mínimo WCAG para un elemento gráfico es 3:1.

   Es además lo que pide el propio sistema de ilustración: contorno de color
   sobre transparencia real, probado sobre fondo claro **y** oscuro. Este vive
   mejor en oscuro.

   Contrastes del texto sobre #0A1230: blanco 17,4:1 y blanco al 82 % 12,1:1. */
.portal-diferencia-caja {
  position: relative;
  overflow: hidden;
  display: grid;
  grid-template-columns: minmax(240px, .8fr) minmax(300px, 1.2fr);
  gap: clamp(24px, 4vw, 52px);
  align-items: center;
  max-width: 1040px;
  margin-inline: auto;
  padding: clamp(24px, 3vw, 44px);
  background: var(--primary-950);
  border-radius: 18px;
  box-shadow: 0 24px 56px rgba(10, 18, 48, .18);
}

/* La franja de marca arriba, como el hero del Portal y el bloque de cierre:
   los tres bloques oscuros del sitio se reconocen como la misma familia. */
.portal-diferencia-caja::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 3px;
  background: var(--brand-gradient);
}

.portal-diferencia-caja h2 {
  margin: 0 0 12px;
  font-size: clamp(22px, 2.6vw, 28px);
  color: #fff;
}

.portal-diferencia-caja p {
  margin: 0 0 16px;
  color: rgba(255, 255, 255, .82);
}

/* El enlace, en cian y no en el azul eléctrico: sobre el azul profundo aquel
   da 3,96:1 y esto es texto pequeño, que pide 4,5:1. El cian da 7,8:1. */
.portal-diferencia-caja .oferta-ver {
  color: var(--cyan);
  border-top-color: rgba(255, 255, 255, .16);
}

/* La ilustración del sistema de marca, con transparencia real: se apoya sobre
   el fondo de la caja sin recuadro. */
.portal-ilustracion {
  display: block;
  width: 100%;
  height: auto;
}

@media (max-width: 720px) {
  .portal-diferencia-caja { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 720px) {
  .portal-lado,
  .portal-diferencia-caja { padding: 22px; }
}

/* ══ La puerta del Portal: registro y acceso ════════════════════════

   Una columna estrecha y centrada. Un formulario de cuatro campos a lo ancho
   de la pantalla se lee como un trámite administrativo; en una tarjeta de 480
   px se lee como una puerta, que es lo que es. */
/* Las puertas del Portal —registro, acceso y el consentimiento de Google— en
   dos columnas desde 1.180: a la izquierda de qué va, a la derecha el
   formulario.

   La tarjeta sola medía 480 px centrados en una pantalla de 1.440 y se leía
   como algo perdido en medio de una página en blanco. Por debajo del corte se
   apila —el texto arriba, el formulario debajo— que es como se lee en un
   móvil. */
.portal-acceso {
  display: grid;
  justify-items: center;
  gap: clamp(26px, 4vw, 56px);
}

.portal-acceso-intro {
  width: 100%;
  max-width: 480px;
}

.portal-acceso-intro h1 {
  margin: 6px 0 0;
  font-size: clamp(26px, 3.4vw, 34px);
}

/* La lista de lo que se consigue, sólo en el registro. Con menos aire que en
   la portada: aquí acompaña a un formulario, no es la pieza principal. */
.portal-acceso-intro .portal-lista { margin-top: 22px; }

@media (min-width: 1180px) {
  .portal-acceso {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    align-items: center;
    justify-items: stretch;
    max-width: 1080px;
    margin-inline: auto;
  }

  .portal-acceso-intro { max-width: 460px; }
  .portal-acceso-caja { max-width: 520px; }
}

/* En tarjeta y no suelta sobre el fondo. Un formulario flotando en medio de
   una página en blanco no se lee como una puerta: se lee como algo a medio
   maquetar. La franja de marca arriba es la misma del bloque de cierre. */
.portal-acceso-caja {
  position: relative;
  width: 100%;
  max-width: 480px;
  padding: clamp(28px, 4vw, 40px);
  overflow: hidden;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: 0 24px 60px rgba(10, 18, 48, .10);
}

.portal-acceso-caja::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 3px;
  background: var(--brand-gradient);
}

.portal-acceso-caja h1 {
  margin: 6px 0 0;
  font-size: clamp(26px, 3.4vw, 32px);
}

.portal-acceso-entrada {
  margin: 10px 0 26px;
  color: var(--muted);
}

.portal-form {
  display: grid;
  gap: 16px;
}

/* Espaciado por el contenedor y no con márgenes en cada campo: así añadir un
   campo no obliga a acordarse de repetir el margen, ni deja huecos dobles
   donde dos márgenes se suman. */
.portal-form .btn {
  margin-top: 4px;
  justify-content: center;
}

/* «¿Has olvidado tu contraseña?», pegado al campo al que se refiere.

   Va como celda de la rejilla del formulario, así que el hueco se lo pone el
   `gap`; el margen negativo lo sube para que se lea como parte del campo de
   arriba y no como una línea suelta entre dos controles. A la derecha por lo
   mismo: alineado a la izquierda competía con la etiqueta del campo siguiente.

   El azul eléctrico de marca sobre el blanco de la tarjeta da 4,90:1, por
   encima del 4,5:1 que pide el texto normal. Medido, no supuesto. */
.portal-form-olvidada {
  margin: -8px 0 0;
  font-size: 14px;
  text-align: right;
}

.portal-form-olvidada a {
  color: var(--primary-800);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.portal-form-olvidada a:hover,
.portal-form-olvidada a:focus-visible { color: var(--primary-950); }

.portal-acceso-pie {
  margin: 22px 0 0;
  padding-top: 18px;
  border-top: 1px solid var(--border);
  color: var(--muted);
  font-size: 14px;
  text-align: center;
}

/* La empresa, cuando la consulta es una candidatura a una oferta. En su
   propia línea: puesto y empresa seguidos se leían como un solo nombre
   larguísimo, y el puesto es lo que la persona vino a buscar. */
.form-tema-empresa {
  display: block;
  margin-top: 2px;
}

/* ══ WhatsApp flotante ══════════════════════════════════════════════
 *
 * Una pastilla de cristal que se abre al pasar por encima y enseña la
 * invitación. En reposo es sólo el icono: la esquina de todas las páginas es
 * un sitio caro y un botón permanente no puede gritar.
 *
 * ## Cristal, y no el degradado de marca
 *
 * Lo llevó un rato y pesaba demasiado para algo que está siempre a la vista.
 * El cristal deja pasar lo que hay detrás, así que acompaña en vez de
 * competir, que es lo que pidió Maude: «mantener la vista limpia».
 *
 * ## La opacidad está calculada, no elegida
 *
 * El botón flota sobre secciones claras **y** sobre el pie, que es Azul
 * Profundo. Con el glifo en Azul Profundo sobre cristal blanco:
 *
 *     alfa 0,62 -> 7,48:1 en el peor fondo
 *     alfa 0,72 -> 9,76:1   <- el que se usa
 *
 * Detalle al 0,72: 17,9:1 sobre una sección clara y 9,8:1 sobre el pie, que
 * es el fondo que manda. Por debajo de 0,62 el glifo empieza a perderse
 * justo donde el fondo es oscuro.
 *
 * ## Y funciona sin `backdrop-filter`
 *
 * El desenfoque es el adorno; el contraste lo garantiza el color sólido de
 * debajo. Donde no esté soportado se ve una pastilla clara, no un botón
 * ilegible.
 */
.whatsapp-flotante {
  position: fixed;
  right: clamp(16px, 2.4vw, 28px);
  bottom: clamp(16px, 2.4vw, 28px);
  z-index: 55;
  display: flex;
  align-items: center;
  gap: 0;
  height: 54px;
  padding: 0 15px;
  border: 0;
  border-radius: 999px;
  /*
   * Verde de WhatsApp con el icono en blanco, que es como lo pidió Maude y
   * como se reconoce el botón sin leer nada.
   *
   * **El verde es un punto más oscuro que el #25D366 de la marca**, y ahí está
   * el porqué: sobre ese verde el blanco da 1,98:1, y un icono que significa
   * algo pide 3:1. En el logotipo de WhatsApp funciona porque es una marca —se
   * mira, no se usa—; aquí es un botón que alguien tiene que encontrar a pleno
   * sol en la calle. Con #1A9E4B el blanco sube a 3,48:1 y el verde sigue
   * siendo el mismo verde a la vista.
   */
  background: #1a9e4b;
  color: #ffffff;
  box-shadow: 0 10px 26px rgba(18, 140, 126, .34);
  transition: gap .28s cubic-bezier(.4, 0, .2, 1),
              background-color .28s ease,
              box-shadow .28s ease,
              border-color .28s ease;
}

.whatsapp-flotante i {
  font-size: 24px;
  line-height: 1;
}

/*
 * El texto, plegado.
 *
 * Se anima `max-width` y no `width`: el ancho del texto depende del idioma
 * -«¿Hablamos?» y «Shall we talk?» no miden lo mismo- y fijarlo obligaría a
 * un valor por idioma que se rompe al primer cambio de copy. El tope va
 * holgado; lo que se ve es el ancho real del texto.
 *
 * `white-space: nowrap` para que no parta en dos líneas mientras se abre.
 */
.whatsapp-flotante-texto {
  max-width: 0;
  overflow: hidden;
  /*
   * 19 px y en negrita, y tampoco es estética: por debajo de 18,66 px en
   * negrita un texto deja de contar como grande y pasa a pedir 4,5:1, que en
   * blanco sobre este verde no se alcanza sin oscurecerlo hasta dejar de
   * parecer WhatsApp. A este tamaño pide 3:1 y da 3,48.
   */
  font-size: 19px;
  font-weight: 800;
  white-space: nowrap;
  opacity: 0;
  transition: max-width .28s cubic-bezier(.4, 0, .2, 1), opacity .2s ease;
}

/* Al pasar por encima, un punto más oscuro: el blanco sube a 4,4:1. */
.whatsapp-flotante:hover,
.whatsapp-flotante:focus-visible {
  gap: 10px;
  background: #148540;
  box-shadow: 0 14px 32px rgba(18, 140, 126, .42);
  color: #ffffff;
}

/* El foco, en azul profundo: sobre el verde se ve, y es el color de foco del
   resto del sitio. */
.whatsapp-flotante:focus-visible {
  outline: 2px solid var(--primary-950);
  outline-offset: 3px;
}

.whatsapp-flotante:hover .whatsapp-flotante-texto,
.whatsapp-flotante:focus-visible .whatsapp-flotante-texto {
  max-width: 14rem;
  opacity: 1;
}

/*
 * Plegado mientras se mira la cabecera de la portada.
 *
 * `visibility` y no sólo `opacity`: invisible pero enfocable es peor que
 * visible, porque el tabulador se para en algo que no se ve. Con `visibility`
 * sale también del árbol de accesibilidad y del orden de tabulación.
 *
 * Lo enciende y lo apaga `app.js`, atado a `data-cabecera-portada`. En el
 * resto de las vistas esta clase no llega a ponerse nunca.
 */
.whatsapp-flotante.esta-plegado {
  opacity: 0;
  visibility: hidden;
  transform: translateY(12px) scale(.9);
  pointer-events: none;
}

.whatsapp-flotante {
  transition: gap .28s cubic-bezier(.4, 0, .2, 1),
              background-color .28s ease,
              box-shadow .28s ease,
              border-color .28s ease,
              opacity .3s ease,
              transform .3s cubic-bezier(.4, 0, .2, 1),
              visibility .3s;
}

/* Mientras el aviso de cookies está a la vista, el botón sube por encima de
   él. El aviso ocupa el ancho entero y se apoya abajo: sin esto, en el móvil
   uno tapa al otro. Cuando se acepta, el aviso recibe `hidden` y el botón
   vuelve solo a su sitio. */
.aviso-cookies:not([hidden]) ~ .whatsapp-flotante {
  bottom: calc(clamp(16px, 2.4vw, 28px) + 128px);
}

@media (max-width: 720px) {
  .whatsapp-flotante {
    height: 50px;
    padding: 0 13px;
  }

  .whatsapp-flotante i {
    font-size: 23px;
  }

  .aviso-cookies:not([hidden]) ~ .whatsapp-flotante {
    bottom: calc(16px + 210px);
  }
}

/*
 * Sin movimiento: el texto no se despliega, se enseña entero desde el
 * principio.
 *
 * Plegarlo sin animación sería peor que no plegarlo: aparecería de golpe al
 * pasar el cursor, que es exactamente el tipo de salto que esa preferencia
 * pide evitar.
 */
@media (prefers-reduced-motion: reduce) {
  .whatsapp-flotante,
  .whatsapp-flotante-texto {
    transition: none;
  }

  .whatsapp-flotante {
    gap: 10px;
  }

  .whatsapp-flotante-texto {
    max-width: 14rem;
    opacity: 1;
  }
}

/* ── El teléfono del pie, en una línea ─────────────────────────────────
   El número no se parte nunca: es una sola unidad y verlo en cuatro trozos,
   uno por grupo de cifras, se lee como un error. Debajo, la invitación en
   pequeño, que es lo que dice qué pasa al pulsarlo. */
.footer-whatsapp .footer-whatsapp-numero {
  display: block;
  white-space: nowrap;
}

.footer-whatsapp .footer-whatsapp-nota {
  display: block;
  margin-top: 1px;
  color: rgba(255, 255, 255, .52);
  font-size: 11.5px;
}

/* `.site-footer a` trae `margin-bottom: 9px`, pensado para los enlaces sueltos
   de las columnas. Aquí el margen lo pone ya el `<p>` que lo envuelve, y
   sumarlos abría un hueco que descuadraba la columna. */
.footer-whatsapp a,
.footer-email a {
  margin-bottom: 0;
}

/* El correo, con el mismo aire que el telefono y la ciudad. `break-all` no:
   una direccion partida por cualquier sitio deja de leerse como una direccion.
   `anywhere` corta solo si de verdad no cabe. */
.footer-email a {
  overflow-wrap: anywhere;
}

.footer-whatsapp a:hover .footer-whatsapp-nota,
.footer-whatsapp a:focus-visible .footer-whatsapp-nota {
  color: rgba(255, 255, 255, .78);
}

/* ══ Servicios de movilidad: la tarjeta que se pulsa ════════════════
 *
 * La tarjeta entera lleva al formulario de contacto. Sólo cuando el
 * componente recibe destino: sin él sigue siendo un `<article>` y esta clase
 * no llega a ponerse.
 */
.strategic-card-enlace {
  position: relative;
  cursor: pointer;
  color: inherit;
}

/*
 * El filete de marca, entrando desde la izquierda al pasar por encima.
 *
 * Es el mismo gesto que ya usan las tarjetas de áreas de la portada, y por eso
 * se repite aquí: dos secciones que se pulsan igual tienen que responder
 * igual, o cada una parece de una web distinta. Ocupa tres píxeles y no mueve
 * nada de sitio.
 */
.strategic-card-enlace::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  z-index: 3;
  height: 3px;
  background: var(--brand-gradient);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .28s cubic-bezier(.4, 0, .2, 1);
}

.strategic-card-enlace:hover::before,
.strategic-card-enlace:focus-visible::before {
  transform: scaleX(1);
}

.strategic-card-enlace:hover,
.strategic-card-enlace:focus-visible {
  border-color: rgba(0, 180, 255, .38);
  color: inherit;
}

/*
 * La acción, sólo al pasar por encima.
 *
 * **Ocupa su sitio siempre, aunque no se vea.** Se anima la opacidad y un
 * desplazamiento de cuatro píxeles, nunca el alto: si apareciera empujando, la
 * tarjeta crecería al pasar el cursor y las seis de la rejilla darían un salto
 * cada vez. Eso es CLS, y aquí ocurriría en cada movimiento del ratón.
 */
.strategic-body {
  display: flex;
  flex-direction: column;
}

.strategic-accion {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin-top: 16px;
  color: var(--primary-900);
  font-size: 13px;
  font-weight: 800;
  letter-spacing: .02em;
  opacity: 0;
  transform: translateY(4px);
  transition: opacity .24s ease, transform .24s cubic-bezier(.4, 0, .2, 1);
}

.strategic-accion i {
  font-size: 14px;
  transition: transform .24s ease;
}

.strategic-card-enlace:hover .strategic-accion,
.strategic-card-enlace:focus-visible .strategic-accion {
  opacity: 1;
  transform: translateY(var(--alza-tarjeta));
}

.strategic-card-enlace:hover .strategic-accion i,
.strategic-card-enlace:focus-visible .strategic-accion i {
  transform: translateX(3px);
}

/* Sin movimiento, la acción se ve siempre: aparecer de golpe al pasar el
   cursor es justo el salto que esa preferencia pide evitar, y esconderla sin
   forma de revelarla dejaría la tarjeta sin decir a dónde lleva. */
@media (prefers-reduced-motion: reduce) {
  .strategic-card-enlace::before,
  .strategic-accion,
  .strategic-accion i {
    transition: none;
  }

  .strategic-accion {
    opacity: 1;
    transform: none;
  }
}


/* ===== Páginas de error =========================================== */
/* El hero lo comparten con el Portal —ver `.portal-hero`, arriba—: una página
   de error sigue siendo el sitio, y es donde más falta hace que se note. Aquí
   sólo va lo que es suyo: el número y la rejilla de destinos.

   El 500 y el 503 no usan nada de esto: se sirven con estilo en línea desde
   `errors/minima.blade.php`, porque esta hoja puede ser justo lo que no ha
   llegado a cargar. */

.error-hero { text-align: left; }
.error-hero-copy { margin-inline: 0; }

/* El número, en el gradiente del manual.

   Es decorativo y va con `aria-hidden`: lo que se lee es el `<h1>`. Contraste
   sobre `--primary-950` a lo largo del gradiente: teal 10,9:1, cian 7,8:1 y
   azul eléctrico 3,96:1 en el extremo más oscuro. El mínimo WCAG para texto
   grande y elementos gráficos es 3:1, así que pasa en todo el recorrido —el
   4,5:1 del texto pequeño no aplica a 88 px. */
.error-codigo {
  margin: 0;
  font-size: clamp(88px, 16vw, 168px);
  font-weight: 800;
  line-height: .88;
  letter-spacing: -.04em;
  /* El respaldo. Si el navegador no recorta el fondo al texto, el número se
     ve en teal en vez de desaparecer: con `color: transparent` suelto, un
     navegador sin soporte deja un hueco en blanco. */
  color: var(--turquoise);
}

@supports (-webkit-background-clip: text) or (background-clip: text) {
  .error-codigo {
    background: var(--brand-gradient);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
  }
}

.error-acciones { margin-top: 30px; }

/* El boton principal sobre fondo oscuro, en teal y no en azul profundo.

   `.btn-primary` pinta `--primary-950` de fondo, que es **exactamente** el
   fondo de estos heroes: el boton desaparece y queda una etiqueta suelta. Se
   veia en la captura, no en el codigo.

   Lo comparten los dos heroes oscuros, la barra de filtros y **el bloque de
   cierre del sitio**, que son azul profundo igual.

   El de cierre es el que mas pesaba: «Agenda una reunion» es el boton que lleva
   al formulario que capta clientes, sale en 21 de las 38 vistas publicas y era
   el elemento menos visible de la pieza que existe para convertir. Al lado,
   «Contacta con nosotros» si lleva borde, asi que el orden de importancia
   quedaba **invertido**. No estaba roto —el enlace siempre funciono—, solo no
   se veia, y por eso nadie lo noto durante meses.

   Azul profundo sobre teal: 10,9:1. El par al reves —blanco sobre teal— daria
   1,59:1 y seria ilegible, que es la trampa de siempre con este color. */
.error-hero .btn-primary,
.portal-hero .btn-primary,
.final-cta .btn-primary,
.filters .btn-primary,
.oportunidades-alta .btn-primary,
.search-band form .btn-primary {
  background: var(--turquoise);
  color: var(--primary-950);
  box-shadow: 0 10px 22px rgba(25, 224, 194, .18);
}

.error-hero .btn-primary:hover,
.portal-hero .btn-primary:hover,
.final-cta .btn-primary:hover,
.filters .btn-primary:hover,
.oportunidades-alta .btn-primary:hover,
.search-band form .btn-primary:hover { background: var(--cyan); }

/* Los destinos, sólo en el 404. */
.error-destinos { margin-top: 46px; }

.error-destinos-titulo {
  margin: 0 0 20px;
  font-size: clamp(20px, 2vw, 26px);
}

.error-destinos-lista {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 14px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.error-destino {
  display: flex;
  align-items: center;
  gap: 12px;
  height: 100%;
  padding: 18px 20px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: #fff;
  color: var(--primary-950);
  font-weight: 600;
  transition: border-color .18s ease, box-shadow .18s ease, transform .18s ease;
}

.error-destino > span { flex: 1; }
.error-destino .bi:first-child { font-size: 20px; color: var(--accent-600); }

/* La flecha se corre al pasar por encima. Es el único movimiento de la
   página: la señal de que el destino es un enlace, no una tarjeta muerta. */
.error-destino-flecha { transition: transform .18s ease; }

.error-destino:hover,
.error-destino:focus-visible {
  border-color: var(--borde-hover);
  box-shadow: var(--sombra-hover);
  transform: translateY(var(--alza-tarjeta));
}

.error-destino:hover .error-destino-flecha,
.error-destino:focus-visible .error-destino-flecha { transform: translateX(4px); }

@media (prefers-reduced-motion: reduce) {
  .error-destino,
  .error-destino-flecha { transition: none; }
  .error-destino:hover,
  .error-destino:focus-visible { transform: none; }
  .error-destino:hover .error-destino-flecha { transform: none; }
}

@media (max-width: 1180px) {
  .error-destinos-lista { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 720px) {
  .error-destinos-lista { grid-template-columns: 1fr; }
  .error-codigo { font-size: clamp(72px, 22vw, 110px); }
}


/* La banda del buscador de la portada del Portal.

   Hereda de `.filters` —el azul profundo, el canto del degradado, los campos
   claros— porque es **la misma barra** que el listado, con un campo en vez de
   cuatro. Era una tarjeta blanca aparte y buscar se veia distinto segun por
   donde se llegara.

   Lo unico propio es la rejilla: `.filters` reparte cinco columnas y aqui hay
   dos. */
/* La barra de búsqueda de la portada del Portal.

   **Sólo el margen.** Antes reordenaba la rejilla a `1fr auto`, porque aquí
   había un campo y un botón y allí cuatro y un botón. Desde que las dos pintan
   la misma pieza, esa regla la rompía: con cinco celdas en dos columnas, los
   desplegables caían uno por fila y el botón ocupaba el ancho entero.

   La rejilla y sus cortes los pone `.filters`, que es de donde sale la barra. */
.portal-buscar-banda {
  margin-bottom: 34px;
}

/* ── El hero de la portada del Portal ─────────────────────────────────
   Mismo reparto que el de formaciones —texto a la izquierda, imagen a la
   derecha, fondo claro— pero con rejilla de verdad y no con la imagen a
   sangre: `.hero` ya la trae, y aquí hace falta que el mockup se vea entero.

   **No toca `.portal-hero`**, que lo comparte la página de error: allí sigue
   siendo la tarjeta oscura con su lienzo. Por eso esto es una clase aparte y
   no una variante de aquélla. */
.portal-hero-presenta {
  /* Al texto un poco mas que a la imagen. Con el reparto que trae `.hero`
     —0,82 contra 1,18— el titular caia en cinco lineas y el mockup se comia
     la pagina; medido sobre la pagina servida, no supuesto. */
  grid-template-columns: minmax(440px, 1.04fr) 1fr;
  align-items: center;
  gap: clamp(20px, 3vw, 44px);
  background: linear-gradient(180deg, #fff, var(--muted-surface));
}

.portal-hero-presenta .hero-copy {
  padding-block: clamp(40px, 5vw, 64px);
}

.portal-hero-presenta h1 {
  margin: 10px 0 0;
  font-size: clamp(30px, 3vw, 44px);
  line-height: 1.08;
  text-wrap: balance;
}

.portal-hero-presenta .hero-lead {
  max-width: 54ch;
  margin-top: 16px;
  font-size: clamp(16px, 1.4vw, 18px);
  line-height: 1.55;
}

.portal-hero-presenta .actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 26px;
}

.portal-hero-presenta .actions .btn { gap: 9px; }

/* El mockup.

   `object-fit: contain` y no `cover`: es una composición de tres pantallas y
   recortarla le corta los bordes, que es justo lo que se quiere enseñar.

   Se sale del contenedor por la derecha en pantallas anchas —`margin-right`
   negativo— para que llegue al borde como la foto de formaciones, sin que eso
   obligue a recortarla. */
/* Las cifras, sobre fondo claro.

   `.portal-cifras` nacio en el hero oscuro: texto blanco al 78 % y el numero
   en teal de marca. Sobre claro el blanco no existe y **el teal da 1,59:1**,
   que es la trampa de siempre con este color: vale para un fondo oscuro y es
   ilegible sobre uno claro. Aqui el numero va en Azul Profundo —15,8:1— y el
   texto en el gris del sitio. */
.portal-hero-presenta .portal-cifras {
  margin-top: 22px;
  color: var(--muted);
}

.portal-hero-presenta .portal-cifras strong { color: var(--primary-950); }

.portal-hero-mockup {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding-block: clamp(20px, 3vw, 40px);
  padding-right: clamp(16px, 2vw, 32px);
}

.portal-hero-mockup img {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 760px;
  height: auto;
  /* Muy lenta y de seis píxeles: lo justo para que la página respire sin
     competir con el titular, que es lo que hay que leer. */
  animation: portal-mockup-flota 9s ease-in-out infinite alternate;
}

/* El resplandor de marca detrás del mockup.

   Los tres colores del manual —teal, cian y azul eléctrico— en tres manchas
   difusas, no un degradado lineal: un degradado recto detrás de una
   composición recortada se lee como un rectángulo de color, y esto se lee
   como luz.

   Al 14 % y desenfocado: sobre el fondo claro del hero tiene que **insinuarse**
   y no teñir. Medido en el gris del fondo, el texto de al lado no cambia de
   contraste porque el resplandor no llega hasta él.

   Es decoración pura, así que va en un pseudoelemento y no en el marcado. */
.portal-hero-mockup::before {
  content: "";
  position: absolute;
  z-index: 0;
  /* Se sale del mockup por los cuatro lados: metido por detrás, la parte
     opaca de las pantallas se lo tapaba y sólo asomaba un halo de dos o tres
     niveles de gris, o sea nada. Medido con muestras de color sobre la página
     servida, no a ojo. */
  /* Contenido en la columna de la imagen.

     Con el borde izquierdo en negativo el desenfoque cruzaba por detrás del
     titular y teñía media página: no llegaba a comprometer el contraste, pero
     se leía como una mancha y no como luz detrás del mockup. Se queda dentro
     y los tres focos se corren a la derecha. */
  inset: -4% -3% 4% 12%;
  border-radius: 50%;
  background:
    radial-gradient(42% 48% at 28% 38%, rgba(25, 224, 194, .46), transparent 66%),
    radial-gradient(40% 46% at 60% 68%, rgba(0, 180, 255, .40), transparent 68%),
    radial-gradient(44% 50% at 88% 34%, rgba(41, 98, 255, .30), transparent 66%);
  filter: blur(42px);
  animation: portal-mockup-respira 11s ease-in-out infinite alternate;
}

@keyframes portal-mockup-flota {
  from { transform: translateY(3px); }
  to { transform: translateY(-3px); }
}

@keyframes portal-mockup-respira {
  from { opacity: .75; transform: scale(.97); }
  to { opacity: 1; transform: scale(1.03); }
}

/* Quien pide menos movimiento se queda con el fotograma quieto, no con una
   versión lenta: la preferencia suele tener un motivo médico. Y el fotograma
   se sostiene solo —el resplandor sigue ahí—, que es la prueba de que el
   efecto no era lo que aguantaba la composición. */
@media (prefers-reduced-motion: reduce) {
  .portal-hero-mockup img,
  .portal-hero-mockup::before { animation: none; }
}

/* Por debajo del corte del sitio, apilado y con la imagen debajo del texto.

   Debajo y no encima: en un móvil lo primero tiene que ser lo que dice qué es
   esto, no una imagen de la que no se distingue nada a ese tamaño. */
@media (max-width: 1180px) {
  .portal-hero-presenta {
    display: block;
  }

  .portal-hero-mockup {
    justify-content: center;
    padding: 0 clamp(16px, 4vw, 32px) clamp(28px, 5vw, 44px);
  }

  .portal-hero-mockup img { max-width: 620px; }
}

.portal-hero-accion {
  margin: 28px 0 0;
}

.portal-hero-accion .btn { gap: 9px; }

/* ── El hero del Portal, en dos columnas ──────────────────────────────
   Apilado y centrado medía 654 px de alto, medidos sobre la página servida:
   con la cabecera fija encima se comía la primera pantalla entera.

   Va sobre `.portal-hero-doble` y no sobre `.portal-hero` porque la página de
   error reutiliza `portal-hero` y `portal-hero-copy` para no duplicar cuarenta
   líneas de CSS; una regla sobre esos nombres la movería también.

   Sólo desde 1.180, el corte del sitio: por debajo, dos columnas son dos
   columnas estrechas y se apila como estaba. */

@media (min-width: 1180px) {
  .portal-hero-doble {
    padding-block: clamp(42px, 4.4vw, 60px);
    text-align: left;
  }

  .portal-hero-doble .portal-hero-copy {
    display: grid;
    /* La columna del texto manda; la de las acciones no baja de 260 px, que es
       lo que necesita el botón de instalar sin partirse en dos líneas. */
    grid-template-columns: minmax(0, 1.5fr) minmax(260px, 0.9fr);
    align-items: center;
    gap: clamp(32px, 4vw, 72px);
    max-width: 1240px;
  }

  /* El texto deja de ir centrado y de estrecharse: la columna ya lo acota. */
  .portal-hero-doble .portal-hero-lead,
  .portal-hero-doble .portal-hero-texto {
    margin-inline: 0;
    max-width: 46ch;
  }

  /* Las acciones, en su columna y alineadas a la izquierda de ella. */
  .portal-hero-doble .portal-hero-hacer {
    display: grid;
    justify-items: start;
    gap: 14px;
  }

  .portal-hero-doble .portal-hero-accion,
  .portal-hero-doble .portal-instalar,
  .portal-hero-doble .portal-cifras {
    margin: 0;
  }

  /* Las cifras, una debajo de otra: en la columna estrecha, en una línea se
     partían por cualquier sitio y el punto de separación quedaba colgando.
     Apiladas sobra, así que se esconde. */
  .portal-hero-doble .portal-cifras {
    display: grid;
    gap: 2px;
    margin-top: 6px;
  }

  .portal-hero-doble .portal-cifra-punto { display: none; }
}

/* ── Postularse a una oferta ──────────────────────────────────────────
   El bloque cambia según quién mire —sin sesión, con perfil, o ya postulado—
   pero la ficha alrededor es la misma. Ver `portal/oferta.blade.php`. */

.oferta-postular {
  display: grid;
  gap: 10px;
  margin-top: 4px;
}

.oferta-postular-rotulo {
  color: var(--primary-950);
  font-size: 13px;
  font-weight: 700;
}

.oferta-postular textarea {
  width: 100%;
  padding: 11px 13px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: #fff;
  font: inherit;
  font-size: 15px;
  /* Sólo vertical: a lo ancho se sale de la columna lateral. */
  resize: vertical;
}

.oferta-postular textarea:focus-visible { border-color: var(--accent-500); }

/* Ya postulado. En verde y no en el azul de marca: es una confirmación, y el
   azul aquí se lee como un enlace más. Texto #0E9F86 sobre su propio tinte al
   10 % —el mismo verde de «éxito» del panel— da 4,6:1. */
.oferta-candidatura {
  margin-top: 4px;
  padding: 14px 16px;
  border: 1px solid rgba(14, 159, 134, .3);
  border-radius: var(--radius-md);
  background: rgba(14, 159, 134, .08);
}

.oferta-candidatura-titulo {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin: 0;
  color: #0B7A66;
  font-size: 15px;
  font-weight: 700;
  line-height: 1.4;
}

.oferta-candidatura-estado {
  margin: 8px 0 0;
  font-size: 14px;
  color: var(--muted);
}

.oferta-candidatura-estado strong { color: var(--primary-950); }

/* «Ya te has postulado», en la tarjeta del listado.

   Discreto a proposito: no es una llamada a la accion, es un dato que ahorra
   abrir la ficha para descubrir que alli no hay nada que hacer. Mismo verde que
   la confirmacion de la ficha, y el texto en #0B7A66 sobre su tinte al 8 % da
   6,1:1. */
.oferta-postulada {
  display: flex;
  align-items: center;
  gap: 7px;
  margin: 12px 0 0;
  padding: 7px 11px;
  border-radius: var(--radius-pill);
  background: rgba(14, 159, 134, .08);
  color: #0B7A66;
  font-size: 13px;
  font-weight: 700;
}

/* «Acceder» en la cabecera, para quien no ha entrado.

   Exactamente el mismo trato que `.nav-perfil`, que es su pareja: ocupan el
   mismo hueco y sale uno u otro segun haya sesion. El color y el tamano los
   pone `.main-nav a`, como a cualquier otro enlace de la barra; fijarlos aqui
   lo separaria del resto en cuanto alguien retoque la cabecera. */
.nav-acceder {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

/* ── Entrar con Google ────────────────────────────────────────────────
   Blanco con borde y el logotipo en sus colores. Sus condiciones de marca
   piden el logotipo tal cual, sin recolorear, asi que este boton es el unico
   del sitio que no lleva la paleta de Maude.

   Texto #1F2933 sobre blanco: 12,6:1. El borde a 1,7:1 no llega al 3:1 que
   pide un componente, asi que **no es lo unico que lo delimita**: el boton
   ocupa todo el ancho y lleva el logotipo dentro, que es lo que lo hace
   reconocible como boton. */
.btn-google {
  width: 100%;
  justify-content: center;
  gap: 10px;
  padding: 12px 16px;
  border: 1px solid var(--border);
  background: #fff;
  color: var(--dark-gray);
  font-weight: 700;
}

.btn-google:hover { background: var(--surface); }
.btn-google svg { flex: none; }

/* «o bien», con una raya a cada lado: deja claro que son dos caminos y no dos
   pasos de uno solo. */
.portal-o-bien {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 18px 0;
  color: var(--muted);
  font-size: 13px;
}

.portal-o-bien::before,
.portal-o-bien::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--border);
}

/* Con que cuenta se va a crear el perfil. Se enseña para que nadie se registre
   con el Gmail equivocado sin darse cuenta: el correo ya no se cambia. */
.portal-google-cuenta {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 4px 0 22px;
  padding: 14px 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
  font-size: 14px;
}

.portal-google-cuenta i { font-size: 22px; color: var(--accent-600); }
.portal-google-cuenta strong { display: block; color: var(--primary-950); }

/* La invitacion a crear perfil, bajo el listado de ofertas.

   Aqui no habia ni un solo enlace al registro: se veian todas las ofertas y
   nada invitaba a entrar. Va debajo de las tarjetas —primero se ve que hay,
   luego se decide— y en claro, para no sumar una cuarta superficie oscura a una
   pagina que ya termina con el bloque de cierre. */
/* La invitación a registrarse, al final del listado.

   **Sobre Azul Profundo y no en blanco.** Era una tarjeta blanca con borde
   fino, o sea exactamente el mismo traje que las tarjetas de oferta que tiene
   encima: en vez de cerrar el listado se leía como una oferta más y se pasaba
   de largo. Los cierres del sitio son superficies oscuras con el canto de
   marca —el bloque final de la portada, el diferenciador del Portal, la propia
   barra de búsqueda de esta misma página—, así que esta entra en esa familia.

   El degradado va como fondo de la caja y no en un pseudoelemento, por lo
   mismo que la barra de búsqueda: así lo recorta el `border-radius` y la
   franja sigue la curva de la esquina en vez de sobresalir. */
.oportunidades-alta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: clamp(18px, 3vw, 40px);
  margin-top: 38px;
  padding: clamp(26px, 3.4vw, 38px);
  border-radius: var(--radius-lg);
  color: #fff;
  background-color: var(--primary-950);
  background-image: var(--brand-gradient);
  background-repeat: no-repeat;
  background-size: 100% 3px;
  background-position: 0 0;
  box-shadow: 0 24px 56px rgba(10, 18, 48, .20);
}

.oportunidades-alta h2 {
  margin: 0 0 8px;
  color: #fff;
  font-size: clamp(21px, 2.3vw, 28px);
  text-wrap: balance;
}

/* Blanco al 82 % sobre el Azul Profundo: 14,4:1, muy por encima del 4,5:1 que
   pide el texto normal. El gris `--muted` de antes era para fondo claro y aquí
   no se leería. */
.oportunidades-alta p {
  margin: 0;
  max-width: 62ch;
  color: rgba(255, 255, 255, .82);
  font-size: 15px;
}

.oportunidades-alta-acciones {
  display: grid;
  justify-items: start;
  gap: 12px;
  flex: none;
}

.oportunidades-alta-pie {
  font-size: 13px;
  color: rgba(255, 255, 255, .74);
}

/* El enlace secundario, que era un subrayado azul de navegador.

   En teal y sin subrayado permanente: el subrayado aparece al pasar por
   encima, que es donde informa. Teal sobre Azul Profundo da 10,9:1. */
.oportunidades-alta-pie a {
  color: var(--turquoise);
  font-weight: 700;
  text-decoration: none;
}

.oportunidades-alta-pie a:hover,
.oportunidades-alta-pie a:focus-visible {
  text-decoration: underline;
  text-underline-offset: 3px;
}


/* ── La invitación al destino ──────────────────────────────────────────
   Cierra el bloque de formaciones de una oferta. Era un botón pequeño al pie
   y eso enterraba lo que hay al otro lado: la ciudad tiene ficha propia con
   fotografía, presentación y motivos, y quien mira una oferta en Málaga casi
   nunca conoce Málaga.

   Horizontal y a todo el ancho, con la foto a un lado. La pieza **entera** es
   el enlace —no un botón dentro de una tarjeta—: así toda la superficie es
   pulsable y con teclado se llega de una sola parada. */
.destino-invitacion {
  display: grid;
  /* Dos columnas: la foto y el resto.

     Fueron tres —foto, texto y una columna aparte con la llamada— y eso dejaba
     **dos huecos en vez de uno**: el párrafo no llena su columna y la de la
     derecha quedaba casi vacía. Con la llamada debajo del texto, lo que sobraba
     se lo queda la fotografía, que es lo que de verdad vende el sitio. */
  /* Mitad y mitad. Medido: el párrafo mide 567 px y su columna, con el relleno,
     necesita unos 630; a `.62fr` sobraban 220 y volvía a verse el hueco. A
     partes iguales el texto llena su mitad y la fotografía —que es lo que de
     verdad vende el sitio— ocupa la otra entera. */
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: stretch;
  margin-top: 34px;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: #fff;
  box-shadow: var(--soft-shadow);
  color: inherit;
  transition: transform .18s ease, border-color .18s ease, box-shadow .22s ease;
}

.destino-invitacion:hover,
.destino-invitacion:focus-visible {
  transform: translateY(var(--alza-tarjeta));
  border-color: var(--borde-hover);
  box-shadow: var(--sombra-hover);
}

.destino-invitacion-media {
  position: relative;
  min-height: 210px;
}

.destino-invitacion-media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* El hueco cuando el destino todavía no tiene foto. Un tinte de marca y el
   icono centrado, como en las fichas de destino: se lee como «aún sin foto»
   y no como un recuadro roto. */
.destino-invitacion-vacia {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: linear-gradient(160deg, rgba(25, 224, 194, .14), rgba(41, 98, 255, .12));
  color: rgba(10, 18, 48, .28);
  font-size: 40px;
}

.destino-invitacion-copy {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  padding: clamp(22px, 2.6vw, 32px);
}

.destino-invitacion-nombre {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 10px;
  color: var(--primary-950);
  font-size: clamp(21px, 2.2vw, 27px);
  line-height: 1.12;
}

/* La provincia, en gris y más pequeña: acompaña al nombre de la ciudad sin
   competir con él, y en las que se llaman igual —Málaga, Málaga— evita que
   parezca un error. */
.destino-invitacion-nombre span {
  color: var(--muted);
  font-size: 14px;
  font-weight: 600;
}

/* Tres líneas y no más.

   Los subtítulos los escribe quien carga el destino y salen de muy distinto
   largo: el de Málaga son dos líneas y el de Móstoles seis. A seis, la pieza
   deja de ser un gancho y se lee como un párrafo más de la página, que es
   justo lo que ya hay debajo.

   Se recorta con `line-clamp` y no cortando la cadena en el Blade: así se
   adapta al ancho —en móvil caben menos palabras por línea— y nunca parte una
   palabra por la mitad. El texto entero está a un clic, en la ficha. */
.destino-invitacion-texto {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  overflow: hidden;
  max-width: 62ch;
  margin-top: 4px;
  color: var(--muted);
  font-size: 15px;
  line-height: 1.55;
}

/* La columna de la derecha: los números y el botón.

   Separada por una línea fina, no por un cambio de fondo: la tarjeta sigue
   siendo una sola pieza y la raya sólo dice dónde acaba de leerse y dónde se
   decide. */
/* El pie de la tarjeta: la llamada y los números, en una fila.

   El botón primero y las cifras después: lo que se decide va delante de lo que
   lo justifica, y así la píldora queda alineada con el texto de arriba. */
.destino-invitacion-pie {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 22px;
  margin-top: 18px;
}

.destino-invitacion-cifras {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 20px;
  color: var(--muted);
  font-size: 14px;
  white-space: nowrap;
}

.destino-invitacion-cifras strong {
  color: var(--primary-950);
  font-size: 18px;
  /* Los números no bailan al cambiar de cifra. */
  font-variant-numeric: tabular-nums;
}

/* La llamada es un `span` con pinta de botón, no un `<a>`: la tarjeta entera ya
   es el enlace y meter otro dentro daría dos paradas de teclado para el mismo
   destino, y un enlace anidado que el navegador no sabe resolver.

   **Y no responde por su cuenta.** Siendo parte de una pieza que ya es pulsable
   entera, un botón que se eleva sólo cuando el puntero le cae justo encima hace
   que la tarjeta parezca dos cosas: se pasa el ratón por el texto, la tarjeta
   sube, y el botón se queda quieto. Manda la tarjeta y el botón la acompaña. */
.destino-invitacion-cta:hover { transform: none; }

.destino-invitacion:hover .destino-invitacion-cta,
.destino-invitacion:focus-visible .destino-invitacion-cta {
  box-shadow: 0 16px 32px rgba(10, 18, 48, .26);
}

.destino-invitacion:hover .destino-invitacion-cta i,
.destino-invitacion:focus-visible .destino-invitacion-cta i {
  background: var(--cyan);
  transform: translateX(3px);
}

/* Apilada en móvil, con la foto arriba: en una columna estrecha, una imagen de
   un tercio del ancho no enseña nada. */
@media (max-width: 720px) {
  .destino-invitacion { grid-template-columns: 1fr; }
  .destino-invitacion-media { min-height: 180px; }
  .destino-invitacion-pie { gap: 14px; }
}

@media (prefers-reduced-motion: reduce) {
  .destino-invitacion:hover .destino-invitacion-cta i { transform: none; }
}

/* La oferta en horizontal, junto a las formaciones.

   Comparte **todas** las reglas de `.destination-training-item` —el borde, el
   canto de marca que asoma al pasar por encima, el levantar tres pixeles, la
   flecha de la derecha— porque en las fichas de destino los dos bloques se leen
   seguidos, y con dos lenguajes distintos parecian dos sistemas pegados uno
   detras de otro.

   Compartir la regla en vez de copiarla es lo que garantiza que sigan iguales
   el dia que alguien retoque una de las dos.

   Aqui solo va lo que es suyo: la linea de datos con iconos, que una formacion
   no tiene. */
.destino-oferta-datos {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 14px;
  margin-top: 2px;
}

/* Sin la mayuscula ni el peso del rotulo de arriba: son datos, no epigrafe. */
.destino-oferta-datos span {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  color: var(--muted);
  font-size: 13px;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
}

/* Los iconos van en el flujo: la regla compartida coloca la flecha en absoluto,
   y estos no son esa flecha. */
.destino-oferta-datos i {
  position: static;
  color: var(--accent-600);
  font-size: 14px;
}

/* «Ya te has postulado», en la fila: mas discreto que en la tarjeta, porque
   aqui compite con menos cosas. */
.destino-oferta-item .oferta-postulada {
  margin: 6px 0 0;
  padding: 4px 9px;
  font-size: 12px;
}


/* Las formaciones del destino, en la ficha de una oferta.

   Rejilla propia y no la de la tarjeta de destino: aquella vive en una columna
   estrecha y esta ocupa el ancho de la pagina, donde `auto-fill` con minimo de
   340 px habria puesto tres o cuatro por fila. Aqui van **dos**, que es lo que
   deja leer el titulo y el resumen sin apretarlos.

   Y con mas aire entre ellas que en la tarjeta —16 en vez de 12—: apiladas a
   todo lo ancho se leian como un bloque continuo, sin separacion entre una
   ficha y la siguiente. */
.oferta-formaciones-grid {
  display: grid;
  gap: 16px;
}

@media (min-width: 720px) {
  .oferta-formaciones-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
