@import url('https://fonts.googleapis.com/css2?family=Cinzel:wght@700&display=swap');

/* ── Radio de esquinas (lg/xl → sm Sail) ───────────────────────────────────
   Baja el radio por defecto de Filament (rounded-lg .5rem / rounded-xl .75rem)
   a 0.25rem (4px) de forma global — radios pequeños del sistema Sail (Stripe),
   cubriendo también responsive (sm:/md:) y direccionales. Sustituye a ~18
   overrides de blade publicados (revertidos) y unifica forms/tables/widgets.

   IMPORTANTE — va ANTES que las reglas .fi-* de radio de este fichero a
   propósito: .fi-section/.fi-card/.fi-ta-ctn (.5rem) tienen la misma
   especificidad y, al ir después, ganan por orden de cascada. Así se conserva
   el radio algo mayor (8px) deliberado en cards y tablas. */
[class*="rounded-xl"],
[class*="rounded-lg"] { border-radius: 0.25rem !important; }

/* Direccionales: solo las esquinas afectadas, para no redondear las que deben
   quedar rectas (p. ej. segmentos internos de un button-group). */
[class*="rounded-t-xl"] { border-top-left-radius: 0.25rem !important;  border-top-right-radius: 0.25rem !important; }
[class*="rounded-b-xl"] { border-bottom-left-radius: 0.25rem !important; border-bottom-right-radius: 0.25rem !important; }
[class*="rounded-s-lg"] { border-start-start-radius: 0.25rem !important; border-end-start-radius: 0.25rem !important; }
[class*="rounded-e-lg"] { border-start-end-radius: 0.25rem !important;   border-end-end-radius: 0.25rem !important; }

/* ── Color de borde neutro unificado ─────────────────────────────────────
   "Todo lo que tenga borde, el mismo gris". Filament dibuja los marcos con dos
   mecanismos y hay que cubrir ambos:
     · bordes reales  → border-gray-* / divide-gray-*
     · RINGS          → ring-gray-950/* (box-shadow gris al 5-10%, casi
                        transparente: por eso widgets y tabs "no se veían" y el
                        dashboard /app parecía revertir al cargar el widget tarde)
   Unificamos los dos a --geist-border-strong (#C1C9D2). NO tocamos colores de
   estado (danger/primary/warning): usan sus propias escalas, no `gray`. */
[class*="ring-gray-950"] { --tw-ring-color: var(--geist-border-strong) !important; }
[class*="border-gray-"]  { border-color: var(--geist-border-strong) !important; }
[class*="divide-gray-"] > :not([hidden]) ~ :not([hidden]) { border-color: var(--geist-border-strong) !important; }

/* ── Sidebar ──────────────────────────────────────────────────────────── */

/* ── Design tokens ────────────────────────────────────────────────────────
   Fuente única de la paleta de marca. Cada color repetido en este fichero se
   declara aquí una vez y se referencia con var(). El espejo Tailwind de esta
   misma paleta vive en `resources/css/app.css` (@theme) y en
   `AppPanelProvider->colors()`; ambos deben mantenerse en sync con estos hex. */
:root {
    --sidebar-width: 280px; /* T17: 240→280. Token/single-source; el ancho REAL se
                               fija en .fi-sidebar (ver nota abajo): Filament pisa este
                               :root con un <style> inline del <head> y gana por cascada. */
    --content-max: 1680px; /* tope de ancho útil en monitores anchos */

    /* ── Paleta de marca (ADR 0020) — FUENTE semántica ──────────────────────
       Teal (primary) · oro académico (secondary) · navy (sidebar) · estados.
       Los tokens legacy --brand-* de abajo son alias delgados sobre estos; los
       ~10 selectores .fi-* consumidores NO se tocan. Espejo PHP en
       app/Support/BrandPalette.php (mismo commit, contrato anti-divergencia).
       secondary (oro) queda DISPONIBLE, sin uso en esta unidad. */
    --primary: #0E9384;
    --primary-hover: #0B7A6E;
    --primary-soft: #E7F5F3;
    --secondary: #C08A2E;
    --secondary-hover: #A6741F;
    --secondary-soft: #F7EED9;
    --navy: #1B2A41;
    --navy-hover: #263850;
    --navy-footer: #142236;
    --info: #5468D6;
    --success: #099268;
    --warning: #F59E0B;
    --danger: #E11D48;
    --danger-hover: #BE123C;

    /* Marca (alias legacy → fuente semántica; NO tocar los consumidores .fi-*) */
    --brand-coral: var(--primary);
    --brand-navy: var(--navy);
    --brand-navy-hover: var(--navy-hover);
    --brand-navy-footer: var(--navy-footer);

    /* Superficies y bordes (escala Sail — Stripe Dashboard) */
    --content-bg: #F7FAFC;
    --surface: #FFFFFF;
    --topbar-border: #E3E8EE;

    /* Sidebar (texto/iconos sobre navy) */
    --sidebar-label: #93a3b8;
    --sidebar-text: #f1f5f9;
    --sidebar-icon: #94a3b8;
    --sidebar-on-active: #ffffff;

    /* Estados: el anillo de foco sigue a primary (teal) vía alias --brand-coral.
       --danger/--danger-hover viven en la fuente semántica (arriba). */
    --focus-ring: var(--brand-coral);

    /* ── Neutrales y superficies (escala Sail — Stripe Dashboard) ───────────
       Grises fríos del sistema Sail, espejo de BrandPalette::GRAY (mantener en
       sync). Reemplazan a la escala Geist neutra previa; el coral de marca y la
       familia (Plus Jakarta Sans) quedan intactos.
       Contraste sobre blanco: #4F5B6E → ~6.9:1 OK como texto secundario;
       #7B8A9C → ~3.5:1 solo para texto grande / no esencial; el teal (primary)
       sigue vetado como color de texto sobre fondo claro. */
    --geist-bg: #FFFFFF;
    --geist-bg-subtle: #F7FAFC;     /* Sail gray-50 */
    --geist-border: #E3E8EE;        /* Sail gray-100 */
    --geist-border-strong: #C1C9D2; /* Sail gray-200 */
    --geist-text: #1A1F36;          /* Sail gray-900 */
    --geist-text-muted: #4F5B6E;    /* Sail gray-600 — ~6.9:1 sobre blanco */
    --geist-text-faint: #7B8A9C;    /* Sail gray-400 — ~3.5:1, solo texto grande/no esencial */

    /* Espaciado — SOLO para nuestros overrides, NO pisa el spacing de Filament */
    --space-1: 4px;
    --space-2: 8px;
    --space-3: 12px;
    --space-4: 16px;
    --space-5: 24px;
    --space-6: 32px;

    /* Radios */
    --radius-sm: 6px;
    --radius-md: 8px;
    --radius-lg: 12px;
    --radius-full: 9999px;

    /* Sombras multicapa (Sail — Stripe Dashboard). La card flota SIN borde: el
       anillo de 1px del box-shadow hace de borde y las capas dan la elevación.
       El botón primario lleva anillo teal + caída pronunciada (efecto "raised"). */
    --shadow-card: 0 0 0 1px rgba(60, 66, 87, 0.10),
                   0 3px 8px -2px rgba(26, 31, 54, 0.12),
                   0 2px 4px -1px rgba(26, 31, 54, 0.08);
    /* Glow del botón primario (teal @30%). Este rgba es el FALLBACK; el color-mix
       real, atado a --primary, se aplica en el @supports del final del fichero
       (color-mix embebido en var() no degrada por redeclaración de custom prop). */
    --glow-primary: rgba(14, 147, 132, 0.30);
    --shadow-btn-primary: 0 0 0 1px var(--brand-coral),
                          0 1px 1px rgba(0, 0, 0, 0.10),
                          0 3px 6px var(--glow-primary),
                          0 4px 10px rgba(42, 47, 69, 0.16);
    --shadow-btn-secondary: 0 0 0 1px rgba(60, 66, 87, 0.12), 0 1px 1px rgba(0, 0, 0, 0.05);

    /* Escala tipográfica (tamaños) */
    --text-xs: 12px;
    --text-sm: 13px;
    --text-base: 14px;
    --text-md: 16px;
    --text-lg: 18px;
    --text-xl: 24px;

    /* Pesos */
    --font-weight-normal: 400;
    --font-weight-medium: 500;
    --font-weight-semibold: 600;

    /* Line-heights */
    --line-height-tight: 1.25;
    --line-height-normal: 1.5;
}

/* Navy background for the sidebar */
.fi-sidebar {
    background-color: var(--brand-navy) !important;
    border-right: none !important;

    /* T17 — ancho REAL del sidebar (280px). El token :root de este fichero NO gana en
       runtime: Filament re-declara `:root { --sidebar-width: … }` en un <style> inline
       del <head> (base.blade.php:64 → getSidebarWidth() = 20rem/320px por defecto, el
       provider no llama a ->sidebarWidth()) que carga DESPUÉS de isiscampus.css y, a
       igual especificidad, vence al token por orden de cascada. Redefiniendo la variable
       sobre el propio elemento consumidor — .fi-sidebar lleva la utilidad
       `w-[--sidebar-width]` — se resuelve localmente y gana a la herencia de :root, sin
       tocar el provider ni el <style> inline. El estado colapsado usa una variable
       distinta (--collapsed-sidebar-width), que NO tocamos, así que
       sidebarCollapsibleOnDesktop sigue intacto. */
    --sidebar-width: 260px !important;
}

/* ── Marca en el topbar (bloque navy = ancho del sidebar) ─────────────────────
   v4 pone el topbar full-width arriba y el sidebar debajo; el logo suelto sale en
   el topbar blanco. Convertimos `.fi-topbar-start` en el bloque de marca navy del
   ancho del sidebar (logo + «isiscampus» + toggle), que se continúa sin costura
   con el sidebar navy de debajo: una única columna navy a la izquierda, como v3.
   El selector de academia arranca justo donde acaba ese bloque (= ancho sidebar).
   Solo en desktop (lg+): en móvil el topbar de v4 (hamburguesa + off-canvas) queda
   intacto. El estado colapsado del sidebar (sin `.fi-sidebar-open`) estrecha el
   bloque y desplaza el selector para seguir el ancho del rail (136px medido). */
@media (min-width: 1024px) {
    .fi-brand-name {
        font-size: 1.35rem;
        font-weight: 700;
        color: #ffffff;
        letter-spacing: 0.1em;
        text-transform: lowercase;
        white-space: nowrap;
    }

    /* El topbar trae padding-inline propio que empujaría el bloque navy 16px a la
       derecha, desalineándolo del sidebar (x=0). Lo anulamos a la izquierda. */
    .fi-topbar {
        padding-inline-start: 0 !important;
        position: relative !important;
    }
    .fi-topbar-start {
        width: 260px !important;
        align-self: stretch !important;
        background-color: var(--brand-navy) !important;
        display: flex !important;
        align-items: center !important;
        gap: 0.85rem !important;
        padding-inline: 1rem !important;
        box-sizing: border-box !important;
    }
    /* logo + «isiscampus» a la izquierda; el toggle de colapso al borde derecho. */
    .fi-topbar-start > a,
    .fi-topbar-start .fi-logo,
    .fi-topbar-start .fi-brand-name {
        order: 1;
    }
    .fi-topbar-start .fi-topbar-collapse-sidebar-btn-ctn {
        order: 2;
        margin-inline-start: auto !important;
    }
    /* iconos/logo claros sobre navy */
    .fi-topbar-start .fi-icon-btn {
        color: var(--sidebar-icon) !important;
    }
    /* El selector de academia arranca donde acaba el sidebar (bloque navy). */
    .academy-selector-topbar {
        position: absolute !important;
        inset-inline-start: 260px !important;
        top: 50% !important;
        transform: translateY(-50%) !important;
        padding-inline-start: 1rem !important;
    }

    /* Sidebar colapsado (pierde `.fi-sidebar-open`): el bloque de marca y el
       selector siguen el ancho del rail (~136px) para no sobresalir. En este
       estado «isiscampus» no cabe; solo queda el logo + el toggle de expandir. */
    body:has(.fi-main-sidebar:not(.fi-sidebar-open)) .fi-topbar-start {
        width: 140px !important;
        gap: 0.4rem !important;
        padding-inline: 0.5rem !important;
    }
    body:has(.fi-main-sidebar:not(.fi-sidebar-open)) .fi-brand-name {
        display: none !important;
    }
    body:has(.fi-main-sidebar:not(.fi-sidebar-open)) .academy-selector-topbar {
        inset-inline-start: 140px !important;
    }
}

