/*
 * Base global: shell (sidebar + topbar), tokens y componentes compartidos.
 * No vive dentro de un @layer, así que sus reglas pesan más que las utilidades de
 * Tailwind (que sí están en @layer theme/utilities) sin importar el orden de carga;
 * por eso basta con redeclarar var(--color-indigo-600), var(--radius-lg), etc. para
 * repintar TODA la app (~150 vistas) sin recompilar con Vite.
 */

:root {
    --color-indigo-50: #eef1ff;
    --color-indigo-100: #e0e4ff;
    --color-indigo-200: #c2c9ff;
    --color-indigo-300: #9ba6ff;
    --color-indigo-400: #7a86fb;
    --color-indigo-500: #5b6bf5;
    --color-indigo-600: #4f6ef7;
    --color-indigo-700: #3c53d6;
    --color-indigo-800: #3142a8;
    --color-indigo-900: #283584;
    --color-indigo-950: #1a2258;

    --radius-md: 0.625rem;
    --radius-lg: 0.9rem;
    --radius-xl: 1.25rem;
    --radius-2xl: 1.5rem;

    --shadow-xs: 0 1px 2px rgba(16, 24, 40, 0.04);
    --shadow-sm: 0 1px 3px rgba(16, 24, 40, 0.06), 0 1px 2px rgba(16, 24, 40, 0.04);
    --shadow-md: 0 4px 10px rgba(16, 24, 40, 0.07);
    --shadow-lg: 0 10px 24px rgba(16, 24, 40, 0.1);
    --shadow-xl: 0 20px 40px rgba(16, 24, 40, 0.12);

    --font-sans: 'Plus Jakarta Sans', ui-sans-serif, system-ui, sans-serif;

    /* Tokens propios */
    --dre-bg: #f4f6fb;
    --dre-primary: var(--color-indigo-600);
    --dre-primary-dark: var(--color-indigo-800);
    --dre-primary-soft: var(--color-indigo-100);
    --dre-success: #027a48;
    --dre-success-bg: #ecfdf3;
    --dre-danger: #b42318;
    --dre-danger-bg: #fef3f2;
    --dre-warning: #b54708;
    --dre-warning-bg: #fffaeb;

    --chip-purple-bg: #f1e9fe; --chip-purple-fg: #7a3ff2;
    --chip-orange-bg: #fef2e0; --chip-orange-fg: #d9822b;
    --chip-green-bg: #e2f8ec;  --chip-green-fg: #12a150;
    --chip-pink-bg: #fdeaf1;  --chip-pink-fg: #e34c8a;
    --chip-blue-bg: #e5edff;  --chip-blue-fg: var(--dre-primary);
}

/* ---------- Base ---------- */

html, body {
    background: var(--dre-bg);
}

body {
    color: #1d2433;
}

h1, h2, h3, h4, h5, h6 {
    font-weight: 700;
    letter-spacing: -0.01em;
    color: #101828;
}

.uppercase { text-transform: none; }
.tracking-wide, .tracking-wider, .tracking-widest { letter-spacing: normal; }

/* ---------- Shell: sidebar + topbar ---------- */

:root {
    --sidebar-w: 260px;
    --sidebar-w-collapsed: 84px;
}

.app-shell {
    min-height: 100vh;
    position: relative;
}

/* "Glass" institucional: sidebar y topbar comparten exactamente el mismo fondo,
   desenfoque y borde para leerse como una sola pieza de chrome, no dos paneles
   distintos. Opacidad alta a propósito (no un glass "de vidrio transparente"):
   sigue siendo un sistema institucional, así que prima la legibilidad sobre el efecto. */
.sidebar,
.topbar {
    background: rgba(255, 255, 255, 0.94);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
}

.sidebar {
    position: fixed;
    inset: 0 auto 0 0;
    width: var(--sidebar-w);
    border-right: 1px solid #e5e7eb;
    padding: 1.5rem 1rem 1rem;
    overflow: hidden;
    z-index: 30;
    display: flex;
    flex-direction: column;
    transition: width 0.25s ease;
}

.sidebar-brand {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.25rem 0.4rem 1.75rem;
}

.sidebar-brand__mark {
    width: 1.85rem;
    height: 1.85rem;
    border-radius: 0.6rem;
    flex-shrink: 0;
    background: linear-gradient(135deg, var(--dre-primary), var(--dre-primary-dark));
}

