/* ================================================================
   Adinath Jainology — Custom Stylesheet
   Color Palette: Purple #7B2380 | Green #8DC63F | Yellow #F5A723 | Coral #E8845A
   ================================================================ */

:root {
    --ajt-purple:  #7B2380;
    --ajt-purple2: #5C1A60;
    --ajt-purple3: #9B3DA0;
    --ajt-green:   #8DC63F;
    --ajt-yellow:  #F5A723;
    --ajt-coral:   #E8845A;
    --ajt-dark:    #2D1B35;
    --ajt-light:   #F8F3FA;
    --ajt-white:   #FFFFFF;
    --sidebar-w:   260px;
    --sidebar-w-collapsed: 78px;
    --topbar-h:    60px;
}

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* Belt-and-braces guarantee against the page itself ever scrolling sideways. Every specific
   overflow cause (a table, a form field, a stat card, ...) gets fixed where it actually is
   as those turn up — this is a backstop underneath all of that: if anything, anywhere, still
   ends up a pixel or two wider than the viewport, it's clipped here instead of dragging the
   whole page into a horizontal scroll. Vertical scrolling is untouched. */
html { overflow-x: hidden; }

/* Set on <html> by custom.js (syncSidebarScrollLock) for as long as the mobile drawer is
   open, so the page behind the overlay can't be scrolled by a touch/wheel gesture while
   it's up — only the drawer's own nav list (which keeps its own overflow-y) should move.
   overflow-y:hidden on both html and body since either can be the actual scrolling
   element depending on the browser. */
html.ajt-scroll-lock, html.ajt-scroll-lock body { overflow-y: hidden; }

body {
    font-family: 'Segoe UI', -apple-system, BlinkMacSystemFont, Roboto, sans-serif;
    background: #F0EBF4;
    color: #333;
    font-size: 14px;
    line-height: 1.6;
    overflow-x: hidden;
}

