[x-cloak] {
    display: none !important;
}

abbr {
    text-decoration: none !important;
}

.apexcharts-toolbar, .apexcharts-menu-icon
{
    background: transparent !important;
}

.select2-container--default .select2-selection--multiple {
    border: 1px solid #cbd5e1;
}


.select2-container--default .select2-selection--single, .select2-selection--multiple {
    height: 38px !important;
    border: 1px solid #cbd5e1;
    box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
    border-radius: 6px;
    padding-top: 5px;
    padding-left: 5px;
    margin-top: 4px;
    font-size: 14px;
}

.select2-container--default .select2-selection--multiple {
    border-radius: 6px;
}

.select2-selection--single, .select2-selection--multiple {
    min-height: 38px !important;
    height: auto !important;
}

.select2-container--default .select2-selection--single .select2-selection__arrow, .select2-selection--multiple .select2-selection__arrow {
    height: 46px !important;
    padding-right: 12px !important;
    display: flex;
    justify-content: center;
    align-items: center;
}

.select2-container--default .select2-selection--single .select2-selection__arrow b {
    background-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E%3Cpath fill='rgb(107,114,127)' stroke='rgb(107,114,127)' stroke-width='10' d='M201.4 342.6c12.5 12.5 32.8 12.5 45.3 0l160-160c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L224 274.7 86.6 137.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l160 160z'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-color: transparent;
    background-size: contain;
    border: none !important;
    height: 12px !important;
    width: 13px !important;
    margin: auto !important;
    top: auto !important;
    left: auto !important;
    color: rgb(107 114 127) !important;
}

.select2-container--default .select2-search--dropdown .select2-search__field {
    border: 1px solid #d1d5db;
    outline: none;
}

.select2-container--default .select2-selection--single .select2-selection__rendered {
    font-size: 0.875rem !important;
    color: black !important;
}

.select2-container--default .select2-selection--single .select2-selection__clear {
    height: 25px;
    padding-right: 10px;
}

.select2-container--default .select2-selection--multiple.select2-selection--clearable {
    margin: 0 !important;
    margin-top: 3.3px !important;
}

/* Multi-select chips: pill instead of select2 stock gray box, with the x kept on the
   left where select2 renders it and the label spaced off it. */
.select2-container--default .select2-selection--multiple .select2-selection__choice {
    display: inline-flex;
    align-items: center;
    margin-top: 2px !important;
    margin-bottom: 2px !important;
    padding: 1px 9px 1px 5px !important;
    border: none !important;
    border-radius: 9999px !important;
    background-color: #e0e7ff !important;
    color: #3730a3 !important;
    line-height: 19px;
}

.select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
    /* select2 4.1 pins this button with position:absolute;left:0;top:0, which drops it
       out of the chip flex row and lands the x on top of the label. Back in flow it
       just sits before the display span. */
    position: static !important;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 15px;
    height: 15px;
    padding: 0 !important;
    margin: 0 !important;
    border: none !important;
    border-radius: 9999px !important;
    background: transparent !important;
    color: #6366f1 !important;
    font-size: 15px;
    line-height: 15px;
    align-self: center;
    flex: none; /* chip is max-width:100%; without this a long label squashes the x */
}

.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover {
    background: rgba(99, 102, 241, .18) !important;
    color: #dc2626 !important;
}

.select2-container--default .select2-selection--multiple .select2-selection__choice__display {
    margin-left: 7px !important;
    padding-left: 0 !important;
}

/* select2 paints a solid black 1px border on focus and the inline search field keeps
   the browser outline; real inputs just tint their border, so match that. */
.select2-container--default.select2-container--focus .select2-selection--multiple,
.select2-container--default.select2-container--open .select2-selection--multiple,
.select2-container--default.select2-container--open .select2-selection--single {
    border-color: #6366f1 !important;
    border-width: 1px !important;
    outline: 0 !important;
}

.select2-container--default .select2-selection--single:hover,
.select2-container--default .select2-selection--multiple:hover {
    border-color: #9ca3af !important;
}

.select2-container--default .select2-search--inline .select2-search__field:focus,
.select2-container--default .select2-search--dropdown .select2-search__field:focus,
.select2-container--default .select2-selection:focus {
    outline: 0 !important;
    box-shadow: none !important;
}

.select2-container--default .select2-selection--multiple .select2-selection__clear {
    margin-top: 0 !important;
}

.select2-container--default {
    font-size: 0.875rem !important;
}

.select2-container--default .select2-search--inline .select2-search__field {
    padding-bottom: 0 !important;
    margin-top: 0 !important;
    line-height: 20px !important;
    font-size: 0.875rem !important;
    margin-left: 7px !important;
}

.select2-container--default .select2-search--inline .select2-search__field::placeholder, .select2-selection__placeholder {
    color: rgba(0, 0, 0, 0.9) !important;
}

@media (max-width: 640px) {
    .-my-2.overflow-x-auto.sm\:-mx-6.lg\:-mx-8 {
        margin-inline: 0 !important;
    }
}

.table-bordered-vertical th, .table-bordered-vertical td {
    border-style: solid !important;
    border-right-width: 1px !important;
}

.table-bordered-vertical th:last-child, .table-bordered-vertical td:last-child {
    border-right-width: 0 !important;
}

#calendar {
    width: 100% !important;
    padding-left: 20px;
    padding-right: 20px;
}

.fc-event {
    cursor: pointer !important;
    pointer-events: auto !important;
    position: relative !important;
}

.fc-col-header-cell {
    background-color: #f9fafb !important;
}

.fc-col-header-cell-cushion {
    font-weight: 600 !important;
    color: #6b7280 !important;
}

.fc-multimonth {
    background-color: #ffffff !important;
}

.fc-multimonth-month {
    margin-bottom: 0 !important;
}

.fc-multimonth-title {
    background-color: transparent !important;
    color: #374151 !important;
    font-weight: 600 !important;
    padding: 1rem 0.5rem !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    margin: 0 !important;
}

.fc-multimonth-daygrid {
    background-color: #ffffff !important;
}

.fc-multimonth .fc-col-header-cell {
    background-color: #f9fafb !important;
    border-color: #e5e7eb !important;
}

.fc-multimonth .fc-col-header-cell-cushion {
    color: #6b7280 !important;
}

.fc-multimonth .fc-daygrid-day {
    background-color: #ffffff !important;
    border-color: #e5e7eb !important;
}

.fc-multimonth .fc-daygrid-day-number {
    color: #111827 !important;
}

.fc-multimonth .fc-day-other .fc-daygrid-day-number {
    color: #9ca3af !important;
}

.fc-multimonth .fc-daygrid-day-events {
    margin: 0 !important;
}

.fc-multimonth .fc-daygrid-event {
    font-size: 0.75rem !important;
    margin-bottom: 1px !important;
}

.fc-list-day-cushion {
    background-color: #f9fafb !important;
}

.fc-list-day-text,
.fc-list-day-side-text {
    font-weight: 600 !important;
    color: #374151 !important;
}

.fc-list-day {
    background-color: #f9fafb !important;
}

.fc-timegrid-slot {
    background-color: transparent !important;
}

.fc-timegrid-col {
    background-color: #ffffff !important;
}

.fc-timegrid-axis,
.fc-timegrid-slot-label {
    background-color: #ffffff !important;
}

.fc-event-title {
    color: inherit !important;
}

.event-tooltip {
    position: fixed;
    z-index: 10000;
    background-color: #1f2937;
    color: #ffffff;
    padding: 0.5rem 0.75rem;
    border-radius: 0.375rem;
    box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.3), 0 4px 6px -2px rgba(0, 0, 0, 0.2);
    max-width: 250px;
    font-size: 0.813rem;
    line-height: 1.4;
    pointer-events: none;
    white-space: normal;
    word-wrap: break-word;
}

#calendar {
    margin-bottom: 1.5rem;
}

.fc .fc-list-empty {
    background-color: #ffffff !important;
}

@media only screen and (max-width: 1024px) {
    .fc-header-toolbar {
        display: flex !important;
        flex-direction: column !important;
    }
}