.sidebar-brand__text {
    font-weight: 600;
    font-size: 1.05rem;
    color: #101828;
    white-space: nowrap;
}

.sidebar-brand__text strong {
    font-weight: 800;
    color: var(--dre-primary);
}

.sidebar-collapse-toggle {
    margin-left: auto;
    width: 1.75rem;
    height: 1.75rem;
    flex-shrink: 0;
    border-radius: 50%;
    border: 1px solid #e5e7eb;
    background: #fff;
    color: #667085;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: transform 0.25s ease, background 0.15s ease;
}

.sidebar-collapse-toggle:hover { background: #f3f4f6; color: #101828; }
.sidebar-collapse-toggle svg { width: 0.95rem; height: 0.95rem; }

/* Identidad del usuario dentro del panel lateral — oculta en escritorio
   (ahí ya vive en la topbar, con espacio de sobra); visible solo en móvil,
   ver @media más abajo. */
.sidebar-user-movil {
    display: none;
    align-items: center;
    gap: 0.7rem;
    padding: 0.85rem 0.6rem;
    margin-bottom: 0.5rem;
    border-top: 1px solid #eef0f5;
    border-bottom: 1px solid #eef0f5;
}

.sidebar-user-movil__avatar {
    width: 2.5rem;
    height: 2.5rem;
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
}

.sidebar-user-movil__avatar--initials {
    background: var(--dre-primary-soft);
    color: var(--dre-primary-dark);
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: 0.85rem;
}

.sidebar-user-movil__info {
    display: flex;
    flex-direction: column;
    line-height: 1.25;
    min-width: 0;
}

.sidebar-user-movil__nombre {
    font-size: 0.9rem;
    font-weight: 700;
    color: #101828;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.sidebar-user-movil__meta {
    font-size: 0.74rem;
    color: #98a2b3;
    text-transform: capitalize;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

@media (max-width: 900px) {
    .sidebar-user-movil { display: flex; }
}

/* Antes .sidebar entero hacía overflow-y:auto, así que la marca y el botón
   "Cerrar sesión" (al final del todo) se desplazaban junto con la lista de
   opciones — con varios grupos abiertos había que hacer scroll para
   encontrarlo. Ahora SOLO esta lista central scrollea (min-height:0 es
   necesario para que un hijo flex pueda encogerse y activar su propio
   scroll); la marca arriba y la tarjeta de usuario + "Cerrar sesión" abajo
   quedan siempre visibles, sin importar cuántas opciones tenga el rol. */
.sidebar-nav {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
}

.nav-link {
    position: relative;
    display: flex;
    align-items: center;
    gap: 0.7rem;
    padding: 0.6rem 0.75rem;
    border-radius: var(--radius-md);
    font-size: 0.85rem;
    font-weight: 500;
    color: #667085;
    text-decoration: none;
    white-space: nowrap;
}

.nav-link:hover {
    background: #f3f4f6;
    color: #101828;
}

.nav-link--active {
    background: var(--dre-primary);
    color: #fff;
    font-weight: 600;
}

.nav-link__icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 1.35rem;
    height: 1.35rem;
    flex-shrink: 0;
}

.nav-link__icon svg { width: 100%; height: 100%; }

/* Elementos que se desvanecen (no se ocultan de golpe) al contraer el sidebar,
   para que la transición se vea suave en vez de un salto brusco. */
.nav-fade {
    opacity: 1;
    max-width: 220px;
    transition: opacity 0.15s ease, max-width 0.25s ease;
}

/* ---------- Grupos del sidebar (temas con sub-opciones plegables) ---------- */

.nav-group-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    width: 100%;
    margin: 0.9rem 0 0.15rem;
    padding: 0 0.75rem;
    background: none;
    border: none;
    cursor: pointer;
    font-family: inherit;
}

.nav-group-header__label {
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    color: #98a2b3;
}

.nav-group-header__chevron {
    display: flex;
    color: #98a2b3;
    transition: transform 0.2s ease;
}

.nav-group-header__chevron svg { width: 0.85rem; height: 0.85rem; }

.nav-group-header__chevron--collapsed { transform: rotate(-90deg); }

