/* sanjuanalmundo - estilos base
   Diseño inspirado en https://www.sanjuanalmundo.com/
   Sin framework, mobile-first, con variables CSS.
   Paleta: azul institucional #1980B6, azul oscuro #03212c.
*/

:root {
    --color-fondo:          #ffffff;
    --color-fondo-alt:      #f2f2f2;
    --color-humo:           #fafafa;   /* fondo suave para tarjetas ("humo") */
    --color-fondo-oscuro:   #03212c;
    --color-texto:          #222;
    --color-texto-suave:    #666;
    --color-primario:       #1980B6;   /* azul SJM */
    --color-primario-oscuro:#125f88;
    --color-acento:         #f39c12;
    --color-borde:          #e2e2e2;
    --radio:                10px;
    --sombra:               0 1px 3px rgba(0, 0, 0, 0.08);
    --sombra-hover:         0 6px 16px rgba(0, 0, 0, 0.12);
    --max-ancho:            1170px;
    --fuente-texto:         "Open Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --fuente-titular:       "Raleway", "Open Sans", Arial, sans-serif;

    /* Fuente principal del sitio (hardcodeada, reemplazable de un solo lugar).
       Cambia esta linea y el <link> de Google Fonts en lib/layout.php para
       cambiar la fuente en todo el sitio de una sola vez. Se usa en el menu
       superior y en la pagina de articulo (volanta, titulo, bajada, cuerpo). */
    --fuente-sitio:         "Roboto Condensed", "Arial Narrow", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;

    /* Tamano base de fuente del sitio. Todos los demas font-size del CSS
       estan en rem/em, asi que subir o bajar este valor escala TODO el
       sitio en forma proporcional (menu, titulares, cards, articulo, aside,
       footer, buscadores, etc.). */
    --fuente-tamano-base:   16px;
}

* { box-sizing: border-box; }

html, body {
    margin: 0;
    padding: 0;
    background: var(--color-fondo);
    color: var(--color-texto);
    font-family: var(--fuente-texto);
    font-size: var(--fuente-tamano-base);
    line-height: 1.55;
}

img { max-width: 100%; height: auto; display: block; }

a { color: var(--color-primario); text-decoration: none; }
a:hover { color: var(--color-primario-oscuro); text-decoration: none; }

h1, h2, h3, h4 { font-family: var(--fuente-titular); margin: 0 0 0.4em; line-height: 1.2; font-weight: 600; }
h1 { font-size: 2rem; }
h2 { font-size: 1.6rem; }
h3 { font-size: 1.3rem; }
h4 { font-size: 1.05rem; }

.container {
    max-width: var(--max-ancho);
    margin: 0 auto;
    padding: 0 15px;
}

/* ================================================================
   Header
================================================================= */
.site-header {
    background: #fff;
    border-bottom: 1px solid var(--color-borde);
    /* Sombra permanente (no aparece/desaparece con el scroll): despega la
       cabecera del contenido, que al ser `sticky` se desliza por debajo.
       El z-index 100 es el mas alto del sitio, asi que la sombra siempre
       cae sobre el contenido y nunca al reves.
       Va en dos capas: una corta y marcada pegada al borde para dar el corte
       nitido, y otra larga y difusa que hunde el contenido bastante mas abajo. */
    box-shadow: 0 4px 5px rgba(0, 0, 0, 0.18),
                0 10px 22px rgba(0, 0, 0, 0.22);
    position: sticky; top: 0; z-index: 100;
}
.site-header-row {
    display: flex; align-items: center; gap: 1rem;
    padding: 0.65rem 15px;
    flex-wrap: wrap;
}
.site-brand {
    display: flex; flex-direction: column; line-height: 1;
    margin-right: 1rem;
}
.site-brand-logo {
    display: block; height: 48px; width: auto;
}
.site-brand-main {
    font-family: var(--fuente-titular);
    font-size: 1.5rem; font-weight: 700; color: var(--color-primario);
    letter-spacing: -0.5px;
}
.site-brand-sub {
    font-size: 0.7rem; color: var(--color-texto-suave);
    letter-spacing: 0.18em; text-transform: uppercase; margin-top: 3px;
}
.site-nav {
    /* Menu compacto en escritorio: la separacion visible entre dos rotulos es
       este `gap` mas el padding lateral de cada enlace (ver `.site-nav a`).
       En mobile el menu es un acordeon vertical y define su propio `gap: 0`. */
    display: flex; gap: 0.15rem; flex: 1; flex-wrap: wrap;
    justify-content: flex-end; align-items: center;
}
.site-nav a {
    font-family: var(--fuente-sitio);
    color: #333; font-weight: 500;
    /* Flex (y no inline) para poder alinear verticalmente el icono de Font
       Awesome con el texto. Los items con desplegable muestran solo el rotulo
       (sin flecha), asi que se ven identicos a los que no lo tienen. */
    display: inline-flex; align-items: center; gap: 0.45rem;
    padding: 0.55rem 0.6rem;
    text-transform: uppercase; font-size: 0.82rem;
    letter-spacing: 0.03em;
    border-radius: 4px;
    transition: color .15s, background .15s;
}
.site-nav a:hover { color: var(--color-primario); background: var(--color-fondo-alt); }
.site-nav-item { position: relative; display: inline-flex; align-items: center; }
.site-nav-toggle { display: inline-flex; align-items: center; }
/* Ancho fijo para que los rotulos arranquen todos en la misma columna aunque
   los glifos de FA tengan anchos distintos. */
.site-nav-icono {
    width: 1em; flex: 0 0 auto;
    font-size: 0.95em; text-align: center;
    opacity: 0.85;
}
.site-nav a:hover .site-nav-icono { opacity: 1; }
.site-nav-dropdown {
    position: absolute; top: 100%; right: 0;
    min-width: 240px;
    background: #fff;
    border: 1px solid var(--color-borde);
    border-radius: 4px;
    box-shadow: 0 8px 22px rgba(0,0,0,0.08);
    padding: 0.35rem 0;
    /* Sin margen: cualquier hueco entre el ítem y el panel es una zona
       muerta donde se pierde el :hover y el desplegable se cierra justo
       cuando el mouse va bajando hacia él. */
    margin: 0;
    list-style: none;
    display: none;
    z-index: 30;
}
/* Sin JS el panel abre con hover / foco, como siempre. Cuando app.js corre
   marca cada ítem con .has-js y el estado pasa a manejarlo el JS (.is-open):
   así el cierre puede ser diferido en vez de instantáneo, y un click puede
   dejar el panel fijado sin que el :hover lo tape ni el :focus-within lo
   deje pegado abierto. */
.site-nav-item:not(.has-js):hover > .site-nav-dropdown,
.site-nav-item:not(.has-js):focus-within > .site-nav-dropdown,
.site-nav-item.is-open > .site-nav-dropdown {
    display: block;
    animation: sjm-dropdown-in .13s ease-out;
}
@keyframes sjm-dropdown-in {
    from { opacity: 0; transform: translateY(-4px); }
    to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
    .site-nav-item:not(.has-js):hover > .site-nav-dropdown,
    .site-nav-item:not(.has-js):focus-within > .site-nav-dropdown,
    .site-nav-item.is-open > .site-nav-dropdown { animation: none; }
}
.site-nav-item.is-open > .site-nav-toggle {
    color: var(--color-primario); background: var(--color-fondo-alt);
}
.site-nav-dropdown li { margin: 0; padding: 0; }
.site-nav-dropdown a {
    font-family: var(--fuente-sitio);
    /* Flex para alinear el icono con el rotulo. El `gap` es mayor que el del
       menu principal porque aca el texto va en minusculas y sin `letter-spacing`,
       asi que necesita un poco mas de aire para no pegarse al glifo. */
    display: flex; align-items: center; gap: 0.6rem;
    padding: 0.5rem 0.95rem;
    text-transform: none;
    letter-spacing: 0;
    font-size: 0.85rem;
    color: #333;
    border-radius: 0;
    white-space: nowrap;
}
.site-nav-dropdown a:hover { background: var(--color-fondo-alt); color: var(--color-primario); }
.site-search {
    display: flex; gap: 0;
    border: 1px solid var(--color-borde);
    border-radius: 4px; overflow: hidden;
    margin-left: 0.5rem;
}
.site-search input {
    font-family: var(--fuente-sitio);
    border: none; padding: 0.4rem 0.7rem;
    font-size: 0.9rem; min-width: 180px; outline: none;
}
.site-search button {
    background: var(--color-primario); color: #fff; border: none;
    padding: 0 0.85rem; cursor: pointer; font-size: 0.95rem;
}
.site-search button:hover { background: var(--color-primario-oscuro); }
/* Con JS el campo no se teclea: app.js lo deja readOnly y el click abre el
   modal de busqueda. Al comportarse como un boton, el cursor lo tiene que
   decir. Sin JS sigue siendo un input normal. */
