/* ==========================================================================
   Telat Group — Design system v2
   Built on top of Bootstrap 5.3 (bootstrap.min.css) — do not edit Bootstrap.
   Brand source: codigos_de_referencia/Manual de Identidad Telat 2026 Final.pdf
   ========================================================================== */

/* -- Fonts -----------------------------------------------------------------
   Body copy: Montserrat (brand manual, sec. 4.3)
   Subheadings: DM Sans (brand manual, sec. 4.2)
   Headings: brand manual specifies "Momo Trust" (sec. 4.1), a licensed font
   not available in this project. Using Poppins as a placeholder with the
   same geometric/rounded character — swap via --tl-font-heading once the
   real font files are supplied.
   -------------------------------------------------------------------------- */
@import url('https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,400;0,500;0,600;0,700;1,400&family=DM+Sans:wght@400;500;700&family=Poppins:wght@500;600;700;800&display=swap');

:root,
[data-bs-theme="light"] {
  /* Brand palette — light mode */
  --tl-blue: #3284C6;
  --tl-blue-rgb: 50, 132, 198;
  --tl-orange: #EB5B27;
  --tl-orange-rgb: 235, 91, 39;
  /* Variantes para cuando el color de marca ES el texto — ver 2.5. Sobre fondo
     claro el naranja da 3.12 y el azul 3.60, ambos por debajo de AA. Fondos,
     bordes, íconos y sombras siguen usando los tokens de arriba. */
  --tl-orange-text: #BE4419;
  --tl-blue-text: #2A6DA6;
  --tl-orange-light: #FECA66;
  --tl-orange-light-rgb: 254, 202, 102;
  --tl-bg: #FBFBFD;
  --tl-surface: #FFFFFF;
  --tl-surface-alt: #F1F3F7;
  --tl-text: #222221;
  --tl-text-muted: #5B5F66;
  --tl-border: rgba(34, 34, 33, 0.10);
  --tl-shadow: 0 1rem 3rem rgba(34, 34, 33, 0.08);

  color-scheme: light;
}

[data-bs-theme="dark"] {
  /* Brand palette — dark mode (tuned for AA contrast, same brand hues) */
  --tl-blue: #62A8E0;
  --tl-blue-rgb: 98, 168, 224;
  --tl-orange: #FF7A4A;
  --tl-orange-rgb: 255, 122, 74;
  /* Aquí el naranja y el azul base ya pasan AA como texto (5.8:1 / 5.8:1 en el
     peor fondo), así que las variantes de texto son las mismas que el resto
     de la marca — no hace falta un segundo par de tonos en oscuro. */
  --tl-orange-text: var(--tl-orange);
  --tl-blue-text: var(--tl-blue);
  --tl-orange-light: #FECA66;
  --tl-orange-light-rgb: 254, 202, 102;
  --tl-bg: #16181C;
  --tl-surface: #1E2126;
  --tl-surface-alt: #24272D;
  --tl-text: #F3F4F6;
  --tl-text-muted: #A7ABB3;
  --tl-border: rgba(255, 255, 255, 0.10);
  --tl-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.35);

  color-scheme: dark;
}

:root {
  --tl-font-body: "Montserrat", system-ui, sans-serif;
  --tl-font-sub: "DM Sans", system-ui, sans-serif;
  --tl-font-heading: "Poppins", system-ui, sans-serif; /* placeholder for Momo Trust */
  --tl-radius: 1rem;
  --tl-radius-sm: .6rem;

  /* -- Fondos de "chip" de marca (ver 2.3) --------------------------------
     Van aquí, en el :root sin tema, y NO en los bloques light/dark: un chip
     lleva texto de color fijo encima, así que su fondo tampoco puede cambiar.
     Cuando `.is-blue` usaba `var(--tl-blue)`, en oscuro el token se aclaraba a
     #62A8E0 y el texto blanco caía a 2.56:1.

     No son `--tl-blue` / `--tl-orange` a secas porque esos dos no sostienen
     texto de 16px: sobre #3284C6 el blanco da 4.00 y la tinta oscura 3.98
     —el azul cae justo en la zona muerta donde no sirve ninguno de los dos—
     y sobre #EB5B27 el blanco da 3.47. Estos son el oscurecimiento mínimo que
     cruza el 4.5 con blanco puro, para mover el tono lo menos posible. */
  --tl-blue-chip: #2E79B6;    /* blanco: 4.64:1 */
  --tl-orange-chip: #C94A1D;  /* blanco: 4.69:1 */
  --tl-gold-chip: #FECA66;    /* tinta #222221: 10.51:1 — el dorado sólo admite tinta oscura */
}

/* -- Map onto Bootstrap's own variables so all components inherit -------- */
[data-bs-theme="light"],
[data-bs-theme="dark"] {
  --bs-body-bg: var(--tl-bg);
  --bs-body-color: var(--tl-text);
  --bs-body-font-family: var(--tl-font-body);
  --bs-border-color: var(--tl-border);

  --bs-primary: var(--tl-blue);
  --bs-primary-rgb: var(--tl-blue-rgb);
  --bs-link-color: var(--tl-blue);
  --bs-link-hover-color: var(--tl-orange);
}

html {
  scroll-behavior: smooth;
}

/* El cintillo diagonal (.tl-marquee-band) va rotado -1.5deg: su caja rotada
   mide ~1px más que el viewport y eso bastaba para provocar scroll horizontal
   en todo el documento.
   Se recorta en <main> y no en <html> ni en <body>: el overflow del elemento
   raíz se propaga al viewport y el del body también cuando el raíz es
   `visible`, así que en ambos casos el recorte se anula y el scroll sigue ahí
   (comprobado en Chrome: seguía desplazando 1px).
   `clip` en vez de `hidden` porque `hidden` crearía un contenedor de scroll.
   La navbar sticky vive fuera de <main>, así que no le afecta. */
main {
  overflow-x: clip;
}

body {
  background-color: var(--tl-bg);
  color: var(--tl-text);
  transition: background-color .25s ease, color .25s ease;
}

/* Páginas de una sola pantalla —gracias, error de postulación— donde el
   contenido no da para empujar el pie hasta abajo y queda un hueco de fondo
   debajo de él.

   Se pide en el <body> de esas páginas y no globalmente: el resto del sitio es
   largo y no lo necesita, y meter `display:flex` en TODOS los body es cambiar
   el contexto de formato de cada página por un problema que sólo tienen dos. */
body.tl-pagina-corta {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

/* `main` crece para empujar el pie, y sus secciones crecen con él: si sólo
   crece `main`, el hueco sobrante aparece entre la última sección y el pie,
   con el fondo del body a la vista en vez del de la sección. */
body.tl-pagina-corta > main {
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
}

body.tl-pagina-corta > main > section {
  flex: 1 0 auto;
  display: flex;
  align-items: center;
}

/* `.container` centra por márgenes automáticos, que como elemento flexible
   siguen funcionando; el ancho sí hay que declararlo o se encoge al contenido. */
body.tl-pagina-corta > main > section > .container {
  width: 100%;
}

h1, h2, h3, h4 {
  font-family: var(--tl-font-heading);
  font-weight: 700;
  letter-spacing: -.01em;
  color: var(--tl-text);
}

h5, h6, .tl-subheading {
  font-family: var(--tl-font-sub);
  font-weight: 700;
}

.tl-eyebrow {
  font-family: var(--tl-font-sub);
  font-weight: 700;
  font-size: 1rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--tl-orange-text);
}

a {
  transition: color .15s ease;
}

/* -- Layout helpers -------------------------------------------------------- */
.tl-section {
  padding-block: clamp(3rem, 6vw, 6rem);
}

/* La navbar es sticky, así que al saltar a un ancla (#cotizar, #postularme,
   #mision-vision, #sedes…) el título de la sección quedaba oculto debajo.
   El margen reserva su altura. */
section[id] {
  scroll-margin-top: 7.5rem;
}

.tl-surface {
  background-color: var(--tl-surface);
}

.tl-surface-alt {
  background-color: var(--tl-surface-alt);
}

.tl-text-muted {
  color: var(--tl-text-muted) !important;
}

/* -- Navbar ------------------------------------------------------------- */
/* Separación entre opciones del menú.
   Se mapea la variable de Bootstrap en vez de sobreescribir el padding: su
   regla `.navbar-expand-lg .navbar-nav .nav-link` tiene más especificidad y
   ganaba siempre. Y la variable va sobre `.navbar` —el <nav>—, no sobre
   `.tl-navbar` —el <header>—, porque Bootstrap la declara ahí mismo y una
   declaración local pisa a la heredada.
   El subrayado del activo usa este mismo valor en su left/right. */
.tl-navbar .navbar {
  --bs-navbar-nav-link-padding-x: 1.15rem;
}

.tl-navbar {
  background-color: color-mix(in srgb, var(--tl-bg) 88%, transparent);
  backdrop-filter: saturate(180%) blur(12px);
  -webkit-backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid var(--tl-border);
  transition: background-color .25s ease, border-color .25s ease;

}

.tl-navbar .nav-link {
  font-family: var(--tl-font-sub);
  font-weight: 500;
  color: var(--tl-text);
  position: relative;
}

.tl-navbar .nav-link.active,
.tl-navbar .nav-link:hover {
  color: var(--tl-blue-text);
}

.tl-navbar .nav-link.active::after {
  content: "";
  position: absolute;
  left: 1.15rem;
  right: 1.15rem;
  bottom: -2px;
  height: 2px;
  background: var(--tl-orange);
  border-radius: 2px;
}

.tl-logo img {
  height: 62px;
  width: auto;
  display: block;
}

.tl-logo .logo-dark { display: block; }
.tl-logo .logo-light { display: none; }
[data-bs-theme="dark"] .tl-logo .logo-dark { display: none; }
[data-bs-theme="dark"] .tl-logo .logo-light { display: block; }

/* -- Theme toggle --------------------------------------------------------- */
.tl-theme-toggle {
  width: 2.5rem;
  height: 2.5rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  border: 1px solid var(--tl-border);
  background: var(--tl-surface);
  color: var(--tl-text);
  cursor: pointer;
}

.tl-theme-toggle:hover {
  border-color: var(--tl-blue);
  color: var(--tl-blue);
}

/* El CTA del navbar se iguala en alto al conmutador de tema (2.5rem). Con el
   padding vertical de .75rem que traen todos los botones se quedaba en 45px y
   sobresalía 2.5px por arriba y por abajo de la fila de controles — `btn-sm`
   no lo corrige, porque en este sistema sólo cambia el tamaño de letra (5.2).
   Se fija la altura en lugar de recalcular el padding para que siga cuadrando
   si algún día cambia el cuerpo de letra. El padding horizontal se conserva.
   Sólo aplica dentro del navbar: fuera, el botón mantiene su tamaño. */
.tl-navbar .btn-tl-primary {
  height: 2.5rem;
  padding-block: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.tl-theme-toggle .bi-sun { display: none; }
.tl-theme-toggle .bi-moon-stars { display: inline-block; }
[data-bs-theme="dark"] .tl-theme-toggle .bi-sun { display: inline-block; }
[data-bs-theme="dark"] .tl-theme-toggle .bi-moon-stars { display: none; }

/* -- Buttons ---------------------------------------------------------- */
.btn-tl-primary {
  --bs-btn-color: #fff;
  --bs-btn-bg: linear-gradient(135deg, var(--tl-blue), var(--tl-orange));
  background: linear-gradient(135deg, var(--tl-blue), var(--tl-orange));
  border: none;
  color: #fff;
  font-family: var(--tl-font-sub);
  font-weight: 700;
  padding: .75rem 1.75rem;
  border-radius: 50rem;
  box-shadow: 0 .5rem 1.25rem rgba(var(--tl-orange-rgb), .28);
  transition: transform .15s ease, box-shadow .15s ease, filter .15s ease;
}

.btn-tl-primary:hover {
  color: #fff;
  filter: brightness(1.06);
  transform: translateY(-1px);
  box-shadow: 0 .75rem 1.75rem rgba(var(--tl-orange-rgb), .35);
}

.btn-tl-outline {
  font-family: var(--tl-font-sub);
  font-weight: 700;
  padding: .75rem 1.75rem;
  border-radius: 50rem;
  border: 1.5px solid var(--tl-border);
  color: var(--tl-text);
  background: transparent;
  transition: border-color .15s ease, color .15s ease;
}

.btn-tl-outline:hover {
  border-color: var(--tl-blue);
  color: var(--tl-blue);
}

/* Sobre hero oscuro —con video o no— el texto de `.btn-tl-outline` usa
   `--tl-text`, que en tema claro es casi negro: el botón quedaba invisible.
   Mismo criterio que `.tl-hero-badge`. */
.tl-hero-video .btn-tl-outline,
.tl-page-hero.is-dark .btn-tl-outline {
  border-color: rgba(255, 255, 255, .35);
  color: #fff;
}
.tl-hero-video .btn-tl-outline:hover,
.tl-page-hero.is-dark .btn-tl-outline:hover {
  border-color: var(--tl-orange-light);
  color: var(--tl-orange-light);
}

/* -- Cards / chips ------------------------------------------------------ */
.tl-card {
  background: var(--tl-surface);
  border: 1px solid var(--tl-border);
  border-radius: var(--tl-radius);
  box-shadow: var(--tl-shadow);
  transition: transform .2s ease, box-shadow .2s ease;
}

/* La elevación sola no se leía: la tarjeta subía pero la sombra seguía siendo
   la de reposo, así que el movimiento no parecía despegar de la página. Se
   refuerza la sombra en hover, igual que hacen .tl-solution-card y
   .tl-value-card. */
.tl-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 1.6rem 3rem rgba(34, 34, 33, .16);
}
[data-bs-theme="dark"] .tl-card:hover {
  box-shadow: 0 1.6rem 3rem rgba(0, 0, 0, .45);
}
/* Modificador de color en hover, mismo lenguaje que .tl-solution-card: la
   sombra toma el color de marca en vez del gris neutro. Va después de la
   regla de tema oscuro para ganarle también ahí — el color de marca funciona
   en ambos temas, así que no necesita variante propia. */