/* Brand area at the top of the sidebar — navy (v4 la oculta en desktop cuando hay
   topbar; la marca vive ahora en `.fi-topbar-start`, ver arriba). */
.fi-sidebar-header {
    background-color: var(--brand-navy) !important;
    border-bottom: 1px solid rgba(255,255,255,0.06) !important;
}

/* ── Navegación (modernización sidebar) ──────────────────────────────────────
   Ritmo aireado + píldoras flotantes insertadas (no pegadas a los bordes) +
   activo elevado con acento de marca a la izquierda e icono teal (inspirado en el
   mockup Dribbble, no literal). El navy y el teal de marca (ADR 0020) se conservan. */

/* Ritmo vertical entre ítems dentro de un grupo */
.fi-sidebar-group-items {
    display: flex !important;
    flex-direction: column !important;
    gap: 0.125rem !important;
}

/* Aire entre grupos */
.fi-sidebar-group + .fi-sidebar-group {
    margin-top: 0.75rem !important;
}

/* Etiquetas de grupo — alineadas al inset de las píldoras */
.fi-sidebar-group-label {
    color: var(--sidebar-label) !important;
    font-size: 0.6875rem !important; /* 11px — spec: 11-12px */
    font-weight: 700 !important;
    letter-spacing: 0.12em !important;
    text-transform: uppercase !important;
    padding-inline: 0.75rem !important;
    margin-bottom: 0.15rem !important;
}

/* Nav items — v4 renombra el <a> de fi-sidebar-item-button → fi-sidebar-item-btn;
   además `.fi-active` ya NO va en ese <a> sino en su <li class="fi-sidebar-item">
   padre (ver vendor/filament/filament/resources/views/components/sidebar/item.blade.php).
   Píldora flotante: margin-inline la separa de los bordes; transición suave. */
.fi-sidebar-item-btn {
    color: var(--sidebar-text) !important;
    border-radius: 0.625rem !important;          /* 10px — píldora */
    margin-inline: 0.5rem !important;
    padding-block: 0.5rem !important;
    transition: background-color .15s ease, color .15s ease, box-shadow .15s ease !important;
}

.fi-sidebar-item-label {
    color: var(--sidebar-text) !important;
    font-size: var(--text-sm) !important;        /* T6: rol nav-item (13px) */
    font-weight: 500 !important;                 /* medium — escala T4 */
    letter-spacing: -0.01em !important;
    line-height: var(--line-height-tight) !important;
}

.fi-sidebar-item-btn:hover {
    background-color: var(--brand-navy-hover) !important;
    color: var(--sidebar-on-active) !important;
}

/* Active nav item — `.fi-active` vive en el <li> ancestro (fi-sidebar-item),
   no en el <a> (fi-sidebar-item-btn). Píldora elevada: superficie translúcida +
   barra de acento teal (inset izquierdo) + icono teal + etiqueta blanca semibold. */
.fi-sidebar-item.fi-active .fi-sidebar-item-btn {
    background-color: rgba(255, 255, 255, 0.07) !important;
    color: var(--sidebar-on-active) !important;
    box-shadow: inset 3px 0 0 0 var(--brand-coral),
                0 1px 2px rgba(0, 0, 0, 0.15) !important;
}

.fi-sidebar-item.fi-active .fi-sidebar-item-btn:hover {
    background-color: rgba(255, 255, 255, 0.10) !important;
}

.fi-sidebar-item.fi-active .fi-sidebar-item-icon {
    color: var(--brand-coral) !important;
}

.fi-sidebar-item.fi-active .fi-sidebar-item-label {
    color: var(--sidebar-on-active) !important;
    font-weight: 600 !important;
}

/* Nav item icons */
.fi-sidebar-item-icon {
    color: var(--sidebar-icon) !important;
    transition: color .15s ease !important;
}

.fi-sidebar-item-btn:hover .fi-sidebar-item-icon {
    color: var(--sidebar-text) !important;
}

/* Sidebar footer (badge de versión) — banda fija al pie, nunca recortada.
   El hook SIDEBAR_FOOTER se pinta como último hijo flex del <aside> h-screen,
   tras el <nav flex-grow>. Con flex-shrink:0 + padding propio queda como banda
   reservada al pie sin comprimirse ni solaparse con la navegación en páginas altas. */
.fi-sidebar-footer {
    flex-shrink: 0;
    padding: 0.5rem 1rem;
    line-height: 1.4;
    background-color: var(--brand-navy) !important; /* mismo navy que el sidebar (sin banda más oscura) */
    border-top: 1px solid rgba(255,255,255,0.08) !important;
}

/* Collapse toggle button — v4 renombra a fi-topbar-*-(collapse-)sidebar-btn
   (el toggle vive ahora en la topbar, no en el header del propio sidebar). */
.fi-topbar-open-sidebar-btn,
.fi-topbar-close-sidebar-btn,
.fi-topbar-open-collapse-sidebar-btn,
.fi-topbar-close-collapse-sidebar-btn {
    color: var(--sidebar-icon) !important;
}

/* ── Topbar ───────────────────────────────────────────────────────────── */

.fi-topbar,
.fi-topbar nav,
header.fi-topbar {
    background-color: var(--surface) !important;
    border-bottom: 1px solid var(--geist-border) !important;
    box-shadow: none !important;
}

/* Needed so the centered academy selector can use absolute positioning */
.fi-topbar nav {
    position: relative !important;
    height: 64px !important;
    min-height: 64px !important;
}

/* ── Content area ─────────────────────────────────────────────────────── */

/* Light background — applied to body, main wrapper and page container */
body.fi-body,
.fi-main,
.fi-page {
    background-color: var(--content-bg) !important;
}

/* Limit content width on ultrawide monitors. Coherente con MaxWidth::Full del
   provider, pero con tope (--content-max) para no estirar formularios a
   full-width y perder legibilidad. v4 elimina el div `.fi-page-container`
   intermedio: el propio `<main class="fi-main">` es ahora el contenedor. */
.fi-main {
    max-width: var(--content-max) !important;
    margin-left: auto !important;
    margin-right: auto !important;
}

/* Form inputs — min-height 40px (WCAG 2.5.5 touch target) */
.fi-input,
.fi-select-input,
.fi-fo-text-input input,
.fi-fo-select select {
    min-height: 40px !important;
    padding-top: 0 !important;
    padding-bottom: 0 !important;
}

/* Cards / panels — card flotante Sail: SIN borde, el anillo del box-shadow hace
   de borde y las capas dan la elevación (así separa del fondo, como Stripe).
   El "borde" NO es un `border`: es el anillo de 1px del box-shadow. Aplica a
   widgets del escritorio y a secciones FUERA de formulario. */
.fi-section,
.fi-card {
    border-radius: 0.5rem !important;
    border: none !important;
    box-shadow: var(--shadow-card) !important;
}

/* ── Rediseño #2 — Secciones ligeras (dentro de formulario) ──────────────── */
/* Se elimina el "efecto tarjeta": sin fondo, sin sombra, sin anillo ni radio.
   La sección queda como «título + línea separadora»; la línea es el `border-t`
   nativo del contenedor de contenido que Filament pinta cuando la sección tiene
   encabezado. El padding horizontal se anula para que título y campos queden a
   ras del borde izquierdo (como el mockup); se conserva el ritmo vertical. */
.fi-sc-form .fi-section:not(.fi-aside) {
    background: transparent !important;
    border-radius: 0 !important;
    box-shadow: none !important;
}

.fi-sc-form .fi-section:not(.fi-aside) > .fi-section-header,
.fi-sc-form .fi-section:not(.fi-aside) > .fi-section-content-ctn > .fi-section-content {
    padding-left: 0 !important;
    padding-right: 0 !important;
}

/* Header: sin padding superior; inferior a la mitad del original (py-4 = 16px →
   8px) para acercar el título a la línea separadora. */
.fi-sc-form .fi-section:not(.fi-aside) > .fi-section-header {
    padding-top: 0 !important;
    padding-bottom: 0.5rem !important;
}

/* Contenido: sin padding inferior. La separación con la siguiente sección la da
   el `margin-top: 2rem` de `.fi-section + .fi-section`; el `p-6` del blade del
   vendor sumaba 24px extra a ese hueco. */
.fi-sc-form .fi-section:not(.fi-aside) > .fi-section-content-ctn > .fi-section-content {
    padding-bottom: 0 !important;
}

/* Table container */
.fi-ta-ctn {
    border-radius: 0.5rem !important;
    border: none !important;
    box-shadow: var(--shadow-card) !important;
}

/* `overflow: hidden` recorta los paneles de los desplegables de la barra de
   cabecera (Filtros/Columnas), que se posicionan `absolute` dentro de
   `.fi-ta-ctn`; su final quedaba cortado por el contenedor. Filament de serie
   solo clipa el contenedor cuando la tabla NO tiene cabecera (`:not(
   .fi-ta-ctn-with-header)`), justo para dejar salir esos menús. Se replica ese
   matiz: el redondeo del cuerpo lo aportan `.fi-ta-content-ctn`/paginación. */
.fi-ta-ctn:not(.fi-ta-ctn-with-header) {
    overflow: hidden;
}

/* T7 — Densidad: fila de tabla a 40px. Se comprime el padding vertical de la
   celda; el alto de 40px lo gobierna el contenido (texto/avatar de ~20-24px)
   más 2×6px de padding. */
.fi-ta-row {
    height: 40px !important;
}

/* El padding vertical de la fila vive en el wrapper interno de cada columna
   (`px-3 py-4` = 16px), NO en `.fi-ta-cell` (que es `p-0`). Se comprime a 8px
   dentro del cuerpo de la tabla para la densidad Stripe; las cabeceras no se
   tocan (usan `.fi-ta-header-cell`, otro selector). */
.fi-ta-cell [class~="py-4"] {
    padding-top: 0.5rem !important;
    padding-bottom: 0.5rem !important;
}

/* Cabecera de columna → estilo Sail (uppercase pequeño, gris, con tracking).
   Filament la pinta `text-sm font-semibold text-gray-950` (título case). */
/* v4 elimina el <span class="fi-ta-header-cell-label">: el texto ahora es hijo
   directo de <th class="fi-ta-header-cell"> (o de .fi-ta-header-cell-sort-btn
   si la columna es ordenable, que hereda tipografía). Se apunta al <th>. */
.fi-ta-header-cell {
    text-transform: uppercase !important;
    font-size: 0.6875rem !important;   /* 11px */
    font-weight: 600 !important;
    letter-spacing: 0.05em !important;
    color: var(--geist-text-muted) !important;   /* Sail gray-600 */
}