.site-search input[readonly] { cursor: pointer; background: #fff; }

/* Item "Buscar" del menu: existe solo en mobile, que es donde la cabecera
   esconde .site-search. La regla necesita el `.site-nav a` completo para
   ganarle en especificidad al `display: inline-flex` de los items del menu. */
.site-nav a.site-nav-buscar { display: none; }

/* Botón hamburguesa (solo mobile). En desktop queda oculto. */
.site-menu-toggle {
    display: none;
    background: transparent;
    border: 1px solid var(--color-borde);
    border-radius: 6px;
    width: 42px; height: 42px;
    padding: 0;
    cursor: pointer;
    align-items: center; justify-content: center;
    margin-left: auto;
}
.site-menu-toggle:hover { background: var(--color-fondo-alt); }
.site-menu-toggle-bars,
.site-menu-toggle-bars::before,
.site-menu-toggle-bars::after {
    display: block;
    width: 22px; height: 2px;
    background: #333;
    border-radius: 2px;
    position: relative;
    transition: transform .2s ease, top .2s ease, opacity .15s ease;
}
.site-menu-toggle-bars::before,
.site-menu-toggle-bars::after {
    content: "";
    position: absolute; left: 0;
}
.site-menu-toggle-bars::before { top: -7px; }
.site-menu-toggle-bars::after  { top:  7px; }
.site-menu-toggle[aria-expanded="true"] .site-menu-toggle-bars { background: transparent; }
.site-menu-toggle[aria-expanded="true"] .site-menu-toggle-bars::before { top: 0; transform: rotate(45deg); }
.site-menu-toggle[aria-expanded="true"] .site-menu-toggle-bars::after  { top: 0; transform: rotate(-45deg); }

/* ================================================================
   Buscador modal (autocompletado)
   Lo abre el buscador de la cabecera cuando hay JS (ver initBuscadorModal
   en app.js). El markup vive en lib/partials/header.php y arranca con el
   atributo `hidden`: sin JS este bloque nunca se ve.
================================================================= */
.buscador-modal {
    position: fixed; inset: 0;
    /* Por encima del .site-header, que es lo mas alto del sitio (z-index 100). */
    z-index: 200;
    /* `flex-start` para que el panel mida lo que mide su contenido: con el
       `stretch` por defecto queda un panel de alto completo con un vacio
       blanco debajo de las sugerencias. */
    display: flex; justify-content: center; align-items: flex-start;
    padding: 8vh 15px 15px;
}
/* El `display: flex` de arriba le gana al display:none que el navegador le
   pone a [hidden]; hay que reponerlo explicitamente. */
.buscador-modal[hidden] { display: none; }
body.has-buscador-modal { overflow: hidden; }

.buscador-modal-fondo {
    position: absolute; inset: 0;
    background: rgba(3, 33, 44, 0.55);
    backdrop-filter: blur(2px);
}
.buscador-modal-panel {
    position: relative;
    width: 100%; max-width: 640px;
    max-height: 100%;
    display: flex; flex-direction: column;
    background: #fff;
    border-radius: var(--radio);
    box-shadow: 0 18px 45px rgba(0, 0, 0, 0.35);
    overflow: hidden;
    animation: sjm-buscador-in .15s ease-out;
}
@keyframes sjm-buscador-in {
    from { opacity: 0; transform: translateY(-10px); }
    to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
    .buscador-modal-panel { animation: none; }
}

.buscador-modal-barra {
    display: flex; align-items: center; gap: 0.6rem;
    padding: 0.5rem 0.75rem;
    border-bottom: 1px solid var(--color-borde);
    flex: 0 0 auto;
}
.buscador-modal-lupa { color: var(--color-primario); font-size: 1rem; }
.buscador-modal-input {
    font-family: var(--fuente-sitio);
    flex: 1; min-width: 0;
    border: none; outline: none;
    padding: 0.55rem 0;
    font-size: 1.15rem; color: var(--color-texto);
    background: transparent;
}
/* La X nativa del type=search duplicaria al boton de cerrar. */
.buscador-modal-input::-webkit-search-cancel-button { display: none; }
.buscador-modal-cerrar {
    background: transparent; border: none;
    color: var(--color-texto-suave);
    width: 34px; height: 34px; border-radius: 50%;
    display: inline-flex; align-items: center; justify-content: center;
    cursor: pointer; font-size: 1rem;
    flex: 0 0 auto;
}
.buscador-modal-cerrar:hover { background: var(--color-fondo-alt); color: var(--color-texto); }

.buscador-modal-cuerpo {
    /* El unico scroll del modal vive aca: la barra de busqueda queda fija. */
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    min-height: 0;
}
.buscador-modal-estado {
    margin: 0; padding: 1rem 1.1rem;
    font-size: 0.88rem; color: var(--color-texto-suave);
}
/* Cuando abajo hay resultados por similitud fonetica (SOUNDEX), el estado
   deja de ser un mensaje suelto y pasa a encabezar la lista. */
.buscador-modal-estado.is-fonetico {
    padding: 0.6rem 1.1rem;
    background: var(--color-humo);
    border-bottom: 1px solid var(--color-borde);
    font-size: 0.82rem;
}
.buscador-modal-lista { list-style: none; margin: 0; padding: 0; }
.buscador-modal-op { margin: 0; }
.buscador-modal-item {
    display: flex; align-items: center; gap: 0.75rem;
    padding: 0.6rem 1.1rem;
    color: var(--color-texto);
    border-left: 3px solid transparent;
}
/* Hover y flechas del teclado comparten el mismo resaltado. */
.buscador-modal-op.is-activo .buscador-modal-item,
.buscador-modal-item:hover {
    background: var(--color-fondo-alt);
    border-left-color: var(--color-primario);
    color: var(--color-texto);
}
.buscador-modal-thumb {
    flex: 0 0 auto;
    width: 62px; height: 44px;
    border-radius: 6px; overflow: hidden;
    background: var(--color-fondo-alt);
}
.buscador-modal-thumb img { width: 100%; height: 100%; object-fit: cover; }
.buscador-modal-datos { min-width: 0; display: flex; flex-direction: column; }
.buscador-modal-titulo {
    font-family: var(--fuente-sitio);
    font-size: 0.98rem; font-weight: 600; line-height: 1.3;
    /* Dos lineas como maximo: los titulos largos no pueden empujar la lista. */
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    overflow: hidden;
}
.buscador-modal-titulo mark {
    background: rgba(243, 156, 18, 0.35);
    color: inherit; padding: 0 1px; border-radius: 2px;
}
.buscador-modal-meta {
    font-size: 0.76rem; color: var(--color-texto-suave);
    margin-top: 2px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.buscador-modal-todos {
    display: block;
    padding: 0.75rem 1.1rem;
    border-top: 1px solid var(--color-borde);
    font-family: var(--fuente-sitio);
    font-size: 0.85rem; font-weight: 600;
    color: var(--color-primario);
    background: var(--color-humo);
}
.buscador-modal-todos:hover { background: var(--color-fondo-alt); }
.buscador-modal-todos[hidden] { display: none; }

@media (max-width: 700px) {
    /* En pantalla chica el modal ocupa todo: el panel es la pantalla. */
    .buscador-modal { padding: 0; }
    .buscador-modal-panel { max-width: none; border-radius: 0; height: 100%; }
}

/* ================================================================
   Streaming / Efemerides banner (azul)
================================================================= */
.streming-seccion {
    background-color: var(--color-primario);
    padding: 25px 0;
    color: #fff;
}
.streming-row {
    display: grid;
    grid-template-columns: 2fr 1fr;
    gap: 20px;
    align-items: start;
}
.visor {
    display: grid; grid-template-columns: 3fr 1fr;
    background: #000; border-radius: var(--radio);
    overflow: hidden;
}
.visor-video {
    background: #000; display: flex; align-items: center; justify-content: center;
    color: #fff; overflow: hidden; padding: 10px; box-sizing: border-box;
    aspect-ratio: 16 / 9; align-self: start;
}
.visor-video-placeholder {
    text-align: center; padding: 2rem 1rem; opacity: 0.75;
}
.visor-video-placeholder .icono { font-size: 3rem; display: block; margin-bottom: 0.5rem; }
.visor-video-player {
    width: 100%; height: 100%;
    display: block; object-fit: cover;
    border-radius: var(--radio);
}
.visor-video-iframe {
    width: 100%; height: 100%;
    display: block; border: 0;
    border-radius: var(--radio);
}
.visor-canal.is-active { background: var(--color-primario); color: #fff; }
.visor-canales {
    background: #1B1B1B; padding: 12px; overflow-y: auto;
    display: flex; flex-direction: column; gap: 8px;
}
.visor-canal {
    font-family: var(--fuente-sitio);
    background: rgba(0,0,0,0.5); color: #fff;
    padding: 10px; border-radius: 8px; text-align: center;
    font-weight: 600; font-size: 0.85rem;
    text-decoration: none;
}
.visor-canal:hover { background: rgba(0,0,0,0.8); color: #fff; }

.efemerides {
    font-family: var(--fuente-sitio);
    background: var(--color-fondo-oscuro);
    color: #fff; padding: 22px 24px;
    border-radius: var(--radio);
    display: flex; flex-direction: column;
    min-height: 320px;
}
.efemerides-eyebrow {
    font-family: var(--fuente-sitio);
    font-size: 0.85rem; opacity: 0.9; margin: 0 0 4px;
    text-transform: uppercase; letter-spacing: 0.08em;
}
.efemeride-titulo {
    font-family: var(--fuente-sitio);
    font-size: 1.6rem; font-weight: 700; color: #fff;
    margin: 0 0 8px;
}
.efemeride-hr {
    border: 0; height: 1px; background: rgba(255,255,255,0.25);
    margin: 6px 0 12px;
}
.efemeride-parrafo {
    font-family: var(--fuente-sitio);
    font-size: 1rem; line-height: 1.55; flex: 1; margin: 0;
    display: -webkit-box; -webkit-line-clamp: 6; -webkit-box-orient: vertical;
    overflow: hidden;
}
.efemeride-seguir {
    font-family: var(--fuente-sitio);
    margin-top: 14px; text-align: right; font-weight: 600;
}
.efemeride-seguir a { color: #fff; text-decoration: none; }
.efemeride-seguir a:hover { color: #fff; text-decoration: underline; }

/* ================================================================
   Secciones alternadas blanco / gris
================================================================= */
.seccion {
    padding: 30px 0;
    margin: 0;
}
.seccion-blanca { background: #fff; }
.seccion-gris   { background: rgba(0, 0, 0, 0.04); }

/* Filas de continuacion (Portada SJM): una banda con mas de 4 fichas se
   guarda como varias secciones encadenadas. Colapsando el padding entre
   ellas y con el mismo fondo, el visitante ve una sola banda con varias
   filas separadas por el mismo gap que la grilla (20px). */
.seccion-continua     { padding-bottom: 10px; }
.seccion-continuacion { padding-top: 10px; }

.seccion-titulo {
    margin: 0 0 20px;
    font-family: var(--fuente-sitio);
    font-size: 1.6rem; font-weight: 600;
    color: #333;
}
.seccion-titulo a {
    color: #333; display: inline-flex; align-items: center; gap: 0.5rem;
}
.seccion-titulo a:hover { color: var(--color-primario); }
.seccion-titulo .plus {
    display: inline-block; width: 22px; height: 22px;
    border: 1px solid #999; border-radius: 3px;
    line-height: 20px; text-align: center; font-size: 1rem;
    color: #999; font-weight: 300;
}
.seccion-titulo a:hover .plus { border-color: var(--color-primario); color: var(--color-primario); }

/* ================================================================
   Grilla de fichas
================================================================= */
/* grid-1 y grid-2 las usa la portada administrada desde cloud
   ("Portada SJM"), donde cada seccion elige entre 1 y 4 columnas. */
.grid { display: grid; gap: 20px; }
.grid-1 { grid-template-columns: 1fr; }
.grid-2 { grid-template-columns: repeat(2, 1fr); }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-4 { grid-template-columns: repeat(4, 1fr); }
.grid-6 { grid-template-columns: repeat(6, 1fr); }

@media (max-width: 900px) {
    .grid-3, .grid-4, .grid-6 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
    .grid-2, .grid-3, .grid-4, .grid-6 { grid-template-columns: 1fr; }
}

/* ================================================================
   Fichas / cards estilo SJM
================================================================= */
.ficha {
    background: #fff;
    border-radius: var(--radio);
    border: 1px solid rgba(0, 0, 0, 0.08);
    overflow: hidden;
    display: flex; flex-direction: column;
    box-shadow: var(--sombra);
    transition: transform 0.15s ease, box-shadow 0.15s ease;
    height: 100%;
}
.seccion-gris .ficha { background: #fff; border-color: rgba(0,0,0,0.10); }
.seccion-blanca .ficha { background: rgba(0,0,0,0.02); border-color: rgba(0,0,0,0.08); }
.ficha:hover { transform: translateY(-3px); box-shadow: var(--sombra-hover); }

.ficha-nombre {
    background: var(--color-primario);
    border-top-left-radius: var(--radio);
    border-top-right-radius: var(--radio);
    margin: -1px -1px 0;
}
.ficha-nombre a {
    font-family: var(--fuente-sitio);
    color: #fff; display: block; padding: 8px 12px;
    font-weight: 700; font-size: 0.9rem;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ficha-nombre a:hover { color: #fff; text-decoration: none; }

.ficha-figura {
    background: #fff;
    height: 200px;
    overflow: hidden;
    display: flex; align-items: center; justify-content: center;
    border-bottom: 1px solid var(--color-borde);
    position: relative;
}
.ficha-figura img {
    width: 100%; height: 100%; object-fit: cover; display: block;
    transition: transform 0.4s;
}
.ficha:hover .ficha-figura img { transform: scale(1.04); }

.ficha-cuerpo {
    padding: 12px 14px 16px;
    display: flex; flex-direction: column; flex: 1;
    min-height: 0;
}
.ficha-cuerpo h4 {
    margin: 0 0 6px;
    font-family: var(--fuente-sitio);
    font-size: 1.02rem;
    line-height: 1.3;
    color: #222;
}
.ficha-cuerpo h4 a { color: #222; }
.ficha-cuerpo h4 a:hover { color: var(--color-primario); }
.ficha-fecha {
    font-family: var(--fuente-sitio);
    display: block; color: #999;
    font-size: 0.78rem; margin-bottom: 8px;
}
.ficha-copete {
    font-family: var(--fuente-sitio);
    color: #555; font-size: 0.88rem; line-height: 1.45;
    margin: 0;
    display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical;
    overflow: hidden; text-overflow: ellipsis;
}

/* Card de personalidad (mantenido para compatibilidad, restyleado) */
.card-personalidad {
    background: #fff; border-radius: var(--radio);
    border: 1px solid rgba(0,0,0,0.08);
    box-shadow: var(--sombra);
    overflow: hidden;
    text-align: center;
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.card-personalidad:hover { transform: translateY(-3px); box-shadow: var(--sombra-hover); }
.card-personalidad .card-imagen {
    display: block; aspect-ratio: 3/4;
    background: var(--color-fondo-alt); overflow: hidden;
}
.card-personalidad .card-imagen img { width: 100%; height: 100%; object-fit: cover; }
.card-personalidad .card-cuerpo { padding: 10px 12px 14px; }
.card-personalidad .card-titulo { margin: 0 0 4px; font-size: 0.98rem; }
.card-personalidad .card-titulo a { color: #222; }
.card-personalidad .card-titulo a:hover { color: var(--color-primario); }
.card-personalidad .card-meta { margin: 0; color: #999; font-size: 0.78rem; }

/* ================================================================
   Articulo individual
================================================================= */
.articulo-page { margin: 2rem auto; }
.articulo-layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 300px;
    gap: 40px;
    align-items: start;
}
.articulo-page .articulo { max-width: none; margin: 0; padding: 0; }

.articulo-aside {
    font-family: var(--fuente-sitio);
    display: flex; flex-direction: column; gap: 20px;
    position: sticky; top: 80px;
}
.aside-widget {
    background: #fff;
    border: 1px solid var(--color-borde);
    border-radius: var(--radio);
    overflow: hidden;
    box-shadow: var(--sombra);
}
.aside-titulo {
    background: var(--color-primario);
    color: #fff;
    margin: 0;
    padding: 10px 14px;
    font-family: var(--fuente-sitio);
    font-size: 0.9rem; font-weight: 700;
    text-transform: uppercase; letter-spacing: 0.06em;
}
.aside-lista { list-style: none; margin: 0; padding: 0; }
.aside-item {
    display: grid;
    grid-template-columns: 84px 1fr;
    gap: 10px;
    padding: 12px 14px;
    border-top: 1px solid var(--color-borde);
}
.aside-item:first-child { border-top: 0; }
.aside-thumb {
    width: 84px; height: 64px;
    overflow: hidden; border-radius: 6px;
    display: block; background: var(--color-fondo-alt);
}
.aside-thumb img { width: 100%; height: 100%; object-fit: cover; }
.aside-cuerpo { min-width: 0; display: flex; flex-direction: column; justify-content: center; }
.aside-cuerpo h4 {
    margin: 0 0 4px;
    font-family: var(--fuente-sitio);
    font-size: 0.88rem; line-height: 1.3; font-weight: 600;
    display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
    overflow: hidden;
}
.aside-cuerpo h4 a { color: #222; }
.aside-cuerpo h4 a:hover { color: var(--color-primario); }
.aside-cuerpo time { color: #999; font-size: 0.75rem; }

@media (max-width: 900px) {
    .articulo-layout { grid-template-columns: 1fr; gap: 24px; }
    .articulo-aside { position: static; }
}

.articulo { max-width: 800px; margin: 2rem auto; padding: 0 15px; }
.articulo-header { margin-bottom: 1.5rem; }
.articulo-categoria {
    font-family: var(--fuente-sitio);
    margin: 0 0 0.5rem; text-transform: uppercase; letter-spacing: 0.08em;
    font-size: 0.82rem; color: var(--color-primario); font-weight: 700;
}
.articulo-volanta {
    font-family: var(--fuente-sitio);
    margin: 0 0 0.4rem; color: var(--color-primario);
    text-transform: uppercase; letter-spacing: 0.05em;
    font-size: 0.9rem; font-weight: 600;
}
.articulo-titulo {
    font-family: var(--fuente-sitio);
    font-size: 2.2rem; line-height: 1.2;
    color: #222; margin: 0 0 0.6rem;
}
.articulo-copete {
    font-family: var(--fuente-sitio);
    font-size: 1.15rem; color: #555; margin: 0 0 1rem;
    font-weight: 400;
}
.articulo-meta {
    font-family: var(--fuente-sitio);
    margin: 0; color: #999; font-size: 0.85rem;
}
.articulo-meta .sep { margin: 0 0.4rem; }

/* Firma: autor (con avatar circular) a la izquierda, fecha a la derecha. */
.articulo-firma {
    font-family: var(--fuente-sitio);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    margin: 0.5rem 0 0;
    color: #666;
    font-size: 0.9rem;
    flex-wrap: wrap;
}
.articulo-firma-autor {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    min-width: 0;
    color: inherit;
    text-decoration: none;
}
a.articulo-firma-autor:hover .articulo-firma-nombre,
a.articulo-firma-autor:focus-visible .articulo-firma-nombre {
    text-decoration: underline;
}
.articulo-firma-avatar {
    display: inline-block;
    width: 40px; height: 40px;
    border-radius: 50%;
    overflow: hidden;
    background: var(--color-fondo-alt);
    flex-shrink: 0;
    box-shadow: 0 1px 2px rgba(0,0,0,0.08);
}
.articulo-firma-avatar img {
    width: 100%; height: 100%;
    object-fit: cover;
    display: block;
}
.articulo-firma-nombre {
    color: #444;
    font-weight: 600;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.articulo-firma-fecha {
    color: #444;
    flex-shrink: 0;
}
.articulo-fuente {
    font-family: var(--fuente-sitio);
    margin: 0.4rem 0 0;
    color: #999;
    font-size: 0.82rem;
}
.articulo-portada { margin: 1.5rem 0; }
.articulo-portada img { border-radius: var(--radio); width: 100%; }
.articulo-portada figcaption {
    font-family: var(--fuente-sitio);
    font-size: 0.85rem; color: #666; margin-top: 0.4rem;
}
.articulo-cuerpo { font-family: var(--fuente-sitio); font-size: 1.02rem; line-height: 1.7; color: #333; }
/* Los headings h1-h4 tienen una regla global (h1,h2,h3,h4 { font-family: --fuente-titular })
   que gana por especificidad sobre el font-family de .articulo-cuerpo. Este override
   scopeado a la pagina de articulo fuerza a que TODO heading interior use la fuente maestra. */
.articulo-page h1,
.articulo-page h2,
.articulo-page h3,
.articulo-page h4 { font-family: var(--fuente-sitio); }
.articulo-cuerpo p { margin: 0 0 1.2em; }
/* Imagenes incrustadas en el texto (vienen en el `cuerpo` del articulo).
   La regla global img{display:block} las deja pegadas al margen izquierdo:
   el margin auto las centra en la columna de lectura. */
.articulo-cuerpo img { border-radius: var(--radio); margin: 1.4em auto; }
.articulo-cuerpo figure { margin: 1.4em 0; }
.articulo-cuerpo figure img { margin: 0 auto; }
.articulo-cuerpo figcaption {
    font-size: 0.85rem; color: #666; text-align: center; margin-top: 0.5rem;
}
.articulo-galeria { margin-top: 2rem; }
.articulo-galeria figure {
    margin: 0;
    background: #fafafa;
    border: 1px solid rgba(0, 0, 0, 0.08);
    border-radius: var(--radio);
    overflow: hidden;
    box-shadow: var(--sombra);
    display: flex; flex-direction: column;
    min-width: 0;
}
.articulo-galeria figure img {
    display: block;
    width: 100%;
    aspect-ratio: 4 / 3;
    object-fit: cover;
    background: var(--color-fondo-alt);
    border-radius: 0;
    margin: 0;
}
.articulo-galeria figcaption {
    font-family: var(--fuente-sitio);
    font-size: 0.85rem; color: #666;
    padding: 8px 12px 10px;
    margin: 0;
    line-height: 1.35;
    /* Acotar el epigrafe al alto de la tarjeta: caja fija de 4 lineas
       (mas el padding) para que todas las figuras midan lo mismo, y lo que
       no entra se corta. En vez de un corte seco (o de una elipsis que en
       flex deja media linea asomando), el texto se desvanece: la mascara
       es opaca hasta el final de la linea 3 y va a transparencia total a
       lo largo de la linea 4. Si el epigrafe entra en 3 lineas o menos, la
       zona del degrade queda vacia y no se nota. */
    height: calc(1.35em * 4 + 18px);
    overflow: hidden;
    word-break: break-word;
    overflow-wrap: anywhere;
    -webkit-mask-image: linear-gradient(to bottom,
        #000 calc(100% - 2.15em), rgba(0, 0, 0, 0) calc(100% - 0.45em));
    mask-image: linear-gradient(to bottom,
        #000 calc(100% - 2.15em), rgba(0, 0, 0, 0) calc(100% - 0.45em));
}
/* Navegadores sin mask-image: se vuelve al recorte por lineas con elipsis. */
@supports not ((mask-image: linear-gradient(#000, #000)) or (-webkit-mask-image: linear-gradient(#000, #000))) {
    .articulo-galeria figcaption {
        height: auto;
        display: -webkit-box;
        -webkit-line-clamp: 3;
        -webkit-box-orient: vertical;
        text-overflow: ellipsis;
    }
}
.articulo-tags { margin-top: 2rem; display: flex; flex-wrap: wrap; gap: 0.4rem; }
.tag {
    background: var(--color-fondo-alt); padding: 0.25rem 0.7rem;
    border-radius: 999px; font-size: 0.85rem; color: #333;
}
.tag:hover { background: var(--color-primario); color: #fff; }

/* --- Franja inferior "Mas en {categoria}" (articulos recomendados) ---
   Scopeado a .articulo-page para no impactar otras paginas que tambien
   usan sjm_card_articulo() (categoria, buscar). */
.articulo-page .seccion { font-family: var(--fuente-sitio); }
.articulo-page .seccion-titulo { font-family: var(--fuente-sitio); }
.articulo-page .card-articulo {
    background: var(--color-humo);
    border: 1px solid rgba(0, 0, 0, 0.08);
    border-radius: var(--radio);
    overflow: hidden;
    display: flex; flex-direction: column;
    box-shadow: var(--sombra);
    transition: transform 0.15s ease, box-shadow 0.15s ease;
    height: 100%;
}
.articulo-page .card-articulo:hover {
    transform: translateY(-3px);
    box-shadow: var(--sombra-hover);
}
.articulo-page .card-articulo .card-imagen {
    display: block;
    aspect-ratio: 4 / 3;
    background: var(--color-fondo-alt);
    overflow: hidden;
    border-radius: var(--radio);
}
.articulo-page .card-articulo .card-imagen img {
    width: 100%; height: 100%;
    object-fit: cover;
    display: block;
    border-radius: var(--radio);
    transition: transform 0.25s ease;
}
.articulo-page .card-articulo:hover .card-imagen img { transform: scale(1.04); }
.articulo-page .card-articulo .card-cuerpo {
    padding: 12px 14px 16px;
    display: flex; flex-direction: column; flex: 1;
    min-width: 0;
}
.articulo-page .card-articulo .card-volanta {
    margin: 0 0 4px;
    color: var(--color-primario);
    text-transform: uppercase; letter-spacing: 0.05em;
    font-size: 0.72rem; font-weight: 700;
}
.articulo-page .card-articulo .card-titulo {
    margin: 0 0 6px;
    font-size: 1rem; line-height: 1.3;
    font-weight: 700;
    color: #222;
}
.articulo-page .card-articulo .card-titulo a { color: #222; }
.articulo-page .card-articulo .card-titulo a:hover { color: var(--color-primario); }
.articulo-page .card-articulo .card-copete {
    color: #555;
    font-size: 0.88rem; line-height: 1.45;
    margin: 0 0 8px;
    display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
    overflow: hidden; text-overflow: ellipsis;
}
.articulo-page .card-articulo .card-meta {
    margin: auto 0 0;
    color: #999;
    font-size: 0.78rem;
}

/* ================================================================
   Personalidad
================================================================= */
.personalidad { max-width: 900px; margin: 2rem auto; padding: 0 15px; }
.personalidad-header {
    display: flex; gap: 1.5rem; align-items: center; margin-bottom: 1.5rem;
    flex-wrap: wrap;
}
.personalidad-retrato {
    width: 180px; height: 220px; object-fit: cover;
    border-radius: var(--radio); box-shadow: var(--sombra);
}
.personalidad-nombre { margin: 0 0 0.3rem; color: #222; }
.personalidad-fechas { margin: 0; color: #666; }
.personalidad-cuerpo { font-size: 1.02rem; line-height: 1.7; color: #333; }

/* ================================================================
   Paginas genericas
================================================================= */
.page-header { margin: 1.5rem 0 2rem; padding: 0 15px; }
.page-header h1 { color: #222; margin-bottom: 0.3rem; }
.page-sub { color: #666; margin: 0 0 1rem; }

.chips { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.chip {
    background: #fff; border: 1px solid var(--color-borde);
    padding: 0.3rem 0.8rem; border-radius: 999px; font-size: 0.9rem;
    color: #333;
}
.chip:hover { border-color: var(--color-primario); color: var(--color-primario); }

.abc { display: flex; flex-wrap: wrap; gap: 0.25rem; }
.abc-item {
    display: inline-block; min-width: 32px; padding: 0.25rem 0.5rem;
    text-align: center; border-radius: 4px;
    color: #333; border: 1px solid transparent;
}
.abc-item:hover { background: var(--color-fondo-alt); }
.abc-item.is-activo {
    background: var(--color-primario); color: #fff; border-color: var(--color-primario);
}

.empty-state {
    background: var(--color-fondo-alt);
    border-radius: var(--radio);
    padding: 2rem; text-align: center; color: #666;
}

/* ================================================================
   Buscador dedicado
================================================================= */
.search-form { display: flex; gap: 0.5rem; margin-top: 1rem; }
.search-form input {
    flex: 1; padding: 0.6rem 0.9rem; font-size: 1rem;
    border: 1px solid var(--color-borde); border-radius: 4px;
}
.search-form button {
    background: var(--color-primario); color: #fff; border: none;
    padding: 0 1.2rem; border-radius: 4px; cursor: pointer;
    font-size: 1rem;
}
.search-form button:hover { background: var(--color-primario-oscuro); }

/* ================================================================
   404
================================================================= */
.hero-404 { text-align: center; padding: 4rem 0; }
.hero-404 h1 { font-size: 6rem; color: var(--color-primario); margin: 0; }
.btn {
    display: inline-block;
    background: var(--color-primario); color: #fff;
    padding: 0.6rem 1.2rem; border-radius: 4px;
    margin-top: 1rem; font-weight: 600;
}
.btn:hover { background: var(--color-primario-oscuro); color: #fff; }

/* ================================================================
   Footer oscuro estilo SJM
================================================================= */
.site-footer {
    font-family: var(--fuente-sitio);
    background: #1a1a1a; color: #bbb;
    margin-top: 0; padding: 40px 0 0;
    font-size: 0.9rem;
}
.site-footer a { color: #ccc; }
.site-footer a:hover { color: #fff; text-decoration: none; }
/* Override para la regla global h1-h4 { font-family: --fuente-titular } y
   para .site-brand-main / .site-brand-sub, que tambien fuerzan otra fuente. */
.site-footer h1, .site-footer h2, .site-footer h3, .site-footer h4,
.site-footer .site-brand-main, .site-footer .site-brand-sub {
    font-family: var(--fuente-sitio);
}
.site-footer-row {
    display: grid;
    grid-template-columns: 2fr 1fr 2fr;
    gap: 30px;
    padding-bottom: 30px;
}
.site-footer-col h4 {
    color: #fff; font-size: 0.95rem; letter-spacing: 0.15em;
    text-transform: uppercase; margin-bottom: 14px; font-weight: 700;
}
.site-footer-brand-block { display: flex; flex-direction: column; gap: 8px; }
.site-footer-brand-block .site-brand-main { color: #fff; font-size: 1.5rem; }
.site-footer-brand-block .site-brand-sub { color: #aaa; }
.site-footer-brand-block p { margin: 6px 0 0; color: #aaa; }
.site-footer-links { list-style: none; padding: 0; margin: 0; }
.site-footer-links li { padding: 4px 0; }
.site-footer-copy {
    background: #111; color: #999; text-align: left;
    padding: 14px 0; font-size: 0.82rem;
    border-top: 1px solid rgba(255,255,255,0.05);
}
.site-footer-copy .site-footer-row {
    display: flex; justify-content: space-between;
    padding: 0; gap: 1rem; flex-wrap: wrap;
}
.site-footer-copy a { color: #ccc; }

/* ================================================================
   Responsive
================================================================= */
@media (max-width: 960px) {
    .streming-row { grid-template-columns: 1fr; }
    .visor { grid-template-columns: 1fr; min-height: auto; }
    .visor-video { min-height: 220px; }
    .visor-canales { flex-direction: row; overflow-x: auto; padding: 10px; }
    .visor-canal { min-width: 130px; }
    .site-footer-row { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 700px) {
    h1 { font-size: 1.6rem; }
    .articulo-titulo { font-size: 1.6rem; }

    /* Mobile: brand a la izquierda, hamburguesa a la derecha, sin buscador
       en la cabecera, y el menú plegado hasta destaparlo. */
    .site-header-row { gap: 0.5rem 0.75rem; }
    .site-brand { margin-right: 0; }
    .site-menu-toggle { display: inline-flex; order: 2; }

    /* El panel del menu va FUERA DEL FLUJO del header, y eso no es cosmetico.
       Si participara del flujo, su alto entraria en el `offsetHeight` que
       app.js publica como `--sjm-header-h`... y el `max-height` de aca abajo
       depende de esa misma variable. La dependencia es circular y no
       converge: se abre el panel -> crece el header -> crece
       `--sjm-header-h` -> el max-height se va a ~0 -> se achica el header ->
       baja la variable -> el panel se vuelve a abrir -> ... Un ciclo por
       frame, que se ve como un parpadeo de alta frecuencia e impide navegar.
       Solo se dispara con los menus largos (Enciclopedia, Trabajos de
       investigacion desplegados), que son los unicos que llegan a topear el
       max-height; los cortos se estabilizan en la primera pasada y por eso
       parecian sanos.
       Absolutamente posicionado, el header mide siempre lo mismo este el
       menu abierto o cerrado, la cuenta cierra a la primera y de paso abrir
       el menu ya no empuja hacia abajo la .nav-topbar sticky ni el resto de
       la pagina. El bloque contenedor es .site-header (es `sticky`, o sea
       un elemento posicionado). */
    .site-nav {
        position: absolute;
        top: 100%;
        left: 0;
        right: 0;
        z-index: 1;
        flex-direction: column;
        /* `nowrap` explicito: la regla base trae `flex-wrap: wrap`, que en un
           contenedor en columna con max-height reparte los items en varias
           columnas en vez de dejarlos scrollear. */
        flex-wrap: nowrap;
        align-items: stretch;
        justify-content: flex-start;
        gap: 0;
        margin: 0;
        padding: 0.35rem 0;
        background: #fff;
        border-top: 1px solid var(--color-borde);
        border-bottom: 1px solid var(--color-borde);
        box-shadow: 0 10px 22px rgba(0,0,0,0.18);
        display: none;
        max-height: calc(100vh - var(--sjm-header-h, 78px) - 12px);
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
        /* El scroll del panel no se encadena al de la pagina. */
        overscroll-behavior: contain;
    }
    .site-nav.is-open { display: flex; }
    .site-nav a {
        padding: 0.75rem 1rem;
        font-size: 0.85rem;
        white-space: normal;
        border-radius: 0;
    }
    .site-nav-item { display: block; width: 100%; }
    .site-nav-item.has-dropdown { flex-direction: column; align-items: stretch; }
    /* `flex` (no `inline-flex`) para que la fila del acordeon ocupe todo el
       ancho y el area clickeable llegue hasta el borde derecho. */
    .site-nav-toggle { display: flex; }
    /* Sobrescribe la regla desktop que muestra el dropdown al :hover /
       :focus-within / .is-open: en mobile manda el acordeón (.is-expanded). */
    .site-nav-item:not(.has-js):hover > .site-nav-dropdown,
    .site-nav-item:not(.has-js):focus-within > .site-nav-dropdown,
    .site-nav-item.is-open > .site-nav-dropdown { display: none; animation: none; }
    .site-nav-dropdown {
        position: static;
        display: none;
        border: 0;
        box-shadow: none;
        margin: 0;
        padding: 0 0 0.25rem;
        min-width: 0;
        background: var(--color-fondo-alt);
    }
    .site-nav-item.is-expanded > .site-nav-dropdown { display: block; }
    .site-nav-dropdown a { padding: 0.55rem 1.75rem; font-size: 0.85rem; }

    /* En mobile el buscador de la cabecera no se muestra: no hay ancho para
       el campo. La búsqueda entra por el ítem "Buscar" del menú, que abre el
       mismo modal (y sin JS lleva a /buscar). Va primero en la lista porque
       es la acción que más se busca al desplegar el menú. */
    .site-search { display: none; }
    .site-nav a.site-nav-buscar { display: flex; }

    .site-footer-row { grid-template-columns: 1fr; }
    .seccion { padding: 22px 0; }
    .seccion-titulo { font-size: 1.3rem; }
}

/* ================================================================
   Banco de Fotos
   Las clases de "chrome" de esta seccion (bdf-topbar, bdf-buscador,
   bdf-layout, bdf-tree*, bdf-resultados, bdf-loader-spinner, bdf-fin) las
   comparte tambien el Banco de Videos. Cambiarlas impacta en las dos paginas.
   Los chips (bdf-filtros*) nacieron como filtro de categoria; cuando las dos
   pantallas pasaron a la barra lateral quedaron libres y hoy los usa el filtro
   por epoca del Banco de Fotos, que es multiple y va en linea arriba de todo.
================================================================= */

/* --- Barra celeste full-width con el nombre de la seccion --- */
.bdf-topbar {
    background-color: var(--color-primario);
    color: #fff;
    padding: 22px 0;
    box-shadow: inset 0 -3px 0 rgba(0,0,0,0.08);
    font-family: var(--fuente-sitio);
}
.bdf-topbar-row {
    display: flex; flex-direction: column; align-items: flex-start; gap: 0.25rem;
}
.bdf-topbar-titulo {
    font-family: var(--fuente-sitio);
    font-size: 2rem; font-weight: 700;
    color: #fff;
    margin: 0;
    letter-spacing: -0.02em;
}
.bdf-topbar-sub {
    color: rgba(255,255,255,0.9);
    font-size: 1rem; margin: 0;
}

/* --- Hero (card de busqueda + contador) --- */
.bdf-hero { margin: 1.75rem 0 1.75rem; font-family: var(--fuente-sitio); }

/* --- Card contenedor del buscador + filtros --- */
.bdf-buscador {
    background: #fff;
    border: 1px solid var(--color-borde);
    border-radius: 12px;
    box-shadow: 0 2px 12px rgba(0,0,0,0.04);
    padding: 1.1rem 1.2rem;
    display: flex; flex-direction: column; gap: 1rem;
    font-family: var(--fuente-sitio);
}

/* --- Input de busqueda: barra unificada con icono + campo + boton --- */
.bdf-buscador-input {
    display: flex; align-items: stretch;
    border: 1px solid var(--color-borde);
    border-radius: 8px;
    background: #fff;
    overflow: hidden;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.bdf-buscador-input:focus-within {
    border-color: var(--color-primario);
    box-shadow: 0 0 0 3px rgba(25, 128, 182, 0.15);
}
.bdf-buscador-icono {
    width: 22px; height: 22px;
    color: var(--color-texto-suave);
    align-self: center;
    margin-left: 0.9rem;
    flex-shrink: 0;
}
.bdf-buscador-campo {
    flex: 1;
    border: none; outline: none; background: transparent;
    padding: 0.85rem 0.75rem;
    font-size: 1.02rem;
    font-family: var(--fuente-sitio);
    color: var(--color-texto);
    min-width: 0;
}
.bdf-buscador-campo::placeholder { color: #999; }
.bdf-buscador-btn {
    background: var(--color-primario);
    color: #fff;
    border: none;
    padding: 0 1.5rem;
    font-size: 0.95rem; font-weight: 600;
    letter-spacing: 0.02em;
    cursor: pointer;
    transition: background 0.15s ease;
    font-family: var(--fuente-sitio);
}
.bdf-buscador-btn:hover { background: var(--color-primario-oscuro); }

/* --- Fila de filtros en linea (hoy: las epocas del Banco de Fotos) --- */
.bdf-filtros {
    display: flex; align-items: center; gap: 0.75rem;
    flex-wrap: wrap;
    padding-top: 0.4rem;
    border-top: 1px dashed #eee;
}
.bdf-filtros-label {
    font-size: 0.78rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--color-texto-suave);
    font-weight: 700;
    padding-top: 0.3rem;
}
.bdf-filtros-chips {
    display: flex; flex-wrap: wrap; gap: 0.4rem;
    flex: 1;
}
.bdf-filtro {
    display: inline-block;
    background: var(--color-fondo-alt);
    color: #444;
    border: 1px solid transparent;
    padding: 0.35rem 0.85rem;
    border-radius: 999px;
    font-size: 0.88rem;
    font-weight: 500;
    transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
    white-space: nowrap;
}
.bdf-filtro:hover {
    background: #e6f2f9;
    color: var(--color-primario-oscuro);
    text-decoration: none;
}
.bdf-filtro.is-activo {
    background: var(--color-primario);
    color: #fff;
    border-color: var(--color-primario);
    box-shadow: 0 2px 6px rgba(25, 128, 182, 0.25);
}
.bdf-filtro.is-activo:hover { background: var(--color-primario-oscuro); color: #fff; }
.bdf-filtros-limpiar {
    font-size: 0.85rem;
    color: var(--color-texto-suave);
    padding: 0.35rem 0.7rem;
    border-radius: 999px;
    background: transparent;
    border: 1px solid transparent;
    transition: color 0.15s ease, background 0.15s ease;
}
.bdf-filtros-limpiar:hover {
    color: #b02a37;
    background: #fbeaec;
    text-decoration: none;
}

/* --- Contador de resultados --- */
.bdf-resultados {
    margin: 1rem 0 0;
    color: var(--color-texto-suave);
    font-size: 0.95rem;
}
.bdf-resultados-num {
    color: #222;
    font-weight: 700;
    font-size: 1.05rem;
    font-variant-numeric: tabular-nums;
}

/* --- Layout de 2 columnas: selector de categorias + resultados ---
   Lo usan las dos pantallas del banco (fotos y videos). El selector es la
   barra lateral calcada del portal legacy; reemplazo a los chips en linea. */
.bdf-layout {
    display: grid;
    grid-template-columns: 260px minmax(0, 1fr);
    gap: 30px;
    align-items: start;
    margin-bottom: 2.5rem;
}
.bdf-listado { min-width: 0; }

/* --- Selector de categorias ---
   Es el card del arbol de /navegar (.nav-tree-*), pero SIN el anclaje sticky
   ni el scroll interno de aquel: aca la barra mide lo que mide su lista y
   scrollea junto con los resultados, como una columna mas de la pagina. Al
   llegar al fondo de la lista queda hueco a la izquierda, y esta bien: es
   preferible a una tarjeta que se despega del contenido.
   De ahi que se desarmen las propiedades que .nav-tree trae para sostener el
   panel fijo (position, max-height y el overflow de la lista); la cabecera,
   ademas, lleva el link de "Limpiar" al lado del titulo.

   OJO con el selector doble: el aside es class="nav-tree bdf-tree" y el bloque
   .nav-tree vive MAS ABAJO en esta hoja. Con un solo .bdf-tree la especificidad
   empata y gana .nav-tree por orden de aparicion, asi que el sticky volvia a
   activarse. Calificar con .nav-tree.bdf-tree lo resuelve sin depender de
   donde quede cada bloque en el archivo. */
.nav-tree.bdf-tree {
    position: static;
    max-height: none;
    z-index: auto;
}
.nav-tree.bdf-tree .nav-tree-lista {
    flex: 0 0 auto;
    overflow-y: visible;
    max-height: none;
}
.bdf-tree-head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 0.6rem;
}
.bdf-tree-limpiar {
    font-size: 0.78rem;
    color: var(--color-texto-suave);
    white-space: nowrap;
}
.bdf-tree-limpiar:hover { color: #b02a37; text-decoration: none; }
/* Categoria sin coincidencias con la busqueda en curso: sigue en la lista
   -para que la barra no cambie de forma con cada termino- pero apagada. */
.bdf-tree .nav-tree-link.is-vacio { opacity: 0.45; }
.bdf-tree .nav-tree-link.is-vacio:hover { opacity: 1; }

/* --- Grilla de resultados ---
   3 columnas y gap de 16px, identica a la del Banco de Videos: desde que el
   tile dejo de ser una miniatura suelta y paso a ser una tarjeta con epigrafe
   y metadatos, con 4 por fila el pie quedaba demasiado angosto. Las dos
   grillas del banco tienen que leerse como la misma.
   El margen de arriba lo pone la grilla del layout. */
.bdf-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 16px;
    margin: 1.5rem 0 2rem;
}
.bdf-layout .bdf-grid { margin-top: 0; }
/* La tarjeta replica la del Banco de Videos: foto arriba, pie con epigrafe y
   metadatos abajo. El radio es el mismo `--radio` de las fichas y las tarjetas
   de categoria, para que las tres grillas del sitio se lean como una familia. */
.bdf-tile {
    display: flex; flex-direction: column;
    background: #fff;
    border: 1px solid var(--color-borde);
    border-radius: var(--radio);
    overflow: hidden;
    box-shadow: var(--sombra);
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.bdf-tile:hover {
    transform: translateY(-2px);
    box-shadow: var(--sombra-hover);
}
/* Box de la foto: el click de aca abre el visor ampliado. El resto de la
   tarjeta no lo abre, asi el enlace "Ver articulo" del pie sigue navegando. */
.bdf-media {
    position: relative;
    display: block;
    aspect-ratio: 3 / 2;
    background: var(--color-fondo-alt);
    overflow: hidden;
}
.bdf-tile img {
    width: 100%; height: 100%;
    object-fit: cover;
    display: block;
    transition: transform 0.25s ease;
}
.bdf-tile:hover img { transform: scale(1.04); }

/* --- Pie de la tarjeta: epigrafe + metadatos (gemelo de .bdv-info) --- */
.bdf-info {
    display: flex; flex-direction: column; gap: 0.35rem;
    padding: 0.6rem 0.7rem 0.7rem;
    font-family: var(--fuente-sitio);
}
.bdf-epigrafe {
    margin: 0;
    font-size: 0.92rem;
    line-height: 1.35;
    color: var(--color-texto);
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.bdf-meta {
    margin: 0;
    display: flex; align-items: center; flex-wrap: wrap; gap: 0.4rem;
    font-size: 0.75rem;
    color: var(--color-texto-suave);
}
.bdf-cat {
    background: var(--color-fondo-alt);
    border-radius: 999px;
    padding: 0.1rem 0.55rem;
}
.bdf-articulo { margin-left: auto; white-space: nowrap; }

/* --- Scroll infinito: sentinel + loader + fin --- */
.bdf-sentinel {
    /* elemento invisible que dispara la carga cuando entra en viewport */
    width: 100%; height: 1px;
    margin: 0; padding: 0;
}
.bdf-loader {
    display: flex; align-items: center; justify-content: center;
    gap: 0.6rem; padding: 1.25rem 0 2rem;
    color: var(--color-texto-suave);
    font-size: 0.95rem;
    font-family: var(--fuente-sitio);
    opacity: 0;
    transition: opacity 0.15s ease;
    min-height: 1.5rem;
}
.bdf-loader.is-visible { opacity: 1; }
.bdf-loader-spinner {
    width: 18px; height: 18px;
    border: 2px solid rgba(25, 128, 182, 0.25);
    border-top-color: var(--color-primario);
    border-radius: 50%;
    display: inline-block;
    animation: bdf-spin 0.8s linear infinite;
}
@keyframes bdf-spin {
    to { transform: rotate(360deg); }
}
.bdf-fin {
    text-align: center;
    color: var(--color-texto-suave);
    font-size: 0.9rem;
    font-family: var(--fuente-sitio);
    padding: 1.5rem 0 2rem;
    margin: 0;
}
.btn.is-disabled {
    background: #ccc; color: #fff; cursor: not-allowed; pointer-events: none;
}

/* --- Visor de la foto ampliada (lightbox) ---
   El markup vive al final de bancodefotos.php y arranca con [hidden]: sin JS
   nunca se ve y cada tile sigue siendo un link al articulo. Lo maneja
   initBancoDeFotosVisor en app.js.
   El Banco de Videos reusa todo este chrome cambiando la <img> por un <video>
   (ver .bdv-visor-video mas abajo). */
.bdf-visor {
    position: fixed; inset: 0;
    /* Por encima del .site-header (100) y del buscador modal (200). */
    z-index: 300;
    display: flex; align-items: center; justify-content: center;
    padding: 24px 16px;
}
/* El display:flex de arriba le gana al display:none de [hidden]. */
.bdf-visor[hidden] { display: none; }
body.has-bdf-visor { overflow: hidden; }

.bdf-visor-fondo {
    position: absolute; inset: 0;
    background: rgba(3, 14, 20, 0.92);
}
.bdf-visor-panel {
    position: relative;
    width: 100%; max-width: 1100px;
    max-height: 100%;
    display: flex; flex-direction: column;
    font-family: var(--fuente-sitio);
    animation: sjm-visor-in .15s ease-out;
}
@keyframes sjm-visor-in {
    from { opacity: 0; transform: scale(0.98); }
    to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
    .bdf-visor-panel { animation: none; }
}

.bdf-visor-cerrar {
    align-self: flex-end;
    background: rgba(255, 255, 255, 0.12); border: none;
    color: #fff;
    width: 36px; height: 36px; border-radius: 50%;
    display: inline-flex; align-items: center; justify-content: center;
    font-size: 1rem; line-height: 1; cursor: pointer;
    margin-bottom: 10px;
    flex: 0 0 auto;
}
.bdf-visor-cerrar:hover { background: rgba(255, 255, 255, 0.25); }

.bdf-visor-figura {
    margin: 0; min-height: 0;
    display: flex; flex-direction: column;
}
.bdf-visor-marco {
    position: relative;
    display: flex; align-items: center; justify-content: center;
    min-height: 0;
}
.bdf-visor-img {
    display: block;
    max-width: 100%; max-height: 74vh;
    width: auto; height: auto;
    object-fit: contain;
    border-radius: 6px;
    box-shadow: 0 18px 45px rgba(0, 0, 0, 0.5);
    transition: opacity .15s ease;
}
.bdf-visor-panel.is-cargando .bdf-visor-img { opacity: 0.35; }

.bdf-visor-spinner {
    position: absolute; top: 50%; left: 50%;
    margin: -14px 0 0 -14px;
    width: 28px; height: 28px;
    border: 3px solid rgba(255, 255, 255, 0.25);
    border-top-color: #fff;
    border-radius: 50%;
    animation: bdf-spin 0.8s linear infinite;
    opacity: 0; pointer-events: none;
    transition: opacity .15s ease;
}
.bdf-visor-panel.is-cargando .bdf-visor-spinner { opacity: 1; }

/* Flechas: van sobre la foto, centradas verticalmente en el marco. */
.bdf-visor-nav {
    position: absolute; top: 50%;
    transform: translateY(-50%);
    width: 46px; height: 46px; border-radius: 50%;
    border: none;
    background: rgba(10, 20, 28, 0.65);
    color: #fff;
    font-size: 1.9rem; line-height: 1;
    display: inline-flex; align-items: center; justify-content: center;
    cursor: pointer;
    transition: background .15s ease, opacity .15s ease;
}
.bdf-visor-nav:hover { background: var(--color-primario); }
.bdf-visor-nav:disabled {
    opacity: 0.25; cursor: default; background: rgba(10, 20, 28, 0.65);
}
.bdf-visor-prev { left: 10px; padding-right: 3px; }
.bdf-visor-next { right: 10px; padding-left: 3px; }

.bdf-visor-pie {
    flex: 0 0 auto;
    margin-top: 14px;
    color: #e9eff3;
    /* Epigrafes largos scrollean en el pie, nunca empujan la foto. */
    max-height: 18vh; overflow-y: auto;
}
.bdf-visor-epigrafe {
    margin: 0;
    font-size: 0.98rem; line-height: 1.45;
}
.bdf-visor-epigrafe[hidden] { display: none; }
.bdf-visor-acciones {
    display: flex; align-items: center; justify-content: space-between;
    gap: 1rem; flex-wrap: wrap;
    margin-top: 0.6rem;
    font-size: 0.85rem;
}
.bdf-visor-contador {
    color: rgba(233, 239, 243, 0.6);
    font-variant-numeric: tabular-nums;
}
.bdf-visor-articulo {
    color: #fff; font-weight: 600;
    border-bottom: 1px solid rgba(255, 255, 255, 0.35);
    padding-bottom: 1px;
}
.bdf-visor-articulo:hover { color: #fff; border-bottom-color: #fff; }

@media (max-width: 900px) {
    /* El selector pasa a ser una lista arriba de los resultados. Sigue sin
       tope de alto ni scroll propio: la pagina entera es la que scrollea. */
    .bdf-layout { grid-template-columns: 1fr; gap: 20px; }
    /* La grilla ya viene en 3 columnas desde el ancho completo, asi que aca no
       hace falta tocarla: solo baja a 2 en el breakpoint de 600px. */
    .bdf-topbar-titulo { font-size: 1.6rem; }
    .bdf-topbar { padding: 18px 0; }
}
@media (max-width: 600px) {
    .bdf-grid { grid-template-columns: repeat(2, 1fr); }
    .bdf-buscador { padding: 0.9rem; }
    .bdf-buscador-campo { padding: 0.75rem 0.55rem; font-size: 0.95rem; }
    .bdf-buscador-btn { padding: 0 1rem; }
    .bdf-filtros-label { flex-basis: 100%; }

    .bdf-visor { padding: 12px 8px; }
    .bdf-visor-img { max-height: 62vh; }
    .bdf-visor-nav { width: 38px; height: 38px; font-size: 1.5rem; }
    .bdf-visor-prev { left: 4px; }
    .bdf-visor-next { right: 4px; }
    .bdf-visor-epigrafe { font-size: 0.9rem; }
    .bdf-visor-pie { max-height: 22vh; }
}

/* ================================================================
   Banco de Videos

   El "chrome" (topbar, card del buscador, layout de 2 columnas + selector de
   categorias, contador, spinner y pie del listado) es el mismo del Banco de
   Fotos y se reusa tal cual con las clases .bdf-*, incluido el visor ampliado
   (.bdf-visor-*). Aca va solo lo propio de la videoteca: la grilla de tarjetas
   y el <video> que se monta dentro del visor.
================================================================= */

/* --- Grilla de resultados ---
   Dentro del layout la columna es mas angosta que el ancho completo, asi que
   entran 3 tarjetas y no 4. El margen de arriba lo pone la grilla del layout. */
.bdv-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 16px;
    margin: 1.5rem 0 2rem;
}
.bdf-layout .bdv-grid {
    grid-template-columns: repeat(3, 1fr);
    margin-top: 0;
}
.bdv-tile {
    display: flex; flex-direction: column;
    background: #fff;
    border: 1px solid var(--color-borde);
    /* Mismo radio que las fichas y las tarjetas de categoria (ver .bdf-tile). */
    border-radius: var(--radio);
    overflow: hidden;
    box-shadow: var(--sombra);
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.bdv-tile:hover {
    transform: translateY(-2px);
    box-shadow: var(--sombra-hover);
}
/* Box de la tapa: el click de aca abre el visor ampliado. */
.bdv-media {
    position: relative;
    display: block;
    aspect-ratio: 4 / 3;
    background: #000;
    overflow: hidden;
}
.bdv-poster {
    width: 100%; height: 100%;
    object-fit: cover;
    display: block;
    transition: transform 0.25s ease, opacity 0.15s ease;
}
.bdv-tile:hover .bdv-poster { transform: scale(1.04); opacity: 0.8; }
/* Boton de play sobreimpreso en la tapa. */
.bdv-play {
    position: absolute; inset: 0;
    display: flex; align-items: center; justify-content: center;
    pointer-events: none;
}
.bdv-play svg {
    width: 30px; height: 30px;
    color: #fff;
    margin-left: 3px;   /* centra opticamente el triangulo dentro del circulo */
    /* El circulo es el ::before de aca abajo, y al estar posicionado se pinta
       POR ENCIMA del contenido en flujo normal -o sea, encima de este svg-.
       Con el fondo negro al 55% el triangulo blanco se transparentaba y algo
       se veia; al pasar el mouse el circulo se vuelve celeste opaco y lo
       tapaba del todo. Posicionar el svg lo sube de capa y queda siempre
       blanco sobre el circulo, con o sin hover. */
    position: relative;
    z-index: 1;
}
.bdv-play::before {
    content: "";
    position: absolute;
    width: 58px; height: 58px;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.55);
    border: 2px solid rgba(255, 255, 255, 0.85);
    transition: background 0.15s ease, transform 0.15s ease;
}
.bdv-tile:hover .bdv-play::before {
    background: var(--color-primario);
    transform: scale(1.06);
}
/* --- Pie de la tarjeta: epigrafe + metadatos --- */
.bdv-info {
    display: flex; flex-direction: column; gap: 0.35rem;
    padding: 0.6rem 0.7rem 0.7rem;
    font-family: var(--fuente-sitio);
}
.bdv-epigrafe {
    margin: 0;
    font-size: 0.92rem;
    line-height: 1.35;
    color: var(--color-texto);
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.bdv-meta {
    margin: 0;
    display: flex; align-items: center; flex-wrap: wrap; gap: 0.4rem;
    font-size: 0.75rem;
    color: var(--color-texto-suave);
}
.bdv-cat {
    background: var(--color-fondo-alt);
    border-radius: 999px;
    padding: 0.1rem 0.55rem;
}
.bdv-articulo { margin-left: auto; white-space: nowrap; }

/* --- Scroll infinito: mismo comportamiento que el Banco de Fotos --- */
.bdv-sentinel { width: 100%; height: 1px; margin: 0; padding: 0; }
.bdv-loader {
    display: flex; align-items: center; justify-content: center;
    gap: 0.6rem; padding: 1.25rem 0 2rem;
    color: var(--color-texto-suave);
    font-size: 0.95rem;
    font-family: var(--fuente-sitio);
    opacity: 0;
    transition: opacity 0.15s ease;
    min-height: 1.5rem;
}
.bdv-loader.is-visible { opacity: 1; }

/* --- Visor del video ampliado (lightbox) ---
   El markup vive al final de bancodevideos.php y arranca con [hidden]: sin JS
   nunca se ve y la tapa sigue siendo un enlace al .mp4. Todo el chrome (fondo,
   panel, boton de cerrar, flechas, spinner y pie) es el del Banco de Fotos
   (.bdf-visor-*); aca va solo el reemplazo de la <img> por el <video> y la
   linea de metadatos del pie. Lo maneja initBancoDeVideosVisor en app.js. */
body.has-bdv-visor { overflow: hidden; }

.bdv-visor-video {
    display: block;
    /* Alto fijo por relacion de aspecto: sin esto el box arranca en el tamano
       por defecto del <video> y salta cuando el navegador lee los metadatos.
       Los videos verticales o 4:3 quedan centrados sobre el fondo negro. */
    width: 100%;
    max-height: 74vh;
    aspect-ratio: 16 / 9;
    object-fit: contain;
    background: #000;
    border-radius: 6px;
    box-shadow: 0 18px 45px rgba(0, 0, 0, 0.5);
    transition: opacity .15s ease;
}
.bdf-visor-panel.is-cargando .bdv-visor-video { opacity: 0.35; }
/* Categoria y fecha: van pegadas al contador y empujan el link del articulo
   contra el borde derecho del pie. */
.bdv-visor-meta {
    margin-right: auto;
    color: rgba(233, 239, 243, 0.6);
}

@media (max-width: 900px) {
    /* El layout y la barra lateral los colapsa la seccion del Banco de Fotos
       (.bdf-layout / .bdf-tree), que es donde vive el componente compartido. */
    .bdv-grid, .bdf-layout .bdv-grid { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 600px) {
    .bdv-grid, .bdf-layout .bdv-grid { grid-template-columns: repeat(2, 1fr); }
    .bdv-grid { gap: 12px; }
    .bdv-play svg { width: 22px; height: 22px; }
    .bdv-play::before { width: 44px; height: 44px; }
    .bdv-epigrafe,
    .bdf-epigrafe { font-size: 0.85rem; -webkit-line-clamp: 2; }

    .bdv-visor-video { max-height: 62vh; }
}

/* ================================================================
   Navegar - arbol de categorias + listado de articulos
================================================================= */

/* --- Barra celeste con titulo "Enciclopedia" + breadcrumb --- */
/* Sticky: se ancla debajo del site-header. Las variables --sjm-header-h /
   --sjm-topbar-h las mide JS en runtime (ver app.js). Los fallbacks son
   los valores desktop tipicos. */
.nav-topbar {
    font-family: var(--fuente-sitio);
    background-color: var(--color-primario);
    color: #fff;
    padding: 22px 0 20px;
    box-shadow: inset 0 -3px 0 rgba(0,0,0,0.08), 0 4px 12px rgba(0,0,0,0.06);
    position: sticky;
    top: var(--sjm-header-h, 65px);
    z-index: 40;
}
/* Variante no anclada: la barra se desplaza con el contenido. La usa
   /articulo, donde lo unico que queda fijo arriba es el site-header. */
.nav-topbar-estatica {
    position: static;
    top: auto;
}
.nav-topbar-row {
    display: flex; flex-direction: column; align-items: flex-start; gap: 0.5rem;
}
.nav-topbar-titulo {
    font-family: var(--fuente-sitio);
    font-size: 2rem; font-weight: 700;
    color: #fff; margin: 0;
    letter-spacing: -0.02em;
}
.nav-topbar-crumbs {
    display: flex; flex-wrap: wrap; align-items: center;
    gap: 0.4rem;
    font-size: 0.95rem;
    color: rgba(255,255,255,0.9);
}
.nav-topbar-crumbs a { color: rgba(255,255,255,0.85); }
.nav-topbar-crumbs a:hover { color: #fff; text-decoration: underline; }
.nav-topbar-crumbs a:last-child { color: #fff; font-weight: 700; }
.nav-topbar-sep { opacity: 0.55; }

/* --- Layout de 2 columnas --- */
.nav-page { margin: 1.75rem auto 2.5rem; }
.nav-layout {
    display: grid;
    grid-template-columns: 260px minmax(0, 1fr);
    gap: 30px;
    align-items: start;
}

/* --- Arbol de categorias (columna izquierda) ---
   Sticky: se ancla justo debajo de la nav-topbar (que a su vez esta
   anclada bajo el site-header). Los tres headers apilados quedan siempre
   visibles al scrollear. align-self: start evita que la grilla lo estire
   y le impida moverse. */
.nav-tree {
    font-family: var(--fuente-sitio);
    background: #fff;
    border: 1px solid var(--color-borde);
    border-radius: 12px;
    box-shadow: 0 2px 12px rgba(0,0,0,0.04);
    overflow: hidden;
    position: sticky;
    position: -webkit-sticky;
    top: calc(var(--sjm-header-h, 75px) + var(--sjm-topbar-h, 105px) + 12px);
    align-self: start;
    z-index: 20;
    max-height: calc(100vh - var(--sjm-header-h, 75px) - var(--sjm-topbar-h, 105px) - 24px);
    display: flex; flex-direction: column;
}
.nav-tree-head {
    padding: 0.7rem 1rem;
    border-bottom: 1px solid var(--color-borde);
    background: var(--color-fondo-alt);
}
.nav-tree-back {
    display: inline-flex; align-items: center; gap: 0.4rem;
    font-size: 0.78rem;
    text-transform: uppercase; letter-spacing: 0.08em;
    color: var(--color-primario-oscuro);
    font-weight: 700;
}
.nav-tree-back:hover { color: var(--color-primario); }
.nav-tree-title {
    font-size: 0.78rem;
    text-transform: uppercase; letter-spacing: 0.08em;
    color: var(--color-texto-suave);
    font-weight: 700;
}
.nav-tree-lista {
    list-style: none;
    margin: 0; padding: 0.35rem 0;
    flex: 1 1 auto;
    overflow-y: auto;
    min-height: 0;
}
.nav-tree-item { margin: 0; padding: 0; }
.nav-tree-link {
    display: flex; align-items: center; justify-content: space-between;
    gap: 0.6rem;
    padding: 0.6rem 1rem;
    color: #333;
    font-size: 0.93rem;
    line-height: 1.3;
    border-left: 3px solid transparent;
    transition: background 0.12s ease, color 0.12s ease, border-color 0.12s ease;
}
.nav-tree-link:hover {
    background: #eef7fc;
    color: var(--color-primario-oscuro);
    border-left-color: var(--color-primario);
    text-decoration: none;
}
/* Categoria seleccionada. Solo la emite el Banco de Videos: /navegar no la
   necesita porque su arbol no lista la categoria en la que uno ya esta, la
   muestra en la cabecera del card. */
.nav-tree-link.is-activo {
    background: var(--color-primario);
    color: #fff;
    border-left-color: var(--color-primario-oscuro);
    font-weight: 600;
}
.nav-tree-link.is-activo:hover { background: var(--color-primario-oscuro); color: #fff; }
.nav-tree-link.is-activo .nav-tree-conteo,
.nav-tree-link.is-activo:hover .nav-tree-conteo {
    background: rgba(255, 255, 255, 0.22);
    color: #fff;
}
.nav-tree-nombre {
    flex: 1; min-width: 0;
    word-break: break-word;
}
.nav-tree-derecha {
    display: inline-flex; align-items: center; gap: 0.35rem;
    flex-shrink: 0;
}
.nav-tree-conteo {
    background: var(--color-fondo-alt);
    color: var(--color-texto-suave);
    font-size: 0.72rem; font-weight: 600;
    padding: 0.1rem 0.5rem;
    border-radius: 999px;
    font-variant-numeric: tabular-nums;
}
.nav-tree-link:hover .nav-tree-conteo { background: #d7ebf6; color: var(--color-primario-oscuro); }
.nav-tree-flecha {
    color: var(--color-texto-suave);
    font-size: 1.15rem; line-height: 1;
}
.nav-tree-link:hover .nav-tree-flecha { color: var(--color-primario); }
.nav-tree-empty {
    padding: 0.9rem 1rem;
    color: var(--color-texto-suave);
    font-size: 0.9rem; margin: 0;
    line-height: 1.4;
}

/* --- Cabecera de resultados: buscador + contador --- */
.nav-resultados { min-width: 0; }
.nav-resultados-head { margin-bottom: 1.5rem; }
.nav-buscador {
    display: flex; align-items: stretch;
    background: #fff;
    border: 1px solid var(--color-borde);
    border-radius: 10px;
    overflow: hidden;
    box-shadow: 0 2px 12px rgba(0,0,0,0.04);
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.nav-buscador:focus-within {
    border-color: var(--color-primario);
    box-shadow: 0 0 0 3px rgba(25, 128, 182, 0.15);
}
.nav-buscador-icono {
    width: 22px; height: 22px;
    color: var(--color-texto-suave);
    align-self: center;
    margin-left: 0.9rem;
    flex-shrink: 0;
}
.nav-buscador-campo {
    flex: 1;
    border: none; outline: none; background: transparent;
    padding: 0.85rem 0.75rem;
    font-size: 1rem;
    font-family: var(--fuente-sitio);
    color: var(--color-texto);
    min-width: 0;
}
.nav-buscador-campo::placeholder { color: #999; }
.nav-buscador-limpiar {
    align-self: center;
    color: var(--color-texto-suave);
    padding: 0 0.75rem;
    font-size: 1rem;
    text-decoration: none;
}
.nav-buscador-limpiar:hover { color: #b02a37; text-decoration: none; }
.nav-buscador-btn {
    background: var(--color-primario);
    color: #fff;
    border: none;
    padding: 0 1.4rem;
    font-family: var(--fuente-sitio);
    font-size: 0.95rem; font-weight: 600;
    letter-spacing: 0.02em;
    cursor: pointer;
    transition: background 0.15s ease;
}
.nav-buscador-btn:hover { background: var(--color-primario-oscuro); }

.nav-resultados-contador {
    margin: 0.9rem 0 0;
    color: var(--color-texto-suave);
    font-size: 0.95rem;
}
.nav-resultados-num {
    color: #222;
    font-weight: 700;
    font-size: 1.05rem;
    font-variant-numeric: tabular-nums;
}

/* --- Listado tipo "row card" (imagen | cuerpo) --- */
.nav-lista {
    display: flex; flex-direction: column; gap: 18px;
    margin: 0 0 2rem;
}
.nav-item {
    /* Ancho de la columna de imagen. Manda el alto de toda la tarjeta: la
       imagen es 3/2, asi que el alto es ancho * 2/3, y de ahi sale tambien el
       alto tope del cuerpo (.nav-item-cuerpo). Los dos valores se derivan de
       esta variable para que no se desincronicen. 235px -> ~157px de alto. */
    --nav-img-ancho: 235px;
    /* Hueco que el texto le reserva a "Ver articulo ->" cuando el link se va al
       angulo inferior derecho (ver .nav-item-cuerpo:not(:has(.nav-item-autor))).
       Tiene que dar para el rotulo entero + aire; el rotulo mide ~101px. */
    --nav-mas-hueco: 118px;
    font-family: var(--fuente-sitio);
    display: grid;
    grid-template-columns: var(--nav-img-ancho) minmax(0, 1fr);
    background: var(--color-humo);
    border: 1px solid var(--color-borde);
    border-radius: 12px;
    overflow: hidden;
    box-shadow: var(--sombra);
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.nav-item:hover {
    transform: translateY(-2px);
    box-shadow: var(--sombra-hover);
}
.nav-item-imagen {
    display: block;
    background: var(--color-fondo-alt);
    aspect-ratio: 3 / 2;
    overflow: hidden;
}
.nav-item-imagen img {
    width: 100%; height: 100%;
    object-fit: cover;
    transition: transform 0.35s ease;
}
.nav-item:hover .nav-item-imagen img { transform: scale(1.04); }

.nav-item-cuerpo {
    padding: 0.5rem 0.6rem 0.55rem;
    display: flex; flex-direction: column; gap: 0.45rem;
    min-width: 0;
    /* Alto tope = alto de la imagen (--nav-img-ancho * 2/3 aspect-ratio). El
       texto que exceda ese alto queda escondido por overflow y se disimula con
       el degrade blanco de .nav-item-texto::after, dejando el pie
       (.nav-item-pie) siempre visible sobre fondo blanco. */
    max-height: calc(var(--nav-img-ancho) * 2 / 3);
    overflow: hidden;
}
.nav-item-texto {
    flex: 1;
    min-height: 0;
    overflow: hidden;
    position: relative;
}
.nav-item-texto::after {
    content: '';
    position: absolute;
    left: 0; right: 0; bottom: 0;
    /* ~1,35 lineas del copete (18,99px c/u). Tiene que ser POCO mas que una
       linea: si mide dos, la ultima entra entera en el tramo opaco, no se ve
       nada de ella y queda una banda vacia entre el texto y el pie. */
    height: 1.6em;
    /* Fade hacia el color de fondo de la tarjeta (humo), no hacia blanco,
       para que se disuelva sin cortar. Llega a opaco al 75% y no al final: el
       recorte de .nav-item-texto cae en cualquier punto de una linea, y si el
       degrade todavia no tapo del todo, esa ultima linea queda partida al
       medio y se ve el filo de los glifos. El tramo opaco de abajo (~10px, la
       mitad de una linea) se traga la linea que el recorte parte, sin apurar
       tanto el fade como para comerse la anterior. */
    background: linear-gradient(to bottom, rgba(250,250,250,0), var(--color-humo) 75%);
    pointer-events: none;
}
/* Tarjetas sin autor (casi todas las efemerides): el pie no tiene mas que el
   link "Ver articulo ->", asi que en vez de comerse una fila entera se va al
   angulo inferior derecho. El texto crece hasta el fondo de la tarjeta y su
   ultima linea -la del degrade- queda A LA IZQUIERDA del link, no arriba.
   Las tarjetas CON autor conservan el pie como fila propia: ahi abajo a la
   izquierda va "Por <autor>", que necesita el ancho completo.
   El :has() cubre tanto el HTML de navegar/buscar como las tarjetas que arma
   app.js en el scroll infinito, que son identicas. */
.nav-item-cuerpo:not(:has(.nav-item-autor)) {
    position: relative;
}
.nav-item-cuerpo:not(:has(.nav-item-autor)) .nav-item-pie {
    position: absolute;
    /* Mismo padding lateral / inferior que .nav-item-cuerpo, para que el link
       caiga exactamente donde caia cuando el pie era una fila. */
    right: 0.6rem; bottom: 0.55rem;
    padding-top: 0;
}
/* El hueco va en el copete y no en .nav-item-texto: el titulo sigue usando el
   ancho completo, igual que en las tarjetas con autor. */
.nav-item-cuerpo:not(:has(.nav-item-autor)) .nav-item-copete {
    padding-right: var(--nav-mas-hueco);
}

.nav-item-cabecera {
    display: flex; align-items: center;
    gap: 0.6rem; flex-wrap: wrap;
}
.nav-item-cabecera .nav-item-fecha { margin-left: auto; }
.nav-item-cat {
    color: var(--color-primario);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-size: 0.72rem;
    font-weight: 700;
    padding: 0.2rem 0.55rem;
    background: #eef7fc;
    border-radius: 4px;
}
.nav-item-cat:hover { background: #d7ebf6; color: var(--color-primario-oscuro); text-decoration: none; }
.nav-item-titulo {
    font-family: var(--fuente-sitio);
    font-size: 1.22rem; line-height: 1.25;
    margin: 0;
    color: #222;
    font-weight: 700;
}
.nav-item-titulo a { color: #222; }
.nav-item-titulo a:hover { color: var(--color-primario); }
.nav-item-copete {
    color: #555;
    /* Mas chico y mas apretado que el resto del sitio: la tarjeta tiene un alto
       tope fijo, asi que cada decima de interlineado que se recorta es una
       linea mas de texto visible antes del degrade. */
    font-size: 0.8rem;
    line-height: 1.38;
    margin: 0;
}
.nav-item-pie {
    margin-top: auto;
    display: flex; align-items: center; justify-content: space-between;
    gap: 0.6rem; flex-wrap: wrap;
    padding-top: 0.3rem;
}
.nav-item-fecha {
    color: #999;
    font-size: 0.8rem;
}
.nav-item-autor {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    color: #555;
    font-size: 0.85rem;
    font-weight: 600;
    text-decoration: none;
    min-width: 0;
}
.nav-item-autor:hover { color: var(--color-primario); }
.nav-item-autor:hover > span:last-child { text-decoration: underline; }
.nav-item-autor-avatar {
    display: inline-block;
    width: 25px; height: 25px;
    border-radius: 50%;
    overflow: hidden;
    background: var(--color-fondo-alt);
    flex-shrink: 0;
}
.nav-item-autor-avatar img {
    width: 100%; height: 100%;
    object-fit: cover;
    display: block;
}
.nav-item-mas {
    margin-left: auto;
    font-size: 0.88rem;
    font-weight: 600;
    color: var(--color-primario);
}
.nav-item-mas:hover { color: var(--color-primario-oscuro); text-decoration: none; }

/* --- Scroll infinito: sentinel + loader + fin --- */
.nav-sentinel {
    width: 100%; height: 1px;
    margin: 0; padding: 0;
}
.nav-loader {
    font-family: var(--fuente-sitio);
    display: flex; align-items: center; justify-content: center;
    gap: 0.6rem; padding: 1.25rem 0 2rem;
    color: var(--color-texto-suave);
    font-size: 0.95rem;
    opacity: 0;
    transition: opacity 0.15s ease;
    min-height: 1.5rem;
}
.nav-loader.is-visible { opacity: 1; }
.nav-loader-spinner {
    width: 18px; height: 18px;
    border: 2px solid rgba(25, 128, 182, 0.25);
    border-top-color: var(--color-primario);
    border-radius: 50%;
    display: inline-block;
    animation: bdf-spin 0.8s linear infinite;
}
.nav-fin {
    font-family: var(--fuente-sitio);
    text-align: center;
    color: var(--color-texto-suave);
    font-size: 0.9rem;
    padding: 1.5rem 0 2rem;
    margin: 0;
}

/* --- Buscador: panel de filtros (columna izquierda) ---
   Reutiliza .nav-tree para el sticky + card, pero libera max-height (el
   form es corto, no hace falta scroll interno). */
.buscar-filtros { max-height: none; }
.buscar-filtros-form {
    display: flex; flex-direction: column;
    gap: 0.9rem;
    padding: 0.9rem 1rem 1rem;
}
.buscar-filtros-campo {
    display: flex; flex-direction: column;
    gap: 0.3rem;
}
.buscar-filtros-label {
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--color-texto-suave);
    font-weight: 700;
}
.buscar-filtros-campo input {
    font-family: var(--fuente-sitio);
    font-size: 0.95rem;
    color: var(--color-texto);
    background: #fff;
    border: 1px solid var(--color-borde);
    border-radius: 8px;
    padding: 0.55rem 0.7rem;
    outline: none;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
    min-width: 0;
}
.buscar-filtros-campo input:focus {
    border-color: var(--color-primario);
    box-shadow: 0 0 0 3px rgba(25, 128, 182, 0.15);
}
.buscar-filtros-acciones {
    display: flex; align-items: center;
    gap: 0.6rem;
    margin-top: 0.2rem;
}
.buscar-filtros-aplicar {
    flex: 1;
    background: var(--color-primario);
    color: #fff;
    border: none;
    border-radius: 8px;
    padding: 0.6rem 0.9rem;
    font-family: var(--fuente-sitio);
    font-size: 0.95rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    cursor: pointer;
    transition: background 0.15s ease;
}
.buscar-filtros-aplicar:hover { background: var(--color-primario-oscuro); }
.buscar-filtros-limpiar {
    font-size: 0.85rem;
    color: var(--color-texto-suave);
    text-decoration: none;
    padding: 0.4rem 0.3rem;
}
.buscar-filtros-limpiar:hover { color: #b02a37; text-decoration: underline; }

/* --- Buscador: aviso de resultados por similitud fonetica ---
   Aparece cuando la busqueda literal no encontro nada y lo que se lista
   salio del pase por SOUNDEX. Tiene que quedar claro que son aproximados:
   el usuario escribio una cosa y esta viendo otra. */
.buscar-aviso-fonetico {
    display: flex; align-items: baseline; gap: 0.55rem;
    margin: 0 0 1rem;
    padding: 0.7rem 0.9rem;
    background: var(--color-humo);
    border: 1px solid var(--color-borde);
    border-left: 3px solid var(--color-acento);
    border-radius: var(--radio);
    font-size: 0.9rem;
    color: var(--color-texto-suave);
}
.buscar-aviso-fonetico i      { color: var(--color-acento); }
.buscar-aviso-fonetico strong { color: var(--color-texto); }

/* --- Buscador: paginacion --- */
.buscar-paginacion {
    display: flex; align-items: center; justify-content: space-between;
    gap: 0.75rem;
    padding: 1rem 0 1.5rem;
    font-family: var(--fuente-sitio);
}
.buscar-paginacion-btn {
    background: #fff;
    color: var(--color-primario);
    border: 1px solid var(--color-borde);
    border-radius: 8px;
    padding: 0.5rem 0.9rem;
    font-size: 0.9rem;
    font-weight: 600;
    text-decoration: none;
    transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.buscar-paginacion-btn:hover {
    background: var(--color-primario);
    color: #fff;
    border-color: var(--color-primario);
    text-decoration: none;
}
.buscar-paginacion-btn.is-disabled {
    color: #bbb;
    background: #f6f6f6;
    border-color: var(--color-borde);
    cursor: default;
    pointer-events: none;
}
.buscar-paginacion-info {
    color: var(--color-texto-suave);
    font-size: 0.9rem;
    font-variant-numeric: tabular-nums;
}

/* --- Autores: filtro A-Z (dentro del sidebar) --- */
.autores-abc {
    display: flex; flex-wrap: wrap;
    gap: 4px;
}
.autores-abc-item {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 26px; padding: 3px 6px;
    font-size: 0.8rem; font-weight: 600;
    color: var(--color-texto-suave);
    background: #fff;
    border: 1px solid var(--color-borde);
    border-radius: 6px;
    text-decoration: none;
    transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.autores-abc-item:hover {
    background: var(--color-primario);
    color: #fff;
    border-color: var(--color-primario);
}
.autores-abc-item.is-activo {
    background: var(--color-primario);
    color: #fff;
    border-color: var(--color-primario);
}

/* --- Autores: grilla de tarjetas con avatar circular --- */
.autores-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 24px;
}
.autor-card {
    display: flex; flex-direction: column; align-items: center;
    gap: 12px;
    padding: 20px 12px 18px;
    background: var(--color-humo);
    border: 1px solid rgba(0,0,0,0.08);
    border-radius: var(--radio);
    box-shadow: var(--sombra);
    text-align: center;
    text-decoration: none;
    color: inherit;
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.autor-card:hover {
    transform: translateY(-3px);
    box-shadow: var(--sombra-hover);
    text-decoration: none;
}
.autor-card-avatar {
    display: block;
    width: 140px; height: 140px;
    border-radius: 50%;
    overflow: hidden;
    background: var(--color-fondo-alt);
    border: 3px solid #fff;
    box-shadow: 0 0 0 1px rgba(0,0,0,0.08);
}
.autor-card-avatar img {
    width: 100%; height: 100%;
    object-fit: cover;
    display: block;
}
.autor-card-nombre {
    font-family: var(--fuente-sitio);
    font-size: 1rem;
    font-weight: 600;
    color: #222;
    line-height: 1.25;
}
.autor-card:hover .autor-card-nombre { color: var(--color-primario); }

/* --- Responsive --- */
@media (max-width: 900px) {
    .nav-layout { grid-template-columns: 1fr; }
    .nav-tree { position: static; max-height: none; }
    .nav-tree-lista { max-height: 320px; }
    /* El alto tope del cuerpo se recalcula solo: sale de la misma variable. */
    .nav-item { --nav-img-ancho: 160px; }
    .nav-item-titulo { font-size: 1.1rem; }
    .nav-topbar-titulo { font-size: 1.6rem; }
    .nav-topbar { padding: 18px 0; }
    .autores-grid { grid-template-columns: repeat(2, 1fr); gap: 18px; }
    .autor-card-avatar { width: 120px; height: 120px; }
}
@media (max-width: 600px) {
    .nav-item { grid-template-columns: 1fr; }
    .nav-item-imagen { aspect-ratio: 16 / 9; }
    /* En stacked (imagen arriba, cuerpo abajo) el cuerpo puede crecer libre
       y no hace falta esconder texto ni pintar el degrade. */
    .nav-item-cuerpo { max-height: none; }
    .nav-item-texto::after { display: none; }
    /* Sin alto tope no hay espacio muerto que recuperar, y el ancho no sobra:
       el pie vuelve a ser una fila y el texto usa todo el ancho. */
    .nav-item { --nav-mas-hueco: 0px; }
    .nav-item-cuerpo:not(:has(.nav-item-autor)) .nav-item-pie { position: static; }
    /* El cuerpo chico de desktop existe para entrar mas lineas en un alto fijo.
       Aca la tarjeta crece lo que necesite, asi que no se gana nada achicando
       la letra y si se pierde legibilidad en pantalla de telefono. */
    .nav-item-copete { font-size: 0.9rem; line-height: 1.5; }
    .nav-buscador-campo { padding: 0.75rem 0.55rem; font-size: 0.95rem; }
    .nav-buscador-btn  { padding: 0 1rem; }
    .autores-grid { grid-template-columns: repeat(2, 1fr); gap: 14px; }
    .autor-card { padding: 14px 8px 12px; }
    .autor-card-avatar { width: 96px; height: 96px; }
    .autor-card-nombre { font-size: 0.9rem; }
}

/* ================================================================
   Libros - biblioteca digital

   /libros reusa el "chrome" del Banco de Fotos (bdf-topbar, bdf-buscador,
   bdf-resultados, bdf-loader, bdf-fin), incluido el scroll infinito. Aca va
   solo lo propio: la grilla de tapas y el visor de /libro.
================================================================= */

/* --- Listado: grilla de tapas --- */
.libros-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 24px;
    margin: 1.5rem 0 2rem;
}
.libro-card {
    display: flex; flex-direction: column;
    background: #fff;
    border: 1px solid var(--color-borde);
    border-radius: var(--radio);
    overflow: hidden;
    box-shadow: var(--sombra);
    text-decoration: none;
    color: inherit;
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.libro-card:hover {
    transform: translateY(-3px);
    box-shadow: var(--sombra-hover);
    text-decoration: none;
}
/* --- Tapa montada sobre el mockup 3D -----------------------------------
   assets/img/libro.png es una foto de un libro parado, en perspectiva y con
   la tapa en blanco. La tapa real del ejemplar se superpone deformada para
   que calce sobre esa cara.

   El fondo usa libro-mockup.webp, derivado de libro.png (800x944, q88): la
   original pesa 2,7 MB y aca se rinde a ~300px. Si se cambia el mockup hay
   que regenerar el .webp Y volver a medir las cuatro esquinas de la cara.

   La geometria sale de medir la cara del libro en libro.png (2040x2408):
       TL (235, 199)   TR (1268, 306)
       BL (228, 1977)  BR (1279, 2230)
   Es un trapecio -el lado derecho esta mas cerca del ojo y mide 8% mas alto
   que el izquierdo-, asi que no alcanza con un skew: hace falta perspectiva
   real. Los valores de abajo son la solucion ajustada a esas cuatro esquinas.

   Todo va en cqw (1cqw = 1% del ancho de .libro-card-tapa, que es el
   contenedor) para que la deformacion escale con la tarjeta: perspective()
   pide una longitud y en px quedaria atada a un unico tamano de tarjeta. */
.libro-card-tapa {
    position: relative;
    display: block;
    aspect-ratio: 800 / 944;   /* el del mockup */
    container-type: inline-size;
    /* El libro no esta centrado en la foto: su cuerpo va del 11,2% al 73,6%
       del ancho, o sea 7,6% corrido a la izquierda. Este desplazamiento lo
       recentra, y lo aplican JUNTAS la foto y la tapa para que no se
       despeguen. La cola de la sombra se pasa del borde derecho: la recorta
       el overflow. */
    --libro-x: 7.6cqw;
    overflow: hidden;
}
.libro-card-mockup {
    position: absolute;
    inset: 0;
    background: url('/assets/img/libro-mockup.webp') var(--libro-x) center / contain no-repeat;
    transition: transform 0.25s ease;
}
.libro-card:hover .libro-card-mockup { transform: scale(1.03); }
.libro-card-mockup img {
    position: absolute;
    left:   calc(11.52cqw + var(--libro-x));
    top:     9.78cqw;
    width:  68.47cqw;
    height: 86.91cqw;
    display: block;
    /* fill: la tapa se estira hasta cubrir la cara entera del libro, sin
       margenes blancos ni recortes. Las del acervo van de 0,64 a 0,83 de
       relacion ancho/alto y la cara del mockup es 0,79, asi que algunas se
       ensanchan un poco; sobre el escorzo casi no se nota, y es preferible a
       recortar titulos (cover) o a dejar ver el blanco del libro (contain). */
    object-fit: fill;
    transform-origin: 0 0;
    transform: perspective(652.9cqw) rotateY(-46.45deg) rotateZ(4.06deg) skewX(4.04deg);
}
.libro-card-formato {
    position: absolute;
    top: 8px; right: 8px;
    background: rgba(3, 33, 44, 0.82);
    color: #fff;
    font-size: 0.68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    padding: 0.2rem 0.5rem;
    border-radius: 999px;
}
.libro-card-cuerpo {
    display: flex; flex-direction: column; gap: 0.25rem;
    padding: 0.7rem 0.8rem 0.85rem;
    font-family: var(--fuente-sitio);
}
.libro-card-titulo {
    font-size: 0.98rem;
    font-weight: 600;
    line-height: 1.25;
    color: #222;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.libro-card:hover .libro-card-titulo { color: var(--color-primario); }
.libro-card-autor {
    font-size: 0.85rem;
    color: var(--color-texto-suave);
    line-height: 1.2;
}
.libro-card-meta {
    font-size: 0.75rem;
    color: var(--color-texto-suave);
    margin-top: 0.1rem;
}
.libro-card-meta span + span::before {
    content: "·";
    margin: 0 0.35rem;
    opacity: 0.7;
}

/* Scroll infinito: el loader y el pie los aporta el chrome del Banco de
   Fotos (.bdf-loader / .bdf-fin); aca solo va el disparador. */
.libros-sentinel { width: 100%; height: 1px; margin: 0; padding: 0; }

/* --- Visor: barra celeste con la ficha + acciones --- */
.libro-topbar {
    background-color: var(--color-primario);
    color: #fff;
    padding: 18px 0;
    box-shadow: inset 0 -3px 0 rgba(0,0,0,0.08);
    font-family: var(--fuente-sitio);
}
.libro-topbar-row {
    display: flex; align-items: flex-end; justify-content: space-between;
    gap: 1rem; flex-wrap: wrap;
}
.libro-topbar-info { min-width: 0; }
.libro-volver {
    display: inline-block;
    color: rgba(255,255,255,0.85);
    font-size: 0.85rem;
    text-decoration: none;
    margin-bottom: 0.2rem;
}
.libro-volver:hover { color: #fff; text-decoration: underline; }
.libro-topbar-titulo {
    font-family: var(--fuente-sitio);
    font-size: 1.7rem; font-weight: 700;
    color: #fff;
    margin: 0;
    line-height: 1.15;
    letter-spacing: -0.01em;
}
.libro-topbar-meta {
    margin: 0.3rem 0 0;
    color: rgba(255,255,255,0.9);
    font-size: 0.9rem;
}
.libro-topbar-meta span + span::before {
    content: "·";
    margin: 0 0.45rem;
    opacity: 0.7;
}
.libro-acciones {
    display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap;
}
.libro-btn {
    display: inline-block;
    background: transparent;
    color: #fff;
    border: 1px solid rgba(255,255,255,0.6);
    border-radius: 8px;
    padding: 0.45rem 0.9rem;
    font-family: var(--fuente-sitio);
    font-size: 0.9rem;
    font-weight: 600;
    text-decoration: none;
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.libro-btn:hover {
    background: rgba(255,255,255,0.15);
    color: #fff;
    border-color: #fff;
    text-decoration: none;
}
.libro-btn-primario {
    background: #fff;
    color: var(--color-primario-oscuro);
    border-color: #fff;
}
.libro-btn-primario:hover {
    background: var(--color-fondo-alt);
    color: var(--color-primario-oscuro);
}

/* --- Visor: caja donde se empotra el ejemplar --- */
.libro-main { padding-top: 1.25rem; }
.libro-visor {
    /* Alto util de pantalla menos cabecera + barra del libro + nota al pie.
       El min-height evita que quede una franja inservible en pantallas bajas. */
    height: calc(100vh - 240px);
    min-height: 480px;
    background: var(--color-fondo-alt);
    border: 1px solid var(--color-borde);
    border-radius: var(--radio);
    overflow: hidden;
    box-shadow: var(--sombra);
}
.libro-visor-frame {
    width: 100%; height: 100%;
    border: none;
    display: block;
}
/* --- Flipbooks "Basic HTML Version" ------------------------------------
   Ese reproductor escala la pagina contra el ANCHO de su ventana y nunca
   contra el alto (ver sjm_libro_flipbook_basico()), asi que con un iframe
   ancho la hoja se sale por abajo. Se le da un iframe alto y angosto: al
   achicarse el ancho, la pagina escala proporcionalmente y entra completa.

   El ancho no es una proporcion del alto sino una recta: el reproductor le da
   a la pagina `ancho_ventana - 100` (las barras de zoom y de compartir van
   superpuestas, no descuentan) y arriba le deja ~63px de barra de navegacion.
   Midiendo la pagina renderizada sale:
       alto_pagina  = (ancho_iframe - 100) x alto/ancho de la pagina
       ancho_iframe = (alto_iframe - 63) / 1,55 + 100
   con 1,55 = la pagina mas alta del acervo. De ahi el calc(): 0,63 x alto
   (con aire) + 56px. Por eso hace falta `cqh`, que da acceso al alto del
   contenedor; con aspect-ratio la parte fija no se puede expresar y termina
   sobrando o faltando segun el tamano de la pantalla. */
.libro-visor.is-basic {
    display: flex;
    justify-content: center;
    background: #fff;
    container-type: size;
}
.libro-visor.is-basic .libro-visor-frame {
    width: calc(63cqh + 56px);
    max-width: 100%;
    height: 100%;
}
.libro-visor-img {
    width: 100%; height: 100%;
    object-fit: contain;
    display: block;
    background: #fff;
}
.libro-visor:fullscreen {
    width: 100%; height: 100%;
    max-height: none;
    border: none;
    border-radius: 0;
    box-shadow: none;
    background: #000;
}
.libro-nota {
    font-family: var(--fuente-sitio);
    text-align: center;
    color: var(--color-texto-suave);
    font-size: 0.85rem;
    /* Ajustada para que la nota entre en pantalla junto con el visor: el alto
       de .libro-visor esta calculado contra 100vh contando este pie. */
    padding: 0.7rem 0 1rem;
    margin: 0;
}

@media (max-width: 900px) {
    .libros-grid { grid-template-columns: repeat(3, 1fr); gap: 18px; }
    .libro-topbar-titulo { font-size: 1.35rem; }
    .libro-visor { height: calc(100vh - 300px); min-height: 420px; }
}
@media (max-width: 600px) {
    .libros-grid { grid-template-columns: repeat(2, 1fr); gap: 14px; }
    .libro-card-titulo { font-size: 0.9rem; -webkit-line-clamp: 2; }
    .libro-card-autor { font-size: 0.8rem; }
    .libro-topbar-row { align-items: flex-start; }
    .libro-acciones { width: 100%; }
    .libro-btn { flex: 1; text-align: center; padding: 0.45rem 0.6rem; font-size: 0.85rem; }
    .libro-visor { height: calc(100vh - 320px); min-height: 360px; }
}