.tl-card.is-blue:hover,
[data-bs-theme="dark"] .tl-card.is-blue:hover {
  box-shadow: 0 1.6rem 3rem rgba(var(--tl-blue-rgb), .3);
}
/* Naranja para los bloques CTA: es el color de acción (2.4) y el que domina el
   extremo del botón primario que llevan dentro. */
.tl-card.is-orange:hover,
[data-bs-theme="dark"] .tl-card.is-orange:hover {
  box-shadow: 0 1.6rem 3rem rgba(var(--tl-orange-rgb), .3);
}

.tl-icon-badge {
  width: 3.25rem;
  height: 3.25rem;
  border-radius: var(--tl-radius-sm);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 1.4rem;
  color: var(--tl-blue);
  background: rgba(var(--tl-blue-rgb), .14);
  /* Mismo canto que .tl-solution-icon (5.4): sin él la placa se queda plana y
     desentona al lado de los íconos de las tarjetas de solución. */
  border: 1px solid rgba(var(--tl-blue-rgb), .45);
}

/* Variante para fondos oscuros fijos (.tl-value-card.is-dark, bandas #1F2124):
   ahí el azul de marca pierde contraste y el dorado es el acento correcto.
   Aquí el glifo SÍ va en dorado —al revés que en .tl-solution-icon.is-gold—
   porque esta variante sólo se usa sobre oscuro, que es donde el dorado
   funciona (regla 2.4). */
.tl-icon-badge.is-gold {
  color: var(--tl-orange-light);
  background: rgba(var(--tl-orange-light-rgb), .18);
  border-color: rgba(var(--tl-orange-light-rgb), .55);
}

/* Sin anidar bajo `.tl-stat`: el número debe estilizarse solo, aunque viva
   dentro de una tarjeta o de cualquier otro contenedor. */
.tl-stat-number {
  font-family: var(--tl-font-heading);
  font-weight: 800;
  font-size: clamp(1.75rem, 3vw, 2.5rem);
  line-height: 1.1;
  color: var(--tl-blue);
}

/* -- Counters band (dark, on-brand background for the animated stats) ----- */
.tl-counters {
  position: relative;
  overflow: hidden;
  padding-block: clamp(3.5rem, 7vw, 5.5rem);
  background: #24272d;
}
.tl-counters::before,
.tl-counters::after {
  content: "";
  position: absolute;
  top: 50%;
  border-radius: 50%;
  filter: blur(50px);
  pointer-events: none;
}
.tl-counters::before {
  width: 26rem;
  height: 26rem;
  left: -10rem;
  transform: translateY(-50%);
  background: rgba(var(--tl-blue-rgb), .55);
}
.tl-counters::after {
  width: 26rem;
  height: 26rem;
  right: -10rem;
  transform: translateY(-50%);
  background: rgba(var(--tl-orange-rgb), .55);
}
.tl-counters .container {
  position: relative;
  z-index: 1;
  /* Más ancho que el .container normal (1320px): la banda va a sangre y con el
     ancho estándar las cuatro cifras quedaban apretadas en el centro dejando
     mucho fondo vacío a los lados. No es full-bleed — pasado cierto ancho las
     cifras se separarían tanto que dejarían de leerse como un grupo. */
  max-width: 1600px;
}
/* Variante montada: la banda sube y la sección anterior queda por encima, de
   modo que sus tarjetas invaden la franja oscura. Mismo recurso que
   .tl-pillars-section sobre el hero, y el que usa la landing entre el hero y
   los pilares.
   El margen negativo (9rem) es mayor que el hueco que dejaba la sección de
   arriba (~5.3rem), y esa diferencia es justo lo que las tarjetas invaden.
   El padding-top compensa **sólo ese solapamiento**, no el margen entero: así
   las cifras quedan centradas en la franja de banda que sigue siendo visible.
   Compensar los 9rem completos dejaba un hueco enorme sobre las cifras. */
.tl-counters.is-mounted {
  margin-top: -9rem;
  padding-top: calc(clamp(3.5rem, 7vw, 5.5rem) + 3.75rem);
}
@media (max-width: 991.98px) {
  /* Apiladas, las notas son mucho más altas y el hueco de arriba es otro:
     con -9rem el solapamiento se comía la primera cifra. */
  .tl-counters.is-mounted {
    margin-top: -5rem;
    padding-top: calc(clamp(3.5rem, 7vw, 5.5rem) + 1.5rem);
  }
}

/* El z-index va en las notas y no en la sección: elevar la sección entera
   subiría también su fondo claro por encima de la banda y taparía justo la
   franja oscura que queremos ver detrás de las tarjetas. */
.tl-notes {
  position: relative;
  z-index: 2;
}

.tl-counters .tl-stat-number {
  font-size: clamp(2.25rem, 4.5vw, 3.25rem);
}
/* Sin anidar bajo .tl-counters: los mismos modificadores sirven para números
   fuera de la banda oscura. Ojo con `.is-gold` — sobre fondo claro no tiene
   contraste (ver 2.4), úsalo sólo sobre oscuro. */
.tl-stat-number.is-blue { color: var(--tl-blue); }
.tl-stat-number.is-orange { color: var(--tl-orange); }
.tl-stat-number.is-gold { color: var(--tl-orange-light); }
.tl-counters .tl-stat p {
  font-family: var(--tl-font-sub);
  font-weight: 600;
  color: rgba(255, 255, 255, .65);
}

/* -- Hero ----------------------------------------------------------------- */
.tl-hero {
  position: relative;
  overflow: hidden;
  background:
    radial-gradient(60% 60% at 85% 10%, rgba(var(--tl-orange-rgb), .16), transparent 60%),
    radial-gradient(50% 50% at 5% 90%, rgba(var(--tl-blue-rgb), .16), transparent 60%);
}

/* Texto de cuerpo sobre hero o banda oscura. Sustituye a `text-white-50` de
   Bootstrap, que se usaba en los 11 párrafos de este tipo: al 50% se quedaba
   en 2.2:1 sobre el velo del hero, ilegible. No era un ajuste estético.
   Va con !important porque sustituye a una utilidad de Bootstrap y en varios
   sitios convive con otras utilidades de color. */
.tl-text-on-dark {
  color: rgba(255, 255, 255, .85) !important;
}
/* Sobre vídeo el fondo es impredecible y no se puede razonar con un color
   fijo: medido sobre los fotogramas más claros de hero-cta, el 85% se queda
   en 4.1:1 por el lado naranja del velo. Sólo el blanco puro sostiene el
   4.5:1 de AA en toda la banda. Sobre una banda oscura sólida (#1F2124) el
   85% pasa de sobra, y ahí sí conviene para no competir con el titular. */
.tl-hero-video .tl-text-on-dark,
.tl-video-band .tl-text-on-dark {
  color: #fff !important;
}

.tl-hero-badge {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  font-family: var(--tl-font-sub);
  font-weight: 600;
  font-size: .85rem;
  padding: .4rem .9rem;
  border-radius: 50rem;
  background: rgba(var(--tl-blue-rgb), .1);
  color: var(--tl-blue);
}

/* -- Contact card ----------------------------------------------------- */
.tl-contact-card {
  background: var(--tl-surface);
  border: 1px solid var(--tl-border);
  border-radius: 1.25rem;
  box-shadow: var(--tl-shadow);
}

.tl-form-control {
  background: var(--tl-surface-alt);
  border: 1px solid var(--tl-border);
  color: var(--tl-text);
}
.tl-form-control:focus {
  background: var(--tl-surface-alt);
  color: var(--tl-text);
  border-color: var(--tl-blue);
  box-shadow: 0 0 0 .2rem rgba(var(--tl-blue-rgb), .15);
}

/* Etiquetas en DM Sans y un escalón por debajo del cuerpo: varias son preguntas
   completas ("¿Qué modalidad de trabajo se adapta mejor a ti?") y a 1rem se
   partían en dos líneas dentro de media columna, descuadrando la rejilla. */
.form-label {
  font-family: var(--tl-font-sub);
  font-weight: 600;
  font-size: .8125rem;
  line-height: 1.35;
  color: var(--tl-text-muted);
  margin-bottom: .4rem;
}

.invalid-feedback,
.valid-feedback {
  font-family: var(--tl-font-sub);
  font-weight: 600;
  font-size: .775rem;
}

/* Bootstrap pinta el icono de estado con background-image; `.tl-form-control`
   usa la abreviatura `background`, que lo borraría. Se reponen el color de
   fondo y el borde de estado con la especificidad suficiente. */
.was-validated .tl-form-control:invalid,
.was-validated .tl-form-control:valid {
  background-color: var(--tl-surface-alt);
}
.was-validated .tl-form-control:invalid {
  border-color: var(--bs-form-invalid-border-color);
}
/* Sólo se señala el error. Bootstrap marca en verde y con palomita TODOS los
   campos correctos; con ocho campos el formulario queda ruidoso y contradice la
   sobriedad de la marca. El acierto es el estado normal, no una recompensa. */
.was-validated .tl-form-control:valid {
  border-color: var(--tl-border);
  background-image: none;
}
.was-validated .form-check-input:valid {
  border-color: var(--tl-border);
}
.was-validated .form-check-input:valid:checked {
  background-color: var(--tl-blue);
  border-color: var(--tl-blue);
}
.was-validated .form-check-input:valid ~ .form-check-label {
  color: inherit;
}

/* -- Footer -------------------------------------------------------------- */
.tl-footer {
  background: var(--tl-text);
  color: #F5F6F8;
  border-top: 1px solid var(--tl-border);
}
[data-bs-theme="dark"] .tl-footer {
  background: #0E1013;
}

.tl-footer a {
  color: rgba(255,255,255,.75);
  text-decoration: none;
}
.tl-footer a:hover {
  color: var(--tl-orange-light);
}

.tl-footer-contact li {
  display: flex;
  align-items: flex-start;
  gap: .6rem;
  font-size: .875rem;
  line-height: 1.5;
  color: rgba(255, 255, 255, .75);
}
/* Se dimensiona por altura, igual que el logo de la cabecera, para no
   depender de un `width` en el marcado. */
.tl-footer-logo {
  height: 72px;
  width: auto;
  display: block;
}

/* `inherit` toma el color del <li>, que es el mismo del texto: así el icono
   acompaña al dato en vez de competir con el título de la columna, que es el
   único blanco puro de la sección. Si cambia el color del texto, el icono lo
   sigue solo. */
.tl-footer-contact li i {
  color: inherit;
  font-size: .95rem;
  margin-top: .2rem;
  flex-shrink: 0;
}

/* La etiqueta va en su propia línea para que el correo disponga del ancho
   completo de la columna: con "Reclutamiento:" delante no cabía y se partía
   a media dirección. */