/* Truco de grid para animar alto sin JS que mida píxeles: 1fr abierto, 0fr cerrado. */
.nav-group {
    display: grid;
    grid-template-rows: 1fr;
    transition: grid-template-rows 0.2s ease;
}

.nav-group--collapsed { grid-template-rows: 0fr; }

.nav-group__inner {
    overflow: hidden;
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    min-height: 0;
}

.sidebar-logout {
    margin-top: 0.5rem;
    padding-top: 0.75rem;
    border-top: 1px solid #e5e7eb;
}

.nav-link--logout {
    width: 100%;
    text-align: left;
    background: none;
    border: none;
    cursor: pointer;
    color: var(--dre-danger);
    font-family: inherit;
}

.nav-link--logout:hover {
    background: var(--dre-danger-bg);
}

.app-body {
    margin-left: var(--sidebar-w);
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    position: relative;
    z-index: 1;
    transition: margin-left 0.25s ease;
}

/* ---------- Sidebar contraído (escritorio) ---------- */

@media (min-width: 901px) {
    html.sidebar-collapsed .sidebar { width: var(--sidebar-w-collapsed); }
    html.sidebar-collapsed .app-body { margin-left: var(--sidebar-w-collapsed); }
    html.sidebar-collapsed .nav-fade { opacity: 0; max-width: 0; }
    html.sidebar-collapsed .sidebar-collapse-toggle { transform: rotate(180deg); }
    /* La marca (1.85rem) + el botón de contraer (1.75rem) lado a lado ya no
       entran en el ancho disponible del sidebar contraído (84px, menos el
       padding propio del .sidebar): antes se centraban como una sola fila y
       el botón terminaba saliéndose del recuadro de la marca, viéndose
       descolgado. Apilados en columna, cada uno entra sobrado. */
    html.sidebar-collapsed .sidebar-brand {
        flex-direction: column;
        gap: 0.5rem;
        justify-content: center;
        padding: 0.25rem 0 1.75rem;
    }
    html.sidebar-collapsed .sidebar-collapse-toggle { margin-left: 0; }
    html.sidebar-collapsed .nav-link { justify-content: center; padding-left: 0; padding-right: 0; }

    /* Con el sidebar contraído no hay espacio para encabezados de grupo: se
       ocultan y todas las opciones quedan visibles en una sola franja de íconos. */
    html.sidebar-collapsed .nav-group-header { display: none; }
    html.sidebar-collapsed .nav-group { grid-template-rows: 1fr !important; }
}

/* Burbuja con el nombre de la opción al pasar el mouse sobre un ícono del
   sidebar contraído. Antes era un ::after/::before puro en CSS posicionado
   con `left: calc(100% + 14px)` respecto al ícono — pero .sidebar tiene
   `overflow-x: hidden` (necesario para que la transición de ancho al
   contraer/expandir no muestre un scrollbar horizontal momentáneo), y ese
   overflow recorta a CUALQUIER descendiente que visualmente se salga del
   panel, sin importar que sea un pseudo-elemento: la burbuja quedaba
   prácticamente invisible (solo se llegaba a ver una astilla de la flechita).
   Por eso el tooltip real se genera con JS (ver navigation.blade.php) como
   un elemento aparte colgado de <body>, position:fixed, fuera del árbol
   recortado por .sidebar. Esta clase es solo su apariencia. */
.sidebar-tooltip {
    position: fixed;
    background: #101828;
    color: #fff;
    font-size: 0.78rem;
    font-weight: 500;
    line-height: 1;
    white-space: nowrap;
    padding: 0.5rem 0.75rem;
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-md);
    z-index: 50;
    pointer-events: none;
}

.sidebar-tooltip::before {
    content: '';
    position: absolute;
    right: 100%;
    top: 50%;
    transform: translateY(-50%);
    border: 6px solid transparent;
    border-right-color: #101828;
}

@media (max-width: 900px) {
    /* En móvil el botón de contraer a modo icono no tiene ningún efecto (las
       reglas de arriba solo aplican desde 901px): dejarlo visible y
       cliqueable ahí era un control muerto que no hacía nada. */
    .sidebar-collapse-toggle { display: none; }
}

.topbar {
    height: 70px;
    border-bottom: 1px solid #e5e7eb;
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 0 1.75rem;
    position: sticky;
    top: 0;
    z-index: 20;
}

