/* ==========================================================================
   UB Logistics · Theme 2026
   Paleta: #9D2035 rojo · #373737 tinta · grises · blanco.
   El material de marca es monocromo: el rojo es el único color.
   ========================================================================== */

:root {
    --ubl-red:       #9D2035;
    --ubl-red-rgb:   157, 32, 53;
    /* El rojo de marca sobre fondo oscuro da 2,2:1 de contraste, por debajo
       del mínimo legible de 4,5:1. Este es el mismo tono aclarado hasta
       6,9:1, así que el acento se mantiene y el texto se lee. */
    --ubl-red-light: #E08A99;
    --ubl-red-dark:  #7E1A2B;
    --ubl-ink:       #373737;
    --ubl-black:     #111111;
    --ubl-gray:      #8A8A93;
    --ubl-gray-50:   #FAFAFA;
    --ubl-gray-100:  #F2F2F2;
    --ubl-gray-200:  #E7E7E7;
    --ubl-gray-300:  #CFCFCF;
    --ubl-white:     #FFFFFF;

    --ubl-font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    --ubl-font-display: 'DM Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;

    --ubl-nav-h: 80px;
    --ubl-topbar-h: 10px;   /* 3% de una lámina 16:9 del deck, llevado a web */

    /* Ritmo vertical del sitio en un solo lugar. */
    --ubl-section-y: clamp(3rem, 6vw, 5.5rem);
    --ubl-section-y-sm: clamp(2.5rem, 4vw, 3.5rem);

    /* Curva de salida: arranca rapido y frena largo. Es la que da la
       sensacion de peso; con `ease` las entradas se leian como un fundido. */
    --ubl-ease: cubic-bezier(.16, 1, .3, 1);
}

/* Las anclas del menú caen bajo un header fijo: scroll-padding-top en html lo
   resuelve para el click, el deep-link al cargar y el botón atrás por igual.
   Es lo que hace scrollIntoView() innecesario en JS. */
html {
    scroll-behavior: smooth;
    scroll-padding-top: calc(var(--ubl-nav-h) + var(--ubl-topbar-h) + 16px);
}
@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
}

body {
    font-family: var(--ubl-font-sans);
    color: var(--ubl-ink);
    background: var(--ubl-white);
    -webkit-font-smoothing: antialiased;
}
body.ubl-solid-nav { padding-top: calc(var(--ubl-nav-h) + var(--ubl-topbar-h)); }

h1, h2, h3, h4 {
    font-family: var(--ubl-font-display);
    font-weight: 700;
    letter-spacing: -0.02em;
    color: var(--ubl-ink);
}

/* El deck va en blanco y negro con el rojo como único color. */
body.ubl-mono .ubl-hero.has-image::before { filter: grayscale(1); }

/* ===== Botones ===== */

