/* =============================================================
 * Bibliografía UCM — Sistema de diseño
 * Paleta inspirada en la identidad institucional (granate UCM),
 * tipografía Inter, escala de espaciado y radios consistentes.
 * ============================================================= */

:root {
    /* Colores */
    --brand-50:  #fbf0f4;
    --brand-100: #f3d9e1;
    --brand-200: #e4adbe;
    --brand-300: #d07f97;
    --brand-500: #b3003c;
    --brand-600: #990033;   /* rojo UCM (primary) */
    --brand-700: #7a0028;
    --brand-800: #5c001e;
    --brand-900: #3d0014;

    --accent-500: #c2410c;  /* naranja para acentos */

    --gray-50:  #fafafa;
    --gray-100: #f4f4f5;
    --gray-200: #e4e4e7;
    --gray-300: #d4d4d8;
    --gray-400: #a1a1aa;
    --gray-500: #71717a;
    --gray-600: #52525b;
    --gray-700: #3f3f46;
    --gray-800: #27272a;
    --gray-900: #18181b;

    --success-500: #16a34a;
    --warning-500: #d97706;
    --danger-500:  #dc2626;
    --info-500:    #0284c7;

    /* Superficies */
    --surface:    #ffffff;
    --surface-2:  #fafafa;
    --surface-3:  #f4f4f5;
    --bg:         #f7f7f9;

    /* Bordes / radios / sombras */
    --border:     #e7e7ea;
    --border-strong: #d4d4d8;
    --radius-sm: 6px;
    --radius:    10px;
    --radius-lg: 14px;

    --shadow-xs: 0 1px 2px rgba(15, 15, 20, 0.04);
    --shadow-sm: 0 1px 3px rgba(15, 15, 20, 0.06), 0 1px 2px rgba(15, 15, 20, 0.04);
    --shadow:    0 4px 12px -2px rgba(15, 15, 20, 0.08), 0 2px 4px rgba(15, 15, 20, 0.04);
    --shadow-lg: 0 12px 32px -8px rgba(15, 15, 20, 0.16), 0 4px 8px rgba(15, 15, 20, 0.04);

    /* Tipografía */
    --font-sans: 'Quattrocento Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    --font-serif: 'Quattrocento', 'Georgia', serif;

    /* Bootstrap overrides */
    --bs-body-font-family: var(--font-sans);
    --bs-body-bg: var(--bg);
    --bs-body-color: var(--gray-800);
    --bs-primary: var(--brand-600);
    --bs-primary-rgb: 153, 0, 51;
    --bs-border-color: var(--border);
    --bs-border-radius: var(--radius);
    --bs-border-radius-sm: var(--radius-sm);
    --bs-border-radius-lg: var(--radius-lg);
}