.ac-months {
    background: linear-gradient(135deg, #fbc2eb, #a6c1ee) !important;
    color: #2b1a2b !important;
}

html.dark .ac-months {
    background: linear-gradient(135deg, #3a1c71, #d76d77) !important;
    color: #ffffff !important;
}

.ac-themes {
    background: linear-gradient(135deg, #80deea, #e0f7fa) !important;
    color: #083042 !important;
}

html.dark .ac-themes {
    background: linear-gradient(135deg, #004e92, #000428) !important;
    color: #ffffff !important;
}

.ac-off-sundays {
    background: linear-gradient(135deg, #ff9a9e, #fad0c4) !important;
    color: #3a1f1f !important;
}

html.dark .ac-off-sundays {
    background: linear-gradient(135deg, #b24592, #f15f79) !important;
    color: #ffffff !important;
}

.ac-days {
    background: linear-gradient(135deg, #43e97b, #38f9d7) !important;
    color: #0f2e22 !important;
}

html.dark .ac-days {
    background: linear-gradient(135deg, #134e5e, #71b280) !important;
    color: #ffffff !important;
}

.ac-working-days {
    background: linear-gradient(135deg, #ffae66, #fee589) !important;
    color: #0d1b2a !important;
}

html.dark .ac-working-days {
    background: linear-gradient(135deg, #0f2027, #2c3864) !important;
    color: #ffffff !important;
}

.ac-table {
    border: 1px solid #e5e7eb !important; /* your color */
}

.ac-table td,
.ac-table th {
    border: 1px solid #e5e7eb !important; /* change this color */
}

.ellipsis {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.ac-menu {
    border-top-right-radius: 50%;
    border-bottom-right-radius: 50%;
    left: -28px !important;
    padding-left: 22px;
    transition: 0.2s;
    margin-top: 4px;
}

.ac-menu:hover {
    left: -8px !important;
    padding-left: 14px;
}

.ac-loading {
    opacity: 0.1 !important;
}

.md-ac-w-full-250 {
    width: calc(100% - 250px) !important;
}

@media (max-width: 768px) {
    .md-ac-w-full-250 {
        width: 100% !important;
    }
}


/* Hide the "Powered by CKEditor" badge. */
.ck-powered-by,
.ck-powered-by-balloon {
    display: none !important;
}

/* Lecture timetable drag & drop affordances. The built app.css has no cursor-grab or
   hover:* utilities for these elements, so the states live here instead of in Tailwind. */
.lt-drag {
    cursor: grab;
    transition: box-shadow .15s, border-color .15s, opacity .15s;
}

.lt-drag:hover {
    border-color: #818cf8;
    box-shadow: 0 4px 6px -1px rgba(0, 0, 0, .1), 0 2px 4px -2px rgba(0, 0, 0, .1);
}

.lt-drag:active,
.lt-drag.is-dragging {
    cursor: grabbing;
}

.lt-drag.is-dragging {
    opacity: .45;
    border-color: #4f46e5;
}

.lt-drop {
    transition: background-color .12s;
}

.lt-drop.is-hint {
    background-color: #f5f3ff;
    outline: 2px dashed #a5b4fc;
    outline-offset: -4px;
}

.lt-drop.is-over {
    background-color: #c7d2fe;
    outline: 2px solid #4f46e5;
    outline-offset: -2px;
}


/* Lecture review rating slider */
.lr-range {
    --lr-fill: #4f46e5;
    --lr-track: #e5e7eb;
    -webkit-appearance: none;
    appearance: none;
    height: 6px;
    border-radius: 9999px;
    background: var(--lr-track);
    outline: none;
    cursor: pointer;
}

.lr-range::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 18px;
    height: 18px;
    border-radius: 9999px;
    background: #4f46e5;
    border: 2px solid #fff;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .25);
}

.lr-range::-moz-range-thumb {
    width: 18px;
    height: 18px;
    border-radius: 9999px;
    background: #4f46e5;
    border: 2px solid #fff;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .25);
}

.lr-range:focus-visible {
    box-shadow: 0 0 0 3px rgba(99, 102, 241, .4);
}

/* ===== Condensed tables (project-wide) =====
   Tailwind UI's "with condensed content" row height, applied once here instead of
   editing padding utilities on several thousand cells. !important because these
   override utility classes (.py-4 is a class selector, `table td` is not).

   Row height has THREE drivers in this app, and condensing only the first is why
   the list pages looked unchanged - the padding did shrink, the avatar underneath
   it did not. */

/* 1. Vertical padding: py-3.5 header / py-4 body (~56px a row) -> ~36px. */
table :is(th, td) {
    padding-top: 0.5rem !important;
    padding-bottom: 0.5rem !important;
}

/* 2. Horizontal padding, so more COLUMNS fit too. First and last column keep
   their gutter (pl-4 sm:pl-6 lg:pl-8) - that is what lines the table up with the
   card heading above it, and flattening it pulls every table out of alignment. */
table :is(th, td):not(:first-child):not(:last-child) {
    padding-left: 0.5rem !important;
    padding-right: 0.5rem !important;
}

/* ...but the outer edges keep a gutter, in thead and tbody alike, so the first
   and last column are not flush against the card. 1.5rem is the card's own
   sm:px-6 inset, so the columns line up with the heading above the table.

   The `[class*="hidden"] +` pair is not decoration: the responsive list tables
   carry TWO first columns, a `lg:hidden` mobile one and a `lg:table-cell hidden`
   desktop one, so on a wide screen the column you SEE is :nth-child(2) and the
   flatten rule above was cutting it to 0.5rem — that is why the left edge stayed
   tight. Same story at the right end. At a breakpoint where both cells happen to
   show, one inner column gets the wider gutter; that is invisible. */
table :is(th, td):first-child,
table :is(th, td):first-child[class*="hidden"] + :is(th, td) {
    padding-left: 1.5rem !important;
}

/* ...except a row sitting under a first-column rowspan: its first cell is an inner
   column, so it keeps the inner padding. .rs-cont is set by layouts/master.blade.php. */
table :is(th, td).rs-cont:first-child {
    padding-left: 0.5rem !important;
}

table :is(th, td):last-child,
table :is(th, td):has(+ :is(th, td):last-child[class*="hidden"]) {
    padding-right: 1.5rem !important;
}

/* 3. Avatars. A 64px profile picture sets the row height on its own, so the
   condensed padding is invisible on the admission / student lists until it comes
   down too. Scoped to rounded-full: in this app that is always a profile picture
   or its placeholder svg, never content. */
table :is(th, td) :is(img, svg).rounded-full {
    height: 2.5rem !important;
    width: 2.5rem !important;
}


/* ===========================================================================
   ACADEMIC CALENDAR — STUDENT-FACING RESTYLE  (self-contained override layer)
   ---------------------------------------------------------------------------
   TO REVERT TO THE OLD LOOK: delete this entire block (down to "END ACADEMIC
   CALENDAR RESTYLE"). Nothing above depends on it. The original `.ac-*`
   gradient rules are still intact further up this file and take over again;
   the blade keeps its original Tailwind classes alongside the new hooks, so
   removing this block restores the previous appearance in both themes.

   Why the change: five clashing multi-hue gradients (pink/blue months, neon
   green day column, orange footer, salmon Sundays) competed with the event
   colours, which are the only thing on this page that carries meaning. The
   chrome is now flat and neutral so the event colours read as data.
   =========================================================================== */

/* --- Card header ------------------------------------------------------- */
.ac-head {
    border-bottom-color: #e2e8f0 !important;
}

.ac-head-eyebrow {
    color: #6366f1;
    font-size: 0.6875rem;
}

.ac-head-title {
    color: #0f172a;
    letter-spacing: -0.01em;
}

html.dark .ac-head {
    border-bottom-color: var(--border) !important;
}

html.dark .ac-head-eyebrow {
    color: #a5b4fc;
}

html.dark .ac-head-title {
    color: var(--text-bright);
}

/* --- Filter panel ------------------------------------------------------ */
.ac-panel {
    border-color: #e2e8f0 !important;
}

.ac-panel-label {
    font-size: 0.6875rem !important;
    letter-spacing: 0.08em;
    color: #64748b;
}

.ac-panel-close {
    color: #334155;
}

/* Inactive filter rows had no hover, no focus ring and no affordance at all —
   they read as static text until clicked. */
.ac-filter-btn {
    font-size: 0.8125rem;
    color: #334155;
    transition: background-color 0.15s ease, color 0.15s ease;
}

.ac-filter-btn:hover {
    background-color: #eef2ff;
    color: #312e81;
}

.ac-filter-btn:focus-visible {
    outline: 2px solid #6366f1;
    outline-offset: 1px;
}

.ac-filter-btn--on {
    background-color: #4338ca;
    color: #fff;
    font-weight: 600;
}

.ac-filter-btn--on:hover {
    background-color: #3730a3;
    color: #fff;
}

html.dark .ac-panel {
    border-color: var(--card-border) !important;
}

html.dark .ac-panel-label {
    color: var(--muted);
}

html.dark .ac-panel-close {
    color: var(--text-bright);
}

html.dark .ac-filter-btn {
    color: var(--text);
}

html.dark .ac-filter-btn:hover {
    background-color: var(--hover);
    color: var(--text-bright);
}

html.dark .ac-filter-btn--on,
html.dark .ac-filter-btn--on:hover {
    background-color: #4338ca;
    color: #fff;
}

/* --- Table chrome ------------------------------------------------------ */
/* Gradients, but single-family and low-contrast: the old ones swept across two
   unrelated hues each (pink -> blue, green -> teal, orange -> yellow) and five
   of them in one table read as noise. Each band now shades within its own hue.
   Direction matters because the gradient repeats per CELL: row bands run
   `to bottom` and column bands `to right`, so adjacent cells match edge-to-edge
   and each band reads as one continuous sweep instead of 12 little ones. */
.ac-months {
    background: linear-gradient(to bottom, #5b52ea, #4338ca) !important;
    color: #ffffff !important;
    letter-spacing: 0.04em;
    padding: 0.375rem 0.5rem !important;
}

.ac-themes {
    background: linear-gradient(to bottom, #f2f5ff, #e2e7ff) !important;
    color: #3730a3 !important;
    font-weight: 500 !important;
}

.ac-days {
    background: linear-gradient(to right, #fbfcfd, #edf0f5) !important;
    color: #334155 !important;
}

/* Per-day colours for the sticky day column. These sit ON TOP of .ac-days
   (which every one of these cells still carries), so deleting this block drops
   the whole column back to one shared style.

   Deliberately one ramp, not six unrelated picks: the day column is 60px wide
   on a phone and repeats ~6 times down the page, so six competing hues there
   would rebuild exactly the noise this restyle removed. Every step is the same
   low saturation and near-identical lightness, walking the spectrum
   indigo -> blue -> cyan -> green -> amber -> violet -> rose(Sunday), so the
   column reads as one system with seven steps and each day is still its own
   colour. `to right` because these are single cells in a column — vertical
   neighbours are different days now, so there is nothing to tile with.

   Sunday is intentionally absent: it keeps .ac-off-sundays, which also paints
   its event cells across the row. */
.ac-day-monday {
    background: linear-gradient(to right, #eef2ff, #dbe2ff) !important;
    color: #3730a3 !important;
}

.ac-day-tuesday {
    background: linear-gradient(to right, #eff6ff, #d5e6fd) !important;
    color: #1e40af !important;
}

.ac-day-wednesday {
    background: linear-gradient(to right, #ecfeff, #cbf1f8) !important;
    color: #155e75 !important;
}

.ac-day-thursday {
    background: linear-gradient(to right, #f0fdf4, #d0f0dc) !important;
    color: #166534 !important;
}

.ac-day-friday {
    background: linear-gradient(to right, #fffbeb, #fdefc8) !important;
    color: #92400e !important;
}

.ac-day-saturday {
    background: linear-gradient(to right, #f5f3ff, #e4ddfe) !important;
    color: #5b21b6 !important;
}

/* Sunday runs `to bottom`, not `to right`: getWeekDays() repeats the week ~6
   times, so each Sunday is a horizontal band spanning every month, and a
   vertical gradient lets its cells tile seamlessly across the row. */
.ac-off-sundays {
    background: linear-gradient(to bottom, #fff5f6, #ffd8dd) !important;
    color: #be123c !important;
}

.ac-working-days {
    background: linear-gradient(to bottom, #f4f7fa, #e2e8f0) !important;
    color: #0f172a !important;
}

/* T.W.D is a running cumulative total, W.D a per-month count — two different
   measures that were sharing one band and reading as a single block. The total
   row gets its own hue rather than a shade of an existing one: indigo is taken
   by the month header and slate by W.D, so teal is the only cool family left
   that reads as distinct at a glance. The top rule marks it as the final line.
   Kept as an extra class on top of .ac-working-days so deleting this block
   drops both rows back to the one shared style. */
.ac-total-days {
    background: linear-gradient(to bottom, #d1f0e9, #aee2d7) !important;
    color: #0f4f4a !important;
    border-top: 2px solid #5eead4 !important;
}

/* Scoped through .ac-table deliberately: the generic
   `html.dark thead th:not([class*="bg-"])` rule in dark-mode.css is !important
   AND more specific than a bare `html.dark .ac-months`, and dark-mode.css loads
   after this file — without the extra class these header cells fall back to the
   grey --thead-bg. */
html.dark .ac-table .ac-months {
    background: linear-gradient(to bottom, #3b34a6, #2b2673) !important;
    color: #e0e7ff !important;
}

html.dark .ac-table .ac-themes {
    background: linear-gradient(to bottom, #272e3e, #1e242f) !important;
    color: #c7d2fe !important;
}

html.dark .ac-table .ac-days {
    background: linear-gradient(to right, #1f252f, #191e26) !important;
    color: var(--text) !important;
}

html.dark .ac-table .ac-off-sundays {
    background: linear-gradient(to bottom, #4d2830, #3a1f26) !important;
    color: #fda4af !important;
}

/* Same ramp, dark. Scoped through .ac-table for the same reason as the bands
   above, and placed after .ac-days so it wins at equal specificity. */
html.dark .ac-table .ac-day-monday {
    background: linear-gradient(to right, #252c50, #1d2240) !important;
    color: #c7d2fe !important;
}

html.dark .ac-table .ac-day-tuesday {
    background: linear-gradient(to right, #1f2f4d, #18243c) !important;
    color: #bfdbfe !important;
}

html.dark .ac-table .ac-day-wednesday {
    background: linear-gradient(to right, #173f4a, #12303a) !important;
    color: #a5e8f5 !important;
}

html.dark .ac-table .ac-day-thursday {
    background: linear-gradient(to right, #1a3d2a, #142f20) !important;
    color: #bbf7d0 !important;
}

html.dark .ac-table .ac-day-friday {
    background: linear-gradient(to right, #40331a, #302614) !important;
    color: #fde68a !important;
}

html.dark .ac-table .ac-day-saturday {
    background: linear-gradient(to right, #2f2450, #251c40) !important;
    color: #ddd6fe !important;
}

html.dark .ac-table .ac-working-days {
    background: linear-gradient(to bottom, #2b3341, #222834) !important;
    color: var(--text-bright) !important;
}

/* The first dark teal (#22514e -> #1a4040) was desaturated at mid-low
   lightness, which is the recipe for mud on a dark surface — it read grey-green
   rather than teal. Saturated and shifted toward cyan instead, with the stops
   further apart so the gradient is actually visible and the bright ink pops. */
html.dark .ac-table .ac-total-days {
    background: linear-gradient(to bottom, #0e5453, #093c3e) !important;
    color: #ccfbf1 !important;
    border-top: 1px solid #3fb8ab !important;
}

/* --- Table geometry --------------------------------------------------- */
/* The day-name / Working-Days column stays put while months scroll past it;
   it needs a z-index and an edge shadow or scrolled cells slide over it. */
.ac-sticky {
    position: sticky !important;
    left: 0 !important;
    z-index: 20;
    box-shadow: 2px 0 4px -2px rgba(15, 23, 42, 0.18);
}

.ac-sticky-head {
    z-index: 30;
}

html.dark .ac-sticky {
    box-shadow: 2px 0 4px -2px rgba(0, 0, 0, 0.55);
}

/* The app-wide `table :is(th, td)` rule forces 0.5rem top/bottom on every cell.
   That is sized for list tables; on a 40-row x 12-month grid it doubles the
   page height and pushes the last months off screen for nothing. */
.ac-table tbody :is(th, td) {
    padding-top: 0.125rem !important;
    padding-bottom: 0.125rem !important;
}

.ac-col-day {
    min-width: 5.75rem;
}

.ac-col-no {
    min-width: 2rem;
}

.ac-col-ev {
    min-width: 6.5rem;
}

/* One visible rule per month boundary, so 12 months don't read as one blur. */
.ac-table .ac-col-no {
    border-left: 1px solid #cbd5e1 !important;
}

html.dark .ac-table .ac-col-no {
    border-left: 1px solid #3a4353 !important;
}

/* --- Event chips ------------------------------------------------------ */
/* The colours stored on academic_calenders are raw colour-wheel primaries —
   #ff0000, #ffff00, #ff00ff, #00fffb, #000000, #01e911 — at full saturation.
   As solid fills they glare, fight each other, and no single text colour is
   readable across them (hence the old JS that flipped between black and white).
   The data is left alone; each stored hex is instead used as a HUE and rendered
   as a soft tint with a saturated edge bar, so the hue still identifies the
   event but the chip sits calmly on the page under one fixed dark ink.
   Side benefit: near-duplicate entries for the same event (#01e911 vs #09ec2f,
   #ffff00 vs #fbff00, #ff00ff vs #e100ff) now render as the same tint.

   Two declarations per property on purpose — the first is the fallback for
   engines without color-mix(), which degrades to a neutral chip that still
   carries its hue on the edge bar rather than to something unreadable.

   Capped width + ellipsis keeps every month column the same width; the full
   name and description stay available in the hover tooltip. */
.ac-ev {
    max-width: 7.5rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    border-radius: 4px;
    margin: 2px;
    line-height: 1.35;
    padding-left: 0.375rem !important;

    background: #f1f5f9 !important;
    background: color-mix(in srgb, var(--ev, #6366f1) 18%, #ffffff) !important;
    color: #1e2939 !important;
    box-shadow: inset 3px 0 0 0 var(--ev, #6366f1);
    box-shadow: inset 3px 0 0 0 color-mix(in srgb, var(--ev, #6366f1) 80%, #1e2939);
}

/* Dark: tint up from a raised neutral rather than down from the card, so a
   pure-black event (#000000, "Kashmir Day") still reads as a chip instead of
   disappearing into the surface. The edge bar lifts toward the text colour for
   the same reason.
   24% is measured, not picked: above ~26% the light hues (#ffff00, #00fffb,
   #01e911) get bright enough that --text-bright on them drops under 4.5:1,
   and below ~14% the chip stops separating from the card. At 24% the worst
   case across all 13 stored colours is 5.0:1 text / 1.16 chip-vs-card. */
html.dark .ac-ev {
    background: var(--elevated) !important;
    background: color-mix(in srgb, var(--ev, #818cf8) 24%, #313a4b) !important;
    color: var(--text-bright) !important;
    box-shadow: inset 3px 0 0 0 var(--ev, #818cf8);
    box-shadow: inset 3px 0 0 0 color-mix(in srgb, var(--ev, #818cf8) 70%, #e3e8f0);
}

.ac-tooltip {
    box-shadow: 0 10px 26px -8px rgba(15, 23, 42, 0.3), 0 2px 6px -2px rgba(15, 23, 42, 0.12) !important;
}

/* The tooltip's colour key keeps the raw stored hex — it is the one place the
   real value should show — but a pure #ffff00 or #00fffb dot is invisible on a
   white card, so it gets a containing ring. */
.ac-ev-dot {
    box-shadow: inset 0 0 0 1px rgba(15, 23, 42, 0.25);
}

html.dark .ac-ev-dot {
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.3);
}

html.dark .ac-tooltip {
    box-shadow: 0 10px 26px -8px rgba(0, 0, 0, 0.7) !important;
}

/* --- Empty + loading states ------------------------------------------- */
.ac-empty {
    color: #64748b;
}

html.dark .ac-empty {
    color: var(--muted);
}

/* 0.1 opacity made the table vanish mid-filter; 0.35 keeps the shape visible
   and blocks stray clicks on stale rows. */
.ac-loading {
    opacity: 0.35 !important;
    pointer-events: none;
}

/* --- Scroll pane ------------------------------------------------------ */
/* `.md-ac-w-full-250` reserves 250px for a filter panel that is actually
   w-72 (288px), so the pane was 38px wider than its slot and the flex row
   squeezed it. Letting flex size it is both correct and immune to the panel
   width changing again; min-width:0 is what lets it scroll instead of
   stretching the row. */
.ac-scroll {
    flex: 1 1 0%;
    min-width: 0;
    width: auto !important;
    scrollbar-width: thin;
}

.ac-scroll::-webkit-scrollbar {
    height: 10px;
}

.ac-scroll::-webkit-scrollbar-thumb {
    background: #cbd5e1;
    border-radius: 9999px;
}

html.dark .ac-scroll::-webkit-scrollbar-thumb {
    background: var(--scrollbar);
}

/* ===========================================================================
   PHONES  (767.98px, not 768px: Tailwind's `md:` starts AT 768px, so a
   max-width:768px query double-applies with md:static on exactly-768 screens
   and the drawer rules would win.)
   =========================================================================== */
@media (max-width: 767.98px) {

    /* The filter panel was `absolute` inside a parent with `overflow-hidden`,
       so it was clipped to the TABLE's height. Filter down to "Today" — one or
       two rows — and the panel is clipped to ~40px: the filters become
       unreachable and there is no way back without reloading the page. `fixed`
       takes it out of that clipping context and makes it a normal drawer with
       its own scroll. */
    .ac-panel {
        position: fixed !important;
        top: 0;
        bottom: 0;
        z-index: 45;
        overflow-y: auto;
        width: min(18rem, calc(100vw - 3rem)) !important;
    }

    /* Backdrop with no extra markup: a huge spread shadow on the drawer itself.
       `.left-0` is only ever set by the Alpine binding, so this applies when
       open and not when parked off-canvas. */
    .ac-panel.left-0 {
        box-shadow: 0 0 0 100vmax rgba(15, 23, 42, 0.45);
    }

    /* The close X is `absolute top-0 right-0`, so it scrolls out of reach on a
       drawer taller than the viewport — and the backdrop above is a box-shadow,
       which takes no clicks. That combination leaves no way to dismiss the
       drawer at all. Pinned while open, via the same .left-0 hook so it stays
       put (and hidden) inside the off-canvas panel when closed. */
    .ac-panel.left-0 > button {
        position: fixed !important;
        top: 0.25rem;
        left: calc(min(18rem, 100vw - 3rem) - 3.25rem);
    }

    /* The open button was a 48px pill sitting at left:-28px — over half of it
       off-screen, well under the 44px minimum touch target, and easy to miss
       entirely. Bring it fully on-screen and let it read as a floating control. */
    .ac-menu {
        left: 0 !important;
        padding-left: 0 !important;
        /* NO !important on display: the button carries x-show="!menu", which
           hides it via an inline display:none, and an !important author rule
           would out-rank that and leave it stuck on screen while open. */
        display: flex;
        align-items: center;
        justify-content: center;
        /* Must clear the sticky day column (z-20) and header (z-30), or the
           button lands underneath them and cannot be tapped at all. */
        z-index: 35;
        border-top-right-radius: 8px;
        border-bottom-right-radius: 8px;
        border-top-left-radius: 0;
        border-bottom-left-radius: 0;

        /* Frosted bluish glass instead of the solid indigo block. The button is
           absolutely positioned at the top of the flex row, which is always the
           indigo month header — so it is reliably sitting on a dark blue ground.
           That is what the tint and the white icon are tuned for; `top` is pinned
           rather than left to margin-top so it cannot drift onto a light band. */
        top: 0.25rem;
        /* The tint DARKENS. A light frost over a mid-indigo ground lifts it
           toward the white icon — measured 3.95:1 on the header's top stop, and
           3.15:1 once pressed. A deep-indigo veil keeps the glass translucent
           and holds the icon at 7.3:1 across both themes and both gradient
           stops. Pressing deepens it further rather than washing it out. */
        background: rgba(30, 27, 90, 0.28) !important;
        -webkit-backdrop-filter: blur(6px) saturate(160%);
        backdrop-filter: blur(6px) saturate(160%);
        /* Light hairline is what actually reads as a glass edge. */
        border: 1px solid rgba(224, 231, 255, 0.45) !important;
        border-left: 0 !important;
        box-shadow: 0 2px 10px -2px rgba(15, 23, 42, 0.35);
    }

    /* Now stylable (the inline !important is gone from the markup). The drop
       shadow is cheap insurance: it keeps the glyph legible against whatever
       ends up behind the glass. */
    .ac-menu svg {
        color: #ffffff !important;
        filter: drop-shadow(0 1px 1px rgba(15, 23, 42, 0.45));
    }

    .ac-menu:hover,
    .ac-menu:active {
        left: 0 !important;
        padding-left: 0 !important;
        background: rgba(30, 27, 90, 0.45) !important;
    }

    /* Without backdrop-filter a 20% tint is just a washed-out smear, so fall
       back to a semi-opaque indigo that still reads as translucent. */
    @supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
        .ac-menu {
            background: rgba(67, 56, 202, 0.55) !important;
        }
    }

    /* Bigger tap targets in the drawer — py-2 alone is ~32px. */
    .ac-filter-btn {
        padding-top: 0.5rem !important;
        padding-bottom: 0.5rem !important;
        font-size: 0.875rem;
    }

    /* Reclaim horizontal room. A 12-month matrix is ~102rem wide, so on a
       375px phone every px saved is a px less scrolling. The day column keeps
       full names ("Wednesday" fits 60px at 10px) rather than being cut off. */
    /* Has to target the cells, not the table: every cell carries Tailwind's
       `text-xs`, and a directly-applied class beats an inherited value. */
    .ac-table :is(th, td) {
        font-size: 0.6875rem !important;
    }

    .ac-table .ac-col-day {
        min-width: 3.75rem;
        font-size: 0.625rem !important;
    }

    .ac-col-no {
        min-width: 1.375rem;
    }

    .ac-col-ev {
        min-width: 4.75rem;
    }

    /* Chips WRAP on phones instead of truncating. The tooltip is bound to
       onmouseover/onmouseout, which touch does not fire reliably — so a
       truncated "Periodic Tes…" would be unreadable with no way to expand it.
       Wrapping trades a little row height for names that can actually be read,
       and keeps the columns narrow at the same time. */
    .ac-ev {
        max-width: none;
        white-space: normal;
        overflow-wrap: break-word;
        line-height: 1.25;
    }

    /* max-w-sm is 384px — wider than the viewport it has to sit in. */
    .ac-tooltip {
        max-width: calc(100vw - 20px) !important;
    }
}

/* ============ END ACADEMIC CALENDAR RESTYLE ============================= */

/* ============ PIKADAY POPUP RESTYLE ===================================
   The CDN stylesheet ships a cramped grey calendar with orange / sky accents.
   This rebuilds it as a card that matches the Tailwind fields: an even 7 column
   grid, rounded day cells, SVG chevrons and indigo states. Every rule is scoped
   under .pika-single so the app's generic table padding cannot stretch the rows.
   Applies to every Pikaday field in the app. Dark mode keeps its own
   html.dark .pika-* block in dark-mode.css, which loads after this file. */
.pika-single {
    border: 1px solid #e5e7eb;
    border-radius: 0.75rem;
    background: #ffffff;
    color: #374151;
    font-family: inherit;
}

/* The popup floats over a card, so it needs more lift than a card has */
.pika-single.is-bound {
    margin-top: 0.25rem;
    box-shadow: 0 12px 28px -6px rgba(15, 23, 42, 0.18), 0 4px 10px -4px rgba(15, 23, 42, 0.08);
}

.pika-single .pika-lendar {
    width: 16.5rem;
    margin: 0;
    padding: 0.75rem;
}

/* Month / year heading, flanked by the arrows */
.pika-single .pika-title {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.25rem;
    height: 2rem;
    margin-bottom: 0.5rem;
}

.pika-single .pika-label {
    padding: 0.25rem 0.375rem;
    border-radius: 0.375rem;
    background: transparent;
    font-size: 0.9375rem;
    font-weight: 600;
    line-height: 1.25rem;
    color: #111827;
}

.pika-single .pika-title select {
    top: 0;
    cursor: pointer;
}

/* Prev / next: round buttons pinned to the corners, the stock PNG triangles
   swapped for chevrons */
.pika-single .pika-prev,
.pika-single .pika-next {
    position: absolute;
    top: 0;
    width: 2rem;
    height: 2rem;
    border-radius: 9999px;
    background-color: transparent;
    background-size: 1.125rem 1.125rem;
    opacity: 1;
    transition: background-color 0.15s;
    /* the "Previous Month" label inside is for screen readers; the stock
       20px indent only hid it inside a 20px button */
    font-size: 0;
    color: transparent;
}

.pika-single .pika-prev {
    left: 0;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='%236b7280'%3E%3Cpath fill-rule='evenodd' d='M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z' clip-rule='evenodd'/%3E%3C/svg%3E");
}

.pika-single .pika-next {
    right: 0;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='%236b7280'%3E%3Cpath fill-rule='evenodd' d='M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z' clip-rule='evenodd'/%3E%3C/svg%3E");
}

.pika-single .pika-prev:hover,
.pika-single .pika-next:hover {
    background-color: #f3f4f6;
}

.pika-single .pika-prev.is-disabled,
.pika-single .pika-next.is-disabled {
    opacity: 0.3;
    cursor: default;
    background-color: transparent;
}

/* An even seven column grid: auto layout sized each column to its header text */
.pika-single .pika-table {
    width: 100%;
    table-layout: fixed;
    border-collapse: separate;
    border-spacing: 0 0.125rem;
}

.pika-single .pika-table th,
.pika-single .pika-table td {
    width: 14.2857%;
    padding: 0;
    border: 0;
    background: transparent;
}

/* Weekday header row */
.pika-single .pika-table th {
    padding-bottom: 0.375rem;
    font-size: 0.6875rem;
    font-weight: 600;
    line-height: 1rem;
    text-align: center;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: #9ca3af;
}

.pika-single .pika-table abbr {
    text-decoration: none;
    border: 0;
    cursor: default;
}

/* Day cells: rounded, centred, with room to be tapped */
.pika-single .pika-button {
    width: 2.125rem;
    height: 2.125rem;
    margin: 0 auto;
    padding: 0;
    border: 0;
    border-radius: 0.5rem;
    background: transparent;
    box-shadow: none;
    font-size: 0.8125rem;
    font-weight: 500;
    line-height: 2.125rem;
    text-align: center;
    color: #374151;
    transition: background-color 0.12s, color 0.12s;
}

/* Stock hover is orange (#ff8000) */
.pika-single .pika-button:hover,
.pika-single .pika-row.pick-whole-week:hover .pika-button {
    background: #eef2ff;
    color: #4338ca;
    border-radius: 0.5rem;
    box-shadow: none;
}

/* Today: a ring, so it still reads when a different day is selected */
.pika-single .is-today .pika-button {
    font-weight: 700;
    color: #4f46e5;
    box-shadow: inset 0 0 0 1px #c7d2fe;
}

/* Selected day: stock is #33aaff with an inset highlight */
.pika-single .is-selected .pika-button,
.pika-single .has-event .pika-button,
.pika-single .is-selected .pika-button:hover {
    background: #4f46e5;
    color: #ffffff;
    font-weight: 600;
    border-radius: 0.5rem;
    box-shadow: 0 1px 2px rgba(79, 70, 229, 0.35);
}

/* Days that cannot be picked: plain faded text, no tile, no hover */
.pika-single .is-disabled .pika-button,
.pika-single .is-disabled .pika-button:hover {
    background: transparent;
    color: #d1d5db;
    box-shadow: none;
    opacity: 1;
    cursor: not-allowed;
}

.pika-single .is-outside-current-month .pika-button {
    color: #d1d5db;
    opacity: 1;
}

/* ============ END PIKADAY POPUP RESTYLE ================================ */

/* ============ NOTIFICATIONS DROPDOWN ==================================
   The panel and rows are styled here, including the .notification /
   .message markup that every resources/views/notification/*.blade.php
   partial already emits — so the 33 partials stay untouched. Colours use
   the dark-mode.css tokens (light values live on :root) and the project
   indigo accent. */

.notif-panel {
    position: absolute;
    top: 100%;
    z-index: 30;
    margin-top: .55rem;
    width: 23rem;
    max-width: calc(100vw - 1.5rem);
    max-height: 26rem;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    background-color: var(--card, #fff);
    border: 1px solid var(--border);
    border-radius: .5rem;
    box-shadow: 0 10px 30px -8px rgba(15, 23, 42, .22), 0 2px 6px -2px rgba(15, 23, 42, .1);
}

.notif-header {
    flex: none;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .75rem;
    padding: .7rem .9rem;
    border-bottom: 1px solid var(--border);
}

.notif-title {
    display: flex;
    align-items: center;
    gap: .45rem;
    font-size: .875rem;
    font-weight: 600;
    color: var(--text);
}

.notif-count {
    padding: .1rem .4rem;
    font-size: .65rem;
    font-weight: 700;
    line-height: 1.25;
    color: #4338ca;
    background-color: #eef2ff;
    border-radius: 9999px;
}

.notif-markall {
    font-size: .75rem;
    font-weight: 500;
    color: #4f46e5;
    white-space: nowrap;
}

.notif-markall:hover {
    text-decoration: underline;
}

.notif-list {
    flex: 1 1 auto;
    overflow-y: auto;
    overscroll-behavior: contain;
}

/* ---- row ---- */

.notif-item {
    display: flex;
    align-items: flex-start;
    gap: .65rem;
    padding: .7rem .9rem;
    border-bottom: 1px solid var(--border);
    transition: background-color .12s ease;
}

.notif-item:last-child {
    border-bottom: 0;
}

.notif-item:hover {
    background-color: var(--hover);
}

.notif-avatar {
    flex: none;
    width: 2.25rem;
    height: 2.25rem;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    font-size: .75rem;
    font-weight: 600;
    letter-spacing: .02em;
    text-transform: uppercase;
    color: #fff;
    border-radius: 9999px;
    user-select: none;
}

.notif-avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.notif-avatar svg {
    width: 1.1rem;
    height: 1.1rem;
}

/* Fallback tones — 0 is the system sender, 1-6 cycle per person. */
.notif-avatar--0 { background-color: #e2e8f0; color: #64748b; }
.notif-avatar--1 { background-color: #4f46e5; }
.notif-avatar--2 { background-color: #0891b2; }
.notif-avatar--3 { background-color: #db2777; }
.notif-avatar--4 { background-color: #ea580c; }
.notif-avatar--5 { background-color: #059669; }
.notif-avatar--6 { background-color: #7c3aed; }

.notif-body {
    flex: 1 1 auto;
    min-width: 0;
}

.notif-body > a {
    display: block;
}

.notif-dot {
    flex: none;
    width: .45rem;
    height: .45rem;
    margin-top: .55rem;
    border-radius: 9999px;
    background-color: #4f46e5;
}

/* ---- partial markup, neutralised so the row above owns the layout ---- */
/* Two-class selectors so these beat the utility classes baked into the partials. */

.notif-body .notification {
    height: auto !important;
    min-height: 0 !important;
    display: block;
    padding: 0;
    border-bottom: 0;
    background: none;
}

.notif-body .message {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: .15rem;
    height: auto;
    padding-left: 0;
}

.notif-body .message h5 {
    font-size: .8rem;
    line-height: 1.35;
    color: var(--text);
    word-break: break-word;
}

.notif-body .message h5 b {
    display: inline;
    font-weight: 600;
}

.notif-body .message h6 {
    font-size: .68rem;
    font-weight: 500;
    color: var(--muted) !important;
}

/* ---- empty state ---- */

.notif-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: .25rem;
    padding: 2.75rem 1rem;
    text-align: center;
    color: var(--muted);
}

.notif-empty svg {
    opacity: .3;
    margin-bottom: .3rem;
}

.notif-empty p {
    font-size: .85rem;
    font-weight: 600;
    color: var(--text);
}

.notif-empty span {
    font-size: .75rem;
}

/* ---- dark ---- */

html.dark .notif-panel,
html.dark-ams .notif-panel,
html.dark-ums .notif-panel {
    box-shadow: 0 14px 36px -10px rgba(0, 0, 0, .65);
}

html.dark .notif-count,
html.dark-ams .notif-count,
html.dark-ums .notif-count {
    color: #c7d2fe;
    background-color: rgba(129, 140, 248, .18);
}

html.dark .notif-markall,
html.dark-ams .notif-markall,
html.dark-ums .notif-markall {
    color: var(--accent);
}

html.dark .notif-dot,
html.dark-ams .notif-dot,
html.dark-ums .notif-dot {
    background-color: var(--accent);
}

html.dark .notif-avatar--0,
html.dark-ams .notif-avatar--0,
html.dark-ums .notif-avatar--0 {
    background-color: var(--hover);
    color: var(--muted);
}

/* ============ END NOTIFICATIONS DROPDOWN ============================== */

/* ============ COLLECT PAYMENT POSTING DATE ============================
   A picker-driven field: the wrapper draws the field, the input inside is bare
   text. Locked (cash) is its own calm state rather than a greyed-out input, so
   it reads as "set for you" instead of "broken". Dark mode lives in dark-mode.css. */
.cp-date {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    height: 2.375rem;
    padding: 0 0.75rem 0 0.375rem;
    background: #ffffff;
    border: 1px solid #d1d5db;
    border-radius: 0.375rem;
    box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
    cursor: pointer;
    transition: border-color 0.15s, box-shadow 0.15s;
}

.cp-date:hover {
    border-color: #9ca3af;
}

.cp-date:focus-within {
    border-color: #6366f1;
    box-shadow: 0 0 0 1px #6366f1;
}

.cp-date__icon {
    display: grid;
    place-items: center;
    flex-shrink: 0;
    width: 1.625rem;
    height: 1.625rem;
    border-radius: 0.25rem;
    background: #eef2ff;
    color: #4f46e5;
}

.cp-date__icon svg {
    width: 1rem;
    height: 1rem;
}

.cp-date .cp-date__input,
.cp-date .cp-date__input:focus {
    flex: 1;
    min-width: 0;
    padding: 0;
    border: 0;
    background: transparent;
    box-shadow: none;
    outline: none;
    font-size: 0.875rem;
    font-weight: 500;
    color: #111827;
    cursor: pointer;
}

.cp-date .cp-date__input::placeholder {
    font-weight: 400;
    color: #9ca3af;
}

.cp-date__chevron {
    flex-shrink: 0;
    width: 1.25rem;
    height: 1.25rem;
    color: #9ca3af;
}

.cp-date.is-locked,
.cp-date.is-locked:hover {
    background: #f9fafb;
    border-color: #e5e7eb;
    box-shadow: none;
    cursor: not-allowed;
}

.cp-date.is-locked .cp-date__icon {
    background: #f3f4f6;
    color: #9ca3af;
}

/* a disabled input is painted grey and faded by the browser; the locked look is set here instead */
.cp-date.is-locked .cp-date__input {
    color: #4b5563;
    -webkit-text-fill-color: #4b5563;
    opacity: 1;
    cursor: not-allowed;
}

.cp-date__badge {
    flex-shrink: 0;
    padding: 0.125rem 0.5rem;
    border-radius: 9999px;
    border: 1px solid #e5e7eb;
    background: #ffffff;
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.025em;
    text-transform: uppercase;
    color: #6b7280;
}

/* ============ END COLLECT PAYMENT POSTING DATE ======================== */

/* ============ STUDENT PROFILE DETAILS =================================
   resources/views/livewire/student/profile/student-details.blade.php.
   Self-contained so dark-mode.css's generic .bg-white / .shadow rules
   never touch it; colours come from the dark-mode.css tokens. */

.sd-card {
    background-color: var(--card, #fff);
    border: 1px solid var(--border);
    box-shadow: 0 1px 3px rgba(15, 23, 42, .06), 0 1px 2px rgba(15, 23, 42, .04);
    overflow: hidden;
    border-radius: .375rem;
    /* Horizontal gutter, same as the app cards' px-4 sm:px-6. */
    --sd-x: 1rem;
}

@media (min-width: 640px) {
    .sd-card {
        --sd-x: 1.5rem;
    }
}

/* App cards are `shadow sm:rounded-md sm:overflow-hidden` (square below sm) across ~570 views.
   Round them on phones too, here rather than in the views: dark-mode.css selectors key on
   the `sm:rounded-md` class, so the class names must stay. */
@media (max-width: 639.98px) {
    .sm\:rounded-md {
        border-radius: .375rem;
    }

    .sm\:rounded-lg {
        border-radius: .5rem;
    }

    /* Clip children to the rounded corners, as sm:overflow-hidden does from sm up. */
    :is(.sm\:rounded-md, .sm\:rounded-lg).sm\:overflow-hidden {
        overflow: hidden;
    }
}

.sd-hero-cover {
    position: relative;
    overflow: hidden;
    height: 5.5rem;
    background: linear-gradient(120deg, #4f46e5 0%, #6366f1 55%, #818cf8 100%);
}

/* Animated pattern over the gradient (so the dark-mode gradient keeps it):
   ::before = rings on the right + a drifting dot grid fading in from the left,
   ::after  = two seamless waves flowing in opposite directions, a light sweep and a top-left glow.
   Each wave tile starts and ends at the same height and slope, so the scroll loops without a seam. */
.sd-hero-cover::before,
.sd-hero-cover::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
}

.sd-hero-cover::before {
    background:
        repeating-radial-gradient(circle at 90% 20%, transparent 0 18px, rgba(255, 255, 255, .14) 19px 20px, transparent 21px 30px),
        radial-gradient(rgba(255, 255, 255, .3) 1px, transparent 1.6px) 0 0 / 14px 14px;
    -webkit-mask-image: linear-gradient(90deg, transparent 10%, #000 70%);
    mask-image: linear-gradient(90deg, transparent 10%, #000 70%);
    animation: sd-dots 6s linear infinite;
}

.sd-hero-cover::after {
    background:
        linear-gradient(110deg, transparent 42%, rgba(255, 255, 255, .18) 50%, transparent 58%) 0 0 / 300% 100% repeat-x,
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 600 100' preserveAspectRatio='none'%3E%3Cpath d='M0 50 Q150 10 300 50 T600 50 V100 H0Z' fill='%23fff' fill-opacity='.1'/%3E%3C/svg%3E") 0 100% / 600px 60% repeat-x,
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 900 100' preserveAspectRatio='none'%3E%3Cpath d='M0 60 Q225 100 450 60 T900 60 V100 H0Z' fill='%23fff' fill-opacity='.12'/%3E%3C/svg%3E") 0 100% / 900px 45% repeat-x,
        radial-gradient(circle at 5% -30%, rgba(255, 255, 255, .25), transparent 45%);
    animation: sd-waves 18s linear infinite;
}

@keyframes sd-dots {
    to { background-position: 0 0, 14px 14px; }
}

/* the sweep tile is 3x the cover wide; -450% moves it 3 tiles right, so it crosses every 6s of the 18s loop */
@keyframes sd-waves {
    to { background-position: -450% 0, -600px 100%, 900px 100%, 0 0; }
}

@media (prefers-reduced-motion: reduce) {
    .sd-hero-cover::before,
    .sd-hero-cover::after {
        animation: none;
    }
}

.sd-hero-body {
    /* the cover is positioned now; keeps the overlapping avatar painted above it */
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 0 var(--sd-x) 1.5rem;
}

.sd-avatar {
    width: 6.5rem;
    height: 6.5rem;
    margin-top: -3.25rem;
    flex: none;
    border-radius: 9999px;
    object-fit: cover;
    border: 4px solid var(--card, #fff);
    background-color: #f1f5f9;
    box-shadow: 0 4px 12px rgba(15, 23, 42, .12);
}

.sd-avatar--empty {
    display: flex;
    align-items: flex-end;
    justify-content: center;
    overflow: hidden;
    color: #cbd5e1;
}

.sd-avatar--empty svg {
    width: 82%;
    height: 82%;
}

.sd-hero-text {
    min-width: 0;
    margin-top: .85rem;
}

.sd-name {
    font-size: 1.25rem;
    font-weight: 700;
    line-height: 1.3;
    color: var(--text);
    overflow-wrap: anywhere;
}

.sd-sub {
    margin-top: .2rem;
    font-size: .875rem;
    color: var(--muted);
    overflow-wrap: anywhere;
}

.sd-chips {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: .4rem;
    margin-top: .75rem;
}

.sd-chip {
    padding: .2rem .65rem;
    font-size: .75rem;
    font-weight: 600;
    line-height: 1.25;
    color: #475569;
    background-color: #f1f5f9;
    border: 1px solid #e2e8f0;
    border-radius: 9999px;
}

.sd-chip--accent {
    color: #4338ca;
    background-color: #eef2ff;
    border-color: #e0e7ff;
}

.sd-card-head {
    display: flex;
    align-items: center;
    gap: .65rem;
    padding: 1.25rem var(--sd-x); /* 20 + 24px title + 20 = 64px to the line, same as the other card headers */
    border-bottom: 1px solid var(--border);
}

.sd-card-head h3 {
    font-size: 1.125rem;
    line-height: 1.5rem;
    font-weight: 500;
    color: var(--text);
}

.sd-row {
    padding: .75rem var(--sd-x);
}

.sd-row + .sd-row {
    border-top: 1px solid var(--border);
}

.sd-row dt {
    font-size: .75rem;
    font-weight: 500;
    color: var(--muted);
}

.sd-row dd {
    margin-top: .15rem;
    font-size: .875rem;
    font-weight: 500;
    color: var(--text);
    overflow-wrap: anywhere;
}

/* Tablet and up: avatar beside the name, label and value on one line. */
@media (min-width: 640px) {
    .sd-hero-cover {
        height: 7rem;
    }

    .sd-hero-body {
        flex-direction: row;
        align-items: flex-end;
        text-align: left;
        gap: 1.25rem;
        padding: 0 var(--sd-x) 1.5rem;
    }

    .sd-avatar {
        width: 8rem;
        height: 8rem;
        margin-top: -4rem;
    }

    .sd-hero-text {
        margin-top: 0;
    }

    .sd-name {
        font-size: 1.5rem;
    }

    .sd-chips {
        justify-content: flex-start;
    }

    .sd-row {
        display: grid;
        grid-template-columns: 8.5rem minmax(0, 1fr);
        gap: 1rem;
        align-items: baseline;
    }

    .sd-row dt {
        font-size: .8125rem;
    }

    .sd-row dd {
        margin-top: 0;
    }
}

/* ---- dark ---- */

html.dark .sd-card,
html.dark-ams .sd-card,
html.dark-ums .sd-card {
    border-color: var(--card-border);
    box-shadow: 0 1px 2px rgba(0, 0, 0, .4);
}

html.dark .sd-hero-cover,
html.dark-ams .sd-hero-cover,
html.dark-ums .sd-hero-cover {
    background: linear-gradient(120deg, #312e81 0%, #3730a3 55%, #4338ca 100%);
}

html.dark .sd-avatar,
html.dark-ams .sd-avatar,
html.dark-ums .sd-avatar {
    background-color: var(--elevated);
    box-shadow: 0 4px 12px rgba(0, 0, 0, .5);
}

html.dark .sd-avatar--empty,
html.dark-ams .sd-avatar--empty,
html.dark-ums .sd-avatar--empty {
    color: var(--muted-dim);
}

html.dark .sd-name,
html.dark-ams .sd-name,
html.dark-ums .sd-name,
html.dark .sd-card-head h3,
html.dark-ams .sd-card-head h3,
html.dark-ums .sd-card-head h3 {
    color: var(--text-bright);
}

html.dark .sd-chip,
html.dark-ams .sd-chip,
html.dark-ums .sd-chip {
    color: var(--text-soft);
    background-color: var(--elevated);
    border-color: var(--card-border);
}

html.dark .sd-chip--accent,
html.dark-ams .sd-chip--accent,
html.dark-ums .sd-chip--accent {
    color: #c7d2fe;
    background-color: rgba(129, 140, 248, .16);
    border-color: rgba(129, 140, 248, .25);
}

/* ---- shared student header + guardian table ---- */

.sd-chip--green {
    color: #166534;
    background-color: #f0fdf4;
    border-color: #dcfce7;
}

.sd-chip--red {
    color: #991b1b;
    background-color: #fef2f2;
    border-color: #fee2e2;
}

.sd-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .5rem;
    padding: 2.5rem 1rem;
    color: var(--muted);
}

.sd-empty svg {
    width: 2.5rem;
    height: 2.5rem;
    opacity: .5;
}

.sd-empty p {
    font-size: .875rem;
    font-weight: 600;
}

.sd-td-name {
    display: block;
    font-weight: 600;
    color: var(--text);
}

.sd-td-rel {
    display: block;
    margin-top: .1rem;
    font-size: .8125rem;
    color: var(--muted);
}

/* Student header (student/profile/student-details-header + admission/student-detail-header):
   round photo on the left, all fields as ruled boxes on the right (5 x 2 on desktop). */
/* The card itself is a standard app card (bg-white shadow sm:rounded-md) for the same border/shadow. */
.sh-card {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    --sd-x: 1rem;
}

@media (min-width: 640px) {
    .sh-card {
        --sd-x: 1.5rem;
    }
}

.sh-photo {
    width: 5.5rem;
    height: 5.5rem;
    margin: 1rem var(--sd-x);
    border-radius: 9999px;
    object-fit: cover;
    background-color: #f1f5f9;
    border: 1px solid var(--border);
    font-size: 0; /* a photo that fails to load showed its alt text (the name in capitals) */
    color: transparent;
}

/* Cells ruled by 1px gaps showing the grid's border-coloured background
   (shadows got covered by the next cell's background). */
.sh-facts {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 1px;
    align-self: stretch;
    background-color: var(--border);
    border-left: 1px solid var(--border);
    --sh-white: var(--card, #fff);
    --sh-tint: #f8fafc;
}

/* 2 per row (phones/tablets): rows 2 and 4 white. */
.sh-facts > div {
    padding: .75rem var(--sd-x);
    background-color: var(--sh-tint);
}

.sh-facts > div:nth-child(4n+3),
.sh-facts > div:nth-child(4n+4) {
    background-color: var(--sh-white);
}

/* Phones: photo centred on its own row, boxes full width below. */
@media (max-width: 639.98px) {
    .sh-card {
        grid-template-columns: minmax(0, 1fr);
        justify-items: center;
    }

    .sh-facts {
        justify-self: stretch;
        border-left: 0;
        border-top: 1px solid var(--border);
    }
}

@media (min-width: 1024px) {
    .sh-facts {
        grid-template-columns: repeat(5, minmax(0, 1fr));
    }

    /* One line; anything still too long ends in "..." with the full text on hover (title). */
    .sh-facts dd {
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    /* Long values step the font down first (length classes set in the blade); "..." only if still too long. */
    .sh-facts dd.sh-long {
        font-size: .8125rem;
    }

    .sh-facts dd.sh-longer {
        font-size: .75rem;
    }

    /* 5 per row: columns 2 and 4 white in both rows. */
    .sh-facts > div:nth-child(n) {
        background-color: var(--sh-tint);
    }

    .sh-facts > div:nth-child(5n+2),
    .sh-facts > div:nth-child(5n+4) {
        background-color: var(--sh-white);
    }
}

.sh-facts dt {
    display: block;
    font-size: .6875rem;
    font-weight: 600;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--muted);
}

.sh-facts dd {
    margin-top: .15rem;
    font-size: .875rem;
    font-weight: 500;
    color: var(--text);
    overflow-wrap: anywhere;
}

/* Name (second box, after Admission #) reads as the title. */
.sh-facts > div:nth-child(2) dd {
    font-weight: 600;
}

/* Guardian cards (guardain-details.blade.php). */
.sd-guardians {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 26rem), 1fr));
    gap: 1rem;
    padding: 1rem var(--sd-x);
}

.sd-guardian {
    --sd-x: 1rem;
    border: 1px solid var(--border);
    border-radius: .5rem;
    overflow: hidden;
}

.sd-guardian-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .75rem;
    padding: .85rem var(--sd-x);
    background-color: #f8fafc;
    border-bottom: 1px solid var(--border);
}

.sd-initials {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    flex: none;
    border-radius: 9999px;
    font-size: .875rem;
    font-weight: 700;
    color: #4338ca;
    background-color: #e0e7ff;
}

.sd-guardian-tags {
    display: flex;
    flex-wrap: wrap;
    gap: .35rem;
    margin-left: auto;
}

html.dark .sh-facts dd,
html.dark-ams .sh-facts dd,
html.dark-ums .sh-facts dd {
    color: var(--text-bright);
}

html.dark .sh-photo,
html.dark-ams .sh-photo,
html.dark-ums .sh-photo {
    background-color: var(--elevated);
    border-color: var(--card-border);
}

html.dark .sh-facts,
html.dark-ams .sh-facts,
html.dark-ums .sh-facts {
    /* Table-header shades: a quiet tint, with lines a step above both cell colours so they still read. */
    background-color: var(--thead-border);
    border-color: var(--thead-border);
    --sh-white: var(--card);
    --sh-tint: var(--thead-bg);
}

html.dark .sd-guardian-head,
html.dark-ams .sd-guardian-head,
html.dark-ums .sd-guardian-head {
    background-color: var(--elevated);
}

html.dark .sd-initials,
html.dark-ams .sd-initials,
html.dark-ums .sd-initials {
    color: #c7d2fe;
    background-color: rgba(129, 140, 248, .2);
}

html.dark .sd-chip--green,
html.dark-ams .sd-chip--green,
html.dark-ums .sd-chip--green {
    color: #86efac;
    background-color: rgba(34, 197, 94, .12);
    border-color: rgba(34, 197, 94, .25);
}

html.dark .sd-chip--red,
html.dark-ams .sd-chip--red,
html.dark-ums .sd-chip--red {
    color: #fca5a5;
    background-color: rgba(239, 68, 68, .12);
    border-color: rgba(239, 68, 68, .25);
}

/* ============ END STUDENT PROFILE DETAILS ============================ */

/* ============ RESPONSIVE TABLE ========================================
   Add `responsive-table` to any <table>: below 768px each row becomes its
   own bordered box, one line per cell with the label above the value -
   the same look as the student details cards (.sd-row). Labels come from
   the column's <th> (filled in by the script in layouts/master.blade.php);
   a td with data-label="" shows no label and reads as the row's title.
   Desktop is untouched. The doubled class out-specifies the app-wide
   `table :is(th, td)` padding rules, which are !important at (0,2,2). */

@media (max-width: 767px) {
    .responsive-table thead {
        display: none;
    }

    .responsive-table,
    .responsive-table tbody,
    .responsive-table tr {
        display: block;
        width: 100%;
    }

    /* No lines between bodies: divide-y draws one above every <tbody> (some
       tables emit one per row), and the boxes carry their own border. Its
       `> :not([hidden]) ~ :not([hidden])` selector needs !important to beat. */
    .responsive-table.responsive-table > tbody {
        border-top-width: 0 !important;
    }

    /* Each row is a box, inset by the card gutter (px-4 sm:px-6). The vertical
       margins collapse, so boxes sit .75rem apart across <tbody>s too. */
    .responsive-table.responsive-table tbody tr {
        width: auto;
        margin: .75rem 1rem;
        border-radius: .375rem;
        overflow: hidden;
    }

    /* :root lifts this over dark-mode.css's `html.dark table tr:last-child` and
       `[class*="divide-y"] > tr` rules, which strip row bottom borders. */
    :root .responsive-table.responsive-table tbody tr {
        border: 1px solid var(--border) !important;
    }

    @media (min-width: 640px) {
        .responsive-table.responsive-table tbody tr {
            margin: .75rem 1.5rem;
        }
    }

    /* Cells are plain blocks: several inline pieces (two buttons and a "|")
       flow side by side and long values wrap naturally. */
    .responsive-table.responsive-table tbody tr > :is(th, td) {
        display: block;
        padding: .6rem .9rem !important;
        text-align: left;
        white-space: normal;
        overflow-wrap: anywhere;
        font-weight: 500;
        border: 0;
    }

    .responsive-table.responsive-table tbody tr > :is(th, td) + :is(th, td) {
        border-top: 1px solid var(--border);
    }

    /* Where one record ends and the next begins. The box outline was the same faint
       --border as the lines between its own fields, so stacked boxes ran together.
       Each box is now a small card: an even outline, more space
       between cards, a tinted header band on its first line, and a "#1, #2…" record pill in the header's corner. Tables whose first
       column is already "Sr #" skip the pill. Lone cells (empty state, class
       headings) stay plain. */
    .responsive-table.responsive-table {
        counter-reset: rt-record;
    }

    .responsive-table.responsive-table tbody tr:not(:has(> :only-child)),
    .responsive-list.responsive-list > :is(li, div):not(.text-red-500) {
        --rt-edge: #d6dbe3;
        --rt-head: #f5f7fa;
        --rt-pill-bg: #eef2f7;
        --rt-pill-text: #64748b;
        position: relative;
        margin-top: 1rem;
        margin-bottom: 1rem;
        border-color: var(--rt-edge) !important;
        border-radius: .5rem;
    }

    html.dark .responsive-table.responsive-table tbody tr:not(:has(> :only-child)),
    html.dark .responsive-list.responsive-list > :is(li, div):not(.text-red-500) {
        --rt-edge: var(--card-border);
        --rt-head: var(--hover);
        --rt-pill-bg: var(--elevated);
        --rt-pill-text: var(--text-soft);
    }

    /* header band: the first visible cell (a hidden Sr # cell is skipped) */
    .responsive-table.responsive-table tbody tr:not(:has(> :only-child)) > :is(th, td):not(.hidden):first-child,
    .responsive-table.responsive-table tbody tr:not(:has(> :only-child)) > .hidden:first-child + :is(th, td) {
        background: var(--rt-head) !important;
        font-weight: 600;
        padding-right: 3.25rem !important;
    }

    /* record number pill in the header's top-right corner */
    .responsive-table.responsive-table tbody tr:not(:has(> :only-child)) {
        counter-increment: rt-record;
    }

    .responsive-table.responsive-table tbody tr:not(:has(> :only-child)):not(:has(> :first-child:not(.hidden)[data-label^="Sr"]))::after {
        content: "#" counter(rt-record);
        position: absolute;
        top: .55rem;
        right: .6rem;
        padding: .1rem .5rem;
        border-radius: 9999px;
        background: var(--rt-pill-bg);
        color: var(--rt-pill-text);
        font-size: .6875rem;
        font-weight: 600;
        line-height: 1.1rem;
        pointer-events: none;
    }

    /* .rt-cont: a row continuing the record above (under a rowspan) - no record number of its own. */
    .responsive-table.responsive-table tbody tr.rt-cont::after {
        content: none;
    }

    /* A cell the table already hides on small screens (`hidden lg:table-cell`)
       stays hidden; the display:block above would otherwise bring it back empty. */
    .responsive-table.responsive-table tbody tr > .hidden {
        display: none;
    }

    .responsive-table.responsive-table tbody tr > .hidden + :is(th, td) {
        border-top: 0;
    }

    /* Value colour of .sd-row dd. !important only to beat .text-gray-500 and its
       dark-mode override; the empty-state cell keeps its own colour. */
    .responsive-table.responsive-table tbody tr > :is(th, td):not(:only-child) {
        color: var(--text) !important;
    }

    .responsive-table tbody tr > :is(th, td)::before {
        content: attr(data-label);
        display: block;
        margin-bottom: .15rem;
        font-size: .75rem;
        font-weight: 500;
        color: var(--muted);
    }

    /* Row title (data-label="") and lone empty-state cells: no label. */
    .responsive-table tbody tr > [data-label=""]::before,
    .responsive-table tbody tr > :only-child::before {
        content: none;
    }

    /* Same cards for a `divide-y` <ul class="responsive-list"> (notice board):
       each <li> becomes a card like a stacked table row - its first child is the
       tinted header band, every later child is a line of its own with a divider
       above it. Outline, radius and spacing come from the card rule above. The
       empty state (red "No Records Yet!" line) stays plain. */
    .responsive-list.responsive-list > :is(li, div):not(.text-red-500) {
        margin-left: 1rem;
        margin-right: 1rem;
        padding: 0 !important;
        overflow: hidden;
        border-width: 1px !important;
        border-style: solid !important;
    }

    .responsive-list.responsive-list > :is(li, div):not(.text-red-500) > * {
        margin: 0 !important;
        padding: .6rem .9rem;
    }

    .responsive-list.responsive-list > :is(li, div):not(.text-red-500) > :first-child {
        background: var(--rt-head);
        align-items: center;
    }

    .responsive-list.responsive-list > :is(li, div):not(.text-red-500) > * + * {
        border-top: 1px solid var(--border);
    }

    /* A <div class="responsive-list"> (lecture review) already sits inside padded
       content and draws its own frame; on phones the frame goes so the cards stand
       apart, and the cards take the full width instead of the 1rem gutter. */
    div.responsive-list.responsive-list {
        border: 0 !important;
        border-radius: 0;
    }

    div.responsive-list.responsive-list > div:not(.text-red-500) {
        margin-left: 0 !important;
        margin-right: 0 !important;
    }

    div.responsive-list.responsive-list > div:not(.text-red-500):first-child {
        margin-top: 0;
    }

    @media (min-width: 640px) {
        .responsive-list.responsive-list > :is(li, div):not(.text-red-500) {
            margin-left: 1.5rem;
            margin-right: 1.5rem;
        }
    }
}

/* ============ END RESPONSIVE TABLE ==================================== */

/* ============ LOCKED SIDEBAR LINK ====================================
   A sidebar link with no page yet (sidebar-partials/group-link.blade.php).
   Muted, not clickable, lock icon; hover/focus shows data-tip above it. */
.sb-locked {
    position: relative;
    color: var(--muted);
    cursor: not-allowed;
    user-select: none;
}

/* Same indent as the submenu links (dark-mode.css only targets a/button). */
#sidebar-nav [x-show^="isExpanded"] .sb-locked {
    padding-left: 1.375rem;
    font-size: 13px;
    white-space: normal;
}

#sidebar-nav [x-show^="isExpanded"] [x-show^="isExpanded"] .sb-locked {
    padding-left: .8125rem;
}

.sb-lock {
    opacity: .7;
}

.sb-locked::after {
    content: attr(data-tip);
    position: absolute;
    left: .5rem;
    bottom: calc(100% + 6px);
    z-index: 50;
    width: max-content;
    max-width: 14rem;
    padding: .45rem .65rem;
    text-align: left;
    white-space: normal;
    font-size: .75rem;
    font-weight: 500;
    line-height: 1.4;
    color: #fff;
    background-color: #1f2937;
    border-radius: .375rem;
    box-shadow: 0 4px 12px rgba(15, 23, 42, .18);
    opacity: 0;
    visibility: hidden;
    transform: translateY(4px);
    transition: opacity .15s ease, transform .15s ease, visibility .15s;
    pointer-events: none;
}

.sb-locked:hover::after,
.sb-locked:focus-visible::after {
    opacity: 1;
    visibility: visible;
    transform: none;
}

.sb-locked:focus-visible {
    outline: 2px solid #6366f1;
    outline-offset: -2px;
}

html.dark .sb-locked::after,
html.dark-ams .sb-locked::after,
html.dark-ums .sb-locked::after {
    color: var(--text-bright);
    background-color: var(--elevated);
    border: 1px solid var(--card-border);
    box-shadow: 0 4px 12px rgba(0, 0, 0, .5);
}

/* Light theme: give every outer app card (`bg-white`/`bg-gray-50` + `shadow`, or `shadow sm:rounded-md`) the same
   hairline + soft shadow as .sd-card. Drawn as a ring inside box-shadow, not a border,
   so no card changes size. Cards nested in another .shadow keep Tailwind's shadow;
   dark themes style cards in dark-mode.css. */
html:not(.dark):not(.dark-ams):not(.dark-ums) :is(div.bg-white.shadow, div.bg-gray-50.shadow, div.shadow.sm\:rounded-md):not(.shadow .shadow) {
    box-shadow: 0 0 0 1px var(--border), 0 1px 3px rgba(15, 23, 42, .06), 0 1px 2px rgba(15, 23, 42, .04);
}

/* Sidebar menu search (include/sidebar-search + script in include/sidebar). While a search is
   active every group is shown open and anything that does not match is hidden; clearing the
   search drops .sb-searching, so groups fall back to their own Alpine open/closed state. */
.sb-searching .sb-miss {
    display: none !important;
}

/* Descendant, not child: nested sub-groups wrap their x-show panel in an extra <div>. */
.sb-searching [x-data] [x-show] {
    display: block !important;
}

.sb-search-input {
    padding-left: 2.25rem;
    padding-right: 3.75rem; /* room for the Ctrl K hint */
}

/* No focus ring or tap flash when a button/link is clicked or tapped (e.g. the phone
   "open sidebar" button); keyboard (Tab) focus still shows it. Only the ring vars are
   reset, so a button's own shadow stays. !important beats the dark-mode ring rules. */
:is(button, a, [role="button"]) {
    -webkit-tap-highlight-color: transparent;
}

:is(button, a, [role="button"]):focus:not(:focus-visible) {
    outline: none !important;
    --tw-ring-offset-shadow: 0 0 #0000 !important;
    --tw-ring-shadow: 0 0 #0000 !important;
}
/* ============ LECTURE SCHEDULE COURSE COLOURS ==========================
   One colour per course code, so the same course looks the same on the
   generated timetable and on the printed reports. Kept here rather than in
   either blade: both pages pick the class the same way (crc32 of the code),
   and dark-mode.css re-tints these twelve in one place. */
.ls-c0 {
    background: #eef2ff;
    color: #3730a3
}

.ls-c1 {
    background: #ecfdf5;
    color: #065f46
}

.ls-c2 {
    background: #fef3c7;
    color: #92400e
}

.ls-c3 {
    background: #fee2e2;
    color: #991b1b
}

.ls-c4 {
    background: #e0f2fe;
    color: #075985
}

.ls-c5 {
    background: #f3e8ff;
    color: #6b21a8
}

.ls-c6 {
    background: #fce7f3;
    color: #9d174d
}

.ls-c7 {
    background: #ecfeff;
    color: #155e75
}

.ls-c8 {
    background: #f7fee7;
    color: #3f6212
}

.ls-c9 {
    background: #fff7ed;
    color: #9a3412
}

.ls-c10 {
    background: #f1f5f9;
    color: #334155
}

.ls-c11 {
    background: #fdf4ff;
    color: #86198f
}

/* ============ END LECTURE SCHEDULE COURSE COLOURS ====================== */

/* ============ LECTURE TIMETABLE REPORT CHIPS ===========================
   The grid the reports tab, the print page and a teacher's own routine all
   draw (include/lecture-schedule-timetable-grids.blade.php). Layout only:
   the fill and the text colour come from the .ls-c0 - .ls-c11 course colours
   above, so a course looks the same on every one of them and in dark mode. */
.tr-chip {
    display: block;
    border-radius: .25rem;
    padding: .125rem .25rem;
    font-size: 10px;
    line-height: 1.3;
}

.tr-chip + .tr-chip {
    margin-top: .125rem;
}

/* The slot times, under a lecture heading and inside a break or free cell. */
.tr-time {
    font-size: 10px;
    line-height: 1.3;
}

/* ============ END LECTURE TIMETABLE REPORT CHIPS ======================= */

/* Light-mode cards: Tailwind's `shadow` / `shadow-md` alone gives a soft blur with
   no edge, and nested cards stack it. Match the login card instead — a 1px
   gray-200 outline plus shadow-sm — drawn as a ring so nothing shifts by a pixel.
   Inner cards keep only the hairline. Positioned panels (dropdowns, modals) and
   shadow-lg/xl are left alone: they genuinely float. Dark mode has its own rules
   in dark-mode.css. */
html:not(.dark) div.bg-white:is(.shadow, .shadow-md):not(.absolute):not(.fixed) {
    box-shadow: 0 0 0 1px #e5e7eb, 0 1px 2px 0 rgb(0 0 0 / 0.05) !important;
}

html:not(.dark) div:is(.shadow, .shadow-md) div.bg-white:is(.shadow, .shadow-md):not(.absolute):not(.fixed) {
    box-shadow: 0 0 0 1px #e5e7eb !important;
}

/* Tables inside a card sit flush: square any rounded wrapper (or the table itself) nested in an
   outer .shadow card, so the thead corners are not clipped round. The outer card keeps its radius. */
.shadow :is(.rounded, .rounded-md, .rounded-lg, .sm\:rounded-md, .sm\:rounded-lg, .md\:rounded-lg):has(thead),
thead, thead tr, thead th {
    border-radius: 0;
}

/* Table headers, every theme: exactly one 1px line above and below each header cell. This replaces
   the lines that used to stack there (divide-y on the tbody's top edge, tr borders, per-th border
   utilities); multi-row headers collapse to one line between rows. --thead-border is redefined for
   the dark shells in dark-mode.css. */
:root {
    --thead-border: #e5e7eb;
}

thead th {
    border-top: 1px solid var(--thead-border) !important;
    border-bottom: 1px solid var(--thead-border) !important;
}

/* A header that asks for black borders (bordered print-style tables, e.g. the
   admission student-details form) keeps them, matching its body cells */
thead th.border-black {
    border-top-color: #000 !important;
    border-bottom-color: #000 !important;
}

table > thead + tbody,
table > thead > tr {
    border-top-width: 0 !important;
    border-bottom-width: 0 !important;
}

/* A table's own wrapper inside a card (`overflow-hidden shadow ring-1 ...`, `rounded-lg`, …) drew a
   ring/drop shadow right on top of that line; in dark mode several card rules (`div.rounded-lg:has(> div)`,
   `form div.shadow`, `.shadow-*:not(input)…`) re-add a 1px ring there. The card already frames the
   table, so drop it. :not(#\#) only lifts specificity above every one of those dark !important rules.
   The second selector covers ring/shadow wrappers further out (`ring-1 … > div > div > table`,
   admission/remarks-list), which otherwise stacked their 1px ring on the thead's top line. */
:is(.shadow, .shadow-sm, .shadow-md, .shadow-lg, .shadow-xl) div:has(> table):not(#\#),
:is(.shadow, .shadow-sm, .shadow-md, .shadow-lg, .shadow-xl) div:is(.ring-1, .shadow, .shadow-sm, .shadow-md, .shadow-lg):has(table):not(#\#) {
    box-shadow: none !important;
}

/* Scrollbars, every theme: transparent track, so a table's horizontal scrollbar (and any other)
   sits on the card instead of a grey slab. Thumb uses the dark shells' --scrollbar when set.
   Zero specificity: anything that sets its own scrollbar-color (sidebar, html.dark *) still wins. */
* {
    scrollbar-width: thin;
    scrollbar-color: var(--scrollbar, #a8b4c4) transparent;
}

/* Horizontal table scrollbars, every theme: inside a card the scroller's negative margins
   (`-mx-* sm:-mx-6 lg:-mx-8`, offset by `md:px-6 lg:px-8` on its child) pushed it past the card
   edge, and the card's overflow-hidden clipped both ends of the scrollbar. Keep it inside. */
div.shadow div.overflow-x-auto:is(.-mx-4, .-mx-6, .sm\:-mx-6, .lg\:-mx-8) {
    margin-left: 0 !important;
    margin-right: 0 !important;
}

/* The padded child can also sit one level down, inside a <form> (admission/collect-fee). */
div.shadow div.overflow-x-auto:is(.-mx-4, .-mx-6, .sm\:-mx-6, .lg\:-mx-8) > div,
div.shadow div.overflow-x-auto:is(.-mx-4, .-mx-6, .sm\:-mx-6, .lg\:-mx-8) > form > div {
    padding-left: 0 !important;
    padding-right: 0 !important;
}

/* A table wrapper with its own top border (`border-t`, `border`, or one handed down by a parent's
   divide-y) stacked it on the thead's 1px line, so the header showed a double line. The thead line
   is the top edge now. Also when the border sits a few first-child wrappers further out
   (`flex flex-col border-t > overflow-x-auto > inline-block > overflow-hidden > table`, event
   Fined Students); a padded one keeps its line, there is a gap between the two. */
div:has(> table > thead),
div:not([class*="pt-"]):not([class*="py-"]):not([class*=" p-"]):has(> :first-child > table:first-child > thead, > :first-child > :first-child > table:first-child > thead, > :first-child > :first-child > :first-child > table:first-child > thead) {
    border-top-width: 0 !important;
}

/* Form/pagination footers (`px-4 py-3 text-right bg-gray-50 ... border-t`): 1px top line in every
   theme, a touch softer than the table header line. */
:root {
    --footer-border: #eceef1;
}

html:is(.dark, .dark-ams, .dark-ums) {
    --footer-border: #323a48;
}

div.bg-gray-50.text-right.border-t {
    border-top: 1px solid var(--footer-border) !important;
}

/* ============ ALERTS (include/error-template) ==========================
   One component for the error/success toasts (pinned top-right) and the inline
   cards in the form. Same anatomy everywhere: hue icon, title, message, close.
   - Card:  soft hue tint + 1px hue edge, flat (it sits inside the form).
   - Toast: solid surface + the same 1px ring (and, in light, faint shadow) as a card
            (opaque, since it floats over live content).
   All colours are tokens below; the dark shells only redefine the tokens. Edges are
   inset box-shadows, not borders, so no global border-color rule can repaint them.
   No Tailwind colour classes in the markup, so dark-mode.css's bg-red-50 /
   bg-green-50 alert overrides never touch it. */
:root {
    --ux-err: #dc2626;
    --ux-err-title: #991b1b;
    --ux-err-text: #b91c1c;
    --ux-err-tint: #fef2f2;
    --ux-err-edge: #fecaca;
    --ux-ok: #16a34a;
    --ux-ok-title: #166534;
    --ux-ok-text: #15803d;
    --ux-ok-tint: #f0fdf4;
    --ux-ok-edge: #bbf7d0;
    --ux-toast-bg: #ffffff;
    --ux-toast-edge: var(--border, #e5e7eb);
    --ux-toast-text: #4b5563;
    --ux-toast-shadow: 0 1px 3px rgba(15, 23, 42, .06), 0 1px 2px rgba(15, 23, 42, .04);
    --ux-close: #9ca3af;
    --ux-close-hover: #374151;
    --ux-close-hover-bg: rgba(15, 23, 42, .06);
}

html:is(.dark, .dark-ams, .dark-ums) {
    --ux-err: #f87171;
    --ux-err-title: #fecaca;
    --ux-err-text: #fca5a5;
    --ux-err-tint: rgba(239, 68, 68, .10);
    --ux-err-edge: rgba(248, 113, 113, .30);
    --ux-ok: #4ade80;
    --ux-ok-title: #bbf7d0;
    --ux-ok-text: #86efac;
    --ux-ok-tint: rgba(34, 197, 94, .10);
    --ux-ok-edge: rgba(74, 222, 128, .28);
    --ux-toast-bg: #1c212b;
    --ux-toast-edge: var(--border);
    --ux-toast-text: #c3cad5;
    --ux-toast-shadow: 0 0 #0000;
    --ux-close: #7c8696;
    --ux-close-hover: #e5e7eb;
    --ux-close-hover-bg: rgba(255, 255, 255, .08);
}

/* Toast stack: top-right from sm up, full width (16px gutter) on phones. Clicks pass
   through the empty area to the page; only the toasts themselves take them. */
.ux-toasts {
    position: fixed;
    inset: 0 0 auto 0;
    z-index: 50;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .75rem;
    padding: 1rem;
    pointer-events: none;
}

@media (min-width: 640px) {
    .ux-toasts {
        align-items: flex-end;
        padding: 1.5rem;
    }
}

.ux-toasts > div {
    width: 100%;
    max-width: 24rem;
}

.ux-alert {
    --a: var(--ux-err);
    --t: var(--ux-err-title);
    --x: var(--ux-err-text);
    --tint: var(--ux-err-tint);
    --edge: var(--ux-err-edge);
    position: relative;
    display: flex;
    align-items: flex-start;
    gap: .75rem;
    padding: .875rem 1rem;
    border-radius: .5rem;
    font-size: .875rem;
    line-height: 1.25rem;
    text-align: left;
}

.ux-alert.ux-alert--success {
    --a: var(--ux-ok);
    --t: var(--ux-ok-title);
    --x: var(--ux-ok-text);
    --tint: var(--ux-ok-tint);
    --edge: var(--ux-ok-edge);
}

.ux-alert.ux-alert--card {
    margin-bottom: 1rem;
    background: var(--tint) !important;
    box-shadow: inset 0 0 0 1px var(--edge) !important;
}

.ux-alert.ux-alert--toast {
    --x: var(--ux-toast-text);
    pointer-events: auto;
    background: var(--ux-toast-bg) !important;
    box-shadow: 0 0 0 1px var(--ux-toast-edge), var(--ux-toast-shadow) !important;
}


.ux-alert .ux-alert__icon {
    flex-shrink: 0;
    width: 1.25rem;
    height: 1.25rem;
    color: var(--a) !important;
}

.ux-alert .ux-alert__body {
    flex: 1 1 0%;
    min-width: 0;
    overflow-wrap: anywhere;
}

.ux-alert .ux-alert__title {
    font-weight: 600;
    color: var(--t) !important;
}

.ux-alert .ux-alert__text,
.ux-alert .ux-alert__list {
    color: var(--x) !important;
}

.ux-alert .ux-alert__title + :is(.ux-alert__text, .ux-alert__list),
.ux-alert .ux-alert__text + .ux-alert__list {
    margin-top: .25rem;
}

.ux-alert .ux-alert__text--strong {
    font-weight: 500;
    color: var(--t) !important;
}

.ux-alert .ux-alert__list {
    padding-left: 1.125rem;
    list-style: disc;
}

.ux-alert .ux-alert__list li + li {
    margin-top: .125rem;
}

.ux-alert .ux-alert__list li::marker {
    color: var(--a);
}

/* !important + two classes: beats `html.dark button { color: … !important }`. */
.ux-alert .ux-alert__close {
    flex-shrink: 0;
    display: inline-flex;
    margin: -.25rem -.375rem -.25rem 0;
    padding: .25rem;
    border-radius: .375rem;
    color: var(--ux-close) !important;
    background: transparent !important;
    box-shadow: none !important;
    transition: color .15s, background-color .15s;
}

.ux-alert .ux-alert__close:hover {
    color: var(--ux-close-hover) !important;
    background: var(--ux-close-hover-bg) !important;
}

.ux-alert .ux-alert__close:focus-visible {
    outline: 2px solid var(--a);
    outline-offset: 1px;
}

.ux-alert .ux-alert__close svg {
    width: 1.125rem;
    height: 1.125rem;
    color: inherit !important;
}

/* Boxes nested in a card's content area (`-mt-2 overflow-x-auto … > overflow-hidden shadow ring-1 >
   shadow sm:rounded-md`, the standard form/table wrapper on ~600 views) drew a second rounded,
   shadowed frame inside the card. Only the card keeps a frame. Positioned layers (dropdowns,
   popups, modals: .absolute/.fixed and anything inside them) are left alone.
   :not(#\#) lifts specificity over dark-mode.css's card ring rules. */
:is(.shadow, .shadow-sm, .shadow-md, .shadow-lg, .shadow-xl) div.overflow-x-auto div:is(.shadow, .shadow-sm, .shadow-md, .ring-1):not(.absolute):not(.fixed):not(:is(.absolute, .fixed) *):not(#\#) {
    box-shadow: none !important;
    border-radius: 0 !important;
}

/* ...but that ring's top edge was the line under the card header ("Search Filters"). Keep just
   that edge on the outermost box (also when a <form> wraps it). Boxes that open with a table (also
   when it sits a few first-child wrappers down: collect-fee Slab Applied, remarks-list) are
   skipped, their thead already draws one; a table with no thead (Selected Student For
   Admission) keeps the line; a table below filters still gets the line. */
:is(.shadow, .shadow-sm, .shadow-md, .shadow-lg, .shadow-xl) :is(div.overflow-x-auto > div, div.overflow-x-auto > div > form) > div:is(.shadow, .shadow-sm, .shadow-md, .ring-1):not(:has(> table:first-child > thead, > :first-child > table:first-child > thead, > :first-child > :first-child > table:first-child > thead, > :first-child > :first-child > :first-child > table:first-child > thead)):not(.absolute):not(.fixed):not(:is(.absolute, .fixed) *):not(#\#) {
    box-shadow: 0 -1px 0 var(--border, #e5e7eb) !important;
}

/* Card headers: one height everywhere, the Incomplete Admissions one (pt-3 card, 40px title row,
   12px down to the content line). Views add mb-3 to the row, mt-5/mt-6 to the next block or h-12
   to the title, which made some headers taller. Only the title row at the top of a pt-3 card is
   touched (directly, inside its px-4 wrapper, one more wrapper down (Struck Off Detail), a flex row that pairs it with
   a button (library categories: Add Category), or inside the card's <form>). A flex row with its
   own py-* (Activity: `px-4 py-4 flex justify-between`) is a padded header bar and is left alone,
   else these margins stacked on its padding. */
:is(:is(.pt-3, .pt-6, .bg-white:not([class*="pt-"]):not([class*="py-"]):not([class*=" p-"])):is(.shadow, .shadow-sm), :is(.pt-3, .pt-6, .bg-white:not([class*="pt-"]):not([class*="py-"]):not([class*=" p-"])):is(.shadow, .shadow-sm) > form) > :is(
    .items-center.h-10:has(> :is(h1, h2, h3), > div > :is(h1, h2, h3)),
    div:has(> .items-center.h-10:only-child > :is(h1, h2, h3), > .items-center.h-10:only-child > div > :is(h1, h2, h3), > div:only-child > .items-center.h-10:only-child > :is(h1, h2, h3)),
    div.flex.justify-between:not([class*="py-"]):has(> .items-center.h-10:first-child > :is(h1, h2, h3))
) {
    margin-bottom: 0 !important;
}

:is(:is(.pt-3, .pt-6, .bg-white:not([class*="pt-"]):not([class*="py-"]):not([class*=" p-"])):is(.shadow, .shadow-sm), :is(.pt-3, .pt-6, .bg-white:not([class*="pt-"]):not([class*="py-"]):not([class*=" p-"])):is(.shadow, .shadow-sm) > form) > div > .items-center.h-10:only-child,
:is(:is(.pt-3, .pt-6, .bg-white:not([class*="pt-"]):not([class*="py-"]):not([class*=" p-"])):is(.shadow, .shadow-sm), :is(.pt-3, .pt-6, .bg-white:not([class*="pt-"]):not([class*="py-"]):not([class*=" p-"])):is(.shadow, .shadow-sm) > form) > div > div:only-child > .items-center.h-10:only-child {
    margin-bottom: 0 !important;
}

:is(:is(.pt-3, .pt-6, .bg-white:not([class*="pt-"]):not([class*="py-"]):not([class*=" p-"])):is(.shadow, .shadow-sm), :is(.pt-3, .pt-6, .bg-white:not([class*="pt-"]):not([class*="py-"]):not([class*=" p-"])):is(.shadow, .shadow-sm) > form) > :is(
    .items-center.h-10:has(> :is(h1, h2, h3), > div > :is(h1, h2, h3)),
    div:has(> .items-center.h-10:only-child > :is(h1, h2, h3), > .items-center.h-10:only-child > div > :is(h1, h2, h3), > div:only-child > .items-center.h-10:only-child > :is(h1, h2, h3)),
    div.flex.justify-between:not([class*="py-"]):has(> .items-center.h-10:first-child > :is(h1, h2, h3))
) + :is(div, form) {
    margin-top: .75rem !important;
}

/* ...and when that next block is a <form>, its own first box no longer adds a gap on top. */
:is(:is(.pt-3, .pt-6, .bg-white:not([class*="pt-"]):not([class*="py-"]):not([class*=" p-"])):is(.shadow, .shadow-sm), :is(.pt-3, .pt-6, .bg-white:not([class*="pt-"]):not([class*="py-"]):not([class*=" p-"])):is(.shadow, .shadow-sm) > form) > :is(
    .items-center.h-10:has(> :is(h1, h2, h3), > div > :is(h1, h2, h3)),
    div:has(> .items-center.h-10:only-child > :is(h1, h2, h3), > .items-center.h-10:only-child > div > :is(h1, h2, h3), > div:only-child > .items-center.h-10:only-child > :is(h1, h2, h3)),
    div.flex.justify-between:not([class*="py-"]):has(> .items-center.h-10:first-child > :is(h1, h2, h3))
) + form > div:first-child {
    margin-top: 0 !important;
}

.items-center.h-10 > :is(h1, h2, h3).h-12 {
    height: auto;
}

/* Header titles: same type everywhere, the Incomplete Admissions one (text-lg, leading-6,
   font-medium). ~100 views use font-semibold, some drop leading-6 or add pt-1/pt-2/py-2, which
   made those headers look bigger (and -mt-1 on a title, e.g. Old Transport Policies, pulled it off centre). Small-on-mobile titles (text-sm, e.g. the admission form logo
   header) are left alone. */
.items-center.h-10 > :is(h1, h2, h3):not(.text-sm),
.items-center.h-10 > div > :is(h1, h2, h3):not(.text-sm) {
    font-size: 1.125rem;
    line-height: 1.5rem;
    font-weight: 500;
    margin-top: 0;
    margin-bottom: 0;
    padding-top: 0;
    padding-bottom: 0;
}

/* Same header for cards whose title is a full-width table cell ("Summer Camp Fee", "Student
   Detail", "Readmission"): they used font-semibold + text-lg's 28px line + py-5, i.e. a heavier
   header the condensed-table padding (`table :is(th, td)`, !important) squashed to a normal
   row's height. 20 + 24 + 20 = 64px, like the card headers above. */
table :is(td, th)[colspan]:is(.text-lg, .text-xl) {
    font-size: 1.125rem;
    line-height: 1.5rem;
    font-weight: 500;
    padding-top: 1.25rem !important;
    padding-bottom: 1.25rem !important;
}

/* Cards: one corner radius everywhere, the standard card's sm:rounded-md (.375rem). Some views
   use rounded-lg / md:rounded-lg / rounded-xl (Summer Camp Fee, report-list tiles...). A rounded table
   inside such a card follows, so its corners sit flush with the card; only its top corners when
   a footer comes after it (else the last row shows rounded notches above the footer), and the
   footer's rounded-b*-lg corners follow the card too. Boxes
   nested inside a card keep the flat corners set above (that rule out-ranks this one), and
   dropdowns / modals (.absolute, .fixed and anything inside them) are left alone. */
div:is(.bg-white, .ring-1):is(.shadow, .shadow-sm, .shadow-md, .shadow-lg, .shadow-xl)[class*="rounded"]:not([class*="rounded-full"]):not(.absolute):not(.fixed):not(:is(.absolute, .fixed) *),
div[class*="shadow"][class*="rounded"] > table:is([class*="rounded-lg"], [class*="rounded-xl"]) {
    border-radius: .375rem !important;
}

div[class*="shadow"][class*="rounded"] > table:is([class*="rounded-lg"], [class*="rounded-xl"]):not(:last-child) {
    border-bottom-left-radius: 0 !important;
    border-bottom-right-radius: 0 !important;
}

div[class*="shadow"][class*="rounded"] > div:last-child:is([class*="rounded-bl-lg"], [class*="rounded-br-lg"], [class*="rounded-b-lg"]) {
    border-bottom-left-radius: .375rem !important;
    border-bottom-right-radius: .375rem !important;
}

/* A table that opens a card with no top padding (collect-fee Slab Applied / Fee Title: every
   wrapper between the card and the table is a first child, and their mt-2 / -my-2 cancel out)
   puts its thead line right against the card's own 1px outline, which reads as a double line.
   The card's outline is the top edge there. */
div.bg-white:is(.shadow, .shadow-md):not([class*="pt-"]):not([class*="py-"]):not([class*="p-"]) table:first-child:not(div.bg-white:is(.shadow, .shadow-md) :not(:first-child) *) > thead:first-child > tr:first-child > th {
    border-top-width: 0 !important;
}

/* sd-card (student profile tabs): .sd-card-head already draws the line under the title, so a
   table placed right under it (directly or in its overflow-x-auto wrapper), also past an
   error-template wrapper (zero height, its toasts are fixed; Student Character Remarks), skips its thead top
   line, which otherwise doubled it (Student Of The Year Categories). */
:is(.sd-card-head, .sd-card-head + div:has(.ux-toasts)) + table > thead:first-child > tr:first-child > th,
:is(.sd-card-head, .sd-card-head + div:has(.ux-toasts)) + div > table:first-child > thead:first-child > tr:first-child > th,
:is(.sd-card-head, .sd-card-head + div:has(.ux-toasts)) + div > div:first-child > table:first-child > thead:first-child > tr:first-child > th {
    border-top-width: 0 !important;
}

/* Collapsible cards (x-show body after the title row): the header rule above drops the row's
   mb-3, so a closed card whose markup has no `open ? '' : 'pb-3'` toggle (Old Transport Policies)
   sat the title on the bottom edge. Give the row back 12px while the body is hidden. */
:is(:is(.pt-3, .pt-6, .bg-white:not([class*="pt-"]):not([class*="py-"]):not([class*=" p-"])):is(.shadow, .shadow-sm), :is(.pt-3, .pt-6, .bg-white:not([class*="pt-"]):not([class*="py-"]):not([class*=" p-"])):is(.shadow, .shadow-sm) > form):not(.pb-3) > :is(
    .items-center.h-10:has(> :is(h1, h2, h3), > div > :is(h1, h2, h3)),
    div:has(> .items-center.h-10:only-child > :is(h1, h2, h3), > .items-center.h-10:only-child > div > :is(h1, h2, h3), > div:only-child > .items-center.h-10:only-child > :is(h1, h2, h3)),
    div.flex.justify-between:not([class*="py-"]):has(> .items-center.h-10:first-child > :is(h1, h2, h3))
):has(+ [style*="display: none"]) {
    margin-bottom: .75rem !important;
}

/* An empty divider (`<div class="mt-3 shadow border-t"></div>`) right above a table drew its
   border + shadow on top of the thead's own line: double line (admission/security-fee). Keep its
   spacing, drop the line; the thead line is the edge. */
div.border-t:empty:has(+ table, + form > table:first-child) {
    border-top-width: 0 !important;
    box-shadow: none !important;
}

/* pt-6 cards (~70 views, Select Options on the reports) carried 24px above the title row instead
   of the standard 12px; the header rules above take them in too (`:is(.pt-3, .pt-6)`). */
div.pt-6:is(.shadow, .shadow-sm):has(> .items-center.h-10 > :is(h1, h2, h3), > div > .items-center.h-10 > :is(h1, h2, h3), > div > div:only-child > .items-center.h-10 > :is(h1, h2, h3), > .sm\:flex.sm\:items-center > .sm\:flex-auto > h1) {
    padding-top: .75rem !important;
}

/* Report result cards (36 views: `sm:flex sm:items-center > sm:flex-auto > h1.text-xl.font-semibold.pl-5`,
   then `mt-5 flex flex-col`): no fixed row height, a bigger/bolder title and a 20px indent.
   Same 40px row, title type, 24px (sm:px-6) indent and 12px gap as the other card headers. */
:is(.pt-3, .pt-6, .bg-white:not([class*="pt-"]):not([class*="py-"]):not([class*=" p-"])):is(.shadow, .shadow-sm) > .sm\:flex.sm\:items-center:has(> .sm\:flex-auto > h1) {
    display: flex;
    align-items: center;
    min-height: 2.5rem;
}

:is(.pt-3, .pt-6, .bg-white:not([class*="pt-"]):not([class*="py-"]):not([class*=" p-"])):is(.shadow, .shadow-sm) > .sm\:flex.sm\:items-center > .sm\:flex-auto > h1 {
    font-size: 1.125rem;
    line-height: 1.5rem;
    font-weight: 500;
    padding-left: 1rem;
}

@media (min-width: 640px) {
    :is(.pt-3, .pt-6, .bg-white:not([class*="pt-"]):not([class*="py-"]):not([class*=" p-"])):is(.shadow, .shadow-sm) > .sm\:flex.sm\:items-center > .sm\:flex-auto > h1 {
        padding-left: 1.5rem;
    }
}

:is(.pt-3, .pt-6, .bg-white:not([class*="pt-"]):not([class*="py-"]):not([class*=" p-"])):is(.shadow, .shadow-sm) > .sm\:flex.sm\:items-center:has(> .sm\:flex-auto > h1) + :is(div, form) {
    margin-top: .75rem !important;
}

/* The error-template's wrapper at the top of a card (`px-4 pb-2`, `px-4 py-6 …`) added its
   padding above the title even with no message showing (toasts are fixed; only the inline
   .ux-alert--card takes room). Fee policy: Add Policies. */
:is(.pt-3, .pt-6, .bg-white:not([class*="pt-"]):not([class*="py-"]):not([class*=" p-"])):is(.shadow, .shadow-sm) > div:has(> div > .ux-toasts):not(:has(.ux-alert--card)) {
    padding-top: 0 !important;
    padding-bottom: 0 !important;
}

/* A bare title at the top of a card, with no 40px title row (`px-4 > [col-span >] h3.text-lg`,
   Fee Discount Policy): same 40px row and 12px gap as the other card headers. A title that
   already sits in a 40px row is not bare (Profit & Loss / library charts: re-centring their
   padded `h-16 pt-3` bar pushed the title down). */
:is(.pt-3, .pt-6, .bg-white:not([class*="pt-"]):not([class*="py-"]):not([class*=" p-"])):is(.shadow, .shadow-sm) > div:has(> :is(h1, h2, h3).text-lg:only-child, > div:only-child:not(.h-10) > :is(h1, h2, h3).text-lg:only-child) {
    display: flex;
    align-items: center;
    min-height: 2.5rem;
    margin-bottom: 0 !important;
}

:is(.pt-3, .pt-6, .bg-white:not([class*="pt-"]):not([class*="py-"]):not([class*=" p-"])):is(.shadow, .shadow-sm) > div:has(> :is(h1, h2, h3).text-lg:only-child, > div:only-child:not(.h-10) > :is(h1, h2, h3).text-lg:only-child) + :is(div, form) {
    margin-top: .75rem !important;
}

:is(.pt-3, .pt-6, .bg-white:not([class*="pt-"]):not([class*="py-"]):not([class*=" p-"])):is(.shadow, .shadow-sm) > div > :is(h1, h2, h3).text-lg:only-child,
:is(.pt-3, .pt-6, .bg-white:not([class*="pt-"]):not([class*="py-"]):not([class*=" p-"])):is(.shadow, .shadow-sm) > div > div:only-child:not(.h-10) > :is(h1, h2, h3).text-lg:only-child {
    font-size: 1.125rem;
    line-height: 1.5rem;
    font-weight: 500;
    margin: 0;
}

div.pt-6:is(.shadow, .shadow-sm):has(> div > :is(h1, h2, h3).text-lg:only-child, > div > div:only-child:not(.h-10) > :is(h1, h2, h3).text-lg:only-child) {
    padding-top: .75rem !important;
}

/* "Back to list" button beside page titles (`a.p-3.bg-gray-200.border-2.border-gray-400` in the
   h3 of ~104 report/list pages): a heavy grey 48px box with a 2px dark border that overflowed the
   40px title row. Same look as the card collapse toggle: 36px, white, 1px border, soft shadow. */
a.p-3.bg-gray-200.border-2.rounded-md.border-gray-400.cursor-pointer {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 2.25rem;
    height: 2.25rem;
    padding: 0;
    color: #6b7280;
    background-color: #fff;
    border: 1px solid #d1d5db;
    border-radius: .375rem;
    box-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);
    transition: color .15s, background-color .15s, border-color .15s;
}

a.p-3.bg-gray-200.border-2.rounded-md.border-gray-400.cursor-pointer:hover {
    color: #374151;
    background-color: #f9fafb;
}

a.p-3.bg-gray-200.border-2.rounded-md.border-gray-400.cursor-pointer:focus-visible {
    outline: 2px solid #6366f1;
    outline-offset: 2px;
}

a.p-3.bg-gray-200.border-2.rounded-md.border-gray-400.cursor-pointer svg {
    width: 1rem;
    height: 1rem;
}

a.p-3.bg-gray-200.border-2.rounded-md.border-gray-400.cursor-pointer + span.ml-4 {
    margin-left: .75rem;
}

/* !important: dark-mode.css paints every .bg-gray-200 (and its hover:bg-gray-300) with !important. */
html:is(.dark, .dark-ams, .dark-ums) a.p-3.bg-gray-200.border-2.rounded-md.border-gray-400.cursor-pointer {
    color: var(--muted) !important;
    background: var(--card) !important;
    border-color: var(--border) !important;
}

html:is(.dark, .dark-ams, .dark-ums) a.p-3.bg-gray-200.border-2.rounded-md.border-gray-400.cursor-pointer:hover {
    color: var(--text-bright, var(--text)) !important;
    background: var(--hover) !important;
}

/* `html.dark svg` colours every icon directly; let the arrow follow the button (and its hover). */
html:is(.dark, .dark-ams, .dark-ums) a.p-3.bg-gray-200.border-2.rounded-md.border-gray-400.cursor-pointer svg {
    color: inherit !important;
}

/* ...and its wrapper: the views wrap that title row in `pb-5` / `pb-2` / `pb-3` / `py-2` / `mb-5`
   (or nothing), so the space down to the first card varied from 20px to 40px. The card's own
   mt-5 (20px) is the gap everywhere now. */
div:is(.pb-2, .pb-3, .pb-5, .py-2, .mb-5):has(> .items-center.h-10 > h3 > a.p-3.bg-gray-200.border-2) {
    padding-top: 0 !important;
    padding-bottom: 0 !important;
    margin-bottom: 0 !important;
}

/* ...a card that opens the component with no mt-* of its own (Paper Marking Amount Payroll Wise,
   API Logs, Closing Balances) sat right under the title row; give it that same 20px. */
div:has(> .items-center.h-10 > h3 > a.p-3.bg-gray-200.border-2) + div > div:first-child:is(.shadow, .shadow-sm):not([class*="mt-"]) {
    margin-top: 1.25rem;
}

/* ===== Reports page (teacher-admin/report-list): sitemap-style index =====================
   15 category cards, ~127 links. Masonry columns (no equal-height gaps); each card is a tight
   block: small uppercase label trailed by a hairline, then plain 13px links at ~22px a row that
   underline on hover. Scoped to the .list-group cards, used only on this page. */
div.grid:has(> div > div > div > ol.list-group) {
    display: block;
    columns: 15rem;
    column-gap: .75rem;
}

div.grid > div.flex.justify-center:has(> div > div > ol.list-group) {
    display: block;
    break-inside: avoid;
    margin-bottom: .75rem;
}

div.bg-white.shadow-md:has(> div > ol.list-group) {
    max-width: none;
    padding: .625rem .875rem .75rem;
}

div.bg-white.shadow-md:has(> div > ol.list-group) > div:first-child {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: 0 0 .375rem;
    font-size: .75rem;
    line-height: 1rem;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: #4338ca;
    border-bottom: 0;
}

/* Section label followed by a hairline that runs to the card edge. */
div.bg-white.shadow-md:has(> div > ol.list-group) > div:first-child::after {
    content: "";
    flex: 1;
    height: 1px;
    background-color: var(--border, #e5e7eb);
}

div.bg-white.shadow-md > div:has(> ol.list-group) {
    padding: 0;
}

ol.list-group {
    list-style: none;
    margin: 0;
    padding: 0;
    counter-reset: report;
}

ol.list-group > li.list-group-item {
    color: #4b5563;
}

ol.list-group > li.list-group-item > a {
    display: flex;
    gap: .5rem;
    padding: .125rem 0;
    font-size: .8125rem;
    line-height: 1.125rem;
    color: inherit;
}

/* Numbering (1, 2, 3 per section; only the reports the user can see are counted). */
ol.list-group > li.list-group-item > a::before {
    counter-increment: report;
    content: counter(report);
    flex: none;
    min-width: 1.125rem;
    font-size: .75rem;
    color: #9ca3af;
    font-variant-numeric: tabular-nums;
    text-align: right;
}

/* Arrow at the end of the row, slides in on hover. */
ol.list-group > li.list-group-item > a::after {
    content: "92";
    flex: none;
    margin-left: auto;
    padding-left: .5rem;
    opacity: 0;
    transform: translateX(-4px);
    transition: opacity .15s, transform .15s;
}

ol.list-group > li.list-group-item > a:hover::after,
ol.list-group > li.list-group-item > a:focus-visible::after {
    opacity: 1;
    transform: translateX(0);
}

/* Arrow at the end of the row, slides in on hover. */
ol.list-group > li.list-group-item > a::after {
    content: "\2192";
    flex: none;
    margin-left: auto;
    padding-left: .5rem;
    opacity: 0;
    transform: translateX(-4px);
    transition: opacity .15s, transform .15s;
}

ol.list-group > li.list-group-item > a:hover::after,
ol.list-group > li.list-group-item > a:focus-visible::after {
    opacity: 1;
    transform: translateX(0);
}

ol.list-group > li.list-group-item > a:hover {
    color: #4f46e5;
}

ol.list-group > li.list-group-item > a:focus-visible {
    outline: 2px solid #6366f1;
    outline-offset: 1px;
    border-radius: 2px;
}

/* Dark shells. !important: dark-mode.css paints li.text-blue-500.list-group-item with it. */
html:is(.dark, .dark-ams, .dark-ums) ol.list-group > li.list-group-item {
    color: var(--muted) !important;
}

html:is(.dark, .dark-ams, .dark-ums) ol.list-group > li.list-group-item > a:hover {
    color: var(--accent, #818cf8);
}

html:is(.dark, .dark-ams, .dark-ums) ol.list-group > li.list-group-item > a::before {
    color: var(--muted);
    opacity: .7;
}

html:is(.dark, .dark-ams, .dark-ums) div.bg-white.shadow-md:has(> div > ol.list-group) > div:first-child {
    color: var(--accent, #818cf8) !important;
}

html:is(.dark, .dark-ams, .dark-ums) div.bg-white.shadow-md:has(> div > ol.list-group) > div:first-child::after {
    background-color: var(--border);
}

/* Cards with no top padding (`bg-white shadow`, e.g. remarks-list "Update Remarks") spaced their
   header with margins instead: an empty messages wrapper (mt-5), the header wrapper (mt-5) and the
   table block (mt-5), ~100px. The header rules above take these cards in too; here the header
   gets the standard 12px above it, and an empty wrapper before it takes no room. A header bar with its own
   top padding (`px-4 h-16 pt-3 border-b`, library dashboard chart) already has its spacing. */
:is(.bg-white:not([class*="pt-"]):not([class*="py-"]):not([class*=" p-"])):is(.shadow, .shadow-sm) > div:not(:has(*)) {
    margin-top: 0 !important;
    margin-bottom: 0 !important;
}

:is(.bg-white:not([class*="pt-"]):not([class*="py-"]):not([class*=" p-"])):is(.shadow, .shadow-sm) > :is(.items-center.h-10:has(> :is(h1, h2, h3), > div > :is(h1, h2, h3)), div:has(> .items-center.h-10:only-child > :is(h1, h2, h3), > .items-center.h-10:only-child > div > :is(h1, h2, h3), > div:only-child > .items-center.h-10:only-child > :is(h1, h2, h3)), div.flex.justify-between:not([class*="py-"]):has(> .items-center.h-10:first-child > :is(h1, h2, h3))):not([class*="pt-"]),
:is(.bg-white:not([class*="pt-"]):not([class*="py-"]):not([class*=" p-"])):is(.shadow, .shadow-sm) > form > :is(.items-center.h-10:has(> :is(h1, h2, h3), > div > :is(h1, h2, h3)), div:has(> .items-center.h-10:only-child > :is(h1, h2, h3), > .items-center.h-10:only-child > div > :is(h1, h2, h3), > div:only-child > .items-center.h-10:only-child > :is(h1, h2, h3)), div.flex.justify-between:not([class*="py-"]):has(> .items-center.h-10:first-child > :is(h1, h2, h3))):not([class*="pt-"]) {
    margin-top: .75rem !important;
}

/* A header further down a card, after other content (Bulk Collections under the class tabs on
   admission/installments): the title row's own mt-5 plus the next block's mt-6 made it 84px from
   the tab line to the table line. The title row never adds its own top margin; when something
   real sits above the header (not the zero-height error-template wrapper), the header gets the
   standard 12px above it (unless it is a padded header bar, see above). */
:is(:is(.pt-3, .pt-6, .bg-white:not([class*="pt-"]):not([class*="py-"]):not([class*=" p-"])):is(.shadow, .shadow-sm), :is(.pt-3, .pt-6, .bg-white:not([class*="pt-"]):not([class*="py-"]):not([class*=" p-"])):is(.shadow, .shadow-sm) > form) > :is(.items-center.h-10:has(> :is(h1, h2, h3), > div > :is(h1, h2, h3)), div:has(> .items-center.h-10:only-child > :is(h1, h2, h3), > .items-center.h-10:only-child > div > :is(h1, h2, h3), > div:only-child > .items-center.h-10:only-child > :is(h1, h2, h3)), div.flex.justify-between:not([class*="py-"]):has(> .items-center.h-10:first-child > :is(h1, h2, h3))) .items-center.h-10,
:is(:is(.pt-3, .pt-6, .bg-white:not([class*="pt-"]):not([class*="py-"]):not([class*=" p-"])):is(.shadow, .shadow-sm), :is(.pt-3, .pt-6, .bg-white:not([class*="pt-"]):not([class*="py-"]):not([class*=" p-"])):is(.shadow, .shadow-sm) > form) > .items-center.h-10:is(:is(.items-center.h-10:has(> :is(h1, h2, h3), > div > :is(h1, h2, h3)), div:has(> .items-center.h-10:only-child > :is(h1, h2, h3), > .items-center.h-10:only-child > div > :is(h1, h2, h3), > div:only-child > .items-center.h-10:only-child > :is(h1, h2, h3)), div.flex.justify-between:not([class*="py-"]):has(> .items-center.h-10:first-child > :is(h1, h2, h3)))) {
    margin-top: 0 !important;
}

:is(:is(.pt-3, .pt-6, .bg-white:not([class*="pt-"]):not([class*="py-"]):not([class*=" p-"])):is(.shadow, .shadow-sm), :is(.pt-3, .pt-6, .bg-white:not([class*="pt-"]):not([class*="py-"]):not([class*=" p-"])):is(.shadow, .shadow-sm) > form) > :not(:has(.ux-toasts)):has(*) + :is(.items-center.h-10:has(> :is(h1, h2, h3), > div > :is(h1, h2, h3)), div:has(> .items-center.h-10:only-child > :is(h1, h2, h3), > .items-center.h-10:only-child > div > :is(h1, h2, h3), > div:only-child > .items-center.h-10:only-child > :is(h1, h2, h3)), div.flex.justify-between:not([class*="py-"]):has(> .items-center.h-10:first-child > :is(h1, h2, h3))):not([class*="pt-"]) {
    margin-top: .75rem !important;
}

/* Guest "Sign in" pill in the topbar (layouts/master) — echoes the theme-toggle pill */
.guest-login-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.25rem 0.9rem 0.25rem 0.25rem;
    border-radius: 9999px;
    background: linear-gradient(135deg, #2A2E6E 0%, #4F46E5 100%);
    color: #fff;
    white-space: nowrap;

    transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.guest-login-btn:hover {
    transform: translateY(-1px);
    box-shadow: 0 8px 20px -6px rgba(79, 70, 229, 0.65);
}
.guest-login-btn:focus-visible {
    outline: 2px solid #818cf8;
    outline-offset: 2px;
}
.guest-login-badge {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    border-radius: 9999px;
    background: #fff;
    color: #2A2E6E;
}
.guest-login-badge svg { width: 1.1rem; height: 1.1rem; }
.guest-login-text { display: flex; flex-direction: column; line-height: 1.1; }
.guest-login-title { font-size: 0.875rem; font-weight: 700; letter-spacing: 0.01em; }
.guest-login-sub { font-size: 0.68rem; opacity: 0.8; }
.guest-login-arrow { width: 0.9rem; height: 0.9rem; transition: transform 0.2s ease; }
.guest-login-btn:hover .guest-login-arrow { transform: translateX(3px); }
@media (max-width: 639px) {
    .guest-login-sub { display: none; }
}

/* Topbar bell + profile trigger/menu (layouts/notifications-dropdown, layouts/profile).
   Borders use !important and icons are colour-scoped through their parent:
   dark-mode.css repaints every border via `html.dark *:not(#cke_editor)` (id
   specificity) and greys every `html.dark svg`. */
.topbar-bell {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border-radius: 9999px;
    background: #f1f5f9;
    border: 1px solid #e2e8f0 !important;
    transition: border-color 0.2s ease, background-color 0.2s ease;
}
.topbar-bell svg { width: 18px; height: 18px; }
.topbar-bell, .topbar-bell svg { color: #2A2E6E; }
.topbar-bell:hover, .topbar-bell.is-open { background: #fff; border-color: #cbd5e1 !important; }
.topbar-bell-badge {
    position: absolute;
    top: -4px;
    right: -5px;
    min-width: 18px;
    height: 18px;
    padding: 0 4px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 9999px;
    background: #dc2626;
    color: #fff;
    font-size: 10px;
    font-weight: 700;
    line-height: 1;
    box-shadow: 0 0 0 2px #fff;
}

/* Profile trigger: no fill. Name + role chip, then the avatar, set off by a hairline */
.topbar-profile {
    position: relative;
    display: flex;
    align-items: center;
    gap: 0.625rem;
    max-width: 17rem;
    padding: 3px 6px 3px 16px;
    border-radius: 0.375rem;
    text-align: right;
    transition: background-color 0.2s ease;
}
.topbar-profile::before {
    content: "";
    position: absolute;
    left: 0;
    top: 50%;
    height: 26px;
    width: 1px;
    transform: translateY(-50%);
    background: #e2e8f0;
}
.topbar-profile:hover, .topbar-profile.is-open { background: #f8fafc; }
.topbar-bell:focus-visible, .topbar-profile:focus-visible { outline: 2px solid #818cf8; outline-offset: 2px; }

.topbar-avatar {
    position: relative;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border-radius: 9999px;
    overflow: hidden;
    background: #e0e7ff;
    color: #2A2E6E;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.02em;
    box-shadow: 0 0 0 2px #fff, 0 0 0 3px #c7d2fe;
}
.topbar-avatar img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.topbar-avatar--lg { width: 42px; height: 42px; font-size: 14px; }

.topbar-profile-text { display: none; min-width: 0; flex-direction: column; align-items: flex-end; gap: 3px; }
.topbar-profile-name { max-width: 11rem; font-size: 0.8125rem; font-weight: 600; line-height: 1.1; color: #0f172a; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* role chip: one hue per portal so students and staff can tell where they are */
.topbar-role {
    display: inline-flex;
    align-items: center;
    padding: 1px 7px;
    border-radius: 9999px;
    font-size: 10px;
    font-weight: 600;
    line-height: 1.5;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    background: #f1f5f9;
    color: #475569;
}
.topbar-role--admin   { background: #eef2ff; color: #4338ca; }
.topbar-role--teacher { background: #fffbeb; color: #b45309; }
.topbar-role--student { background: #ecfdf5; color: #047857; }

.topbar-profile .topbar-profile-chevron { display: none; flex-shrink: 0; width: 14px; height: 14px; color: #94a3b8; transition: transform 0.2s ease; }
.topbar-profile.is-open .topbar-profile-chevron { transform: rotate(180deg); }
@media (min-width: 1024px) {
    .topbar-profile-text { display: flex; }
    .topbar-profile .topbar-profile-chevron { display: block; }
}
@media (max-width: 1023.98px) {
    .topbar-profile { padding: 3px 3px 3px 12px; }
}

.topbar-menu {
    position: absolute;
    right: 0;
    z-index: 20;
    width: 16rem;
    margin-top: 0.5rem;
    padding: 0.375rem;
    transform-origin: top right;
    border-radius: 0.375rem; /* rounded-md, same as the app cards */
    background: #fff;
    border: 1px solid #e2e8f0 !important;
    box-shadow: 0 10px 30px -10px rgba(15, 23, 42, 0.25);
}
.topbar-menu-head {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.625rem 0.5rem 0.75rem;
    margin-bottom: 0.375rem;
    border-bottom: 1px solid #f1f5f9 !important;
}
.topbar-menu-head .topbar-role { margin-top: 0.3rem; }
.topbar-menu-name { display: block; font-size: 0.875rem; font-weight: 600; color: #0f172a; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.topbar-menu-email { display: block; font-size: 0.75rem; color: #64748b; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.topbar-menu-item {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    padding: 0.5rem;
    border-radius: 0.25rem;
    font-size: 0.875rem;
    font-weight: 500;
    color: #334155;
}
.topbar-menu-item svg { width: 16px; height: 16px; color: #64748b; }
.topbar-menu-item:hover { background: #f1f5f9; color: #0f172a; }
.topbar-menu-item--danger, .topbar-menu-item--danger svg { color: #dc2626; }
.topbar-menu-item--danger:hover { background: #fef2f2; color: #b91c1c; }

html.dark .topbar-bell { background: var(--input-bg); border-color: var(--input-border) !important; }
html.dark .topbar-bell:hover, html.dark .topbar-bell.is-open { background: var(--elevated); border-color: var(--input-border-hover) !important; }
html.dark .topbar-bell, html.dark .topbar-bell svg { color: var(--text-bright); }
html.dark .topbar-bell-badge { box-shadow: 0 0 0 2px var(--card); }
html.dark .topbar-profile::before { background: var(--border); }
html.dark .topbar-profile:hover, html.dark .topbar-profile.is-open { background: var(--hover); }
html.dark .topbar-avatar { background: var(--accent-muted); color: #e0e7ff; box-shadow: 0 0 0 2px var(--card), 0 0 0 3px #3f4a7a; }
html.dark .topbar-profile-name, html.dark .topbar-menu-name { color: var(--text-bright); }
html.dark .topbar-menu-email, html.dark .topbar-profile .topbar-profile-chevron { color: var(--muted); }
html.dark .topbar-role { background: var(--elevated); color: var(--text-soft); }
html.dark .topbar-role--admin   { background: rgb(129 140 248 / 0.15); color: #a5b4fc; }
html.dark .topbar-role--teacher { background: rgb(251 191 36 / 0.12); color: #fcd34d; }
html.dark .topbar-role--student { background: rgb(52 211 153 / 0.12); color: #6ee7b7; }
html.dark .topbar-menu { background: var(--card); border-color: var(--card-border) !important; box-shadow: 0 10px 30px -10px rgba(0, 0, 0, 0.6); }
html.dark .topbar-menu-head { border-bottom-color: var(--border) !important; }
html.dark .topbar-menu-item { color: var(--text); }
html.dark .topbar-menu-item svg { color: var(--muted); }
html.dark .topbar-menu-item:hover { background: var(--hover); color: var(--text-bright); }
html.dark .topbar-menu-item--danger, html.dark .topbar-menu-item--danger svg { color: #f87171; }
html.dark .topbar-menu-item--danger:hover { background: rgb(248 113 113 / 0.1); color: #fca5a5; }

/* Topbar campus identity (layouts/master): logo, institution eyebrow, "Campus · City"
   from config('app.client_name') / config('app.branch') */
.topbar-branch { display: none; align-items: center; gap: 0.75rem; min-width: 0; }
@media (min-width: 768px) { .topbar-branch { display: flex; } }
.topbar-branch-logo { flex-shrink: 0; height: 36px; width: auto; object-fit: contain; }
.topbar-branch-eyebrow {
    display: block;
    font-size: 10px;
    font-weight: 600;
    line-height: 1.3;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: #64748b;
    white-space: nowrap;
}
.topbar-branch-name {
    font-size: 0.9375rem;
    font-weight: 700;
    line-height: 1.3;
    color: #0f172a;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.topbar-branch-city { margin-left: 0.3rem; font-weight: 500; color: #64748b; }
html.dark .topbar-branch-eyebrow, html.dark .topbar-branch-city { color: var(--muted); }
html.dark .topbar-branch-name { color: var(--text-bright); }
/* logos are drawn for white paper; give them a light chip on dark */
html.dark .topbar-branch-logo { padding: 3px; border-radius: 0.375rem; background: #f8fafc; }

/* "Back to Admin Portal" (layouts/back-button) — shown while an admin is signed in as
   someone else; tinted like the Admin Portal role chip so the way back reads as admin */
.topbar-back {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    height: 34px;
    padding: 0 0.875rem 0 0.625rem;
    border-radius: 9999px;
    background: #eef2ff;
    border: 1px solid #c7d2fe !important;
    color: #4338ca;
    font-size: 0.8125rem;
    font-weight: 600;
    white-space: nowrap;
    transition: background-color 0.2s ease, border-color 0.2s ease;
}
.topbar-back svg { width: 15px; height: 15px; color: #4338ca; transition: transform 0.2s ease; }
.topbar-back:hover { background: #e0e7ff; border-color: #a5b4fc !important; }
.topbar-back:hover svg { transform: translateX(-2px); }
.topbar-back:focus-visible { outline: 2px solid #818cf8; outline-offset: 2px; }
html.dark .topbar-back { background: rgb(129 140 248 / 0.12); border-color: rgb(129 140 248 / 0.3) !important; color: #a5b4fc; }
html.dark .topbar-back svg { color: #a5b4fc; }
html.dark .topbar-back:hover { background: rgb(129 140 248 / 0.2); border-color: rgb(129 140 248 / 0.5) !important; }

/* "Switch Portal" (livewire/layouts/switch-portal) — group-admission students hop
   between sibling portals; tinted like the Student Portal role chip */
.topbar-switch {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    height: 34px;
    padding: 0 0.625rem;
    border-radius: 9999px;
    background: #ecfdf5;
    border: 1px solid #a7f3d0 !important;
    color: #047857;
    font-size: 0.8125rem;
    font-weight: 600;
    white-space: nowrap;
    transition: background-color 0.2s ease, border-color 0.2s ease;
}
.topbar-switch svg { width: 15px; height: 15px; color: #047857; }
.topbar-switch .topbar-switch-chevron { width: 13px; height: 13px; opacity: 0.7; transition: transform 0.2s ease; }
.topbar-switch.is-open .topbar-switch-chevron { transform: rotate(180deg); }
.topbar-switch:hover, .topbar-switch.is-open { background: #d1fae5; border-color: #6ee7b7 !important; }
.topbar-switch:focus-visible { outline: 2px solid #34d399; outline-offset: 2px; }

/* "Open BrightMap" (layouts/master) — off-site link to the college's other portal:
   a soft indigo chip (flat at rest, so it sits in the white topbar) with a gradient badge */
.topbar-external {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    height: 34px;
    padding: 0 0.75rem 0 0.25rem;
    border-radius: 9999px;
    background: #f5f7ff;
    border: 1px solid #e0e7ff !important;
    color: #3730a3;
    font-size: 0.8125rem;
    font-weight: 600;
    letter-spacing: 0.01em;
    white-space: nowrap;
    box-shadow: none;
    transition: background-color 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
}
.topbar-external-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border-radius: 9999px;
    background: linear-gradient(135deg, #818cf8 0%, #6366f1 55%, #4f46e5 100%);
    box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.25);
}
.topbar-external-badge svg { width: 14px; height: 14px; color: #fff; }
.topbar-external-arrow { width: 13px; height: 13px; color: #818cf8; transition: transform 0.2s ease, color 0.2s ease; }
.topbar-external:hover {
    background: #eef2ff;
    border-color: #c7d2fe !important;
    box-shadow: 0 2px 6px -1px rgb(99 102 241 / 0.18);
}
.topbar-external:hover .topbar-external-arrow { color: #6366f1; transform: translate(1px, -1px); }
.topbar-external:focus-visible { outline: 2px solid #818cf8; outline-offset: 2px; }
@media (max-width: 639px) {
    .topbar-external { padding: 0; width: 34px; justify-content: center; }
    .topbar-external-label, .topbar-external-arrow { display: none; }
}
html.dark .topbar-external { background: rgb(129 140 248 / 0.08); border-color: rgb(129 140 248 / 0.22) !important; color: #e0e7ff; box-shadow: none; }
html.dark .topbar-external-badge svg { color: #fff; }
html.dark .topbar-external-arrow { color: #818cf8; }
html.dark .topbar-external:hover { background: rgb(129 140 248 / 0.15); border-color: rgb(129 140 248 / 0.4) !important; box-shadow: 0 2px 8px -1px rgb(0 0 0 / 0.4); }
html.dark .topbar-external:hover .topbar-external-arrow { color: #a5b4fc; }
.topbar-menu-label {
    display: block;
    padding: 0.375rem 0.5rem 0.25rem;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: #94a3b8;
}
.topbar-menu-hint { display: block; font-size: 0.6875rem; font-weight: 400; color: #94a3b8; }
html.dark .topbar-switch { background: rgb(52 211 153 / 0.1); border-color: rgb(52 211 153 / 0.3) !important; color: #6ee7b7; }
html.dark .topbar-switch svg { color: #6ee7b7; }
html.dark .topbar-switch:hover, html.dark .topbar-switch.is-open { background: rgb(52 211 153 / 0.18); border-color: rgb(52 211 153 / 0.5) !important; }
html.dark .topbar-menu-label, html.dark .topbar-menu-hint { color: var(--muted-dim); }

/* Toast auto-close countdown: the toast closes on this animation's animationend (include/error-template). */
.ux-alert.ux-alert--toast {
    overflow: hidden;
}

.ux-alert .ux-alert__timer {
    position: absolute;
    left: 0;
    bottom: 0;
    height: 3px;
    width: 100%;
    background: var(--a);
    animation: ux-alert-timer 8s linear forwards;
}

@keyframes ux-alert-timer {
    to { width: 0; }
}

.ux-alert.ux-alert--toast:hover .ux-alert__timer {
    animation-play-state: paused;
}

/* Tab bars (dashboard / admission / exam tabs): the gray baseline is an inset
   shadow so the active tab's underline paints over it instead of relying on
   -mb-px overlap, which the overflow-x-auto scroller clipped. */
.tab-strip { box-shadow: inset 0 -1px 0 #e5e7eb; }
.tab-strip nav > a { border-bottom-width: 3px; }

/* Timetable shift header row (Day / 1st shift / 2nd shift): calm tints, one hue
   per group (slate / sky / violet) with matching deep text.
   Dark mode overrides these in dark-mode.css. */
.shift-timing-row th.bg-red-600    { background-color: #f1f5f9; color: #334155; }
.shift-timing-row th.bg-yellow-300 { background-color: #e0f2fe; color: #075985; }
.shift-timing-row th.bg-rose-300   { background-color: #ede9fe; color: #5b21b6; }

/* Page top spacing, every page: the shell (main.page-shell in layouts/master > .py-6 > container) already pads the top,
   so the first block's own mt-* only made the gap differ from page to page. Zero it on the
   first block, looking through wrappers only - Livewire roots ([wire:id], incl. the
   lazy-load wrapper), class-less divs and class-less forms - so margins inside cards are
   never touched. "First" also means right after a leading <style>/<script> tag.
   Each line below is one wrapper level deeper:
     W = :is([wire\:id], div:not([class]), form:not([class]))
     F = :is(:first-child, :is(style, script):first-child + *) */
.page-shell > .py-6 > div > :is(:first-child, :is(style, script):first-child + *),
.page-shell > .py-6 > div > :is([wire\:id], div:not([class]), form:not([class])):is(:first-child, :is(style, script):first-child + *) > :is(:first-child, :is(style, script):first-child + *),
.page-shell > .py-6 > div > :is([wire\:id], div:not([class]), form:not([class])):is(:first-child, :is(style, script):first-child + *) > :is([wire\:id], div:not([class]), form:not([class])):is(:first-child, :is(style, script):first-child + *) > :is(:first-child, :is(style, script):first-child + *),
.page-shell > .py-6 > div > :is([wire\:id], div:not([class]), form:not([class])):is(:first-child, :is(style, script):first-child + *) > :is([wire\:id], div:not([class]), form:not([class])):is(:first-child, :is(style, script):first-child + *) > :is([wire\:id], div:not([class]), form:not([class])):is(:first-child, :is(style, script):first-child + *) > :is(:first-child, :is(style, script):first-child + *) {
    margin-top: 0;
}

/* ...and the shell's own top padding matches the container's side padding
   (px-4 sm:px-6 md:px-8), so the page has the same gutter on top, left and right */
.page-shell > .py-6 {
    padding-top: 1rem;
}

@media (min-width: 640px) {
    .page-shell > .py-6 {
        padding-top: 1.5rem;
    }
}

@media (min-width: 768px) {
    .page-shell > .py-6 {
        padding-top: 2rem;
    }
}