.tl-footer-etiqueta {
  display: block;
  font-family: var(--tl-font-sub);
  font-weight: 700;
  font-size: .7rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  /* 55% y no 45%: a 11px esto es texto normal y necesita 4.5:1. Al 45% daba
     4.32 sobre el fondo del footer; al 55% sube a 5.79 y sigue leyéndose como
     etiqueta secundaria frente al blanco puro de los títulos de columna. */
  color: rgba(255, 255, 255, .55);
}

/* Una dirección de correo nunca debe cortarse a media palabra: si no cabe,
   que baje entera. La dirección postal sí puede fluir con normalidad. */
.tl-footer-contact a[href^="mailto:"],
.tl-footer-contact a[href^="tel:"] {
  display: block;
  white-space: nowrap;
}

.tl-social-icon {
  width: 2.25rem;
  height: 2.25rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: rgba(255,255,255,.08);
  color: #fff;
  font-size: 1.05rem;
}
.tl-social-icon:hover {
  background: var(--tl-orange);
  color: #fff;
}

/* -- Cintillo móvil (marquee) -------------------------------------------- */
.tl-marquee-band {
  background: var(--tl-text);
  border-top: 4px solid var(--tl-orange);
  border-bottom: 4px solid var(--tl-orange);
  transform: rotate(-1.5deg);
  overflow: hidden;
}
[data-bs-theme="dark"] .tl-marquee-band {
  background: #0E1013;
}

.tl-marquee-track {
  display: flex;
  width: max-content;
  gap: 2.5rem;
  padding-block: 1rem;
  animation: tl-marquee 28s linear infinite;
}

.tl-marquee-track span {
  font-family: var(--tl-font-heading);
  font-weight: 700;
  font-size: clamp(1.1rem, 2.2vw, 1.6rem);
  text-transform: uppercase;
  letter-spacing: .02em;
  color: #fff;
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  gap: 2.5rem;
}

.tl-marquee-track .tl-marquee-dot {
  font-size: 1.1rem;
}
.tl-marquee-track .tl-marquee-dot.is-gold {
  color: var(--tl-orange-light);
}
.tl-marquee-track .tl-marquee-dot.is-blue {
  color: var(--tl-blue);
}

@keyframes tl-marquee {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}

@media (prefers-reduced-motion: reduce) {
  .tl-marquee-track { animation: none; }
}

/* -- Premios / awards carousel -------------------------------------------- */
.tl-awards-scroller {
  display: flex;
  gap: 1.5rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  padding-block: .5rem 1.5rem;
  scrollbar-width: thin;
  /* Cinco tarjetas de 15rem no llenan el ancho en pantallas ≥1600px y dejaban
     un hueco a la derecha. `safe center` las centra cuando caben y vuelve solo
     al inicio cuando desbordan — con `center` a secas las primeras tarjetas
     quedarían fuera de alcance al hacer scroll. */
  justify-content: safe center;
}

.tl-award-card {
  flex: 0 0 15rem;
  scroll-snap-align: start;
  background: var(--tl-surface);
  border: 1px solid var(--tl-border);
  border-radius: var(--tl-radius);
  box-shadow: none;
  padding: 1.5rem 1rem;
  text-align: center;
  transition: box-shadow .35s ease, border-color .35s ease;
}
.tl-award-card:hover {
  border-color: rgba(var(--tl-orange-rgb), .4);
  box-shadow: 0 1.5rem 3rem rgba(var(--tl-orange-rgb), .25);
}

.tl-award-card .tl-award-img-wrap {
  height: 8rem;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: visible;
  margin-bottom: .75rem;
}

.tl-award-card img {
  height: 6.5rem;
  width: auto;
  display: block;
  transition: transform .4s cubic-bezier(.4,0,.2,1), filter .4s ease;
}
.tl-award-card:hover img {
  transform: scale(1.4);
  filter: drop-shadow(0 1.25rem 1.75rem rgba(0, 0, 0, .3));
}

.tl-award-card .tl-award-year {
  font-family: var(--tl-font-heading);
  font-weight: 800;
  font-size: 1.5rem;
  color: var(--tl-orange);
}

/* -- Certification badges ------------------------------------------------- */
.tl-cert-badge {
  filter: grayscale(1) opacity(.55);
  transition: filter .35s ease, transform .35s ease;
}
.tl-cert-badge:hover {
  filter: grayscale(0) opacity(1);
  transform: translateY(-6px) scale(1.06);
}
/* Los sellos son line-art oscuro: sobre el fondo oscuro del tema se perdían
   casi por completo. Se aclaran para conservar la misma lectura que en claro. */
[data-bs-theme="dark"] .tl-cert-badge {
  filter: grayscale(1) opacity(.5) invert(1) brightness(1.6);
}
[data-bs-theme="dark"] .tl-cert-badge:hover {
  filter: opacity(1) invert(1) brightness(1.6);
}

/* -- Tarjeta de certificación (página Certificaciones) --------------------
   Sello + categoría + norma + descripción. El sello va sobre una placa clara
   de color fijo por el mismo motivo que .tl-solution-icon.is-brand: es
   line-art oscuro y en modo oscuro desaparecería. */
.tl-cert-card {
  position: relative;
  height: 100%;
  display: flex;
  flex-direction: column;
  background: var(--tl-surface);
  border: 1px solid var(--tl-border);
  border-radius: var(--tl-radius);
  overflow: hidden;
  transition: transform .3s ease, box-shadow .3s ease;
}
.tl-cert-card:hover {
  transform: translateY(-6px);
  box-shadow: 0 1.5rem 3rem rgba(var(--tl-blue-rgb), .22);
}

.tl-cert-card-plate {
  background: #F1F3F7;
  padding: 1.75rem 1rem;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 11rem;
}
.tl-cert-card-plate img {
  max-height: 7.5rem;
  max-width: 100%;
  width: auto;
  object-fit: contain;
  transition: transform .35s cubic-bezier(.4, 0, .2, 1);
}
.tl-cert-card:hover .tl-cert-card-plate img {
  transform: scale(1.08);
}

.tl-cert-card-body {
  padding: 1.5rem;
  display: flex;
  flex-direction: column;
  flex: 1;
}
.tl-cert-card-category {
  font-family: var(--tl-font-sub);
  font-weight: 700;
  font-size: .7rem;
  letter-spacing: .15em;
  text-transform: uppercase;
  color: var(--tl-orange-text);
  margin-bottom: .4rem;
}
.tl-cert-card-title {
  font-family: var(--tl-font-heading);
  font-weight: 700;
  font-size: 1.15rem;
  margin-bottom: .5rem;
}
.tl-cert-card-text {
  font-size: .875rem;
  line-height: 1.55;
  color: var(--tl-text-muted);
  margin-bottom: 0;
}

/* Barra inferior en degradado de marca — cierra la tarjeta y repite el
   recurso del botón primario sin añadir un color nuevo. */
.tl-cert-card::after {
  content: "";
  height: 4px;
  background: linear-gradient(90deg, var(--tl-blue), var(--tl-orange));
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .35s ease;
}
.tl-cert-card:hover::after {
  transform: scaleX(1);
}

/* Scroll-reveal (applied via JS: .tl-reveal starts hidden, .is-visible animates in) */
.tl-reveal {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity .6s cubic-bezier(.4,0,.2,1), transform .6s cubic-bezier(.4,0,.2,1);
}
.tl-reveal.is-visible {
  opacity: 1;
  transform: translateY(0);
}
@media (prefers-reduced-motion: reduce) {
  .tl-reveal { opacity: 1; transform: none; transition: none; }
}

/* -- Inner page hero -------------------------------------------------- */
.tl-page-hero {
  background:
    radial-gradient(60% 80% at 90% 0%, rgba(var(--tl-orange-rgb), .14), transparent 60%),
    radial-gradient(50% 60% at 0% 100%, rgba(var(--tl-blue-rgb), .14), transparent 60%);
  /* Más holgado que `.tl-section`, no menos: este hero apila badge, eyebrow,
     título, bajada, dos botones, contacto directo y los numerales. Antes tenía
     88/56 frente a los 96/96 de una sección normal y se sentía apretado. */
  padding-block: clamp(3.5rem, 8vw, 6.5rem) clamp(3rem, 6vw, 5rem);
}

/* Hero interno en oscuro. NO es `.tl-dark-band`: esa aplica un color plano y
   borraba los degradados de marca de `.tl-page-hero`, dejando un rectángulo
   negro sin profundidad. Aquí los degradados se conservan, subidos de opacidad
   para que se lean sobre el fondo oscuro. */
.tl-page-hero.is-dark {
  background:
    radial-gradient(60% 80% at 85% 0%, rgba(var(--tl-orange-rgb), .38), transparent 62%),
    radial-gradient(55% 65% at 5% 100%, rgba(var(--tl-blue-rgb), .34), transparent 62%),
    #1F2124;
}

/* Banda oscura de sección. Sustituye al `style="background: #1F2124;"` que
   estaba repetido en varias vistas; color fijo, como el resto de bloques
   oscuros intencionales.
   Va DESPUÉS de .tl-page-hero a propósito: ambas usan la abreviatura
   `background` con la misma especificidad, así que gana la última declarada. */
.tl-dark-band {
  background: #1F2124;
}

/* Enlace de contacto directo sobre hero oscuro (teléfono, correo). */
.tl-hero-link {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  font-family: var(--tl-font-sub);
  font-weight: 600;
  font-size: .95rem;
  color: rgba(255, 255, 255, .65);
  text-decoration: none;
}
.tl-hero-link:hover {
  color: var(--tl-orange-light);
}
.tl-hero-link i {
  font-size: 1.05rem;
}

/* -- Sticky notes: valores y misión/visión --------------------------------
   Tarjeta tipo nota adhesiva: color plano de marca, cinta de papel en la
   esquina superior y una ligera rotación. El "desorden" es deliberado y
   viene de la maqueta de marca (Cultura Telat_.docx / Misión y visión_.docx):
   es lo que separa esta sección de una rejilla de tarjetas genérica.
   La rotación y el desfase los reparte .tl-notes según la posición, así el
   HTML no carga modificadores de presentación. */
.tl-value-card {
  --tl-note-rot: 0deg;
  --tl-note-shift: 0rem;
  --tl-note-shadow: var(--tl-shadow);
  position: relative;
  border-radius: 1.5rem;
  padding: 2rem;
  height: 100%;
  box-shadow: var(--tl-note-shadow);
  transform: rotate(var(--tl-note-rot)) translateY(var(--tl-note-shift));
  transition: transform .3s cubic-bezier(.4, 0, .2, 1), box-shadow .3s ease;
}
/* Al pasar el mouse la nota se endereza: el gesto es "acomodar el papel". */
.tl-value-card:hover {
  transform: rotate(0deg) translateY(0) scale(1.04);
  box-shadow: 0 1.6rem 3rem rgba(34, 34, 33, .18);
  z-index: 2;
}
[data-bs-theme="dark"] .tl-value-card:hover {
  box-shadow: 0 1.6rem 3rem rgba(0, 0, 0, .45);
}
.tl-value-card .tl-value-title {
  font-family: var(--tl-font-heading);
  font-weight: 700;
  font-size: 1.4rem;
  margin-bottom: .6rem;
}
.tl-value-card p {
  line-height: 1.6;
}

/* Reparto de rotaciones por posición dentro de la rejilla. El patrón se
   repite cada 6 tarjetas, así sirve igual para 2 (misión/visión) que para 6
   (valores) sin tocar el marcado. */
.tl-notes > :nth-child(6n + 1) .tl-value-card { --tl-note-rot: -3deg; }
.tl-notes > :nth-child(6n + 2) .tl-value-card { --tl-note-rot: 2deg;  --tl-note-shift: 1rem; }
.tl-notes > :nth-child(6n + 3) .tl-value-card { --tl-note-rot: -2deg; }
.tl-notes > :nth-child(6n + 4) .tl-value-card { --tl-note-rot: 3deg;  --tl-note-shift: .5rem; }
.tl-notes > :nth-child(6n + 5) .tl-value-card { --tl-note-rot: -1deg; --tl-note-shift: 1.25rem; }
.tl-notes > :nth-child(6n + 6) .tl-value-card { --tl-note-rot: 2deg;  --tl-note-shift: .25rem; }

/* En una sola columna el desfase vertical no aporta y la rotación completa
   se sale del contenedor: se conserva sólo un guiño. */
@media (max-width: 767.98px) {
  .tl-notes .tl-value-card {
    transform: rotate(calc(var(--tl-note-rot) * .5));
  }
}