/* Hover de fila sutil (Sail gray-50) */
.fi-ta-row:hover {
    background-color: var(--geist-bg-subtle) !important;
}

/* Banda de búsqueda de la tabla (`.fi-ta-header-toolbar`, `py-3` = 12px):
   se comprime a 6px para que no quede una franja vacía tan alta sobre la tabla. */
.fi-ta-header-toolbar {
    padding-top: 0.375rem !important;
    padding-bottom: 0.375rem !important;
}

/* ── Brand logo in sidebar ────────────────────────────────────────────── */

/* Logo del header: es el <img class="fi-logo"> que pinta Filament (sin wrapper
   .fi-brand-logo en esta versión). Filament fija la altura inline vía
   brandLogoHeight, por eso !important. El logo se muestra en sus colores
   originales; el icono es cuadrado (600×600), así que width:auto + object-fit
   lo mantienen a proporción. */
.fi-logo {
    height: 2.9rem !important;
    width: auto !important;
    object-fit: contain;
    padding-left: 10px !important;
}


/* Brand name text (shown when sidebar is collapsed) */
.fi-brand-name {
    color: var(--sidebar-on-active) !important;
    font-weight: 700 !important;                 /* wordmark: bold intencional */
    letter-spacing: -0.01em !important;
    line-height: var(--line-height-tight) !important;
}

/* ── Page header ──────────────────────────────────────────────────────── */

.fi-header {
    position: sticky;
    top: 82px;
    z-index: 10;
    background-color: var(--content-bg);
    /* Sangra el fondo a los lados hasta el borde del contenido (padding de
       .fi-main: px-4 / md:px-6 / lg:px-8) para que no queden márgenes por los
       que asome el borde de la sección al scrollear. El contenido no se mueve:
       el padding-inline compensa el margin-inline negativo. */
    margin-inline: -1rem;
    padding-inline: 1rem;
}

@media (min-width: 768px) {
    .fi-header { margin-inline: -1.5rem; padding-inline: 1.5rem; }
}

@media (min-width: 1024px) {
    .fi-header { margin-inline: -2rem; padding-inline: 2rem; }
}

/* Tapa que se extiende hacia arriba: cubre la banda del padding-top por la que
   se colaba el contenido al hacer scroll bajo el header sticky (mismo fix que
   el buscador del sidebar). inset-inline:0 abarca el header ya sangrado. */
.fi-header::before {
    content: "";
    position: absolute;
    inset-inline: 0;
    bottom: 100%;
    height: 2rem;
    background-color: var(--content-bg);
}

.fi-header-heading {
    font-size: var(--text-xl) !important;        /* T6: rol título de página (24px) */
    font-weight: 600 !important;                 /* semibold — escala T4 */
    letter-spacing: -0.01em !important;          /* T6: −0.02em → −0.01em */
    line-height: var(--line-height-tight) !important;
}

/* ── Breadcrumbs (estilo Sail) ────────────────────────────────────────── */
/* Filament: labels `text-sm gray-500`. Refinamos a la sensación Stripe: hover
   coral en los enlaces y el item ACTUAL (último) más marcado («estás aquí»). */
.fi-breadcrumbs-item-label:hover {
    color: var(--brand-coral) !important;
}

.fi-breadcrumbs-item:last-child .fi-breadcrumbs-item-label {
    color: var(--geist-text) !important;   /* Sail gray-900 */
    font-weight: 600 !important;
}

/* ── Tabs (combined relation manager) ────────────────────────────────── */

/* v4 unifica los dos tipos de pestaña de v3 (`.fi-tabs-tab` del listado de
   RelationManagers y `.fi-tabs-item` del formulario) en un único componente
   Schemas\Components\Tabs → siempre `.fi-tabs-item`; `.fi-tabs-tab` ya no se
   genera nunca (regla eliminada, redundante con la de abajo). Tampoco existe ya
   `.fi-tabs-item-active` (solo `.fi-active`) ni `.fi-tabs-item-icon` (el icono
   del tab se genera vía generate_icon_html() sin clase propia — solo la
   genérica `.fi-icon`). */

/* Pestañas (filtro de recurso y de formulario comparten `.fi-tabs-item`):
   la activa pasa de `bg-gray-50` (apenas visible) a un chip coral de marca.
   Versión segura para ambos contextos; el "segmented track" exacto del mockup
   tocaría también los formularios, así que queda como follow-up acotado. */
.fi-tabs-item {
    font-weight: 600 !important;
}

.fi-tabs-item.fi-active {
    /* chip teal tenue: este rgba es el FALLBACK; el color-mix real (X=12%, atado
       a --primary) está en el @supports del final del fichero. */
    background-color: rgba(14, 147, 132, 0.12) !important;
    color: var(--brand-coral) !important;
}

.fi-tabs-item.fi-active .fi-icon {
    color: var(--brand-coral) !important;
}

/* Pestañas de FORMULARIO (contained): estilo UNDERLINE (subrayado coral en la
   activa) en vez de la pastilla tipo v3. `.fi-contained` ya aporta el
   border-bottom del contenedor; la activa se marca con una lengüeta coral
   (inset box-shadow: no altera el layout ni desplaza el texto). El rail vertical
   de staff (.staff-modules-tabs) es también contained pero reasienta su pastilla
   más abajo (un subrayado inferior no encaja en un rail vertical); el filtro de
   recurso es `:not(.fi-contained)` y conserva su segmented. */
.fi-tabs.fi-contained {
    padding-bottom: 0 !important;
}
.fi-tabs.fi-contained .fi-tabs-item {
    border-radius: 0 !important;
    background-color: transparent !important;
    box-shadow: inset 0 -2px 0 0 transparent !important;
}
.fi-tabs.fi-contained .fi-tabs-item:hover,
.fi-tabs.fi-contained .fi-tabs-item:focus-visible {
    background-color: transparent !important;
    color: var(--brand-coral) !important;
}
.fi-tabs.fi-contained .fi-tabs-item.fi-active {
    background-color: transparent !important;
    color: var(--brand-coral) !important;
    box-shadow: inset 0 -2px 0 0 var(--brand-coral) !important;
}
/* El componente Tabs contained dibuja una caja (anillo box-shadow + radio) que
   con el underline ya sobra: la retiramos para que las pestañas y su contenido
   fluyan sobre la página. El border-bottom del nav (baseline del underline) vive
   en `.fi-tabs.fi-contained`, así que no se ve afectado. */
.fi-sc-tabs.fi-contained {
    box-shadow: none !important;
    border: 0 !important;
    border-radius: 0 !important;
}

/* Pestañas de página NO contained (Schemas Tabs): la barra COMBINADA de la edición
   —contenido + relation managers, p.ej. la academia con
   hasCombinedRelationManagerTabsWithContent— y los FILTROS de listado comparten la
   misma estructura `.fi-sc-tabs > .fi-tabs:not(.fi-contained)` (indistinguibles por
   CSS), así que van unificadas al mismo UNDERLINE que las Tabs de formulario. Antes
   eran un segmented (track gris + pastilla blanca); se retiró por coherencia. */
.fi-tabs:not(.fi-contained) {
    margin-left: 0 !important;                 /* anula el mx-auto (centrado) */
    margin-right: auto !important;
    background-color: transparent !important;  /* fuera track gris */
    box-shadow: none !important;               /* fuera shadow-sm + ring */
    padding: 0 !important;
    border-radius: 0 !important;
    border-bottom: 1px solid var(--geist-border) !important;
    gap: 0 !important;
}
.fi-tabs:not(.fi-contained) .fi-tabs-item {
    border-radius: 0 !important;
    background-color: transparent !important;
    box-shadow: inset 0 -2px 0 0 transparent !important;
    /* Sin margin-bottom negativo: estas barras llevan overflow-x:auto, que por
       spec convierte overflow-y en auto, y 1px sobrante dispara un scroll vertical
       espurio. El subrayado inset ya se dibuja sobre el borde del contenedor. */
}
.fi-tabs:not(.fi-contained) .fi-tabs-item:hover,
.fi-tabs:not(.fi-contained) .fi-tabs-item:focus-visible {
    background-color: transparent !important;
    color: var(--brand-coral) !important;
}
.fi-tabs:not(.fi-contained) .fi-tabs-item.fi-active {
    background-color: transparent !important;
    color: var(--brand-coral) !important;
    box-shadow: inset 0 -2px 0 0 var(--brand-coral) !important;
}

/* ── Empty state (tablas) ─────────────────────────────────────────────── */

.fi-ta-empty-state-heading {
    font-size: var(--text-md) !important;        /* T6: rol título empty-state (16px) */
    font-weight: 600 !important;                 /* semibold — escala T4 */
    letter-spacing: -0.01em !important;
    line-height: var(--line-height-tight) !important;
}

/* ── Sidebar nav spacing ──────────────────────────────────────────────── */

/* Reduce gap between navigation groups */
.fi-sidebar-nav > ul {
    gap: 0.25rem !important;
}

/* Márgenes laterales del nav: 24px→8px/lado para que el sidebar (260px) no crezca
   de más y los ítems mantengan ~244px de ancho útil */
.fi-sidebar-nav {
    padding-left: 8px !important;
    padding-right: 8px !important;
}

/* Reduce padding inside each group */
.fi-sidebar-group {
    padding-top: 0.25rem !important;
    padding-bottom: 0.25rem !important;
}

/* Spacing between items within a group — spec: 4px */
.fi-sidebar-group-items {
    gap: 4px !important;
}

/* Nav item click targets — alto de item 28px (densidad), border-radius 6px */
.fi-sidebar-item-btn {
    padding: 2px 12px !important;                /* 8→2 para comprimir a 28px con icono de 24px */
    min-height: 28px !important;                 /* alto de item 28px */
    border-radius: 6px !important;
}

/* ── Sidebar scrollbar — hidden by default, visible on hover ─────────── */

.fi-sidebar-nav {
    scrollbar-gutter: auto !important;
    scrollbar-width: thin;
    scrollbar-color: transparent transparent;
}

.fi-sidebar-nav:hover {
    scrollbar-color: rgba(255, 255, 255, 0.18) transparent;
}

/* Webkit (Chrome, Edge, Safari) */
.fi-sidebar-nav::-webkit-scrollbar {
    width: 4px;
}

.fi-sidebar-nav::-webkit-scrollbar-track {
    background: transparent;
}

.fi-sidebar-nav::-webkit-scrollbar-thumb {
    background: transparent;
    border-radius: 4px;
    transition: background 0.2s;
}

.fi-sidebar-nav:hover::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.18);
}

/* ── Notification popups ──────────────────────────────────────────────── */

.fi-no-notification:not(.fi-inline) {
    background-color: #FAF7F2 !important;
}

/* ── Badges (estado) ──────────────────────────────────────────────────── */
/* Filament ya las pinta pastel (bg-custom-50 + text-custom-600). Subimos el
   peso a semibold y, SOLO en el estado de tabla, anteponemos un punto de color
   (currentColor = el text-custom-600 de la badge) — patrón Sail/Stripe. Se acota
   a `.fi-ta-cell` para no meter puntos en las badges-contador (pestañas, campana). */
.fi-badge {
    font-weight: 600 !important;
}

.fi-ta-cell .fi-badge::before {
    content: "";
    width: 0.375rem;
    height: 0.375rem;
    border-radius: 9999px;
    background-color: currentColor;
    flex: 0 0 auto;
}

/* ── Buttons (Filament overrides) ─────────────────────────────────────── */

