/* Portal del empleado (migracion del Portal legacy IIPortal2025).
   Shell de nav horizontal estilo Inspinia, INDEPENDIENTE del layout vertical con sidenav: NO usa
   .wrapper/.content-page del tema (esos reservan un margen izquierdo para el menu lateral, que aqui
   no existe y desplazaba el contenido).

   Dos anchos "boxed" conmutables. OJO: en esta app el tema (Inspinia) NO compila los max-width de
   Bootstrap para `.container`/`.container-fluid` (ambos = 100%), y las paginas normales nunca llenan
   el viewport porque el sidenav se come ~250px. El portal no tiene sidenav, asi que un 100% llena
   TODA la pantalla (se siente excesivo). Por eso fijamos aqui el tope explicitamente:
   - boxed (por defecto, replica de la plantilla): ancho contenido centrado.
   - wide (`.portal--wide`): mucho mas ancho, como una pagina normal amplia, pero con margen (no a
     sangre) en pantallas grandes.
   El contenido de la pagina usa `.portal-container` (ancho fijo); la barra superior (fondo y
   contenido) usa `.portal-navbar`/`.portal-navbar-inner`, con una escala adaptativa por breakpoint
   (ver mas abajo). Los feeds se pintan en recuadros `.portal-box` dentro de `.portal-container`. */

.portal-shell {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}

.portal-container {
    width: 100%;
    max-width: 1140px;
    margin-inline: auto;
    padding-inline: 1rem;
}

.portal-shell.portal--wide .portal-container {
    max-width: 1600px;
}

/* El propio fondo de la barra (no solo su contenido) queda recortado a un ancho adaptativo
   (ver media queries de abajo): por debajo de sm sigue a sangre (width:100%, sin redondear); a partir
   de sm se acota, centra y redondea. */
.portal-navbar {
    width: 100%;
    margin-inline: auto;
    /* El tema distingue topbar (--ins-topbar-bg, gris claro #f1f2f7 por defecto) de sidenav
       (--ins-sidenav-bg, otro valor): no deben coincidir. La clase Bootstrap "bg-body" del <nav>
       (ver PortalLayout.razor/PortalAdminLayout.razor) pinta blanco puro, no el gris real de
       Scrumtegy -de ahi que esta barra se viera blanca en vez del mismo tono que .app-topbar-.
       !important para ganarle a "bg-body" (que tambien es !important, utilidad de Bootstrap). */
    background-color: var(--ins-topbar-bg) !important;
}

@media (min-width: 576px) {
    .portal-navbar {
        border-radius: 0.5rem;
    }
}

/* Menu lateral del Portal publico (PortalNav.razor): reutiliza ".sidenav-menu" del tema (fixed,
   ancho var(--ins-sidenav-width)/-sm en condensado, colapsable con el toggleSidebar() global -mismo
   mecanismo que ya usaba PortalAdminNav en /portal/admin, ver admin-area.css-). El propio
   .sidenav-menu ya es position:fixed por el tema, no necesita margin; aqui solo desplazamos
   .portal-navbar/.portal-content para dejarle sitio. Scopeado a ".portal-shell--with-nav" para no
   tocar PortalAdminLayout (que usa ".wrapper.admin-area", una clase distinta con su propia regla ya
   existente en admin-area.css). */
.portal-shell--with-nav .portal-navbar,
.portal-shell--with-nav .portal-content {
    margin-left: var(--ins-sidenav-width);
}

html[data-sidenav-size="condensed"] .portal-shell--with-nav .portal-navbar,
html[data-sidenav-size="condensed"] .portal-shell--with-nav .portal-content {
    margin-left: var(--ins-sidenav-width-sm);
}

/* .portal-container (1140px boxed / 1600px wide, ver arriba) queda mas estrecho que el tope que
   tenian antes las tarjetas (la caja de tarjetas y .portal-navbar compartian hasta 1560px boxed / 2173px
   wide, ver @media mas abajo) -con el escape a 100vw desactivado (regla de mas abajo), ahora todo el
   feed vive DENTRO de .portal-container, asi que hereda su tope mas estrecho y las tarjetas se ven
   mas pequeñas que antes. Se ensancha aqui SOLO cuando hay sidenav (".portal-shell--with-nav"), a los
   mismos topes que tenian las tarjetas antes, para que no cambien de tamaño visualmente. */
.portal-shell--with-nav .portal-container,
.portal-shell--topnav .portal-container {
    max-width: 1560px;
}

.portal-shell--with-nav.portal--wide .portal-container,
.portal-shell--topnav.portal--wide .portal-container {
    max-width: 2173px;
}

/* .portal-news-detail-bleed (ver News/Detail.razor y detalles analogos) se "escapa" a TODO el ancho del
   VIEWPORT (width:100vw + margin-left:calc(50% - 50vw)) para no quedar encajonado por el .portal-container
   estrecho -pensado para cuando este esta centrado SIMETRICAMENTE sobre el viewport, sin sidenav-. Con el
   sidenav, .portal-content ya no esta centrado, asi que ese calculo ya no coincide con el centro real y el
   bloque se "escapaba" por DEBAJO del sidenav. Aqui se desactiva el escape cuando hay sidenav. */
.portal-shell--with-nav .portal-news-detail-bleed,
.portal-shell--topnav .portal-news-detail-bleed {
    width: 100%;
    margin-left: 0;
    margin-right: 0;
}

/* La navbar ya no lleva logo ni secciones (se movieron al sidenav, ver mas arriba): en vez de quedar
   acotada+centrada (max-width adaptativo, ver @media mas abajo) y
   con esquinas redondeadas, pasa a ocupar TODO el ancho libre junto al sidenav, de borde a borde, sin
   redondear -una barra de utilidades, no una "caja" mas como las tarjetas-. max-width:none +
   especificidad de 2 clases para ganarle al max-width de los @media de mas abajo (que siguen
   aplicando al resto). */
.portal-shell--with-nav .portal-navbar,
.portal-shell--with-nav .portal-navbar-inner {
    max-width: none;
}

.portal-shell--with-nav .portal-navbar {
    /* width:100% (base rule de arriba) + margin-left fijo desbordaria -el ancho se calcularia sobre
       el 100% del padre y luego se le sumaria el margen, en vez de descontarlo-. width:auto dejar que
       el bloque se autoajuste al espacio restante, mismo arreglo que ya usa admin-area.css para este
       mismo caso en PortalAdminLayout.
       margin-right:0 es el que de verdad arregla el ancho (sin esto se veia una barra pequeña pegada
       a la izquierda): .portal-navbar es un flex item de .portal-shell (flex-direction:column), que
       por defecto hace align-items:stretch -el hijo ocupa todo el ancho-, PERO un margen "auto" en el
       eje transversal (aqui margin-right, heredado de la regla base ".portal-navbar{margin-inline:
       auto}") desactiva el stretch y absorbe el hueco sobrante en ese margen invisible en vez de
       estirar la caja. Mismo fix que usa admin-area.css para este mismo caso. */
    width: auto;
    margin-right: 0;
    border-radius: 0;
}