/* Cinta de papel, esquina superior izquierda */
.tl-value-card::before {
  content: "";
  position: absolute;
  top: -.6rem;
  left: 2rem;
  width: 3.5rem;
  height: 1.25rem;
  background: rgba(255, 255, 255, .25);
  border: 1px solid rgba(255, 255, 255, .3);
  border-radius: .25rem;
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  transform: rotate(-4deg);
  pointer-events: none;
}
.tl-value-card.is-dark::before {
  background: rgba(254, 202, 102, .3);
  border-color: rgba(254, 202, 102, .2);
}
.tl-value-card.is-surface::before {
  background: rgba(var(--tl-blue-rgb), .12);
  border-color: rgba(var(--tl-blue-rgb), .2);
}
.tl-value-card.is-surface-warm::before {
  background: rgba(var(--tl-orange-rgb), .12);
  border-color: rgba(var(--tl-orange-rgb), .2);
}

/* Acento decorativo suelto (chispa, punto) sobre el borde de la nota */
.tl-note-accent {
  position: absolute;
  top: -.75rem;
  right: 1.5rem;
  font-size: 1.75rem;
  line-height: 1;
  pointer-events: none;
  transition: transform .3s ease;
}
.tl-note-accent.is-dot {
  font-size: .85rem;
  top: -.4rem;
}
.tl-note-accent.is-blue { color: var(--tl-blue); }
.tl-note-accent.is-orange { color: var(--tl-orange); }
.tl-value-card:hover .tl-note-accent {
  transform: scale(1.25) rotate(10deg);
}

/* Dashed decorative circle — brand "resources" doodle */
.tl-doodle-circle {
  position: absolute;
  width: 12rem;
  height: 12rem;
  border: 2px dashed rgba(var(--tl-blue-rgb), .35);
  border-radius: 50%;
  pointer-events: none;
}
.tl-doodle-circle.is-orange {
  border-color: rgba(var(--tl-orange-rgb), .3);
}
.tl-doodle-circle.is-top-start { top: 4rem; left: -4rem; }
.tl-doodle-circle.is-top-end { top: 3rem; right: -3rem; }
.tl-doodle-circle.is-spinning {
  animation: tl-spin-slow 22s linear infinite;
}
@keyframes tl-spin-slow {
  to { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
  .tl-doodle-circle.is-spinning { animation: none; }
}

/* Brand-chip cards: fixed palette, deliberately NOT theme-reactive so
   contrast holds the same in light and dark mode. */
.tl-value-card.is-dark {
  background: #1F2124;
  color: #F5F6F8;
  --tl-note-shadow: 0 .9rem 2.2rem rgba(34, 34, 33, .3);
}
.tl-value-card.is-blue {
  background: var(--tl-blue-chip);
  color: #fff;
  --tl-note-shadow: 0 .9rem 2.2rem rgba(var(--tl-blue-rgb), .3);
}
.tl-value-card.is-orange {
  background: var(--tl-orange-chip);
  color: #fff;
  --tl-note-shadow: 0 .9rem 2.2rem rgba(var(--tl-orange-rgb), .3);
}
.tl-value-card.is-gold {
  background: var(--tl-gold-chip);
  color: #222221;
  --tl-note-shadow: 0 .9rem 2.2rem rgba(254, 202, 102, .35);
}
/* Resplandor de marca para una nota oscura grande que sólo lleva texto: sin él
   se lee como un rectángulo plano. Es el mismo recurso de .tl-counters, pero
   contenido dentro de la tarjeta — no se puede usar `overflow:hidden` aquí
   porque recortaría la cinta de papel, que va por fuera del borde. Debe ir
   DESPUÉS de las variantes de color: éstas usan la abreviatura `background`,
   que borraría este background-image. */
.tl-value-card.has-glow {
  background-image:
    radial-gradient(45% 55% at 100% 0%, rgba(var(--tl-orange-rgb), .2), transparent 70%),
    radial-gradient(45% 55% at 0% 100%, rgba(var(--tl-blue-rgb), .18), transparent 70%);
}
/* Sombra dorada en hover. Se cuelga de .has-glow y no de .is-dark a propósito:
   `is-dark` lo comparte la nota de Liderazgo en Cultura Telat, que debe seguir
   con la sombra neutra del resto de notas. El dorado es el acento correcto
   sobre oscuro (2.4). Repetida bajo el tema oscuro para ganarle a la regla
   genérica de `.tl-value-card:hover`, que allí pinta negro. */
.tl-value-card.has-glow:hover,
[data-bs-theme="dark"] .tl-value-card.has-glow:hover {
  box-shadow: 0 1.6rem 3rem rgba(var(--tl-orange-light-rgb), .35);
}

.tl-value-card.is-surface,
.tl-value-card.is-surface-warm {
  background: var(--tl-surface);
  color: var(--tl-text);
  border: 2px solid rgba(var(--tl-blue-rgb), .2);
  --tl-note-shadow: 0 .9rem 2.2rem rgba(var(--tl-blue-rgb), .12);
}
.tl-value-card.is-surface-warm {
  border-color: rgba(var(--tl-orange-rgb), .2);
  --tl-note-shadow: 0 .9rem 2.2rem rgba(var(--tl-orange-rgb), .12);
}

/* El cuerpo hereda el contraste de su chip: evita depender de utilidades de
   opacidad de Bootstrap, que sólo existen en pasos de 25. */
.tl-value-card.is-dark p:not(.tl-value-title) {
  color: rgba(255, 255, 255, .9);
}
/* Sobre los chips de color el cuerpo va en blanco puro, no al 90%: ese 10% de
   fondo mezclado bajaba el texto de 16px a 4.38:1 sobre el naranja, justo por
   debajo de AA. Sobre `.is-dark` no hace falta — ahí el 90% sobra de largo. */
.tl-value-card.is-blue p:not(.tl-value-title),
.tl-value-card.is-orange p:not(.tl-value-title) {
  color: #fff;
}
.tl-value-card.is-gold p:not(.tl-value-title) {
  color: rgba(34, 34, 33, .8);
}
.tl-value-card.is-surface p:not(.tl-value-title),
.tl-value-card.is-surface-warm p:not(.tl-value-title) {
  color: var(--tl-text-muted);
}

/* -- Floating stat badge (overlaps a photo's corner) ----------------------- */
.tl-floating-badge {
  position: absolute;
  left: 1rem;
  right: 1rem;
  bottom: 1rem;
  display: flex;
  align-items: center;
  gap: 1rem;
  background: var(--tl-surface);
  border: 1px solid var(--tl-border);
  border-radius: 1.25rem;
  padding: 1.1rem 1.35rem;
  box-shadow: var(--tl-shadow);
}
@media (min-width: 992px) {
  .tl-floating-badge {
    left: -1.75rem;
    right: auto;
    bottom: -1.75rem;
    max-width: 16rem;
  }
}
.tl-floating-badge .tl-floating-badge-number {
  font-family: var(--tl-font-heading);
  font-weight: 800;
  font-size: 2.25rem;
  line-height: 1;
  color: var(--tl-orange);
  flex-shrink: 0;
}
.tl-floating-badge p {
  font-family: var(--tl-font-sub);
  font-weight: 600;
  font-size: .8rem;
  line-height: 1.3;
  color: var(--tl-text-muted);
  margin: 0;
}

/* -- Misión / Visión timeline -----------------------------------------------
   Two connected stops on a thin vertical line instead of color-block cards
   — the brand colors show up only as a marker ring and a line gradient,
   not as full fills. Full container width, staggered left/right of a
   central line, so it carries the same visual weight as the sections
   around it instead of reading as a narrow, centered afterthought. */
.tl-timeline {
  position: relative;
}
.tl-timeline::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 1.5rem;
  bottom: 1.5rem;
  width: 2px;
  transform: translateX(-50%);
  background: linear-gradient(to bottom, var(--tl-blue), var(--tl-orange));
  opacity: .3;
}
.tl-timeline-row {
  position: relative;
  margin-bottom: 3.5rem;
}
.tl-timeline-row:last-child {
  margin-bottom: 0;
}
.tl-timeline-marker {
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 50%;
  background: var(--tl-surface);
  border: 2px solid var(--tl-border);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.15rem;
  box-shadow: var(--tl-shadow);
  flex-shrink: 0;
  position: relative;
  z-index: 1;
}
.tl-timeline-marker.is-blue { border-color: var(--tl-blue); color: var(--tl-blue); }
.tl-timeline-marker.is-orange { border-color: var(--tl-orange); color: var(--tl-orange); }

.tl-timeline-label {
  font-family: var(--tl-font-heading);
  font-weight: 700;
  font-size: 1.4rem;
  margin-bottom: .6rem;
}