.ubl-btn {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    padding: .8rem 1.6rem;
    border-radius: 999px;
    border: 2px solid transparent;
    font-family: var(--ubl-font-display);
    font-weight: 700;
    font-size: .92rem;
    text-decoration: none;
    transition: background .18s ease, color .18s ease, transform .18s ease;
}
.ubl-btn--primary { background: var(--ubl-red); color: #fff; }
.ubl-btn--primary:hover { background: var(--ubl-red-dark); color: #fff; transform: translateY(-2px); }
.ubl-btn--ghost { border-color: currentColor; color: var(--ubl-ink); }
.ubl-btn:focus-visible { outline: 3px solid color-mix(in srgb, var(--ubl-red) 45%, transparent); outline-offset: 3px; }

/* ===== Header ===== */

.ubl-skip { position: absolute; z-index: 1100; }

.ubl-header {
    position: fixed;
    inset: var(--ubl-topbar-h) 0 auto 0;
    z-index: 1030;
    height: var(--ubl-nav-h);
    display: flex;
    align-items: center;
    background: var(--ubl-white);
    border-bottom: 1px solid var(--ubl-gray-200);
    transition: background .2s ease, box-shadow .2s ease, border-color .2s ease;
}
/* En la home arranca transparente encima del hero y se solidifica al scrollear. */
body.ubl-over-hero .ubl-header {
    background: transparent;
    border-bottom-color: transparent;
}
body.ubl-over-hero .ubl-header.is-scrolled {
    background: var(--ubl-white);
    border-bottom-color: var(--ubl-gray-200);
    box-shadow: 0 1px 0 rgba(0, 0, 0, .08);
}
.ubl-navbar { width: 100%; padding: 0; }

.ubl-brand__img { display: block; height: 54px; width: auto; }
/* Sobre el hero el logo rojo no contrasta. El filtro lo pasa a blanco sin pedir
   una segunda imagen; el footer sí usa el PNG blanco porque ahí es permanente. */
body.ubl-over-hero .ubl-header:not(.is-scrolled) .ubl-brand__img { filter: brightness(0) invert(1); }

.ubl-nav-link,
.ubl-nav .nav-link {
    position: relative;
    font-size: .86rem;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--ubl-ink);
    padding: .5rem .9rem;
    transition: color .25s ease;
}
/* El ítem activo se marca con un filete propio en vez de text-decoration: el
   subrayado del navegador se pega a las descendentes y corta los acentos. */
.ubl-nav .nav-link::after {
    content: '';
    position: absolute;
    left: .9rem;
    right: .9rem;
    bottom: .15rem;
    height: 2px;
    background: currentColor;
    transform: scaleX(0);
    transform-origin: left;
    transition: transform .35s var(--ubl-ease);
}
.ubl-nav .nav-link:hover::after,
.ubl-nav .nav-link.active::after { transform: scaleX(1); }
.ubl-nav .nav-link:hover,
.ubl-nav .nav-link.active { color: var(--ubl-red); }
body.ubl-over-hero .ubl-header:not(.is-scrolled) .ubl-nav .nav-link { color: #fff; }
body.ubl-over-hero .ubl-header:not(.is-scrolled) .ubl-nav .nav-link:hover,
body.ubl-over-hero .ubl-header:not(.is-scrolled) .ubl-nav .nav-link.active { color: #fff; }

.ubl-lang__toggle {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    padding: .38rem .8rem;
    border: 1px solid var(--ubl-gray-200);
    border-radius: 999px;
    background: transparent;
    font-family: var(--ubl-font-display);
    font-size: .78rem;
    font-weight: 700;
    letter-spacing: .06em;
    color: var(--ubl-ink);
    transition: background-color .25s ease, border-color .25s ease, color .25s ease;
}
.ubl-lang__toggle:hover { border-color: var(--ubl-red); color: var(--ubl-red); }
.ubl-lang__toggle:focus-visible { outline: 2px solid var(--ubl-red); outline-offset: 2px; }

/* El menú se configura con las variables del propio dropdown de Bootstrap en
   vez de sobrescribir sus reglas: menos especificidad y nada que romper si
   cambia de versión. */
.ubl-lang__menu {
    --bs-dropdown-min-width: 11rem;
    --bs-dropdown-spacer: 1.1rem;
    --bs-dropdown-border-radius: 2px;
    --bs-dropdown-border-color: var(--ubl-gray-200);
    --bs-dropdown-font-size: .88rem;
    --bs-dropdown-link-active-bg: var(--ubl-red);
    --bs-dropdown-link-hover-bg: var(--ubl-gray-100);
    box-shadow: 0 18px 40px rgba(0, 0, 0, .12);
}
.ubl-lang__menu .dropdown-item { display: flex; align-items: center; gap: .6rem; padding: .55rem 1rem; }
.ubl-lang__code {
    min-width: 1.7rem;
    font-size: .68rem;
    font-weight: 700;
    letter-spacing: .1em;
    color: var(--ubl-gray);
}
.ubl-lang__menu .dropdown-item.active .ubl-lang__code { color: rgba(255, 255, 255, .7); }

/* Sobre el hero el header es transparente: el botón se invierte para leerse. */
body.ubl-over-hero .ubl-header:not(.is-scrolled) .ubl-lang__toggle { color: #fff; border-color: rgba(255,255,255,.45); }
body.ubl-over-hero .ubl-header:not(.is-scrolled) .ubl-lang__toggle:hover { background: #fff; color: var(--ubl-red); border-color: #fff; }

@media (max-width: 991.98px) {
    .ubl-navbar .navbar-collapse {
        background: var(--ubl-white);
        margin: 0 -1rem;
        padding: 1rem;
        border-top: 1px solid var(--ubl-gray-200);
    }
    body.ubl-over-hero .ubl-header:not(.is-scrolled) .navbar-collapse .nav-link { color: var(--ubl-ink); }
    body.ubl-over-hero .ubl-header:not(.is-scrolled) .navbar-collapse .ubl-lang__toggle { color: var(--ubl-ink); border-color: var(--ubl-gray-200); }
}

/* ===== Secciones ===== */

.ubl-section { padding: var(--ubl-section-y) 0; }
.ubl-hero + .ubl-kpis + .ubl-section,
.ubl-hero + .ubl-section { padding-top: var(--ubl-section-y-sm); }
.ubl-section--gray { background: var(--ubl-gray-50); }
.ubl-section--dark { background: var(--ubl-ink); color: #fff; }
.ubl-section--dark h1, .ubl-section--dark h2, .ubl-section--dark h3 { color: #fff; }

.ubl-eyebrow {
    display: block;
    font-size: .74rem;
    font-weight: 600;
    letter-spacing: .22em;
    text-transform: uppercase;
    color: var(--ubl-red);
    margin-bottom: .75rem;
}
/* Sobre el hero y cualquier bloque oscuro, el rojo de marca no se lee. */
.ubl-hero .ubl-eyebrow,
.ubl-section--dark .ubl-eyebrow { color: var(--ubl-red-light); }
.ubl-section__head { max-width: 62ch; margin-bottom: clamp(2rem, 4vw, 3rem); }
.ubl-section__title { font-size: clamp(1.9rem, 3.6vw, 3rem); line-height: 1.12; margin: 0 0 1rem; }
.ubl-section__lead { font-size: clamp(1rem, 1.3vw, 1.15rem); line-height: 1.7; color: var(--ubl-gray); margin: 0; }
.ubl-section--dark .ubl-section__lead { color: rgba(255,255,255,.75); }
.ubl-empty { color: var(--ubl-gray); font-style: italic; }

/* ===== Hero ===== */

.ubl-hero {
    position: relative;
    display: flex;
    align-items: flex-end;
    min-height: clamp(520px, 78vh, 760px);
    padding: calc(var(--ubl-nav-h) + var(--ubl-topbar-h) + 3rem) 0 clamp(3rem, 6vw, 5rem);
    background: var(--ubl-ink);
    color: #fff;
    overflow: hidden;
}
.ubl-hero.has-image::before {
    content: "";
    position: absolute;
    inset: 0;
    background-image: var(--ubl-hero-img);
    background-size: cover;
    background-position: center;
}
/* El video va detrás del velo (::after) y del contenido. `object-fit: cover`
   lo recorta al alto del hero en vez de deformarlo. */
.ubl-hero__video {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    z-index: 0;
    pointer-events: none;
}
/* Quien pidió menos movimiento no debería recibir un video en bucle de fondo:
   se oculta y queda el color del hero, que ya da el contraste del texto. */
@media (prefers-reduced-motion: reduce) {
    .ubl-hero__video { display: none; }
}
.ubl-hero::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, rgba(17,17,17,.45) 0%, rgba(17,17,17,.75) 100%);
}
.ubl-hero .container { position: relative; z-index: 1; }
/* El ancho se mide en rem y no en ch: el título usa la display a ~4rem, así que
   34ch de esa fuente dejaba una columna angosta que partía el titular palabra
   por palabra. */
.ubl-hero__body { max-width: min(46rem, 100%); }
.ubl-hero__title {
    color: #fff;
    font-size: clamp(2.4rem, 5.5vw, 4.2rem);
    line-height: 1.05;
    margin: 0 0 1.25rem;
}
.ubl-hero__lead {
    font-size: clamp(1.02rem, 1.4vw, 1.2rem);
    line-height: 1.7;
    color: rgba(255,255,255,.85);
    margin: 0 0 1.75rem;
    max-width: 52ch;
}

/* ===== KPIs ===== */

/* En el material de marca el rojo es acento sobre blanco, nunca un bloque a
   todo ancho: como franja llena se leía marrón y se comía el hero. */
.ubl-kpis { padding: clamp(2rem, 4vw, 3rem) 0; border-bottom: 1px solid var(--ubl-gray-200); }
.ubl-kpis__grid { display: grid; grid-template-columns: repeat(4, 1fr); }
.ubl-kpi { text-align: center; padding: 0 1rem; border-left: 1px solid var(--ubl-gray-200); }
.ubl-kpi:first-child { border-left: 0; }
.ubl-kpi__value {
    display: block;
    font-family: var(--ubl-font-display);
    font-size: clamp(2rem, 4vw, 3.1rem);
    font-weight: 500;
    letter-spacing: -.03em;
    font-variant-numeric: tabular-nums;
    color: var(--ubl-red);
}
.ubl-kpi__label {
    display: block;
    font-size: .7rem;
    letter-spacing: .18em;
    text-transform: uppercase;
    color: var(--ubl-gray);
    margin-top: .4rem;
}
@media (max-width: 767.98px) {
    .ubl-kpis__grid { grid-template-columns: repeat(2, 1fr); gap: 1.5rem 0; }
    .ubl-kpi:nth-child(odd) { border-left: 0; }
}

/* ===== ADN ===== */

/* El video es vertical (se grabó para redes), así que ocupa una columna
   angosta al lado del texto en vez de estirarse a un ancho para el que no fue
   filmado. */
/* ===== Quiénes somos: texto + foto con botón de video ===== */

.ubl-about { display: grid; grid-template-columns: 1.5fr 1fr; gap: clamp(1.5rem, 4vw, 3.5rem); align-items: center; }
.ubl-about__media { position: relative; border-radius: 2px; overflow: hidden; }
.ubl-about__photo { display: block; width: 100%; aspect-ratio: 4 / 5; object-fit: cover; }

/* El botón cubre toda la foto: el objetivo de pulsación es la imagen entera y
   no un círculo de 60px, que en un celular se falla más de lo que se acierta. */
.ubl-playbtn {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: .9rem;
    padding: 1.5rem;
    border: 0;
    background: linear-gradient(180deg, rgba(17,17,17,.15) 0%, rgba(17,17,17,.62) 100%);
    color: #fff;
    cursor: pointer;
    text-align: center;
    transition: background-color .35s ease;
}
.ubl-playbtn:hover { background: linear-gradient(180deg, rgba(17,17,17,.25) 0%, rgba(17,17,17,.72) 100%); }
.ubl-playbtn__icon {
    display: grid;
    place-items: center;
    width: 66px;
    height: 66px;
    border-radius: 50%;
    background: var(--ubl-red);
    font-size: 1.9rem;
    line-height: 1;
    padding-left: 4px;
    box-shadow: 0 10px 30px rgba(0, 0, 0, .35);
    transition: transform .4s var(--ubl-ease);
}
.ubl-playbtn:hover .ubl-playbtn__icon { transform: scale(1.1); }
.ubl-playbtn__label {
    max-width: 22ch;
    font-family: var(--ubl-font-display);
    font-size: .88rem;
    font-weight: 600;
    line-height: 1.45;
    text-shadow: 0 1px 6px rgba(0,0,0,.5);
}
.ubl-playbtn:focus-visible { outline: 3px solid #fff; outline-offset: -6px; }

/* Visor del video: se abre encima, con el video en su formato vertical real. */
.ubl-lightbox {
    position: fixed;
    inset: 0;
    z-index: 1200;
    display: none;
    place-items: center;
    padding: clamp(1rem, 4vw, 3rem);
    background: rgba(10, 10, 10, .92);
}
.ubl-lightbox.is-open { display: grid; }
.ubl-lightbox video {
    max-width: min(420px, 100%);
    max-height: 88vh;
    width: auto;
    border-radius: 3px;
    background: #000;
}
.ubl-lightbox__close {
    position: absolute;
    top: clamp(.75rem, 3vw, 1.5rem);
    right: clamp(.75rem, 3vw, 1.5rem);
    width: 46px;
    height: 46px;
    display: grid;
    place-items: center;
    border: 0;
    border-radius: 50%;
    background: rgba(255,255,255,.14);
    color: #fff;
    font-size: 1.3rem;
    cursor: pointer;
    transition: background-color .25s ease;
}
.ubl-lightbox__close:hover { background: rgba(255,255,255,.28); }

@media (max-width: 767.98px) {
    .ubl-about { grid-template-columns: 1fr; }
    .ubl-about__photo { aspect-ratio: 3 / 2; }
}

/* ===== Nuestro ADN — lámina 03 del deck ===== */

/* Foto a sangre completa ocupando la mitad izquierda, cortada en diagonal, y el
   contenido sobre el blanco de la derecha. Es la composición del propio deck. */
.ubl-adn-slab { position: relative; padding: var(--ubl-section-y) 0; overflow: hidden; }
.ubl-adn-slab__photo {
    position: absolute;
    inset: 0 auto 0 0;
    width: 52%;
    /* La diagonal: recto arriba a la izquierda y en punta hacia abajo, como en
       la lámina. Sin soporte de clip-path queda un rectángulo, que se ve
       distinto pero no roto. */
    clip-path: polygon(0 0, 100% 0, 62% 100%, 0 100%);
}
.ubl-adn-slab__photo img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    /* En blanco y negro porque así está en el deck: el rojo es el único color
       del sistema y una foto a color le competiría a las baldosas.
       El oscurecido no es estética: la foto del pasillo es muy luminosa y en
       gris quedaba casi blanca, indistinguible del fondo de la sección. */
    filter: grayscale(1) contrast(1.18) brightness(.72);
}
/* Degradado hacia la diagonal, para que el borde del recorte no quede como un
   corte duro contra el blanco. */
.ubl-adn-slab__photo::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(105deg, rgba(17,17,17,.15) 40%, rgba(17,17,17,.55) 100%);
}
.ubl-adn-slab__photo { position: absolute; }
.ubl-adn-slab > .container { position: relative; z-index: 1; }

.ubl-adn-list { list-style: none; margin: 0; padding: 0; display: grid; gap: clamp(1.25rem, 2.5vw, 2rem); }
/* Escalonado: cada fila entra un poco más a la derecha que la anterior, que es
   lo que le da movimiento a la lámina. */
.ubl-adn-row {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: clamp(1rem, 2vw, 1.5rem);
    align-items: start;
    margin-left: calc(var(--ubl-step, 0) * clamp(1.5rem, 3.4vw, 3.6rem) + 46%);
    max-width: 44ch;
}
.ubl-adn-row__icon {
    display: grid;
    place-items: center;
    width: clamp(56px, 6vw, 74px);
    aspect-ratio: 1;
    border-radius: 16px;
    background: var(--ubl-red);
    color: #fff;
    font-size: clamp(1.4rem, 2.2vw, 1.9rem);
    box-shadow: 0 12px 28px rgba(var(--ubl-red-rgb), .3);
}
.ubl-adn-row__title { font-size: clamp(1.1rem, 1.6vw, 1.45rem); margin: 0 0 .35rem; }
.ubl-adn-row__text { color: var(--ubl-gray); line-height: 1.6; margin: 0; font-size: .95rem; }

@media (max-width: 991.98px) {
    /* La diagonal necesita ancho para leerse; abajo de eso la foto pasa a ser
       una franja superior y las filas dejan de escalonarse. */
    /* El encuadre baja al centro de la foto: recortada por arriba se queda con
       el techo del almacén, que es la zona más clara y la que menos dice. */
    .ubl-adn-slab__photo { position: relative; width: 100%; height: 34vh; clip-path: none; margin-bottom: 2rem; }
    .ubl-adn-slab__photo img { object-position: center 62%; }
    .ubl-adn-slab { padding-top: 0; }
    .ubl-adn-row { margin-left: 0; max-width: none; }
}
.ubl-adn__item {
    position: relative;
    padding: 1.75rem 1.5rem;
    background: var(--ubl-gray-50);
    border-top: 3px solid var(--ubl-red);
    transition: transform .4s var(--ubl-ease), box-shadow .4s var(--ubl-ease), background-color .3s ease;
}
/* El filete se dibuja sobre el borde superior que la tarjeta ya trae, en vez de
   abajo como en servicios: es el mismo gesto, en el lado que le corresponde. */
.ubl-adn__item::after {
    content: '';
    position: absolute;
    left: 0;
    top: -3px;
    height: 3px;
    width: 100%;
    background: var(--ubl-red-dark);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform .45s var(--ubl-ease);
}
.ubl-adn__item:hover,
.ubl-adn__item:focus-within {
    transform: translateY(-8px);
    background: #fff;
    box-shadow: 0 22px 45px rgba(0, 0, 0, .10);
}
.ubl-adn__item:hover::after,
.ubl-adn__item:focus-within::after { transform: scaleX(1); }
.ubl-adn__icon {
    display: block;
    font-size: 1.6rem;
    color: var(--ubl-red);
    margin-bottom: .75rem;
    transition: transform .4s var(--ubl-ease);
}
.ubl-adn__item:hover .ubl-adn__icon { transform: translateY(-3px) scale(1.12); }
.ubl-adn__title { font-size: 1.05rem; margin: 0 0 .5rem; }
.ubl-adn__text { font-size: .93rem; line-height: 1.65; color: var(--ubl-gray); margin: 0; }

/* ===== Servicios ===== */

.ubl-services { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 1.75rem; }
.ubl-service {
    position: relative;
    background: #fff;
    border: 1px solid var(--ubl-gray-200);
    padding: 2rem 1.75rem;
    transition: transform .4s var(--ubl-ease), box-shadow .4s var(--ubl-ease), border-color .3s ease;
}
/* La regla roja se dibuja de izquierda a derecha al entrar el puntero: es el
   mismo gesto del filete rojo del deck, no un color nuevo. */
.ubl-service::after {
    content: '';
    position: absolute;
    left: 0;
    bottom: -1px;
    height: 3px;
    width: 100%;
    background: var(--ubl-red);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform .45s var(--ubl-ease);
}
.ubl-service:hover,
.ubl-service:focus-within {
    transform: translateY(-8px);
    box-shadow: 0 22px 45px rgba(0, 0, 0, .10);
    border-color: var(--ubl-gray-100);
}
.ubl-service:hover::after,
.ubl-service:focus-within::after { transform: scaleX(1); }
.ubl-service__icon {
    display: block;
    font-size: 2rem;
    color: var(--ubl-red);
    margin-bottom: 1rem;
    transition: transform .4s var(--ubl-ease);
}
.ubl-service:hover .ubl-service__icon { transform: translateY(-3px) scale(1.12); }
.ubl-service__title { font-size: 1.25rem; margin: 0 0 .65rem; }
.ubl-service__text { color: var(--ubl-gray); line-height: 1.7; margin: 0 0 1.25rem; }
.ubl-chips { list-style: none; display: flex; flex-wrap: wrap; gap: .4rem; padding: 0; margin: 0; }
.ubl-chip {
    padding: .3rem .75rem;
    border-radius: 999px;
    background: var(--ubl-gray-100);
    color: var(--ubl-ink);
    font-size: .74rem;
    font-weight: 600;
    letter-spacing: .02em;
    transition: background-color .35s ease, color .35s ease;
}
.ubl-service:hover .ubl-chip {
    background: rgba(var(--ubl-red-rgb), .09);
    color: var(--ubl-red);
}

/* El botón solo aparece cuando el script pudo hacerse cargo del panel; sin JS
   los atributos quedan visibles y un botón muerto sobraría. */
.ubl-service__toggle { display: none; }
.ubl-service__toggle.is-enhanced {
    display: inline-flex;
    align-items: center;
    gap: .45rem;
    margin-top: 1.25rem;
    padding: 0;
    border: 0;
    background: none;
    font-family: var(--ubl-font-display);
    font-size: .78rem;
    font-weight: 700;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--ubl-red);
    cursor: pointer;
    transition: gap .3s var(--ubl-ease);
}
.ubl-service__toggle.is-enhanced:hover { gap: .8rem; }
.ubl-service__toggle .bi { transition: transform .35s var(--ubl-ease); }
.ubl-service__toggle[aria-expanded="true"] .bi { transform: rotate(180deg); }
.ubl-service__toggle:focus-visible { outline: 2px solid var(--ubl-red); outline-offset: 3px; }

/* El panel se muestra u oculta con `display` y la entrada la hace una animación
   sobre la lista. Animar la altura del contenedor obliga a que la transición
   llegue a destino para que el contenido exista; así, si el navegador
   estrangula las animaciones, los atributos igual quedan a la vista. */
.ubl-service__toggle.is-enhanced ~ .ubl-service__more { display: none; margin-top: 1rem; }
.ubl-service__toggle.is-enhanced ~ .ubl-service__more.is-open { display: block; }
.ubl-service__more.is-open .ubl-service__highlights { animation: ubl-more-in .45s var(--ubl-ease) both; }
@keyframes ubl-more-in { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
    .ubl-service__more.is-open .ubl-service__highlights { animation: none; }
}
.ubl-service__highlights {
    list-style: none;
    padding: 0;
    margin: 0;
    display: grid;
    gap: .7rem;
}
.ubl-service__highlights li {
    position: relative;
    padding-left: 1.1rem;
    font-size: .88rem;
    line-height: 1.6;
    color: var(--ubl-gray);
}
.ubl-service__highlights li::before {
    content: '';
    position: absolute;
    left: 0;
    top: .55em;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--ubl-red);
}

/* ===== Cobertura · mapa ===== */

.ubl-coverage__layout { display: grid; gap: clamp(1.75rem, 4vw, 2.75rem); }
.ubl-coverage__layout > * { min-width: 0; }
/* El mapa es un SVG incrustado; los arcos y los pines van en capas hermanas
   con la misma caja, para que las coordenadas en porcentaje coincidan. */
.ubl-coverage__stage { position: relative; width: 100%; max-width: 1100px; margin: 0 auto; }
.rd-map { display: block; width: 100%; height: auto; }
.ubl-coverage__arcs { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible;
    pointer-events: none;
    filter: drop-shadow(0 0 1.5px rgba(0,0,0,.55)) drop-shadow(0 1.5px 3px rgba(0,0,0,.35)); }
.ubl-coverage__pins { position: absolute; inset: 0; }

.rd-prov { fill: var(--ubl-gray-200); stroke: #fff; stroke-width: 2; transition: fill .5s var(--ubl-ease); }
.rd-prov.is-on { fill: var(--ubl-red); }
.rd-islote { fill: var(--ubl-gray-200); }
.rd-label { font-family: var(--ubl-font-sans); font-size: 15px; fill: var(--ubl-gray);
    text-anchor: middle; pointer-events: none; transition: fill .5s ease; }
.rd-label.is-on { fill: #fff; font-weight: 700; }

/* El punteado fluye del almacén hacia la provincia: hace legible el sentido del
   reparto sin tener que explicarlo. */
.ubl-arc { fill: none; stroke: #fff; stroke-width: 2.6; stroke-linecap: round;
    stroke-dasharray: 9 11; marker-end: url(#ubl-arrow);
    opacity: 0; transition: opacity .5s ease; animation: ubl-flujo 1.1s linear infinite; }
.ubl-arc.is-on { opacity: 1; }
@keyframes ubl-flujo { to { stroke-dashoffset: -20; } }

/* Lista de provincias: reemplaza a los rótulos donde el mapa es muy chico. */
.ubl-coverage__list { display: none; list-style: none; padding: 0;
    margin: 1rem auto 0; max-width: 1100px; flex-wrap: wrap; gap: .45rem; }
.ubl-coverage__list li { padding: .34rem .75rem; border-radius: 999px;
    background: rgba(var(--ubl-red-rgb), .09); color: var(--ubl-red);
    font-size: .78rem; font-weight: 600; }

/* Por debajo de ~640px el mapa queda en ~200px de ancho y los rótulos se pisan
   aunque se agranden. Salen del mapa y pasan a la lista, que además es texto
   seleccionable. */
@media (max-width: 639.98px) {
    .rd-label { display: none; }
    .ubl-coverage__list { display: flex; }
    .ubl-arc { stroke-width: 5; }
}
@media (min-width: 640px) and (max-width: 900px) {
    .rd-label { font-size: 22px; }
    .rd-label:not(.is-on) { opacity: .75; }
}
@media (prefers-reduced-motion: reduce) {
    .ubl-arc { animation: none; }
}

/* El mapa vectorial no trae los marcadores dibujados (el PNG del deck sí), así
   que el pin los pinta: punto siempre visible, halo solo al seleccionar. */
.ubl-pin {
    position: absolute;
    width: 0;
    height: 0;
    padding: 0;
    border: 0;
    background: none;
    cursor: pointer;
    z-index: 2;
}
/* Cada pieza se centra sobre el punto por su cuenta. Con grid no funcionaba:
   el tamaño de la celda lo fija el hijo más grande (el halo, 78px), así que
   `place-items: center` centraba dentro de esa celda y no sobre el punto —
   corría el marcador media celda abajo y a la derecha del origen real. */
.ubl-pin__dot,
.ubl-pin__halo,
.ubl-pin__name {
    position: absolute;
    left: 0;
    top: 0;
}
.ubl-pin__dot {
    transform: translate(-50%, -50%);
    width: 15px;
    height: 15px;
    border-radius: 50%;
    background: var(--ubl-red);
    box-shadow: 0 0 0 3.5px #fff, 0 2px 7px rgba(0, 0, 0, .35);
    transition: transform .35s var(--ubl-ease);
}
.ubl-pin__halo {
    width: 78px;
    height: 78px;
    border-radius: 50%;
    background: rgba(var(--ubl-red-rgb), .16);
    opacity: 0;
    transform: translate(-50%, -50%) scale(.35);
    transition: opacity .35s ease, transform .45s var(--ubl-ease);
}
/* El nombre del almacén, como en la lámina del deck. */
.ubl-pin__name {
    transform: translate(-50%, 16px);
    white-space: nowrap;
    font-family: var(--ubl-font-display);
    font-size: .74rem;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--ubl-red);
    text-shadow: 0 0 4px #fff, 0 0 4px #fff, 0 0 8px #fff;
    pointer-events: none;
    transition: color .3s ease;
}
.ubl-pin:hover .ubl-pin__dot,
.ubl-pin.is-active .ubl-pin__dot { transform: translate(-50%, -50%) scale(1.2); }
.ubl-pin:hover .ubl-pin__halo,
.ubl-pin:focus-visible .ubl-pin__halo,
.ubl-pin.is-active .ubl-pin__halo { opacity: 1; transform: translate(-50%, -50%) scale(1); }
.ubl-pin.is-active .ubl-pin__name { color: var(--ubl-red-dark); }
.ubl-pin:focus-visible { outline: 3px solid color-mix(in srgb, var(--ubl-red) 55%, transparent); outline-offset: 10px; border-radius: 50%; }

@media (max-width: 639.98px) {
    .ubl-pin__dot { width: 12px; height: 12px; box-shadow: 0 0 0 3px #fff, 0 2px 6px rgba(0,0,0,.35); }
    .ubl-pin__halo { width: 52px; height: 52px; }
    .ubl-pin__name { font-size: .6rem; transform: translate(-50%, 12px); }
}

.ubl-coverage__side { order: -1; }
.ubl-warehouses {
    list-style: none;
    padding: 0;
    margin: 0 0 1.25rem;
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: .75rem;
}
.ubl-warehouses > li { display: flex; }
.ubl-warehouse {
    display: grid;
    grid-template-columns: auto 1fr;
    align-content: start;
    gap: .2rem .85rem;
    width: 100%;
    padding: .9rem 1rem 1rem;
    border: 0;
    border-top: 3px solid var(--ubl-gray-200);
    background: var(--ubl-gray-50);
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
    opacity: .6;
    transition: opacity .25s ease, border-color .25s ease, box-shadow .25s ease, background-color .25s ease;
}
.ubl-warehouse:hover { opacity: 1; }
.ubl-section--gray .ubl-warehouse { background: #fff; }
.ubl-warehouse.is-active { opacity: 1; border-top-color: var(--ubl-red); background: #fff; box-shadow: 0 10px 24px -16px rgba(0, 0, 0, .35); }
.ubl-warehouse__num {
    font-family: var(--ubl-font-display);
    font-size: .8rem;
    font-weight: 700;
    color: var(--ubl-red);
    letter-spacing: .08em;
    padding-top: .2rem;
}
.ubl-warehouse__body { display: flex; flex-direction: column; min-height: 100%; }
.ubl-warehouse:focus-visible { outline: 3px solid color-mix(in srgb, var(--ubl-red) 45%, transparent); outline-offset: 2px; }
.ubl-warehouse__name { display: block; font-family: var(--ubl-font-display); font-size: 1.05rem; font-weight: 700; color: var(--ubl-ink); margin: 0 0 .15rem; }
.ubl-warehouse__place { display: block; font-size: .8rem; color: var(--ubl-gray); margin: 0 0 .35rem; letter-spacing: .04em; text-transform: uppercase; }
.ubl-warehouse__detail { display: block; font-size: .88rem; color: var(--ubl-gray); line-height: 1.55; margin: 0; }
.ubl-warehouse.is-active .ubl-warehouse__place { color: var(--ubl-red); font-weight: 600; }
.ubl-coverage__ports {
    display: flex;
    gap: .6rem;
    align-items: flex-start;
    font-size: .9rem;
    line-height: 1.6;
    color: var(--ubl-ink);
    border-left: 3px solid var(--ubl-red);
    padding: .25rem 0 .25rem 1rem;
    margin: 0;
}
.ubl-coverage__ports .ubl-anchor { flex: none; color: var(--ubl-red); margin-top: .3em; }

@media (max-width: 767.98px) {
    .ubl-warehouses { grid-template-columns: 1fr; gap: .5rem; }
}

/* ===== Conectividad · Gran Santo Domingo ===== */

.ubl-connect__layout { display: grid; gap: clamp(1.75rem, 4vw, 2.75rem); }
.ubl-connect__layout > * { min-width: 0; }
.ubl-connect__side { order: -1; }
.ubl-connect__side .ubl-connect__list { margin-bottom: .75rem; }
.ubl-connect__map { margin: 0; }
.ubl-connect__scroll { border-radius: 14px; }
.ubl-connect__canvas { position: relative; }
.ubl-connect__stage { border-radius: 14px; overflow: hidden; box-shadow: 0 1px 0 var(--ubl-gray-200), 0 18px 40px -24px rgba(0, 0, 0, .35); }
.gsd-map { display: block; width: 100%; height: auto; }
.gsd-land { fill: #F4F2EF; }
.gsd-sea { fill: #DCE4EB; }
.gsd-rivers path { fill: none; stroke: #C5D2DE; stroke-width: 1.6px; vector-effect: non-scaling-stroke; stroke-linecap: round; }
.gsd-roads path, .gsd-runways path, .gsd-circ path { fill: none; vector-effect: non-scaling-stroke; stroke-linecap: round; stroke-linejoin: round; }
.gsd-roads--minor path { stroke: #DDD7D0; stroke-width: 1px; }
.gsd-roads--major path { stroke: #BFB8B0; stroke-width: 2px; }
.gsd-runways path { stroke: #BFB8B0; stroke-width: 3px; }
.gsd-circ path { stroke: var(--ubl-red); stroke-opacity: .16; stroke-width: 4px; }
.gsd-areas text { font-family: var(--ubl-font-sans); font-size: 13px; font-weight: 600; letter-spacing: 2px; fill: #A9A096; text-anchor: middle; }

.gsd-route { fill: none; stroke: var(--ubl-red); stroke-width: 2.5; stroke-opacity: .1; stroke-linecap: round; stroke-linejoin: round; transition: stroke-opacity .3s ease; }
.gsd-route.is-active {
    stroke-width: 6.5;
    stroke-opacity: 1;
    stroke-dasharray: 1;
    animation: gsd-draw 1.5s var(--ubl-ease) both;
}
@keyframes gsd-draw { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }

.ubl-connect__pins { position: absolute; inset: 0; bottom: auto; aspect-ratio: 1600 / 736; pointer-events: none; }
.ubl-connect__credit { margin-top: .4rem; font-size: .68rem; color: var(--ubl-gray); text-align: right; }

.ubl-connect__origin { position: absolute; width: 0; height: 0; z-index: 3; }
.ubl-connect__origin-dot,
.ubl-connect__origin-halo,
.ubl-connect__origin-name { position: absolute; left: 0; top: 0; }
.ubl-connect__origin-dot {
    width: 22px; height: 22px; border-radius: 50%;
    background: var(--ubl-red);
    box-shadow: 0 0 0 4px #fff, 0 3px 10px rgba(0, 0, 0, .35);
    transform: translate(-50%, -50%);
}
.ubl-connect__origin-halo {
    width: 70px; height: 70px; border-radius: 50%;
    background: rgba(var(--ubl-red-rgb), .18);
    transform: translate(-50%, -50%);
    animation: gsd-pulse 2.4s ease-out infinite;
}
@keyframes gsd-pulse { 0% { transform: translate(-50%, -50%) scale(.45); opacity: 1; } 100% { transform: translate(-50%, -50%) scale(1.25); opacity: 0; } }
.ubl-connect__origin-name {
    transform: translate(22px, -50%);
    white-space: nowrap;
    font-family: var(--ubl-font-display);
    font-size: 1.05rem;
    font-weight: 800;
    color: var(--ubl-red);
    text-shadow: 0 0 4px #fff, 0 0 4px #fff, 0 0 10px #fff;
}

.ubl-dest {
    position: absolute;
    width: 0; height: 0; padding: 0; border: 0; background: none;
    cursor: pointer;
    pointer-events: auto;
    z-index: 2;
}
.ubl-dest.is-active { z-index: 4; }
.ubl-dest__icon,
.ubl-dest__halo,
.ubl-dest__label { position: absolute; left: 0; top: 0; }
.ubl-dest__icon {
    display: grid; place-items: center;
    width: 46px; height: 46px; border-radius: 50%;
    background: #fff;
    color: var(--ubl-red);
    border: 3px solid var(--ubl-red);
    font-size: 1.3rem;
    box-shadow: 0 4px 12px rgba(0, 0, 0, .22);
    transform: translate(-50%, -50%);
    transition: transform .35s var(--ubl-ease), background-color .25s ease, color .25s ease;
}
.ubl-dest__halo {
    width: 84px; height: 84px; border-radius: 50%;
    background: rgba(var(--ubl-red-rgb), .16);
    opacity: 0;
    transform: translate(-50%, -50%) scale(.4);
    transition: opacity .35s ease, transform .45s var(--ubl-ease);
}
.ubl-dest__label {
    display: grid; justify-items: center;
    transform: translate(-50%, 30px);
    white-space: nowrap;
    pointer-events: none;
    text-shadow: 0 0 4px #F4F2EF, 0 0 4px #F4F2EF, 0 0 10px #F4F2EF;
}
.ubl-dest.is-label-above .ubl-dest__label { transform: translate(-50%, calc(-100% - 30px)); }
.ubl-dest__name { font-family: var(--ubl-font-display); font-size: .86rem; font-weight: 700; color: var(--ubl-ink); }
.ubl-dest__meta {
    font-size: .8rem; font-weight: 700; color: var(--ubl-red);
    max-height: 0; opacity: 0; overflow: hidden;
    transition: opacity .3s ease, max-height .3s ease;
}
.ubl-dest:hover .ubl-dest__icon,
.ubl-dest:focus-visible .ubl-dest__icon { transform: translate(-50%, -50%) scale(1.08); }
.ubl-dest.is-active .ubl-dest__icon { background: var(--ubl-red); color: #fff; transform: translate(-50%, -50%) scale(1.12); }
.ubl-dest.is-active .ubl-dest__halo { opacity: 1; transform: translate(-50%, -50%) scale(1); }
.ubl-dest.is-active .ubl-dest__meta { max-height: 1.4em; opacity: 1; }
.ubl-dest:focus-visible { outline: none; }
.ubl-dest:focus-visible .ubl-dest__icon { outline: 3px solid color-mix(in srgb, var(--ubl-red) 55%, transparent); outline-offset: 4px; }

.ubl-connect__from {
    display: flex; align-items: center; gap: .45rem;
    margin: 0 0 1rem;
    font-family: var(--ubl-font-display); font-size: .8rem; font-weight: 700;
    letter-spacing: .08em; text-transform: uppercase; color: var(--ubl-red);
}
.ubl-connect__group + .ubl-connect__group { margin-top: .5rem; }
.ubl-connect__group-title {
    display: flex; align-items: center; gap: .5rem;
    font-size: .8rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
    color: var(--ubl-gray); margin: 0 0 .25rem;
}
.ubl-connect__group-title span { display: inline-flex; color: var(--ubl-red); font-size: 1rem; }
.ubl-anchor { width: 1em; height: 1em; }
.ubl-connect__list {
    list-style: none; padding: 0; margin: .4rem 0 1.25rem;
    display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .75rem;
}
.ubl-connect__list > li { display: flex; }
.ubl-connect__card {
    display: grid; gap: .3rem;
    width: 100%;
    text-align: left;
    align-content: start;
    padding: .9rem 1rem 1rem;
    border: 0;
    border-top: 3px solid var(--ubl-gray-200);
    background: var(--ubl-gray-50);
    color: inherit;
    font: inherit;
    cursor: pointer;
    opacity: .6;
    transition: opacity .25s ease, border-color .25s ease, background-color .25s ease;
}
div.ubl-connect__card { cursor: default; }
.ubl-section--gray .ubl-connect__card { background: #fff; }
.ubl-connect__card:hover,
.ubl-connect__card:focus-visible { opacity: 1; }
.ubl-connect__card.is-active { opacity: 1; border-top-color: var(--ubl-red); box-shadow: 0 10px 24px -16px rgba(0, 0, 0, .35); }
.ubl-connect__card-name { font-family: var(--ubl-font-display); font-size: 1.05rem; font-weight: 700; color: var(--ubl-ink); }
.ubl-connect__card-meta { display: flex; flex-wrap: wrap; gap: .35rem 1.1rem; font-size: .9rem; color: var(--ubl-gray); }
.ubl-connect__card.is-active .ubl-connect__card-meta { color: var(--ubl-red); font-weight: 600; }
.ubl-connect__card-meta i { margin-right: .2rem; }

.ubl-maplink {
    display: inline-flex; align-items: center; gap: .4rem;
    align-self: flex-start;
    margin-top: auto;
    padding: .3rem .7rem .3rem .55rem;
    border-radius: 999px;
    border: 1px solid rgba(var(--ubl-red-rgb), .25);
    font-size: .74rem; font-weight: 700; letter-spacing: .03em;
    color: var(--ubl-red);
    background: rgba(var(--ubl-red-rgb), .04);
    transition: background-color .25s ease, color .25s ease, border-color .25s ease;
}
.ubl-warehouse__body .ubl-maplink { margin-top: .75rem; }
.ubl-connect__card .ubl-maplink { margin-top: .35rem; }
.ubl-maplink i { font-size: .85rem; transition: transform .3s var(--ubl-ease); }
.ubl-warehouse:hover .ubl-maplink, .ubl-connect__card:hover .ubl-maplink,
.ubl-warehouse:focus-visible .ubl-maplink, .ubl-connect__card:focus-visible .ubl-maplink { background: var(--ubl-red); border-color: var(--ubl-red); color: #fff; }
.ubl-warehouse:hover .ubl-maplink i, .ubl-connect__card:hover .ubl-maplink i { transform: translateY(2px); }
.ubl-warehouse.is-active .ubl-maplink, .ubl-connect__card.is-active .ubl-maplink { border-color: rgba(var(--ubl-red-rgb), .45); }

@media (max-width: 991.98px) {
    .gsd-route { stroke-width: 5; }
    .gsd-route.is-active { stroke-width: 11; }
}
@media (max-width: 767.98px) {
    .ubl-connect__scroll { overflow-x: auto; scrollbar-width: thin; padding-bottom: .35rem; }
    .ubl-connect__canvas { width: 680px; }
    .ubl-connect__list { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .5rem; }
    .ubl-connect__card { padding: .75rem .75rem .85rem; }
    .ubl-connect__card-name { font-size: .95rem; }
    .ubl-connect__card-meta { font-size: .8rem; gap: .2rem .7rem; }
    .gsd-areas { display: none; }
    .gsd-route { stroke-width: 7; }
    .gsd-route.is-active { stroke-width: 16; }
    .ubl-dest__icon { width: 32px; height: 32px; font-size: .9rem; border-width: 2px; }
    .ubl-dest__halo { width: 56px; height: 56px; }
    .ubl-dest__label { display: none; }
    .ubl-connect__origin-dot { width: 15px; height: 15px; box-shadow: 0 0 0 3px #fff, 0 2px 6px rgba(0, 0, 0, .35); }
    .ubl-connect__origin-halo { width: 46px; height: 46px; }
    .ubl-connect__origin-name { font-size: .75rem; transform: translate(14px, -50%); }
}
@media (prefers-reduced-motion: reduce) {
    .gsd-route.is-active { animation: none; }
    .ubl-connect__origin-halo { animation: none; opacity: .6; }
}

/* ===== Seguridad ===== */

.ubl-security__stats {
    list-style: none; padding: 0; margin: 0 0 clamp(2.5rem, 5vw, 3.75rem);
    display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(1rem, 3vw, 2.5rem);
}
.ubl-security__stat { display: grid; gap: .6rem; justify-items: center; text-align: center; }
.ubl-security__value {
    font-family: var(--ubl-font-display);
    font-size: clamp(2.6rem, 5.2vw, 4.2rem);
    font-weight: 700;
    line-height: 1;
    letter-spacing: -.02em;
    color: var(--ubl-ink);
}
.ubl-security__pill {
    display: block;
    width: 100%;
    padding: .7rem 1.25rem;
    border-radius: 999px;
    text-align: center;
    font-family: var(--ubl-font-display);
    font-size: clamp(.7rem, 1vw, .82rem);
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    background: var(--ubl-gray-200);
    color: var(--ubl-black);
}
.ubl-security__stat:nth-child(2) .ubl-security__value { color: var(--ubl-red); }
.ubl-security__stat:nth-child(2) .ubl-security__pill { background: #2B2B2B; color: #fff; }
.ubl-security__stat:nth-child(3) .ubl-security__value { color: var(--ubl-black); }
.ubl-security__stat:nth-child(3) .ubl-security__pill { background: var(--ubl-red); color: #fff; }

.ubl-security__md {
    display: grid;
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    gap: clamp(1rem, 2.5vw, 2rem);
    align-items: stretch;
}
.ubl-security__tabs { display: grid; gap: .5rem; align-content: start; }
.ubl-security__tab {
    display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: .9rem;
    width: 100%;
    padding: .8rem 1rem;
    border: 1px solid var(--ubl-gray-200);
    border-radius: 16px;
    background: #fff;
    color: var(--ubl-ink);
    font: inherit;
    text-align: left;
    cursor: pointer;
    transition: background-color .25s ease, border-color .25s ease, color .25s ease, transform .25s var(--ubl-ease), box-shadow .25s ease;
}
.ubl-security__tab:hover { border-color: rgba(var(--ubl-red-rgb), .35); transform: translateX(3px); }
.ubl-security__tab:focus-visible { outline: 3px solid color-mix(in srgb, var(--ubl-red) 45%, transparent); outline-offset: 2px; }
.ubl-security__tab-icon {
    display: grid; place-items: center;
    width: 42px; aspect-ratio: 1; border-radius: 12px;
    background: rgba(var(--ubl-red-rgb), .08);
    color: var(--ubl-red);
    font-size: 1.15rem;
    transition: background-color .25s ease, color .25s ease;
}
.ubl-security__tab-title { font-size: .84rem; font-weight: 700; letter-spacing: .04em; line-height: 1.35; text-transform: uppercase; }
.ubl-security__tab-arrow { color: var(--ubl-gray-300); transition: transform .25s var(--ubl-ease), color .25s ease; }
.ubl-security__tab.is-active {
    background: var(--ubl-red);
    border-color: var(--ubl-red);
    color: #fff;
    box-shadow: 0 14px 28px -18px rgba(var(--ubl-red-rgb), .9);
    transform: none;
}
.ubl-security__tab.is-active .ubl-security__tab-icon { background: rgba(255, 255, 255, .16); color: #fff; }
.ubl-security__tab.is-active .ubl-security__tab-arrow { color: #fff; transform: translateX(3px); }

.ubl-security__panels { position: relative; display: grid; }
.ubl-security__panel {
    position: relative;
    overflow: hidden;
    isolation: isolate;
    padding: clamp(1.5rem, 3vw, 2.5rem);
    border-radius: 24px;
    background: var(--ubl-gray-50);
    border: 1px solid var(--ubl-gray-200);
}
.ubl-section--gray .ubl-security__panel { background: #fff; }
.ubl-security__panels.is-js .ubl-security__panel { grid-area: 1 / 1; opacity: 0; visibility: hidden; transform: translateY(8px); transition: opacity .35s ease, transform .45s var(--ubl-ease), visibility 0s linear .35s; }
.ubl-security__panels.is-js .ubl-security__panel.is-active { opacity: 1; visibility: visible; transform: none; transition: opacity .35s ease, transform .45s var(--ubl-ease), visibility 0s; }
.ubl-security__panels:not(.is-js) { gap: 1rem; }
.ubl-security__panel-mark {
    position: absolute; right: -.1em; bottom: -.18em; z-index: -1;
    font-size: clamp(9rem, 16vw, 14rem); line-height: 1;
    color: var(--ubl-red); opacity: .05;
    transform: rotate(-10deg);
    pointer-events: none;
}
.ubl-security__panel-count {
    margin: 0 0 1.25rem;
    font-family: var(--ubl-font-display); font-size: .78rem; font-weight: 700; letter-spacing: .14em;
    color: var(--ubl-gray);
}
.ubl-security__panel-head { display: flex; align-items: center; gap: 1rem; margin-bottom: 1.5rem; }
.ubl-security__icon {
    display: grid; place-items: center; flex: none;
    width: 60px; aspect-ratio: 1;
    border-radius: 16px;
    background: var(--ubl-red);
    color: #fff;
    font-size: 1.6rem;
    box-shadow: 0 12px 24px -10px rgba(var(--ubl-red-rgb), .55);
}
.ubl-security__title {
    margin: 0;
    font-size: clamp(1.15rem, 1.8vw, 1.45rem);
    font-weight: 700;
    line-height: 1.25;
    color: var(--ubl-black);
}
.ubl-security__points {
    list-style: none; padding: 0; margin: 0;
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .75rem 1.5rem;
}
.ubl-security__points li { display: flex; align-items: flex-start; gap: .6rem; font-size: .95rem; line-height: 1.45; color: var(--ubl-ink); }
.ubl-security__points li i {
    flex: none;
    display: grid; place-items: center;
    width: 22px; height: 22px; border-radius: 50%;
    background: rgba(var(--ubl-red-rgb), .1);
    color: var(--ubl-red);
    font-size: .85rem;
    margin-top: .05rem;
}

@media (max-width: 991.98px) {
    .ubl-security__md { grid-template-columns: 1fr; }
    .ubl-security__tabs {
        display: flex; gap: .5rem;
        overflow-x: auto; scrollbar-width: none;
        padding-bottom: .25rem;
    }
    .ubl-security__tabs::-webkit-scrollbar { display: none; }
    .ubl-security__tab { flex: 0 0 auto; width: auto; grid-template-columns: auto auto; padding: .6rem .9rem .6rem .6rem; }
    .ubl-security__tab:hover { transform: none; }
    .ubl-security__tab-arrow { display: none; }
    .ubl-security__tab-title { white-space: nowrap; font-size: .76rem; }
    .ubl-security__tab-icon { width: 34px; font-size: 1rem; }
}
@media (max-width: 767.98px) {
    .ubl-security__stats { grid-template-columns: 1fr; gap: 1.25rem; }
    .ubl-security__stat { grid-template-columns: auto 1fr; align-items: center; justify-items: start; text-align: left; gap: 1rem; }
    .ubl-security__value { font-size: 2.4rem; min-width: 3.4ch; }
    .ubl-security__points { grid-template-columns: 1fr; }
}
@media (prefers-reduced-motion: reduce) {
    .ubl-security__panels.is-js .ubl-security__panel { transition: none; transform: none; }
}

/* ===== Servicios adicionales · bento ===== */

.ubl-extras__grid {
    list-style: none; padding: 0; margin: 0;
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    grid-auto-rows: minmax(210px, auto);
    gap: clamp(.9rem, 1.6vw, 1.25rem);
}
.ubl-extra {
    position: relative;
    overflow: hidden;
    isolation: isolate;
    display: flex; flex-direction: column; justify-content: space-between; gap: 1.5rem;
    padding: clamp(1.35rem, 2.2vw, 1.85rem);
    border-radius: 24px;
    background: #fff;
    border: 1px solid var(--ubl-gray-200);
    color: var(--ubl-ink);
    transition: transform .45s var(--ubl-ease), box-shadow .45s ease, border-color .3s ease;
}
.ubl-extra:hover { transform: translateY(-5px); box-shadow: 0 26px 50px -30px rgba(0, 0, 0, .45); }

.ubl-extra:nth-child(1) {
    grid-column: span 2; grid-row: span 2;
    background: radial-gradient(120% 90% at 100% 0%, #B8263F 0%, var(--ubl-red) 45%, var(--ubl-red-dark) 100%);
    border-color: transparent;
    color: #fff;
}
.ubl-extra:nth-child(2) { grid-column: span 2; background: var(--ubl-gray-50); }
.ubl-section--gray .ubl-extra:nth-child(2) { background: #fff; }
.ubl-extra:nth-child(3) { background: #232323; border-color: transparent; color: #fff; }
.ubl-extra:nth-child(4) { background: var(--ubl-gray-100); }

.ubl-extra__watermark {
    position: absolute;
    right: -.08em; bottom: -.2em;
    z-index: -1;
    font-size: clamp(7rem, 12vw, 10rem);
    line-height: 1;
    color: currentColor;
    opacity: .06;
    transform: rotate(-12deg);
    transition: transform .6s var(--ubl-ease), opacity .4s ease;
    pointer-events: none;
}
.ubl-extra:nth-child(1) .ubl-extra__watermark { font-size: clamp(13rem, 22vw, 19rem); opacity: .1; }
.ubl-extra:hover .ubl-extra__watermark { transform: rotate(-4deg) scale(1.06); opacity: .1; }
.ubl-extra:nth-child(1):hover .ubl-extra__watermark { opacity: .14; }

.ubl-extra__head { display: flex; align-items: center; gap: .85rem; }
.ubl-extra__icon {
    display: grid; place-items: center; flex: none;
    width: 46px; aspect-ratio: 1; border-radius: 14px;
    background: rgba(var(--ubl-red-rgb), .1);
    color: var(--ubl-red);
    font-size: 1.25rem;
}
.ubl-extra:nth-child(1) .ubl-extra__icon,
.ubl-extra:nth-child(3) .ubl-extra__icon { background: rgba(255, 255, 255, .14); color: #fff; }
.ubl-extra__title {
    margin: 0;
    font-size: .8rem; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
    color: inherit;
}

.ubl-extra__body { display: grid; gap: .85rem; }
.ubl-extra__figure { display: grid; gap: .35rem; margin: 0; }
.ubl-extra__value {
    font-family: var(--ubl-font-display);
    font-size: clamp(2.6rem, 4vw, 3.4rem);
    font-weight: 700;
    line-height: .95;
    letter-spacing: -.03em;
    color: var(--ubl-red);
}
.ubl-extra:nth-child(1) .ubl-extra__value { font-size: clamp(4.5rem, 9vw, 7.5rem); color: #fff; }
.ubl-extra:nth-child(3) .ubl-extra__value { color: var(--ubl-red-light); }
.ubl-extra__value-label { font-size: .95rem; font-weight: 600; opacity: .85; }
.ubl-extra:nth-child(1) .ubl-extra__value-label { font-size: clamp(1rem, 1.4vw, 1.2rem); }
.ubl-extra__text { margin: 0; max-width: 40ch; font-size: .95rem; line-height: 1.55; opacity: .85; }

.ubl-extra__chips { list-style: none; padding: 0; margin: .25rem 0 0; display: flex; flex-wrap: wrap; gap: .5rem; }
.ubl-extra__chips li {
    padding: .45rem .95rem;
    border-radius: 999px;
    font-size: .85rem; font-weight: 600;
    background: rgba(var(--ubl-red-rgb), .08);
    color: var(--ubl-red-dark);
}
.ubl-extra:nth-child(1) .ubl-extra__chips li,
.ubl-extra:nth-child(3) .ubl-extra__chips li {
    background: rgba(255, 255, 255, .14);
    color: #fff;
    border: 1px solid rgba(255, 255, 255, .22);
    backdrop-filter: blur(6px);
}

@media (max-width: 991.98px) {
    .ubl-extras__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); grid-auto-rows: minmax(190px, auto); }
    .ubl-extra:nth-child(1) { grid-column: span 2; grid-row: span 1; min-height: 300px; }
    .ubl-extra:nth-child(2) { grid-column: span 2; }
}
@media (max-width: 479.98px) {
    .ubl-extras__grid { grid-template-columns: 1fr; }
    .ubl-extra:nth-child(1), .ubl-extra:nth-child(2) { grid-column: auto; }
}
@media (prefers-reduced-motion: reduce) {
    .ubl-extra, .ubl-extra__watermark { transition: none; }
}

/* ===== Sostenibilidad ===== */

.ubl-sustain__layout {
    display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    gap: clamp(2rem, 6vw, 5rem); align-items: center;
}
.ubl-sustain__intro .ubl-section__lead { margin-bottom: 2rem; }
.ubl-sustain__cta { background: var(--ubl-black); color: #fff; }
.ubl-sustain__cta:hover { background: var(--ubl-red); color: #fff; transform: translateY(-2px); }

.ubl-sustain__path { position: relative; --ubl-wave-x: clamp(2.5rem, 7vw, 5.5rem); }
.ubl-sustain__wave { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; }
.ubl-sustain__wave path {
    fill: none;
    stroke: rgba(var(--ubl-red-rgb), .13);
    stroke-width: 44;
    stroke-linecap: round;
    stroke-linejoin: round;
}
.ubl-sustain__list { position: relative; list-style: none; padding: 0; margin: 0; display: grid; gap: clamp(1.4rem, 2.6vw, 2rem); }
.ubl-sustain__item {
    display: grid; grid-template-columns: auto 1fr; align-items: center; gap: 1rem;
    margin-left: calc(var(--ubl-wave, 0) * var(--ubl-wave-x));
}
.ubl-sustain__node {
    display: grid; place-items: center;
    width: 52px; aspect-ratio: 1; border-radius: 50%;
    background: #fff;
    border: 2.5px solid var(--ubl-red);
    color: var(--ubl-red);
    font-size: 1.3rem;
    box-shadow: 0 6px 16px -8px rgba(0, 0, 0, .35);
    transition: transform .35s var(--ubl-ease), background-color .25s ease, color .25s ease;
}
.ubl-sustain__item:hover .ubl-sustain__node { transform: scale(1.1); background: var(--ubl-red); color: #fff; }
.ubl-sustain__title { margin: 0; font-size: 1.02rem; font-weight: 700; color: var(--ubl-black); }
.ubl-sustain__detail { margin: .15rem 0 0; font-size: .88rem; color: var(--ubl-gray); line-height: 1.5; }

@media (max-width: 991.98px) {
    .ubl-sustain__layout { grid-template-columns: 1fr; }
    .ubl-sustain__path { --ubl-wave-x: clamp(1.5rem, 8vw, 3rem); }
}
@media (max-width: 479.98px) {
    .ubl-sustain__wave path { stroke-width: 34; }
    .ubl-sustain__node { width: 44px; font-size: 1.1rem; }
}

/* ===== Ley 30-24 · anillo EOL ===== */

/* La diagonal es el recurso de composición del deck. Acá entra como un lavado
   rojo muy bajo detrás de la sección: da profundidad sin meter un color nuevo
   ni otro bloque oscuro (el contacto ya venía inmediatamente después). */
.ubl-eol { position: relative; overflow: hidden; }
.ubl-eol::before {
    content: '';
    position: absolute;
    top: -20%;
    right: -14%;
    width: 60%;
    height: 140%;
    background: linear-gradient(135deg, rgba(var(--ubl-red-rgb), .07), rgba(var(--ubl-red-rgb), 0) 62%);
    transform: skewX(-12deg);
    pointer-events: none;
}
.ubl-eol > .container { position: relative; }

.ubl-eol__intro { max-width: 56ch; margin-bottom: clamp(2rem, 4vw, 3.5rem); }

.ubl-eol__wheel {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: clamp(1.5rem, 3vw, 3rem);
}
.ubl-eol__col { display: flex; flex-direction: column; justify-content: space-between; gap: clamp(1.75rem, 3vw, 3rem); }

.ubl-eol__item { cursor: default; transition: transform .35s var(--ubl-ease); }
.ubl-eol__item--left { text-align: right; }
.ubl-eol__item--right { text-align: left; }
.ubl-eol__item-title {
    font-size: clamp(1rem, 1.25vw, 1.2rem);
    margin: 0 0 .5rem;
    transition: color .3s ease;
}
.ubl-eol__item-text {
    color: var(--ubl-gray);
    font-size: .93rem;
    line-height: 1.65;
    margin: 0;
    max-width: 34ch;
    transition: color .3s ease;
}
.ubl-eol__item--left .ubl-eol__item-text { margin-left: auto; }

/* Pareja resaltada: el JS marca a la vez la porción y su bloque de texto, así
   que da igual por cuál de los dos entre el puntero. */
.ubl-eol__item.is-active .ubl-eol__item-title { color: var(--ubl-red); }
.ubl-eol__item.is-active .ubl-eol__item-text { color: var(--ubl-ink); }
.ubl-eol__item--left.is-active { transform: translateX(-6px); }
.ubl-eol__item--right.is-active { transform: translateX(6px); }

.ubl-eol__donut {
    position: relative;
    width: clamp(280px, 32vw, 440px);
    aspect-ratio: 1;
    flex: none;
}
.ubl-eol__svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }

/* Rojo y negro alternados, como en la lámina. Con un número impar de ítems la
   alternancia se corta en la última porción; es el único caso y se prefiere
   eso a repintar el anillo entero. */
.ubl-eol__slice {
    fill: var(--ubl-ink);
    cursor: pointer;
    transform-origin: center;
    transition: transform .4s var(--ubl-ease), fill .3s ease, filter .3s ease;
}
.ubl-eol__slice:nth-of-type(odd) { fill: var(--ubl-red); }
.ubl-eol__slice.is-active {
    transform: translate(calc(var(--ubl-dx) * 1px), calc(var(--ubl-dy) * 1px));
    filter: drop-shadow(0 6px 16px rgba(0, 0, 0, .28));
}
.ubl-eol__slice.is-active { fill: var(--ubl-black); }
.ubl-eol__slice:nth-of-type(odd).is-active { fill: var(--ubl-red-dark); }

.ubl-eol__hub-bg { fill: var(--ubl-red); }

/* Los iconos van en HTML encima del SVG: bootstrap-icons es una fuente y no
   entra en un <svg> sin foreignObject. El translate replica el del hover de su
   porción para que salgan juntos. */
.ubl-eol__ico {
    position: absolute;
    transform: translate(-50%, -50%);
    color: #fff;
    font-size: clamp(1.1rem, 2.4vw, 1.75rem);
    line-height: 1;
    pointer-events: none;
    transition: transform .4s var(--ubl-ease);
}
.ubl-eol__ico.is-active {
    transform: translate(-50%, -50%) translate(calc(var(--ubl-dx) * 1%), calc(var(--ubl-dy) * 1%)) scale(1.12);
}

.ubl-eol__hub {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    width: 40%;
    text-align: center;
    font-family: var(--ubl-font-display);
    font-size: clamp(.72rem, 1.1vw, .95rem);
    font-weight: 700;
    letter-spacing: .08em;
    color: #fff;
    pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
    .ubl-eol__slice, .ubl-eol__ico, .ubl-eol__item { transition: none; }
    .ubl-eol__slice.is-active, .ubl-eol__ico.is-active, .ubl-eol__item.is-active { transform: none; }
    .ubl-eol__ico.is-active { transform: translate(-50%, -50%); }
}

/* Debajo de 992px las columnas laterales no caben al lado del anillo: el
   gráfico pasa arriba y los seis textos bajan a una sola columna. Como todos
   están visibles siempre, no se pierde nada al reordenar. */
@media (max-width: 991.98px) {
    .ubl-eol__wheel { grid-template-columns: 1fr; justify-items: center; }
    .ubl-eol__donut { order: -1; width: min(82vw, 380px); }
    .ubl-eol__col { width: 100%; }
    .ubl-eol__item--left, .ubl-eol__item--right { text-align: left; }
    .ubl-eol__item--left .ubl-eol__item-text { margin-left: 0; }
    .ubl-eol__item-text { max-width: none; }
    .ubl-eol__item--left.is-active, .ubl-eol__item--right.is-active { transform: translateX(4px); }
}

/* ===== Clientes y certificaciones ===== */

.ubl-marquee {
    position: relative;
    overflow: hidden;
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
            mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.ubl-marquee__track {
    display: flex;
    align-items: center;
    width: max-content;
    animation: ubl-marquee var(--ubl-marquee-duration, 40s) linear infinite;
}
.ubl-marquee:hover .ubl-marquee__track { animation-play-state: paused; }
.ubl-marquee__item {
    flex: 0 0 auto;
    display: flex; align-items: center; justify-content: center;
    padding: 0 clamp(1.75rem, 4vw, 3.25rem);
}
.ubl-marquee__item img {
    height: clamp(48px, 5.5vw, 78px);
    width: auto;
    max-width: 220px;
    object-fit: contain;
    opacity: .85;
    transition: transform .3s ease, opacity .3s ease;
}
.ubl-marquee__item:hover img { transform: scale(1.06); opacity: 1; }
@keyframes ubl-marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }
@media (prefers-reduced-motion: reduce) {
    .ubl-marquee { -webkit-mask-image: none; mask-image: none; }
    .ubl-marquee__track { animation: none; flex-wrap: wrap; justify-content: center; width: 100%; row-gap: 1.5rem; }
    .ubl-marquee__item[aria-hidden="true"] { display: none; }
}
#certificaciones .ubl-certs { margin-top: 0; padding-top: 0; border-top: 0; }
.ubl-certs {
    display: grid;
    grid-template-columns: 1.4fr .6fr;
    gap: clamp(1.5rem, 4vw, 3.5rem);
    align-items: center;
    margin-top: clamp(2.5rem, 5vw, 4rem);
    padding-top: clamp(2rem, 4vw, 3rem);
    border-top: 1px solid var(--ubl-gray-200);
}
.ubl-certs__title { font-size: clamp(1.4rem, 2.4vw, 2rem); margin: 0 0 1rem; }
.ubl-certs__text { color: var(--ubl-gray); line-height: 1.75; margin: 0 0 .85rem; max-width: 62ch; }
.ubl-certs__text:last-child { margin-bottom: 0; }
.ubl-certs__list { display: flex; flex-wrap: wrap; gap: clamp(1.25rem, 2.5vw, 2rem); align-items: center; }
/* Los sellos traen su propia bajada de texto (BASC, "Operador Económico
   Autorizado"): por debajo de ~100px dejan de leerse. */
.ubl-certs__logo { max-height: 104px; max-width: 170px; width: auto; height: auto; }
/* Sello de respaldo mientras no haya logo cargado en el panel. */
.ubl-certs__seal {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 5.5rem;
    padding: .9rem 1.3rem;
    border: 2px solid var(--ubl-red);
    border-radius: 999px;
    font-family: var(--ubl-font-display);
    font-size: 1rem;
    font-weight: 700;
    letter-spacing: .12em;
    color: var(--ubl-red);
}
@media (max-width: 767.98px) {
    .ubl-certs { grid-template-columns: 1fr; }
}

/* ===== Contacto ===== */

.ubl-contact-data { margin: 2rem 0 0; }
.ubl-contact-data dt { font-size: .72rem; letter-spacing: .18em; text-transform: uppercase; color: var(--ubl-red); margin-top: 1.25rem; }
.ubl-contact-data dd { margin: .25rem 0 0; color: var(--ubl-ink); }

/* El formulario lo arma el módulo Forms con clases de Bootstrap; el tema no
   toca ese markup, solo lo reviste desde acá. Por eso todo cuelga de .ubl-form,
   que es la clase que el partial recibe como `extra_class`. */
.ubl-form {
    background: #fff;
    border: 1px solid var(--ubl-gray-200);
    border-top: 3px solid var(--ubl-red);
    padding: clamp(1.5rem, 3vw, 2.25rem);
    box-shadow: 0 24px 60px rgba(0, 0, 0, .06);
}
.ubl-form .form-label {
    font-family: var(--ubl-font-display);
    font-size: .7rem;
    font-weight: 700;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--ubl-gray);
    margin-bottom: .4rem;
}
.ubl-form .form-label .text-danger { color: var(--ubl-red) !important; }
.ubl-form .form-control,
.ubl-form .form-select {
    border-radius: 2px;
    border: 1px solid var(--ubl-gray-200);
    background: var(--ubl-gray-50);
    padding: .75rem .9rem;
    font-size: .95rem;
    color: var(--ubl-ink);
    transition: background-color .25s ease, border-color .25s ease, box-shadow .25s ease;
}
.ubl-form .form-control::placeholder { color: var(--ubl-gray-300); }
.ubl-form .form-control:focus,
.ubl-form .form-select:focus {
    background: #fff;
    border-color: var(--ubl-red);
    box-shadow: 0 0 0 3px rgba(var(--ubl-red-rgb), .12);
}
.ubl-form textarea.form-control { min-height: 8rem; resize: vertical; }

/* El botón lo emite el módulo como .btn-primary: se reviste con las propias
   variables de Bootstrap para que quede igual al .ubl-btn--primary del tema. */
.ubl-form .btn-primary {
    --bs-btn-bg: var(--ubl-red);
    --bs-btn-border-color: var(--ubl-red);
    --bs-btn-hover-bg: var(--ubl-red-dark);
    --bs-btn-hover-border-color: var(--ubl-red-dark);
    --bs-btn-active-bg: var(--ubl-red-dark);
    --bs-btn-active-border-color: var(--ubl-red-dark);
    --bs-btn-disabled-bg: var(--ubl-gray-300);
    --bs-btn-disabled-border-color: var(--ubl-gray-300);
    --bs-btn-focus-shadow-rgb: var(--ubl-red-rgb);
    --bs-btn-border-radius: 999px;
    --bs-btn-padding-x: 1.7rem;
    --bs-btn-padding-y: .8rem;
    --bs-btn-font-family: var(--ubl-font-display);
    --bs-btn-font-size: .92rem;
    --bs-btn-font-weight: 700;
    transition: transform .25s var(--ubl-ease);
}
.ubl-form .btn-primary:hover { transform: translateY(-2px); }
.ubl-form .alert { border-radius: 2px; }
.ubl-form .form-errors:empty { display: none; }

/* ===== Páginas sueltas y errores ===== */

.ubl-page-hero { background: var(--ubl-ink); color: #fff; padding: calc(var(--ubl-nav-h) + 2rem) 0 2.5rem; }
.ubl-page-hero__title { color: #fff; font-size: clamp(1.9rem, 4vw, 3rem); margin: 0; }
.ubl-prose { max-width: 70ch; line-height: 1.8; }
.ubl-notfound { text-align: center; }

/* ===== Footer ===== */

.ubl-footer { background: var(--ubl-black); color: rgba(255,255,255,.75); padding: clamp(2.5rem, 5vw, 4rem) 0 1.5rem; }
.ubl-footer__logo { display: block; height: 42px; width: auto; }
.ubl-footer__tagline { margin: .75rem 0 1rem; font-size: .92rem; line-height: 1.6; }
.ubl-footer__title { font-size: .72rem; letter-spacing: .18em; text-transform: uppercase; color: #fff; margin: 0 0 .5rem; }
.ubl-footer__text { font-size: .92rem; line-height: 1.6; margin: 0; }
.ubl-footer__link { color: var(--ubl-red); font-size: .9rem; text-decoration: none; }
.ubl-footer__social { display: flex; gap: .75rem; font-size: 1.15rem; }
.ubl-footer__social a { color: rgba(255,255,255,.7); }
.ubl-footer__social a:hover { color: #fff; }
.ubl-footer__menu { list-style: none; display: flex; flex-wrap: wrap; gap: 1.25rem; padding: 0; margin: 2rem 0 0; }
.ubl-footer__menu a { color: rgba(255,255,255,.7); font-size: .88rem; text-decoration: none; }
.ubl-footer__bottom {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    margin-top: 2rem;
    padding-top: 1.25rem;
    border-top: 1px solid rgba(255, 255, 255, .12);
}
.ubl-footer__copy { margin: 0; font-size: .82rem; }

/* El selector se repite en el footer, que es oscuro: se invierte el botón. */
.ubl-footer .ubl-lang__toggle { color: rgba(255, 255, 255, .85); border-color: rgba(255, 255, 255, .25); }
.ubl-footer .ubl-lang__toggle:hover { background: #fff; color: var(--ubl-red); border-color: #fff; }

/* ===== Motion ===== */

/* El estado oculto se aplica SOLO si el JS confirmó que puede animar (clase en
   <html>). Si el script falla o el observer nunca dispara, el contenido se ve
   igual: antes dependía de JS para ser visible, que es al revés de lo que conviene. */
/* El estado oculto se declara sobre `:not(.is-visible)` y el visible no declara
   transform en absoluto. Si el visible lo fijara en `none`, esa regla le ganaría
   por especificidad al `:hover` de cada tarjeta y la elevación nunca ocurriría
   (pasaba en servicios y en el ADN). Así, una vez revelado, el elemento vuelve
   a su transform por defecto y cada componente manda sobre el suyo. */
.ubl-js .ubl-reveal {
    transition: opacity .8s var(--ubl-ease), transform .8s var(--ubl-ease);
    transition-delay: var(--reveal-delay, 0ms);
}
.ubl-js .ubl-reveal:not(.is-visible) {
    opacity: 0;
    transform: translateY(44px) scale(.97);
}

/* Variantes direccionales: cada bloque entra desde el lado que ocupa en la
   grilla, así el movimiento acompaña la lectura en vez de cruzarla. */
.ubl-js .ubl-reveal--left:not(.is-visible) { transform: translateX(-52px); }
.ubl-js .ubl-reveal--right:not(.is-visible) { transform: translateX(52px); }

@media (prefers-reduced-motion: reduce) {
    .ubl-reveal { opacity: 1; transform: none; transition: none; }
    .ubl-btn, .ubl-pin, .ubl-service, .ubl-adn__item, .ubl-lang__toggle { transition: none; }
    .ubl-service:hover, .ubl-adn__item:hover, .ubl-form .btn-primary:hover { transform: none; }
}

/* ===== Navbar toggler ===== */

/* El icono de hamburguesa de Bootstrap es oscuro: sobre el hero, con el header
   transparente, quedaba invisible. */
.ubl-navbar .navbar-toggler { border-color: rgba(0, 0, 0, .18); padding: .35rem .5rem; }
.ubl-navbar .navbar-toggler:focus { box-shadow: 0 0 0 .2rem color-mix(in srgb, var(--ubl-red) 28%, transparent); }
body.ubl-over-hero .ubl-header:not(.is-scrolled) .navbar-toggler { border-color: rgba(255, 255, 255, .55); }
body.ubl-over-hero .ubl-header:not(.is-scrolled) .navbar-toggler-icon { filter: invert(1) brightness(2); }

/* ===== Marco del deck ===== */

/* Barra roja superior: en el PDF cruza las 13 láminas. En una web de scroll
   continuo repetirla por sección se vería raro, así que va una sola vez arriba. */
.ubl-topbar {
    position: fixed;
    inset: 0 0 auto 0;
    z-index: 1040;
    height: var(--ubl-topbar-h);
    background: var(--ubl-red);
}

/* Con sesión abierta el CMS inyecta su barra de administración fija arriba. Su
   middleware empuja los headers de una lista de clases que no incluye las de
   este tema, y tampoco podría: son dos elementos fijos apilados. Se resuelve
   acá, que es donde se sabe el orden. */
body.cms-has-admin-bar .ubl-topbar { top: var(--cms-admin-bar-height, 46px); }
body.cms-has-admin-bar .ubl-header { top: calc(var(--cms-admin-bar-height, 46px) + var(--ubl-topbar-h)); }
body.cms-has-admin-bar.ubl-solid-nav {
    padding-top: calc(var(--cms-admin-bar-height, 46px) + var(--ubl-nav-h) + var(--ubl-topbar-h)) !important;
}

/* Etiqueta numerada arriba a la derecha, como el "02 QUIÉNES SOMOS" del deck. */
.ubl-seclabel {
    text-align: right;
    font-family: var(--ubl-font-display);
    font-size: .78rem;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--ubl-gray);
    margin: 0 0 clamp(1.5rem, 3vw, 2.5rem);
}
.ubl-seclabel strong { color: var(--ubl-ink); font-weight: 700; }
.ubl-section--gray .ubl-seclabel strong { color: var(--ubl-ink); }