/* display:flex + flex-direction:column es lo que necesita el Footer (margin-top:auto, ver
   _footer.scss) para pegarse abajo cuando el contenido de la pagina es corto (p.ej. el detalle de
   un evento con poco texto): sin esto el footer quedaba justo debajo del contenido en vez de al
   fondo de la pantalla. .wrapper.admin-area .portal-content (admin-area.css) ya aplicaba este
   mismo mecanismo solo para /portal/admin; aqui se generaliza para el resto del portal. */
.portal-content {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
}

/* Cabecera de los feeds del portal (NewsFeed/PublicationsFeed/EventsFeed/DocumentsFeed/FaqsFeed, ver el
   componente compartido PortalFeedHeader.razor): titulo de seccion a la izquierda, paginador en el centro,
   buscador + filtro de etiquetas + selector Cajas/Lista + boton crear a la derecha, en la misma fila en
   escritorio. Va DENTRO del recuadro .portal-box (ver mas abajo), dentro de .portal-container. */
.portal-feed-header {
    position: relative;
}

/* Paginador del header (ver PortalFeedHeader.razor): centrado de verdad en TODA la fila, no solo
   "en medio" entre titulo y botones -que con el titulo a flex-grow-1 quedaria pegado a la izquierda,
   mas cerca del titulo que de los botones-. Se saca del flujo flex con position:absolute, centrado
   respecto a .portal-feed-header (que ya es position:relative), igual que antes se hacia con los
   botones cuando el titulo iba centrado. En pantallas muy estrechas puede solaparse con el titulo si
   este es muy largo: no hay hueco reservado para el, al estar fuera del flujo. */
.portal-feed-header-pagination {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
}

/* Movil (< md): centrado absoluto se queda sin sitio (el titulo ocupa casi todo el ancho) y
   taparia el titulo. La cabecera se apila en filas: titulo (flex-basis:100%), paginador (order:2, en
   flujo normal) y acciones (order:3). Un paginador vacio (1 sola pagina) se oculta para no dejar hueco. */
@media (max-width: 767.98px) {
    .portal-feed-header {
        flex-wrap: wrap;
        row-gap: 0.5rem;
    }

    .portal-feed-header-title {
        flex: 1 1 100%;
    }

    .portal-feed-header-pagination {
        position: static;
        transform: none;
        order: 2;
        flex-basis: 100%;
    }

    .portal-feed-header-pagination:empty {
        display: none;
    }

    .portal-feed-header-actions {
        order: 3;
        flex: 1 1 100%;
        flex-wrap: wrap;
    }
}

/* Titulo de seccion dentro de la cabecera del recuadro: mas grande que el h2 por defecto del tema (ver
   .h2 en app.css), algo menor en movil. */
.portal-feed-header-title .portal-section-title {
    font-size: 1.75rem;
}

@media (max-width: 767.98px) {
    .portal-feed-header-title .portal-section-title {
        font-size: 1.4rem;
    }
}

/* Buscador inline (>= md): a la izquierda del boton de lupa, en la MISMA fila que titulo/botones
   (ver PortalFeedHeader.razor). Anima "width" (no "max-height" como la variante movil de abajo) para
   que abrir/cerrar el buscador no desplace las tarjetas hacia abajo: el espacio para el input ya
   esta reservado en la fila, solo se revela. */
.portal-feed-search-inline {
    width: 0;
    opacity: 0;
    overflow: hidden;
    transition: width 0.25s ease, opacity 0.2s ease;
}

/* overflow:visible SOLO cuando esta abierto (nunca durante el cierre): el input-group tiene un
   dropdown-menu de Bootstrap (checkbox "buscar en descripcion") que se recortaria si el padre se
   quedase con overflow:hidden mientras esta desplegado. */
.portal-feed-search-inline.show {
    width: 260px;
    opacity: 1;
    overflow: visible;
}

.portal-feed-search-inline .input-group {
    width: 260px;
    flex-shrink: 0;
}

/* .portal-feed-search (variante movil, < md, ver d-md-none en PortalFeedHeader.razor): equivalente
   del "toggleSearchXxx" + barra colapsable del legacy (Views/Home/Index.cshtml) sin JQuery/
   bootstrap.collapse: se pliega/despliega solo con CSS (max-height + opacity) al alternar la clase
   .show, evitando meter un plugin de JS para una transicion tan simple. En movil no cabe bien en la
   misma fila que titulo+botones, asi que se mantiene como fila aparte debajo (SI desplaza el
   contenido, a diferencia de la variante inline de arriba). */
.portal-feed-search {
    max-height: 0;
    opacity: 0;
    overflow: hidden;
    transition: max-height 0.25s ease, opacity 0.2s ease, margin-top 0.25s ease;
}

.portal-feed-search.show {
    max-height: 5rem;
    opacity: 1;
    margin-top: 0.75rem;
}

/* Recuadro de seccion de los feeds (ver PortalFeedBox.razor): UN .portal-box por seccion (Noticias,
   Publicaciones, Eventos, Documentos, FAQs) con el fondo/borde de seccion configurables (--portal-section-bg
   / --portal-section-border) que contiene la cabecera, los chips (FAQs) y las tarjetas/listado. Vive dentro
   de .portal-container (ya no se "escapa" a 100vw con .news-feed-bleed/.publication-feed-bleed, retirados). */