/* -- Map (sedes) --------------------------------------------------------- */
.tl-map-wrap {
  background: var(--tl-text);
  border-radius: var(--tl-radius);
  overflow: hidden;
}
[data-bs-theme="dark"] .tl-map-wrap { background: #0E1013; }

.tl-map-canvas {
  width: 100%;
  height: 26rem;
}

.tl-location-btn {
  width: 100%;
  text-align: left;
  background: rgba(255,255,255,.05);
  border: 1px solid rgba(255,255,255,.1);
  border-radius: 1.25rem;
  padding: 1.1rem 1.25rem;
  color: #fff;
  transition: background .2s ease, border-color .2s ease;
}
.tl-location-btn:hover,
.tl-location-btn.active {
  background: rgba(255,255,255,.1);
  border-color: var(--tl-orange-light);
}
/* Sin anidar bajo .tl-location-btn a propósito: el popup del mapa reutiliza
   estas mismas clases, y su marcado lo genera MapLibre fuera del botón. */
.tl-location-tag {
  font-family: var(--tl-font-sub);
  font-size: .7rem;
  font-weight: 700;
  letter-spacing: .15em;
  text-transform: uppercase;
  color: var(--tl-orange-light);
}
.tl-location-name {
  font-family: var(--tl-font-heading);
  font-weight: 700;
  font-size: 1.15rem;
  color: #fff;
}
.tl-location-addr {
  color: rgba(255,255,255,.6);
  font-size: .85rem;
}

/* Marcador: punto de color con aro blanco y halo del mismo color (el color y
   el halo los aplica el JS, uno por sede). */
.tl-map-marker {
  width: 1.5rem;
  height: 1.5rem;
  border-radius: 50%;
  border: 4px solid #fff;
  cursor: pointer;
}

/* Fondo fijo, no `--tl-text`: en modo oscuro ese token es casi blanco y el
   popup quedaba con texto blanco sobre fondo claro. */
.maplibregl-popup-content {
  background: #222221 !important;
  color: #fff !important;
  border: 1px solid rgba(255, 255, 255, .08) !important;
  border-radius: 1rem !important;
  padding: 1.1rem 1.25rem !important;
  font-family: var(--tl-font-body);
  box-shadow: 0 1rem 2rem rgba(0, 0, 0, .35) !important;
}
.maplibregl-popup-tip { border-top-color: #222221 !important; }
.maplibregl-popup-content a {
  color: var(--tl-orange-light);
  font-family: var(--tl-font-sub);
  font-weight: 700;
  font-size: .85rem;
  text-decoration: none;
}
.maplibregl-popup-content a:hover { text-decoration: underline; }

/* -- FAQ accordion ---------------------------------------------------- */
.tl-accordion .accordion-item {
  background: var(--tl-surface);
  border: 1px solid var(--tl-border);
  border-radius: var(--tl-radius) !important;
  overflow: hidden;
  margin-bottom: 1rem;
}
.tl-accordion .accordion-button {
  background: var(--tl-surface);
  color: var(--tl-text);
  font-family: var(--tl-font-heading);
  font-weight: 700;
  box-shadow: none !important;
}
.tl-accordion .accordion-button:not(.collapsed) {
  color: var(--tl-blue-text);
  background: var(--tl-surface);
}
.tl-accordion .accordion-button::after {
  filter: none;
}
[data-bs-theme="dark"] .tl-accordion .accordion-button::after {
  filter: invert(1);
}
.tl-accordion .accordion-body {
  color: var(--tl-text-muted);
  font-family: var(--tl-font-body);
}

/* -- Hollow numbers (referral steps) --------------------------------------- */
.tl-hollow-number {
  font-family: var(--tl-font-heading);
  font-size: clamp(3.5rem, 9vw, 6rem);
  line-height: .85;
  color: transparent;
  -webkit-text-stroke: 3px var(--tl-orange);
  text-stroke: 3px var(--tl-orange);
}

/* -- Solution cards (colored top border, hover tooltip) -------------------- */
.tl-solution-card {
  position: relative;
  background: var(--tl-surface);
  border: 1px solid var(--tl-border);
  border-top: 3px solid transparent;
  border-radius: var(--tl-radius);
  padding: 2rem;
  height: 100%;
  display: flex;
  flex-direction: column;
  transition: transform .3s ease, box-shadow .3s ease;
}
.tl-solution-card:hover {
  transform: translateY(-6px);
}
.tl-solution-card.is-blue { border-top-color: var(--tl-blue); }
.tl-solution-card.is-orange { border-top-color: var(--tl-orange); }
.tl-solution-card.is-gold { border-top-color: var(--tl-orange-light); }
.tl-solution-card.is-blue:hover { box-shadow: 0 1.5rem 3rem rgba(var(--tl-blue-rgb), .25); }
.tl-solution-card.is-orange:hover { box-shadow: 0 1.5rem 3rem rgba(var(--tl-orange-rgb), .25); }
.tl-solution-card.is-gold:hover { box-shadow: 0 1.5rem 3rem rgba(254, 202, 102, .3); }

.tl-solution-icon {
  width: 3.25rem;
  height: 3.25rem;
  border-radius: .85rem;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.4rem;
  margin-bottom: 1.25rem;
  /* Placa translúcida, no color sólido: el tinte queda claro y el glifo lleva
     el color fuerte. El borde del mismo color a más alpha es lo que da el
     canto de "cristal" — sin él la placa se deshace sobre superficies claras.
     El backdrop-filter sólo se nota cuando hay algo detrás (hero, banda de
     video); sobre una tarjeta opaca es inocuo. */
  border: 1px solid transparent;
  backdrop-filter: blur(8px);
  transition: transform .3s ease, background-color .3s ease;
}
.tl-solution-card:hover .tl-solution-icon {
  transform: scale(1.08) rotate(-4deg);
}
.tl-solution-icon.is-blue {
  background: rgba(var(--tl-blue-rgb), .14);
  border-color: rgba(var(--tl-blue-rgb), .45);
  color: var(--tl-blue);
}
.tl-solution-icon.is-orange {
  background: rgba(var(--tl-orange-rgb), .14);
  border-color: rgba(var(--tl-orange-rgb), .45);
  color: var(--tl-orange);
}
/* El glifo NO va en dorado: sobre placa clara el dorado no tiene contraste
   (regla 2.4, "dorado sólo sobre oscuro"). Va en --tl-text, que se resuelve
   oscuro en claro y claro en oscuro, así la variante funciona en ambos temas
   sin dejar de distinguirse por el tinte de la placa. */
.tl-solution-icon.is-gold {
  background: rgba(var(--tl-orange-light-rgb), .20);
  border-color: rgba(var(--tl-orange-light-rgb), .55);
  color: var(--tl-text);
}

/* Variante para la iconografía oficial de marca (codigos_de_referencia/ÍCONOS).
   Son PNG de trazo negro con un acento de color, así que NO pueden ir sobre un
   fondo sólido de marca como los de fuente: necesitan una placa clara. La placa
   es de color fijo, no reactiva al tema — en modo oscuro el trazo negro
   desaparecería. Mismo criterio que los logos de cliente. */
.tl-solution-icon.is-brand {
  width: 4rem;
  height: 4rem;
  background: #F1F3F7;
  padding: .5rem;
  border: 1px solid rgba(34, 34, 33, .06);
}
.tl-solution-icon.is-brand img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}

/* Lista de beneficios (Servicios). El Home muestra un solo beneficio por
   solución con .tl-solution-benefit; aquí se desarrollan los tres. */
.tl-solution-benefits {
  margin-top: auto;
  padding-top: 1rem;
  border-top: 1px solid var(--tl-border);
  list-style: none;
  padding-left: 0;
  margin-bottom: 0;
  display: grid;
  gap: .45rem;
}
.tl-solution-benefits li {
  display: flex;
  align-items: flex-start;
  gap: .45rem;
  font-family: var(--tl-font-sub);
  font-weight: 600;
  font-size: .8rem;
  line-height: 1.4;
}
.tl-solution-benefits li i {
  flex-shrink: 0;
  margin-top: .1rem;
  color: var(--tl-orange);
}
.tl-solution-card.is-orange .tl-solution-benefits li i { color: var(--tl-blue); }

.tl-solution-title {
  font-family: var(--tl-font-heading);
  font-weight: 700;
  font-size: 1.15rem;
  margin-bottom: .75rem;
  position: relative;
  padding-top: .6rem;
}
.tl-solution-title::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 2.25rem;
  height: 3px;
  background: var(--tl-orange-light);
}

.tl-solution-benefit {
  margin-top: auto;
  padding-top: 1rem;
  border-top: 1px solid var(--tl-border);
  font-weight: 700;
  font-size: .875rem;
}

.tl-solution-tooltip {
  position: absolute;
  left: 50%;
  bottom: 100%;
  transform: translate(-50%, 8px);
  background: var(--tl-text);
  color: var(--tl-bg);
  padding: .5rem 1rem;
  border-radius: .5rem;
  font-family: var(--tl-font-sub);
  font-weight: 700;
  font-size: .8rem;
  text-align: center;
  width: max-content;
  max-width: 15rem;
  opacity: 0;
  visibility: hidden;
  transition: opacity .25s ease, transform .25s ease;
  pointer-events: none;
  z-index: 5;
  margin-bottom: .6rem;
  box-shadow: 0 .75rem 1.5rem rgba(0, 0, 0, .25);
}
.tl-solution-tooltip::after {
  content: "";
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  border: 6px solid transparent;
  border-top-color: var(--tl-text);
}
.tl-solution-card:hover .tl-solution-tooltip {
  opacity: 1;
  visibility: visible;
  transform: translate(-50%, -6px);
}
[data-bs-theme="dark"] .tl-solution-tooltip { background: #0E1013; color: #fff; }
[data-bs-theme="dark"] .tl-solution-tooltip::after { border-top-color: #0E1013; }

/* El hero que lleva pilares montados encima necesita más aire abajo: los
   íconos suben 3.75rem y se comían la separación del CTA, que quedaba en 58px
   frente a los 94px que hay entre el borde superior del hero y el badge. Con
   esto las dos distancias quedan iguales y el hero se lee simétrico.
   Se compensa alargando el hero, no reduciendo el margen negativo de los
   pilares: eso último recortaría el solapamiento, que es el efecto buscado.
   El `:has()` evita añadir una clase suelta en la vista y ata el ajuste a la
   única condición que lo justifica — que haya pilares montados detrás.
   Va en la <section> y no en su .container porque el container lleva la
   utilidad `py-4` de Bootstrap, que es `!important` y gana siempre.
   Sólo en ≥992px: en móvil los pilares se apilan y el hero ya quedaba
   equilibrado (44px abajo contra 56 arriba); añadir el margen ahí lo dejaba
   descompensado al revés, con 80px abajo. */
@media (min-width: 992px) {
  .tl-hero-video:has(+ .tl-pillars-section) {
    padding-bottom: 2.25rem;
  }
}

/* -- Industry picker (selector + panel) -----------------------------------
   No es una tarjeta ni una variación de tarjeta: es un selector — lista de
   nombres a la izquierda, un único panel de detalle a la derecha que
   cambia con JS. Sólo un bloque de contenido visible a la vez, en vez de
   N cajas repetidas; el peso visual es asimétrico (lista ligera / panel
   grande), justo lo que no logran ni la tarjeta con ícono ni el póster de
   color. Reutiliza `.tl-solution-icon` para el glifo del panel — ya es
   translúcido y reactivo al tema, no hacía falta un ícono nuevo. */
.tl-industry-picker {
  display: flex;
  flex-direction: column;
  gap: .25rem;
}
.tl-industry-option {
  display: flex;
  align-items: center;
  gap: 1rem;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  border-left: 3px solid transparent;
  border-radius: 0 var(--tl-radius-sm) var(--tl-radius-sm) 0;
  padding: .9rem 1rem;
  font-family: var(--tl-font-sub);
  font-weight: 600;
  font-size: 1rem;
  color: var(--tl-text-muted);
  cursor: pointer;
  transition: color .25s ease, border-color .25s ease, background-color .25s ease;
}
.tl-industry-option:hover {
  color: var(--tl-text);
  background: var(--tl-surface-alt);
}
.tl-industry-option.active {
  color: var(--tl-text);
  font-weight: 700;
  background: var(--tl-surface-alt);
}
.tl-industry-option.is-blue.active { border-left-color: var(--tl-blue); }
.tl-industry-option.is-orange.active { border-left-color: var(--tl-orange); }
.tl-industry-option.is-gold.active { border-left-color: var(--tl-orange-light); }
/* Número en trazo hueco, misma técnica que .tl-hollow-number: transparente
   con sólo el contorno. En reposo el contorno es neutro (--tl-border); la
   fila activa lo tiñe del color de esa industria — es el mismo lenguaje del
   primer boceto de esta sección, aquí a escala de lista en vez de fila
   suelta. Decorativo (es un índice, no el nombre), por eso sin requisito de
   contraste de texto. */
.tl-industry-option-num {
  flex: 0 0 auto;
  width: 2.25rem;
  font-family: var(--tl-font-heading);
  font-weight: 800;
  font-size: 1.4rem;
  line-height: 1;
  color: transparent;
  /* --tl-border (10% de opacidad) se perdía casi por completo en reposo.
     --tl-text es el neutro fuerte de la paleta — casi negro en claro, casi
     blanco en oscuro — y se sigue sobreescribiendo al color de marca en la
     fila activa. */
  -webkit-text-stroke: 1.5px var(--tl-text);
  text-stroke: 1.5px var(--tl-text);
  transition: -webkit-text-stroke-color .25s ease;
}
.tl-industry-option.is-blue.active .tl-industry-option-num { -webkit-text-stroke-color: var(--tl-blue); text-stroke-color: var(--tl-blue); }
.tl-industry-option.is-orange.active .tl-industry-option-num { -webkit-text-stroke-color: var(--tl-orange); text-stroke-color: var(--tl-orange); }
.tl-industry-option.is-gold.active .tl-industry-option-num { -webkit-text-stroke-color: var(--tl-orange-light); text-stroke-color: var(--tl-orange-light); }
.tl-industry-option-label {
  flex: 1 1 auto;
}
/* Comportamiento de acordeón, pero el contenido "abre" hacia el panel de
   al lado y no hacia abajo: la fila no crece, sólo cambia el estado activo
   y el chevrón apunta hacia donde está la respuesta, igual que el acordeón
   de FAQ apunta hacia abajo con su propio contenido. */
.tl-industry-option-chevron {
  flex: 0 0 auto;
  font-size: .9rem;
  color: var(--tl-border);
  transition: color .25s ease, transform .25s ease;
}
.tl-industry-option:hover .tl-industry-option-chevron {
  transform: translateX(2px);
}
.tl-industry-option.is-blue.active .tl-industry-option-chevron { color: var(--tl-blue); }
.tl-industry-option.is-orange.active .tl-industry-option-chevron { color: var(--tl-orange); }
.tl-industry-option.is-gold.active .tl-industry-option-chevron { color: var(--tl-orange-light); }

.tl-industry-panel {
  background: var(--tl-surface);
  border: 1px solid var(--tl-border);
  border-top: 3px solid transparent;
  border-radius: var(--tl-radius);
  padding: clamp(1.75rem, 4vw, 2.75rem);
  height: 100%;
  transition: border-color .3s ease;
}
.tl-industry-panel.is-blue { border-top-color: var(--tl-blue); }
.tl-industry-panel.is-orange { border-top-color: var(--tl-orange); }
.tl-industry-panel.is-gold { border-top-color: var(--tl-orange-light); }
.tl-industry-panel-label {
  font-family: var(--tl-font-sub);
  font-weight: 700;
  font-size: .8rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--tl-text-muted);
  margin-bottom: 1rem;
}
.tl-industry-panel-name {
  font-family: var(--tl-font-heading);
  font-weight: 700;
  font-size: clamp(1.5rem, 3vw, 2rem);
  margin-bottom: .75rem;
}
.tl-industry-panel-service {
  font-size: 1.05rem;
  color: var(--tl-text-muted);
  margin-bottom: 0;
}

/* -- Pilares (circular icons straddling the hero's bottom edge) ----------- */
.tl-pillars-section {
  position: relative;
  z-index: 3;
  /* Pull the row up so the icons overlap the hero: half over the video,
     half over this section's own background. */
  margin-top: -3.75rem;
}

.tl-pillars-icon {
  width: 7.5rem;
  height: 7.5rem;
  border-radius: 50%;
  background: var(--tl-surface);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 2.25rem;
  color: var(--tl-blue);
  box-shadow: var(--tl-shadow);
  margin: 0 auto 1.5rem;
  position: relative;
  border: 4px solid var(--tl-bg);
  transition: background-color .25s ease, color .25s ease, transform .25s ease, box-shadow .25s ease;
}

.col-md-4:hover .tl-pillars-icon {
  background: linear-gradient(135deg, var(--tl-blue), var(--tl-orange));
  color: #fff;
  transform: translateY(-6px) scale(1.05);
  box-shadow: 0 1.25rem 2.5rem rgba(var(--tl-orange-rgb), .35);
}

.tl-pillars-title {
  font-family: var(--tl-font-heading);
  font-weight: 800;
  letter-spacing: .03em;
  text-transform: uppercase;
  text-align: center;
  margin-bottom: .75rem;
  font-size: 1.05rem;
}

/* -- Video hero (home) ---------------------------------------------------- */
.tl-hero-video {
  position: relative;
  z-index: 1;
  overflow: hidden;
  min-height: 30rem;
  display: flex;
  align-items: center;
  background: #1F2124;
}
.tl-hero-video-bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
}
/* El gradiente de marca solo, por opaco que fuera, no daba contraste: es color
   saturado, no oscuridad, y sobre los fotogramas quemados del vídeo (medidos:
   picos de luminancia en 255) el texto blanco se perdía. Con el .75 anterior el
   lead se quedaba en 2.2:1 — muy por debajo del 4.5:1 de WCAG AA.
   La solución es la misma que ya usaba .tl-video-band-overlay: bajar el
   gradiente y meter una base oscura debajo, que aplana los picos de luz sin
   apagar el color de marca.
   La base está en .72 y no menos porque los vídeos no son igual de oscuros:
   hero-cta (Home y Quiénes somos) aguantaba con .65, pero hero-servicios,
   hero-certificaciones y hero-carreras son más brillantes y se quedaban en
   4.2:1. Con .72 el peor fotograma de las cinco páginas da 4.61:1.
   Si algún día se cambia un vídeo de hero, hay que volver a medir. */