/* #112 — Base dimensions and typography */
.fi-btn {
    height: 36px !important;                      /* T7: 40→36 densidad; hit-area ≥44px vía ::after */
    padding: 0 16px !important;
    border-radius: 5px !important;
    font-size: 14px !important;
    font-weight: 500 !important;                 /* medium — escala T4 */
    letter-spacing: -0.01em !important;          /* T6: rol acción */
    line-height: 1 !important;
    position: relative !important;               /* T7: ancla del ::after de hit-area */
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    text-transform: none !important;
}

/* T7 — Hit-area WCAG 2.5.8 ≥44px preservada pese al alto visual de 36px
   (frontera ADR 0004). (44 - 36) / 2 = 4px de inset negativo → 44px de área
   clicable. Invisible (sin fondo/borde) y sin desplazar el layout; los clics
   siguen impactando en .fi-btn. Los botones lg (48px) ya superan 44px y su
   ::after extra es inocuo; size-sm (32px) mantiene su propio inset (-6px). */
.fi-btn::after {
    content: '';
    position: absolute;
    inset: -4px;
}

.fi-btn.fi-size-lg {
    height: 48px !important;
    padding: 0 24px !important;
    font-size: 16px !important;
}

.fi-btn.fi-size-sm {
    height: 32px !important;
    padding: 0 12px !important;
}

/* Primary — relleno teal + elevación multicapa (Sail/Stripe): anillo 1px + capas
   suaves. El anillo hace de borde, así el botón no necesita otro.
   WCAG AA (frontera ADR 0004): el relleno se fija a --primary-hover (#0B7A6E →
   blanco ~5.2:1), NO al teal base #0E9384 (~3.8:1, insuficiente para el texto
   normal de 14px del botón). */
.fi-btn.fi-color-primary:not(:disabled):not([disabled]) {
    background-color: var(--primary-hover) !important;
    box-shadow: var(--shadow-btn-primary) !important;
}

/* Hover: oscurece el teal un paso más (conserva el contraste AA y da feedback).
   color-mix sobre background-color (propiedad real): sin soporte degrada al hover
   nativo de Filament, aceptable. */