/* ============================== Base ============================== */
* { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
html { overflow-x: hidden; }
body {
    overflow-x: hidden;
    font-family: var(--font-sans);
    background: var(--bg);
    color: var(--gray-800);
    font-feature-settings: 'cv11', 'ss01';
    letter-spacing: -0.01em;
}
.public-body {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
}
.public-main {
    flex: 1;
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
}
h1, h2, h3, h4, h5, h6 { font-weight: 600; letter-spacing: -0.02em; color: var(--gray-900); }
.display-5, .display-6 { font-weight: 700; letter-spacing: -0.03em; }
a { color: var(--brand-600); text-decoration: none; }
a:hover { color: var(--brand-700); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; }
code, pre { font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.875em; }
hr { border-color: var(--border); opacity: 1; }

/* ============================== Botones ============================== */
.btn {
    border-radius: var(--radius);
    font-weight: 500;
    padding: 0.5rem 1rem;
    transition: all 0.15s ease;
    box-shadow: var(--shadow-xs);
    border: 1px solid transparent;
}
.btn-sm { padding: 0.3rem 0.7rem; font-size: 0.8125rem; border-radius: var(--radius-sm); }
.btn-lg { padding: 0.7rem 1.5rem; font-size: 1.0625rem; }

.btn-primary {
    background: var(--brand-600);
    border-color: var(--brand-600);
    color: #fff;
}
.btn-primary:hover, .btn-primary:focus {
    background: var(--brand-700);
    border-color: var(--brand-700);
    color: #fff;
    box-shadow: 0 0 0 3px var(--brand-100);
}
.btn-outline-primary {
    color: var(--brand-600);
    border-color: var(--brand-200);
    background: var(--surface);
}
.btn-outline-primary:hover {
    background: var(--brand-50);
    border-color: var(--brand-300);
    color: var(--brand-700);
}
.btn-outline-secondary {
    color: var(--gray-700);
    border-color: var(--border-strong);
    background: var(--surface);
}
.btn-outline-secondary:hover {
    background: var(--gray-50);
    color: var(--gray-900);
    border-color: var(--gray-400);
}
.btn-outline-danger {
    color: var(--danger-500);
    border-color: var(--border-strong);
    background: var(--surface);
}
.btn-outline-danger:hover { background: #fef2f2; border-color: var(--danger-500); color: var(--danger-500); }
.btn-link { box-shadow: none; padding-left: 0.5rem; padding-right: 0.5rem; }
.btn-light-ghost {
    background: transparent; color: var(--gray-300); border: none; box-shadow: none;
}
.btn-light-ghost:hover { background: rgba(255,255,255,0.08); color: #fff; }

/* ============================== Cards ============================== */
.card {
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    background: var(--surface);
    box-shadow: var(--shadow-xs);
    transition: box-shadow 0.15s ease;
}
.card:hover { box-shadow: var(--shadow-sm); }
.card-header {
    background: transparent;
    border-bottom: 1px solid var(--border);
    padding: 1rem 1.25rem;
    font-weight: 600;
    font-size: 0.875rem;
    color: var(--gray-700);
    letter-spacing: -0.005em;
}
.card-body { padding: 1.25rem; }
.shadow-sm { box-shadow: var(--shadow-sm) !important; }

/* KPI cards (dashboard) */
.kpi-card {
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    background: var(--surface);
    padding: 1.25rem;
    transition: all 0.2s ease;
    position: relative;
    overflow: hidden;
}
.kpi-card:hover { transform: translateY(-1px); box-shadow: var(--shadow); border-color: var(--brand-200); }
.kpi-label {
    text-transform: uppercase;
    font-size: 0.6875rem;
    letter-spacing: 0.06em;
    color: var(--gray-500);
    font-weight: 600;
    margin-bottom: 0.5rem;
}
.kpi-value {
    font-size: 2rem;
    font-weight: 700;
    letter-spacing: -0.04em;
    color: var(--gray-900);
    line-height: 1;
}
.kpi-card::before {
    content: '';
    position: absolute; top: 0; left: 0; right: 0; height: 3px;
    background: linear-gradient(90deg, var(--brand-600), var(--brand-400));
    opacity: 0; transition: opacity 0.2s ease;
}
.kpi-card:hover::before { opacity: 1; }

/* ============================== Tablas ============================== */
.table {
    --bs-table-bg: var(--surface);
    --bs-table-border-color: var(--border);
    margin-bottom: 0;
}
.table thead th {
    background: var(--surface-2);
    color: var(--gray-500);
    font-weight: 600;
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    border-bottom: 1px solid var(--border);
    padding: 0.75rem 1rem;
}
/* Cabeceras de columna ordenables. El par de flechas se muestra siempre,
   atenuado, para que la columna se lea como ordenable sin tener que probar;
   al ordenar por ella se resalta la del sentido aplicado. */
.th-sort {
    color: inherit; text-decoration: none; cursor: pointer;
    display: inline-flex; align-items: center; gap: 0.35em;
    white-space: nowrap;
}
.th-sort:hover { color: var(--brand-600); text-decoration: none; }
.th-sort.is-active { color: var(--brand-600); }

.th-sort-ind { flex: none; opacity: 0.38; transition: opacity 0.15s ease; }
.th-sort:hover .th-sort-ind { opacity: 0.9; }
.th-sort.is-active .th-sort-ind { opacity: 1; }
/* En la columna activa, la flecha contraria se apaga para no confundir. */
.th-sort.is-active.dir-asc .down,
.th-sort.is-active.dir-desc .up { opacity: 0.2; }

/* Toda la celda responde al puntero, no solo el texto. */
.table thead th:has(.th-sort) { cursor: pointer; }
.table thead th:has(.th-sort):hover { background: var(--surface-3); }
.table tbody td {
    padding: 0.9rem 1rem;
    border-color: var(--border);
    vertical-align: middle;
}
.table tbody tr:last-child td { border-bottom: 0; }
.table-hover tbody tr:hover { background: var(--surface-2); }

/* ============================== Forms ============================== */
.form-control, .form-select {
    border-radius: var(--radius);
    border-color: var(--border-strong);
    padding: 0.55rem 0.85rem;
    background: var(--surface);
    color: var(--gray-900);
    font-size: 0.9375rem;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.form-control-sm, .form-select-sm { padding: 0.35rem 0.65rem; font-size: 0.875rem; border-radius: var(--radius-sm); }
.form-control:focus, .form-select:focus {
    border-color: var(--brand-500);
    box-shadow: 0 0 0 3px var(--brand-100);
}
.form-label {
    font-weight: 500;
    color: var(--gray-700);
    font-size: 0.875rem;
    margin-bottom: 0.4rem;
}
.form-label.small { font-size: 0.8125rem; color: var(--gray-600); }
.form-check-input:checked { background-color: var(--brand-600); border-color: var(--brand-600); }
.form-check-input:focus { box-shadow: 0 0 0 3px var(--brand-100); border-color: var(--brand-500); }

/* ============================== Badges ============================== */
.badge {
    font-weight: 500;
    padding: 0.25em 0.55em;
    border-radius: var(--radius-sm);
    letter-spacing: 0;
}
.text-bg-primary { background-color: var(--brand-100) !important; color: var(--brand-700) !important; }
.text-bg-secondary { background-color: var(--gray-100) !important; color: var(--gray-700) !important; }
.text-bg-light { background-color: var(--surface-3) !important; color: var(--gray-700) !important; }
.text-bg-success { background-color: #dcfce7 !important; color: #15803d !important; }
.text-bg-danger { background-color: #fee2e2 !important; color: #b91c1c !important; }
.text-bg-warning { background-color: #fef3c7 !important; color: #b45309 !important; }
.text-bg-info { background-color: #dbeafe !important; color: #1d4ed8 !important; }

/* ============================== Alerts ============================== */
.alert {
    border: 1px solid transparent;
    border-radius: var(--radius);
    padding: 0.75rem 1rem;
    font-size: 0.9375rem;
}
.alert-success { background: #f0fdf4; border-color: #bbf7d0; color: #166534; }
.alert-danger { background: #fef2f2; border-color: #fecaca; color: #991b1b; }
.alert-warning { background: #fffbeb; border-color: #fde68a; color: #92400e; }
.alert-info { background: #eff6ff; border-color: #bfdbfe; color: #1e40af; }

/* ============================== Public layout ============================== */
.site-header {
    background: var(--surface);
}
.site-header-logos { padding: 1.25rem 0; flex-wrap: wrap; gap: 0.75rem; }
.ucm-logo { height: 56px; width: auto; display: block; }
.site-title {
    font-size: clamp(1.125rem, 5vw, 2rem);
    font-weight: 700;
    color: var(--brand-600);
    text-decoration: none;
}
.site-title:hover { color: var(--brand-700); text-decoration: none; }
@media (max-width: 480px) {
    .ucm-logo { height: 40px; }
}
.site-header-band {
    background: var(--brand-600);
    height: 8px;
}
.hero {
    padding: 6rem 0 4.5rem;
    text-align: center;
}
.hero h1 {
    font-size: clamp(2rem, 4vw, 3rem);
    font-weight: 700;
    letter-spacing: -0.04em;
    color: var(--gray-900);
    margin-bottom: 2.5rem;
}
.hero .lead {
    font-size: 1.125rem;
    color: var(--gray-600);
    max-width: 520px;
    margin: 0 auto 2.5rem;
}
.search-wrap {
    max-width: 640px;
    margin: 0 auto;
    position: relative;
}
.search-input {
    width: 100%;
    border: 1px solid var(--border-strong);
    border-radius: 999px;
    padding: 0.875rem 1.5rem 0.875rem 3rem;
    font-size: 1rem;
    background: var(--surface);
    box-shadow: var(--shadow-sm);
    transition: all 0.15s ease;
}
.search-input:focus {
    outline: none;
    border-color: var(--brand-500);
    box-shadow: var(--shadow), 0 0 0 4px var(--brand-100);
}
.search-icon {
    position: absolute;
    left: 1.125rem; top: 50%;
    transform: translateY(-50%);
    color: var(--gray-400);
    pointer-events: none;
}
.search-results {
    position: absolute;
    top: calc(100% + 0.5rem);
    left: 0; right: 0;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    overflow: hidden;
    z-index: 30;
    list-style: none;
    padding: 0.375rem;
    margin: 0;
}
.search-results:empty { display: none; }
.search-results li {
    padding: 0.75rem 1rem;
    border-radius: var(--radius);
    cursor: pointer;
    display: flex; align-items: center; gap: 0.75rem;
    transition: background 0.1s ease;
}
.search-results li:hover, .search-results li.is-active { background: var(--surface-3); }
.search-results .item-tag {
    font-size: 0.6875rem; text-transform: uppercase; letter-spacing: 0.05em;
    color: var(--brand-700); background: var(--brand-50);
    padding: 0.2em 0.55em; border-radius: var(--radius-sm); font-weight: 600;
    flex-shrink: 0;
}
.search-results .item-title { font-weight: 500; color: var(--gray-900); }
.search-results .item-meta { font-size: 0.8125rem; color: var(--gray-500); }
.search-results .item-more {
    padding: 0.625rem 1rem; cursor: default;
    font-size: 0.8125rem; color: var(--gray-500); font-style: italic;
    border-top: 1px solid var(--border); border-radius: 0; margin-top: 0.25rem;
}
.search-results .item-more:hover { background: transparent; }

/* ---- Últimas bibliografías añadidas (carrusel) ---- */
/* Últimos títulos añadidos ------------------------------------------------
   Son fichas de catálogo, no tarjetas de producto: no hay portada que enseñar
   (de cada libro solo tenemos OCN, título, autor y pie de imprenta), así que
   el peso visual lo llevan la tipografía y la jerarquía. De ahí el título en
   la serif de la casa, el pie de imprenta en versalitas y un único punto de
   color por ficha. */
.latest {
    max-width: 1040px;
    margin: 2.5rem auto 3rem;
    padding: 0 1.25rem;
    width: 100%;
}
.latest-head {
    display: flex; align-items: baseline; justify-content: space-between;
    gap: 1rem; margin-bottom: 1.15rem;
    padding-bottom: 0.7rem;
    border-bottom: 1px solid var(--border);
}
.latest-head h2 {
    font-family: var(--font-serif);
    font-size: 1.375rem; font-weight: 700; margin: 0;
    color: var(--gray-900); letter-spacing: -0.01em;
}
.latest-nav { display: flex; gap: 0.4rem; flex-shrink: 0; align-self: center; }
.latest-arrow {
    width: 34px; height: 34px; border-radius: 50%;
    border: 1px solid var(--border-strong); background: var(--surface);
    color: var(--gray-600); cursor: pointer;
    display: inline-flex; align-items: center; justify-content: center;
    transition: color 0.12s ease, border-color 0.12s ease, background 0.12s ease;
}
.latest-arrow:hover {
    border-color: var(--brand-500); color: var(--brand-600); background: var(--brand-50);
}
.latest-arrow:focus-visible { outline: 2px solid var(--brand-500); outline-offset: 2px; }
.latest-track {
    display: flex; gap: 1.1rem;
    overflow-x: auto; scroll-snap-type: x mandatory;
    scroll-padding-left: 0.35rem;
    padding: 0.35rem 0.35rem 1.25rem;
    margin: 0 -0.35rem;
    scrollbar-width: thin;
}
.latest-card {
    position: relative;
    flex: 0 0 280px; scroll-snap-align: start;
    display: flex; flex-direction: column;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-xs);
    overflow: hidden;
    transition: box-shadow 0.18s ease, transform 0.18s ease, border-color 0.18s ease;
}
/* Filete superior: discreto en reposo y del color de la casa al pasar por
   encima. Es el punto de color que sustituye a la portada que no tenemos. */
.latest-card::before {
    content: ''; position: absolute; inset: 0 0 auto 0; height: 3px;
    background: var(--brand-200);
    transition: background 0.18s ease;
}
.latest-card:hover {
    box-shadow: var(--shadow);
    transform: translateY(-3px);
    border-color: var(--border-strong);
}
.latest-card:hover::before {
    background: linear-gradient(90deg, var(--brand-600), var(--accent-500));
}
.latest-card-body {
    padding: 1.15rem 1.1rem 1rem;
    flex: 1; display: flex; flex-direction: column;
}
.latest-card-title {
    font-family: var(--font-serif);
    font-size: 1.0625rem; font-weight: 700; line-height: 1.32;
    color: var(--gray-900); text-decoration: none;
    display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
a.latest-card-title:hover {
    color: var(--brand-600); text-decoration: underline; text-underline-offset: 2px;
}
a.latest-card-title:focus-visible {
    outline: 2px solid var(--brand-500); outline-offset: 2px; border-radius: 2px;
}
.latest-card-author {
    font-size: 0.875rem; color: var(--gray-600); margin-top: 0.45rem; line-height: 1.4;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
/* Pie de imprenta en versalitas y al fondo de la ficha: es el dato que menos
   se lee, y arriba competía con el título. El margen automático lo empuja
   abajo, así que queda a la misma altura en todas las fichas. */
.latest-card-meta {
    margin-top: auto; padding-top: 0.85rem;
    font-size: 0.6875rem; font-weight: 700;
    letter-spacing: 0.06em; text-transform: uppercase;
    color: var(--gray-500);
}
/* Pie: a qué asignatura pertenece. Alto fijo para que la línea de separación
   caiga a la misma altura en toda la fila, aunque un nombre ocupe dos líneas. */
.latest-card-course {
    position: relative;
    display: flex; flex-direction: column; justify-content: center;
    height: 5rem;
    text-decoration: none;
    border-top: 1px solid var(--border);
    padding: 0.7rem 2.1rem 0.7rem 1.1rem;
    background: var(--surface-2);
    transition: background 0.15s ease;
}
.latest-card-course:hover { background: var(--brand-50); }
.latest-card-course:focus-visible { outline: 2px solid var(--brand-500); outline-offset: -2px; }
/* La flecha se ve siempre, atenuada: en pantalla táctil no hay "pasar por
   encima" que la revele. */
.latest-card-course::after {
    content: '→';
    position: absolute; right: 0.95rem; top: 50%; transform: translateY(-50%);
    color: var(--brand-500); opacity: 0.4;
    transition: opacity 0.15s ease, right 0.15s ease;
}
.latest-card-course:hover::after { opacity: 1; right: 0.75rem; }
.latest-card-asig {
    font-size: 0.875rem; font-weight: 700; color: var(--brand-700); line-height: 1.3;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.latest-card-titu {
    display: block; font-size: 0.75rem; color: var(--gray-500); margin-top: 0.15rem;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
@media (prefers-reduced-motion: reduce) {
    .latest-card { transition: none; }
    .latest-card:hover { transform: none; }
    .latest-card-course::after { transition: none; }
}

.public-footer {
    position: relative;
    background: var(--gray-900);
    color: var(--gray-400);
    font-size: 0.875rem;
    margin-top: 2rem;
}
.public-footer::before {
    content: "";
    position: absolute; top: 0; left: 0; right: 0; height: 3px;
    background: linear-gradient(90deg, var(--brand-600), var(--accent-500));
}
.public-footer a { color: var(--gray-300); text-decoration: none; transition: color 0.15s ease; }
.public-footer a:hover { color: #fff; }

.footer-top {
    display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
    gap: 1.25rem;
    padding: 2.75rem 0 1.75rem;
}
.footer-brand { display: flex; flex-direction: column; gap: 0.2rem; }
.footer-brand-title {
    font-family: var(--font-serif); font-size: 1.125rem; font-weight: 700; color: #fff;
}
.footer-brand-tagline { font-size: 0.8125rem; color: var(--gray-500); }
.footer-links { display: flex; flex-wrap: wrap; gap: 0.5rem 1.75rem; }
.footer-links a { font-weight: 500; }

.footer-bottom {
    display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
    gap: 0.5rem 1.5rem;
    border-top: 1px solid rgba(255, 255, 255, 0.08);
    padding: 1.25rem 0 1.75rem;
    font-size: 0.8125rem;
    color: var(--gray-500);
}
.footer-legal { display: flex; flex-wrap: wrap; gap: 0.375rem 1.25rem; }

@media (max-width: 640px) {
    .footer-top, .footer-bottom { justify-content: center; text-align: center; }
    .footer-links, .footer-legal { justify-content: center; }
}

/* ============================== Public asignatura page ============================== */
.asig-header { padding: 1rem 0 2rem; }
.asig-meta {
    display: inline-flex; gap: 0.5rem; flex-wrap: wrap;
    color: var(--gray-500); font-size: 0.875rem;
    align-items: center;
}
.asig-meta .dot { color: var(--gray-300); }
.biblio-section { margin-top: 2.5rem; }
.biblio-section h2 {
    font-size: 1rem; font-weight: 600;
    text-transform: uppercase; letter-spacing: 0.06em;
    color: var(--gray-500); margin-bottom: 1rem;
}
.biblio-list { list-style: none; padding: 0; margin: 0; border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden; background: var(--surface); }
.biblio-item {
    padding: 1.125rem 1.25rem;
    border-bottom: 1px solid var(--border);
    display: flex; justify-content: space-between; gap: 1.5rem; align-items: flex-start;
    transition: background 0.1s ease;
}
.biblio-item:last-child { border-bottom: 0; }
.biblio-item:hover { background: var(--surface-2); }
.biblio-title { font-weight: 600; color: var(--gray-900); margin-bottom: 0.25rem; }
.biblio-meta { font-size: 0.875rem; color: var(--gray-500); }
.biblio-note { font-size: 0.8125rem; color: var(--gray-600); font-style: italic; margin-top: 0.5rem; }

/* ============================== Admin: sidebar layout ============================== */
.admin-shell {
    display: grid;
    grid-template-columns: 240px 1fr;
    min-height: 100vh;
}
.admin-sidebar {
    background: linear-gradient(180deg, var(--gray-900) 0%, #0f0f12 100%);
    color: var(--gray-300);
    padding: 1.25rem 0.75rem;
    border-right: 1px solid #000;
    display: flex; flex-direction: column;
    position: sticky; top: 0; height: 100vh;
}
.admin-sidebar .sidebar-brand {
    display: block;
    padding: 0.25rem 0.5rem 1.25rem;
}
.admin-sidebar .sidebar-logo-wrap {
    background: #0f0f12; border-radius: 10px; padding: 8px 12px;
    display: block; box-shadow: var(--shadow-sm);
}
.admin-sidebar .sidebar-logo-wrap img { width: 100%; height: auto; display: block; }
.admin-sidebar .sidebar-brand-sub {
    color: var(--gray-400); font-size: 0.75rem; text-transform: uppercase;
    letter-spacing: 0.06em; margin-top: 0.625rem; padding-left: 0.25rem;
}
.sidebar-section {
    text-transform: uppercase; font-size: 0.6875rem; letter-spacing: 0.08em;
    color: var(--gray-500); font-weight: 600;
    padding: 0.75rem 0.875rem 0.5rem;
}
.sidebar-nav { list-style: none; padding: 0; margin: 0; flex: 1; }
.sidebar-nav a {
    display: flex; align-items: center; gap: 0.625rem;
    padding: 0.55rem 0.875rem;
    color: var(--gray-300);
    border-radius: var(--radius-sm);
    font-size: 0.875rem;
    font-weight: 500;
    text-decoration: none;
    margin-bottom: 0.125rem;
    transition: all 0.12s ease;
}
.sidebar-nav a:hover { background: rgba(255,255,255,0.06); color: #fff; text-decoration: none; }
.sidebar-nav a.is-active {
    background: rgba(139, 21, 56, 0.18);
    color: #fff;
    box-shadow: inset 2px 0 0 var(--brand-500);
}
.sidebar-nav a svg { flex-shrink: 0; opacity: 0.7; }
.sidebar-nav a.is-active svg { opacity: 1; }
.sidebar-footer {
    border-top: 1px solid rgba(255,255,255,0.08);
    padding-top: 0.875rem;
    margin-top: 0.875rem;
    font-size: 0.8125rem;
}
.sidebar-user {
    padding: 0.5rem 0.875rem;
    color: var(--gray-300);
    display: flex; align-items: center; gap: 0.625rem;
}
.sidebar-user .avatar {
    width: 30px; height: 30px;
    background: linear-gradient(135deg, var(--brand-500), var(--brand-700));
    border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    color: #fff; font-weight: 600; font-size: 0.75rem;
}
.sidebar-user .meta { line-height: 1.2; overflow: hidden; }
.sidebar-user .meta .name { color: #fff; font-weight: 500; font-size: 0.8125rem; }
.sidebar-user .meta .role { color: var(--gray-400); font-size: 0.6875rem; text-transform: uppercase; letter-spacing: 0.05em; }

.admin-main { padding: 2rem 2.5rem; max-width: 1400px; }
@media (max-width: 768px) { .admin-main { padding: 1.25rem 1rem; } }
.admin-header { margin-bottom: 1.75rem; }
.admin-header h1 { font-size: 1.5rem; font-weight: 700; letter-spacing: -0.03em; margin-bottom: 0.25rem; }
.admin-header .subtitle { color: var(--gray-500); font-size: 0.9375rem; }
.admin-breadcrumb {
    font-size: 0.8125rem; color: var(--gray-500);
    margin-bottom: 0.5rem; display: flex; align-items: center; gap: 0.375rem;
}
.admin-breadcrumb a { color: var(--gray-500); }
.admin-breadcrumb a:hover { color: var(--brand-600); }
.admin-breadcrumb .sep { color: var(--gray-300); }

/* ---- Admin: barra superior móvil + cajón lateral (off-canvas) ---- */
/* Barra superior: oculta en escritorio; visible <992px (ver media query). */
.admin-topbar { display: none; }
.admin-topbar-toggle, .admin-topbar-logout {
    display: inline-flex; align-items: center; justify-content: center;
    width: 40px; height: 40px; padding: 0;
    background: transparent; border: none; border-radius: var(--radius-sm);
    color: var(--gray-300); cursor: pointer;
}
.admin-topbar-toggle:hover, .admin-topbar-logout:hover { background: rgba(255,255,255,0.08); color: #fff; }
.admin-topbar-brand {
    font-weight: 600; font-size: 0.9375rem; color: #fff; text-decoration: none;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.admin-topbar-brand:hover { color: #fff; text-decoration: none; }
.admin-backdrop {
    position: fixed; inset: 0; z-index: 40;
    background: rgba(0,0,0,0.5);
}

/* La barra superior y el cajón solo entran en juego por debajo de 992px:
   este bloque va DESPUÉS de las reglas base para ganar la cascada (las media
   queries no añaden especificidad). */
@media (max-width: 991px) {
    .admin-shell { grid-template-columns: 1fr; }
    .admin-topbar {
        display: flex; align-items: center; gap: 0.5rem;
        padding: 0.5rem 0.75rem;
        background: var(--gray-900);
        position: sticky; top: 0; z-index: 30;
        border-bottom: 1px solid #000;
    }
    .admin-sidebar {
        position: fixed; top: 0; left: 0; z-index: 50;
        width: 260px; max-width: 82vw; height: 100vh; height: 100dvh;
        transform: translateX(-100%);
        transition: transform 0.22s ease;
    }
    .admin-sidebar.is-open { transform: translateX(0); box-shadow: 0 0 40px rgba(0,0,0,0.5); }
    body.admin-nav-open { overflow: hidden; }
}
@media (min-width: 992px) {
    .admin-backdrop { display: none; }
}

/* ---- Ayuda: botón flotante + tour guiado ---- */
.admin-help-fab {
    position: fixed; right: 1.1rem; bottom: 1.1rem; z-index: 45;
    width: 46px; height: 46px; border-radius: 50%;
    background: var(--brand-600); color: #fff; border: none;
    display: inline-flex; align-items: center; justify-content: center;
    font-size: 1.35rem; font-weight: 700; cursor: pointer;
    box-shadow: var(--shadow-lg);
}
.admin-help-fab:hover { background: var(--brand-700); }
/* Durante el tour se muestra el menú lateral (aunque en móvil esté oculto) y
   se bloquea el scroll para que los resaltados no se descoloquen. */
body.tour-active { overflow: hidden; }
body.tour-active .admin-backdrop { display: none !important; }
/* El menú lateral se fuerza visible solo en los pasos que lo señalan. */
body.tour-show-nav .admin-sidebar { transform: translateX(0) !important; transition: none !important; }
.tour-mask { position: fixed; inset: 0; z-index: 999; }
.tour-highlight {
    position: fixed; z-index: 1000; border-radius: 8px; pointer-events: none;
    box-shadow: 0 0 0 3px var(--brand-500), 0 0 0 9999px rgba(15, 15, 18, 0.62);
    transition: left 0.2s ease, top 0.2s ease, width 0.2s ease, height 0.2s ease;
}
.tour-tooltip {
    position: fixed; z-index: 1001; width: min(340px, calc(100vw - 2rem));
    background: var(--surface); border-radius: var(--radius); box-shadow: var(--shadow-lg);
    padding: 1rem 1.1rem;
}
.tour-tooltip h3 { font-size: 1rem; font-weight: 700; margin: 0 0 0.4rem; color: var(--gray-900); }
.tour-tooltip p { font-size: 0.9rem; line-height: 1.45; margin: 0 0 0.9rem; color: var(--gray-700); }
.tour-tooltip .tour-actions { display: flex; align-items: center; gap: 0.4rem; flex-wrap: wrap; }
.tour-tooltip .tour-step { font-size: 0.8rem; color: var(--gray-500); margin-right: auto; }

/* ---- Selector de asignatura con búsqueda (alta de bibliografía) ---- */
.ap { position: relative; }
.ap-results {
    position: absolute; top: calc(100% + 0.25rem); left: 0; right: 0; z-index: 30;
    max-height: 320px; overflow-y: auto;
    list-style: none; margin: 0; padding: 0.25rem;
    background: var(--surface); border: 1px solid var(--border);
    border-radius: var(--radius); box-shadow: var(--shadow-lg);
}
.ap-results:empty { display: none; }
.ap-item { padding: 0.5rem 0.75rem; border-radius: var(--radius-sm); cursor: pointer; }
.ap-item:hover, .ap-item.is-active { background: var(--surface-3); }
/* Ya elegida: la lista sigue abierta, así que hay que distinguirlas. */
.ap-item.is-added { opacity: 0.55; }
.ap-item.is-added .ap-item-title::after {
    content: ' ✓'; color: var(--success-500); font-weight: 700;
}
.ap-item-title { font-weight: 500; color: var(--gray-900); font-size: 0.9375rem; }
.ap-item-meta { font-size: 0.8125rem; color: var(--gray-500); }
.ap-empty { padding: 0.6rem 0.75rem; color: var(--gray-500); font-size: 0.875rem; }
/* Atajo para añadir de golpe todos los resultados de la búsqueda. */
.ap-all {
    padding: 0.5rem 0.75rem; margin-bottom: 0.25rem;
    border-bottom: 1px solid var(--border);
    color: var(--brand-600); font-weight: 600; font-size: 0.875rem; cursor: pointer;
}
.ap-all:hover { background: var(--brand-50); }
/* Asignaturas ya elegidas. */
.ap-chips { list-style: none; margin: 0.5rem 0 0; padding: 0; display: grid; gap: 0.375rem; }
.ap-chip {
    display: flex; align-items: center; gap: 0.5rem;
    padding: 0.4rem 0.6rem;
    background: var(--brand-50); border: 1px solid var(--brand-200);
    border-radius: var(--radius);
}
.ap-chip-text { flex: 1; font-size: 0.875rem; color: var(--gray-900); }
.ap-chip-x {
    border: none; background: transparent; cursor: pointer; line-height: 1;
    font-size: 1.25rem; color: var(--gray-500); padding: 0 0.15rem;
}
.ap-chip-x:hover { color: var(--danger-500); }

/* ---- Selección múltiple para borrar bibliografía en bloque ---- */
.chk-col { width: 2.5rem; text-align: center; }
.bulk-bar {
    display: flex; align-items: center; gap: 0.75rem;
    padding: 0.5rem 1rem;
    background: var(--brand-50); border-bottom: 1px solid var(--brand-200);
}
.bulk-count { font-size: 0.875rem; color: var(--gray-700); font-weight: 500; }
/* Aviso del tope: aparece al llegar al máximo y parpadea si se intenta pasar. */
.bulk-max {
    font-size: 0.75rem; font-weight: 600; color: #92400e;
    background: #fef3c7; border: 1px solid #fcd34d;
    border-radius: 999px; padding: 0.1rem 0.5rem;
}
.bulk-max.is-flash { animation: bulkMaxFlash 0.5s ease; }
@keyframes bulkMaxFlash {
    0%, 100% { transform: scale(1); }
    30%      { transform: scale(1.12); background: #fde68a; }
}
.table tbody tr.is-selected > td { background: var(--brand-50); }

/* ---- Marca de revisión de la bibliografía ---- */
/* Progreso de revisión: una asignatura larga se revisa en varias sesiones y
   conviene ver de un vistazo cuánto queda. */
/* Sincronización con WorldCat: progreso de la creación/retirada de LBD. */
.lbd-sync {
    margin: 0.75rem 1rem 0;
    padding: 0.65rem 0.85rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface-2, #f7f7f8);
}
.lbd-sync-cab { display: flex; align-items: center; gap: 0.6rem; font-size: 0.875rem; }
.lbd-sync-cifra { color: var(--gray-500); font-variant-numeric: tabular-nums; }
.lbd-sync .rev-barra { margin: 0.5rem 0; }

/* Mientras trabaja, la tarjeta tiene que cantar: son minutos de llamadas a
   WorldCat y si se cierra la pestaña el trabajo se queda a medias. Un recuadro
   gris más no lo miraría nadie. */
.lbd-sync.is-activa {
    border-color: var(--brand-300);
    background: var(--brand-50);
    box-shadow: 0 0 0 3px var(--brand-100);
}
.lbd-sync.is-activa .lbd-sync-cab { font-weight: 600; color: var(--brand-800); }
.lbd-sync.is-activa .lbd-sync-cifra { color: var(--brand-700); }
/* Rueda de progreso: dice "esto sigue vivo" incluso cuando una llamada tarda. */
.lbd-sync.is-activa .lbd-sync-cab::before {
    content: '';
    width: 14px; height: 14px; flex: none;
    border: 2px solid var(--brand-200);
    border-top-color: var(--brand-600);
    border-radius: 50%;
    animation: lbdGira 0.8s linear infinite;
}
/* Al relleno de la barra se le superpone un rayado en marcha: la anchura solo
   cambia al terminar cada tanda, y entre tanda y tanda parecería congelada. */
.lbd-sync.is-activa .rev-barra > span {
    background-image: linear-gradient(115deg,
        rgba(255, 255, 255, 0.45) 25%, transparent 25%, transparent 50%,
        rgba(255, 255, 255, 0.45) 50%, rgba(255, 255, 255, 0.45) 75%,
        transparent 75%, transparent);
    background-size: 14px 14px;
    animation: lbdRayas 0.7s linear infinite;
}
.lbd-sync.is-activa #lbdAviso { color: var(--brand-700); font-weight: 600; }

@keyframes lbdGira { to { transform: rotate(360deg); } }
@keyframes lbdRayas { to { background-position: 14px 0; } }

/* Quien pide menos movimiento se queda con el color, que es lo que de verdad
   distingue el estado; el giro y el rayado son el adorno. */
@media (prefers-reduced-motion: reduce) {
    .lbd-sync.is-activa .lbd-sync-cab::before,
    .lbd-sync.is-activa .rev-barra > span { animation: none; }
}
/* Estado del LBD de una fila. Solo aparece cuando falta o falló: si estuviera
   siempre, sería una etiqueta repetida en 62.000 filas sin decir nada. */
.lbd-badge {
    display: inline-block;
    margin-left: 0.4rem;
    padding: 0.05rem 0.4rem;
    border-radius: 999px;
    font-size: 0.6875rem;
    font-weight: 600;
    line-height: 1.5;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    background: var(--gray-100, #f1f1f3);
    color: var(--gray-600, #52525b);
    cursor: help;
    vertical-align: middle;
}
.lbd-badge.is-error { background: #fdf0d5; color: #8a5a00; }
.lbd-badge.is-bloqueada { background: #fde2e2; color: #a01b1b; }

.rev-progreso { display: flex; align-items: center; gap: 0.6rem; margin-top: 0.6rem; }
.rev-barra {
    flex: 1; height: 5px; border-radius: 999px;
    background: var(--gray-200); overflow: hidden;
}
.rev-barra > span {
    display: block; height: 100%; border-radius: 999px;
    background: var(--success-500); transition: width 0.2s ease;
}
.rev-texto { font-size: 0.75rem; color: var(--gray-500); white-space: nowrap; font-weight: 500; }

.rev-filtro { display: flex; gap: 0.25rem; margin-top: 0.6rem; flex-wrap: wrap; }
.rev-filtro a {
    font-size: 0.75rem; font-weight: 500; padding: 0.2rem 0.6rem;
    border-radius: 999px; color: var(--gray-600);
    background: var(--surface-3); text-decoration: none;
}
.rev-filtro a:hover { background: var(--gray-200); color: var(--gray-900); text-decoration: none; }
.rev-filtro a.is-active { background: var(--brand-600); color: #fff; }

/* Reinicio de la revisión de toda la asignatura (p. ej. al cambiar de curso).
   Discreto: es poco frecuente y no debe competir con el filtro. */
.rev-reset {
    border: 1px solid var(--border-strong); background: var(--surface);
    color: var(--gray-600); border-radius: 999px;
    font-size: 0.75rem; font-weight: 500; padding: 0.2rem 0.7rem; cursor: pointer;
}
.rev-reset:hover { border-color: var(--warning-500); color: var(--warning-500); }

/* Botón que alterna el estado de una fila. */
.rev-toggle {
    border: 1px solid var(--border-strong); background: var(--surface);
    color: var(--gray-300); border-radius: var(--radius-sm);
    padding: 0.15rem 0.35rem; line-height: 0; cursor: pointer;
    transition: all 0.15s ease;
}
.rev-toggle:hover { border-color: var(--success-500); color: var(--success-500); }
.rev-toggle.is-on {
    background: #ecfdf5; border-color: var(--success-500); color: var(--success-500);
}

/* ---- Notas de la asignatura ---- */
/* Aviso al bibliotecario mientras trabaja la bibliografía; se distingue del
   contenido sin gritar, con el amarillo de aviso ya definido. */
.asig-nota {
    display: flex; gap: 0.75rem; align-items: flex-start;
    background: #fffbeb; border: 1px solid #fde68a;
    border-radius: var(--radius); padding: 0.75rem 1rem; margin-bottom: 1rem;
}
.asig-nota-eti {
    flex: none; text-transform: uppercase; font-size: 0.6875rem; font-weight: 700;
    letter-spacing: 0.06em; color: var(--warning-500); padding-top: 0.1rem;
}
.asig-nota-texto { font-size: 0.875rem; color: var(--gray-800); }

/* Aspa de quitar filtros: a 13px apenas se veía ni se acertaba a pulsarla.
   Se dobla el tamaño y se compensa la altura de línea para no descuadrar la
   fila de filtros. */
.btn-limpiar-x {
    font-size: 26px;
    line-height: 1;
    padding-top: 0;
    padding-bottom: 0;
    color: var(--gray-500);
}
.btn-limpiar-x:hover { color: var(--danger-500); text-decoration: none; }

/* ============================== Admin login ============================== */
.login-shell {
    min-height: 100vh;
    display: grid;
    place-items: center;
    background:
        radial-gradient(circle at 30% 20%, rgba(139, 21, 56, 0.06) 0%, transparent 50%),
        radial-gradient(circle at 70% 80%, rgba(194, 65, 12, 0.04) 0%, transparent 50%),
        var(--bg);
    padding: 2rem 1rem;
}
.login-card {
    width: 100%; max-width: 420px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    padding: 2rem;
}
.login-brand {
    display: flex; align-items: center; gap: 0.625rem;
    margin-bottom: 1.5rem;
    color: var(--gray-900); font-weight: 600;
}
.login-brand .brand-mark {
    width: 36px; height: 36px;
    background: linear-gradient(135deg, var(--brand-600), var(--brand-700));
    border-radius: 9px;
    display: flex; align-items: center; justify-content: center;
    color: #fff; font-weight: 700;
    box-shadow: var(--shadow-sm);
}

/* ============================== Utilities ============================== */
.text-muted { color: var(--gray-500) !important; }
.fw-semibold { font-weight: 600; }
.small { font-size: 0.8125rem; }
.tiny { font-size: 0.75rem; }
.divider-vertical { width: 1px; background: var(--border); align-self: stretch; }
.btn-icon {
    width: 32px; height: 32px;
    display: inline-flex; align-items: center; justify-content: center;
    padding: 0;
}

/* Animaciones */
@keyframes fadeIn { from { opacity: 0; transform: translateY(2px); } to { opacity: 1; transform: translateY(0); } }
.search-results { animation: fadeIn 0.12s ease; }
.alert { animation: fadeIn 0.15s ease; }