.tl-hero-video-overlay {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(135deg, rgba(var(--tl-blue-rgb), .60), rgba(var(--tl-orange-rgb), .60)),
    rgba(34, 34, 33, .72);
  z-index: 1;
}
.tl-hero-video .container {
  z-index: 2;
}
/* Sobre cualquier hero oscuro —con video o no— el azul de marca del badge
   pierde contraste: se pasa a blanco translúcido. */
.tl-hero-video .tl-hero-badge,
.tl-page-hero.is-dark .tl-hero-badge {
  background: rgba(255, 255, 255, .15);
  color: #fff;
}

/* -- Numerales al pie de un hero oscuro (Contacto) ------------------------
   Van dentro del propio hero, separados por una línea, en vez de una banda
   de contadores aparte: así la página tiene un solo bloque oscuro. */
.tl-hero-stats {
  margin-top: 3.5rem;
  padding-top: 2.75rem;
  border-top: 1px solid rgba(255, 255, 255, .14);
}
.tl-hero-stats .tl-stat-number {
  font-size: clamp(1.6rem, 2.6vw, 2.1rem);
  line-height: 1.1;
}
.tl-hero-stats p {
  font-family: var(--tl-font-sub);
  font-weight: 600;
  font-size: .8rem;
  line-height: 1.35;
  color: rgba(255, 255, 255, .6);
  margin-bottom: 0;
}

/* -- Banda de video divisoria ---------------------------------------------
   Franja full-bleed que corta el flujo entre dos secciones. Más baja que un
   hero y con el texto centrado: no compite con el hero de la página, sólo da
   respiro y aporta prueba visual.
   El velo es más oscuro que el del hero (gradiente de marca al 55% sobre una
   base oscura, no al 75% a secas): el metraje es cálido y movido, y con el
   velo del hero el texto centrado no se leía. */
.tl-video-band {
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  min-height: 24rem;
  padding-block: clamp(3rem, 6vw, 5rem);
  background: #1F2124;
}
.tl-video-band-overlay {
  position: absolute;
  inset: 0;
  z-index: 1;
  background:
    linear-gradient(135deg, rgba(var(--tl-blue-rgb), .55), rgba(var(--tl-orange-rgb), .55)),
    rgba(34, 34, 33, .5);
}
.tl-video-band .container {
  position: relative;
  z-index: 2;
}

/* -- Hero del blog ---------------------------------------------------------
   El fondo es un mosaico con las fotos de los propios artículos: da peso al
   único hero del sitio sin video y dice "blog" sin recurrir a decoración
   inventada. Van en escala de grises y muy bajas de opacidad para que el
   titular mande. */
.tl-blog-hero {
  position: relative;
  overflow: hidden;
  background: #1F2124;
  padding-block: clamp(3.5rem, 8vw, 6rem);
}
.tl-blog-hero-mosaico {
  position: absolute;
  inset: 0;
  display: flex;
  z-index: 0;
}
.tl-blog-hero-mosaico img {
  flex: 1 1 0;
  min-width: 0;
  height: 100%;
  object-fit: cover;
  filter: grayscale(1);
  opacity: .28;
}
/* A partir de 4 imágenes el mosaico se vuelve ruido en pantallas estrechas. */
@media (max-width: 767.98px) {
  .tl-blog-hero-mosaico img:nth-child(n + 4) { display: none; }
}
.tl-blog-hero-velo {
  position: absolute;
  inset: 0;
  z-index: 1;
  background:
    radial-gradient(60% 80% at 85% 0%, rgba(var(--tl-orange-rgb), .3), transparent 62%),
    radial-gradient(55% 65% at 5% 100%, rgba(var(--tl-blue-rgb), .28), transparent 62%),
    linear-gradient(180deg, rgba(31, 33, 36, .82), rgba(31, 33, 36, .92));
}
.tl-blog-hero .container {
  position: relative;
  z-index: 2;
}

/* -- Blog ------------------------------------------------------------------
   Tarjeta de artículo: imagen con proporción fija arriba, categoría y título
   abajo. El alto lo iguala el grid, así que los títulos de distinto largo no
   descuadran la rejilla. */
.tl-post-card {
  position: relative;
  height: 100%;
  display: flex;
  flex-direction: column;
  background: var(--tl-surface);
  border: 1px solid var(--tl-border);
  border-radius: var(--tl-radius);
  overflow: hidden;
  transition: transform .3s ease, box-shadow .3s ease;
}
.tl-post-card:hover {
  transform: translateY(-6px);
  box-shadow: 0 1.5rem 3rem rgba(var(--tl-blue-rgb), .2);
}

.tl-post-card-img {
  position: relative;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  background: var(--tl-surface-alt);
}
.tl-post-card-img img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform .5s cubic-bezier(.4, 0, .2, 1);
}
.tl-post-card:hover .tl-post-card-img img {
  transform: scale(1.06);
}

.tl-post-card-body {
  padding: 1.5rem;
  display: flex;
  flex-direction: column;
  flex: 1;
  gap: .75rem;
}

/* Chip de categoría. El color distingue las dos secciones del blog. */
.tl-post-cat {
  align-self: flex-start;
  font-family: var(--tl-font-sub);
  font-weight: 700;
  font-size: .7rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  padding: .3rem .7rem;
  border-radius: 50rem;
}
.tl-post-cat.is-news {
  color: var(--tl-blue-text);
  background: rgba(var(--tl-blue-rgb), .12);
}
.tl-post-cat.is-together {
  color: var(--tl-orange-text);
  background: rgba(var(--tl-orange-rgb), .12);
}

.tl-post-title {
  font-family: var(--tl-font-heading);
  font-weight: 700;
  font-size: 1.05rem;
  line-height: 1.35;
  margin-bottom: 0;
}
.tl-post-title a {
  color: var(--tl-text);
  text-decoration: none;
}
.tl-post-card:hover .tl-post-title a {
  color: var(--tl-blue);
}

/* Extracto: primer párrafo del artículo. En la rejilla se recorta a 3 líneas
   para que las tarjetas conserven la misma altura. */