.fi-btn.fi-color-primary:not(:disabled):not([disabled]):hover {
    background-color: color-mix(in srgb, var(--primary-hover) 90%, #000) !important;
}

/* Secondary (gray) → blanco con anillo + sombra (Sail), en vez de outline.
   Afecta a «Exportar CSV», Cancelar de modales, paginación, etc.
   v4: "gray" es el color POR DEFECTO de los botones (HasDefaultGrayColor) y ya
   NO añade ninguna clase `fi-color-*` — así que se selecciona por AUSENCIA de
   cualquier `fi-color-*` explícito, en vez de una clase `fi-btn-color-gray`
   (que ya no existe). */
.fi-btn:not([class*="fi-color-"]) {
    background: #FFFFFF !important;
    border: none !important;
    color: #3C4759 !important;              /* Sail gray-700 */
    box-shadow: var(--shadow-btn-secondary) !important;
}

.fi-btn:not([class*="fi-color-"]):hover {
    background: var(--geist-bg-subtle) !important;   /* Sail gray-50 */
}

/* #112 — Destructive */
.fi-btn.fi-color-danger {
    background-color: var(--danger) !important;
}

.fi-btn.fi-color-danger:hover {
    background-color: var(--danger-hover) !important;
}

/* #113 — Focus ring WCAG AA 2.4.7 */
.fi-btn:focus-visible,
[role="button"]:focus-visible {
    outline: 2px solid var(--focus-ring) !important;
    outline-offset: 2px !important;
}

/* #113 — Touch target mínimo 44×44px para botones sm (WCAG 2.5.8) */
.fi-btn.fi-size-sm {
    position: relative !important;
}

.fi-btn.fi-size-sm::after {
    content: '';
    position: absolute;
    inset: -6px; /* (44 - 32) / 2 */
}

/* #113 — Disabled state (grises Sail, sin elevación) */
.fi-btn:disabled,
.fi-btn[disabled] {
    background-color: #E3E8EE !important;   /* Sail gray-100 */
    color: #7B8A9C !important;              /* Sail gray-400 */
    cursor: not-allowed !important;
    opacity: 0.55 !important;
    pointer-events: none !important;
    box-shadow: none !important;
}

/* #114 — Livewire loading: cursor wait, bloquear re-clic */
.fi-btn[wire\:loading] {
    cursor: wait !important;
    pointer-events: none !important;
}

/* ── Spacing between form sections (#124) ────────────────────────────── */

.fi-section + .fi-section {
    margin-top: 2rem !important; /* 32px entre bloques lógicos */
}

/* ── Button group layout (#115) ───────────────────────────────────────── */

/* Gap mínimo 12px entre botones hermanos para evitar clics accidentales.
   Primario a la derecha del secundario (dirección de avance cognitivo).
   v4 unifica `fi-ac-actions`/`fi-form-actions` en una sola clase genérica de
   grupo de acciones: `.fi-ac` (Schemas\Components\Actions). */
.fi-modal-footer-actions,
.fi-ac,
.btn-group {
    gap: 12px !important;
}

/* ── Tooltip Tippy: tema "black" (fondo negro, texto blanco) ──────────── */
/* Usado por x-tooltip en los chips de alumno del horario (condiciones
   especiales). El extra [data-theme~='black'] gana en especificidad a la
   flecha por defecto (#333), sin necesidad de !important. */
.tippy-box[data-theme~='black'] {
    background-color: #000;
    color: #fff;
}
.tippy-box[data-theme~='black'][data-placement^='top'] > .tippy-arrow::before {
    border-top-color: #000;
}
.tippy-box[data-theme~='black'][data-placement^='bottom'] > .tippy-arrow::before {
    border-bottom-color: #000;
}
.tippy-box[data-theme~='black'][data-placement^='left'] > .tippy-arrow::before {
    border-left-color: #000;
}
.tippy-box[data-theme~='black'][data-placement^='right'] > .tippy-arrow::before {
    border-right-color: #000;
}

/* ── Modal de novedades (footer sidebar, #370) ───────────────────────────── */
/* Botón v{{version}}+icono que abre un x-filament::modal con el último release
   del changelog público. El pill necesita leerse como clicable EN REPOSO, no
   solo al hover (antes era un tooltip por hover, sin affordance visible).
   .fi-sidebar-footer es SIEMPRE navy (--brand-navy-footer, ver arriba) — no
   depende de claro/oscuro — así que el overlay va en blanco, sin variante .dark. */
.isis-whatsnew-trigger {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.125rem 0.5rem;
    border-radius: 9999px;
    border: 1px solid rgba(255, 255, 255, .14);
    background-color: rgba(255, 255, 255, .06);
    color: inherit;
    transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}
.isis-whatsnew-trigger:hover,
.isis-whatsnew-trigger:focus-visible {
    background-color: rgba(255, 255, 255, .12);
    border-color: rgba(255, 255, 255, .26);
    color: #fff;
}
.isis-whatsnew-trigger svg {
    color: var(--brand-coral);
}

/* Contenido inyectado como HTML crudo (PublicChangelog::bodyToHtml): no pasa
   por el escaneo de Tailwind (solo mira resources/**), así que va con clases
   propias y CSS a mano, no utilidades. */
.isis-whatsnew-body {
    max-height: 60vh;
    overflow-y: auto;
    overflow-x: hidden;
    overflow-wrap: anywhere;
    text-align: left;
}
.isis-whatsnew-section {
    font-weight: 600;
    margin: 0.5rem 0 0.25rem;
}
.isis-whatsnew-section:first-of-type {
    margin-top: 0;
}
.isis-whatsnew-list {
    list-style: disc;
    padding-left: 1rem;
    margin: 0 0 0.5rem;
}
.isis-whatsnew-list li {
    margin-bottom: 0.25rem;
}
.isis-whatsnew-note {
    margin: 0 0 0.5rem;
    font-style: italic;
}

/* ── Wizard: botones de navegación centrados y juntos ──────────────────── */
/* El footer nativo de Filament (flex justify-between) empuja «Anterior» y
   «Siguiente/Enviar» a extremos opuestos del modal. Lo centramos para
   agruparlos; el gap-x-3 propio del footer conserva la separación entre
   ambos. Es el último hijo de .fi-sc-wizard (header, pasos, footer; v4 renombra
   Forms\Components\Wizard → Schemas\Components\Wizard, clase fi-fo-wizard →
   fi-sc-wizard). Mayor especificidad que la utilidad .justify-between, sin
   necesidad de !important. */
.fi-sc-wizard > div:last-child {
    justify-content: center;
}

/* ── Form de Academia: confinamiento, densidad y proporcionalidad (T15) ──
   Scope: `.fi-resource-academies` — la clase que Filament pone en la página de
   la Academia (create y edit record page, slug = "academies"). Así el cambio
   afecta SOLO al form de esta pantalla; otros recursos quedan intactos.
   Deliberadamente NO se toca `--content-max` (1680px, T10) ni `.fi-page-container`:
   los relation managers de la edit record page son hermanos del <form>, fuera de
   `.fi-form`, y deben conservar su ancho. */

/* 1. Confinamiento: form centrado a una columna útil de ~1000px (nunca full-bleed,
      nunca por encima de ~1200px). El <form id="form" class="fi-form"> encapsula
      solo el formulario y su botonera; las tablas de RM quedan fuera y anchas. */
.fi-resource-academies .fi-form {
    max-width: 1200px;
    margin-inline: auto;
}

/* 2. Proporcionalidad de inputs: el ancho del control sugiere la longitud del dato
      (internal_ux.md §9). Se limita la caja `.fi-input-wrp` (el recuadro con borde),
      no el input crudo, para que el borde acompañe al nuevo ancho. El input lleva
      id = statePath = `data.<campo>`; `:has()` selecciona la caja que lo contiene.
      Como grid-item con max-width, la caja se topa y queda alineada a la izquierda
      dentro de su celda, sin recolocar la etiqueta. */
.fi-resource-academies .fi-input-wrp:has(#data\.name)                    { max-width: 320px; }
.fi-resource-academies .fi-input-wrp:has(#data\.email)                   { max-width: 480px; }
.fi-resource-academies .fi-input-wrp:has(#data\.phone)                   { max-width: 160px; }
.fi-resource-academies .fi-input-wrp:has(#data\.postal_code)             { max-width: 96px; }
/* Campos numéricos compactos (internal_ux.md §9): el ancho del control sugiere la
   longitud del dato. El input se marca con la clase `num-compact` (vía
   extraInputAttributes) y se limita la caja `.fi-input-wrp` que lo contiene —no el
   input crudo— para que el borde acompañe al ancho y la etiqueta conserve el suyo.
   Con `:has()` funciona igual en el formulario de la ficha y en los modales de los
   relation managers (aulas, grupos, tarifas, bonos, series), donde el id del input
   cambia y un selector por id no llegaría. */
.fi-input-wrp:has(input.num-compact) { max-width: 90px; }
/* Variante para numéricos compactos CON sufijo (%, €): el sufijo y las flechas
   del spinner comen ancho y a 90px se corta el 2.º–3.er dígito. Un poco más de
   caja para que «100 %» se lea entero. Va después de la base para ganarle por
   orden (misma especificidad). */
.fi-input-wrp:has(input.num-compact.num-suffix) { max-width: 128px; }

/* 3a. Densidad: −~15% en el gap vertical entre campos dentro de cada fieldset
       (grid `.fi-fo-component-ctn`, gap-6 = 1.5rem → 1.25rem). Se acota a los grids
       DENTRO de un `.fi-fieldset` para no encoger la separación entre los 3 bloques
       lógicos (chunking de T14), que la fija el grid de la pestaña. El gap horizontal
       (columnas) se conserva; solo se reduce el row-gap.
       PENDIENTE-V4: `.fi-fo-component-ctn` no existe en el vendor v4 (ni el div
       wrapper del grid interno del fieldset, que ahora recibe sus clases
       `fi-grid`/`fi-grid-cols-*` directamente vía Schema::grid(), sin nombre fijo
       localizable en el código fuente). Sin verificación visual no hay sustituto
       seguro; se deja el selector v3 tal cual (inerte, no rompe nada). */
.fi-resource-academies .fi-fieldset .fi-fo-component-ctn {
    row-gap: 1.25rem !important;
}

/* 3b. Helper text (p.ej. el preaviso de cancelación): más pequeño, gris (color de
       Filament gray-500 ya lo da) y pegado a su campo (compensa el gap-y-2 del grid
       que lo separa del input).
       v4: el helper text ya no es un elemento con clase propia
       `fi-fo-field-wrp-helper-text` — se renderiza como un componente Text
       genérico (`Filament\Schemas\Components\Text`, clase `fi-sc-text`) inyectado
       como ÚLTIMO hijo de `.fi-fo-field-content-col` (ver
       forms/resources/views/components/field-wrapper.blade.php, slot
       belowContentSchema). Se acota a ese contenedor para no afectar otros usos
       de Text::make() sueltos en el formulario. */
.fi-resource-academies .fi-fo-field-content-col > .fi-sc-text {
    font-size: 0.75rem;
    line-height: 1.25;
    margin-top: -0.25rem;
}

/* Badge «Beta»: etiqueta autónoma reutilizable para marcar funciones en pruebas.
   bg azul claro literal a propósito (una utilidad Tailwind como bg-blue-50 se
   purgaría al inyectarse por HTML fuera del scan de Tailwind); el texto sigue al
   token de estado --info (blurple ADR 0020). */
.badge-beta {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.125rem 0.5rem;
    border-radius: 9999px;
    font-size: 0.6875rem;
    font-weight: 600;
    line-height: 1;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    background-color: #EBF5FF;
    color: var(--info);
}

/* ADR 0019 — Homogeneización de tablas (T45): disparadores de filtros y de
   «alternar columnas» y sus popovers, presentados igual en toda la app. Solo
   selectores `.fi-*` en CSS crudo (una utilidad Tailwind inyectada por HTML se
   purgaría). No se publican blades del vendor: el registro global fija icono y
   color (embudo / columnas, gris); aquí solo se afina el disparador y el panel. */
.fi-ta-header-toolbar .fi-icon-btn.fi-dropdown-trigger,
.fi-ta-header-toolbar .fi-dropdown-trigger > .fi-icon-btn {
    color: #6B7280; /* gray-500: acento neutro homogéneo del disparador vertical */
}

/* Panel de los popovers de filtros/columnas: misma elevación y radio que el
   resto de superficies del tema (evita popovers planos y de esquinas dispares). */
.fi-dropdown-panel {
    border-radius: 0.5rem;
    box-shadow: 0 4px 12px -2px rgba(17, 24, 39, 0.10), 0 2px 6px -2px rgba(17, 24, 39, 0.06);
}

/* Menú de usuario (#476): el panel por defecto de Filament se capa en 14rem y
   trunca el nombre/email/tenant de la cabecera. Se ensancha SOLO ese panel —lo
   identifica la cabecera data-user-menu-identity, ya que el panel se teletransporta
   al body y no puede targetearse por .fi-user-menu—. El !important vence al
   `!max-w-[14rem]` utilitario; el min() lo mantiene dentro del viewport en móvil. */
.fi-dropdown-panel:has(> [data-user-menu-identity]) {
    max-width: min(20rem, calc(100vw - 2rem)) !important;
}

/* ── color-mix real (ADR 0020) donde el navegador lo soporte ────────────────
   Los valores rgba de arriba (glow del botón primario y chip de pestaña activa)
   son el FALLBACK. Aquí se sustituyen por color-mix atado a --primary para que
   sigan a la marca sin fijar el hex. Se usa @supports —y no redeclaración— porque
   color-mix embebido dentro de var() no degrada a la declaración rgba previa. */
@supports (background-color: color-mix(in srgb, red 30%, transparent)) {
    :root {
        --glow-primary: color-mix(in srgb, var(--primary) 30%, transparent);
    }
    .fi-tabs-item.fi-active {
        background-color: color-mix(in srgb, var(--primary) 12%, transparent) !important;
    }
}

/* ── Popover de perfil de alumno (hover en los listados) ──────────────────────
   CSS crudo (no utilidades Tailwind) porque la tarjeta se inyecta en <body>
   fuera del árbol de Filament: las utilidades se purgarían. Estética inspirada
   en una ficha de persona (cabecera + filas etiqueta/valor + secciones con
   pills), con la paleta de marca (teal/navy). El popover lo posiciona y muestra
   filament/hooks/student-popover.blade.php (JS delegado, sin Tippy). */
.isis-spop-trigger {
    text-decoration: underline dotted;
    text-decoration-color: #cbd5e1;
    text-underline-offset: 2px;
    cursor: help;
}

/* Distintivo de vínculo familiar en activo, junto al nombre en el listado. */
.isis-sibling-badge {
    display: inline-flex;
    align-items: center;
    margin-inline-start: 4px;
    vertical-align: middle;
    color: var(--brand-coral, #f56565);
}

.isis-sibling-badge__icon {
    width: 15px;
    height: 15px;
}

.isis-spop-pop {
    position: fixed;
    z-index: 9999;
    width: 300px;
    max-width: calc(100vw - 16px);
    background: #ffffff;
    color: var(--navy);
    border: 1px solid #e8ecf1;
    border-radius: 14px;
    box-shadow: 0 12px 32px -8px rgba(27, 42, 65, .22), 0 4px 10px -6px rgba(27, 42, 65, .16);
    padding: 14px 16px;
    font-size: 13px;
    line-height: 1.45;
    animation: isis-spop-in .12s ease-out;
}

@keyframes isis-spop-in {
    from { opacity: 0; transform: translateY(4px); }
    to   { opacity: 1; transform: translateY(0); }
}

.isis-spop-pop__loading {
    color: #94a3b8;
    padding: 2px 0;
}

.isis-spop__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 10px;
}

.isis-spop__name {
    font-weight: 700;
    font-size: 15px;
    color: var(--navy);
}

.isis-spop__status {
    flex-shrink: 0;
    border-radius: 9999px;
    padding: 2px 9px;
    font-size: 11px;
    font-weight: 600;
    line-height: 1.4;
    background: #eef1f5;
    color: #475569;
}
.isis-spop__status--success { background: color-mix(in srgb, var(--success) 14%, #fff); color: var(--success); }
.isis-spop__status--warning { background: color-mix(in srgb, var(--warning) 18%, #fff); color: #B45309; }
.isis-spop__status--danger  { background: color-mix(in srgb, var(--danger) 12%, #fff);  color: var(--danger); }
.isis-spop__status--info    { background: color-mix(in srgb, var(--info) 14%, #fff);    color: var(--info); }
.isis-spop__status--primary { background: var(--primary-soft); color: var(--primary); }

.isis-spop__facts {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: 5px 14px;
    margin: 0;
}
.isis-spop__facts dt {
    font-size: 10px;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: #94a3b8;
    align-self: center;
}
.isis-spop__facts dd {
    margin: 0;
    color: #334155;
    word-break: break-word;
}
.isis-spop__na {
    color: #94a3b8;
    font-style: italic;
}
.dark .isis-spop__na { color: #6b7280; }

.isis-spop__seasons {
    margin-top: 12px;
    padding-top: 12px;
    border-top: 1px solid #eef1f5;
    display: flex;
    flex-direction: column;
    gap: 11px;
}

.isis-spop__season-title {
    font-size: 12px;
    font-weight: 700;
    color: var(--primary);
    margin-bottom: 5px;
}

.isis-spop__chips {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
}
.isis-spop__chip {
    background: #f1f5f9;
    color: #334155;
    border-radius: 9999px;
    padding: 2px 10px;
    font-size: 11px;
    font-weight: 500;
    line-height: 1.5;
}
/* Chips coloreados (condiciones especiales): bg translúcido del color + texto del color. */
.isis-spop__chip--gray    { background: #eef1f5; color: #475569; }
.isis-spop__chip--info    { background: color-mix(in srgb, var(--info) 15%, transparent);    color: var(--info); }
.isis-spop__chip--success { background: color-mix(in srgb, var(--success) 15%, transparent); color: var(--success); }
.isis-spop__chip--warning { background: color-mix(in srgb, var(--warning) 20%, transparent); color: #B45309; }
.isis-spop__chip--danger  { background: color-mix(in srgb, var(--danger) 14%, transparent);  color: var(--danger); }
.isis-spop__chip--primary { background: var(--primary-soft); color: var(--primary); }

/* Condiciones especiales — sección con título de acento. */
.isis-spop__conds {
    margin-top: 12px;
    padding-top: 12px;
    border-top: 1px solid #eef1f5;
}
.isis-spop__conds-title {
    font-size: 12px;
    font-weight: 700;
    color: var(--primary);
    margin-bottom: 6px;
}

/* Asistencia global — valor en color según umbral (80/60). */
.isis-spop__att { font-weight: 700; }
.isis-spop__att--success { color: var(--success); }
.isis-spop__att--warning { color: #B45309; }
.isis-spop__att--danger  { color: var(--danger); }

.isis-spop__tariff {
    margin-top: 6px;
    font-size: 12px;
    color: #64748b;
}

.isis-spop__empty {
    margin-top: 12px;
    padding-top: 12px;
    border-top: 1px solid #eef1f5;
    color: #94a3b8;
    font-style: italic;
}

/* Tema oscuro (Filament conmuta .dark en <html>). */
.dark .isis-spop-pop {
    background: #1f2937;
    color: #e5e7eb;
    border-color: #374151;
    box-shadow: 0 12px 32px -8px rgba(0, 0, 0, .5), 0 4px 10px -6px rgba(0, 0, 0, .4);
}
.dark .isis-spop__name { color: #f9fafb; }
.dark .isis-spop__facts dd { color: #d1d5db; }
.dark .isis-spop__facts dt { color: #9ca3af; }
.dark .isis-spop__seasons,
.dark .isis-spop__empty,
.dark .isis-spop__conds { border-top-color: #374151; }
.dark .isis-spop__chip { background: rgba(255, 255, 255, .08); color: #e5e7eb; }
.dark .isis-spop__chip--gray { background: rgba(255, 255, 255, .08); color: #e5e7eb; }
.dark .isis-spop__chip--warning,
.dark .isis-spop__att--warning { color: #fbbf24; }
.dark .isis-spop__chip--info { color: #93a4f4; }
.dark .isis-spop__status { background: rgba(255, 255, 255, .1); color: #d1d5db; }
.dark .isis-spop__tariff { color: #9ca3af; }
.dark .isis-spop-trigger { text-decoration-color: #4b5563; }

/* ── Cuerpo de anuncio (WYSIWYG) ────────────────────────────────────────────
   El editor genera HTML (listas, enlaces, negritas). El preflight de Tailwind
   quita viñetas/estilo, así que se restauran mínimamente para que el anuncio se
   vea con formato en el portal del alumno (student-portal.blade). */
.announcement-body ul { list-style: disc; padding-left: 1.25rem; margin: .25rem 0; }
.announcement-body ol { list-style: decimal; padding-left: 1.25rem; margin: .25rem 0; }
.announcement-body li { margin: .125rem 0; }
.announcement-body p { margin: .25rem 0; }
.announcement-body a { color: #e05b49; text-decoration: underline; }
.announcement-body strong { font-weight: 600; }
.announcement-body em { font-style: italic; }

/* #304 — pestañas Filament scroll horizontal en móvil ─────────────────────────
   En móvil las barras de pestañas (`.fi-tabs`) recortaban la última pestaña sin
   affordance de scroll. Afecta a los dos contextos:
     · navegación de página (segmented `:not(.fi-contained)`, p.ej. /app/mail-logs)
     · `Tabs` de formulario (`.fi-contained`, p.ej. /app/academies/create)
   Se fuerza el scroll horizontal sin wrap y se añade pista de sombra en los
   bordes (técnica de "scrolling shadows" de Lea Verou: dos sombras fijas
   `scroll` + dos "tapas" del color del track con `background-attachment:local`
   que ocultan la sombra al alcanzar cada extremo — así la pista aparece/oculta
   según la posición de scroll). Todo dentro del @media móvil: escritorio intacto. */
@media (max-width: 640px) {
    .fi-tabs {
        flex-wrap: nowrap !important;
        overflow-x: auto !important;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;                 /* Firefox: barra oculta */

        /* Sombras de scroll. --tab-fade-bg = color de fondo del contenedor,
           ajustado por contexto (blanco en form contained; gris en el segmented). */
        --tab-fade-bg: #FFFFFF;
        background-image:
            linear-gradient(to right, var(--tab-fade-bg) 40%, transparent),
            linear-gradient(to left,  var(--tab-fade-bg) 40%, transparent),
            radial-gradient(farthest-side at   0 50%, rgba(26, 31, 54, 0.20), transparent),
            radial-gradient(farthest-side at 100% 50%, rgba(26, 31, 54, 0.20), transparent);
        background-position: left center, right center, left center, right center;
        background-repeat: no-repeat;
        background-size: 24px 100%, 24px 100%, 12px 100%, 12px 100%;
        background-attachment: local, local, scroll, scroll;
    }

    /* Barra de scroll oculta (Webkit) — el desplazamiento se guía por la sombra. */
    .fi-tabs::-webkit-scrollbar {
        height: 0;
        display: none;
    }

    /* Los items conservan su ancho (no se comprimen) y se desplazan en fila.
       v4: solo `.fi-tabs-item` existe (ver nota en la sección Tabs de arriba). */
    .fi-tabs .fi-tabs-item {
        flex: 0 0 auto !important;
        white-space: nowrap !important;
    }

}

/* #307 — pestañas de dominio nuclear desplazables en ESCRITORIO ───────────────
   El dominio nuclear (Grupos, Tarifas, Profesores…) vive como fila de pestañas
   (RelationManagers) dentro de `Editar Academia`. Con 10+ pestañas la fila
   desborda; se mantiene en una sola línea desplazable (sin envolver) para que
   ningún módulo quede recortado. Acotado a la fila de RMs
   (`.fi-resource-relation-managers .fi-tabs`); no toca los `Tabs` de formulario
   (`.fi-contained`) ni el segmented de listados.

   El desbordamiento se resuelve con el scroll nativo: sin la affordance de
   sombra/tapa en los extremos que se retiró por preferencia de UX. */
.fi-resource-relation-managers .fi-tabs {
    flex-wrap: nowrap !important;
    overflow-x: auto !important;
    -webkit-overflow-scrolling: touch;
}

.fi-resource-relation-managers .fi-tabs .fi-tabs-item {
    flex: 0 0 auto !important;
    white-space: nowrap !important;
}
/* #305 — matar rubber-band iOS/PWA ──────────────────────────────────────────
   Elimina el rebote elástico (overscroll / rubber-band) al arrastrar en iOS
   Safari y en la PWA instalada (/app), para que no se despegue la página ni
   asome el fondo blanco por arriba/abajo. El scroll de los paneles Filament
   ocurre sobre <body> (topbar sticky), así que el objetivo del fix es el propio
   documento, no un `#app` (no existe ese id aquí).

   Nivel 1 (aplicado): `overscroll-behavior: none` en el documento y en los
   contenedores de scroll de Filament. Es no-destructivo (no reposiciona nada),
   así que NO rompe el topbar sticky, modales, slide-overs ni popovers/Tippy, y
   funciona en iOS Safari 16+ y en modo standalone. En los scrollers internos
   (sidebar-nav) evita además el "scroll chaining" que también dispara el rebote.

   Nivel 2 (position:fixed en <body> + reasignar el scroll a un wrapper interno)
   NO se aplica: exige conocer/rewirear el contenedor de scroll real y romper el
   `top:82px` de .fi-header, con riesgo para el topbar/modales; requeriría un
   wrapper propio vía render hook (fuera de la whitelist de esta unidad) y
   verificación en runtime. Ver reporte.

   `env(safe-area-inset-*)`: irrelevante en Nivel 1 (no hay reposicionamiento) y,
   de hecho, el panel /app no declara `viewport-fit=cover`, por lo que los insets
   son 0 hoy; sería una consideración del Nivel 2. */
html,
body,
body.fi-body,
.fi-main-ctn,
.fi-main {
    overscroll-behavior: none;
}

/* Scrollers internos: `contain` corta el encadenamiento al documento (otra vía
   del rebote) sin matar su propio overscroll local. */
.fi-sidebar-nav {
    overscroll-behavior: contain;
}

/* ── Scroll vertical fantasma en TODAS las páginas ──────────────────────────
   Filament añade al final del <body> los wrappers de los modales de acción
   (page/tabla) como `<div class="fi-modal inline-block">`, vacíos y de altura 0.
   Al ser `inline-block` participan en un contexto inline y generan una CAJA DE
   LÍNEA cuyo alto es el `line-height` del <body> (~24px), que se suma a la
   altura del documento: aparece una barra de scroll vertical permanente aunque
   el contenido quepa de sobra en el viewport.
   `display:block` los saca del contexto inline (mata la caja de línea) sin
   ocultarlos, así que la apertura del modal (panel `position:fixed`) no se ve
   afectada. Acotado a hijos directos de <body>: nunca toca los triggers de
   modal inline dentro del contenido. */
body > .fi-modal {
    display: block;
}

/* ── Grid de 12 columnas (Mi portal: logros / progreso) ─────────────────────
   El panel /app sirve el CSS PRECOMPILADO que Filament publica desde SUS
   PROPIOS blades (vendor/filament/*), no un build Tailwind sobre las vistas
   de esta app: una utilidad que Filament no usa internamente (grid-cols-N
   salvo 1 y 7, cualquier col-span-*) no existe en ese bundle — no es purga ni
   caché, la regla nunca se generó. Se declaran a mano las que consume
   student-portal.blade.php; ampliar aquí si otra vista necesita más valores. */
.grid-cols-12 { grid-template-columns: repeat(12, minmax(0, 1fr)); }
.col-span-4   { grid-column: span 4 / span 4; }
.col-span-6   { grid-column: span 6 / span 6; }

@media (min-width: 640px) {
    .sm\:col-span-3 { grid-column: span 3 / span 3; }
}

/* ── Rail de secciones de notas (escritorio, pestaña Notas) ─────────────────
   `w-56`/`md:w-56` no existen en el bundle precompilado (Filament no usa esa
   anchura en sus propios blades): mismo motivo que el grid de 12 columnas de
   arriba. Pero aquí SÍ hay conflicto de cascada, no solo ausencia: el mismo
   elemento también lleva `w-full` (para el apilado móvil), y `.w-full{width:
   100%}` SÍ existe en filament/filament/app.css — que además se carga
   DESPUÉS de isiscampus.css en el <head>, así que con igual especificidad
   gana por orden de aparición y machaca el ancho fijo. `!important` (patrón
   ya usado en todo este fichero para pisar el CSS precompilado de Filament). */
@media (min-width: 768px) {
    .md\:w-56 { width: 14rem !important; }

    /* Columna 2 (lista de notas) del panel /app tras el layout de 3 columnas
       (issue #367, unidad 2): mismo motivo que `.md\:w-56` arriba — `w-72`/
       `md:w-72` no existen en el bundle precompilado. */
    .md\:w-72 { width: 18rem !important; }
}

/* ── Sección activa del rail de notas: mismo acento que el item activo del
   sidebar principal (`.fi-sidebar-item-button.fi-active`, arriba) ──────────
   El resaltado previo (`bg-primary-50 dark:bg-primary-500/10` +
   `text-primary-700 dark:text-primary-400`) era casi invisible porque esas
   utilidades ni siquiera existen en el bundle precompilado (grep en
   public/build/assets/app-*.css: 0 resultados para bg-primary-* ni text-primary-*
   — Filament no las usa en sus propios blades). Reutiliza las mismas 2
   variables CSS que el sidebar para que el acento de marca sea consistente. */
.note-section-row.is-active {
    background-color: var(--brand-coral) !important;
    color: var(--sidebar-on-active) !important;
}

/* Contraste de los iconos (drag handle, renombrar, eliminar) sobre el fondo
   sólido: los heroicons usan fill/stroke="currentColor", así que fijar
   `color` en el propio <svg> basta para recolorearlos, sin depender de si el
   icono venía de una utilidad Tailwind (drag handle) o de las variables CSS
   inline del componente `x-filament::icon-button` (renombrar/eliminar). */
.note-section-row.is-active svg {
    color: var(--sidebar-on-active) !important;
}

@media (min-width: 1024px) {
    .lg\:col-span-2 { grid-column: span 2 / span 2; }
}

/* ── Slot seleccionado del picker de horarios de alumnos (schedule-group-picker.blade.php,
   creación y edición) ─────────────────────────────────────────────────────────────────
   El estado seleccionado usa `ring-2 ring-primary-500 bg-primary-50 dark:bg-primary-900/30`,
   pero esas utilidades `primary-*` no existen en el bundle precompilado de Filament (mismo
   motivo que `.note-section-row.is-active` arriba). El anillo cae al azul por defecto de
   Tailwind (`--tw-ring-color: rgba(59,130,246,.5)` del preflight), muy sutil. Se sustituye
   por el acento de marca con opacidad alta para que resalte. */
.ring-primary-500 {
    --tw-ring-color: var(--brand-coral) !important;
    --tw-ring-opacity: 1 !important;
}

/* ─────────────────────────────────────────────────────────────────────────
   TEMA OSCURO — sobrescritura de tokens de color
   Filament conmuta la clase `dark` en <html>; `html.dark` gana a `:root` por
   especificidad (independiente del orden en el fichero). Solo se redefinen
   tokens de COLOR/superficie/sombra; espaciado, radios, tipografía y la paleta
   de marca (teal/navy/estados) se heredan de :root SIN cambios.
   El sidebar sigue navy y sus tokens de texto ya son claros → intactos.
   NO tocar app/Support/BrandPalette.php: describe la paleta de marca, que aquí
   no cambia.
   ───────────────────────────────────────────────────────────────────────── */
html.dark {
    /* Superficies */
    --content-bg:    #0B1220;   /* fondo de página (slate muy oscuro) */
    --surface:       #131C2E;   /* topbar, cards, popovers */
    --topbar-border: #263247;

    /* Neutrales / superficies (espejo oscuro de la escala Sail) */
    --geist-bg:            #131C2E;
    --geist-bg-subtle:     #1B2536;   /* hover de fila, fondos sutiles */
    --geist-border:        #263247;
    --geist-border-strong: #35435C;
    --geist-text:          #E6EBF2;   /* texto principal */
    --geist-text-muted:    #A6B2C4;   /* secundario (~7:1 sobre #0B1220) */
    --geist-text-faint:    #75839A;   /* terciario */

    /* Tinte suave de primary para fondos (equivalente oscuro de #E7F5F3) */
    --primary-soft: rgba(14, 147, 132, 0.16);

    /* Sombras: en oscuro el "anillo" se hace con blanco translúcido + caída negra */
    --shadow-card: 0 0 0 1px rgba(255, 255, 255, 0.06),
                   0 2px 4px -1px rgba(0, 0, 0, 0.40),
                   0 4px 12px -2px rgba(0, 0, 0, 0.50);
    --shadow-btn-secondary: 0 0 0 1px rgba(255, 255, 255, 0.10),
                            0 1px 2px rgba(0, 0, 0, 0.40);
}

/* ─────────────────────────────────────────────────────────────────────────
   TEMA OSCURO — remanentes con color claro hardcodeado
   Reglas .dark que no se resuelven vía tokens (colores literales en las reglas
   base). El prefijo `.dark` sube la especificidad → ganan a su contraparte
   clara y al CSS de Filament sin depender del orden de carga.
   ───────────────────────────────────────────────────────────────────────── */

/* Pestañas de página NO contained en oscuro: underline coral (antes segmented).
   El fondo transparente ya lo pone la regla base; aquí solo el color activo. */
.dark .fi-tabs:not(.fi-contained) .fi-tabs-item.fi-active {
    background-color: transparent !important;
    color: #5EEAD4 !important;
    box-shadow: inset 0 -2px 0 0 #5EEAD4 !important;
}

/* Popup de notificaciones (base crema #FAF7F2 → superficie oscura) */
.dark .fi-no-notification:not(.fi-inline) {
    background-color: var(--surface) !important;
}

/* Botón secundario/gris (base blanco #FFFFFF → superficie oscura). v4: gray es
   el color por defecto sin clase `fi-color-*` (ver nota arriba). */
.dark .fi-btn:not([class*="fi-color-"]) {
    background: var(--surface) !important;
    color: var(--geist-text) !important;
}

/* Botón deshabilitado (base grises claros → grises oscuros) */
.dark .fi-btn:disabled,
.dark .fi-btn[disabled] {
    background-color: #2A3346 !important;
    color: #5A6B82 !important;
}

/* Badge «Beta» (base azul claro #EBF5FF → azul oscuro translúcido) */
.dark .badge-beta {
    background-color: rgba(84, 104, 214, 0.18);
    color: #93A4F4;
}

/* Sombras de scroll de pestañas en móvil: la "tapa" toma el color del track
   oscuro y la pista de sombra pasa a blanco translúcido para verse sobre fondo
   oscuro. Solo redeclara background-image y --tab-fade-bg; el resto de
   background-* de la regla base sigue vigente. */
@media (max-width: 640px) {
    .dark .fi-tabs {
        --tab-fade-bg: #131C2E;
        background-image:
            linear-gradient(to right, var(--tab-fade-bg) 40%, transparent),
            linear-gradient(to left,  var(--tab-fade-bg) 40%, transparent),
            radial-gradient(farthest-side at   0 50%, rgba(255, 255, 255, 0.16), transparent),
            radial-gradient(farthest-side at 100% 50%, rgba(255, 255, 255, 0.16), transparent);
    }
}

/* Ayuda contextual (hintIcon "?"): tenue en reposo, plena al interactuar. El
   icono señala que hay ayuda sin competir con el contenido; al pasar el ratón
   por el campo o enfocarlo, se resalta con un fundido. Global a todos los
   hintIcon del panel. En táctil (sin hover) queda siempre visible aunque
   tenue: la ayuda nunca es inalcanzable.
   v4: el hintIcon ya no tiene clase propia `fi-fo-field-wrp-hint-icon` — se
   renderiza como un componente Icon genérico (`Filament\Schemas\Components\Icon`,
   clase `fi-sc-icon`) inyectado tras la etiqueta, dentro de
   `.fi-fo-field-label-col` (ver forms/resources/views/components/field-wrapper.
   blade.php, slot afterLabelSchema). Se acota a ese contenedor porque es
   compartido con posibles hintActions, no exclusivo del hintIcon. */
.fi-fo-field-label-col .fi-sc-icon {
    opacity: 0.3;
    transition: opacity 0.15s ease-in-out;
}

.fi-fo-field:hover .fi-fo-field-label-col .fi-sc-icon,
.fi-fo-field:focus-within .fi-fo-field-label-col .fi-sc-icon {
    opacity: 1;
}

/* Campos de fecha (DatePicker): ancho estático. El contenido de una fecha
   nunca supera ~155px, así que se evita que el campo se estire a toda la fila
   de su contenedor. La clase se aplica con extraFieldWrapperAttributes en cada
   DatePicker; se define aquí como CSS crudo porque el panel usa el CSS
   precompilado de Filament y su Tailwind no escanea los PHP de app, de modo que
   la utilidad Tailwind arbitraria w-[155px] se purgaría y no llegaría a existir.
   v4 renombra el wrapper de campo `fi-fo-field-wrp` → `fi-fo-field` (ver
   forms/resources/views/components/field-wrapper.blade.php). */
.fi-fo-field.w-\[155px\] {
    width: 155px;
}

/* Campos de fecha-hora (DateTimePicker): ancho estático algo mayor que el del
   DatePicker por incluir la hora (formato d/m/Y H:i). Mismo motivo para el CSS
   crudo que en la regla de arriba: la utilidad Tailwind arbitraria w-[185px] se
   purgaría (el panel usa el CSS precompilado de Filament, que no escanea los PHP
   de app). */
.fi-fo-field.w-\[185px\] {
    width: 185px;
}

/* Campos de hora (TimePicker): ancho estático ceñido al contenido (HH:MM).
   Mismo motivo de CSS crudo que las reglas de arriba (el panel usa el CSS
   precompilado de Filament y su Tailwind no escanea los PHP de app). */
.fi-fo-field.w-\[130px\] {
    width: 130px;
}

/* Fila en línea de fecha + horas (modal de evento del calendario): sustituye la
   rejilla de Filament por un flex ceñido para que fecha/comienza/acaba queden
   juntas, cada una con su ancho fijo. La clase la pone extraAttributes en el div
   EXTERIOR del Grid (forms/grid.blade); los campos viven en el `.grid` interior
   (component-container), así que el override apunta a ese hijo directo. El
   !important gana al `display:grid` que Filament aplica ahí. Raw CSS por el
   mismo motivo que las utilidades w-[...] (Tailwind no escanea los PHP de app y
   se purgarían). */
.isis-inline-row > * {
    display: flex !important;
    flex-wrap: wrap;
    gap: 1rem;
    align-items: flex-start;
}

/* Perfiles de empleado: pestañas de módulos en rail vertical (Filament v3 no
   trae ->vertical(); se emula con flex). Rail de módulos a la izquierda y el
   panel del módulo activo (toggle + sub-permisos) a su lado.
   v4 traslada Tabs de Forms a Schemas: fi-fo-tabs → fi-sc-tabs (contenedor) y
   fi-fo-tabs-tab → fi-sc-tabs-tab (panel activo); fi-tabs (nav) y fi-tabs-item
   no cambian. */
.staff-modules-tabs.fi-sc-tabs {
    flex-direction: row;
    align-items: flex-start;
    gap: 1.5rem;
}
.staff-modules-tabs > .fi-tabs {
    flex-direction: column;
    flex-shrink: 0;
    width: 16rem;
    max-width: 16rem;
    overflow-x: visible;
    align-self: stretch;
}
.staff-modules-tabs > .fi-tabs .fi-tabs-item {
    width: 100%;
    justify-content: flex-start;
    /* El rail vertical conserva la pastilla (anula el underline de formulario:
       un subrayado inferior no encaja en tabs verticales). */
    border-radius: var(--radius-lg, 0.5rem) !important;
    box-shadow: none !important;
}
.staff-modules-tabs > .fi-tabs .fi-tabs-item.fi-active {
    background-color: rgba(14, 147, 132, 0.12) !important;
    color: var(--brand-coral) !important;
    box-shadow: none !important;
}
.staff-modules-tabs > .fi-sc-tabs-tab.fi-active {
    flex: 1 1 auto;
    min-width: 0;
    margin-top: 0;
}
@media (max-width: 640px) {
    .staff-modules-tabs.fi-sc-tabs {
        flex-direction: column;
    }
    .staff-modules-tabs > .fi-tabs {
        width: 100%;
        max-width: 100%;
        flex-direction: row;
        overflow-x: auto;
    }
}

/* ── Barra de aforo segmentada ───────────────────────────────────────
   Un rectángulo por plaza: gris = libre; verde/ámbar/rojo según ocupación
   (ámbar ≥80%, rojo ≥100%). Definida aquí (CSS raw) porque el panel Filament
   solo carga su subconjunto de utilidades + este fichero, no el app.css de
   Vite; así no dependemos del build ni de estilos inline. */
.seat-bar {
    display: flex;
    flex: 1;
    flex-wrap: wrap;
    gap: 2px;
    padding: 3px 0;
}
.seat {
    flex: 1 1 0;
    min-width: 4px;
    height: 12px;
    border-radius: 2px;
    background-color: rgba(156, 163, 175, 0.35); /* plaza libre */
}
.seat--ok   { background-color: #22c55e; }
.seat--warn { background-color: #f59e0b; }
.seat--full { background-color: #ef4444; }

/* Separador entre la barra de aforo y el listado de alumnos. */
.seat-divider {
    margin-top: 6px;
    margin-bottom: 12px;
    border: 0;
    border-top: 1px solid #e5e7eb; /* gray-200 */
}
.dark .seat-divider {
    border-top-color: #4b5563; /* gray-600 */
}

/* Celda de día en que la academia está cerrada (según su temporada): fondo
   azulado muy suave para distinguirla de un día abierto sin sesiones (gris). */
.day-closed {
    background-color: rgba(59, 130, 246, 0.11);
}
.dark .day-closed {
    background-color: rgba(96, 165, 250, 0.16);
}

/* Inputs de hora: un <input type="time"> solo muestra HH:MM (+ el icono de
   reloj nativo); nunca necesita el ancho completo del contenedor. Regla
   global (ambos paneles): 75px basta y evita campos desproporcionados
   (p. ej. apertura/cierre del horario comercial). El selector de atributo
   (0,1,1) gana a las utilidades de ancho de Tailwind como .w-40 (0,1,0). */
input[type="time"] {
    width: 75px;
}


/* ── Cabecera de estado del alumno (#490·U2) ──────────────────────────────────
   Franja fija sobre las pestañas de EditStudent. Mismo lenguaje visual y
   tokens que el popover de perfil (.isis-spop*, ver arriba): superficie,
   bordes y texto de --geist-*/--navy/--surface, semántica de color reservada
   a lo que exige atención (deuda, renovación). */
.isis-shdr {
    border: 1px solid var(--geist-border);
    border-radius: var(--radius-lg);
    background: var(--surface);
    overflow: hidden;
    margin-bottom: var(--space-5);
}

.isis-shdr__top {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    padding: var(--space-4) var(--space-5);
    border-bottom: 1px solid var(--geist-border);
    background: var(--geist-bg-subtle);
}

.isis-shdr__avatar {
    width: 48px;
    height: 48px;
    border-radius: 9999px;
    flex-shrink: 0;
    display: grid;
    place-items: center;
    background: var(--navy);
    color: #fff;
    font-weight: 700;
    font-size: 17px;
    letter-spacing: .02em;
}

.isis-shdr__idblock {
    min-width: 0;
    flex: 1;
}

.isis-shdr__name {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-wrap: wrap;
}
.isis-shdr__name h2 {
    margin: 0;
    font-size: 17px;
    font-weight: 700;
    color: var(--geist-text);
    letter-spacing: -.01em;
}

.isis-shdr__meta {
    margin-top: 3px;
    font-size: var(--text-sm);
    color: var(--geist-text-muted);
    display: flex;
    gap: var(--space-2);
    align-items: center;
    flex-wrap: wrap;
}
.isis-shdr__sep { color: var(--geist-border-strong); }

.isis-shdr__status {
    font-size: 11px;
    font-weight: 700;
    padding: 2px 9px;
    border-radius: 9999px;
    letter-spacing: .01em;
    white-space: nowrap;
    background: #eef1f5;
    color: #475569;
}
.isis-shdr__status--success { background: color-mix(in srgb, var(--success) 14%, #fff); color: var(--success); }
.isis-shdr__status--warning { background: color-mix(in srgb, var(--warning) 18%, #fff); color: #B45309; }
.isis-shdr__status--danger  { background: color-mix(in srgb, var(--danger) 12%, #fff);  color: var(--danger); }
.isis-shdr__status--info    { background: color-mix(in srgb, var(--info) 14%, #fff);    color: var(--info); }
.isis-shdr__status--primary { background: var(--primary-soft); color: var(--primary); }
.isis-shdr__status--gray    { background: #eef1f5; color: #475569; }
.isis-shdr__status--neutral { background: #eef1f5; color: #475569; }

.isis-shdr__facts {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 1px;
    background: var(--geist-border);
}

.isis-shdr__fact {
    background: var(--surface);
    padding: var(--space-3) var(--space-4);
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-width: 0;
    position: relative;
}
.isis-shdr__fact-k {
    font-size: 10px;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--geist-text-faint);
    font-weight: 600;
}
.isis-shdr__fact-v {
    font-size: var(--text-base);
    font-weight: 500;                            /* medium: los valores no van en negrita */
    color: var(--geist-text);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.isis-shdr__fact-v small {
    font-weight: 500;
    color: var(--geist-text-muted);
    font-size: 12px;
}

.isis-shdr__tick {
    display: inline-block;
    width: 15px;
    height: 15px;
    color: var(--success);
    vertical-align: -2px;
    margin-right: 4px;
}

.isis-shdr__strong { font-weight: 650; }         /* negrita reservada al dato clave */
.isis-shdr__strong--success { color: var(--success); }
.isis-shdr__strong--warning { color: #B45309; }
.isis-shdr__strong--danger  { color: var(--danger); }

.isis-shdr__fact--flag::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 3px;
}
.isis-shdr__fact--flag-danger::before  { background: var(--danger); }
.isis-shdr__fact--flag-warning::before { background: var(--warning); }

@media (max-width: 780px) {
    .isis-shdr__facts { grid-template-columns: repeat(2, 1fr); }
}

/* Tema oscuro (Filament conmuta .dark en <html>). */
.dark .isis-shdr__status,
.dark .isis-shdr__status--neutral,
.dark .isis-shdr__status--gray { background: rgba(255, 255, 255, .08); color: #e5e7eb; }

/* ─────────────────────────────────────────────────────────────────────────
   Página: informe de asistencia por grupo (#618)
   Blade previo: `<style>` inline con badges de estado; movido aquí porque
   este Blade no está en el `content` de Tailwind del panel.
   ───────────────────────────────────────────────────────────────────────── */
.attendance-report__sticky-col {
    position: sticky;
    left: 0;
    z-index: 5;
    min-width: 180px;
}
.att-cell-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.5rem;
    padding: 0.125rem 0.4rem;
    border-radius: 0.375rem;
    font-size: 0.75rem;
    font-weight: 600;
    line-height: 1rem;
    cursor: pointer;
}
.att-pending   { background: #f3f4f6; color: #4b5563; }
.att-present   { background: #dcfce7; color: #15803d; }
.att-late      { background: #fef9c3; color: #a16207; }
.att-absent    { background: #fee2e2; color: #b91c1c; }
.att-justified { background: #dbeafe; color: #1d4ed8; }
.dark .att-pending   { background: #37415133; color: #9ca3af; }
.dark .att-present   { background: #14532d55; color: #86efac; }
.dark .att-late      { background: #78350f55; color: #fcd34d; }
.dark .att-absent    { background: #7f1d1d55; color: #fca5a5; }
.dark .att-justified { background: #1e3a8a55; color: #93c5fd; }
#attendance-menu { min-width: 11rem; }

/* ─────────────────────────────────────────────────────────────────────────
   Página: mensajería (#618)
   Blade previo: `<style>` inline con fondo/burbujas de chat; movido aquí por
   el mismo motivo (Blade fuera del `content` de Tailwind del panel).
   ───────────────────────────────────────────────────────────────────────── */
.chat-bg {
    background-color: #e5ddd5;
    background-image: url("data:image/svg+xml,%3Csvg width='80' height='80' viewBox='0 0 80 80' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='%23c8b89a' fill-opacity='0.18' fill-rule='evenodd'%3E%3Cpath d='M0 0h40v40H0V0zm40 40h40v40H40V40zm0-40h2l-2 2V0zm0 4l4-4h2l-6 6V4zm0 4l8-8h2L40 10V8zm0 4L52 0h2L40 14v-2zm0 4L56 0h2L40 18v-2zm0 4L60 0h2L40 22v-2zm0 4L64 0h2L40 26v-2zm0 4L68 0h2L40 30v-2zm0 4L72 0h2L40 34v-2zm0 4L76 0h2L40 38v-2zm0 4L80 0v2L42 40h-2zm4 0L80 4v2L46 40h-2zm4 0L80 8v2L50 40h-2zm4 0L80 12v2L54 40h-2zm4 0L80 16v2L58 40h-2zm4 0L80 20v2L62 40h-2zm4 0L80 24v2L66 40h-2zm4 0L80 28v2L70 40h-2zm4 0L80 32v2L74 40h-2zm4 0L80 36v2L78 40h-2zm4 0L80 40v-2h-2z'/%3E%3C/g%3E%3C/svg%3E");
}
.dark .chat-bg {
    background-color: #0b141a;
    background-image: none;
}
/* Burbujas: colores explícitos para no depender del JIT de Tailwind
   (este Blade no está en el `content` del build de Filament). */
.chat-bubble-mine,
.chat-bubble-other       { border-radius: 0.75rem; }
.chat-bubble-mine        { background-color: #dcf8c6; border-top-right-radius: 0.25rem; }
.dark .chat-bubble-mine  { background-color: #005c4b; }
.chat-bubble-other       { background-color: #ffffff; border-top-left-radius: 0.25rem; }
.dark .chat-bubble-other { background-color: #202c33; }

/* Layout responsive de la mensajería: en escritorio (md+, >=768px) split de
   dos paneles a la vez; en móvil (<768px) UN solo panel (lista XOR detalle),
   conmutado por [data-has-selection] según haya conversación seleccionada.
   Se resuelve con media queries + atributo (no con variantes `md:`) porque
   este Blade no está en el `content` del build de Filament y el JIT las
   purgaría. */
/* isolation: encierra los z-index internos (p.ej. el z-20 de la lista) en un
   contexto de apilamiento propio para que no se filtren al layout y tapen el
   flyout de los ítems del sidebar colapsado de Filament. */
.chat-shell  { flex-direction: column; isolation: isolate; }
.chat-list   { width: 100%; min-height: 0; }
@media (min-width: 768px) {
    .chat-shell { flex-direction: row; }
    .chat-list  { width: 18rem; flex-shrink: 0; }
}
@media (max-width: 767px) {
    .chat-list { flex: 1 1 auto; }
    .chat-shell[data-has-selection="1"] .chat-list   { display: none; }
    .chat-shell[data-has-selection="0"] .chat-detail { display: none; }
}
/* Botón "volver" a la lista: solo en móvil, dentro del detalle. */
.chat-back { display: none; }
@media (max-width: 767px) { .chat-back { display: inline-flex; } }

/* ─────────────────────────────────────────────────────────────────────────
   Página: horario del profesor (#618)
   Iconos de marca de sesión (lista pasada / incidencia): color literal fijo
   en ambos temas (el original no distinguía claro/oscuro).
   ───────────────────────────────────────────────────────────────────────── */
.schedule-mark--taken    { color: #16a34a; }
.schedule-mark--incident { color: #f97316; }

/* ─────────────────────────────────────────────────────────────────────────
   Informes tabulares (#617): chrome compartido de las Pages de informe
   (rentabilidad, facturación mensual, asistencia). Las filas/columnas se
   siguen computando en PHP (matriz/agregado); esto solo unifica el envoltorio
   visual que antes era Tailwind inline duplicado. Bordes vía
   --geist-border-strong para coincidir con el override global de border-gray-*
   (idéntico en claro/oscuro). Alineación/colores de dato siguen en el blade.
   ───────────────────────────────────────────────────────────────────────── */
.isis-report-filters { display: flex; flex-wrap: wrap; align-items: flex-end; gap: .75rem; margin-bottom: .5rem; }
.isis-report-label   { display: block; margin-bottom: .25rem; font-size: .75rem; line-height: 1rem; font-weight: 500; text-transform: uppercase; letter-spacing: .05em; color: #6b7280; }
.dark .isis-report-label { color: #9ca3af; }

.isis-report-select { display: block; padding: .375rem .75rem; font-size: .875rem; line-height: 1.25rem; border: 1px solid var(--geist-border-strong); border-radius: .375rem; background-color: #fff; color: #111827; box-shadow: 0 1px 2px 0 rgba(0, 0, 0, .05); }
.isis-report-select:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 1px var(--primary); }
.dark .isis-report-select { background-color: #374151; color: #fff; }

.isis-report-empty { padding: 2rem; text-align: center; color: #6b7280; background-color: #fff; border: 1px solid var(--geist-border-strong); border-radius: .375rem; }
.dark .isis-report-empty { background-color: #1f2937; }

.isis-report-tablewrap { overflow-x: auto; background-color: #fff; border: 1px solid var(--geist-border-strong); border-radius: .375rem; box-shadow: 0 1px 2px 0 rgba(0, 0, 0, .05); }
.dark .isis-report-tablewrap { background-color: #1f2937; }

.isis-report-table { width: 100%; font-size: .875rem; border-collapse: collapse; }
.isis-report-table thead tr,
.isis-report-table tfoot tr { background-color: #f9fafb; }
.dark .isis-report-table thead tr,
.dark .isis-report-table tfoot tr { background-color: #111827; }
.isis-report-table thead tr { border-bottom: 1px solid var(--geist-border-strong); }
.isis-report-table tfoot tr { border-top: 2px solid var(--geist-border-strong); }
.isis-report-table th { padding: .75rem 1rem; font-weight: 600; color: #4b5563; }
.dark .isis-report-table th { color: #d1d5db; }
.isis-report-table td { padding: .75rem 1rem; }
.isis-report-table tbody tr + tr { border-top: 1px solid var(--geist-border-strong); }
.isis-report-table tbody tr:hover { background-color: #f9fafb; }
.dark .isis-report-table tbody tr:hover { background-color: #273244; }