/* ── Scrollbar ── */
::-webkit-scrollbar { width: 5px; height: 5px; }
::-webkit-scrollbar-track { background: #f1f1f1; }
::-webkit-scrollbar-thumb { background: var(--ajt-purple); border-radius: 3px; }

/* ================================================================
   SIDEBAR
   ================================================================ */

.ajt-sidebar {
    position: fixed;
    top: 0; left: 0;
    width: var(--sidebar-w);
    height: 100vh;
    background: linear-gradient(180deg, var(--ajt-dark) 0%, var(--ajt-purple2) 40%, #3A1545 100%);
    z-index: 1000;
    display: flex;
    flex-direction: column;
    overflow-y: auto;
    transition: width 0.3s ease, transform 0.3s ease;
}


.ajt-sidebar .brand {
    padding: 20px 20px 16px;
    border-bottom: 1px solid rgba(255,255,255,0.1);
    display: flex;
    align-items: center;
    gap: 12px;
    transition: padding 0.3s ease;
}
.ajt-sidebar .brand img { width: 46px; height: 46px; object-fit: contain; border-radius: 10px; background: rgba(255,255,255,0.15); padding: 4px; flex-shrink: 0; }
.ajt-sidebar .brand-text { white-space: nowrap; }
.ajt-sidebar .brand-text .app-name { color: #fff; font-size: 14px; font-weight: 700; line-height: 1.2; }
.ajt-sidebar .brand-text .app-sub  { color: rgba(255,255,255,0.55); font-size: 11px; }
.sidebar-close-btn {
    display: none;
    margin-left: auto;
    flex-shrink: 0;
    width: 32px;
    height: 32px;
    border: none;
    border-radius: 50%;
    background: rgba(255,255,255,0.1);
    color: #fff;
    font-size: 15px;
    align-items: center;
    justify-content: center;
    transition: background 0.2s, transform 0.15s;
}
.sidebar-close-btn:hover { background: rgba(255,255,255,0.2); }
.sidebar-close-btn:active { transform: scale(0.9); }

.ajt-sidebar .nav-section-label {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 1.5px;
    text-transform: uppercase;
    color: rgba(255,255,255,0.35);
    padding: 20px 20px 6px;
}

.ajt-sidebar .nav-link {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 20px;
    color: rgba(255,255,255,0.72);
    text-decoration: none;
    font-size: 13.5px;
    font-weight: 500;
    border-radius: 0;
    transition: background 0.2s, color 0.2s;
    position: relative;
}
.ajt-sidebar .nav-link .nav-icon { font-size: 16px; width: 20px; text-align: center; flex-shrink: 0; }
.ajt-sidebar .nav-link:hover,
.ajt-sidebar .nav-link.active {
    background: rgba(255,255,255,0.12);
    color: #fff;
}
.ajt-sidebar .nav-link.active::before {
    content: '';
    position: absolute;
    left: 0; top: 50%;
    transform: translateY(-50%);
    width: 3px; height: 28px;
    background: var(--ajt-green);
    border-radius: 0 2px 2px 0;
}
.ajt-sidebar .nav-link .badge-pill {
    margin-left: auto;
    background: var(--ajt-coral);
    color: #fff;
    font-size: 10px;
    padding: 2px 7px;
    border-radius: 20px;
    font-weight: 600;
}

/* Sidebar submenu */
.ajt-sidebar .has-submenu > .nav-link { cursor: pointer; }
.ajt-sidebar .has-submenu > .nav-link::after {
    content: '\f107';
    font-family: 'Font Awesome 6 Free';
    font-weight: 900;
    margin-left: auto;
    font-size: 11px;
    transition: transform 0.25s;
}
.ajt-sidebar .has-submenu.open > .nav-link::after { transform: rotate(180deg); }
.ajt-sidebar .submenu { display: none; }
.ajt-sidebar .has-submenu.open .submenu { display: block; }
.ajt-sidebar .submenu .nav-link { padding-left: 52px; font-size: 13px; }

/* Top-level section toggles (Main, Academic, Examination, ...) — every menu section is
   collapsed to just this row by default; clicking it opens/closes its own submenu only. */
.ajt-sidebar > .has-submenu > .nav-link {
    font-size: 11.5px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: rgba(255,255,255,0.55);
}
.ajt-sidebar > .has-submenu > .nav-link:hover { color: #fff; background: rgba(255,255,255,0.08); }
.ajt-sidebar > .has-submenu > .nav-link .nav-icon { font-size: 13px; opacity: 0.7; }
.ajt-sidebar > .has-submenu.open > .nav-link { color: #fff; }
.ajt-sidebar > .has-submenu.open > .nav-link .nav-icon { opacity: 1; }

/* ================================================================
   MAIN CONTENT WRAPPER
   ================================================================ */

.ajt-main {
    margin-left: var(--sidebar-w);
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    transition: margin-left 0.3s ease;
}

/* ================================================================
   SIDEBAR — COLLAPSED (icon rail, desktop only)
   ================================================================ */
@media (min-width: 992px) {
    html.sidebar-collapsed .ajt-sidebar { width: var(--sidebar-w-collapsed); }
    html.sidebar-collapsed .ajt-main    { margin-left: var(--sidebar-w-collapsed); }

    html.sidebar-collapsed .ajt-sidebar .brand { padding: 20px 0; justify-content: center; }
    html.sidebar-collapsed .ajt-sidebar .brand-text,
    html.sidebar-collapsed .ajt-sidebar .nav-section-label,
    html.sidebar-collapsed .ajt-sidebar .badge-pill,
    html.sidebar-collapsed .ajt-sidebar .has-submenu > .nav-link::after {
        display: none;
    }

    html.sidebar-collapsed .ajt-sidebar .sidebar-user-mini { justify-content: center; padding: 16px 0; }
    html.sidebar-collapsed .ajt-sidebar .sidebar-user-mini-text { display: none; }

    html.sidebar-collapsed .ajt-sidebar .nav-link {
        justify-content: center;
        padding: 12px 0;
        gap: 0;
        font-size: 0;               /* collapses the text node next to the icon */
    }
    html.sidebar-collapsed .ajt-sidebar .nav-link .nav-icon {
        font-size: 17px;
        width: auto;
    }
    html.sidebar-collapsed .ajt-sidebar .submenu { display: none !important; }

    html.sidebar-collapsed .ajt-sidebar .sidebar-footer { padding: 20px 10px; }
    html.sidebar-collapsed .ajt-sidebar .sidebar-footer .btn-ajt-outline {
        font-size: 0;
        padding: 10px 0;
    }
    html.sidebar-collapsed .ajt-sidebar .sidebar-footer .btn-ajt-outline i { font-size: 15px; }
}

/* ── Topbar ── */
.ajt-topbar {
    height: var(--topbar-h);
    background: #fff;
    border-bottom: 1px solid #EDE7F2;
    display: flex;
    align-items: center;
    padding: 0 24px;
    position: sticky;
    top: 0;
    z-index: 500;
    gap: 12px;
    box-shadow: 0 1px 4px rgba(123,35,128,0.06);
}
/* Mobile-only brand mark — hidden on desktop, where the sidebar's own logo is always
   visible. On mobile the sidebar is off-screen until opened, and with .page-title also
   hidden there (see the media query below), the topbar had no branding in it at all
   before this — just the hamburger button and the user avatar. */
.ajt-topbar .topbar-logo { display: none; width: 30px; height: 30px; object-fit: contain; flex-shrink: 0; }
.ajt-topbar .sidebar-toggle {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    flex-shrink: 0;
    background: var(--ajt-light);
    border: none;
    border-radius: 10px;
    cursor: pointer;
    transition: background 0.2s ease, transform 0.15s ease;
}
.ajt-topbar .sidebar-toggle:hover  { background: #EEE0F2; }
.ajt-topbar .sidebar-toggle:active { transform: scale(0.92); }
.ajt-topbar .sidebar-toggle .collapse-icon {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
}
.ajt-topbar .sidebar-toggle .bar {
    display: block;
    width: 18px;
    height: 2px;
    border-radius: 2px;
    background: var(--ajt-purple);
    transition: width 0.2s ease;
}
.ajt-topbar .sidebar-toggle .bar:nth-child(2) { width: 13px; }
.ajt-topbar .sidebar-toggle:hover .bar:nth-child(2) { width: 18px; }
.ajt-topbar .sidebar-toggle .icon-arrow { font-size: 16px; color: var(--ajt-purple); }
.ajt-topbar .page-title { font-size: 16px; font-weight: 700; color: var(--ajt-dark); flex: 1; }
.ajt-topbar .topbar-actions { display: flex; align-items: center; gap: 16px; }
.ajt-topbar .user-badge {
    display: flex; align-items: center; gap: 8px;
    background: var(--ajt-light);
    border-radius: 24px;
    padding: 4px 14px 4px 6px;
    cursor: pointer;
}
.ajt-topbar .user-badge img { width: 30px; height: 30px; border-radius: 50%; object-fit: cover; border: 2px solid var(--ajt-purple); }
.ajt-topbar .user-badge .user-name { font-size: 13px; font-weight: 600; color: var(--ajt-dark); }
.ajt-topbar .user-badge .user-role { font-size: 10px; color: #888; }

.ajt-topbar .btn-notif {
    position: relative;
    background: none;
    border: none;
    font-size: 20px;
    color: #888;
    cursor: pointer;
    transition: color 0.2s;
}
.ajt-topbar .btn-notif:hover { color: var(--ajt-purple); }
.ajt-topbar .btn-notif .count {
    position: absolute;
    top: -4px; right: -4px;
    background: var(--ajt-coral);
    color: #fff;
    font-size: 9px;
    width: 16px; height: 16px;
    border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    font-weight: 700;
}

/* ── Page Content ── */
.ajt-content {
    padding: 24px;
    flex: 1;
}

/* Prevent Bootstrap columns and their controls from overflowing into neighbors. */
.row { min-width: 0; }
.row > [class*="col-"] {
    min-width: 0;
    max-width: 100%;
    overflow: hidden;
}

/* ================================================================
   DASHBOARD STAT CARDS
   ================================================================ */

.stat-card {
    background: #fff;
    border-radius: 14px;
    padding: 22px 20px;
    display: flex;
    align-items: center;
    gap: 16px;
    box-shadow: 0 2px 12px rgba(123,35,128,0.07);
    border: 1px solid rgba(123,35,128,0.06);
    transition: transform 0.2s, box-shadow 0.2s;
    text-decoration: none;
    color: inherit;
    height: 100%;
}
.stat-card:hover { transform: translateY(-2px); box-shadow: 0 6px 20px rgba(123,35,128,0.12); }
.stat-card .stat-icon {
    width: 52px; height: 52px;
    border-radius: 12px;
    display: flex; align-items: center; justify-content: center;
    font-size: 22px;
    flex-shrink: 0;
}
.stat-card .stat-icon.purple { background: rgba(123,35,128,0.12); color: var(--ajt-purple); }
.stat-card .stat-icon.green  { background: rgba(141,198,63,0.15);  color: #5a8a00; }
.stat-card .stat-icon.yellow { background: rgba(245,167,35,0.15);  color: #b07200; }
.stat-card .stat-icon.coral  { background: rgba(232,132,90,0.15);  color: #c05a30; }
.stat-card .stat-icon.blue   { background: rgba(70,130,180,0.15);  color: #3070b0; }

.stat-card .stat-info .stat-value { font-size: 26px; font-weight: 800; color: var(--ajt-dark); line-height: 1; }
.stat-card .stat-info .stat-label { font-size: 12px; color: #888; margin-top: 4px; font-weight: 500; }
.stat-card .stat-info .stat-change { font-size: 11px; margin-top: 4px; }
.stat-card .stat-info .stat-change.up   { color: #5a8a00; }
.stat-card .stat-info .stat-change.down { color: var(--ajt-coral); }

/* ================================================================
   CARDS / PANELS
   ================================================================ */

.ajt-card {
    background: #fff;
    border-radius: 14px;
    box-shadow: 0 2px 12px rgba(123,35,128,0.07);
    border: 1px solid rgba(123,35,128,0.06);
    overflow: hidden;
}
.ajt-card .ajt-card-header {
    padding: 16px 20px;
    border-bottom: 1px solid #F0E8F5;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}
.ajt-card .ajt-card-header .card-title {
    font-size: 15px;
    font-weight: 700;
    color: var(--ajt-dark);
    display: flex;
    align-items: center;
    gap: 8px;
}
.ajt-card .ajt-card-header .card-title i { color: var(--ajt-purple); }
.ajt-card .ajt-card-body { padding: 20px; }

/* ================================================================
   MODALS
   ================================================================ */

.modal-header {
    background: linear-gradient(135deg, var(--ajt-purple) 0%, var(--ajt-purple2) 100%);
    color: #fff;
    border-bottom: none;
}
.modal-header .modal-title { color: #fff; }
.modal-header small,
.modal-header .text-muted { color: rgba(255,255,255,0.75) !important; }
.modal-header .btn-close {
    filter: invert(1) grayscale(100%) brightness(200%);
}

/* ================================================================
   WHATSAPP TEMPLATE DETAILS (admin/whatsapp_templates "View Details" modal)
   Same fields as before, presented as cards instead of a plain text grid.
   ================================================================ */

/* Two-column layout: WhatsApp bubble preview pinned on the left, all the labeled
   detail groups scrolling on the right. */
.wat-grid { display: grid; grid-template-columns: 290px 1fr; gap: 24px; align-items: start; }
@media (max-width: 700px) { .wat-grid { grid-template-columns: 1fr; } }
.wat-preview-col { position: sticky; top: 0; }

/* WhatsApp bubble preview. Rendered with the real WhatsApp bubble colors on purpose —
   it's simulating the actual WhatsApp app, so borrowing the site's purple palette here
   would look wrong, not "on brand". */
.wat-phone-wrap { display: flex; }
.wat-phone {
    width: 270px;
    background: #0b141a;
    border-radius: 20px;
    padding: 10px;
    box-shadow: 0 10px 28px rgba(45,27,53,0.22);
}
.wat-phone-bar {
    display: flex;
    align-items: center;
    gap: 8px;
    color: rgba(255,255,255,0.9);
    font-size: 11.5px;
    font-weight: 600;
    padding: 8px 10px 12px;
}
.wat-phone-bar i { background: rgba(255,255,255,0.12); width: 22px; height: 22px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 10px; }
.wat-phone-screen {
    background: #111b21;
    border-radius: 14px;
    padding: 16px 10px;
    min-height: 160px;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
}
.wat-bubble {
    background: #d9fdd3;
    border-radius: 10px 10px 10px 2px;
    padding: 10px 12px;
    box-shadow: 0 1px 2px rgba(0,0,0,0.15);
}
.wat-bubble-header { font-weight: 700; font-size: 13px; color: #111b21; margin-bottom: 4px; }
.wat-bubble-body { white-space: pre-wrap; line-height: 1.45; font-size: 13px; color: #111b21; word-break: break-word; }
.wat-bubble-footer { color: #667781; font-size: 11px; margin-top: 6px; }
.wat-bubble-time { text-align: right; font-size: 10px; color: #667781; margin-top: 5px; }
.wat-bubble-time i { color: #53bdeb; font-size: 12px; }
.wat-bubble-empty { color: #667781; font-size: 12px; font-style: italic; text-align: center; padding: 20px 0; }
.wat-var-highlight { background: rgba(123,35,128,0.14); color: var(--ajt-purple2); padding: 0 4px; border-radius: 4px; font-weight: 700; }

.wat-group { margin-bottom: 22px; }
.wat-group:last-child { margin-bottom: 0; }
.wat-group-title {
    font-size: 11.5px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: var(--ajt-purple);
    margin-bottom: 10px;
    padding-bottom: 7px;
    border-bottom: 1px solid #F0E8F5;
    display: flex;
    align-items: center;
    gap: 7px;
}
.wat-group-title i { font-size: 11px; }

.wat-field-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
    gap: 12px;
}
.wat-field {
    background: #fff;
    border: 1px solid #F0E8F5;
    border-radius: 12px;
    padding: 12px 14px;
    transition: border-color 0.15s, box-shadow 0.15s;
}
.wat-field:hover { border-color: rgba(123,35,128,0.25); box-shadow: 0 4px 14px rgba(123,35,128,0.08); }
.wat-field-top { display: flex; align-items: center; gap: 8px; margin-bottom: 7px; }
.wat-field-icon {
    width: 24px; height: 24px;
    border-radius: 7px;
    background: var(--ajt-light);
    color: var(--ajt-purple);
    display: flex; align-items: center; justify-content: center;
    font-size: 10.5px;
    flex-shrink: 0;
}
.wat-field-label { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px; color: #aaa; }
.wat-field-value { font-size: 13.5px; font-weight: 600; color: var(--ajt-dark); word-break: break-word; padding-left: 32px; }
.wat-field-value.empty { color: #c4bcc9; font-weight: 500; }

.wat-content-block {
    background: var(--ajt-light);
    border: 1px solid #EDE0F3;
    border-radius: 12px;
    padding: 14px 16px;
    margin-top: 12px;
}
.wat-content-label {
    font-size: 10.5px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--ajt-purple);
    margin-bottom: 7px;
    display: flex;
    align-items: center;
    gap: 6px;
}
.wat-content-text { font-size: 13px; color: #333; white-space: pre-wrap; line-height: 1.55; }
.wat-content-text.empty { color: #c4bcc9; font-style: italic; }

/* ================================================================
   PAGINATION
   ================================================================ */

.pagination {
    gap: 6px;
    flex-wrap: wrap;
}
.pagination .page-item .page-link {
    border: none;
    border-radius: 8px !important;
    min-width: 36px;
    height: 36px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0 12px;
    font-size: 13px;
    font-weight: 600;
    color: var(--ajt-purple2);
    background: var(--ajt-light);
    box-shadow: none;
    transition: all 0.15s ease;
}
.pagination .page-item .page-link:hover {
    background: rgba(123,35,128,0.14);
    color: var(--ajt-purple2);
}
.pagination .page-item .page-link:focus {
    box-shadow: 0 0 0 3px rgba(123,35,128,0.15);
}
.pagination .page-item.active .page-link {
    background: linear-gradient(135deg, var(--ajt-purple) 0%, var(--ajt-purple2) 100%);
    color: #fff;
    box-shadow: 0 4px 12px rgba(123,35,128,0.3);
}
.pagination .page-item.disabled .page-link {
    background: transparent;
    color: #c9c2ce;
}
.pagination .page-item:first-child .page-link,
.pagination .page-item:last-child .page-link {
    background: #fff;
    border: 1.5px solid rgba(123,35,128,0.18);
    color: var(--ajt-purple);
    font-size: 13px;
    border-radius: 50% !important;
    width: 36px;
    min-width: 36px;
    padding: 0;
}
.pagination .page-item:first-child .page-link:hover,
.pagination .page-item:last-child .page-link:hover {
    background: var(--ajt-purple);
    border-color: var(--ajt-purple);
    color: #fff;
}
.pagination .page-item:first-child.disabled .page-link,
.pagination .page-item:last-child.disabled .page-link {
    background: var(--ajt-light);
    border-color: transparent;
    color: #c9c2ce;
}

/* DataTables pagination (Bootstrap 5 integration reuses .pagination/.page-link) */
.dataTables_wrapper .dataTables_paginate {
    margin-top: 6px;
}
.dataTables_wrapper .dataTables_info {
    color: #888;
    font-size: 13px;
    padding-top: 8px;
}
/* Top toolbar ("Show N entries" + Search box) — the dom config renders both in one
   flex row (d-flex justify-content-between) with no wrap, which overflows the table's
   width on a phone instead of shrinking. Global: every .ajt-datatable gets this. */
@media (max-width: 480px) {
    .dataTables_wrapper > .d-flex.justify-content-between {
        flex-wrap: wrap;
        gap: 8px;
    }
    .dataTables_wrapper .dataTables_length,
    .dataTables_wrapper .dataTables_filter {
        width: 100%;
    }
    /* The search icon/text + input sit inside the .dataTables_filter <label> itself, not
       directly in the outer div — the flex row (and the input's flex:1 growth inside it)
       has to be set there for the input to actually fill the available width. */
    .dataTables_wrapper .dataTables_filter label {
        display: flex;
        align-items: center;
        width: 100%;
        gap: 6px;
    }
    .dataTables_wrapper .dataTables_filter input {
        flex: 1;
        min-width: 0;
        max-width: none;
    }
}

/* ================================================================
   DROPDOWNS
   ================================================================ */

.dropdown-menu {
    border: none;
    border-radius: 14px;
    box-shadow: 0 12px 36px rgba(45,27,53,0.18);
    padding: 8px;
    margin-top: 10px !important;
    min-width: 200px;
    /* animation: ajt-dropdown-in 0.16s ease; */
}
@keyframes ajt-dropdown-in {
    from { opacity: 0; transform: translateY(-6px); }
    to   { opacity: 1; transform: translateY(0); }
}
.dropdown-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 12px;
    border-radius: 9px;
    font-size: 13.5px;
    font-weight: 500;
    color: var(--ajt-dark);
    transition: background 0.15s, color 0.15s;
}
.dropdown-item i { width: 16px; text-align: center; color: var(--ajt-purple); font-size: 14px; flex-shrink: 0; }
.dropdown-item:hover, .dropdown-item:focus {
    background: var(--ajt-light);
    color: var(--ajt-purple2);
}
.dropdown-item:active {
    background: var(--ajt-purple);
    color: #fff;
}
.dropdown-item:active i { color: #fff; }
.dropdown-item.text-danger i { color: var(--ajt-coral); }
.dropdown-item.text-danger:hover { background: rgba(232,132,90,0.12); color: #c65a2e; }
.dropdown-divider { margin: 6px 4px; border-color: #f0eaf5; }

/* ================================================================
   BUTTONS
   ================================================================ */

.btn-ajt-primary {
    background: linear-gradient(135deg, var(--ajt-purple) 0%, var(--ajt-purple2) 100%);
    color: #fff;
    border: none;
    padding: 9px 20px;
    border-radius: 8px;
    font-size: 13.5px;
    font-weight: 600;
    cursor: pointer;
    transition: opacity 0.2s, transform 0.15s;
    display: inline-flex;
    align-items: center;
    gap: 7px;
    text-decoration: none;
}
.btn-ajt-primary:hover { opacity: 0.88; transform: translateY(-1px); color: #fff; }
.btn-ajt-primary:active { transform: translateY(0); }

.btn-ajt-success {
    background: linear-gradient(135deg, #5a8a00, var(--ajt-green));
    color: #fff;
    border: none;
    padding: 9px 20px;
    border-radius: 8px;
    font-size: 13.5px;
    font-weight: 600;
    cursor: pointer;
    transition: opacity 0.2s;
    display: inline-flex;
    align-items: center;
    gap: 7px;
    text-decoration: none;
}
.btn-ajt-success:hover { opacity: 0.88; color: #fff; }

.btn-ajt-outline {
    background: transparent;
    color: var(--ajt-purple);
    border: 1.5px solid var(--ajt-purple);
    padding: 8px 18px;
    border-radius: 8px;
    font-size: 13.5px;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.2s, color 0.2s;
    display: inline-flex;
    align-items: center;
    gap: 7px;
    text-decoration: none;
}
.btn-ajt-outline:hover { background: var(--ajt-purple); color: #fff; }

.btn-icon {
    width: 32px; height: 32px;
    border-radius: 7px;
    border: none;
    display: inline-flex; align-items: center; justify-content: center;
    font-size: 13px;
    cursor: pointer;
    transition: opacity 0.2s;
    text-decoration: none;
}
.btn-icon:hover { opacity: 0.8; }
.btn-icon.edit   { background: rgba(245,167,35,0.15); color: #b07200; }
.btn-icon.view   { background: rgba(123,35,128,0.12); color: var(--ajt-purple); }
.btn-icon.delete { background: rgba(232,132,90,0.15); color: #c05a30; }
.btn-icon.approve{ background: rgba(141,198,63,0.15); color: #5a8a00; }
.btn-icon.pay    { background: rgba(32,178,170,0.15); color: #167e77; }
.btn-icon.certificate  { background: rgba(47,111,237,0.15); color: #1d4ed8; }
.btn-icon.consolidated { background: rgba(180,146,63,0.18); color: #8a6d1f; }

/* ================================================================
   FORMS
   ================================================================ */

.form-label-ajt { font-size: 12.5px; font-weight: 600; color: #5a5a7a; margin-bottom: 5px; display: block; }
.form-control-ajt {
    width: 100%;
    min-width: 0;
    padding: 10px 14px;
    border: 1.5px solid #E0D5EC;
    border-radius: 8px;
    font-size: 14px;
    color: var(--ajt-dark);
    background: #FDFAFF;
    outline: none;
    transition: border-color 0.2s, box-shadow 0.2s;
}
select.form-control-ajt {
    display: block;
    box-sizing: border-box;
    width: 100%;
    min-width: 0;
    max-width: 100%;
    flex: 0 1 auto;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.form-control-ajt:focus {
    border-color: var(--ajt-purple);
    background: #fff;
    box-shadow: 0 0 0 3px rgba(123,35,128,0.1);
}
.form-control-ajt.is-invalid { border-color: var(--ajt-coral); }

/* Select2 — match the .form-control-ajt look so every dropdown stays on-brand */
.select2-container--bootstrap-5 .select2-selection {
    border: 1.5px solid #E0D5EC !important;
    border-radius: 8px !important;
    background-color: #FDFAFF !important; /* background-color, not background — the shorthand wipes the theme's chevron background-image */
    min-height: 41px !important;
}
.select2-container--bootstrap-5.select2-container--focus .select2-selection,
.select2-container--bootstrap-5.select2-container--open .select2-selection {
    border-color: var(--ajt-purple) !important;
    background-color: #fff !important;
    box-shadow: 0 0 0 3px rgba(123,35,128,0.1) !important;
}
.select2-container--bootstrap-5 .select2-selection--single {
    display: flex;
    align-items: center;
}
.select2-container--bootstrap-5 .select2-selection--single .select2-selection__rendered {
    padding: 0 !important;
    line-height: normal !important;
    font-size: 14px;
    color: var(--ajt-dark);
}
/* Stays at the shared 41px min-height (same as the single-selects) until chips are actually
   selected; only then does it grow, capped at 68px with a scrollbar past that. The filter row
   uses align-items-start so this growth never moves the other fields. */
.select2-container--bootstrap-5 .select2-selection--multiple {
    max-height: 68px !important;
    overflow-y: auto !important;
}
.select2-container--bootstrap-5 .select2-selection--multiple .select2-selection__rendered {
    font-size: 14px;
    color: var(--ajt-dark);
}
.select2-container--bootstrap-5 .select2-dropdown { border-color: #E0D5EC; border-radius: 8px; overflow: hidden; }
/* No fixed min-width here on purpose — a hardcoded fallback (e.g. 140px) becomes the VISIBLE
   width whenever custom.js's own live measurement doesn't apply in time, and that fallback
   almost never matches the actual field's width. custom.js now retries its measurement instead
   of leaving a mismatched number behind, so the dropdown always tracks the field it belongs to.
   Pinned above the fixed sidebar (z-index:1000) and topbar (z-index:500) — this file loads after
   select2's own CSS and should be the final word on stacking. */
.select2-container--bootstrap-5 .select2-dropdown { z-index: 2000; }
.select2-container--open { z-index: 2000; }
.select2-container--bootstrap-5 .select2-search__field { border-color: #E0D5EC !important; border-radius: 6px !important; }
.select2-container--bootstrap-5 .select2-search__field:focus {
    border-color: var(--ajt-purple) !important;
    box-shadow: 0 0 0 3px rgba(123,35,128,0.1) !important;
}
.select2-container--bootstrap-5 .select2-results__option[aria-selected="true"] {
    background-color: var(--ajt-purple) !important;
    color: #fff !important;
}
.select2-container--bootstrap-5 .select2-results__option--highlighted:not([aria-selected="true"]) {
    background-color: rgba(123,35,128,0.12) !important;
    color: var(--ajt-dark) !important;
}
.select2-container--bootstrap-5 .select2-dropdown .select2-results__options .select2-results__option.select2-results__option--selected{
    background-color: #7b2380!important;
}

.form-section-title {
    font-size: 13px;
    font-weight: 700;
    color: var(--ajt-purple);
    text-transform: uppercase;
    letter-spacing: 0.8px;
    margin: 24px 0 14px;
    padding-bottom: 8px;
    border-bottom: 2px solid var(--ajt-light);
}

/* ================================================================
   TABLES
   ================================================================ */

.ajt-table { width: 100%; border-collapse: separate; border-spacing: 0; }
.ajt-table thead tr th {
    background: var(--ajt-light);
    color: var(--ajt-dark);
    font-size: 12px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    padding: 12px 14px;
    border-bottom: 2px solid #E8DCF0;
    white-space: nowrap;
}
.ajt-table tbody tr td { padding: 12px 14px; border-bottom: 1px solid #F5EDF9; vertical-align: middle; }
.ajt-table tbody tr:last-child td { border-bottom: none; }
.ajt-table tbody tr:hover td { background: #FBF6FF; }

/* ── Row expand/collapse (+/-), mobile only (assets/js/custom.js: ajtSetupLrColumns etc.) ──
   Ported from the same proven pattern in the Sparkle project. Below the breakpoint, a
   dedicated leading column holds a +/- toggle; the 1-2 most identifying columns stay in the
   row, everything else moves into an expand panel below it. Desktop/tablet are untouched. */

/* Zero-width (not display:none) on desktop: DataTables assigns each column its own inline
   width and expects the header/body cell counts to always match — hiding the <th>/<td>
   outright would desync its column bookkeeping. Collapsing to nothing visually (but still
   present) keeps the count truthful while taking no visible space or layout row. The
   !important throughout beats DataTables' own inline per-column width style. */
th.ajt-lr-th, td.ajt-lr-cell { width: 0 !important; min-width: 0 !important; max-width: 0 !important; padding: 0 !important; border-width: 0 !important; overflow: hidden !important; }
.ajt-lr-toggle { display: none; }

@media (max-width: 700px) {
    /* Guarantees the table itself never needs horizontal scrolling, regardless of what's
       left in it. table-layout:fixed is the key part: normal ("auto") table layout still
       lets a cell's CONTENT (a long title, an unbroken string) force that column — and so
       the whole table — wider than the screen even with every width set to 100%/auto.
       Fixed layout locks the table to its own width no matter what; word-break/overflow-wrap
       below make long content wrap inside its cell instead of trying to stretch it. */
    /* min-width:0 matters as much as width:100% here — several tables (exam results, mock
       test / exam attempt reports) carry an inline style="min-width:1000px" etc. for their
       desktop wide-table scroll. Without overriding it too, min-width still won it against
       width:100% (a box's rendered width is clamped to at least its min-width), so the table
       stayed locked at its full desktop width and never actually shrank down to the columns
       row-expand left visible — the toggle worked, but there was still nothing to gain from
       it since the table never got narrower. */
    /* Scoped to .ajt-lr-ready (added by custom.js only once row-expand actually built a
       toggle column) rather than every .ajt-datatable — a table with nothing to collapse
       (most commonly: it loaded with zero rows, so there was no data to rank columns by)
       never gets this marker, and forcing table-layout:fixed on it anyway would squeeze
       ALL of its columns — none of them hidden — into an equal, much-too-narrow share of
       the width, wrapping every header into an unreadable single-character stack. Such a
       table is left on normal layout instead, same as it was before row-expand existed. */
    table.ajt-datatable.ajt-lr-ready { width: 100% !important; min-width: 0 !important; table-layout: fixed; }
    table.ajt-datatable.ajt-lr-ready > thead > tr > th:not(.ajt-lr-th):not(.ajt-lr-hide),
    table.ajt-datatable.ajt-lr-ready > tbody > tr > td:not(.ajt-lr-cell):not(.ajt-lr-hide) {
        width: auto !important;
        white-space: normal !important;
        word-break: break-word;
        overflow-wrap: anywhere;
    }
    /* Headers still wrapped mid-word even with only 1-2 columns left (e.g. a single word
       like "DESCRIPTION" broken into a vertical letter stack) — 2-3 equal-width columns on
       a ~320-375px phone only leaves ~90-110px each, and the base 12px uppercase letter-
       spaced header style needs more room than that for most real column names. Shrunk
       specifically for header cells on a ready table; overflow-wrap:anywhere above stays
       as the last-resort safety net for a genuinely long single word even at this size,
       but at 9.5px tight-spaced it's now rarely needed for an ordinary column label. */
    table.ajt-datatable.ajt-lr-ready > thead > tr > th:not(.ajt-lr-th):not(.ajt-lr-hide) {
        font-size: 9.5px !important;
        letter-spacing: .2px !important;
        padding-left: 6px !important;
        padding-right: 6px !important;
    }

    th.ajt-lr-th, td.ajt-lr-cell {
        width: 30px !important; min-width: 30px !important; max-width: 30px !important;
        padding: 4px !important; border-width: 0 !important; text-align: center; vertical-align: middle;
        overflow: visible !important;
    }
    .ajt-lr-hide { display: none; }
    .ajt-lr-toggle {
        display: inline-flex; align-items: center; justify-content: center;
        width: 22px; height: 22px; flex-shrink: 0;
        border: 1.5px solid #E0D5EC; border-radius: 6px; background: #fff; color: var(--ajt-purple);
        cursor: pointer; font-size: 11px; line-height: 1; padding: 0;
        transition: border-color .15s ease, background .15s ease;
    }
    .ajt-lr-toggle:hover, .ajt-lr-toggle:focus { border-color: var(--ajt-purple); background: var(--ajt-light); }
    .ajt-lr-toggle i { pointer-events: none; }
}

/* Expand panel: one row per hidden column, label above a right-aligned value so which is
   which is never ambiguous even at a glance. */
tr.ajt-lr-detail > td { background: #FBF6FF; padding: 8px 14px; }
.ajt-lr-grid { display: flex; flex-direction: column; }
.ajt-lr-field { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 7px 0; border-bottom: 1px solid #F0E8F5; font-size: 12.5px; }
.ajt-lr-field:last-child { border-bottom: 0; }
.ajt-lr-label { color: #888; font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .4px; flex-shrink: 0; }
.ajt-lr-value { font-weight: 600; color: var(--ajt-dark); text-align: right; word-break: break-word; min-width: 0; }

/* ================================================================
   STATUS BADGES
   ================================================================ */

.badge-ajt {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 4px 10px;
    border-radius: 20px;
    font-size: 11.5px;
    font-weight: 600;
    white-space: nowrap;
}
.badge-ajt.active, .badge-ajt.completed, .badge-ajt.present { background: rgba(141,198,63,0.18); color: #4a7000; }
.badge-ajt.pending, .badge-ajt.in_progress { background: rgba(245,167,35,0.18); color: #7a5200; }
.badge-ajt.inactive, .badge-ajt.absent { background: rgba(232,132,90,0.18); color: #8a3010; }
.badge-ajt.dropped { background: rgba(150,150,150,0.18); color: #555; }
.badge-ajt.scholarship { background: rgba(123,35,128,0.12); color: var(--ajt-purple); }

/* ================================================================
   FLASH ALERTS
   ================================================================ */

.ajt-alert {
    border-radius: 10px;
    padding: 12px 18px;
    margin-bottom: 16px;
    display: flex;
    align-items: flex-start;
    gap: 12px;
    font-size: 13.5px;
}
.ajt-alert.success { background: #f0fff4; border: 1px solid #9ae6b4; color: #276749; }
.ajt-alert.error   { background: #fff5f5; border: 1px solid #feb2b2; color: #c53030; }
.ajt-alert.warning { background: #fffaf0; border: 1px solid #fbd38d; color: #7b5200; }
.ajt-alert.info    { background: #ebf8ff; border: 1px solid #90cdf4; color: #2a6f9f; }
.ajt-alert i { font-size: 16px; margin-top: 2px; flex-shrink: 0; }

/* ================================================================
   PAGE HEADER
   ================================================================ */

.page-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    margin-bottom: 20px;
    gap: 12px;
    flex-wrap: wrap;
}
.page-header .page-header-left h2 { font-size: 20px; font-weight: 800; color: var(--ajt-dark); }
.page-header .page-header-left p  { font-size: 13px; color: #888; margin-top: 2px; }
.page-header .page-header-actions { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }

/* ================================================================
   LOGIN PAGE
   ================================================================ */

.login-shell {
    min-height: 100vh;
    display: flex;
    align-items: stretch;
    background: var(--ajt-light);
}
.login-brand {
    flex: 0 0 52%;
    background: linear-gradient(145deg, var(--ajt-dark) 0%, var(--ajt-purple2) 50%, var(--ajt-purple) 100%);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 48px 56px;
    position: relative;
    overflow: hidden;
}
.login-brand::before {
    content: '';
    position: absolute;
    width: 500px; height: 500px;
    border-radius: 50%;
    border: 60px solid rgba(141,198,63,0.08);
    top: -120px; right: -140px;
}
.login-brand::after {
    content: '';
    position: absolute;
    width: 350px; height: 350px;
    border-radius: 50%;
    border: 50px solid rgba(245,167,35,0.07);
    bottom: -90px; left: -100px;
}
.login-brand .brand-logo {
    background: rgba(255,255,255,0.12);
    border: 1px solid rgba(255,255,255,0.2);
    border-radius: 20px;
    padding: 20px 36px;
    display: inline-block;
    margin-bottom: 32px;
    backdrop-filter: blur(8px);
}
.login-brand .brand-logo img { height: 70px; width: auto; display: block; }
.login-brand .brand-title { font-size: 28px; font-weight: 800; color: #fff; line-height: 1.3; margin-bottom: 14px; }
.login-brand .brand-title span { color: var(--ajt-green); }
.login-brand .brand-tagline { font-size: 14px; color: rgba(255,255,255,0.6); line-height: 1.7; margin-bottom: 36px; }
.login-brand .feature-pill {
    display: flex; align-items: center; gap: 12px;
    background: rgba(255,255,255,0.07);
    border: 1px solid rgba(255,255,255,0.12);
    border-radius: 12px;
    padding: 12px 16px;
    margin-bottom: 10px;
}
.login-brand .feature-pill .fp-icon {
    width: 36px; height: 36px;
    background: rgba(141,198,63,0.18);
    border-radius: 8px;
    display: flex; align-items: center; justify-content: center;
    color: var(--ajt-green);
    font-size: 15px;
}
.login-brand .feature-pill .fp-text { font-size: 13px; color: rgba(255,255,255,0.75); }
.login-brand .feature-pill .fp-text strong { display: block; color: #fff; }

.login-form-panel {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 40px 32px;
}
.login-card {
    background: #fff;
    border-radius: 20px;
    box-shadow: 0 12px 48px rgba(123,35,128,0.12);
    padding: 44px 40px;
    width: 100%;
    max-width: 420px;
}
.login-card h2 { font-size: 22px; font-weight: 800; color: var(--ajt-dark); margin-bottom: 4px; }
.login-card .subtitle { font-size: 13.5px; color: #888; margin-bottom: 28px; }
.lf-group { margin-bottom: 18px; }
.lf-input-wrap { position: relative; }
.lf-input-wrap .lf-icon { position: absolute; left: 14px; top: 50%; transform: translateY(-50%); color: #aaa; font-size: 14px; pointer-events: none; }
.lf-input {
    width: 100%;
    height: 46px;
    padding: 0 42px 0 40px;
    border: 1.5px solid #E0D5EC;
    border-radius: 10px;
    font-size: 14px;
    color: var(--ajt-dark);
    background: #FDFAFF;
    outline: none;
    transition: border-color 0.2s, box-shadow 0.2s;
}
.lf-input:focus { border-color: var(--ajt-purple); background: #fff; box-shadow: 0 0 0 3px rgba(123,35,128,0.1); }
.btn-login {
    width: 100%;
    height: 48px;
    background: linear-gradient(135deg, var(--ajt-purple), var(--ajt-purple2));
    border: none;
    border-radius: 10px;
    color: #fff;
    font-size: 15px;
    font-weight: 700;
    cursor: pointer;
    transition: opacity 0.2s, transform 0.15s;
    display: flex; align-items: center; justify-content: center; gap: 8px;
    margin-top: 20px;
}
.btn-login:hover { opacity: 0.9; transform: translateY(-1px); }
.captcha-box {
    background: linear-gradient(135deg, var(--ajt-purple), var(--ajt-purple2));
    color: #fff;
    border-radius: 8px;
    padding: 8px 16px;
    font-size: 16px;
    font-weight: 800;
    letter-spacing: 2px;
}

/* ================================================================
   VIDEO PLAYER
   ================================================================ */

.video-container {
    position: relative;
    background: #000;
    border-radius: 12px;
    overflow: hidden;
    user-select: none;
    -webkit-user-select: none;
}
.video-container video {
    width: 100%;
    display: block;
    pointer-events: auto;
}
.video-overlay {
    position: absolute;
    top: 0; left: 0; right: 0; bottom: 0;
    pointer-events: none;
    display: flex;
    align-items: flex-start;
    justify-content: flex-end;
    padding: 14px;
}
.video-watermark {
    color: rgba(255,255,255,0.25);
    font-size: 13px;
    font-weight: 600;
    letter-spacing: 1px;
    text-shadow: 1px 1px 2px rgba(0,0,0,0.5);
    transform: rotate(-15deg);
    user-select: none;
}
.video-progress-bar { height: 4px; background: #ddd; border-radius: 4px; overflow: hidden; }
.video-progress-fill { height: 100%; background: linear-gradient(90deg, var(--ajt-purple), var(--ajt-green)); border-radius: 4px; transition: width 0.5s; }

/* ================================================================
   STUDENT ID CARD
   ================================================================ */

.id-card {
    width: 340px;
    border-radius: 18px;
    overflow: hidden;
    box-shadow: 0 8px 32px rgba(123,35,128,0.18);
    font-family: 'Segoe UI', sans-serif;
    margin: 0 auto;
}
.id-card .card-header {
    background: linear-gradient(135deg, var(--ajt-purple), var(--ajt-purple2));
    padding: 20px;
    text-align: center;
    color: #fff;
}
.id-card .card-header img { height: 48px; margin-bottom: 8px; }
.id-card .card-header h4 { font-size: 14px; font-weight: 700; margin: 0; }
.id-card .card-header p  { font-size: 11px; opacity: 0.7; margin: 0; }
.id-card .card-body { background: #fff; padding: 20px; }
.id-card .student-photo {
    width: 80px; height: 80px;
    border-radius: 50%;
    object-fit: cover;
    border: 3px solid var(--ajt-purple);
    display: block;
    margin: 0 auto 12px;
}
.id-card .student-name { font-size: 16px; font-weight: 800; color: var(--ajt-dark); text-align: center; }
.id-card .enrolment-no { font-size: 12px; color: var(--ajt-purple); text-align: center; font-weight: 700; background: var(--ajt-light); padding: 3px 12px; border-radius: 20px; display: inline-block; margin: 6px auto 12px; display: block; text-align: center; }
.id-card .info-row { display: flex; justify-content: space-between; font-size: 12px; padding: 5px 0; border-bottom: 1px dashed #eee; }
.id-card .info-row .label { color: #888; }
.id-card .info-row .value { font-weight: 600; color: var(--ajt-dark); }
.id-card .card-footer { background: linear-gradient(135deg, var(--ajt-green), #5a8a00); padding: 10px 20px; text-align: center; color: #fff; font-size: 11px; font-weight: 600; }

/* ================================================================
   EXAM TIMER
   ================================================================ */

.exam-timer {
    background: var(--ajt-dark);
    color: #fff;
    padding: 10px 20px;
    border-radius: 12px;
    text-align: center;
    font-size: 28px;
    font-weight: 800;
    letter-spacing: 2px;
    font-variant-numeric: tabular-nums;
    min-width: 120px;
}
.exam-timer.warning { background: #b07200; }
.exam-timer.danger  { background: var(--ajt-coral); animation: blink 1s step-end infinite; }
@keyframes blink { 50% { opacity: 0.7; } }

.question-card {
    background: #fff;
    border-radius: 12px;
    padding: 20px;
    margin-bottom: 20px;
    box-shadow: 0 2px 8px rgba(123,35,128,0.07);
    border-left: 4px solid var(--ajt-purple);
}
.question-card .q-number { font-size: 12px; font-weight: 700; color: var(--ajt-purple); margin-bottom: 8px; }
.question-card .q-text { font-size: 15px; font-weight: 600; color: var(--ajt-dark); margin-bottom: 14px; }
.option-label { display: flex; align-items: center; gap: 10px; padding: 10px 14px; border: 1.5px solid #E0D5EC; border-radius: 8px; cursor: pointer; margin-bottom: 8px; transition: border-color 0.2s, background 0.2s; }
.option-label:hover { border-color: var(--ajt-purple); background: var(--ajt-light); }
.option-label input[type="radio"]:checked ~ .ajt-content,
.option-label:has(input:checked) { border-color: var(--ajt-purple); background: rgba(123,35,128,0.06); }

/* ================================================================
   ATTENDANCE CHART / PROGRESS
   ================================================================ */

.attendance-circle {
    position: relative;
    width: 100px;
    height: 100px;
    margin: 0 auto;
}
.attendance-circle svg { transform: rotate(-90deg); }
.attendance-circle .pct-text {
    position: absolute;
    top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    font-size: 18px;
    font-weight: 800;
    color: var(--ajt-dark);
}

/* ================================================================
   RESPONSIVE
   ================================================================ */

@media (max-width: 991px) {
    /* The drawer (and its scrim, below) starts under the topbar instead of at the very top
       of the viewport, so the topbar — and the same toggle button that opened the drawer —
       stays visible and clickable above it. Without this the drawer's own z-index (1000)
       covered the toggle button (z-index 500) as soon as it opened, so the button could open
       the sidebar but couldn't be clicked again to close it. */
    .ajt-sidebar { transform: translateX(-100%); top: var(--topbar-h); height: calc(100vh - var(--topbar-h)); }
    .ajt-sidebar.open { transform: translateX(0); box-shadow: 4px 0 20px rgba(0,0,0,0.3); }
    .sidebar-close-btn { display: flex; }
    .ajt-main { margin-left: 0; }
    /* The topbar's page-title duplicates the in-content page-header-left (h2 + description)
       that almost every page already renders. Desktop keeps both — there's room, and the
       topbar title helps orientation while scrolled past the in-page one. On mobile, where
       both eat into limited width/height, the in-content one wins since it can carry a
       description and actions the topbar copy can't. */
    .ajt-topbar .page-title { display: none; }
    /* page-title was flex:1, so it doubled as the spacer pushing topbar-actions to the far
       right. Hiding it removes that spacer too — without this, the user badge/notif bell
       would collapse in next to the hamburger button instead of staying on the right. */
    .ajt-topbar .topbar-actions { margin-left: auto; }
    /* With page-title hidden, the topbar-logo added right after the hamburger button is
       the only branding visible on screen until the drawer is actually opened. */
    .ajt-topbar .topbar-logo { display: block; }
    /* Select2's own theme truncates a selected label to one line with an ellipsis once it's
       longer than the field — that's not a shortage of WIDTH (the field is already full-
       width on mobile), it's the theme choosing to clip rather than wrap. A label built from
       multiple joined parts (e.g. a semester label that also carries its course name) can be
       long enough that truncating it leaves nothing useful readable at all. Wrapped instead,
       so the whole label shows across as many lines as it needs; the box grows to match
       rather than staying pinned to the single-line 41px height. */
    .select2-container--bootstrap-5 .select2-selection--single {
        height: auto !important;
        min-height: 41px !important;
        align-items: flex-start;
        /* left/right padding restored to match the theme's own desktop values (0.75rem /
           2.25rem, the latter clearing the chevron drawn at "right 0.75rem" by the theme) —
           this rule used to zero them out (padding: 8px 0), leaving text flush against the
           left edge and able to run under the chevron on the right, on every Select2 box
           at tablet/mobile widths. */
        padding: 8px 2.25rem 8px 0.75rem;
    }
    .select2-container--bootstrap-5 .select2-selection--single .select2-selection__rendered {
        white-space: normal !important;
        overflow: visible !important;
        text-overflow: clip !important;
        word-break: break-word;
        line-height: 1.35 !important;
    }
    .login-brand { display: none; }
    /* .login-shell/.login-form-panel center the card with flexbox (align-items:center)
       for the desktop two-panel layout. On mobile, once the brand panel is hidden, that
       same centering becomes a trap: if the card's content (OTP steps, a wrapped captcha
       row, the keyboard shrinking the visible viewport) ends up taller than the screen,
       a vertically-centered flex item that overflows its container has its *top* clipped
       and unreachable by scrolling — only the bottom overflow can be scrolled into view.
       That reads as "the page is fixed / won't scroll". Switching to normal block flow
       here removes the centering (and the bug with it) — the card just sits in the
       document and the whole page scrolls like any other page. */
    .login-shell { display: block; min-height: 100vh; }
    .login-form-panel {
        display: block;
        min-height: 100vh;
        background: linear-gradient(145deg, var(--ajt-dark), var(--ajt-purple));
    }
    .login-card { max-width: 480px; margin: 0 auto; }
}
@media (max-width: 576px) {
    .ajt-content { padding: 16px; }
    .login-card { padding: 32px 22px; border-radius: 16px; }
    .stat-card .stat-info .stat-value { font-size: 22px; }
    /* Page title + its action button(s) used to wrap onto separate lines here (page-header
       has flex-wrap:wrap) whenever their combined width overflowed a phone screen — title
       above, buttons below, or several buttons stacking on top of each other. Title and
       buttons are kept on the same row instead: the title column shrinks (font-size) and
       stays flexible in width, but its text is never truncated — a long title wraps onto
       as many lines as it needs, in full, rather than being cut off with an ellipsis. The
       actions column never shrinks below its buttons' natural size (flex-shrink:0) and
       instead scrolls sideways as a last resort on a page with several of them (e.g.
       student view's Back/Edit/ID Card/Approve row), so a long title growing taller never
       squeezes the buttons themselves. */
    .page-header { flex-wrap: nowrap; align-items: flex-start; }
    .page-header .page-header-left { min-width: 0; flex: 1 1 auto; }
    .page-header .page-header-left h2 {
        font-size: 15px;
        white-space: normal;
        overflow-wrap: break-word;
    }
    .page-header .page-header-left p {
        font-size: 11px;
        white-space: normal;
        overflow-wrap: break-word;
    }
    .page-header .page-header-actions {
        flex-wrap: nowrap;
        flex-shrink: 0;
        gap: 6px;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }
    .page-header .page-header-actions .btn-ajt-primary,
    .page-header .page-header-actions .btn-ajt-outline {
        font-size: 11.5px;
        padding: 7px 10px;
        white-space: nowrap;
        flex-shrink: 0;
    }
    /* .page-header-actions can hold either a short row of simple buttons (Back/Edit/Print,
       what the rules above are for) or, on filter-driven pages like Attendance Report, an
       entire <form> with several select fields. flex-shrink:0 has nowhere to shrink a
       multi-field form TO, so with the rules above it just claims its full natural (huge)
       width and squeezes the title column down to almost nothing — the title ends up
       wrapping one letter per line. A header whose actions column holds a form falls back
       to the original stacked layout instead: title on its own row, then the form below,
       wrapping normally within itself (already handled by the form.d-flex.flex-wrap rule
       above, which stacks each of the form's own fields full-width in turn). */
    .page-header:has(.page-header-actions form) {
        flex-wrap: wrap;
    }
    .page-header:has(.page-header-actions form) .page-header-actions {
        flex-shrink: 1;
        flex-basis: 100%;
        overflow-x: visible;
        width: 100%;
    }
    /* Filter/search bars across admin & coordinator list pages share this exact Bootstrap
       utility combo — form.d-flex.gap-2.flex-wrap, with each field given its own fixed
       inline px width for desktop (e.g. style="width:200px"). Left alone, flex-wrap just
       breaks them onto new lines wherever the running total of those fixed widths happens
       to overflow the viewport at that exact width — sometimes landing evenly, sometimes
       not, and never the same from one screen width or one page's field widths to the next.
       Every field/button in such a form goes full-width and stacks one per row here
       instead, for a layout that's consistent everywhere rather than by coincidence. */
    form.d-flex.flex-wrap > * {
        flex: 1 1 100% !important;
        width: 100% !important;
    }
    /* A second, separate family of filter bars — the Reports pages (Student Report, Book
       Issue Report, Student Feedback, Book Dispatch Report, on both admin and coordinator)
       — uses flex-nowrap instead of flex-wrap, plus its own page-local <style> block
       (id-scoped, e.g. #reportFilterForm) that only re-enables wrapping at a fixed 140px
       flex-basis per field. That still crams 3-4 dropdowns onto one cramped row on a phone,
       each too narrow to show its own label text (the "All Exa…" / "All Cour…" truncation).
       !important is required here since the page-local rule targets an #id, which normally
       outranks this class selector on specificity alone. */
    .d-flex.flex-nowrap {
        /* The bug that actually mattered: telling each FIELD to be 100% wide is meaningless
           without also telling the ROW to wrap — flex-nowrap literally means "never start a
           new line", so every child kept trying to claim the full row width on the SAME
           line and the browser's only way to satisfy that was to shrink every one of them
           down to a sliver instead, which is what produced the icon-only, unreadable mess. */
        flex-wrap: wrap !important;
    }
    .d-flex.flex-nowrap > * {
        flex: 1 1 100% !important;
        width: 100% !important;
        min-width: 0 !important;
        max-width: 100% !important;
    }
    /* Select2 replaces each <select> with its own .select2-container span — but custom.js's
       init copies that select's ORIGINAL desktop inline width (e.g. 220px, 200px — often a
       different value per field) onto the container as a fresh inline style once, at page
       load. The rules above make each FIELD's own wrapper (the form's direct child, be it
       the <select>/.select2-container itself or, on pages like Offline Result's filter,
       an extra <div> holding a <label>+<select>+error-message) go full width — but that
       wrapper being full width doesn't make the Select2 box INSIDE it grow to match; left
       at its old fixed pixel width, it just sits at one end of the now-wider wrapper,
       leaving dead space and every field a visibly different size instead of a uniform,
       edge-to-edge row. Reached here regardless of nesting depth (a plain descendant
       selector, not a direct-child one) and regardless of which of the two filter-bar
       families (flex-wrap or flex-nowrap) it's inside. */
    .d-flex.flex-wrap .select2-container,
    .d-flex.flex-wrap .select2-selection,
    .d-flex.flex-nowrap .select2-container,
    .d-flex.flex-nowrap .select2-selection {
        width: 100% !important;
        max-width: 100% !important;
    }
    /* Same bug, plain <input> version — filter bars across the app (WA/SMS Log's From/To
       Date, and ~20 other list/report pages) give each date/text field its own hardcoded
       style="width:170px" (or similar) inline, sized for the desktop row. The rules above
       make the field's WRAPPER go full width, but the input itself keeps that old fixed
       pixel width and just sits at one end of the now-wider wrapper — small, oddly placed,
       and inconsistent with every other full-width mobile field (Select2 boxes included,
       fixed above). An inline width has higher specificity than a class rule, so this needs
       !important regardless of nesting depth (plain descendant selector, both filter-bar
       families) to actually override it. */
    .d-flex.flex-wrap input.form-control-ajt,
    .d-flex.flex-nowrap input.form-control-ajt {
        width: 100% !important;
        max-width: 100% !important;
    }
}
@media (max-width: 420px) {
    /* Two stat cards per row (col-6) leaves roughly 130-140px per card at this width — the
       card's own padding + fixed 52px icon + gap alone used to eat almost all of that,
       leaving no room for the number/label, which then got clipped by the column's own
       overflow:hidden (see ".row > [class*='col-']" above) instead of just shrinking. */
    .stat-card { padding: 12px 10px; gap: 8px; }
    .stat-card .stat-icon { width: 36px; height: 36px; font-size: 15px; border-radius: 9px; }
    .stat-card .stat-info .stat-value { font-size: 16px; }
    .stat-card .stat-info .stat-label { font-size: 9.5px; line-height: 1.25; }
}

/* ── Backdrop for mobile sidebar ── */
.sidebar-backdrop {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.45);
    z-index: 999;
}
.sidebar-backdrop.show { display: block; }
@media (max-width: 991px) {
    /* Matches the drawer's own top offset above so the scrim doesn't cover the topbar either
       — otherwise it sat on top of the toggle button and swallowed the click meant to close it. */
    .sidebar-backdrop { top: var(--topbar-h); }
}

/* ── Misc utilities ── */
.text-purple { color: var(--ajt-purple) !important; }
.text-green  { color: var(--ajt-green)  !important; }
.text-yellow { color: var(--ajt-yellow) !important; }
.text-coral  { color: var(--ajt-coral)  !important; }
.bg-purple-light { background: var(--ajt-light) !important; }
.border-purple   { border-color: var(--ajt-purple) !important; }
.rounded-ajt     { border-radius: 12px !important; }
.fw-800          { font-weight: 800 !important; }
.section-divider { height: 1px; background: linear-gradient(90deg, var(--ajt-purple), transparent); margin: 24px 0; opacity: 0.15; }
.table-responsive {
        padding: 14px;
}

/* ================================================================
   FLATPICKR — global date picker theme (replaces native browser
   calendar UI on every input[type=date], see assets/js/custom.js)
   ================================================================ */

.flatpickr-input.form-control-ajt[readonly] { background: #FDFAFF; cursor: pointer; }

.flatpickr-calendar {
    background: #fff;
    border-radius: 14px;
    box-shadow: 0 12px 40px rgba(45,27,53,0.18);
    border: 1px solid #E0D5EC;
    font-family: inherit;
    width: 300px;
}
.flatpickr-calendar.arrowTop:before,
.flatpickr-calendar.arrowTop:after { border-bottom-color: var(--ajt-purple); }
.flatpickr-months { background: linear-gradient(135deg, var(--ajt-purple) 0%, var(--ajt-purple2) 100%); border-radius: 14px 14px 0 0; padding: 10px 0; }
.flatpickr-months .flatpickr-month { color: #fff; fill: #fff; height: 34px; }
.flatpickr-months .flatpickr-prev-month,
.flatpickr-months .flatpickr-next-month { fill: #fff; color: #fff; top: 10px; padding: 6px; }
.flatpickr-months .flatpickr-prev-month:hover svg,
.flatpickr-months .flatpickr-next-month:hover svg { fill: var(--ajt-green); }
.flatpickr-current-month { font-size: 14px; font-weight: 700; }
.flatpickr-current-month .flatpickr-monthDropdown-months { background: transparent; font-weight: 700; }
.flatpickr-current-month .flatpickr-monthDropdown-months option { color: var(--ajt-dark); }
.flatpickr-current-month input.cur-year { font-weight: 700; color: #fff; }
.flatpickr-weekdays { background: var(--ajt-light); }
span.flatpickr-weekday { color: var(--ajt-purple2); font-weight: 700; font-size: 11px; text-transform: uppercase; }
.flatpickr-day { border-radius: 8px; font-weight: 600; color: var(--ajt-dark); }
.flatpickr-day.today { border-color: var(--ajt-green); }
.flatpickr-day.today:hover { border-color: var(--ajt-green); background: var(--ajt-green); color: #fff; }
.flatpickr-day:hover { background: var(--ajt-light); border-color: var(--ajt-light); }
.flatpickr-day.selected,
.flatpickr-day.selected:hover,
.flatpickr-day.startRange,
.flatpickr-day.endRange {
    background: var(--ajt-purple);
    border-color: var(--ajt-purple);
    color: #fff;
    box-shadow: 0 2px 8px rgba(123,35,128,0.35);
}
.flatpickr-day.inRange { background: rgba(123,35,128,0.1); border-color: transparent; box-shadow: none; }
.flatpickr-day.flatpickr-disabled,
.flatpickr-day.flatpickr-disabled:hover { color: #ccc; }
.flatpickr-day.nextMonthDay,
.flatpickr-day.prevMonthDay { color: #ccc; }
.flatpickr-time { border-top: 1px solid #E0D5EC; }
.flatpickr-time input:hover,
.flatpickr-time .flatpickr-am-pm:hover,
.flatpickr-time input:focus,
.flatpickr-time .flatpickr-am-pm:focus { background: var(--ajt-light); }
.numInputWrapper span.arrowUp:after { border-bottom-color: var(--ajt-purple); }
.numInputWrapper span.arrowDown:after { border-top-color: var(--ajt-purple); }

/* ── Calendar icon (assets/js/flatpickr-helpers.js: attachPickerIcon) ── */
.ajt-date-wrap { position: relative; }
.ajt-date-wrap .flatpickr-input { padding-right: 38px !important; cursor: pointer; }
.ajt-date-icon {
    position: absolute;
    right: 13px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--ajt-purple);
    font-size: 14px;
    cursor: pointer;
    pointer-events: auto;
}
.ajt-date-icon:hover { color: var(--ajt-purple2); }

/* ── Month & Year dropdowns (attachMonthDropdown / attachYearDropdown) ──
   Native <select> option lists render with unstylable OS chrome, so these
   replace the month select + year spinner with a themed button + popup. ── */
.flatpickr-current-month { display: flex; align-items: center; justify-content: center; gap: 6px; padding: 0 6px; }
.ajt-cal-dd { position: relative; display: inline-block; }
.ajt-cal-dd-btn {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    background: rgba(255,255,255,0.14);
    color: #fff;
    border: 1px solid rgba(255,255,255,0.22);
    border-radius: 7px;
    font-weight: 700;
    font-size: 13.5px;
    font-family: inherit;
    padding: 5px 10px;
    cursor: pointer;
    transition: background .15s, border-color .15s;
}
.ajt-cal-dd-btn:hover { background: rgba(255,255,255,0.26); border-color: rgba(255,255,255,0.4); }
.ajt-cal-dd-btn i { font-size: 9px; opacity: .8; transition: transform .18s; }
.ajt-cal-dd.open .ajt-cal-dd-btn { background: rgba(255,255,255,0.28); }
.ajt-cal-dd.open .ajt-cal-dd-btn i { transform: rotate(180deg); }
.ajt-cal-dd-label { white-space: nowrap; }

/* Appended straight to .flatpickr-calendar (not nested under the month row)
   and positioned in JS (assets/js/flatpickr-helpers.js) — Flatpickr clips
   overflow on the month-header row for its slide animation, which would
   otherwise cut this off short if nested there. It must stay inside
   .flatpickr-calendar itself though, or Flatpickr's own outside-click
   handler treats clicks on it as "outside" and closes the whole picker. */
.flatpickr-calendar { overflow: visible; }
.ajt-cal-dd-list {
    display: none;
    position: absolute;
    transform: translateX(-50%);
    max-height: 220px;
    overflow-y: auto;
    background: #fff;
    border-radius: 12px;
    box-shadow: 0 16px 38px rgba(45,27,53,0.35);
    border: 1px solid #E0D5EC;
    padding: 6px;
    z-index: 40;
}
.ajt-cal-dd-list.open { display: block; }
.ajt-month-dd-list { width: 148px; }
.ajt-year-dd-list { width: 92px; }
.ajt-cal-dd-list::-webkit-scrollbar { width: 5px; }
.ajt-cal-dd-list::-webkit-scrollbar-thumb { background: var(--ajt-purple3); border-radius: 3px; }

.ajt-cal-dd-item {
    padding: 7px 10px;
    margin-bottom: 2px;
    border-radius: 7px;
    font-size: 13px;
    font-weight: 600;
    color: var(--ajt-dark);
    text-align: center;
    cursor: pointer;
    transition: background .12s, color .12s;
}
.ajt-cal-dd-item:last-child { margin-bottom: 0; }
.ajt-cal-dd-item:hover { background: var(--ajt-light); color: var(--ajt-purple); }
.ajt-cal-dd-item.selected { background: var(--ajt-purple); color: #fff; }
.ajt-cal-dd-item.selected:hover { background: var(--ajt-purple); color: #fff; }

/* ── Today / Cancel footer (attachFooterButtons) ── */
.ajt-fp-footer {
    display: flex;
    gap: 8px;
    padding: 10px 12px;
    border-top: 1px solid #E0D5EC;
    background: var(--ajt-light);
    border-radius: 0 0 14px 14px;
}
.ajt-fp-btn {
    flex: 1;
    padding: 7px 0;
    border-radius: 8px;
    font-size: 12.5px;
    font-weight: 700;
    cursor: pointer;
    border: 1.5px solid transparent;
    transition: background .15s, border-color .15s, opacity .15s;
}
.ajt-fp-today { background: var(--ajt-purple); color: #fff; border-color: var(--ajt-purple); }
.ajt-fp-today:hover:not(:disabled) { background: var(--ajt-purple2); }
.ajt-fp-today:disabled { opacity: .4; cursor: not-allowed; }

/* ─── Page Loader ─────────────────────────────────────────────────────────────
   Shown right before a full page navigation (a form submit or link click that
   reloads the page) so the blank moment while the browser loads the next page
   doesn't read as "nothing happened" — see showPageLoader() in layout_admin.php. */
#ajtPageLoader {
    position: fixed; inset: 0; background: rgba(255,255,255,0.8);
    z-index: 99999; display: none; align-items: center; justify-content: center;
    flex-direction: column; gap: 12px;
}
#ajtPageLoader.show { display: flex; }
#ajtPageLoader .ajt-spinner {
    width: 42px; height: 42px; border-radius: 50%;
    border: 4px solid #e8dff0; border-top-color: var(--ajt-purple);
    animation: ajtSpin .8s linear infinite;
}
#ajtPageLoader .ajt-loader-text { font-size: 13px; font-weight: 600; color: var(--ajt-purple); }
@keyframes ajtSpin { to { transform: rotate(360deg); } }
.ajt-fp-cancel { background: #fff; color: var(--ajt-purple); border-color: #E0D5EC; }
.ajt-fp-cancel:hover { border-color: var(--ajt-purple); background: #fff; }