.tl-post-extracto {
  font-size: .875rem;
  line-height: 1.55;
  color: var(--tl-text-muted);
  margin-bottom: 0;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* El enlace "Leer artículo" se estira sobre toda la tarjeta: así el área
   clicable es la tarjeta entera, no sólo el título. */
.tl-post-link {
  margin-top: auto;
  font-family: var(--tl-font-sub);
  font-weight: 700;
  font-size: .85rem;
  color: var(--tl-orange-text);
  text-decoration: none;
}
.tl-post-link::after {
  content: "";
  position: absolute;
  inset: 0;
}

/* Distintivo del artículo destacado, sobre la imagen. Sin él la tarjeta grande
   sólo se leía como "una tarjeta más pero más grande". */
.tl-post-destacado {
  position: absolute;
  top: 1rem;
  left: 1rem;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  font-family: var(--tl-font-sub);
  font-weight: 700;
  font-size: .72rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  padding: .4rem .85rem;
  border-radius: 50rem;
  /* Tinta fija, no `var(--tl-text)`: el dorado no cambia con el tema pero el
     token de texto sí, y en oscuro la etiqueta quedaba en casi blanco sobre
     dorado — 1.38:1, ilegible. Mismo par que `.tl-value-card.is-gold`. */
  color: #222221;
  background: var(--tl-gold-chip);
}

/* En el destacado el enlace cubre la tarjeta desde un <a> propio, porque el
   botón visible no debe ser el que se estira. */
.tl-post-link-cover {
  position: absolute;
  inset: 0;
}

/* Artículo destacado: misma tarjeta en horizontal. */
@media (min-width: 992px) {
  .tl-post-card.is-featured {
    flex-direction: row;
  }
  /* Proporción explícita, no `auto`: sin ella la imagen se renderiza a tamaño
     natural y estira la tarjeta a más de 1000px de alto. */
  .tl-post-card.is-featured .tl-post-card-img {
    flex: 0 0 55%;
    aspect-ratio: 16 / 10;
  }
  .tl-post-card.is-featured .tl-post-card-body {
    padding: 2.5rem 3rem;
    justify-content: center;
    gap: 1rem;
  }
  .tl-post-card.is-featured .tl-post-title {
    font-size: 1.75rem;
  }
  /* El extracto del destacado tiene sitio de sobra: no se recorta a 3 líneas. */
  .tl-post-card.is-featured .tl-post-extracto {
    font-size: 1rem;
    -webkit-line-clamp: 5;
  }
}

/* Filtros de categoría */
.tl-filter-tabs {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: .5rem;
}
.tl-filter-tab {
  font-family: var(--tl-font-sub);
  font-weight: 600;
  font-size: .875rem;
  padding: .5rem 1.25rem;
  border: 1px solid var(--tl-border);
  border-radius: 50rem;
  background: transparent;
  color: var(--tl-text-muted);
  transition: border-color .2s ease, color .2s ease, background .2s ease;
}
.tl-filter-tab:hover {
  border-color: var(--tl-blue);
  color: var(--tl-blue);
}
/* Chip relleno con texto blanco encima: mismo caso que `.tl-value-card.is-blue`,
   así que usa el mismo fondo fijo. Con `var(--tl-blue)` daba 4.00:1 en claro y
   2.56:1 en oscuro. */
.tl-filter-tab.active {
  background: var(--tl-blue-chip);
  border-color: var(--tl-blue-chip);
  color: #fff;
}

/* -- Botón flotante de WhatsApp -------------------------------------------
   Equivalente al Joinchat de la landing, resuelto con nuestros propios
   estilos en vez de traer el plugin. Aparece con retraso para no competir
   con el hero y usa la foto de Perro, la mascota. */
.tl-wa-fab {
  position: fixed;
  right: 1.25rem;
  bottom: 1.25rem;
  z-index: 1040;
  display: flex;
  align-items: center;
  gap: .65rem;
  text-decoration: none;
  /* Entra desde abajo cuando el JS le añade .is-visible */
  opacity: 0;
  transform: translateY(1rem) scale(.9);
  transition: opacity .35s ease, transform .35s cubic-bezier(.34, 1.56, .64, 1);
  pointer-events: none;
}
.tl-wa-fab.is-visible {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}

.tl-wa-fab-avatar {
  position: relative;
  width: 3.75rem;
  height: 3.75rem;
  border-radius: 50%;
  flex-shrink: 0;
  /* Sin borde: el propio PNG trae el aro verde de WhatsApp ya dibujado, y un
     `border` encima lo duplicaba.
     Tampoco `overflow: hidden`: el recorte circular caía justo sobre ese aro
     y se lo comía, además de cortar la insignia de WhatsApp, que va con
     offsets negativos. El PNG ya es circular y transparente fuera del aro,
     así que no hace falta recortar nada. */
  background: var(--tl-surface);
  box-shadow: 0 .75rem 1.75rem rgba(0, 0, 0, .25);
  transition: transform .25s ease;
}
.tl-wa-fab-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.tl-wa-fab:hover .tl-wa-fab-avatar {
  transform: scale(1.06);
}

/* La insignia de WhatsApp que iba sobre el avatar se retiró: el nuevo PNG ya
   trae el aro verde de WhatsApp y la insignia tapaba media cara del perro.
   El destino sigue anunciado en el `aria-label` del enlace, así que no se
   pierde para lectores de pantalla. */

.tl-wa-fab-globo {
  order: -1;
  background: var(--tl-surface);
  color: var(--tl-text);
  border: 1px solid var(--tl-border);
  border-radius: 50rem;
  padding: .5rem 1rem;
  font-family: var(--tl-font-sub);
  font-weight: 600;
  font-size: .85rem;
  white-space: nowrap;
  box-shadow: var(--tl-shadow);
  /* Sólo al pasar por encima: en reposo se quedaba fijo en pantalla toda la
     visita compitiendo con el contenido. El texto no se pierde para lectores
     de pantalla — va en el aria-label del enlace, y el globo es aria-hidden.
     `pointer-events: none` porque sigue ocupando su hueco en el flex aunque
     esté invisible, y no debe interceptar clics de la página. */
  opacity: 0;
  transform: translateX(.5rem);
  pointer-events: none;
  transition: opacity .25s ease, transform .25s ease;
}
.tl-wa-fab:hover .tl-wa-fab-globo,
.tl-wa-fab:focus-visible .tl-wa-fab-globo {
  opacity: 1;
  transform: none;
}
/* En móvil sólo el avatar: el globo se comería el ancho de pantalla. */
@media (max-width: 575.98px) {
  .tl-wa-fab-globo { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .tl-wa-fab { transition: opacity .2s ease; transform: none; }
}

/* -- Back to top ------------------------------------------------------ */
.tl-back-to-top {
  position: fixed;
  right: 1.25rem;
  /* Por encima del botón de WhatsApp, que ocupa la esquina. */
  bottom: 6.25rem;
  z-index: 1030;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 50%;
  display: none;
  align-items: center;
  justify-content: center;
  background: var(--tl-surface);
  border: 1px solid var(--tl-border);
  color: var(--tl-text);
  box-shadow: var(--tl-shadow);
}
.tl-back-to-top.show {
  display: inline-flex;
}

/* -- Páginas legales --------------------------------------------------
   Aviso de Privacidad, Políticas de Gestión Integral y Términos.

   Toda la presentación del texto jurídico se resuelve AQUÍ, por descendencia,
   para que los parciales de `app/Views/sitio/legal/` no lleven ni una clase: son
   ~2.400 líneas de prosa que hay que poder cotejar línea a línea contra el
   documento que firma Legal, y una sopa de clases lo haría inviable.

   Es la única zona del sistema donde se estiliza por elemento y no por clase.
   La alternativa —marcar cada <p> y cada <h3>— obligaría a tocar el texto legal
   cada vez que cambie el diseño, que es exactamente lo que no se quiere. */
.tl-legal-prose {
  /* Medida de lectura: la prosa legal se lee de corrido y a 100% del contenedor
     las líneas pasan de 110 caracteres. Las tablas sí desbordan a propósito
     (ver más abajo), por eso el tope va aquí y no en el contenedor. */
  max-width: 68ch;
  margin-inline: auto;
  color: var(--tl-text);
  font-size: 1rem;
  line-height: 1.75;
}

/* Título de cada aviso. */
.tl-legal-prose h2 {
  margin-top: 3.5rem;
  margin-bottom: 1.25rem;
  font-size: clamp(1.35rem, 2.5vw, 1.75rem);
  line-height: 1.3;
}
.tl-legal-prose > :first-child,
.tl-legal-prose .tab-pane > :first-child {
  margin-top: 0;
}

/* Apartados numerados (I, II, III…). El romano ya viene en el texto: no se
   genera con un contador porque la numeración del original tiene saltos
   deliberados que un contador borraría. */
.tl-legal-prose h3 {
  margin-top: 2.5rem;
  margin-bottom: .85rem;
  font-family: var(--tl-font-sub);
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: .01em;
  color: var(--tl-blue-text);
}

.tl-legal-prose p {
  margin-bottom: 1.15rem;
  text-align: justify;
  text-wrap: pretty;
  hyphens: auto;
}

.tl-legal-prose ul,
.tl-legal-prose ol {
  margin-bottom: 1.15rem;
  padding-left: 1.5rem;
}
.tl-legal-prose li {
  margin-bottom: .5rem;
}
/* Las listas del legacy traen la numeración escrita en el propio texto
   («1) Datos de contacto…»). `list-unstyled` evita el doble numeral. */
.tl-legal-prose .list-unstyled {
  padding-left: 0;
}

.tl-legal-prose a {
  color: var(--tl-blue-text);
  text-underline-offset: .2em;
}

/* -- Tablas del aviso -------------------------------------------------
   Rompen la medida de lectura a propósito: son rejillas de dos columnas
   («datos que se recaban» / «finalidades») y a 68ch quedan ilegibles. */
.tl-legal-prose .table-responsive {
  /* Se sale del `max-width: 68ch` del contenedor hasta el ancho de la columna.
     `max-width: 100vw` evita que el truco genere scroll horizontal de página
     en pantallas estrechas. */
  width: min(100%, 60rem);
  max-width: 100vw;
  margin-inline: calc(50% - min(50%, 30rem));
  margin-bottom: 2rem;
}
.tl-legal-prose .table {
  --bs-table-bg: transparent;
  --bs-table-color: var(--tl-text);
  margin-bottom: 0;
  font-size: .9rem;
  line-height: 1.6;
  border-color: var(--tl-border);
}
.tl-legal-prose .table th,
.tl-legal-prose .table td {
  padding: .75rem .9rem;
  border: 1px solid var(--tl-border);
  vertical-align: top;
}
.tl-legal-prose .table th {
  background: var(--tl-surface-alt);
  font-family: var(--tl-font-sub);
  font-weight: 700;
}
.tl-legal-prose .table ul {
  margin-bottom: 0;
}

/* -- Pestañas de los tres avisos --------------------------------------
   No son `nav-tabs` de Bootstrap: ese componente dibuja una caja con borde
   que compite con las tablas del propio aviso. Aquí sólo subrayado activo,
   igual que los enlaces del navbar. */
.tl-legal-tabs {
  gap: .25rem;
  border-bottom: 1px solid var(--tl-border);
  flex-wrap: wrap;
}
.tl-legal-tabs .nav-link {
  position: relative;
  border: 0;
  background: none;
  padding: .75rem 1.1rem;
  font-family: var(--tl-font-sub);
  font-size: .95rem;
  font-weight: 600;
  color: var(--tl-text-muted);
  border-radius: 0;
}
.tl-legal-tabs .nav-link:hover {
  color: var(--tl-text);
}
.tl-legal-tabs .nav-link.active {
  color: var(--tl-orange-text);
  background: none;
}
.tl-legal-tabs .nav-link.active::after {
  content: "";
  position: absolute;
  left: 1.1rem;
  right: 1.1rem;
  bottom: -1px;
  height: 2px;
  background: var(--tl-orange);
}
.tl-legal-tabs .nav-link:focus-visible {
  outline: 2px solid var(--tl-blue);
  outline-offset: -2px;
}

/* -- Modal de solicitud ARCO ------------------------------------------ */
.tl-legal-modal {
  background: var(--tl-surface);
  border: 1px solid var(--tl-border);
  border-radius: var(--tl-radius);
}
.tl-legal-modal .modal-header,
.tl-legal-modal .modal-footer {
  border-color: var(--tl-border);
}
.tl-legal-modal .form-label {
  font-family: var(--tl-font-sub);
  font-size: .9rem;
  font-weight: 600;
  margin-bottom: .35rem;
}

@media (max-width: 767.98px) {
  .tl-legal-prose {
    font-size: .95rem;
  }
  /* Justificado + medida corta abre ríos de espacio en blanco. */
  .tl-legal-prose p {
    text-align: left;
  }
  .tl-legal-tabs .nav-link {
    padding: .6rem .75rem;
    font-size: .875rem;
  }
  .tl-legal-tabs .nav-link.active::after {
    left: .75rem;
    right: .75rem;
  }
}

/* -- Tarjetas de sede (Contacto) --------------------------------------
   Equivalente claro de `.tl-footer-contact`, que no se puede reutilizar
   porque fija texto blanco para el pie oscuro. Mismo ritmo, colores del
   tema. */
.tl-sede-datos li {
  display: flex;
  align-items: flex-start;
  gap: .6rem;
  font-size: .875rem;
  line-height: 1.5;
  color: var(--tl-text-muted);
}
/* El ícono NO hereda: lleva el color de la sede en un inline style, que es la
   excepción tolerada del sistema (pintar un ícono con un color de marca). */
.tl-sede-datos li i {
  font-size: .95rem;
  margin-top: .15rem;
  flex-shrink: 0;
}
.tl-sede-datos a {
  color: var(--tl-text);
  text-decoration: none;
}
.tl-sede-datos a:hover {
  color: var(--tl-orange-text);
  text-decoration: underline;
}
/* Un correo o un teléfono nunca se parten a media palabra. */
.tl-sede-datos a[href^="mailto:"],
.tl-sede-datos a[href^="tel:"] {
  white-space: nowrap;
}

.tl-sede-mapa {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  font-family: var(--tl-font-sub);
  font-weight: 600;
  font-size: .9rem;
  color: var(--tl-blue-text);
  text-decoration: none;
}
.tl-sede-mapa:hover {
  color: var(--tl-orange-text);
}

/* -- Las dos tarjetas-camino de Contacto ------------------------------
   Son un <a> entero, así que hay que devolverle el color al texto: el
   `text-decoration-none` del marcado quita el subrayado pero no el color de
   enlace, y el h2 y el párrafo salían azules. */
a.tl-card {
  color: inherit;
}
a.tl-card h2,
a.tl-card p {
  color: inherit;
}
a.tl-card p.tl-text-muted {
  color: var(--tl-text-muted);
}

/* -- Detalle de artículo del blog -------------------------------------
   Mismo reparto que las legales: el cuerpo del artículo llega sin clases
   desde `app/Views/sitio/blog/articulos/` y se estiliza por descendencia. */
.tl-articulo-hero {
  background:
    radial-gradient(55% 70% at 85% 0%, rgba(var(--tl-orange-rgb), .10), transparent 60%),
    radial-gradient(45% 55% at 0% 100%, rgba(var(--tl-blue-rgb), .10), transparent 60%);
  padding-block: clamp(2.5rem, 6vw, 4rem) clamp(2rem, 4vw, 3rem);
}

/* Migas. Separador con ::after y no con un carácter en el marcado, para que
   no lo lea el lector de pantalla como parte del nombre de la página. */
.tl-migas {
  gap: .5rem;
  font-family: var(--tl-font-sub);
  font-size: .8rem;
  color: var(--tl-text-muted);
  margin: 0;
}
.tl-migas li {
  display: flex;
  align-items: center;
  gap: .5rem;
  min-width: 0;
}
.tl-migas li:not(:last-child)::after {
  content: "/";
  color: var(--tl-border);
}
.tl-migas a {
  color: var(--tl-text-muted);
  text-decoration: none;
  white-space: nowrap;
}
.tl-migas a:hover {
  color: var(--tl-orange-text);
}
/* El título del artículo puede ser largo: se recorta con puntos suspensivos
   en vez de partir la línea de migas en dos. */
.tl-migas li[aria-current] {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tl-articulo-portada {
  width: 100%;
  height: auto;
  border-radius: var(--tl-radius);
  display: block;
}

.tl-articulo-prose {
  font-size: 1.05rem;
  line-height: 1.8;
  color: var(--tl-text);
}
.tl-articulo-prose h2 {
  margin-top: 3rem;
  margin-bottom: 1rem;
  font-size: clamp(1.3rem, 2.2vw, 1.6rem);
  line-height: 1.3;
}
.tl-articulo-prose > :first-child {
  margin-top: 0;
}
.tl-articulo-prose p {
  margin-bottom: 1.35rem;
  text-wrap: pretty;
}
.tl-articulo-prose ul,
.tl-articulo-prose ol {
  margin-bottom: 1.35rem;
  padding-left: 1.5rem;
}
.tl-articulo-prose li {
  margin-bottom: .5rem;
}
.tl-articulo-prose strong {
  color: var(--tl-text);
  font-weight: 700;
}
.tl-articulo-prose a {
  color: var(--tl-blue-text);
  text-underline-offset: .2em;
}
/* Las imágenes intercaladas respiran por encima y por debajo, y nunca
   desbordan la columna de lectura. */
.tl-articulo-prose img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--tl-radius);
  margin-block: 2rem;
}

@media (max-width: 767.98px) {
  .tl-articulo-prose {
    font-size: 1rem;
  }
}

/* ==========================================================================
   Tarjeta de la vacante (.tl-vac-card) — landing de Agente Bilingüe
   ==========================================================================
   La plaza es lo que el candidato viene a leer, así que la tarjeta es la única
   de la landing con banda de color: le da un ancla en una página que por lo
   demás es texto sobre blanco.

   La banda usa `--tl-blue-chip` / `--tl-orange-chip` y no los azules y naranjas
   de marca: lleva texto blanco encima y los tonos base no lo sostienen (2.3).
   Al vivir esos tokens fuera de los bloques de tema, la banda se ve igual en
   claro y en oscuro, que es lo que se quiere cuando el texto es de color fijo.

   Las dos listas no se maquetan igual a propósito. «Requisitos» son cinco y
   «Ofrecemos» dos: en dos columnas idénticas la corta parece inacabada. Yendo
   en un panel con fondo, la de dos se lee como un destacado y no como el hueco
   que dejó la otra. */
.tl-vac-card {
  overflow: hidden;   /* la banda llega al borde; sin esto se sale del radio */
}

/* No es un enlace: el levantamiento de `.tl-card` prometería un clic que no
   existe. El botón de dentro es lo que se pulsa. */
.tl-vac-card:hover {
  transform: none;
  box-shadow: var(--tl-shadow);
}

.tl-vac-head {
  background: linear-gradient(135deg, var(--tl-blue-chip), var(--tl-orange-chip));
  color: #fff;
  padding: 1.75rem;
}

.tl-vac-etiqueta {
  display: inline-block;
  margin-bottom: 1.1rem;
  padding: .35rem .85rem;
  border-radius: 50rem;
  background: rgba(255, 255, 255, .18);
  border: 1px solid rgba(255, 255, 255, .35);
  font-family: var(--tl-font-sub);
  font-weight: 600;
  font-size: .82rem;
}

.tl-vac-head-fila {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.tl-vac-icono {
  width: 3.5rem;
  height: 3.5rem;
  flex-shrink: 0;
  border-radius: .9rem;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.6rem;
  background: rgba(255, 255, 255, .18);
  border: 1px solid rgba(255, 255, 255, .35);
}

.tl-vac-titulo {
  /* `h1..h4` fijan `color: var(--tl-text)` sobre el elemento, así que la
     herencia de `.tl-vac-head` no llega: hay que declararlo aquí. */
  color: #fff;
  font-family: var(--tl-font-heading);
  font-weight: 700;
  font-size: clamp(1.35rem, 3vw, 1.75rem);
  line-height: 1.15;
  margin-bottom: .2rem;
}

.tl-vac-sub {
  font-family: var(--tl-font-sub);
  font-weight: 700;
  font-size: .85rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  margin-bottom: 0;
  /* Blanco al 85%: a plena opacidad compite con el título, y más abajo no
     llegaría al contraste que pide un texto de este tamaño. */
  color: rgba(255, 255, 255, .85);
}

.tl-vac-body {
  padding: 1.75rem;
}

.tl-vac-lista-t {
  font-family: var(--tl-font-sub);
  font-weight: 700;
  font-size: .8rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--tl-text-muted);
  margin-bottom: .9rem;
}

.tl-vac-lista {
  list-style: none;
  padding-left: 0;
  margin-bottom: 0;
}
.tl-vac-lista li {
  display: flex;
  gap: .6rem;
  font-size: .925rem;
  line-height: 1.45;
  margin-bottom: .6rem;
}
.tl-vac-lista li:last-child {
  margin-bottom: 0;
}
.tl-vac-lista i {
  flex-shrink: 0;
  /* Alinea el glifo con la primera línea del renglón, no con su centro: en los
     puntos que ocupan dos líneas se quedaba flotando a media altura. */
  line-height: 1.45;
  color: var(--tl-blue-text);
}

/* Panel del destacado. `--tl-surface-alt` lo separa de la tarjeta sin meter
   otro color de marca: en la banda ya hay bastante. */
.tl-vac-oferta {
  height: 100%;
  padding: 1.25rem;
  border-radius: var(--tl-radius-sm);
  background: var(--tl-surface-alt);
  border: 1px solid var(--tl-border);
}
.tl-vac-oferta .tl-vac-lista i {
  color: var(--tl-orange-text);
}

@media (min-width: 992px) {
  .tl-vac-head,
  .tl-vac-body {
    padding: 2.25rem;
  }
}

/* ==========================================================================
   Pasos siguientes (.tl-pasos) — página de gracias
   ==========================================================================
   Tres tarjetas atravesadas por una línea a la altura de sus distintivos, que
   es lo que las lee como una secuencia y no como tres bloques sueltos. El
   degradado azul→naranja es el mismo lenguaje de progresión de .tl-timeline.

   La línea es UN solo trazo en `.tl-pasos::before`, no un tramo por tarjeta:
   así el degradado recorre los tres pasos de principio a fin en lugar de
   reiniciarse en cada calle. Las tarjetas van encima con fondo opaco, de modo
   que del trazo sólo asoman las calles. Por eso `.tl-paso` necesita
   `z-index`: un pseudoelemento posicionado se pinta por encima de los hijos
   en flujo, y sin él la línea cruzaría por delante de las tarjetas.

   El primer paso va relleno y los otros dos en contorno. Es el único que
   depende del candidato —los demás le ocurren a él—, así que el relleno dice
   dónde está parado.

   Las medidas salen de variables porque la posición de la línea las suma: el
   centro del distintivo es el relleno de la tarjeta más medio disco. Cambiar
   el relleno con una clase de utilidad descuadra el trazo; se cambia aquí.
   El ancho de calle se toma de `--bs-gutter-x`, que pone Bootstrap con `g-4`,
   para que no haya dos fuentes de la misma medida. */
.tl-pasos {
  --tl-paso-pad: 1.75rem;
  --tl-paso-disco: 2.75rem;
  --tl-paso-eje: calc(var(--tl-paso-pad) + var(--tl-paso-disco) / 2 - 1px);

  position: relative;
  list-style: none;
  padding-left: 0;
  margin-bottom: 0;
}

.tl-paso {
  position: relative;
  z-index: 1;
}

.tl-paso-card {
  padding: var(--tl-paso-pad);
}

/* Estas tarjetas no son enlaces. El levantamiento de `.tl-card` prometería un
   clic que no existe y, de paso, despegaría la tarjeta de la línea. */
.tl-paso-card:hover {
  transform: none;
  box-shadow: var(--tl-shadow);
}

.tl-paso-num {
  width: var(--tl-paso-disco);
  height: var(--tl-paso-disco);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  margin-bottom: 1.1rem;
  font-family: var(--tl-font-heading);
  font-weight: 700;
  font-size: 1.15rem;
  line-height: 1;
  background: var(--tl-surface);
  border: 2px solid var(--tl-border);
  color: var(--tl-text-muted);
}

/* `--tl-blue-chip` y no `--tl-blue`: el disco lleva texto blanco encima y el
   azul de marca no lo sostiene (ver 2.3). */
.tl-paso.is-activo .tl-paso-num {
  background: var(--tl-blue-chip);
  border-color: var(--tl-blue-chip);
  color: #fff;
}

.tl-paso-titulo {
  font-size: 1rem;
  margin-bottom: .45rem;
}

@media (min-width: 768px) {
  .tl-pasos::before {
    content: "";
    position: absolute;
    /* `margin-top` del gutter vertical: Bootstrap lo pone en `.row > *`, así
       que la tarjeta empieza ahí y no en el borde de la fila. */
    top: calc(var(--bs-gutter-y) + var(--tl-paso-eje));
    left: calc(var(--bs-gutter-x) / 2);
    right: calc(var(--bs-gutter-x) / 2);
    height: 2px;
    background: linear-gradient(to right, var(--tl-blue), var(--tl-orange));
    opacity: .45;
  }
}

/* Apiladas, la línea pasa a ser vertical y va por calle, porque ya no hay una
   sola recta que las atraviese a todas. */
@media (max-width: 767.98px) {
  .tl-paso::after {
    content: "";
    position: absolute;
    top: 100%;
    left: calc(var(--bs-gutter-x) / 2 + var(--tl-paso-eje));
    width: 2px;
    height: var(--bs-gutter-y);
    background: linear-gradient(to bottom, var(--tl-blue), var(--tl-orange));
    opacity: .45;
  }
  .tl-paso:last-child::after {
    content: none;
  }
}

/* ==========================================================================
   Aviso de cookies (.tl-cookies)
   ==========================================================================
   Barra discreta abajo. NO es un gestor de consentimiento: informa y se cierra,
   no pregunta ni bloquea nada. Por eso no ocupa media pantalla ni oscurece el
   fondo — el peso visual de un diálogo prometería una decisión que aquí no se
   está pidiendo.

   Se aparta del botón flotante de WhatsApp, que vive en la esquina derecha. */
.tl-cookies {
  position: fixed;
  left: 1rem;
  bottom: 1rem;
  z-index: 1040;
  max-width: 30rem;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .75rem 1rem;
  padding: 1rem 1.15rem;
  background: var(--tl-surface);
  border: 1px solid var(--tl-border);
  border-radius: var(--tl-radius);
  box-shadow: 0 1rem 2.5rem rgba(34, 34, 33, .18);
}
[data-bs-theme="dark"] .tl-cookies {
  box-shadow: 0 1rem 2.5rem rgba(0, 0, 0, .5);
}

.tl-cookies-texto {
  flex: 1 1 15rem;
  font-size: .85rem;
  line-height: 1.5;
  color: var(--tl-text-muted);
}
.tl-cookies-texto strong {
  display: block;
  color: var(--tl-text);
  font-family: var(--tl-font-sub);
  font-weight: 700;
  margin-bottom: .15rem;
}
.tl-cookies-texto a { color: var(--tl-blue); }

.tl-cookies-boton {
  flex-shrink: 0;
  font-family: var(--tl-font-sub);
  font-weight: 700;
  font-size: .82rem;
  color: #fff;
  background: var(--tl-blue-chip);
  border: 0;
  border-radius: 50rem;
  padding: .5rem 1.15rem;
  cursor: pointer;
}
.tl-cookies-boton:hover { background: var(--tl-text); }
.tl-cookies-boton:focus-visible {
  outline: 2px solid var(--tl-blue);
  outline-offset: 2px;
}

/* En móvil ocupa el ancho: media barra flotante se lee peor que una completa. */
@media (max-width: 575.98px) {
  .tl-cookies {
    left: .75rem;
    right: .75rem;
    bottom: .75rem;
    max-width: none;
  }
}

/* ==========================================================================
   Campo trampa anti-bot (.tl-trampa)
   ==========================================================================
   Oculta el señuelo de App\Libraries\AntiBots sin usar `display:none` ni el
   atributo `hidden`: los raspadores más simples buscan justamente eso y saltan
   el campo. Sacarlo del flujo y dejarlo transparente lo esconde igual de bien
   para una persona y peor para un script.

   `aria-hidden` en el marcado se encarga de los lectores de pantalla, que sí
   verían el campo por estar en el árbol de accesibilidad.

   No se toca sin leer AntiBots: si esto deja de ocultar, los candidatos ven un
   campo «No llenar» en mitad del formulario. */
.tl-trampa {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
    opacity: 0;
    pointer-events: none;
}