/* Chip de institución: sin esto, la sesión activa (sobre todo para un
   admin_instituto o secretario que solo ve SU institución) no dejaba ninguna
   pista de a qué institución pertenecen los datos que se están viendo.
   Estilo "institucional": logo real de la institución (como una credencial),
   etiqueta pequeña en mayúsculas y el nombre grande — pero SIN encerrarlo en
   una píldora/tarjeta: va suelto sobre el propio fondo "glass" de la topbar,
   igual que el resto de sus elementos (nadie más ahí lleva una caja propia). */
.topbar-institucion {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    min-width: 0;
}

/* object-fit:contain (no "cover") + fondo neutro en vez de recorte circular:
   un escudo/sello institucional casi nunca es un círculo perfecto, así que
   forzarlo con border-radius:50%+cover le cortaba las puntas o lo deformaba.
   Aquí se ve completo, en su forma y proporción originales, sobre una
   tarjetita cuadrada suave (el mismo tratamiento que le da cualquier sistema
   institucional a un logo de procedencia variable). */
.topbar-institucion__logo {
    width: 2.75rem;
    height: 2.75rem;
    border-radius: 0.65rem;
    object-fit: contain;
    flex-shrink: 0;
    background: #fff;
    padding: 0.2rem;
}

.topbar-institucion__logo--placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(135deg, var(--dre-primary), var(--dre-primary-dark));
    color: #fff;
    font-weight: 800;
    font-size: 0.85rem;
    letter-spacing: 0.02em;
    border: none;
    padding: 0;
}

.topbar-institucion__texto {
    display: flex;
    flex-direction: column;
    line-height: 1.2;
    min-width: 0;
}

.topbar-institucion__etiqueta {
    font-size: 0.68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: #98a2b3;
}

.topbar-institucion__nombre {
    font-size: 1.2rem;
    font-weight: 800;
    color: #101828;
    letter-spacing: -0.01em;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

@media (max-width: 1180px) {
    /* Antes de llegar al punto de quiebre móvil, el nombre completo ya no
       cabe cómodo junto al resto de la topbar (logo del usuario, campana);
       se mantiene el logo institucional (con el nombre en el title="") en
       vez de forzar el resto de la barra a apretarse. */
    .topbar-institucion__texto { display: none; }
    .topbar-institucion__logo { width: 2.35rem; height: 2.35rem; }
}

.topbar-spacer { flex: 1; }

.sidebar-toggle {
    display: none;
    flex-direction: column;
    gap: 4px;
    background: none;
    border: none;
    cursor: pointer;
    padding: 0.4rem;
}

.sidebar-toggle span {
    width: 20px;
    height: 2px;
    border-radius: 2px;
    background: #475467;
}

.topbar-user {
    display: flex;
    align-items: center;
    gap: 0.65rem;
}

.topbar-user__avatar {
    width: 2.25rem;
    height: 2.25rem;
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
}

.topbar-user__avatar--initials {
    background: var(--dre-primary-soft);
    color: var(--dre-primary-dark);
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: 0.75rem;
}

.topbar-user__info {
    display: flex;
    flex-direction: column;
    line-height: 1.2;
}

.topbar-user__name {
    font-size: 0.85rem;
    font-weight: 600;
    color: #101828;
}

.topbar-user__codigo {
    margin-left: 0.4rem;
    font-size: 0.72rem;
    font-weight: 500;
    color: #98a2b3;
}

@media (max-width: 900px) {
    /* En móvil el nombre, código, rol y el botón "Salir" se mudan por completo
       al panel lateral (.sidebar-user-movil, debajo de la marca) — ahí no hay
       problema de espacio para mostrarlos con calma, a diferencia de la
       topbar de una sola franja de 70px. Eso deja la topbar móvil con solo
       tres elementos: el botón de menú, el logo institucional y la campana. */
    .topbar-user { display: none; }
}

.topbar-user__role {
    font-size: 0.72rem;
    color: #98a2b3;
    text-transform: capitalize;
}

.topbar-logout {
    margin-left: 0.5rem;
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--dre-danger);
    background: var(--dre-danger-bg);
    border: none;
    border-radius: var(--radius-md);
    padding: 0.4rem 0.8rem;
    cursor: pointer;
    font-family: inherit;
}