.portal-box {
    background-color: var(--portal-section-bg, #f1f2f7);
    /* Ancho configurable (--portal-section-border-width, 1..6 px); sin configurar, 1px de siempre. */
    border: var(--portal-section-border-width, 1px) solid var(--portal-section-border, #d8dce4);
    border-radius: 0.5rem;
}

/* Cabecera del recuadro: fondo transparente (= el del recuadro) y sin linea inferior. */
.portal-box-header {
    background-color: transparent;
    padding: 0.9rem 1.25rem;
    border-radius: 0.5rem 0.5rem 0 0;
}

/* Botones y paginador de la cabecera/chips de la seccion: mismo color que el titulo de seccion
   (--portal-section-title-color, ver mas abajo). Sin configurar, el verde primary de siempre. */
.portal-box {
    --portal-section-accent: var(--portal-section-title-color, var(--ins-primary));
}

.portal-box-header .portal-feed-header-actions .btn-primary,
.portal-box-chips .btn-primary,
.portal-box-header .portal-feed-header-actions .show > .btn-primary.dropdown-toggle {
    background-color: var(--portal-section-accent);
    border-color: var(--portal-section-accent);
    color: #fff;
}

.portal-box-header .portal-feed-header-actions .btn-primary:hover,
.portal-box-header .portal-feed-header-actions .btn-primary:focus-visible,
.portal-box-header .portal-feed-header-actions .btn-primary:active,
.portal-box-chips .btn-primary:hover,
.portal-box-chips .btn-primary:focus-visible,
.portal-box-chips .btn-primary:active {
    background-color: color-mix(in srgb, var(--portal-section-accent) 85%, #000);
    border-color: color-mix(in srgb, var(--portal-section-accent) 85%, #000);
    color: #fff;
}

.portal-box-chips .btn-outline-primary {
    color: var(--portal-section-accent);
    border-color: var(--portal-section-accent);
}

.portal-box-chips .btn-outline-primary:hover,
.portal-box-chips .btn-outline-primary:focus-visible,
.portal-box-chips .btn-outline-primary:active {
    background-color: var(--portal-section-accent);
    border-color: var(--portal-section-accent);
    color: #fff;
}

/* Paginador con el mismo color. OJO: el tema usa variables --ins-pagination-*, no --bs-*; las flechas
   deshabilitadas mantienen opacity 1. */
.portal-box-header .pagination {
    --ins-pagination-color: #fff;
    --ins-pagination-bg: var(--portal-section-accent);
    --ins-pagination-border-color: var(--portal-section-accent);
    --ins-pagination-hover-color: #fff;
    --ins-pagination-hover-bg: var(--portal-section-accent);
    --ins-pagination-hover-border-color: var(--portal-section-accent);
    --ins-pagination-focus-color: #fff;
    --ins-pagination-focus-bg: var(--portal-section-accent);
    --ins-pagination-disabled-color: #fff;
    --ins-pagination-disabled-bg: var(--portal-section-accent);
    --ins-pagination-disabled-border-color: var(--portal-section-accent);
}

.portal-box-header .pagination .page-link:hover {
    filter: brightness(0.92);
}

.portal-box-header .pagination .page-item.disabled .page-link {
    opacity: 1;
}

/* Indicador "N / M" (span.page-link): invertido, fondo blanco y texto/borde del color de la seccion. */
.portal-box-header .pagination span.page-link {
    background-color: #fff;
    color: var(--portal-section-accent);
    border-color: var(--portal-section-accent);
}

/* Chips de FAQs (tematicas) y cuerpo con las tarjetas. */
.portal-box-chips {
    padding: 0.25rem 1.25rem 0;
}

.portal-box-body {
    padding: 0.5rem 1.25rem 1.5rem;
}

@media (max-width: 767.98px) {
    .portal-box-header {
        padding: 0.75rem 1rem;
    }

    .portal-box-chips,
    .portal-box-body {
        padding-inline: 1rem;
    }
}

/* --portal-section-title-color: configurable desde /portal/admin/misc (Miscelanea >
   Tipografia > "Colores de secciones"). Sin configurar, el color de texto de siempre (heredado)
   no cambia: el fallback es "inherit", no un color fijo. Aplica al <h2> de titulo de cada
   seccion del portal (Home.razor). */
.portal-section-title {
    color: var(--portal-section-title-color, inherit);
}

/* .portal-navbar-inner: contenido del nav superior (logo, secciones, engranaje de admin, boton de
   ancho…). Usa la escala adaptativa del bloque de media queries
   de abajo, en vez del ancho fijo boxed/wide (no adaptativo) de .portal-container que usaba
   antes. width:100% porque aqui reemplaza a .portal-container,
   que ya llevaba ese width explicito. */
.portal-navbar-inner {
    width: 100%;
    margin-inline: auto;
    padding-inline: 1rem;
}

/* Tope adaptativo por breakpoint de Bootstrap (576/768/992/1200, ver --bs-breakpoint-* en
   vendors.min.css), en vez de un unico max-width fijo aplicado a todos los tamaños por igual.
   Mobile-first: por debajo de sm no hay tope (100% del contenedor, como cualquier .container de
   Bootstrap). En cada breakpoint se usa el mismo ancho de .container de Bootstrap (540/720/960/
   1140) multiplicado x4/3 -la proporcion que compensa pasar de 3 a 4 tarjetas por fila (ver
   col-xl-3 en NewsFeed.razor) para que cada tarjeta ocupe el mismo ancho que con 3-, y +40px en
   .portal-navbar para el margen visible alrededor. El tope de xl (1520px/2133px wide) es el
   mismo de siempre y NO crece mas alla: en pantallas ≥1200px las tarjetas deben verse igual de
   grandes que antes, la escala adaptativa solo afecta a los breakpoints intermedios (antes todos
   usaban ese mismo tope de 1520px de golpe, aunque el hueco disponible fuera menor). En modo
   "wide" (.portal--wide) se aplica el mismo ancho de .container pero multiplicado x1,87 en vez de
   x4/3 -la proporcion que llevaba el tope "wide" (1600px) del boxed (1140px) del portal, tambien
   x4/3-, así ambos modos escalan con la misma logica en los breakpoints intermedios.
   .portal-navbar-inner usa el tope base y .portal-navbar (el fondo de la barra) el tope +40. */
@media (min-width: 576px) {
    .portal-navbar-inner { max-width: 720px; }
    .portal-navbar { max-width: 760px; }
    .portal-shell.portal--wide .portal-navbar-inner { max-width: 1010px; }
    .portal-shell.portal--wide .portal-navbar { max-width: 1050px; }
}

@media (min-width: 768px) {
    .portal-navbar-inner { max-width: 960px; }
    .portal-navbar { max-width: 1000px; }
    .portal-shell.portal--wide .portal-navbar-inner { max-width: 1347px; }
    .portal-shell.portal--wide .portal-navbar { max-width: 1387px; }
}

@media (min-width: 992px) {
    .portal-navbar-inner { max-width: 1280px; }
    .portal-navbar { max-width: 1320px; }
    .portal-shell.portal--wide .portal-navbar-inner { max-width: 1796px; }
    .portal-shell.portal--wide .portal-navbar { max-width: 1836px; }
}

@media (min-width: 1200px) {
    .portal-navbar-inner { max-width: 1520px; }
    .portal-navbar { max-width: 1560px; }
    .portal-shell.portal--wide .portal-navbar-inner { max-width: 2133px; }
    .portal-shell.portal--wide .portal-navbar { max-width: 2173px; }
}

.news-card {
    /* --portal-publication-bg / --portal-publication-border: configurables desde
       /portal/admin/misc (Miscelanea > Tipografia > "Colores de publicaciones"). Sin configurar,
       el fondo blanco y el borde de siempre no cambian. */
    background-color: var(--portal-publication-bg, #fff);
    border-color: var(--portal-publication-border, #d8dce4);
    /* Ancho configurable (--portal-publication-border-width); sin configurar, el de .card del tema (1px). */
    border-width: var(--portal-publication-border-width, var(--ins-card-border-width));
    cursor: pointer;
    transition: box-shadow 0.15s ease, transform 0.15s ease;
}

.news-card:hover {
    box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.1);
    transform: translateY(-2px);
}

/* Ajuste de la imagen destacada en la tarjeta (HeroImageFit de cada elemento): por defecto la imagen entera
   (contain, como legacy) sobre fondo gris claro; --cover la rellena y recorta lo que sobra. */
.news-card-img,
.card-img-top.news-card-img {
    display: block;
    width: calc(100% - 24px);
    height: 180px;
    margin: 12px auto;
    border-radius: 6px;
    object-fit: contain;
    background-color: #f8f9fa;
}

.news-card-img--cover {
    object-fit: cover;
}

/* Icono como alternativa a la imagen destacada (legacy: div .icon-container de _noticiasList.cshtml
   cuando Imagen no es una URL https, sino el icono en si). Mutuamente excluyente con .news-card-img. */
.news-card-icon {
    width: calc(100% - 24px);
    height: 180px;
    margin: 12px auto;
    border-radius: 6px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: #f8f9fa;
}

.portal-news-hero-icon {
    width: 100%;
    max-width: 440px;
    height: 260px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: #f8f9fa;
}

/* Noticia en modo Test (legacy Enum_Estado.Test / IsTest): borde, badge y titulo con el MISMO verde
   que los botones de crear/buscar (var(--ins-primary), ver PortalFeedHeader.razor), fondo del mismo
   verde pero mas transparente (rgba con --ins-primary-rgb). Antes era azul/amarillo, sin relacion con
   el resto de la paleta del Portal. */
@keyframes news-card-test-pulse {
    0%, 100% {
        box-shadow: 0 0 0 0 rgba(var(--ins-primary-rgb), 0.15);
    }

    50% {
        box-shadow: 0 0 0 6px rgba(var(--ins-primary-rgb), 0);
    }
}

@keyframes news-card-test-blink {
    50% {
        opacity: 0.55;
    }
}

.news-card-test {
    border: 2px solid var(--ins-primary) !important;
    background-color: rgba(var(--ins-primary-rgb), 0.08);
    position: relative;
    animation: news-card-test-pulse 3s ease-in-out infinite;
}

.news-card-test-badge {
    position: absolute;
    top: 10px;
    right: 10px;
    z-index: 10;
    animation: news-card-test-blink 2s linear infinite;
}

.news-card-test-title {
    color: var(--ins-primary) !important;
}

/* Vista de detalle de noticia (Detail.razor): TODA la vista (titulo, imagen+texto, adjuntos,
   comentarios...) usa .portal-news-detail-inner como contenedor de pagina. El contenido va alineado a
   la IZQUIERDA (junto al sidenav) y el espacio sobrante queda en una banda a la DERECHA que se adapta
   al ancho de pantalla: grande en pantallas grandes (donde la noticia quedaba muy deslabazada) y cada
   vez mas pequena hasta quedar en el margen minimo en pantallas estrechas. Va en padding-right (no en
   max-width) para que la banda sea proporcional al viewport: 30% del ancho que excede de 768px, con
   tope de 28rem. */
.portal-news-detail-bleed {
    width: 100vw;
    margin-left: calc(50% - 50vw);
    margin-right: calc(50% - 50vw);
}

.portal-news-detail-inner {
    width: 100%;
    margin-inline: 0;
    padding-left: 1rem;
    padding-right: clamp(1rem, calc((100vw - 768px) * 0.3), 28rem);
}

/* Elementos relacionados (PortalRelatedItems) en el detalle de noticia. Tarjeta de 280px en el hueco
   derecho (sticky). < 992px: debajo del contenido a ancho completo. >= 992px: a la derecha; con
   relacionados (.has-related) el padding-right pasa a max(clamp real, 312px = 280 + 16 + 16) para que el
   texto solo se estreche lo justo por debajo de 1808px; desde ahi el clamp real ya >= 312px y la pagina
   queda como sin relacionados. Sin .has-related no cambia nada. */
.portal-related-aside {
    margin-top: 2rem;
}

@media (min-width: 992px) {
    .portal-news-detail-inner.has-related {
        --related-padding-right: max(clamp(1rem, calc((100vw - 768px) * 0.3), 28rem), 312px);
        padding-right: var(--related-padding-right);
    }

    /* El aside vive dentro del article: su top (0) coincide con el del titulo. Sale por la derecha del
       article, hasta 1rem del borde de la banda reservada (por eso el right negativo). */
    .portal-news-detail-inner.has-related > article {
        position: relative;
    }

    .portal-news-detail-inner.has-related .portal-related-aside {
        position: absolute;
        top: 0;
        bottom: 0;
        right: calc(1rem - var(--related-padding-right));
        width: 280px;
        margin-top: 0;
    }

    .portal-related-aside .portal-related {
        position: sticky;
        top: 4rem;
    }
}

.portal-related {
    background: var(--bs-body-bg);
    border: 1px solid var(--bs-border-color);
    border-radius: .5rem;
    box-shadow: 0 1px 3px rgba(20, 22, 40, .08);
    overflow: hidden;
}

.portal-related-title {
    margin: 0;
    padding: .8rem 1rem;
    font-size: 1rem;
    font-weight: 600;
    color: var(--bs-emphasis-color);
    border-bottom: 1px solid var(--bs-border-color);
}

.portal-related-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.portal-related-list > li + li {
    border-top: 1px solid var(--bs-border-color);
}

.portal-related-item {
    position: relative;
    display: block;
    padding: .8rem 1rem;
    color: inherit;
    text-decoration: none;
    transition: background .12s;
}

.portal-related-item:hover {
    background: var(--bs-tertiary-bg);
    color: inherit;
}

/* Elemento de prueba (Test): mismo estilo que las filas del feed (.portal-feed-list-row--test). */
.portal-related-li--test {
    background-color: rgba(var(--ins-primary-rgb), 0.08);
    box-shadow: inset 0 0 0 2px var(--ins-primary);
}

.portal-related-li--test .portal-related-name {
    color: var(--ins-primary);
}

.portal-related-test-badge {
    position: absolute;
    top: -9px;
    right: 12px;
    z-index: 2;
    animation: publication-card-test-blink 2s linear infinite;
}

.portal-related-body {
    min-width: 0;
    flex: 1;
}

/* Linea del tipo: icono 16px + nombre (+ fecha del evento) en el color de titulo de seccion del Portal
   (Miscelanea > Tipografia, variable --portal-section-title-color); sin configurar, el primario de los botones. */
.portal-related-type {
    display: flex;
    align-items: center;
    gap: .3rem;
    font-size: .6875rem;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--portal-section-title-color, var(--ins-primary, var(--bs-primary)));
}

.portal-related-type-icon {
    flex: none;
    display: inline-flex;
    align-items: center;
}

/* Fuerza 16px tanto al icono Tabler (<i>) como al SVG Lucide. */
.portal-related-type-icon i {
    font-size: 16px;
    line-height: 1;
}

.portal-related-type-icon svg {
    width: 16px;
    height: 16px;
}

.portal-related-type-date {
    font-weight: 500;
    letter-spacing: 0;
    text-transform: none;
    white-space: nowrap;
}

.portal-related-name {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
    font-size: .875rem;
    font-weight: 600;
    color: var(--bs-emphasis-color);
    line-height: 1.3;
    margin: .2rem 0 .3rem;
}

.portal-related .entity-tag-chip {
    font-size: .6875rem;
    padding: 1px 7px;
    max-width: 140px;
}

/* Imagen destacada del detalle: 2 columnas (imagen | texto) desde md, centradas verticalmente
   entre si (align-items:center); apiladas por debajo de md. */
.portal-news-detail-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1.5rem;
}

@media (min-width: 768px) {
    .portal-news-detail-grid {
        grid-template-columns: minmax(280px, 440px) 1fr;
        /* Texto e imagen alineados arriba: con una imagen alta el texto no debe quedar centrado. */
        align-items: start;
        /* Mas aire entre la imagen/icono y el texto que el gap base de 1.5rem. */
        column-gap: 3rem;
    }
}

/* Ajuste global "Posicion de la imagen en el detalle" (Miscelanea > Tipografia): con "right" en
   .portal-shell (PortalLayout.razor, data-detail-image) la imagen pasa a la columna derecha y el texto
   a la izquierda. Solo desde md: apilado en movil la imagen sigue arriba. Con --no-media la rejilla es
   de 1 columna (regla de mas abajo, misma especificidad pero posterior), asi que no se ve afectada. */
@media (min-width: 768px) {
    .portal-shell[data-detail-image="right"] .portal-news-detail-grid:not(.portal-news-detail-grid--no-media) {
        grid-template-columns: 1fr minmax(280px, 440px);
    }

    .portal-shell[data-detail-image="right"] .portal-news-detail-grid .portal-news-detail-media {
        order: 2;
    }

    .portal-shell[data-detail-image="right"] .portal-news-detail-grid .portal-news-detail-body {
        order: 1;
    }
}

/* Color de fondo del detalle (Miscelanea > Tipografia > "Colores de detalle"): un panel detras de imagen y
   descripcion (la rejilla entera) con el color elegido. PortalLayout/portalApplyAppearance ponen
   data-detail-bg="on" y --portal-detail-bg/--portal-detail-fg en .portal-shell solo cuando hay color; --portal-detail-fg
   es el texto claro u oscuro que se lee sobre ese fondo. El color de texto se aplica tambien a los enlaces y a los
   elementos de la descripcion, salvo los que el autor haya coloreado a mano (estilo en linea). */
.portal-shell[data-detail-bg] .portal-news-detail-grid {
    background: var(--portal-detail-bg);
    padding: 1.25rem;
    border-radius: 0.5rem;
}

.portal-shell[data-detail-bg] .portal-news-content,
.portal-shell[data-detail-bg] .portal-news-content a {
    color: var(--portal-detail-fg);
}

/* Se anula el margen inferior del contenido (mb-3/mb-4) dentro de su celda, y tambien el parrafo vacio
   que el editor (Quill) suele dejar al final (<p><br></p>), que alargaba la celda de texto. */
.portal-news-detail-grid .portal-news-detail-body .portal-news-content {
    margin-bottom: 0 !important;
}

.portal-news-detail-grid .portal-news-content > p:last-child:has(> br:only-child) {
    display: none;
}

/* Subtitulo (descripcion corta bajo el titulo) de los detalles de noticias, publicaciones y documentos:
   un poco mas grande que el texto base. */
.portal-detail-subtitle {
    font-size: 1.15rem;
}

/* Sin imagen ni icono (entidades con hero opcional): el texto ocupa todo el ancho, alineado a la izquierda. */
@media (min-width: 768px) {
    .portal-news-detail-grid.portal-news-detail-grid--no-media {
        grid-template-columns: 1fr;
    }
}

/* La imagen/icono llenan la columna de .portal-news-detail-grid (acotada por el minmax(.., 440px)
   de la columna, no por un max-width propio). Acotada solo en ANCHO: el alto queda libre
   (height:auto) para que la imagen nunca se recorte verticalmente, tome el alto que le corresponda
   segun su proporcion -tanto vertical como panoramica-. */
.portal-news-hero {
    width: 100%;
    height: auto;
    display: block;
}

/* El contenido HTML (Quill) del detalle no debe desbordar el ancho del contenedor. */
.portal-news-content img {
    max-width: 100%;
    height: auto;
}

/* ============================================================================================
   Publicaciones (clon estructural de Noticias, ver Components/Portal/PublicationsFeed.razor).
   Duplicado deliberado de las reglas .news-* de arriba bajo el prefijo .publication-*, sin reutilizar
   las clases de Noticias. El recuadro (.portal-box) y la cabecera son comunes a todos los feeds.
   ============================================================================================ */

.publication-card {
    background-color: var(--portal-publication-bg, #fff);
    border-color: var(--portal-publication-border, #d8dce4);
    border-width: var(--portal-publication-border-width, var(--ins-card-border-width));
    cursor: pointer;
    transition: box-shadow 0.15s ease, transform 0.15s ease;
}

.publication-card:hover {
    box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.1);
    transform: translateY(-2px);
}

.publication-card-img,
.card-img-top.publication-card-img {
    display: block;
    width: calc(100% - 24px);
    height: 180px;
    margin: 12px auto;
    border-radius: 6px;
    object-fit: contain;
    background-color: #f8f9fa;
}

.publication-card-img--cover {
    object-fit: cover;
}

/* Icono como alternativa a la imagen destacada. Mutuamente excluyente con .publication-card-img. */
.publication-card-icon {
    width: calc(100% - 24px);
    height: 180px;
    margin: 12px auto;
    border-radius: 6px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: #f8f9fa;
}

/* ============================================================================================
   Tarjetas de evento (vista Cajas, ver EventsFeed.razor y PortalEventDateBox.razor): la fecha es la protagonista.
   - Sin imagen: tarjeta normal (.publication-card) con la caja de fecha grande y centrada en la cabecera.
   - Con imagen (.portal-event-card): la imagen es el fondo de toda la tarjeta; caja de fecha arriba a la izquierda
     y titulo + chips sobre un degradado oscuro abajo. Con "Ajustar" (Contain) la imagen se ve entera y el hueco se
     rellena con la misma imagen desenfocada (.portal-event-card-blur); con "Rellenar" (Cover) cubre la tarjeta.
   ============================================================================================ */
.portal-event-date {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-width: 68px;
    padding: 0.4rem 0.65rem;
    line-height: 1.1;
    text-align: center;
    background: #fff;
    border-radius: 10px;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.18);
}

.portal-event-date-time,
.portal-event-date-month {
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--portal-section-title-color, var(--ins-primary));
}

.portal-event-date-month {
    font-weight: 700;
    text-transform: uppercase;
}

.portal-event-date-day {
    font-size: 1.65rem;
    font-weight: 700;
    color: #212529;
    white-space: nowrap;
}

.portal-event-date--lg {
    min-width: 96px;
    padding: 0.6rem 0.9rem;
}

.portal-event-date--lg .portal-event-date-day {
    font-size: 2.3rem;
}

.portal-event-date--lg .portal-event-date-time,
.portal-event-date--lg .portal-event-date-month {
    font-size: 0.85rem;
}

/* Titulo un poco mayor (+2.5px) en las tarjetas sin imagen. */
.portal-event-title-lg {
    font-size: 1rem;
}

.portal-event-chips {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem;
    min-width: 0;
}

/* Tarjetas sin imagen: aunque otra tarjeta de la fila tenga el titulo en mas lineas, los chips y los botones
   quedan siempre alineados al fondo. */
.card-body > .portal-event-chips {
    margin-top: auto;
}

.portal-event-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    max-width: 100%;
    padding: 0.15rem 0.5rem;
    font-size: 0.74rem;
    color: #fff;
    /* Color de titulo de seccion (Miscelanea > Tipografia); sin configurar, el primario. Mismo color en todos los
       chips; solo el aforo completo se marca en rojo para que se distinga. */
    background: var(--portal-section-title-color, var(--ins-primary));
    border-radius: 5px;
}

.portal-event-chip--full {
    background: #c0392b;
}

.portal-event-chip--location {
    min-width: 0;
}

.portal-event-card {
    position: relative;
    display: flex;
    align-items: flex-end;
    min-height: 300px;
    height: 100%;
    overflow: hidden;
    background: #f8f9fa;
    border: var(--portal-publication-border-width, var(--ins-card-border-width, 1px)) solid var(--portal-publication-border, #d8dce4);
    border-radius: 0.375rem;
    cursor: pointer;
    transition: box-shadow 0.15s ease, transform 0.15s ease;
}

.portal-event-card:hover {
    box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.1);
    transform: translateY(-2px);
}

.portal-event-card--test {
    border: 2px solid var(--ins-primary);
}

.portal-event-card-img,
.portal-event-card-blur {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
}

.portal-event-card-img--contain {
    object-fit: contain;
}

.portal-event-card-img--cover {
    object-fit: cover;
}

.portal-event-card-blur {
    inset: -20px;
    width: calc(100% + 40px);
    height: calc(100% + 40px);
    object-fit: cover;
    filter: blur(18px) saturate(1.1);
}

.portal-event-card > .portal-event-date {
    position: absolute;
    top: 14px;
    left: 14px;
    z-index: 2;
}

.portal-event-card-overlay {
    position: relative;
    z-index: 1;
    width: 100%;
    padding: 3.5rem 1rem 1rem;
    color: #fff;
    background: linear-gradient(to top, rgba(0, 0, 0, 0.82) 0%, rgba(0, 0, 0, 0.55) 55%, rgba(0, 0, 0, 0) 100%);
}

.portal-event-card-overlay h5 {
    color: #fff;
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
    /* h5 del tema (semibold) +2px en las tarjetas con imagen. */
    font-size: calc(0.84552rem + 2px);
}

/* Aviso del evento: esquina superior derecha de la tarjeta, a la misma altura que la caja de fecha de la tarjeta con
   imagen (.portal-event-card > .portal-event-date, top: 14px); la tarjeta sin imagen usa el mismo desplazamiento. Si la
   tarjeta tambien es de test, baja justo debajo de la etiqueta "Test" (.publication-card-test-badge). */
.portal-event-card-notice {
    position: absolute;
    top: 14px;
    right: 10px;
    z-index: 10;
    max-width: 60%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.portal-event-card-notice--below-test {
    top: 40px;
}

.portal-publication-hero-icon {
    width: 100%;
    height: 220px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: #f8f9fa;
}

@keyframes publication-card-test-pulse {
    0%, 100% {
        box-shadow: 0 0 0 0 rgba(var(--ins-primary-rgb), 0.15);
    }

    50% {
        box-shadow: 0 0 0 6px rgba(var(--ins-primary-rgb), 0);
    }
}

@keyframes publication-card-test-blink {
    50% {
        opacity: 0.55;
    }
}

/* Mismo verde que los botones de crear/buscar (var(--ins-primary)) y que .news-card-test: ver
   comentario de esa regla, misma razon (antes azul/amarillo, sin relacion con el resto de la
   paleta). Reutilizado tambien por EventsFeed.razor (clon de PublicationsFeed). */
.publication-card-test {
    border: 2px solid var(--ins-primary) !important;
    background-color: rgba(var(--ins-primary-rgb), 0.08);
    position: relative;
    animation: publication-card-test-pulse 3s ease-in-out infinite;
}

.publication-card-test-badge {
    position: absolute;
    top: 10px;
    right: 10px;
    z-index: 10;
    animation: publication-card-test-blink 2s linear infinite;
}

.publication-card-test-title {
    color: var(--ins-primary) !important;
}

/* Icono de tipo de archivo (Tabler) como hero de documento sin imagen ni icono Lucide. */
.document-card-file-icon i {
    font-size: 4rem;
    color: var(--ins-primary);
    opacity: 0.75;
}

/* El modal de firma vive dentro de la tarjeta: un transform en hover rompe su position:fixed. */
.document-card:hover {
    transform: none;
}

.portal-publication-hero {
    width: 100%;
    max-width: 700px;
    height: auto;
    display: block;
    margin-inline: auto;
}

.portal-publication-content img {
    max-width: 100%;
    height: auto;
}

/* Gestor de usuario en la navbar del Portal (UserDropdown con PortalMode, ver PortalLayout.razor).
   Las reglas del tema de .topbar-item/.topbar-link estan acotadas a ".app-topbar .topbar-menu", que
   la navbar del Portal no tiene: se replican aqui para que avatar y nombre se vean igual. */
.portal-navbar .topbar-item {
    display: flex;
    align-items: center;
    justify-content: center;
}

.portal-navbar .topbar-item .topbar-link {
    border: none;
    background-color: transparent;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--ins-topbar-item-color);
    position: relative;
}

.portal-navbar .topbar-item .topbar-link:hover,
.portal-navbar .topbar-item .topbar-link:active,
.portal-navbar .topbar-item .topbar-link:focus {
    color: var(--ins-topbar-item-hover-color);
}

/* La navbar del Portal mide lo mismo que la topbar de Scrumtegy (--ins-topbar-height): altura fija,
   sin padding vertical (el py-2 de Bootstrap + el .nav-user de UserDropdown, de min-height igual a la
   topbar, la dejaban mas alta). Scopeado a ".portal-shell--with-nav" para no tocar PortalAdminLayout. */
.portal-shell--with-nav .portal-navbar {
    height: var(--ins-topbar-height);
    padding-top: 0 !important;
    padding-bottom: 0 !important;
}

.portal-shell--with-nav .portal-navbar-inner {
    height: 100%;
}

.portal-navbar .topbar-item {
    height: var(--ins-topbar-height);
}

/* Desplegable de usuario: la navbar del Portal es un ".navbar" de Bootstrap, y dentro de un navbar
   Bootstrap desactiva Popper (el data-bs-offset="0,16" de UserDropdown no se aplica) y posiciona el menu
   por CSS justo bajo el boton, solapando la barra. Se replica la posicion que Popper le da en la topbar
   de Scrumtegy (desplazamiento de 16px del data-bs-offset + los 3px de margen de la animacion).
   Se desplaza con "top" y no con margin-top porque la animacion DropDownSlideUp del tema (fill-mode
   both) fija margin-top y le gana a cualquier regla. */
.portal-navbar .nav-user .dropdown-menu {
    top: calc(100% + 16px);
}

/* Menu superior (Miscelanea > Secciones > "Tipo de menu" = superior, ver PortalTopNav.razor): sin sidenav, la
   barra va a todo el ancho (sin esquinas ni tope; el contenido interior se acota al mismo ancho que la
   pagina, --portal-topnav-max) y reune logo, secciones y acciones. El tope del contenido es el mismo que con
   sidenav (ver ".portal-shell--topnav .portal-container" mas arriba) para que secciones y tarjetas no cambien
   de tamano entre los dos tipos de menu. */
.portal-shell--topnav {
    --portal-topnav-max: 1560px;
}

.portal-shell--topnav.portal--wide {
    --portal-topnav-max: 2173px;
}

.portal-shell.portal-shell--topnav .portal-navbar {
    width: 100%;
    max-width: none;
    margin: 0;
    border-radius: 0;
}

.portal-shell.portal-shell--topnav .portal-navbar-inner {
    max-width: var(--portal-topnav-max);
    flex-wrap: wrap;
}

.portal-topnav-logo {
    display: inline-flex;
    align-items: center;
    margin-right: 1.25rem;
}

.portal-topnav-logo img {
    height: 36px;
    width: auto;
    display: block;
}

.portal-topnav-collapse {
    align-items: center;
}

.portal-topnav-links {
    gap: 0.25rem;
    margin-bottom: 0;
    align-self: center;
}

.portal-topnav-links .nav-item {
    display: flex;
    align-items: center;
}

/* Enlaces de seccion con el color de titulo de seccion (Miscelanea > Tipografia); sin configurar, el primario. */
.portal-topnav-links .nav-link {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 1rem;
    border-radius: 0.375rem;
    font-weight: 600;
    font-size: 1.3rem;
    line-height: 1.3;
    text-transform: uppercase;
    color: var(--portal-section-title-color, var(--ins-primary));
}

.portal-topnav-links .nav-link i {
    font-size: 1.7rem;
}

.portal-topnav-links .nav-link:hover,
.portal-topnav-links .nav-link:focus-visible {
    background: color-mix(in srgb, var(--portal-section-title-color, var(--ins-primary)) 10%, transparent);
    color: var(--portal-section-title-color, var(--ins-primary));
}

/* Ancla con hueco para la barra fija al saltar a una seccion. */
.portal-shell--topnav section[id] {
    scroll-margin-top: 4.5rem;
}

/* Detalle de noticias, publicaciones, eventos, documentos y FAQs con menu superior: en vez de ir pegado a la
   izquierda (pensado para el sidenav, ver .portal-news-detail-inner), el bloque principal se centra con la misma
   caja que el contenido de la barra (mismo tope y padding de 1rem: arranca a la altura del logo). Sin
   relacionados ocupa todo ese ancho; con relacionados llega hasta el separador del bloque de usuario y los
   relacionados salen desde ahi hacia la derecha (pueden invadir el margen de la pagina, que en pantallas
   anchas sobra). --detail-pad-right lo calcula portal.js (la distancia del separador al borde derecho de
   la caja) y ".related-below" lo pone el mismo script cuando a la derecha no caben (pantallas estrechas): los
   relacionados pasan debajo del contenido, a su ancho. */
.portal-shell--topnav .portal-news-detail-inner {
    max-width: var(--portal-topnav-max);
    margin-inline: auto;
    padding-left: 1rem;
    padding-right: 1rem;
}

@media (min-width: 992px) {
    .portal-shell--topnav .portal-news-detail-inner.has-related:not(.related-below) {
        padding-right: var(--detail-pad-right, 1rem);
    }

    .portal-shell--topnav .portal-news-detail-inner.has-related:not(.related-below) .portal-related-aside {
        right: auto;
        left: calc(100% + 1rem);
        width: 280px;
    }

    .portal-shell--topnav .portal-news-detail-inner.has-related.related-below .portal-related-aside {
        position: static;
        margin-top: 2rem;
        width: auto;
    }
}

/* Movil: el desplegable ocupa todo el ancho y apila enlaces + acciones. */
@media (max-width: 991.98px) {
    .portal-topnav-collapse {
        flex-basis: 100%;
        padding-top: 0.5rem;
    }

    .portal-topnav-links {
        flex-direction: column;
        align-items: stretch;
    }

    .portal-topnav-actions {
        margin-top: 0.5rem;
        padding-top: 0.5rem;
        border-top: 1px solid var(--ins-border-color, #dee2e6);
    }
}

/* Formato impuesto a la descripcion del detalle (Superadmin > Formato de descripciones). Solo actua cuando
   PortalLayout/portalApplyAppearance ponen data-description-font / data-description-size en .portal-shell
   (sin valor guardado no hay atributo y cada contenido conserva el formato de su autor). Lleva !important
   para ganar a las clases ql-font y ql-size y a los estilos en linea de Quill, y se iguala TODO el
   contenido (tambien los titulos). Se respetan sub/sup (tamano relativo) y pre/code (monoespaciado). */
.portal-shell[data-description-font] .portal-news-content,
.portal-shell[data-description-font] .portal-news-content *:not(pre):not(code):not(.ql-syntax) {
    font-family: var(--portal-description-font) !important;
}

.portal-shell[data-description-size] .portal-news-content,
.portal-shell[data-description-size] .portal-news-content *:not(sub):not(sup) {
    font-size: var(--portal-description-size) !important;
}

/* Selector de tamano de letra (px) en los editores Quill del Portal (data-quill-sizes, ver
   form-quilljs.js): ancho para el numero. */
.ql-snow .ql-picker.ql-size {
    width: 64px;
}

/* Tamano por defecto = 13px (el heredado del tema, sin cambiar la apariencia de lo ya publicado): el
   selector lo muestra como "13" en vez de "Normal" cuando el texto no lleva un tamano explicito. Un
   tamano elegido a mano (span con font-size inline) sigue mandando sobre el valor base. */
.ql-snow .ql-picker.ql-size .ql-picker-label:not([data-label])::before,
.ql-snow .ql-picker.ql-size .ql-picker-label[data-label='']::before {
    content: '13';
}

/* ============================================================================================
   Vista "Listado" de los feeds del Portal (ver PortalFeedListRow.razor / PortalFeedHeader.razor):
   una fila por elemento con miniatura (imagen o icono; hueco reservado si no hay ninguno para que los
   nombres queden alineados), nombre y fecha.
   ============================================================================================ */
.portal-feed-list {
    display: flex;
    flex-direction: column;
    gap: .5rem;
}

.portal-feed-list-row {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: .5rem .75rem;
    /* Mismos colores configurables que las tarjetas de la vista Cajas (/portal/admin/misc > Tipografia >
       "Colores de publicaciones"); sin configurar se mantiene el fondo blanco y el borde de siempre. */
    background: var(--portal-publication-bg, #fff);
    border: var(--portal-publication-border-width, 1px) solid var(--portal-publication-border, var(--ins-border-color, #dee2e6));
    border-radius: .375rem;
    cursor: pointer;
    transition: box-shadow 0.15s ease, transform 0.15s ease;
    /* Ancla de la etiqueta Test y de la banda de destacado (sin overflow:hidden para que la etiqueta pueda sobresalir). */
    position: relative;
}

/* Hover: se eleva como las tarjetas de la vista Cajas (.news-card:hover / .publication-card:hover). */
.portal-feed-list-row:hover {
    box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.1);
    transform: translateY(-2px);
}

.portal-feed-list-row--test {
    border: 2px solid var(--ins-primary);
    background-color: rgba(var(--ins-primary-rgb), 0.08);
}

.portal-feed-list-title--test {
    color: var(--ins-primary);
}

/* Etiqueta "Test": flota sobre el borde superior derecho; mismo parpadeo que .publication-card-test-badge. */
.portal-feed-list-test-badge {
    position: absolute;
    top: -9px;
    right: 12px;
    z-index: 2;
    animation: publication-card-test-blink 2s linear infinite;
}

/* Destacado (Eventos): banda amarilla en el borde izquierdo, con las esquinas de la fila, y estrella junto al nombre. */
.portal-feed-list-row--featured::before {
    content: "";
    position: absolute;
    top: -1px;
    bottom: -1px;
    left: -1px;
    width: 5px;
    background: #ffc107;
    border-radius: .375rem 0 0 .375rem;
}

.portal-feed-list-row--featured.portal-feed-list-row--test::before {
    top: -2px;
    bottom: -2px;
    left: -2px;
}

.portal-feed-list-star {
    color: #e0a800;
}

.portal-feed-list-thumb {
    flex: 0 0 56px;
    width: 56px;
    height: 56px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: #f8f9fa;
    border-radius: .25rem;
    overflow: hidden;
}

.portal-feed-list-img {
    width: 100%;
    height: 100%;
}

.portal-feed-list-img--cover {
    object-fit: cover;
}

.portal-feed-list-img--contain {
    object-fit: contain;
}

.portal-feed-list-main {
    flex: 1 1 auto;
    min-width: 0;
}

.portal-feed-list-title {
    font-weight: 600;
    min-width: 0;
}

/* Subtitulo (descripcion corta) bajo el nombre: una linea, cortada con "..." (text-truncate en el marcado). */
.portal-feed-list-subtitle {
    margin-top: .1rem;
    font-size: .9rem;
}

/* Linea del nombre: nombre (se trunca) + estrella + fecha + badges. */
.portal-feed-list-nameline {
    display: flex;
    align-items: center;
    gap: .5rem;
    min-width: 0;
}

.portal-feed-list-date {
    flex: 0 0 auto;
    font-size: .82rem;
    white-space: nowrap;
}

/* Area de indicadores: ANCHO FIJO (igual en todas las filas, tenga los indicadores que tenga), indicadores
   compactos icono+numero y, al final, el icono de estado del usuario (.portal-feed-list-state). */
.portal-feed-list-indicators {
    flex: 0 0 140px;
    width: 140px;
    align-self: stretch;
    display: flex;
    align-items: center;
    gap: .6rem;
    padding-left: .6rem;
    border-left: 1px solid var(--bs-border-color, #dee2e6);
    font-size: .9rem;
    font-weight: 700;
    white-space: nowrap;
}

.portal-feed-list-indicators > * {
    white-space: nowrap;
}

.portal-feed-list-indicator {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
}

.portal-feed-list-indicator--zero {
    color: #adb5bd;
}

.portal-feed-list-state {
    margin-left: auto;
    font-size: 1.05rem;
    font-weight: 400;
}

/* Botones a la derecha de la fila: ancho fijo (caben 3). */
.portal-feed-list-actions {
    flex: 0 0 92px;
    width: 92px;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: .25rem;
}

@media (max-width: 640px) {
    .portal-feed-list-row {
        flex-wrap: wrap;
    }

    .portal-feed-list-indicators,
    .portal-feed-list-actions {
        flex-basis: auto;
        width: auto;
    }

    .portal-feed-list-indicators {
        border-left: 0;
        padding-left: 0;
    }
}

/* Etiquetas del Portal (PortalTagChips) en la linea del nombre de la fila del listado: una sola linea, se recortan si no caben. */
.portal-feed-list-tags {
    flex: 0 1 auto;
    min-width: 0;
    overflow: hidden;
}

.portal-feed-list-tags .entity-tags {
    flex-wrap: nowrap;
    gap: 4px;
}

/* Footer del Portal (PortalSiteFooter.razor, Configuracion > RGPD): tarjeta redondeada con los enlaces legales como
   pildoras. --pf-bg / --pf-text vienen de la configuracion del tenant (por defecto #f3f4f7 / #000000); el fondo de las
   pildoras se deriva del color del texto, asi que contrastan con cualquier combinacion. .portal-content es una
   columna flex: margin-top:auto lo deja abajo del todo cuando el contenido es corto. */
.portal-site-footer-wrap {
    margin-top: auto;
    padding-top: 1.5rem;
    padding-bottom: 1rem;
}

.portal-site-footer {
    background: var(--pf-bg, #f3f4f7);
    color: var(--pf-text, #000000);
    border-radius: 12px;
    padding: 14px 18px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    font-size: 0.8125rem;
}

.portal-site-footer nav {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 8px;
}

.portal-site-footer-link {
    border: 0;
    color: var(--pf-text, #000000);
    background: color-mix(in srgb, var(--pf-text, #000000) 12%, transparent);
    padding: 5px 14px;
    border-radius: 999px;
    font: inherit;
    cursor: pointer;
}

.portal-site-footer-link:hover {
    background: color-mix(in srgb, var(--pf-text, #000000) 24%, transparent);
}

/* Iconos de utilidades de la barra del Portal (soporte, ayuda): mismo color que los .topbar-link de la
   topbar de Scrumtegy (--ins-topbar-item-color; verde --ins-topbar-item-hover-color al pasar por encima),
   en lugar del primario que da btn-link. */
.portal-navbar .portal-nav-icon {
    color: var(--ins-topbar-item-color, #6c757d);
}

.portal-navbar .portal-nav-icon:hover,
.portal-navbar .portal-nav-icon:focus,
.portal-navbar .portal-nav-icon:active {
    color: var(--ins-topbar-item-hover-color, #1ab394);
}