.app-content {
    padding: 2rem;
    max-width: 1600px;
    width: 100%;
    margin: 0 auto;
}

/* Fondo oscuro detrás del sidebar en móvil. Sin esto, al abrir el menú
   (position:fixed, z-index:30) tapaba también al propio botón hamburguesa
   —que vive dentro de .topbar, z-index:20, en esa misma franja izquierda—
   así que una vez abierto no había ningún control visible para volver a
   cerrarlo: quedaba atrapado abierto hasta recargar la página. Este fondo
   se ve (contraste de que hay un panel encima) y, al ser cliqueable, es
   ahora la forma de cerrarlo. */
.sidebar-backdrop {
    display: none;
}

@media (max-width: 900px) {
    .sidebar {
        transform: translateX(-100%);
        transition: transform 0.2s ease;
    }
    .sidebar.sidebar--open {
        transform: translateX(0);
        box-shadow: var(--shadow-lg);
    }
    .app-body { margin-left: 0; }
    .sidebar-toggle { display: flex; }
    .app-content { padding: 1.25rem; }

    .sidebar-backdrop.sidebar-backdrop--visible {
        display: block;
        position: fixed;
        inset: 0;
        background: rgba(16, 24, 40, 0.45);
        z-index: 25;
    }
}

/* ---------- Encabezado de página ---------- */

.page-heading {
    margin: 0 0 1.5rem;
}

.page-heading h1 {
    font-size: 1.5rem;
    line-height: 1.25;
    margin: 0;
}

/* ---------- Avisos de sesión ---------- */

.notice {
    margin-bottom: 1.5rem;
    padding: 0.85rem 1.1rem;
    border-radius: var(--radius-md);
    background: #f6f7fb;
    color: #344054;
    font-size: 0.875rem;
}

.notice-success { background: var(--dre-success-bg); color: var(--dre-success); }
.notice-danger { background: var(--dre-danger-bg); color: var(--dre-danger); }

/* Texto de "aún no hay nada que mostrar" dentro de una tarjeta o lista. */
.empty-state {
    padding: 1.5rem;
    text-align: center;
    color: #667085;
    font-size: 0.875rem;
}

/* ---------- Tablas ---------- */

table { border-collapse: collapse; width: 100%; }
th, td { vertical-align: middle; }

table thead th {
    background: #f9fafb;
    border-bottom: 1px solid #eef0f5;
    padding: 0.65rem 1rem;
    font-size: 0.78rem;
    font-weight: 600;
    color: #667085;
    text-align: left;
}

table tbody td { padding: 0.7rem 1rem; }
table tbody tr { border-bottom: 1px solid #f2f4f7; }
table tbody tr:hover { background: #fafbfe; }

/* ---------- Contenido enriquecido (editor WYSIWYG) ----------
   El plugin @tailwindcss/typography no está instalado: sin estas reglas, las clases
   `prose`/`prose-sm` usadas en anuncios, tareas y sílabos no aplican ningún estilo. */

.prose { color: #344054; line-height: 1.7; }
.prose :where(h1, h2, h3, h4) { color: #101828; font-weight: 700; margin: 1.1em 0 0.5em; line-height: 1.25; }
.prose h1 { font-size: 1.5em; }
.prose h2 { font-size: 1.3em; }
.prose h3 { font-size: 1.15em; }
.prose p { margin: 0.75em 0; }
.prose ul, .prose ol { margin: 0.75em 0; padding-left: 1.4em; }
.prose ul { list-style: disc; }
.prose ol { list-style: decimal; }
.prose li { margin: 0.25em 0; }
.prose a { color: var(--dre-primary); text-decoration: underline; text-underline-offset: 2px; }
.prose strong { color: #101828; }
.prose blockquote {
    border-left: 3px solid #d0d5dd;
    padding-left: 1em;
    margin: 1em 0;
    color: #667085;
    font-style: italic;
}
.prose table { width: 100%; margin: 1em 0; font-size: 0.925em; }
.prose th, .prose td { border: 1px solid #eef0f5; padding: 0.5em 0.7em; text-align: left; }
.prose th { background: #f9fafb; }
.prose img, .prose video { max-width: 100%; border-radius: var(--radius-md); margin: 0.75em 0; }
.prose code {
    background: #f2f4f7;
    padding: 0.15em 0.4em;
    border-radius: 4px;
    font-size: 0.9em;
    font-family: ui-monospace, monospace;
}
.prose hr { border: none; border-top: 1px solid #eef0f5; margin: 1.5em 0; }
.prose-sm { font-size: 0.925rem; }

/*
 * ---------- Relleno de utilidades responsivas de Tailwind que faltan en el bundle ----------
 * El bundle compilado en public/build/ quedó fijado en un momento anterior del proyecto y,
 * al no haber Node/npm disponible en este entorno, no se puede volver a compilar con
 * `vite build` para que Tailwind detecte clases nuevas usadas en las vistas. Cualquier
 * combinación de utilidad responsiva (sm:/lg:/...) que no existiera ya en ese bundle
 * simplemente no tiene ninguna regla CSS y no hace nada — es lo que causaba, por ejemplo,
 * que `grid grid-cols-1 gap-6 lg:grid-cols-2` se quedara en una sola columna sin ningún
 * aviso ni error, o que dos tarjetas quedaran pegadas por no tener `gap` aplicado.
 * Estas reglas reproducen exactamente esas utilidades ausentes (mismos breakpoints,
 * sm=40rem, lg=64rem, que usa el propio Tailwind) para que sigan funcionando sin
 * depender de recompilar el bundle. Antes de usar una utilidad responsiva nueva en
 * cualquier vista, conviene revisar aquí si ya existe o agregarla.
 */
@media (min-width: 40rem) {
    .sm\:col-span-1 { grid-column: span 1 / span 1; }
    .sm\:col-span-3 { grid-column: span 3 / span 3; }
    .sm\:grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .sm\:grid-cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
    .sm\:grid-cols-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
    .sm\:grid-cols-6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }
    .sm\:w-auto { width: auto; }
}

@media (min-width: 64rem) {
    .lg\:col-span-1 { grid-column: span 1 / span 1; }
    .lg\:col-span-2 { grid-column: span 2 / span 2; }
    .lg\:col-span-3 { grid-column: span 3 / span 3; }
    .lg\:grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .lg\:grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .lg\:grid-cols-6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }
    .lg\:grid-cols-8 { grid-template-columns: repeat(8, minmax(0, 1fr)); }
}

/*
 * Igual que el bloque anterior, pero para utilidades NO responsivas que tampoco
 * están en el bundle (auditadas comparando cada clase usada en resources/views
 * contra public/build/assets/app-*.css). Es una lista larga porque el bundle
 * quedó fijado en un punto muy temprano del proyecto: cosas tan básicas como
 * `mb-3`, `border-gray-100` o `space-y-6` ya faltaban, usadas en decenas de
 * vistas — no es un caso aislado del apartado de Aula Virtual.
 */

/* Espaciado */
.mb-3 { margin-bottom: 0.75rem; }
.mt-3 { margin-top: 0.75rem; }
.mt-5 { margin-top: 1.25rem; }
.mt-1\.5 { margin-top: 0.375rem; }
.mx-1 { margin-left: 0.25rem; margin-right: 0.25rem; }
.ml-11 { margin-left: 2.75rem; }
.ml-auto { margin-left: auto; }
.my-3 { margin-top: 0.75rem; margin-bottom: 0.75rem; }
.my-4 { margin-top: 1rem; margin-bottom: 1rem; }
.pt-2 { padding-top: 0.5rem; }
.pt-3 { padding-top: 0.75rem; }
.pt-4 { padding-top: 1rem; }
.pt-5 { padding-top: 1.25rem; }
.pt-6 { padding-top: 1.5rem; }
.pb-2 { padding-bottom: 0.5rem; }
.p-1\.5 { padding: 0.375rem; }
.p-3 { padding: 0.75rem; }

/* Espaciado entre hijos directos (space-y-N), mismo selector que usa Tailwind */
.space-y-1 > :not([hidden]) ~ :not([hidden]) { margin-top: 0.25rem; }
.space-y-2 > :not([hidden]) ~ :not([hidden]) { margin-top: 0.5rem; }
.space-y-3 > :not([hidden]) ~ :not([hidden]) { margin-top: 0.75rem; }
.space-y-6 > :not([hidden]) ~ :not([hidden]) { margin-top: 1.5rem; }
.space-y-8 > :not([hidden]) ~ :not([hidden]) { margin-top: 2rem; }

/* Tamaños */
.max-w-xs { max-width: 20rem; }
.max-h-32 { max-height: 8rem; }
.w-px { width: 1px; }
.w-0 { width: 0; }
.w-12 { width: 3rem; }
.w-20 { width: 5rem; }
.w-24 { width: 6rem; }
.w-28 { width: 7rem; }
.w-56 { width: 14rem; }
.h-12 { height: 3rem; }
.h-full { height: 100%; }

/* Layout / varios */
.grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-cols-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
.items-end { align-items: flex-end; }
.sticky { position: sticky; }
.z-10 { z-index: 10; }
.object-cover { object-fit: cover; }
.object-contain { object-fit: contain; }
.line-through { text-decoration-line: line-through; }
.italic { font-style: italic; }
.font-normal { font-weight: 400; }
.tabular-nums { font-variant-numeric: tabular-nums; }
.whitespace-pre-line { white-space: pre-line; }
.border-2 { border-width: 2px; }
.border-l-2 { border-left-width: 2px; }

/* Colores */
.border-gray-100 { border-color: oklch(96.7% .003 264.542); }
.ring-gray-100 { --tw-ring-color: oklch(96.7% .003 264.542); }
.bg-gray-300 { background-color: oklch(87.2% .01 258.338); }
.bg-yellow-50 { background-color: oklch(98.7% .026 102.212); }
.ring-yellow-200 { --tw-ring-color: oklch(94.5% .129 101.54); }
.bg-blue-50 { background-color: oklch(97% .014 254.604); }
.text-blue-800 { color: oklch(42.4% .199 265.638); }
.ring-blue-200 { --tw-ring-color: oklch(88.2% .059 254.128); }
.text-green-600 { color: oklch(62.7% .194 149.214); }
.text-red-500 { color: oklch(63.7% .237 25.331); }
.text-amber-600 { color: oklch(66.6% .179 58.318); }
.bg-indigo-50 { background-color: var(--color-indigo-50); }
.bg-indigo-500 { background-color: var(--color-indigo-500); }
.text-indigo-900 { color: var(--color-indigo-900); }
.border-indigo-100 { border-color: var(--color-indigo-100); }
.border-indigo-200 { border-color: var(--color-indigo-200); }
.ring-indigo-100 { --tw-ring-color: var(--color-indigo-100); }
.bg-indigo-50\/40 { background-color: color-mix(in oklab, var(--color-indigo-50) 40%, transparent); }

.hover\:text-indigo-600:hover { color: var(--color-indigo-600); }
.hover\:text-indigo-500:hover { color: var(--color-indigo-500); }
.hover\:text-red-500:hover { color: oklch(63.7% .237 25.331); }
.hover\:ring-indigo-300:hover { --tw-ring-color: var(--color-indigo-300); }

.focus-within\:ring-2:focus-within { --tw-ring-shadow: var(--tw-ring-inset, ) 0 0 0 calc(2px + var(--tw-ring-offset-width, 0px)) var(--tw-ring-color, currentcolor); box-shadow: var(--tw-inset-shadow, 0 0 #0000), var(--tw-inset-ring-shadow, 0 0 #0000), var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow, 0 0 #0000); }
.focus-within\:ring-indigo-500:focus-within { --tw-ring-color: var(--color-indigo-500); }
.focus-within\:border-indigo-500:focus-within { border-color: var(--color-indigo-500); }

/* input[type=file]: pseudo-elemento del botón nativo */
.file\:mr-3::file-selector-button { margin-right: 0.75rem; }
.file\:rounded-md::file-selector-button { border-radius: var(--radius-md); }
.file\:border-0::file-selector-button { border-width: 0; }
.file\:bg-gray-100::file-selector-button { background-color: oklch(96.7% .003 264.542); }
.file\:px-3::file-selector-button { padding-left: 0.75rem; padding-right: 0.75rem; }
.file\:py-2::file-selector-button { padding-top: 0.5rem; padding-bottom: 0.5rem; }
.file\:text-sm::file-selector-button { font-size: 0.875rem; }
.file\:font-medium::file-selector-button { font-weight: 500; }
