:root {
    /* Ink: one refined ramp — deep, quiet, confident. Never a random gray. */
    --text: #0b1120;
    --text-2: #434d61;
    --muted: #737d90;

    /* Surfaces: a calm neutral page, pure-white cards — quiet contrast, so a card reads
       as lifted from a hairline alone. Elegance here is restraint. */
    --content-bg: #f5f6f9;
    --card-bg: #ffffff;
    --border: #e4e7f0;
    --border-strong: #d2d7e2;

    /* Near-black navy sidebar — the poised anchor of the whole layout. */
    --sidebar-bg: #0b0f1c;
    --sidebar-bg-2: #141b2d;
    --sidebar-hover: rgba(255, 255, 255, .055);
    --sidebar-text: #969fb5;

    /* Indigo primary, a classic, restrained admin accent. */
    --accent: #4f46e5;
    --accent-dark: #4338ca;
    --accent-2: #7c3aed;
    --accent-soft: #eef1fe;

    --success: #10b981;
    --success-bg: #ecfdf5;
    --danger: #ef4444;

    /* Elevation: restrained and layered — a hairline plus a faint lift, never a cloud.
       Cards are defined by their border first, shadow second. That reads expensive. */
    --shadow-1: 0 1px 2px rgba(11, 17, 32, .05);
    --shadow-2: 0 1px 3px rgba(11, 17, 32, .06), 0 3px 10px -5px rgba(11, 17, 32, .10);
    --shadow-3: 0 6px 16px -8px rgba(11, 17, 32, .12), 0 14px 34px -14px rgba(11, 17, 32, .14);
    --ring: 0 0 0 3px rgba(79, 70, 229, .16);
    /* Sharp, edgy corners across the whole project. */
    --radius: 2px;

    /* Named surfaces — every hardcoded near-white in components maps to one of these,
       which is what lets the dark theme below re-skin the whole app from one block. */
    --surface: #ffffff;      /* popups, cells, inputs — the brightest layer */
    --surface-2: #f8f9fd;    /* subtle panel headers / zebra fills */
    --surface-3: #f1f3f6;    /* muted chips and fills */
    --hover-tint: #f8f9ff;   /* row / chip hover wash */
    --warn-bg: #fffbeb;
}

/* ---------- Dark theme ----------
   Toggled by html[data-theme="dark"] (persisted in localStorage, applied pre-paint by the
   shell). Bootstrap gets data-bs-theme="dark" at the same time, so its modals, dropdowns
   and form controls flip in step with these variables. */
html[data-theme="dark"] {
    color-scheme: dark;

    --text: #e8ecf5;
    --text-2: #b4bdd0;
    --muted: #8791a5;

    --content-bg: #0b0f1a;
    --card-bg: #131a2b;
    --border: #243049;
    --border-strong: #34405e;

    --surface: #131a2b;
    --surface-2: #172034;
    --surface-3: #1d2740;
    --hover-tint: #1a2338;
    --warn-bg: rgba(245, 158, 11, .13);

    --sidebar-bg: #070b14;
    --sidebar-bg-2: #0d1322;

    --accent-soft: rgba(99, 102, 241, .16);
    --success-bg: rgba(16, 185, 129, .14);

    --shadow-1: 0 1px 2px rgba(0, 0, 0, .35);
    --shadow-2: 0 1px 3px rgba(0, 0, 0, .4), 0 3px 10px -5px rgba(0, 0, 0, .5);
    --shadow-3: 0 6px 16px -8px rgba(0, 0, 0, .55), 0 14px 34px -14px rgba(0, 0, 0, .6);
    --ring: 0 0 0 3px rgba(99, 102, 241, .28);
}

body {
    font-family: 'Inter', system-ui, sans-serif;
    background: var(--content-bg);
    color: var(--text);
    overflow-x: hidden;
    /* Inter is designed for this; without it the weights look muddy on Windows. */
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    font-feature-settings: 'cv11', 'ss01';
    letter-spacing: -.005em;
    /* Condense the whole project to ~80%. zoom re-lays-out (text stays crisp, unlike a
       transform), scaling text, spacing AND fixed-pixel boxes uniformly. Elements that must
       equal the viewport (100vh/100vw) aren't rescaled by zoom, so they're compensated with
       `/ .8` below, and the Bootstrap backdrop's vw/vh is overridden with %. */
    zoom: .8;
}

/* Numbers in a column line up; numbers in prose don't need to. */
table, .att-chip, .pager, .viz-tick { font-variant-numeric: tabular-nums; }

/* ---------- Elegant typography ----------
   Display text gets tight optical tracking (Inter looks cheap at 0 on big weights);
   large numerals go tabular so figures feel engineered, not typed. */
h1, h2, h3, h4, h5, h6,
.topbar-title, .dash-banner h2, .dash-banner h2 + p, .kpi-tile__val, .stat-value,
.donut__total, .kpi-value, .modal-title {
    letter-spacing: -.021em;
}
.kpi-tile__val, .stat-value, .donut__total, .kpi-value, .chart__val,
.mini-tile__val, .list-count b, .pager-info b {
    font-variant-numeric: tabular-nums;
    font-feature-settings: 'tnum', 'cv11', 'ss01';
}

/* Micro-labels: a hair more tracking + lighter weight reads considered, not shouty. */
.stat-label, .kpi-tile__lbl, .mini-tile__lbl, .donut__cap,
table.premium-table thead th {
    letter-spacing: .05em;
}

/* ---------- Shell layout ---------- */
.app-shell {
    display: flex;
    /* /.8 compensates the body zoom so the shell still fills the real viewport height. */
    min-height: calc(100vh / .8);
}

.app-sidebar {
    /* 216px, down from 244. Sized against the longest labels at the condensed row
        metrics: "User Credentials" on a leaf and "Student Diary" on a branch both clear it
        with room, and the deepest submenu label ("Analytics & Evaluation") just fits.
        .nav-text ellipsises and carries a title, so anything longer degrades rather than
        breaks. Narrower than ~200px starts clipping ordinary top-level labels. */
    width: 216px;
    flex-shrink: 0;
    /* A slow vertical gradient reads as depth; a flat block reads as a wall. */
    background: linear-gradient(180deg, var(--sidebar-bg-2) 0%, var(--sidebar-bg) 46%, #090d18 100%);
    position: sticky;
    top: 0;
    height: calc(100vh / .8);
    display: flex;
    flex-direction: column;
    z-index: 40;
    box-shadow: inset -1px 0 0 rgba(255, 255, 255, .05);
}

.sidebar-brand {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .34rem .6rem;
    border-bottom: 1px solid rgba(255, 255, 255, .08);
}

.brand-mark {
    width: 26px;
    height: 26px;
    border-radius: 7px;
    background: linear-gradient(135deg, var(--accent), var(--accent-2));
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 800;
    font-size: .82rem;
    flex-shrink: 0;
}

/* "eSs" is three glyphs where the old "NS" was two — tighten so it still fits the tile. */
.brand-mark--ess { font-size: .66rem; font-weight: 900; letter-spacing: -.04em; }

/* The school's own logo in the tile. White plate because most logos are drawn for paper and
   vanish against the dark sidebar; contain so nothing is cropped. */
.brand-mark--img {
    background: #fff;
    object-fit: contain;
    padding: 2px;
}

.brand-text {
    color: #fff;
    font-weight: 700;
    letter-spacing: .2px;
    /* School names run long ("Government Higher Secondary School …") — clip rather than
       push the close button out of the rail. */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    flex: 1 1 auto;
    min-width: 0;
}

.sidebar-nav {
    flex: 1;
    padding: .3rem .42rem;
    display: flex;
    flex-direction: column;
    gap: .04rem;
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: rgba(255, 255, 255, .16) transparent;
}
.sidebar-nav::-webkit-scrollbar { width: 6px; }
.sidebar-nav::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, .12); border-radius: 3px; }
.sidebar-nav::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, .22); }

.nav-notification-badge {
    margin-left: auto;
    min-width: 1.25rem;
    height: 1.25rem;
    padding: 0 .3rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 999px;
    background: #ec4899;
    color: #fff;
    font-size: .65rem;
    font-weight: 800;
    line-height: 1;
    box-shadow: 0 0 0 2px rgba(236, 72, 153, .18);
}

/* ---------- Expandable navigation tree ----------
   One knob drives the item size for the whole rail — standard 14px, matching the rest of
   the project. A row is either a leaf link (.nav-link) or a branch toggle (.nav-parent);
   both share this base so the tree reads as one control. Rows stay compact vertically
   (tight padding) while the text stays at a legible, standard size. */
/* SIZED TO FIT: a SchoolAdmin has 19 top-level rows, and all of them must land on one
   1366x768 screen without the rail scrolling. Row height is driven by the icon chip, not
   the text — the chip is the knob to turn if rows are ever added. Budget at 768px (body
   carries zoom:.8, so the rail gets 960 CSS px): 19 x 31 = 589 + brand 39 + footer 44. */
.app-sidebar { --nav-fs: .82rem; --nav-chip: 22px; }

.nav-link,
.nav-parent {
    position: relative;
    display: flex;
    align-items: center;
    gap: .52rem;
    width: 100%;
    padding: .26rem .5rem;
    color: var(--sidebar-text);
    text-decoration: none;
    text-align: left;
    border: none;
    border-radius: 10px;
    font-family: inherit;
    font-weight: 600;
    font-size: var(--nav-fs);
    letter-spacing: -.006em;
    line-height: 1.25;
    background: transparent;
    cursor: pointer;
    transition: background .16s ease, color .16s ease, box-shadow .16s ease;
}

/* Inside the installed app there is nothing to install: drop the "Install App" row.
   The media query covers Android/desktop; the attribute (set by pwa.js) covers iOS,
   whose standalone mode only reports through navigator.standalone. */
@media all and (display-mode: standalone) {
    [data-pwa-install] { display: none; }
}

[data-pwa-installed] [data-pwa-install] { display: none; }

.nav-link:hover,
.nav-parent:hover {
    background: var(--sidebar-hover);
    color: #fff;
}

.nav-icon-chip {
    width: var(--nav-chip, 22px);
    height: var(--nav-chip, 22px);
    border-radius: 7px;
    display: flex;
    align-items: center;
    justify-content: center;
    /* The item's own hue, held back until it matters. */
    background: color-mix(in srgb, var(--chip-color, var(--accent)) 18%, transparent);
    color: var(--chip-color, var(--accent));
    font-size: .8rem;
    flex-shrink: 0;
    transition: background .16s ease, color .16s ease, box-shadow .16s ease, transform .16s ease;
}

.nav-link:hover .nav-icon-chip,
.nav-parent:hover .nav-icon-chip {
    background: color-mix(in srgb, var(--chip-color, var(--accent)) 32%, transparent);
    color: #fff;
}

.nav-text {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Caret on a branch — points right, rotates down when the branch is open. */
.nav-caret {
    font-size: .7rem;
    color: var(--sidebar-text);
    opacity: .55;
    flex-shrink: 0;
    transition: transform .22s ease, opacity .16s ease;
}
.nav-parent:hover .nav-caret { opacity: 1; }
.nav-item.open > .nav-parent > .nav-caret { transform: rotate(90deg); }

/* A branch on the active page's path keeps its label bright. */
.nav-item.trail > .nav-parent { color: #eef1ff; }
.nav-item.trail > .nav-parent .nav-icon-chip {
    background: color-mix(in srgb, var(--chip-color, var(--accent)) 30%, transparent);
    color: #fff;
}

/* Active leaf — a refined accent pill, a glowing left rail, and a gradient chip. */
.nav-link.active {
    background: linear-gradient(90deg, color-mix(in srgb, var(--accent) 26%, transparent), color-mix(in srgb, var(--accent) 5%, transparent));
    color: #fff;
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 32%, transparent);
}
.nav-link.active::before {
    content: '';
    position: absolute;
    left: -.5rem;
    top: 50%;
    transform: translateY(-50%);
    height: 58%;
    width: 3px;
    border-radius: 0 3px 3px 0;
    background: var(--accent);
    box-shadow: 0 0 10px var(--accent);
}
.nav-link.active .nav-icon-chip {
    background: linear-gradient(135deg, var(--accent), var(--accent-2));
    color: #fff;
    box-shadow: 0 4px 12px -2px var(--accent);
}

/* Collapsible child list — animated open via a 0fr→1fr grid row, so no fixed height. */
.nav-sub {
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows .26s ease;
}
.nav-item.open > .nav-sub { grid-template-rows: 1fr; }
.nav-sub-inner {
    overflow: hidden;
    min-height: 0;
    /* Indent children and draw a guide rail down the group. */
    margin: .12rem 0 .2rem .7rem;
    padding-left: .42rem;
    border-left: 1px solid rgba(255, 255, 255, .1);
    display: flex;
    flex-direction: column;
    gap: .06rem;
}

/* Nested rows are one step down from the standard size, so depth reads at a glance. */
.nav-sub .nav-link,
.nav-sub .nav-parent { font-size: .78rem; padding: .22rem .48rem; gap: .46rem; }
.nav-sub .nav-icon-chip { width: 19px; height: 19px; font-size: .7rem; border-radius: 6px; }

.app-main {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

/* Was #f0ffcc — a lime green that belonged to no palette in this project. */
.app-topbar {
    position: sticky;
    top: 0;
    z-index: 30;
    /* A clean, faintly translucent bar — a crisp hairline instead of a shadow slab. */
    background: rgba(255, 255, 255, .9);
    backdrop-filter: saturate(180%) blur(14px);
    border-bottom: 1px solid var(--border);
    padding: .5rem .9rem;
    display: flex;
    align-items: center;
    gap: .7rem;
    box-shadow: none;
}

.topbar-submenu {
    display: flex;
    gap: .4rem;
    flex-wrap: wrap;
    justify-content: flex-start;
    flex: 1 1 auto;
    min-width: 0;
}

/* The current page's name — fills the topbar between the (mobile) hamburger and the
   profile/logout actions. app.js keeps #topbarTitle in sync on SPA navigation. */
.topbar-title {
    flex: 1 1 auto;
    min-width: 0;
    margin: 0;
    font-size: 1.1rem;
    font-weight: 800;
    letter-spacing: -.01em;
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.topbar-right {
    margin-left: auto;
    flex-shrink: 0;
    display: flex;
    gap: .4rem;
}

.submenu-btn {
    display: flex;
    align-items: center;
    gap: .4rem;
    height: 34px;
    flex: 0 0 auto;
    padding: 0 .7rem;
    border: 1px solid var(--border);
    border-radius: 8px;
    color: var(--chip-color, #475569);
    text-decoration: none;
    font-size: 1rem;
    font-weight: 600;
    background: var(--card-bg);
    white-space: nowrap;
    box-shadow: var(--shadow-1);
    transition: transform .1s ease, box-shadow .12s ease, background .12s ease, color .12s ease, border-color .12s ease;
}

.submenu-btn .submenu-label {
    font-size: .82rem;
}

.submenu-btn:hover {
    transform: translateY(-1px);
    box-shadow: var(--shadow-2);
}

/* Coloured elevation instead of a black slab — same treatment as .btn-premium. */
.submenu-btn:hover,
.submenu-btn.active {
    background: var(--chip-color, var(--accent));
    color: #fff;
    border-color: transparent;
    box-shadow: 0 1px 1px rgba(16, 19, 31, .1), 0 6px 14px -4px var(--chip-color, var(--accent)), inset 0 1px 0 rgba(255, 255, 255, .18);
}

.submenu-btn:active {
    transform: translateY(1px);
    box-shadow: inset 0 1px 3px rgba(0, 0, 0, .18);
}

.submenu-btn-primary {
    background: var(--chip-color, #10b981);
    color: #fff;
    border-color: transparent;
    box-shadow: 0 1px 1px rgba(16, 19, 31, .1), 0 6px 14px -4px var(--chip-color, #10b981), inset 0 1px 0 rgba(255, 255, 255, .18);
}

.submenu-btn-primary:hover {
    background: var(--chip-color, #10b981);
    filter: saturate(112%);
    box-shadow: 0 2px 3px rgba(16, 19, 31, .1), 0 10px 20px -6px var(--chip-color, #10b981), inset 0 1px 0 rgba(255, 255, 255, .22);
}

.submenu-btn-primary:active {
    transform: translateY(1px);
    box-shadow: inset 0 1px 3px rgba(0, 0, 0, .18);
}

/* ---------- Topbar hamburger + mobile brand (shown only on small screens) ---------- */
.topbar-toggle {
    display: none;
    width: 38px;
    height: 38px;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--border);
    border-radius: 9px;
    background: var(--card-bg);
    color: var(--text-2);
    font-size: 1.15rem;
    box-shadow: var(--shadow-1);
    transition: background .12s ease, color .12s ease;
}
.topbar-toggle:hover { background: var(--accent-soft); color: var(--accent); }

/* Off-canvas backdrop — dims the page behind the drawer on mobile. */
.sidebar-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(9, 13, 24, .5);
    backdrop-filter: blur(2px);
    opacity: 0;
    visibility: hidden;
    z-index: 45;
    transition: opacity .25s ease, visibility .25s ease;
}

/* Under the body zoom, Bootstrap's backdrop (sized in vw/vh, which zoom doesn't rescale)
   would only cover ~80% of the screen. % of the fixed containing block does scale, so it
   fills the viewport again. */
.modal-backdrop { width: 100%; height: 100%; }

/* Close button that lives at the top of the drawer (mobile only). */
.sidebar-close {
    display: none;
    margin-left: auto;
    width: 32px;
    height: 32px;
    align-items: center;
    justify-content: center;
    border: none;
    border-radius: 8px;
    background: rgba(255, 255, 255, .08);
    color: #e8ecff;
    font-size: 1.1rem;
}
.sidebar-close:hover { background: rgba(255, 255, 255, .16); }

.app-content {
    padding: .5rem .9rem;
    flex: 1;
}

@media (max-width: 991.98px) {
    /* The sidebar becomes an off-canvas drawer: fixed, slid off to the left, revealed
       when body.sidebar-open is set by the hamburger. */
    .app-sidebar {
        position: fixed;
        top: 0;
        left: 0;
        height: calc(100dvh / .8);
        width: 270px;
        max-width: 84vw;
        z-index: 50;
        transform: translateX(-100%);
        transition: transform .28s cubic-bezier(.4, 0, .2, 1);
        box-shadow: 0 0 60px rgba(0, 0, 0, .4);
    }

    body.sidebar-open .app-sidebar { transform: translateX(0); }
    body.sidebar-open .sidebar-backdrop { opacity: 1; visibility: visible; }

/* Lock the page behind the open drawer. */
    body.sidebar-open { overflow: hidden; }

    .topbar-toggle { display: flex; }
    .sidebar-close { display: flex; }

    .app-content { padding: .45rem .7rem; }

    .topbar-submenu { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }
    .topbar-submenu::-webkit-scrollbar { display: none; }

    .submenu-btn {
        width: 38px;
        height: 38px;
        padding: 0;
        justify-content: center;
    }

    .submenu-btn .submenu-label {
        display: none;
    }
}

/* ---------- Impersonation banner ---------- */
.impersonation-banner {
    background: linear-gradient(120deg, #f59e0b, #f97316);
    color: #fff;
    padding: .45rem .75rem;
    border-radius: 8px;
    margin-bottom: .6rem;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .75rem;
    font-weight: 600;
    font-size: .85rem;
    flex-wrap: wrap;
}

.impersonation-banner a {
    color: #fff;
    font-weight: 700;
}

/* ---------- Shared premium components ---------- */
/* The hard 3px black edge these carried read as a toy button. Elevation now comes from
   the accent's own colour, which is what makes it look expensive rather than loud. */
.btn-premium {
    /* A confident, near-solid indigo with a whisper of depth and a hairline top-light —
       elegant, not a loud gradient slab. */
    background: linear-gradient(180deg, var(--accent), var(--accent-dark));
    border: none;
    border-radius: 7px;
    font-weight: 600;
    letter-spacing: -.01em;
    color: #fff;
    box-shadow: 0 1px 2px rgba(11, 17, 32, .12), 0 4px 12px -4px rgba(67, 56, 202, .42), inset 0 1px 0 rgba(255, 255, 255, .16);
    transition: transform .12s ease, box-shadow .18s ease, filter .18s ease;
}

.btn-premium:hover {
    transform: translateY(-1px);
    filter: brightness(1.06);
    box-shadow: 0 2px 4px rgba(11, 17, 32, .12), 0 8px 20px -6px rgba(67, 56, 202, .5), inset 0 1px 0 rgba(255, 255, 255, .2);
    color: #fff;
}

.btn-premium:active {
    transform: translateY(0);
    filter: none;
    box-shadow: 0 1px 2px rgba(11, 17, 32, .14), inset 0 1px 3px rgba(0, 0, 0, .16);
}

.btn-premium:focus-visible,
.btn:focus-visible,
.form-control:focus,
.form-select:focus {
    outline: none;
    box-shadow: var(--ring);
    border-color: var(--accent);
}

.toolbar-card {
    background: var(--card-bg);
    border-radius: 10px;
    border: 1px solid var(--border);
    box-shadow: var(--shadow-1);
    padding: .3rem .35rem;
}

.search-input {
    border-radius: 6px;
    border: 1px solid var(--border);
    padding: .4rem .7rem;
    background: var(--surface-2);
    box-shadow: inset 0 1px 3px rgba(15, 23, 42, .07);
    transition: box-shadow .15s ease, border-color .15s ease;
}

.search-input:focus {
    border-color: var(--accent);
    box-shadow: inset 0 1px 3px rgba(15, 23, 42, .07), 0 0 0 .2rem rgba(99, 102, 241, .15);
    background: var(--surface);
}

.status-select {
    border-radius: 6px;
    border: 1px solid var(--border);
    background: var(--surface-2);
    padding: .4rem .7rem;
    box-shadow: inset 0 1px 3px rgba(15, 23, 42, .07);
}

.status-select:focus {
    border-color: var(--accent);
    box-shadow: inset 0 1px 3px rgba(15, 23, 42, .07), 0 0 0 .2rem rgba(99, 102, 241, .15);
}

.table-card {
    background: var(--card-bg);
    border-radius: 12px;
    border: 1px solid var(--border);
    box-shadow: var(--shadow-2);
    overflow: hidden;
}

/* The overflow above outranks Bootstrap's .table-responsive and would clip a wide
   table instead of scrolling it. */
.table-card.table-responsive {
    overflow: auto;
}

table.premium-table {
    margin-bottom: 0;
}

table.premium-table thead th {
    border: none;
    border-bottom: 1px solid var(--border);
    /* A clean, near-transparent header — separated by the hairline, not a fill. Elegant. */
    background: #fcfcfe;
    color: var(--muted);
    text-transform: uppercase;
    font-size: .62rem;
    letter-spacing: .09em;
    font-weight: 600;
    padding: .3rem .8rem;
    white-space: nowrap;
}

table.premium-table thead th[data-sort] {
    cursor: pointer;
    user-select: none;
    white-space: nowrap;
    transition: color .12s ease, background .12s ease;
}

table.premium-table thead th[data-sort]:hover {
    color: var(--accent);
    background: var(--accent-soft);
}

.sort-icon {
    font-size: .65rem;
    margin-left: .25rem;
    opacity: .4;
}

.sort-icon.active {
    opacity: 1;
    color: var(--accent);
}

table.premium-table tbody td {
    border-top: 1px solid var(--border);
    padding: .28rem .75rem;
    vertical-align: middle;
}

table.premium-table tbody tr {
    transition: background .15s ease;
}

table.premium-table tbody tr:hover {
    background: var(--accent-soft);
}

.avatar-circle {
    width: 38px;
    height: 38px;
    min-width: 38px;
    border-radius: 50%;
    background: linear-gradient(135deg, var(--accent), var(--accent-2));
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: .9rem;
}

.badge-status {
    border-radius: 999px;
    font-weight: 600;
    font-size: .72rem;
    padding: .2rem .55rem;
}

.badge-active {
    background: var(--success-bg);
    color: #047857;
}

.badge-inactive {
    background: var(--surface-3);
    color: #64748b;
}

.badge-warning {
    background: var(--warn-bg);
    color: #b45309;
}

.badge-danger {
    background: #fef2f2;
    color: #b91c1c;
}

.icon-btn {
    width: 36px;
    height: 36px;
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 6px;
    border: 1px solid var(--border);
    background: var(--card-bg);
    color: var(--muted);
    font-size: 1rem;
    padding: 0;
    line-height: 1;
    box-shadow: var(--shadow-1);
    transition: transform .1s ease, box-shadow .12s ease, background .12s ease, color .12s ease, border-color .12s ease;
}

.icon-btn:hover {
    transform: translateY(-1px);
    box-shadow: var(--shadow-2);
}

.icon-btn:active {
    transform: translateY(0);
    box-shadow: var(--shadow-1);
}

.icon-btn-primary {
    color: #f59e0b;
    border-color: rgba(245, 158, 11, .28);
}

.icon-btn-primary:hover {
    background: #f59e0b;
    color: #fff;
    border-color: #f59e0b;
    box-shadow: 0 3px 0 rgba(180, 108, 0, .55), 0 6px 14px rgba(245, 158, 11, .35), inset 0 1px 0 rgba(255, 255, 255, .3);
}

.icon-btn-danger {
    color: var(--danger);
    border-color: rgba(239, 68, 68, .25);
}

.icon-btn-danger:hover {
    background: var(--danger);
    color: #fff;
    border-color: var(--danger);
    box-shadow: 0 3px 0 rgba(153, 27, 27, .55), 0 6px 14px rgba(239, 68, 68, .35), inset 0 1px 0 rgba(255, 255, 255, .3);
}

.icon-btn-secondary {
    color: #475569;
}

.icon-btn-secondary:hover {
    background: #475569;
    color: #fff;
    border-color: #475569;
    box-shadow: 0 3px 0 rgba(30, 41, 59, .55), 0 6px 14px rgba(71, 85, 105, .3), inset 0 1px 0 rgba(255, 255, 255, .25);
}

.icon-btn-teal {
    color: #0891b2;
    border-color: rgba(8, 145, 178, .28);
}

.icon-btn-teal:hover {
    background: #0891b2;
    color: #fff;
    border-color: #0891b2;
    box-shadow: 0 3px 0 rgba(8, 90, 110, .55), 0 6px 14px rgba(8, 145, 178, .35), inset 0 1px 0 rgba(255, 255, 255, .3);
}

.actions-row {
    display: flex;
    align-items: center;
    gap: .4rem;
    flex-wrap: nowrap;
}

.sa-card {
    background: var(--surface);
    border-radius: 10px;
    border: 1px solid var(--border);
    box-shadow: 0 6px 18px rgba(15, 23, 42, .06);
    padding: .6rem .75rem;
    margin-bottom: .5rem;
    transition: transform .15s ease, box-shadow .15s ease;
}

.sa-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 12px 26px rgba(15, 23, 42, .1);
}

.sa-card .sa-card-top {
    display: flex;
    align-items: center;
    gap: .75rem;
    margin-bottom: .75rem;
}

.sa-card .sa-name {
    font-weight: 700;
    margin: 0;
}

.sa-card .sa-meta {
    font-size: .85rem;
    color: var(--muted);
    margin: 0;
}

.sa-card .sa-row {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    gap: .5rem;
    font-size: .85rem;
    padding: .3rem 0;
    border-top: 1px dashed var(--border);
}

.sa-card .sa-row span:first-child {
    color: var(--muted);
    flex-shrink: 0;
}

.sa-card .sa-row span:last-child {
    text-align: right;
    overflow-wrap: anywhere;
    min-width: 0;
}

.sa-card .sa-actions {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: .4rem;
    margin-top: .85rem;
}

.empty-state {
    background: var(--surface);
    border-radius: 10px;
    border: 1px dashed var(--border);
    padding: 1.5rem 1rem;
}

.modal-content {
    border-radius: 12px;
    border: none;
    box-shadow: 0 20px 50px rgba(15, 23, 42, .25);
}

.modal-header,
.modal-footer {
    border-color: var(--border);
}

.modal-header {
    padding: .6rem .9rem;
}

.modal-body {
    padding: .7rem .9rem;
}

.modal-footer {
    padding: .6rem .9rem;
}

.modal .form-label {
    font-weight: 600;
    font-size: .82rem;
    color: #334155;
    margin-bottom: .3rem;
}

.modal-section-title {
    font-size: .72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--accent);
    margin: 1rem 0 .6rem;
    padding-top: .75rem;
    border-top: 1px dashed var(--border);
}

.modal-section-title:first-child {
    margin-top: 0;
    padding-top: 0;
    border-top: none;
}

.modal-xl .modal-content {
    box-shadow: 0 30px 70px rgba(15, 23, 42, .3);
}

.field-row {
    display: flex;
    align-items: stretch;
}

.field-row-label {
    flex: 0 0 40%;
    max-width: 40%;
    display: flex;
    align-items: center;
    gap: .5rem;
    font-weight: 600;
    font-size: .82rem;
    color: #334155;
    margin: 0;
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-right: none;
    border-radius: 6px 0 0 6px;
    padding: 0 .7rem;
}

.field-row-label i {
    color: var(--accent);
    font-size: .95rem;
    flex-shrink: 0;
}

.field-row-input {
    flex: 1 1 60%;
    min-width: 0;
}

.field-row-input .form-control,
.field-row-input .form-select {
    border-radius: 0 6px 6px 0;
    height: 100%;
}

/* ---------- Global form controls ---------- */
.form-control,
.form-select {
    border-radius: 6px;
    border: 1px solid var(--border);
    padding: .1rem .3rem;
    font-size: .7rem;
    line-height: 1.25;
    min-height: 24px;
    transition: box-shadow .15s ease, border-color .15s ease;
}

.form-select {
    padding-right: 1.25rem;
    background-size: 10px 7px;
    background-position: right .3rem center;
}

.input-group-text {
    padding: .1rem .3rem;
    font-size: .7rem;
    border-radius: 6px;
}

textarea.form-control { min-height: 44px; }

/* Field rows sit as tight as the grid allows — Bootstrap's g-2/g-3 gutters are
   overridden here so every form and filter bar shares one spacing. */
.toolbar-card .row,
.pcard .row,
.modal-body .row {
    --bs-gutter-x: .25rem;
    --bs-gutter-y: .25rem;
}

.form-control:focus,
.form-select:focus {
    border-color: var(--accent);
    box-shadow: 0 0 0 .2rem rgba(99, 102, 241, .15);
}

.form-check-input:checked {
    background-color: var(--accent);
    border-color: var(--accent);
}

.form-check-input:focus {
    border-color: var(--accent);
    box-shadow: 0 0 0 .2rem rgba(99, 102, 241, .15);
}

.btn-close:focus {
    box-shadow: 0 0 0 .2rem rgba(99, 102, 241, .15);
}

.stat-card {
    background: var(--surface);
    border-radius: 8px;
    border: 1px solid var(--border);
    border-left: 3px solid var(--stat-color, var(--accent));
    box-shadow: 0 2px 0 rgba(15, 23, 42, .06), 0 6px 16px rgba(15, 23, 42, .05);
    padding: .5rem .65rem;
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: .55rem;
    transition: transform .15s ease, box-shadow .15s ease;
}

.stat-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 3px 0 rgba(15, 23, 42, .08), 0 12px 24px rgba(15, 23, 42, .1);
}

.stat-icon {
    width: 30px;
    height: 30px;
    border-radius: 6px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: .9rem;
    color: #fff;
    flex-shrink: 0;
    background: var(--stat-color, var(--accent));
    box-shadow: 0 2px 0 rgba(0, 0, 0, .3), inset 0 1px 0 rgba(255, 255, 255, .25);
}

.stat-body {
    display: flex;
    align-items: baseline;
    gap: .35rem;
    min-width: 0;
    flex-wrap: wrap;
}

.stat-value {
    font-weight: 800;
    font-size: 1.05rem;
    line-height: 1;
}

.stat-label {
    color: var(--muted);
    font-size: .66rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .02em;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

@media (min-width: 992px) {
    .stat-card {
        padding: .4rem .55rem;
        gap: .65rem;
    }

    .stat-icon {
        width: 42px;
        height: 42px;
        font-size: 1.2rem;
        border-radius: 7px;
    }

    .stat-value {
        font-size: 1.5rem;
    }

    .stat-label {
        font-size: .78rem;
    }
}

/* ---------- WhatsApp setting ---------- */
.wa-card {
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 12px;
    box-shadow: 0 6px 18px rgba(15, 23, 42, .05);
    overflow: hidden;
}

.wa-card-head {
    display: flex;
    align-items: center;
    gap: .6rem;
    padding: .7rem .9rem;
    background: linear-gradient(120deg, #128c7e, #25d366);
    color: #fff;
}

.wa-head-icon {
    width: 30px;
    height: 30px;
    border-radius: 7px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1rem;
    background: rgba(255, 255, 255, .18);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .3);
}

.wa-head-title {
    font-weight: 700;
    font-size: .95rem;
    letter-spacing: .2px;
}

.wa-conn-badge {
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    padding: .2rem .6rem;
    border-radius: 20px;
    font-size: .72rem;
    font-weight: 600;
    background: rgba(255, 255, 255, .18);
    color: #fff;
}

.wa-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    display: inline-block;
    flex-shrink: 0;
}

.wa-conn-badge.is-online .wa-dot {
    animation: wa-pulse 2s infinite;
}

@keyframes wa-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: .35; }
}

.wa-card-body {
    padding: .9rem;
}

.wa-verify-row {
    margin-bottom: .9rem;
}

.wa-verify-btn {
    width: 100%;
    padding: .55rem 1rem;
}

.wa-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: .9rem;
}

.wa-api-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    margin-bottom: .6rem;
    padding: .5rem 1rem;
}

.wa-guide-card {
    border: 1px solid var(--border);
    border-radius: 10px;
    overflow: hidden;
    background: var(--surface);
}

.wa-guide-head {
    background: linear-gradient(120deg, #128c7e, #25d366);
    color: #fff;
    padding: .5rem .8rem;
    font-weight: 600;
    font-size: .82rem;
}

.wa-guide-body {
    padding: .35rem .6rem;
    overflow-x: auto;
}

.wa-guide-table {
    width: 100%;
    border-collapse: collapse;
    font-size: .78rem;
}

.wa-guide-table tr {
    border-bottom: 1px solid var(--border);
}

.wa-guide-table tr:last-child {
    border-bottom: none;
}

.wa-guide-table td {
    padding: .3rem .35rem;
    vertical-align: top;
}

.wa-guide-table .k {
    font-weight: 600;
    color: var(--muted);
    white-space: nowrap;
}

.wa-guide-table .k.warn,
.wa-guide-table .warn-text {
    color: var(--danger);
    font-weight: 600;
}

.wa-guide-table .mono {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    word-break: break-all;
}

.wa-copy-btn {
    background: none;
    border: none;
    padding: 0 .25rem;
    color: var(--accent);
    cursor: pointer;
}

.wa-copy-btn:hover {
    color: var(--accent-dark);
}

.wa-triggers {
    border: 1px solid var(--border);
    border-radius: 10px;
    overflow: hidden;
    background: var(--surface);
}

.wa-triggers-head {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .5rem .8rem;
    background: linear-gradient(120deg, #128c7e, #25d366);
    color: #fff;
    font-weight: 600;
    font-size: .84rem;
}

.wa-triggers-head .wa-conn-badge {
    font-size: .68rem;
    padding: .15rem .5rem;
}

.wa-triggers-body {
    padding: .3rem .8rem .6rem;
}

.wa-rule {
    display: flex;
    align-items: center;
    gap: .6rem;
    padding: .4rem .1rem;
    border-bottom: 1px solid var(--border);
}

.wa-rule:last-child {
    border-bottom: none;
}

.wa-rule-icon {
    width: 26px;
    height: 26px;
    font-size: .78rem;
}

.wa-rule-label {
    flex: 1;
    font-size: .82rem;
    font-weight: 500;
    color: #1e2432;
}

.wa-switch {
    position: relative;
    width: 40px;
    height: 22px;
    flex-shrink: 0;
    cursor: pointer;
    margin: 0;
}

.wa-switch input {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
}

.wa-switch-track {
    position: absolute;
    inset: 0;
    background: #cbd2e0;
    border-radius: 20px;
    transition: background .2s ease;
    box-shadow: inset 0 1px 2px rgba(15, 23, 42, .18);
}

.wa-switch-track::after {
    content: '';
    position: absolute;
    top: 2px;
    left: 2px;
    width: 18px;
    height: 18px;
    background: var(--surface);
    border-radius: 50%;
    box-shadow: 0 1px 3px rgba(15, 23, 42, .3);
    transition: transform .2s ease;
}

.wa-switch input:checked + .wa-switch-track {
    background: linear-gradient(120deg, #128c7e, #25d366);
}

.wa-switch input:checked + .wa-switch-track::after {
    transform: translateX(18px);
}

.wa-otp-input {
    letter-spacing: .6em;
    font-weight: 700;
    border-radius: 8px;
}

.wa-otp-input:focus {
    border-color: #25d366;
    box-shadow: 0 0 0 .2rem rgba(37, 211, 102, .18);
}

.wa-toast-container {
    position: fixed;
    top: 1rem;
    right: 1rem;
    z-index: 1080;
    display: flex;
    flex-direction: column;
    gap: .5rem;
    max-width: 340px;
}

.wa-toast {
    display: flex;
    align-items: center;
    gap: .6rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: .6rem .7rem;
    box-shadow: 0 10px 26px rgba(15, 23, 42, .16);
    animation: wa-toast-in .25s ease;
}

@keyframes wa-toast-in {
    from { transform: translateX(20px); opacity: 0; }
    to { transform: translateX(0); opacity: 1; }
}

.wa-toast-icon {
    width: 26px;
    height: 26px;
    border-radius: 6px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-size: .85rem;
    flex-shrink: 0;
}

.wa-toast-msg {
    flex: 1;
    font-size: .82rem;
    font-weight: 500;
}

.wa-toast .btn-close {
    font-size: .6rem;
}

@media (min-width: 992px) {
    .wa-grid:not(.single) {
        grid-template-columns: 1fr 1.4fr;
        align-items: start;
    }
}

/* ============================================================
   PREMIUM SETTINGS UI KIT
   ============================================================ */

@keyframes premIn {
    from { opacity: 0; transform: translateY(10px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* ---------- Page actions row ---------- */
/* Just a row: the page's own search / filters / action buttons, sitting directly
   on the content background. No surface of its own — the controls inside carry
   all the styling there is. */
.page-actions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: .3rem;
    margin-bottom: .5rem;
}

/* Left-aligned search / filters. Doesn't grow: leftover width stays to the right
   so the action buttons sit next to the search, not at the far edge. */
.act-left {
    display: flex;
    align-items: center;
    gap: .3rem;
    flex: 0 1 auto;
    min-width: 0;
    flex-wrap: nowrap; /* the search stays on the buttons' line, never below them */
}

/* Hint text ("Subjects come from the section's syllabus") must never push the
   controls out of line — it truncates instead. */
.act-left > span {
    font-size: .7rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}

.act-search-wrap {
    position: relative;
    display: flex;
    align-items: center;
    flex: 1 1 140px;
    min-width: 0;
    max-width: 260px;
}

.act-search-wrap > i {
    position: absolute;
    left: .55rem;
    font-size: .72rem;
    color: var(--muted);
    pointer-events: none;
}

.act-search,
.act-select {
    width: 100%;
    height: 30px;
    color: var(--text);
    background: var(--content-bg);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: .1rem .55rem;
    font-size: .78rem;
    line-height: 1;
    transition: background .15s ease, border-color .15s ease, box-shadow .15s ease;
}

.act-search { padding-left: 1.5rem; }

.act-select {
    width: auto;
    cursor: pointer;
}

.act-search::placeholder { color: var(--muted); }

.act-search:focus,
.act-select:focus {
    outline: none;
    color: var(--text);
    background: var(--surface);
    border-color: var(--accent);
    box-shadow: var(--ring);
}

.act-select option { color: #1e2432; }

/* Premium action button — the accent primary, icon + label on desktop. */
.act-btn {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    flex: 0 0 auto;
    height: 30px;
    padding: 0 .75rem;
    border: none;
    border-radius: 8px;
    font-weight: 600;
    font-size: .78rem;
    white-space: nowrap;
    color: #fff;
    background: linear-gradient(135deg, var(--accent), var(--accent-dark));
    box-shadow: 0 6px 14px -6px var(--accent);
    transition: transform .1s ease, box-shadow .15s ease, filter .15s ease;
}

.act-btn:hover {
    color: #fff;
    transform: translateY(-1px);
    filter: saturate(112%);
    box-shadow: 0 10px 22px -8px var(--accent);
}

.act-btn:active {
    transform: translateY(0);
    filter: none;
    box-shadow: 0 4px 10px -6px var(--accent);
}

.act-btn i { font-size: .8rem; }

/* A second action button sits next to the first, not pushed away from it. */
.act-btn + .act-btn { margin-left: 0; }

@media (max-width: 575.98px) {
    .act-btn { padding: 0 .45rem; }
    .act-btn .act-btn__label { display: none; }
}

/* ---------- Premium panel (card) ---------- */
.pcard {
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 16px;
    /* Defined by the hairline first, lifted by a faint shadow second — restrained. */
    box-shadow: var(--shadow-2);
    overflow: hidden;
    animation: premIn .5s ease both;
}

.pcard + .pcard { margin-top: 1rem; }

.pcard__head {
    display: flex;
    align-items: center;
    gap: .65rem;
    padding: .5rem 1.1rem;
    border-bottom: 1px solid var(--border);
    background: linear-gradient(180deg, #fbfcff, #f5f7fe);
}

.pcard__ico {
    width: 32px;
    height: 32px;
    border-radius: 10px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-size: .95rem;
    flex-shrink: 0;
    background-color: var(--c, var(--accent));
    background-image: linear-gradient(135deg, rgba(255, 255, 255, .3), rgba(255, 255, 255, 0) 55%);
    box-shadow: 0 3px 8px rgba(15, 23, 42, .18), inset 0 1px 0 rgba(255, 255, 255, .4);
}

.pcard__title {
    font-weight: 700;
    font-size: .95rem;
    letter-spacing: .1px;
}

.pcard__sub {
    margin-left: auto;
    font-size: .75rem;
    color: var(--muted);
    font-weight: 600;
}

.pcard__body { padding: .65rem 1.1rem; }

.pcard__foot {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: .5rem;
    padding: .5rem 1.1rem;
    border-top: 1px solid var(--border);
    background: #fbfcff;
}

/* ---------- Setting rows ---------- */
.set-row {
    display: flex;
    align-items: center;
    gap: .9rem;
    padding: .85rem .3rem;
    border-bottom: 1px solid var(--border);
    transition: background .15s ease;
}

.set-row:last-child { border-bottom: none; }
.set-row:hover { background: var(--hover-tint); }

.set-row__ico {
    width: 40px;
    height: 40px;
    border-radius: 12px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-size: 1.05rem;
    flex-shrink: 0;
    background-color: var(--c, var(--accent));
    background-image: linear-gradient(135deg, rgba(255, 255, 255, .28), rgba(255, 255, 255, 0) 55%);
    box-shadow: 0 4px 10px rgba(15, 23, 42, .16), inset 0 1px 0 rgba(255, 255, 255, .4);
}

.set-row__text { flex: 1; min-width: 0; }

.set-row__label {
    font-weight: 600;
    font-size: .92rem;
    color: #1e2432;
}

.set-row__desc {
    font-size: .78rem;
    color: var(--muted);
    margin-top: .1rem;
}

/* ---------- Fields ---------- */
.field { margin-bottom: .9rem; }

.field > label,
.field-label {
    display: block;
    font-weight: 600;
    font-size: .78rem;
    color: #475569;
    margin-bottom: .35rem;
    letter-spacing: .1px;
}

.field-label .opt {
    color: var(--muted);
    font-weight: 500;
}

.pcard .form-control,
.pcard .form-select {
    background-color: #f9fafe;
}

.pcard .form-control:focus,
.pcard .form-select:focus {
    background-color: var(--surface);
}

/* ---------- Premium switch ---------- */
.pcard .form-switch { padding-left: 0; min-height: auto; }

.pcard .form-switch .form-check-input {
    width: 2.7em;
    height: 1.45em;
    margin: 0;
    cursor: pointer;
    background-color: #cbd2e0;
    border: none;
    box-shadow: inset 0 1px 2px rgba(15, 23, 42, .2);
}

.pcard .form-switch .form-check-input:checked {
    background-color: var(--accent);
    box-shadow: inset 0 1px 2px rgba(67, 56, 202, .4), 0 2px 8px rgba(99, 102, 241, .35);
}

/* ---------- Soft / ghost buttons ---------- */
.btn-soft {
    background: var(--accent-soft);
    border: 1px solid var(--border);
    color: var(--accent-dark);
    border-radius: 8px;
    font-weight: 600;
    transition: background .15s ease, transform .1s ease, box-shadow .15s ease;
}

.btn-soft:hover {
    background: #e5e9fb;
    color: var(--accent-dark);
    transform: translateY(-1px);
    box-shadow: 0 6px 14px rgba(99, 102, 241, .16);
}

/* ---------- Premium table inside a panel ---------- */
.pcard .table { margin: 0; }

.pcard .table > thead > tr > th {
    font-size: .7rem;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: var(--muted);
    border-bottom: 1px solid var(--border);
    font-weight: 700;
    padding: .3rem .6rem;
}

.pcard .table > tbody > tr > td {
    padding: .38rem .6rem;
    border-color: var(--border);
    vertical-align: middle;
}

.pcard .table > tbody > tr:last-child > td { border-bottom: none; }

.pcard .table > tbody > tr { transition: background .15s ease; }
.pcard .table > tbody > tr:hover { background: var(--hover-tint); }

/* ---------- Logo dropzone ---------- */
/* ---------- Premium checkbox chips (assignment modals) ---------- */
.check-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: .5rem;
}

.check-chip {
    display: flex;
    align-items: center;
    gap: .55rem;
    margin: 0;
    padding: .55rem .7rem;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--surface);
    cursor: pointer;
    transition: border-color .15s ease, background .15s ease, box-shadow .15s ease;
}

.check-chip:hover { border-color: #c3cbe4; background: var(--hover-tint); }

.check-chip:has(input:checked) {
    border-color: var(--accent);
    background: var(--accent-soft);
    box-shadow: 0 2px 10px rgba(99, 102, 241, .16);
}

.check-chip input {
    margin: 0;
    flex-shrink: 0;
    width: 1.05em;
    height: 1.05em;
}

.check-chip span {
    font-size: .85rem;
    font-weight: 600;
    color: #1e2432;
    line-height: 1.15;
}

/* ---------- Compact table rows: fit more records per screen ---------- */
table.premium-table tbody td {
    padding: .28rem .5rem;
    line-height: 1.2;
}

table.premium-table thead th {
    padding: .32rem .5rem;
    line-height: 1.2;
    cursor: pointer;
    user-select: none;
    white-space: nowrap;
}

table.premium-table thead th[data-nosort] { cursor: default; }

table.premium-table .avatar-circle {
    width: 26px;
    height: 26px;
    min-width: 26px;
    font-size: .7rem;
}

table.premium-table .form-control-sm,
table.premium-table .form-select-sm {
    padding: .1rem .4rem;
    font-size: .75rem;
    min-height: 0;
    height: 26px;
}

table.premium-table .icon-btn {
    width: 28px;
    height: 28px;
    font-size: .8rem;
}

table.premium-table .badge-status {
    padding: .1rem .45rem;
    font-size: .68rem;
}

table.premium-table .form-check-input {
    margin-top: 0;
}

/* ---------- Premium toasts (global) ---------- */
.toast-stack {
    position: fixed;
    top: 1rem;
    right: 1rem;
    z-index: 1090;
    display: flex;
    flex-direction: column;
    gap: .5rem;
    max-width: 340px;
}

.app-toast {
    position: relative;
    display: flex;
    align-items: center;
    gap: .6rem;
    overflow: hidden;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: .6rem .7rem;
    box-shadow: 0 10px 26px rgba(15, 23, 42, .16);
    animation: appToastIn .25s ease;
}

.app-toast__ico {
    width: 26px;
    height: 26px;
    border-radius: 6px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    color: #fff;
    font-size: .85rem;
    background: var(--accent);
    background-image: linear-gradient(135deg, rgba(255, 255, 255, .28), rgba(255, 255, 255, 0) 60%);
}

.app-toast__msg {
    flex: 1;
    font-size: .82rem;
    font-weight: 500;
    color: #1e2432;
}

.app-toast .btn-close { font-size: .6rem; }

.app-toast__bar {
    position: absolute;
    left: 0;
    bottom: 0;
    height: 2px;
    background: var(--accent);
    animation: appToastBar 4s linear forwards;
}

.app-toast.is-success .app-toast__ico,
.app-toast.is-success .app-toast__bar { background-color: var(--success); }

.app-toast.is-error .app-toast__ico,
.app-toast.is-error .app-toast__bar { background-color: var(--danger); }

.app-toast.is-warning .app-toast__ico,
.app-toast.is-warning .app-toast__bar { background-color: #f59e0b; }

@keyframes appToastIn {
    from { transform: translateX(20px); opacity: 0; }
    to { transform: none; opacity: 1; }
}

@keyframes appToastBar {
    from { width: 100%; }
    to { width: 0; }
}

/* ---------- Alert bubbles (school notifications) ----------
   Sits below the toast stack: a toast reports what YOU just did and disappears, a bubble
   reports what the SCHOOL just sent and stays until dismissed or opened. Bottom-anchored so
   the two never fight for the same corner, and clear of the mobile nav bar. */
.bubble-stack {
    position: fixed;
    right: 1rem;
    bottom: 1rem;
    z-index: 1085;
    display: flex;
    flex-direction: column;
    gap: .5rem;
    max-width: 340px;
}

@media (max-width: 767.98px) {
    .bubble-stack {
        left: 1rem;
        right: 1rem;
        bottom: 4.75rem;
        max-width: none;
    }
}

.alert-bubble {
    position: relative;
    display: flex;
    align-items: flex-start;
    gap: .6rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-left: 3px solid #ec4899;
    border-radius: 10px;
    padding: .65rem .7rem;
    box-shadow: 0 10px 26px rgba(15, 23, 42, .18);
    animation: appToastIn .25s ease;
    text-align: left;
}

.alert-bubble__ico {
    width: 26px;
    height: 26px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    color: #fff;
    font-size: .8rem;
    background: #ec4899;
    background-image: linear-gradient(135deg, rgba(255, 255, 255, .28), rgba(255, 255, 255, 0) 60%);
}

.alert-bubble__body { flex: 1; min-width: 0; }

.alert-bubble__title {
    display: block;
    font-size: .8rem;
    font-weight: 800;
    color: #1e2432;
}

/* The alert body is a labelled block, so its newlines must survive. Long alerts are
   clamped: the full text is one tap away in the inbox. */
.alert-bubble__msg {
    display: -webkit-box;
    -webkit-line-clamp: 5;
    -webkit-box-orient: vertical;
    overflow: hidden;
    margin: .15rem 0 0;
    font-size: .76rem;
    line-height: 1.45;
    white-space: pre-line;
    color: #55607a;
}

.alert-bubble .btn-close {
    font-size: .55rem;
    flex-shrink: 0;
    margin-top: .1rem;
}

/* ---------- Column show/hide toggle bar (above tables) ---------- */
/* One row above the table: column chips on the left, search on its right.
   Most pages hide the chips below md (d-none d-md-flex), so the search takes the
   row alone. A page that keeps them — the marks grid, where hiding a subject
   column is how a phone-sized grid stays usable — gets them on a second line
   under the search instead. */
.list-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .4rem;
    margin-bottom: .55rem;
}

.list-bar .col-toggle {
    flex: 1 1 auto;
    min-width: 0;
    margin-bottom: 0;
    width: auto;
}

.list-bar .list-search {
    flex: 0 0 240px;
    width: 240px;
}

@media (max-width: 767.98px) {
    /* Search first, chips under it — `order` rather than markup order so the
       desktop layout (chips left, search right) stays a single source. */
    .list-bar .list-search { flex: 1 1 100%; width: auto; order: 1; }
    .list-bar .col-toggle { flex: 1 1 100%; order: 2; }

    /* On a wide bar the chips share the row equally so it spans the table. On a
       phone that division is the problem: eight subjects would give each chip
       ~40px and every label would be an ellipsis. They size to their text and
       wrap onto as many lines as they need — a chip you cannot read is not a
       control. */
    .col-toggle .check-chip { flex: 0 1 auto; }
}

.col-toggle {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .35rem;
    margin-bottom: .55rem;
    width: 100%;
}

/* Chips share the row equally so the bar spans the full table width. */
.col-toggle .check-chip {
    flex: 1 1 0;
    min-width: 0;
    justify-content: center;
    padding: .28rem .55rem;
    border-radius: 8px;
}

.col-toggle .check-chip span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.col-toggle .check-chip span { font-size: .74rem; }

.col-toggle .check-chip input {
    width: .95em;
    height: .95em;
}

/* ---------- Premium icon fields (colored input-group addon, no labels) ---------- */
/* ---------- Attendance status buttons ---------- */
/* Four statuses (P / A / L / H) sit on one line — the group never wraps, so a
   narrow Status column shrinks the buttons rather than stacking them. */
.att-btn-group {
    display: flex;
    flex-wrap: nowrap;
    gap: .25rem;
    justify-content: center;
}

/* Square buttons: fixed box rather than flex-fill, so a wide column can't stretch them. */
.att-btn-group .att-btn {
    flex: 0 0 auto;
    width: 22px;
    height: 22px;
    padding: 0;
    font-size: .66rem;
    font-weight: 700;
    line-height: 1;
    border-radius: 5px;
}

/* ---------- Attendance tally + bulk bar ---------- */
.att-bar {
    display: flex;
    align-items: center;
    gap: .5rem;
    flex-wrap: wrap;
    margin-bottom: .4rem;
}

.att-tally {
    display: flex;
    gap: .3rem;
    flex-wrap: wrap;
}

.att-chip {
    display: inline-flex;
    align-items: center;
    gap: .25rem;
    padding: .1rem .45rem;
    border-radius: 999px;
    font-size: .66rem;
    font-weight: 600;
    background: var(--surface-3);
    color: var(--muted);
    border: 1px solid var(--border);
}

.att-chip b { font-weight: 800; color: var(--text); }
.att-chip.is-success { background: #ecfdf5; border-color: #a7f3d0; }
.att-chip.is-success b { color: #047857; }
.att-chip.is-danger { background: #fef2f2; border-color: #fecaca; }
.att-chip.is-danger b { color: #b91c1c; }
.att-chip.is-warning { background: var(--warn-bg); border-color: #fde68a; }
.att-chip.is-warning b { color: #b45309; }

.att-bulk {
    display: flex;
    align-items: center;
    gap: .35rem;
    margin-left: auto;
}

.att-bulk-label {
    font-size: .66rem;
    font-weight: 700;
    color: var(--muted);
    text-transform: uppercase;
    letter-spacing: .03em;
}

/* A datesheet field whose scoped sections disagree: blank, but visibly not empty-by-default. */
.ds-f.is-mixed {
    border-style: dashed;
    border-color: #f59e0b;
    background: var(--warn-bg);
}

/* ---------- Marks entry grid (spreadsheet-style) ----------
   Deliberately unlike the other premium tables: continuous gridlines, grey column
   headers and edge-to-edge cells, so bulk keying feels like a spreadsheet. */
/* Capped height so the wrapper (not the page) scrolls — that is what lets the
   column headers stay stuck while keying long sections. */
.table-card:has(.mk-grid) {
    border-radius: 4px;
    padding: 0;
    max-height: 72vh;
    overflow: auto;
}

table.mk-grid {
    border-collapse: separate;
    border-spacing: 0;
    font-variant-numeric: tabular-nums;
}

table.mk-grid thead th {
    position: sticky;
    top: 0;
    z-index: 2;
    background: var(--surface-3);
    border: 1px solid #c6cdd5;
    border-left-width: 0;
    border-top-width: 0;
    padding: .18rem .25rem;
    text-align: center;
    font-size: .66rem;
    font-weight: 700;
    color: #374151;
    text-transform: none;
    letter-spacing: 0;
}

table.mk-grid thead th:first-child { border-left-width: 1px; }

table.mk-grid th .mk-total {
    font-size: .58rem;
    font-weight: 600;
    color: var(--muted);
}

table.mk-grid tbody td {
    padding: 0;
    border: 1px solid #dde2e8;
    border-left-width: 0;
    border-top-width: 0;
    text-align: center;
    font-size: .72rem;
    background: var(--surface);
}

table.mk-grid tbody td:first-child { border-left-width: 1px; }
table.mk-grid tbody tr:hover td { background: #f7fbff; }

table.mk-grid .mk-name {
    padding: .1rem .35rem;
    text-align: left;
    white-space: nowrap;
}

/* Mark cells hold at most 3 characters ("100" / "A"), so keep them tight and let the
   name column take the space back. Borderless: the cell's own gridline is the border. */
table.mk-grid .mk-cell {
    width: 100%;
    min-width: 34px;
    text-align: center;
    padding: .1rem;
    font-size: .72rem;
    height: 22px;
    min-height: 0;
    border: 0;
    border-radius: 0;
    background: transparent;
    box-shadow: none;
}

/* Excel-style: the active cell is ringed rather than merely tinted. */
table.mk-grid .mk-cell:focus {
    outline: 2px solid #217346;
    outline-offset: -2px;
    background: var(--surface);
    box-shadow: none;
}

/* Absent cells read as a state, not a typo. */
table.mk-grid .mk-cell.is-absent {
    background: #fdeaea;
    color: #b91c1c;
    font-weight: 700;
}

/* A mark over the subject's total, or not a number at all. The grid autosaves, so
   this cell is the one thing on the page that is NOT being written — it has to
   look wrong, not merely be wrong. Ringed rather than bordered: the cell has
   `border: 0` above and its gridline belongs to the <td>.
   Bootstrap's own `.is-invalid` cannot do this job here — `.mk-cell` overrides
   border, background and box-shadow at a higher specificity, so its red border
   and warning glyph would both be swallowed. */
table.mk-grid .mk-cell.is-invalid {
    background: #fef2f2;
    color: #b91c1c;
    font-weight: 700;
    box-shadow: inset 0 0 0 2px #ef4444;
}
table.mk-grid .mk-cell.is-invalid:focus { outline-color: #ef4444; }

table.mk-grid .mk-sum {
    font-size: .72rem;
    font-weight: 600;
    white-space: nowrap;
    background: #fafbfc;
}

table.mk-grid .mk-rank, table.mk-grid .mk-pct { background: #fafbfc; }

/* ---------- Monthly register grid ---------- */
table.att-register td.reg-day {
    padding: .1rem;
    text-align: center;
    cursor: pointer;
    font-size: .62rem;
    font-weight: 700;
}

table.att-register td.reg-day.is-P { background: #ecfdf5; color: #047857; }
table.att-register td.reg-day.is-A { background: #fef2f2; color: #b91c1c; }
table.att-register td.reg-day.is-L { background: var(--warn-bg); color: #b45309; }
table.att-register td.reg-day.is-H { background: #ecfeff; color: #0e7490; }
table.att-register td.reg-day.is-off { background: var(--surface-3); color: #cbd5e1; cursor: default; }
table.att-register th.reg-dow { font-size: .55rem; color: var(--muted); font-weight: 600; }
table.att-register th { text-align: center; }
table.att-register th:first-child, table.att-register td:first-child { text-align: left; }

/* Attendance is the one table that stays a table on phones, so squeeze it to fit. */
@media (max-width: 767.98px) {
    table.att-table tbody td,
    table.att-table thead th {
        padding: .2rem .3rem;
        font-size: .68rem;
        line-height: 1.15;
    }

    table.att-table .att-btn-group { gap: .12rem; }

    table.att-table .att-btn-group .att-btn {
        width: 22px;
        height: 22px;
        font-size: .58rem;
    }
}

/* ==== BEGIN marks grid polish ====
   Self-contained: delete this whole block to return to the plain spreadsheet look. */

/* Header reads as a fixed rail: subtle depth, and a shadow once the body scrolls under it. */
table.mk-grid thead th {
    background: linear-gradient(180deg, #f8fafc, #eceff3);
    box-shadow: 0 1px 0 #c6cdd5;
    color: #1f2937;
    cursor: default;
}

table.mk-grid thead th .mk-total { color: #8a93a2; font-weight: 500; }

/* A firm rule where data entry stops and computed columns begin. */
table.mk-grid .mk-edge { border-left: 2px solid #c6cdd5 !important; }

/* Computed block: flat, recessive, clearly not typeable. */
table.mk-grid .mk-sum,
table.mk-grid .mk-pct,
table.mk-grid .mk-rank {
    background: #f7f8fa;
    color: #475569;
}

table.mk-grid .mk-name { color: #1f2937; }
table.mk-grid .mk-name .fw-semibold { color: #0f172a; }

/* Typing surface: quiet until touched, then unmistakable. */
table.mk-grid .mk-cell {
    color: #111827;
    caret-color: #217346;
}

table.mk-grid .mk-cell:hover:not(:focus) { background: #f2f6ff; }
table.mk-grid .mk-cell::placeholder { color: #cbd5e1; }

table.mk-grid tbody tr:hover td { background: #f4f8ff; }
table.mk-grid tbody tr:hover .mk-sum,
table.mk-grid tbody tr:hover .mk-pct,
table.mk-grid tbody tr:hover .mk-rank { background: var(--surface-3); }

/* On a phone the grid keeps only what you need to TYPE: the roll number and the mark
   boxes. The name is the widest column and the ranks are the least useful mid-entry, so
   both step aside rather than pushing the boxes off-screen. Roll identifies the row. */
@media (max-width: 767.98px) {
    table.mk-grid .mk-col-name,
    table.mk-grid .mk-col-rank { display: none; }

/* Taller boxes: these are finger targets on a phone, not mouse targets.
       padding is reset because the shared .att-table phone rule would otherwise
       pad the cell around an input that is already full-bleed. */
    table.mk-grid .mk-cell { height: 30px; font-size: .8rem; min-width: 40px; }
    table.mk-grid tbody td { font-size: .76rem; padding: 0; }
}

/* ==== END marks grid polish ==== */

/* ---------- Charts ----------
   Ink and gridlines are recessive; only the data carries colour. Series hues live
   in the page's JS (validated categorical slots), not here. */
.viz-card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 14px;
    box-shadow: 0 10px 30px rgba(15, 23, 42, .05);
    padding: .7rem .8rem .5rem;
    height: 100%;
}

.viz-head { margin-bottom: .35rem; }

.viz-title {
    margin: 0;
    font-size: .8rem;
    font-weight: 700;
    color: #0b0b0b;
}

.viz-sub {
    margin: 0;
    font-size: .66rem;
    color: #898781;
}

.viz-plot { width: 100%; }
.viz-plot--meter { display: flex; align-items: center; min-height: 118px; }

.viz-empty {
    margin: 0;
    padding: 2rem 0;
    text-align: center;
    font-size: .72rem;
    color: #898781;
}

/* Text wears ink tokens, never the series colour. */
.viz-tick { font-size: 9px; fill: #898781; font-variant-numeric: tabular-nums; }
.viz-legend { font-size: 10px; fill: #52514e; }
.viz-endlabel { font-size: 10px; font-weight: 700; fill: #52514e; }
.viz-sublabel { font-size: 10px; fill: #52514e; }
.viz-figure { font-size: 34px; font-weight: 700; fill: #0b0b0b; }

.viz-tip {
    position: fixed;
    z-index: 1090;
    display: none;
    padding: .3rem .5rem;
    border-radius: 7px;
    background: rgba(15, 23, 42, .94);
    color: #fff;
    font-size: .68rem;
    line-height: 1.35;
    pointer-events: none;
    box-shadow: 0 6px 18px rgba(0, 0, 0, .25);
}

.viz-tip b { font-weight: 700; }

/* Table twin: the values a tooltip shows must be readable without hovering. */
.viz-table { margin-top: .35rem; }

.viz-table summary {
    cursor: pointer;
    font-size: .66rem;
    color: #52514e;
    list-style: none;
}

.viz-table summary::before { content: '⊞ '; color: #898781; }
.viz-table[open] summary::before { content: '⊟ '; }

.viz-table table {
    width: 100%;
    margin-top: .3rem;
    font-size: .68rem;
    font-variant-numeric: tabular-nums;
    border-collapse: collapse;
}

.viz-table th, .viz-table td {
    padding: .15rem .35rem;
    border-bottom: 1px solid var(--border);
    text-align: left;
}

.viz-table th { color: #898781; font-weight: 600; }
.viz-table td { color: #0b0b0b; }

/* ---------- Pager ---------- */
.pager {
    display: flex;
    align-items: center;
    gap: .5rem;
    flex-wrap: wrap;
    margin: .5rem 0 1rem;
    padding: .3rem .5rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 10px;
    font-size: .72rem;
}

.pager-info { color: var(--muted); }
.pager-info b { color: var(--text); }

.pager-btns {
    display: flex;
    align-items: center;
    gap: .25rem;
    margin-left: auto;
}

.pager-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border-radius: 6px;
    border: 1px solid var(--border);
    background: var(--surface);
    color: var(--text);
    text-decoration: none;
    font-size: .7rem;
}

.pager-btn:hover { background: var(--accent); border-color: var(--accent); color: #fff; }

.pager-page {
    padding: 0 .4rem;
    font-weight: 600;
    color: var(--text);
    white-space: nowrap;
}

.pager-per {
    height: 24px;
    padding: 0 .3rem;
    border: 1px solid var(--border);
    border-radius: 6px;
    background: var(--surface);
    font-size: .7rem;
    color: var(--text);
}

/* ---------- Segmented date field ----------
   The box wears .form-control so it inherits the theme's border, height and sizing and
   drops straight into an .input-group; the three inputs inside are stripped bare. */
.dt-seg {
    display: flex;
    align-items: center;
    gap: 1px;
    cursor: text;
    /* .form-control is display:block; keep its own padding but let the boxes breathe. */
    padding-left: .55rem;
    padding-right: .35rem;
}

.dt-seg:focus-within {
    border-color: var(--accent);
    box-shadow: 0 0 0 .18rem var(--accent-soft);
    outline: 0;
}

.dt-seg.is-invalid { border-color: var(--danger); }
.dt-seg.is-invalid:focus-within { box-shadow: 0 0 0 .18rem rgba(239, 68, 68, .18); }

/* The words that used to live in the placeholder — "From", "Due date". The boxes
   themselves say dd/mm/yyyy, so only the labelling part is worth keeping. */
.dt-pre {
    flex: 0 1 auto;
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    margin-right: .3rem;
    color: var(--muted);
    font-size: .82em;
}

.dt-part {
    flex: 0 0 auto;
    min-width: 0;
    padding: 0;
    border: 0;
    border-radius: 3px;
    background: transparent;
    color: inherit;
    font: inherit;
    font-variant-numeric: tabular-nums;
    text-align: center;
    -moz-appearance: textfield;
}

.dt-part:focus { outline: 0; background: var(--accent-soft); }
.dt-part::placeholder { color: var(--muted); opacity: .75; letter-spacing: -.02em; }
.dt-part:disabled { color: var(--muted); }

.dt-d, .dt-m { width: 2.1ch; }
.dt-y { width: 3.9ch; }

.dt-sep {
    flex: 0 0 auto;
    color: var(--muted);
    padding: 0 .05rem;
    user-select: none;
}

/* Always holds its slot so filling the field never nudges the boxes sideways. */
.dt-clear {
    flex: 0 0 auto;
    width: 1rem;
    height: 1rem;
    margin-left: auto;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--muted);
    font-size: .95rem;
    line-height: 1;
    visibility: hidden;
    cursor: pointer;
}

.dt-seg.is-filled:hover .dt-clear,
.dt-seg.is-filled:focus-within .dt-clear { visibility: visible; }
.dt-clear:hover { background: rgba(239, 68, 68, .14); color: var(--danger); }

/* A datesheet cell whose scoped sections disagree keeps its dashed warning. */
.ds-f.is-mixed + .dt-seg {
    border-style: dashed;
    border-color: #f59e0b;
    background: var(--warn-bg);
}

/* Phones: give the digits a real tap target, and never let the row wrap mid-date. */
@media (max-width: 576px) {
    .dt-part { padding: .15rem 0; }
    .dt-d, .dt-m { width: 2.4ch; }
    .dt-y { width: 4.2ch; }
}

html[data-theme="dark"] .dt-part:focus { background: rgba(148, 163, 184, .18); }

/* ---------- Mobile field layout ----------
   Filter bars and page cards pack two fields per row. MODALS deliberately do NOT:
   a dialog on a phone gets ONE field per row whatever column classes the view used
   (col-6, col-4, col-md-6 — all of them), so every field keeps room for its label,
   its hint and the icon addon. This overrides Bootstrap's own column widths, which
   is the point: a modal is already a narrow surface on a phone. */
@media (max-width: 767.98px) {
    .toolbar-card .row > [class*="col-"],
    .pcard .row > [class*="col-"] {
        flex: 0 0 50%;
        max-width: 50%;
        width: 50%;
    }

    .modal-body .row > [class*="col-"] {
        flex: 0 0 100%;
        max-width: 100%;
        width: 100%;
    }

/* A field that can't work at half width keeps the whole row: the roll-number
       composite, textareas, checkbox chip grids, and anything marked .col-keep.
       Modals need no entry here — they are already one per row above. */
    .toolbar-card .row > .col-keep,
    .pcard .row > .col-keep,
    .toolbar-card .row > [class*="col-"]:has(textarea),
    .pcard .row > [class*="col-"]:has(textarea),
    .pcard .row > [class*="col-"]:has(.check-grid),
    .pcard .row > [class*="col-"]:has(#rollPrefixBox) {
        flex: 0 0 100%;
        max-width: 100%;
        width: 100%;
    }
}

/* The icon addon shrinks with the field — at half-width there is less room to spare. */
.input-group-text.pf-ico {
    min-width: 24px;
    font-size: .7rem;
    justify-content: center;
    color: #fff;
    border-color: transparent;
    background-color: var(--c, var(--accent));
    background-image: linear-gradient(135deg, rgba(255, 255, 255, .28), rgba(255, 255, 255, 0) 60%);
}

/* ---------- WhatsApp setting (admin/setting/whatsapp/) ----------
   Two card families, both living inside a .pcard body: .wa-num for each linked number and
   .trg for each message trigger. Both draw on the shared tokens above — the only new colour
   is WhatsApp's own green, used as an accent and never as a surface. */

.wa-nums {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(15.5rem, 1fr));
    gap: .85rem;
}

.wa-num {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: .75rem;
    padding: .95rem;
    border: 1px solid var(--border);
    border-radius: 14px;
    background: var(--card-bg);
    box-shadow: var(--shadow-1);
    transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}

/* The green rail carries the status: full when linked, ghosted when not. */
.wa-num::before {
    content: '';
    position: absolute;
    inset: 0 0 auto 0;
    height: 3px;
    border-radius: 14px 14px 0 0;
    background: linear-gradient(90deg, #25d366, #0f9d73);
    opacity: .18;
    transition: opacity .18s ease;
}

.wa-num.is-on::before { opacity: 1; }

.wa-num:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-2);
    border-color: var(--border-strong);
}

.wa-num__top { display: flex; align-items: center; gap: .6rem; }

.wa-num__avatar {
    width: 38px;
    height: 38px;
    border-radius: 11px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-size: 1.05rem;
    flex-shrink: 0;
    background-color: #25d366;
    background-image: linear-gradient(135deg, rgba(255, 255, 255, .3), rgba(255, 255, 255, 0) 55%);
    box-shadow: 0 4px 10px rgba(37, 211, 102, .3), inset 0 1px 0 rgba(255, 255, 255, .4);
}

.wa-num.is-off .wa-num__avatar {
    background-color: #aab2c5;
    box-shadow: 0 4px 10px rgba(16, 19, 31, .12), inset 0 1px 0 rgba(255, 255, 255, .4);
}

.wa-num__id {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: .68rem;
    color: var(--muted);
    letter-spacing: .04em;
}

.wa-num__number {
    font-weight: 800;
    font-size: .98rem;
    letter-spacing: .2px;
    color: var(--text);
    line-height: 1.2;
}

.wa-num__number.is-empty { color: var(--muted); font-weight: 600; font-style: italic; }

.wa-num__body {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .45rem;
    text-align: center;
    padding: .35rem 0;
}

.wa-num__qr {
    width: 170px;
    max-width: 100%;
    border-radius: 10px;
    border: 1px solid var(--border);
    padding: 6px;
    background: var(--surface);
}

.wa-num__foot {
    display: flex;
    align-items: center;
    gap: .4rem;
    padding-top: .7rem;
    border-top: 1px dashed var(--border);
    margin-top: auto;
}

.wa-delay {
    display: flex;
    align-items: center;
    gap: .3rem;
    font-size: .72rem;
    color: var(--muted);
    font-weight: 600;
}

.wa-delay .form-control {
    width: 3.1rem;
    text-align: center;
    padding: .2rem .25rem;
    font-size: .76rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

/* Spinners add nothing at this size and unbalance the field. */
.wa-delay input[type=number] { -moz-appearance: textfield; }
.wa-delay input[type=number]::-webkit-outer-spin-button,
.wa-delay input[type=number]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

.wa-num__acts { display: flex; gap: .3rem; margin-left: auto; }

.wa-icon-btn {
    width: 28px;
    height: 28px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 8px;
    border: 1px solid var(--border);
    background: var(--surface);
    color: var(--muted);
    font-size: .78rem;
    transition: all .15s ease;
}

.wa-icon-btn:hover { color: var(--text); border-color: var(--border-strong); background: var(--hover-tint); }
.wa-icon-btn.is-danger:hover { color: var(--danger); border-color: #fca5a5; background: #fef2f2; }

/* Empty state: a dashed slot that reads as "add one here", not as a broken card. */
.wa-empty {
    grid-column: 1 / -1;
    text-align: center;
    padding: 2rem 1rem;
    border: 1.5px dashed var(--border-strong);
    border-radius: 14px;
    color: var(--muted);
    background: linear-gradient(180deg, #fbfcff, #f6f8fd);
}

.wa-empty i { font-size: 1.6rem; color: #25d366; opacity: .55; }

/* ---------- Trigger / channel card ----------
   One row: icon | label + desc | optional select | on/off switch. Everything on a single
   line keeps the card at its natural height — nothing here is worth a second row.
   Shared by the WhatsApp triggers and the Notification channels; keep it generic. */
.trg {
    display: flex;
    align-items: center;
    gap: .65rem;
    height: 100%;
    padding: .7rem .8rem;
    border: 1px solid var(--border);
    border-radius: 14px;
    background: var(--card-bg);
    box-shadow: var(--shadow-1);
    transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease, opacity .18s ease;
}

.trg:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-2);
    border-color: var(--border-strong);
}

/* An off trigger stays legible but reads as inert — nothing will come from it. */
.trg.is-off { opacity: .62; }
.trg.is-off .trg__ico { filter: grayscale(1); }

.trg__ico {
    width: 38px;
    height: 38px;
    border-radius: 11px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-size: 1rem;
    flex-shrink: 0;
    background-color: var(--c, var(--accent));
    background-image: linear-gradient(135deg, rgba(255, 255, 255, .28), rgba(255, 255, 255, 0) 55%);
    box-shadow: 0 4px 10px rgba(15, 23, 42, .16), inset 0 1px 0 rgba(255, 255, 255, .4);
    transition: filter .18s ease;
}

.trg__body { flex: 1; min-width: 0; }

.trg__label {
    display: flex;
    align-items: center;
    gap: .3rem;
    font-weight: 700;
    font-size: .88rem;
    color: var(--text);
    line-height: 1.25;
}

.trg__desc {
    font-size: .74rem;
    color: var(--muted);
    margin-top: .1rem;
    line-height: 1.35;
    /* One line: the description is a reminder, not documentation, and letting it wrap is
       what would push these cards back out of a single row. */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Sits between the title and the switch — read "send this / from this / on or off". */
.trg__sel {
    flex-shrink: 0;
    width: 6.9rem;
}

.pcard .trg__sel.form-select {
    font-size: .73rem;
    padding: .22rem 1.4rem .22rem .45rem;
    font-weight: 600;
    background-position: right .4rem center;
}

.trg .form-switch { flex-shrink: 0; }

/* Green when live: this switch decides whether a WhatsApp message goes out, so it reads in
   WhatsApp's colour rather than the app accent. Same specificity as the .pcard rule it
   overrides, so it must stay below it in this file. */
.trg .form-switch .form-check-input:checked {
    background-color: #25d366;
    box-shadow: inset 0 1px 2px rgba(6, 95, 70, .35), 0 2px 8px rgba(37, 211, 102, .4);
}

.trg .form-switch .form-check-input:focus {
    box-shadow: 0 0 0 3px rgba(37, 211, 102, .2);
}

/* Attendance outranks the queue — say so, quietly. */
.trg__flag {
    display: inline-flex;
    align-items: center;
    gap: .2rem;
    font-size: .64rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: #b91c1c;
    background: #fef2f2;
    border: 1px solid #fecaca;
    border-radius: 999px;
    padding: .05rem .4rem;
    white-space: nowrap;
}

/* ---------- Send by link ---------- */
.wa-link-out {
    display: flex;
    align-items: center;
    gap: .5rem;
    margin-top: .8rem;
    padding: .6rem .7rem;
    border-radius: 12px;
    border: 1px solid #bbf3d6;
    background: linear-gradient(180deg, #f0fdf7, #e7fbf0);
}

.wa-link-out input {
    border: none;
    background: transparent;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: .74rem;
    color: #0f766e;
    flex: 1;
    min-width: 0;
    padding: 0;
}

.wa-link-out input:focus { outline: none; box-shadow: none; }

.wa-api {
    margin-top: .8rem;
    padding: .6rem .7rem;
    border-radius: 10px;
    background: #f6f8fd;
    border: 1px solid var(--border);
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: .72rem;
    color: var(--text-2);
    overflow-x: auto;
    white-space: nowrap;
}

/* One card per row on phones — a QR beside anything else is unscannably small. */
@media (max-width: 767.98px) {
    .wa-nums { grid-template-columns: 1fr; }
    .wa-num__foot { flex-wrap: wrap; }

/* The select would squeeze the title to nothing on a narrow phone. */
    .trg__sel { width: 5.9rem; }
}

/* ---------- Notification setting (admin/setting/notifications/) ----------
   Reuses the .trg card from the WhatsApp page — same shape, same behaviour: an icon, a
   label, and a switch on one row. Only the bits unique to this page live here. */

/* A channel with nothing behind it. Still shows its stored value, but can't be changed,
   because flipping it would promise something the project cannot do. */
.trg.is-na { background: #fbfcff; }
.trg.is-na .trg__ico { filter: grayscale(1); opacity: .5; }
.trg.is-na .form-check-input { cursor: not-allowed; opacity: .5; }
.trg.is-na:hover { transform: none; box-shadow: var(--shadow-1); border-color: var(--border); }

/* Neutral sibling of .trg__flag — states a fact rather than raising a flag. */
.trg__na {
    display: inline-flex;
    align-items: center;
    gap: .2rem;
    font-size: .64rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--muted);
    background: var(--surface-3);
    border: 1px solid var(--border-strong);
    border-radius: 999px;
    padding: .05rem .4rem;
    white-space: nowrap;
}

/* The live channel gets WhatsApp's green, matching the trigger switches it governs. */
.trg.is-live .form-switch .form-check-input:checked {
    background-color: #25d366;
    box-shadow: inset 0 1px 2px rgba(6, 95, 70, .35), 0 2px 8px rgba(37, 211, 102, .4);
}

.trg.is-live .form-switch .form-check-input:focus {
    box-shadow: 0 0 0 3px rgba(37, 211, 102, .2);
}

/* ---------- Signature preview ----------
   The sender name is appended to every outgoing message, so show that rather than describe
   it: what the admin types is what lands on a parent's phone. */
.nf-prev {
    border-radius: 14px;
    padding: 1rem;
    background:
        radial-gradient(circle at 20% 20%, rgba(37, 211, 102, .06), transparent 45%),
        linear-gradient(180deg, #eef3ec, #e8efe6);
    border: 1px solid #dbe5d8;
}

.nf-prev__bubble {
    position: relative;
    max-width: 21rem;
    margin-left: auto;
    padding: .55rem .7rem;
    border-radius: 12px 12px 2px 12px;
    background: #d9fdd3;
    color: #111b21;
    font-size: .8rem;
    line-height: 1.5;
    white-space: pre-wrap;
    word-break: break-word;
    box-shadow: 0 1px 1px rgba(11, 20, 26, .13);
}

.nf-prev__sig {
    display: block;
    margin-top: .55rem;
    font-weight: 700;
    color: #0f7a54;
}

.nf-prev__sig:empty { display: none; }

.nf-prev__meta {
    display: block;
    text-align: right;
    font-size: .62rem;
    color: #667781;
    margin-top: .15rem;
}

@media (max-width: 767.98px) {
    .nf-prev__bubble { max-width: 100%; }
}

/* ---------- Academic session (admin/setting/academic-session/) ----------
   The page does one thing: pick which year this school is currently in. So each year is a
   selectable tile rather than a table row with a button hidden at the far end. */
.ay-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(10.5rem, 1fr));
    gap: .75rem;
}

.ay {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: .15rem;
    padding: 1.1rem .8rem;
    border: 1.5px solid var(--border);
    border-radius: 14px;
    background: var(--card-bg);
    box-shadow: var(--shadow-1);
    cursor: pointer;
    text-align: center;
    transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease, background .18s ease;
}

.ay:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-2);
    border-color: var(--accent);
}

.ay:focus-visible { outline: none; box-shadow: var(--ring); }

.ay__year {
    font-weight: 800;
    font-size: 1.35rem;
    letter-spacing: -.01em;
    color: var(--text);
    font-variant-numeric: tabular-nums;
    line-height: 1.1;
}

.ay__state {
    margin-top: .45rem;
    font-size: .68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: var(--muted);
}

/* The current session: the one fact this page exists to show. */
.ay.is-current {
    border-color: var(--success);
    background: linear-gradient(180deg, #f4fdf9, #ecfdf5);
    cursor: default;
}

.ay.is-current:hover { transform: none; box-shadow: var(--shadow-1); border-color: var(--success); }
.ay.is-current .ay__year { color: #0f7a54; }
.ay.is-current .ay__state { color: var(--success); }

.ay__tick {
    position: absolute;
    top: .5rem;
    right: .5rem;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--success);
    color: #fff;
    font-size: .68rem;
    box-shadow: 0 2px 6px rgba(16, 185, 129, .45);
}

.ay-empty {
    grid-column: 1 / -1;
    text-align: center;
    padding: 2rem 1rem;
    border: 1.5px dashed var(--border-strong);
    border-radius: 14px;
    color: var(--muted);
    background: linear-gradient(180deg, #fbfcff, #f6f8fd);
}

.ay-empty i { font-size: 1.6rem; color: #f59e0b; opacity: .55; }

@media (max-width: 575.98px) {
    .ay-grid { grid-template-columns: repeat(auto-fill, minmax(8.5rem, 1fr)); }
    .ay { padding: .9rem .6rem; }
    .ay__year { font-size: 1.15rem; }
}

/* ---------- School setting (admin/setting/school/) ---------- */
.ss-logo {
    position: relative;
    width: 100%;
    max-width: 15rem;
    aspect-ratio: 1;
    margin: 0 auto;
    border-radius: 18px;
    border: 1.5px dashed var(--border-strong);
    background:
        radial-gradient(circle at 30% 25%, rgba(91, 94, 240, .05), transparent 55%),
        linear-gradient(180deg, #fbfcff, #f4f6fd);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    cursor: pointer;
    transition: border-color .18s ease, background .18s ease, transform .18s ease;
}

.ss-logo:hover { border-color: var(--accent); transform: translateY(-2px); }
.ss-logo:focus-visible { outline: none; box-shadow: var(--ring); }

/* Dragging a file over it — the whole tile is the target, so it has to say so. */
.ss-logo.is-drag {
    border-color: var(--accent);
    border-style: solid;
    background: var(--accent-soft);
    transform: scale(1.01);
}

.ss-logo img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    padding: .9rem;
}

.ss-logo__empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .35rem;
    color: var(--muted);
    font-size: .78rem;
    font-weight: 600;
    pointer-events: none;
}

.ss-logo__empty i { font-size: 2.4rem; color: #c3cbe4; }

/* Revealed on hover once a logo exists — otherwise there is no affordance to replace it. */
.ss-logo__over {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: .3rem;
    background: rgba(16, 19, 31, .55);
    color: #fff;
    font-size: .78rem;
    font-weight: 700;
    opacity: 0;
    transition: opacity .18s ease;
    pointer-events: none;
}

.ss-logo__over i { font-size: 1.4rem; }
.ss-logo:hover .ss-logo__over,
.ss-logo.is-drag .ss-logo__over { opacity: 1; }
.ss-logo.is-empty .ss-logo__over { display: none; }

/* Busy state while the browser is resizing / the upload is in flight. */
.ss-logo.is-busy { pointer-events: none; }
.ss-logo.is-busy::after {
    content: '';
    position: absolute;
    inset: 0;
    background: rgba(255, 255, 255, .72);
    backdrop-filter: blur(1px);
}

.ss-logo__spin {
    position: absolute;
    inset: 0;
    display: none;
    align-items: center;
    justify-content: center;
    z-index: 1;
}

.ss-logo.is-busy .ss-logo__spin { display: flex; }

.ss-hint {
    text-align: center;
    font-size: .72rem;
    color: var(--muted);
    margin-top: .55rem;
}

/* ---------- Fees module polish ----------
   Inline amount/concession cells read as edit-in-place: tinted, borderless until you touch
   them, right-aligned tabular figures — far calmer than a grid full of hard-bordered inputs. */
.premium-table input.fee-amount,
.premium-table input.fee-discount,
.sa-card input.fee-amount,
.sa-card input.fee-discount {
    text-align: right;
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    border-color: transparent;
    background: #f6f8fd;
    transition: background .15s ease, border-color .15s ease;
}

.premium-table input.fee-amount:hover,
.premium-table input.fee-discount:hover { border-color: var(--border-strong); }

.premium-table input.fee-amount:focus,
.premium-table input.fee-discount:focus,
.sa-card input.fee-amount:focus,
.sa-card input.fee-discount:focus { background: var(--surface); border-color: var(--accent); }

.premium-table input.fee-amount:disabled,
.premium-table input.fee-discount:disabled {
    background: transparent;
    color: var(--muted);
    box-shadow: none;
}

/* A concession is a reduction — tint it so it reads differently from the gross amount. */
.premium-table input.fee-discount:not(:disabled),
.sa-card input.fee-discount:not(:disabled) { color: #b45309; }

/* Net is the number that matters — give it weight. */
.fee-net { font-weight: 700; color: var(--text); font-variant-numeric: tabular-nums; }

/* The By-Section prompt before a section is chosen: a calm empty state, not a bare row. */
.fee-empty {
    text-align: center;
    color: var(--muted);
    padding: 2.4rem 1rem;
}
.fee-empty i { font-size: 1.8rem; color: #cbd3e6; display: block; margin-bottom: .5rem; }

/* ============================================================
   LAYOUT DESIGNS — switchable whole-app themes
   Chosen from the sidebar "Design" dropdown, persisted in
   localStorage, applied as html[data-design="..."] (layout.php
   sets it pre-paint; app.js applyDesign() handles live changes).
   "aurora" is the base look and needs no rules here. Sidebars stay
   dark across every design so their white labels/active text stay
   legible; each design shifts the accent palette, content surface,
   corner radius, elevation and button shape — not just hue.
   ============================================================ */

/* The switcher itself, styled for the dark sidebar. */
.sidebar-design {
    padding: .28rem .42rem;
    border-top: 1px solid rgba(255, 255, 255, .07);
}
.sidebar-design-label {
    display: flex;
    align-items: center;
    gap: .4rem;
    margin: 0 0 .16rem .1rem;
    color: var(--sidebar-text);
    font-size: .62rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .06em;
}
.sidebar-design-label i { font-size: .82rem; }
.sidebar-design-select {
    width: 100%;
    padding: .18rem 1.3rem .18rem .42rem;
    border-radius: 7px;
    border: 1px solid rgba(255, 255, 255, .13);
    background-color: rgba(255, 255, 255, .06);
    color: #e8ecff;
    font-size: .76rem;
    font-weight: 600;
    cursor: pointer;
    -webkit-appearance: none;
    appearance: none;
    /* Same single-caret language as the app fields, in a sidebar-safe ink. */
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 7'%3E%3Cpath d='M1.2 1.6 5 5.2 8.8 1.6' fill='none' stroke='%23cdd3f0' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right .45rem center;
    background-size: 10px 7px;
    transition: border-color .15s ease, background-color .15s ease;
}
.sidebar-design-select:hover { background-color: rgba(255, 255, 255, .1); }
.sidebar-design-select:focus {
    outline: none;
    border-color: rgba(255, 255, 255, .32);
    box-shadow: 0 0 0 3px rgba(255, 255, 255, .08);
}
.sidebar-design-select option { color: #10131f; background: var(--surface); }/* the popup list is on white */

/* Smooth the transition when a design is switched live. */
.app-content,
.table-card,
.toolbar-card,
.sa-card,
.btn-premium,
.form-control,
.form-select,
.nav-btn {
    transition: background-color .25s ease, color .2s ease, border-color .2s ease, box-shadow .2s ease;
}

/* ---------- Ocean — sky-blue, roomy corners, soft cool shadows ---------- */
html[data-design="ocean"] {
    --accent: #0ea5e9; --accent-dark: #0369a1; --accent-2: #06b6d4;
    --accent-soft: #e0f2fe; --ring: 0 0 0 3px rgba(14, 165, 233, .18);
    --content-bg: #eef4fb; --border: #dbe6f2; --border-strong: #c6d7ea;
    --shadow-1: 0 1px 2px rgba(9, 55, 90, .05);
    --shadow-2: 0 2px 4px rgba(9, 55, 90, .05), 0 10px 24px -8px rgba(9, 55, 90, .16);
    --shadow-3: 0 4px 10px rgba(9, 55, 90, .06), 0 20px 46px -14px rgba(9, 55, 90, .22);
}
html[data-design="ocean"] .app-sidebar {
    background: linear-gradient(180deg, #0a2a4a 0%, #0a2540 45%, #071a30 100%);
}
html[data-design="ocean"] .table-card { border-radius: 16px; }
html[data-design="ocean"] .toolbar-card,
html[data-design="ocean"] .sa-card { border-radius: 14px; }html[data-design="ocean"] .btn-premium { border-radius: 10px; }
html[data-design="ocean"] .form-control,
html[data-design="ocean"] .form-select,
html[data-design="ocean"] .input-group-text { border-radius: 9px; }

/* ---------- Emerald — deep green, crisp default geometry ---------- */
html[data-design="emerald"] {
    --accent: #059669; --accent-dark: #047857; --accent-2: #10b981;
    --accent-soft: #e7f7ef; --ring: 0 0 0 3px rgba(5, 150, 105, .18);
    --content-bg: #eef5f1; --border: #dceae2; --border-strong: #c6ddd0;
    --shadow-1: 0 1px 2px rgba(6, 45, 32, .05);
    --shadow-2: 0 2px 4px rgba(6, 45, 32, .05), 0 10px 24px -8px rgba(6, 45, 32, .15);
    --shadow-3: 0 4px 10px rgba(6, 45, 32, .06), 0 20px 46px -14px rgba(6, 45, 32, .2);
}
html[data-design="emerald"] .app-sidebar {
    background: linear-gradient(180deg, #0b3b2a 0%, #08301f 48%, #04231a 100%);
}

/* ---------- Sunset — warm coral, pill buttons, generous rounding ---------- */
html[data-design="sunset"] {
    --accent: #f97316; --accent-dark: #ea580c; --accent-2: #fb7185;
    --accent-soft: #fff0e6; --ring: 0 0 0 3px rgba(249, 115, 22, .18);
    --content-bg: #fbf3ec; --card-bg: #fffdfb; --border: #f0e2d6; --border-strong: #e6cdb8;
    --shadow-1: 0 1px 2px rgba(120, 53, 15, .05);
    --shadow-2: 0 2px 6px rgba(120, 53, 15, .06), 0 12px 28px -8px rgba(120, 53, 15, .16);
    --shadow-3: 0 6px 14px rgba(120, 53, 15, .08), 0 22px 48px -14px rgba(120, 53, 15, .22);
}
html[data-design="sunset"] .app-sidebar {
    background: linear-gradient(180deg, #3b1e2e 0%, #301826 46%, #241019 100%);
}
html[data-design="sunset"] .table-card,
html[data-design="sunset"] .sa-card { border-radius: 20px; }
html[data-design="sunset"] .toolbar-card { border-radius: 16px; }html[data-design="sunset"] .btn-premium { border-radius: 999px; }
html[data-design="sunset"] .nav-btn { border-radius: 12px; }
html[data-design="sunset"] .form-control,
html[data-design="sunset"] .form-select,
html[data-design="sunset"] .input-group-text { border-radius: 12px; }

/* Neutralise the default indigo button glow under the coloured themes. */
html[data-design="ocean"] .btn-premium,
html[data-design="emerald"] .btn-premium,
html[data-design="sunset"] .btn-premium {
    box-shadow: 0 1px 1px rgba(16, 19, 31, .1), 0 8px 18px -6px rgba(16, 19, 31, .28), inset 0 1px 0 rgba(255, 255, 255, .18);
}

/* ---------- Graphite — flat minimal: sharp corners, hairlines, no elevation ---------- */
html[data-design="graphite"] {
    --accent: #334155; --accent-dark: #1e293b; --accent-2: #64748b;
    --accent-soft: #eef1f5; --ring: 0 0 0 3px rgba(51, 65, 85, .16);
    --content-bg: #f4f5f7; --border: #e2e5ea; --border-strong: #cfd4dc;
    --shadow-1: none; --shadow-2: none; --shadow-3: 0 1px 0 rgba(15, 23, 42, .05);
}
html[data-design="graphite"] .app-sidebar {
    background: #14181f;
}
html[data-design="graphite"] .table-card,
html[data-design="graphite"] .toolbar-card,
html[data-design="graphite"] .sa-card { border-radius: 4px; box-shadow: none; }
html[data-design="graphite"] .btn-premium {
    background: var(--accent-dark);
    border-radius: 4px;
    box-shadow: none;
}
html[data-design="graphite"] .btn-premium:hover { background: #0f172a; filter: none; transform: none; box-shadow: none; }
html[data-design="graphite"] .brand-mark { border-radius: 4px; background: var(--accent-2); }html[data-design="graphite"] .nav-btn,
html[data-design="graphite"] .nav-icon-chip,
html[data-design="graphite"] .form-control,
html[data-design="graphite"] .form-select,
html[data-design="graphite"] .input-group-text { border-radius: 4px; }
html[data-design="graphite"] .nav-label { text-transform: uppercase; letter-spacing: .05em; font-size: .72rem; }

/* ---------- List module toolbar: record count chip (used by roster/list pages) ---------- */
.list-count {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    flex: 0 0 auto;
    height: 31px;
    padding: 0 .7rem;
    border-radius: 8px;
    font-size: .74rem;
    font-weight: 600;
    color: var(--muted);
    background: var(--card-bg);
    border: 1px solid var(--border);
    white-space: nowrap;
}
.list-count b { color: var(--text); font-weight: 800; }
.list-count i { color: var(--accent); }
.list-bar .list-count { margin-right: auto; }/* =====================================================================
   EDGY / SHARP THEME
   Square off every rectangular surface,
control,
chip,
avatar and badge so
   the whole project reads hard-edged and technical. Genuinely circular UI is
   deliberately excluded: the dashboard donut (.donut/.donut__hole),
its legend
   dots (.dot),
and toggle switches (.form-switch .form-check-input) stay round.
   !important is intentional here — this is a theme-wide corner reset that must
   beat the many per-component radii (and the dashboard's inline styles).
   ===================================================================== */

/* Cards,
panels,
surfaces */
.pcard,
.table-card,
.toolbar-card,
.stat-card,
.sa-card,
.list-count,
.impersonation-banner,
.app-toast,
.modal-content,
.toast-stack .app-toast,
.alert-bubble,
.bubble-stack .alert-bubble,
.login-shell,
.login-aside,
.kpi-card,
.pager,
.modal-header,
.modal-footer,
/* Dashboard surfaces + bars */
.dash-banner,
.dash-banner__cta,
.kpi-tile,
.mini-tile,
.quick__item,
.recent,
.chart__bar,
.cs-card,
/* WhatsApp settings surfaces + tiles */
.wa-card,
.wa-num,
.wa-empty,
.wa-guide-card,
.wa-triggers,
.trg,
.wa-num__avatar,
.trg__ico,
.wa-link-out,
.wa-api,
.wa-icon-btn,
.wa-num__qr,
/* Buttons + interactive controls */
.btn,
.btn-sm,
.btn-premium,
.submenu-btn,
.act-btn,
.icon-btn,
.pager-btn,
.pager-per,
.nav-link,
.nav-parent,
.topbar-toggle,
.sidebar-close,
.check-chip,
.mobile-nav-btn,
.act-search-wrap,
/* Form fields */
.form-control,
.form-select,
.input-group-text,
.act-search,
.act-select,
.search-input,
.status-select,
.sidebar-design-select,
.login-field .form-control,
.login-btn,
/* Icon tiles,
avatars,
brand — square,
not round */
.nav-icon-chip,
.stat-icon,
.avatar-circle,
.brand-mark,
.cs-icon,
.kpi-tile__ico,
.mini-tile__ico,
.kpi-ico,
.dash-banner .kpi-ico,
.alert-bubble__ico,
/* Badges become sharp tags,
not pills */
.badge-status,
.badge,
.att-chip {
    border-radius: 2px !important;
}

/* Input groups: keep the seam between addon and field crisp on both ends. */
.input-group > :first-child { border-top-left-radius: 2px !important; border-bottom-left-radius: 2px !important; }
.input-group > :last-child  { border-top-right-radius: 2px !important; border-bottom-right-radius: 2px !important; }

/* The active sidebar rail reads sharper as a flat bar. */
.nav-link.active::before { border-radius: 0 !important; box-shadow: none !important; }

/* ---------- Settings pages: compact, label-free, premium form controls ----------
   Shared by every admin/setting/* page (School, Preferences, Notifications, …). Icons +
   placeholders carry the meaning, so no labels; fields stay compact but substantial. */
.ss-page .ss-field { margin-bottom: .4rem; }
.ss-page .ss-field:last-child { margin-bottom: 0; }
.ss-page .form-control,
.ss-page .form-select { height: 32px; font-size: .82rem; font-weight: 500; padding: .24rem .7rem; }
.ss-page textarea.form-control { height: auto; min-height: 60px; line-height: 1.45; }
.ss-page .input-group-text.pf-lbl { font-size: .6rem; }
.ss-page .ss-field--area .input-group-text { align-items: flex-start; padding-top: .35rem; }
.ss-page .form-control::placeholder { color: #9aa3b5; font-weight: 400; }

/* ============================================================
   PREMIUM UI LAYER — dark-theme fixes, progress bar, command
   palette, table tools, page transitions, responsive polish.
   ============================================================ */

/* ---------- Dark theme: targeted fixes for the few spots variables can't reach ---------- */
html[data-theme="dark"] .sidebar-design-select option { color: var(--text); background: var(--card-bg); }
html[data-theme="dark"] .att-chip.is-warning { border-color: rgba(245, 158, 11, .35); }
html[data-theme="dark"] .check-chip:hover { border-color: var(--border-strong); }
html[data-theme="dark"] table.att-register td.reg-day.is-off { color: var(--muted); }
html[data-theme="dark"] .modal-content { background: var(--card-bg); color: var(--text); }
html[data-theme="dark"] .modal-content .form-control,
html[data-theme="dark"] .modal-content .form-select { background-color: var(--surface-3); border-color: var(--border-strong); color: var(--text); }
html[data-theme="dark"] img { filter: brightness(.92); }

/* The topbar theme toggle — mirrors the profile/logout chips. */
.theme-toggle .bi-moon-stars-fill { display: inline-block; }
.theme-toggle .bi-sun-fill { display: none; }
html[data-theme="dark"] .theme-toggle .bi-moon-stars-fill { display: none; }
html[data-theme="dark"] .theme-toggle .bi-sun-fill { display: inline-block; }

/* ---------- Top loading progress bar (SPA navigation) ---------- */
.app-progress {
    position: fixed; top: 0; left: 0; height: 3px; width: 0;
    background: linear-gradient(90deg, var(--accent), var(--accent-2), #ec4899);
    background-size: 200% 100%;
    z-index: 3000; opacity: 0; pointer-events: none;
    transition: width .25s ease, opacity .3s ease;
    animation: progressShimmer 1.2s linear infinite;
}
.app-progress.is-active { opacity: 1; }
@keyframes progressShimmer { to { background-position: -200% 0; } }

/* ---------- Page enter transition (SPA navigation) ---------- */
.app-content.page-leave { opacity: .4; transform: translateY(4px); transition: opacity .15s ease, transform .15s ease; }

/* No fill-mode and a transform-free final frame: a lingering transform on .app-content
   would trap position:fixed descendants (Bootstrap modals rendered inside page content)
   under the body-level .modal-backdrop — the "black layer over the modal" bug. The class
   is also removed on animationend by app.js for the same reason. */
.app-content.page-enter { animation: pageEnter .28s cubic-bezier(.2, .7, .3, 1); }
@keyframes pageEnter {
    from { opacity: 0; transform: translateY(10px); }
    to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
    .app-content.page-enter { animation: none; }
    .app-content.page-leave { transition: none; transform: none; }
}

/* ---------- Command palette (Ctrl+K) ---------- */
.cmdk-backdrop {
    position: fixed; inset: 0; z-index: 2500;
    background: rgba(7, 10, 20, .55);
    backdrop-filter: blur(3px);
    display: none; align-items: flex-start; justify-content: center;
    padding: 10vh 1rem 1rem;
}
.cmdk-backdrop.open { display: flex; }
.cmdk {
    width: 100%; max-width: 620px;
    background: var(--card-bg); color: var(--text);
    border: 1px solid var(--border-strong);
    border-radius: 14px; overflow: hidden;
    box-shadow: var(--shadow-3), 0 30px 80px -20px rgba(0, 0, 0, .5);
    animation: pageEnter .18s ease both;
}
.cmdk-input-wrap { display: flex; align-items: center; gap: .6rem; padding: .85rem 1rem; border-bottom: 1px solid var(--border); }
.cmdk-input-wrap .bi-search { color: var(--muted); font-size: 1.05rem; }
.cmdk-input {
    flex: 1; border: 0; outline: 0; background: transparent;
    color: var(--text); font-size: 1rem; font-weight: 500;
}
.cmdk-input::placeholder { color: var(--muted); }
.cmdk-kbd {
    font-size: .68rem; font-weight: 700; color: var(--muted);
    border: 1px solid var(--border-strong); border-radius: 6px; padding: .15rem .4rem;
    background: var(--surface-3);
}
.cmdk-list { max-height: 55vh; overflow-y: auto; padding: .45rem; }
.cmdk-group { font-size: .68rem; font-weight: 700; text-transform: uppercase; letter-spacing: .07em; color: var(--muted); padding: .55rem .6rem .3rem; }
.cmdk-item {
    display: flex; align-items: center; gap: .7rem;
    padding: .55rem .6rem; border-radius: 9px; cursor: pointer;
    color: var(--text-2); text-decoration: none;
}
.cmdk-item .cmdk-ico {
    width: 30px; height: 30px; border-radius: 8px; flex-shrink: 0;
    display: flex; align-items: center; justify-content: center;
    font-size: .95rem; color: var(--ico-c, var(--accent));
    background: color-mix(in srgb, var(--ico-c, var(--accent)) 13%, transparent);
}
.cmdk-item .cmdk-meta { display: flex; flex-direction: column; min-width: 0; }
.cmdk-item .cmdk-title { font-weight: 600; font-size: .9rem; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cmdk-item .cmdk-sub { font-size: .74rem; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cmdk-item .cmdk-go { margin-left: auto; color: var(--muted); font-size: .8rem; opacity: 0; }
.cmdk-item:hover, .cmdk-item.is-sel { background: var(--accent-soft); }
.cmdk-item.is-sel .cmdk-go { opacity: 1; }
.cmdk-empty { text-align: center; color: var(--muted); padding: 1.6rem 1rem; font-size: .88rem; }
.cmdk-foot {
    display: flex; gap: 1rem; padding: .5rem .9rem; border-top: 1px solid var(--border);
    font-size: .7rem; color: var(--muted); background: var(--surface-2);
}
.cmdk-foot b { font-weight: 700; color: var(--text-2); }

/* Topbar search button */
.topbar-search {
    display: inline-flex; align-items: center; gap: .5rem;
    border: 1px solid var(--border); background: var(--surface-2);
    color: var(--muted); border-radius: 9px; padding: .38rem .7rem;
    font-size: .82rem; font-weight: 500; cursor: pointer;
    transition: border-color .12s ease, color .12s ease, box-shadow .12s ease;
}
.topbar-search:hover { border-color: var(--accent); color: var(--text-2); box-shadow: var(--ring); }
.topbar-search .cmdk-kbd { margin-left: .3rem; }
@media (max-width: 767.98px) {
    .topbar-search span, .topbar-search .cmdk-kbd { display: none; }
    .topbar-search { padding: .45rem .6rem; }
}

/* ---------- Table tools (Export CSV / Print) — injected next to column toggles ---------- */
.table-tools { display: inline-flex; gap: .4rem; margin-left: auto; }
.table-tools .tt-btn {
    display: inline-flex; align-items: center; gap: .35rem;
    border: 1px solid var(--border); background: var(--surface);
    color: var(--text-2); border-radius: 8px; padding: .3rem .65rem;
    font-size: .76rem; font-weight: 600; cursor: pointer;
    transition: border-color .12s ease, color .12s ease, background .12s ease;
}
.table-tools .tt-btn:hover { border-color: var(--accent); color: var(--accent); background: var(--accent-soft); }
[data-coltoggle] { display: flex; flex-wrap: wrap; align-items: center; gap: .35rem; }

/* ---------- Responsive & mobile polish ---------- */
/* Any card that wraps a wide table scrolls sideways on its own — the page never does. */
.pcard, .table-card { max-width: 100%; }
@media (max-width: 991.98px) {
    .pcard { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* Comfortable touch targets. */
    .topbar-toggle, .submenu-btn { min-height: 40px; min-width: 40px; }
    .sidebar-nav .nav-link, .sidebar-nav .nav-parent { min-height: 42px; }
}
@media (max-width: 575.98px) {
    .app-content { padding-left: .7rem !important; padding-right: .7rem !important; }
    .modal-dialog { margin: .6rem; }
    .cmdk-backdrop { padding-top: 4vh; }
}

/* ---------- Dark theme beats every layout design ----------
   The design blocks above re-declare light surfaces (Ocean's --content-bg etc.) and sit
   later in the file than the main dark block, so they'd win the tie on specificity.
   Re-asserting the dark surface set here — after them — settles it: a design keeps its
   accent + geometry in dark mode, but never its light surfaces. */
html[data-theme="dark"] {
    --content-bg: #0b0f1a;
    --card-bg: #131a2b;
    --border: #243049;
    --border-strong: #34405e;
    --surface: #131a2b;
    --surface-2: #172034;
    --surface-3: #1d2740;
    --hover-tint: #1a2338;
    --warn-bg: rgba(245, 158, 11, .13);
    --accent-soft: color-mix(in srgb, var(--accent) 16%, transparent);
    --shadow-1: 0 1px 2px rgba(0, 0, 0, .35);
    --shadow-2: 0 1px 3px rgba(0, 0, 0, .4), 0 3px 10px -5px rgba(0, 0, 0, .5);
    --shadow-3: 0 6px 16px -8px rgba(0, 0, 0, .55), 0 14px 34px -14px rgba(0, 0, 0, .6);
}

/* ---------- Premium modals (global) ----------
   One consistent, considered dialog language with viewport-safe scrolling,
   touch-friendly controls and responsive action areas. */
.modal-backdrop {
    background: radial-gradient(circle at 50% 20%, rgba(43, 52, 84, .3), transparent 45%),
                rgba(7, 10, 20, .66);
}
.modal-backdrop.show {
    opacity: 1;
    backdrop-filter: blur(8px) saturate(.8);
    -webkit-backdrop-filter: blur(8px) saturate(.8);
}

.modal {
    --modal-edge-space: clamp(.75rem, 2.5vw, 1.75rem);
    padding: var(--modal-edge-space) !important;
}
.modal-dialog {
    width: auto;
    margin: auto;
    min-height: calc(100% - (var(--modal-edge-space) * 2));
    display: flex;
    align-items: center;
}

.modal-content {
    position: relative;
    display: flex;
    flex-direction: column;
    width: 100%;
    max-height: calc(100dvh - (var(--modal-edge-space) * 2));
    border: 1px solid var(--border-strong);
    border-radius: 18px;
    background: var(--card-bg);
    color: var(--text);
    box-shadow: 0 2px 5px rgba(15, 23, 42, .08),
                0 24px 60px -18px rgba(0, 0, 0, .38),
                0 48px 110px -35px color-mix(in srgb, var(--accent) 25%, transparent);
    overflow: hidden;
    isolation: isolate;
}
.modal-content::before {
    content: '';
    position: absolute;
    inset: 0 0 auto;
    height: 3px;
    z-index: 4;
    background: linear-gradient(90deg, var(--accent), var(--accent-2) 55%, transparent 92%);
    box-shadow: 0 1px 12px color-mix(in srgb, var(--accent) 26%, transparent);
}
.modal-header {
    flex: 0 0 auto;
    min-height: 68px;
    background: color-mix(in srgb, var(--surface-2) 90%, transparent);
    border-bottom: 1px solid var(--border);
    padding: 1rem 1.25rem;
    gap: .85rem;
    z-index: 2;
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
}
.modal-title {
    color: var(--text);
    font-size: 1rem;
    line-height: 1.25;
    letter-spacing: -.02em;
}
.modal-heading {
    display: flex;
    align-items: center;
    gap: .75rem;
    min-width: 0;
}
.modal-heading__icon {
    width: 38px;
    height: 38px;
    display: inline-grid;
    place-items: center;
    flex: 0 0 38px;
    color: var(--accent);
    background: var(--accent-soft);
    border: 1px solid color-mix(in srgb, var(--accent) 22%, var(--border));
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .35);
}
.modal-heading__copy { min-width: 0; }
.modal-heading__copy small {
    display: block;
    margin-top: .18rem;
    color: var(--muted);
    font-size: .72rem;
    line-height: 1.35;
}
.modal-header .btn-close {
    width: 40px;
    height: 40px;
    flex: 0 0 40px;
    margin: 0 0 0 auto;
    padding: 0;
    border: 1px solid transparent;
    background-size: 12px;
    background-position: center;
    border-radius: 10px;
    opacity: .62;
    transition: background-color .15s ease, border-color .15s ease, opacity .15s ease, transform .15s ease;
}
.modal-header .btn-close:hover {
    opacity: 1;
    background-color: var(--hover-tint);
    border-color: var(--border);
    transform: rotate(4deg);
}
.modal-header .btn-close:focus-visible {
    opacity: 1;
    box-shadow: 0 0 0 3px var(--accent-soft);
}
.modal-body {
    min-height: 0;
    padding: 1.25rem;
    overflow-x: hidden;
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-gutter: stable;
}

/* Keep the complete 16:9 YouTube canvas visible. Width is capped by both viewport
   dimensions, which lets the player modal retain natural/auto height even in a short
   landscape window instead of clipping the lower part of the video. */
.modal.tutorial-player-modal.show {
    display: flex !important;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}
.tutorial-player-modal .modal-dialog {
    width: min(94vw, 1100px, calc(177.78vh - 12.45rem));
    width: min(94vw, 1100px, calc(177.78dvh - 12.45rem));
    max-width: none;
    max-height: calc(100vh - 3.5rem);
    max-height: calc(100dvh - 3.5rem);
    min-height: 0;
    margin: 0;
    flex: 0 0 auto;
}
.tutorial-player-modal .modal-content {
    height: auto;
    max-height: 100%;
    overflow: hidden;
}
.tutorial-player-modal .modal-body {
    flex: 0 0 auto;
    min-height: 0;
    overflow: hidden;
    scrollbar-gutter: auto;
}
.tutorial-player-modal .ratio {
    width: 100%;
    height: auto;
    aspect-ratio: 16 / 9;
}
.tutorial-player-modal .ratio > iframe {
    display: block;
    width: 100%;
    height: 100%;
    border: 0;
    overflow: hidden;
    touch-action: manipulation;
}

/* Desktop player: the iframe itself is exactly one browser-screen high. The title and
   close button float over the top edge, so neither steals height from the YouTube frame.
   YouTube handles non-16:9 desktop windows with its own letterboxing, keeping the complete
   video visible without introducing a scrollbar. */
@media (min-width: 576px) {
    .modal.tutorial-player-modal {
        padding: 0 !important;
    }
    .tutorial-player-modal .modal-dialog {
        width: 100vw;
        height: 100vh;
        height: 100dvh;
        max-width: none;
        max-height: none;
        margin: 0;
    }
    .tutorial-player-modal .modal-content {
        width: 100%;
        height: 100%;
        max-height: none;
        border: 0;
        border-radius: 0;
    }
    .tutorial-player-modal .modal-content::before {
        display: none;
    }
    .tutorial-player-modal .modal-header {
        position: absolute;
        inset: .75rem .75rem auto;
        min-height: 0;
        padding: 0;
        border: 0;
        background: transparent;
        pointer-events: none;
        z-index: 5;
    }
    .tutorial-player-modal .modal-title {
        max-width: calc(100% - 4rem);
        overflow: hidden;
        padding: .45rem .7rem;
        color: #fff;
        background: rgba(3, 7, 18, .76);
        border-radius: 8px;
        text-overflow: ellipsis;
        white-space: nowrap;
        text-shadow: 0 1px 3px #000;
        backdrop-filter: blur(8px);
        -webkit-backdrop-filter: blur(8px);
        pointer-events: auto;
    }
    .tutorial-player-modal .modal-header .btn-close {
        width: 38px;
        height: 38px;
        flex-basis: 38px;
        background-color: rgba(255, 255, 255, .92);
        border-color: rgba(255, 255, 255, .75);
        pointer-events: auto;
    }
    .tutorial-player-modal .modal-body,
    .tutorial-player-modal .ratio {
        width: 100%;
        height: 100vh;
        height: 100dvh;
    }
    .tutorial-player-modal .ratio {
        aspect-ratio: auto;
    }
    .tutorial-player-modal .ratio::before {
        display: none;
    }
    .tutorial-player-modal .ratio > iframe {
        position: static;
    }
}

@media (max-width: 575.98px) {
    .modal.tutorial-player-modal {
        --modal-edge-space: .45rem;
        padding: var(--modal-edge-space) !important;
    }
    .tutorial-player-modal .modal-dialog {
        /* Full phone width in portrait; viewport-height cap keeps every control visible
           when the phone is rotated to landscape. */
        width: min(calc(100vw - .9rem), calc(177.78vh - 8rem));
        width: min(calc(100vw - .9rem), calc(177.78dvh - 8rem));
        max-height: calc(100vh - .9rem);
        max-height: calc(100dvh - .9rem);
        margin: auto;
    }
    .tutorial-player-modal .modal-content {
        border-radius: 12px;
    }
    .tutorial-player-modal .modal-header {
        min-height: 50px;
        padding: .45rem .65rem;
        gap: .5rem;
    }
    .tutorial-player-modal .modal-title {
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        font-size: .88rem;
    }
    .tutorial-player-modal .modal-header .btn-close {
        width: 34px;
        height: 34px;
        flex-basis: 34px;
    }
}

.modal-footer {
    flex: 0 0 auto;
    min-height: 64px;
    background: color-mix(in srgb, var(--surface-2) 90%, transparent);
    border-top: 1px solid var(--border);
    padding: .75rem 1.25rem;
    gap: .55rem;
    z-index: 2;
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
}
.modal-footer .btn {
    min-height: 40px;
    padding-inline: 1rem;
    border-radius: 9px;
    font-size: .8rem;
    font-weight: 700;
}
.modal-footer .btn-premium {
    box-shadow: 0 8px 20px -10px color-mix(in srgb, var(--accent) 65%, transparent);
}
.modal .form-control,
.modal .form-select,
.modal .input-group-text {
    min-height: 42px;
}
.modal .form-control:focus,
.modal .form-select:focus {
    position: relative;
    z-index: 2;
    border-color: color-mix(in srgb, var(--accent) 70%, var(--border));
    box-shadow: 0 0 0 3px var(--accent-soft);
}

/* Entrance: settle down + scale in, instead of Bootstrap's plain slide. */
.modal.fade .modal-dialog {
    opacity: 0;
    transform: translateY(20px) scale(.975);
    transition: transform .24s cubic-bezier(.2, .75, .25, 1), opacity .18s ease;
}
.modal.show .modal-dialog { opacity: 1; transform: none; }

html[data-theme="dark"] .modal-header .btn-close {
    filter: invert(1) grayscale(1);
}

@media (max-width: 575.98px) {
    .modal {
        --modal-edge-space: .5rem;
        padding-top: max(.5rem, env(safe-area-inset-top)) !important;
        padding-bottom: max(.5rem, env(safe-area-inset-bottom)) !important;
    }
    .modal-dialog {
        min-height: calc(100% - 1rem);
        align-items: flex-end;
    }
    .modal-content {
        max-height: calc(100dvh - 1rem - env(safe-area-inset-top) - env(safe-area-inset-bottom));
        border-radius: 16px 16px 8px 8px;
    }
    .modal-header {
        min-height: 62px;
        padding: .8rem .9rem;
    }
    .modal-heading { gap: .65rem; }
    .modal-heading__icon { width: 36px; height: 36px; flex-basis: 36px; }
    .modal-heading__copy small { font-size: .68rem; }
    .modal-body {
        padding: 1rem .9rem;
        scrollbar-gutter: auto;
    }
    .modal-footer {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(112px, 1fr));
        min-height: auto;
        padding: .7rem .9rem max(.7rem, env(safe-area-inset-bottom));
    }
    .modal-footer > .text-muted {
        grid-column: 1 / -1;
        width: 100%;
        margin: 0 0 .2rem !important;
        line-height: 1.4;
    }
    .modal-footer .btn {
        width: 100%;
        min-height: 44px;
        margin: 0 !important;
    }
    .modal .form-control,
    .modal .form-select {
        min-height: 44px;
        font-size: 16px;
    }
}

@media (hover: none), (pointer: coarse) {
    .modal-header .btn-close,
    .modal-footer .btn { min-width: 44px; min-height: 44px; }
}
@media (prefers-reduced-motion: reduce) {
    .modal.fade .modal-dialog { transition: none; transform: none; }
    .modal-header .btn-close:hover { transform: none; }
}

/* ============================================================
   Final polish layer — accessibility, texture, quiet details
   ============================================================ */

/* Keyboard focus: a clear, themed ring only for keyboard users. */
:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: 6px;
}
.btn:focus-visible, .form-control:focus-visible, .form-select:focus-visible { outline-offset: 0; }

/* Text selection in the brand color. */
::selection { background: color-mix(in srgb, var(--accent) 24%, transparent); color: var(--text); }

/* Themed scrollbars (WebKit + Firefox). */
* { scrollbar-width: thin; scrollbar-color: color-mix(in srgb, var(--muted) 38%, transparent) transparent; }
*::-webkit-scrollbar { width: 9px; height: 9px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb {
    background: color-mix(in srgb, var(--muted) 34%, transparent);
    border-radius: 999px;
    border: 2px solid transparent;
    background-clip: content-box;
}
*::-webkit-scrollbar-thumb:hover { background: color-mix(in srgb, var(--muted) 55%, transparent); background-clip: content-box; }

/* Dark-mode autofill: kill the yellow WebKit fill on login and forms. */
html[data-theme="dark"] input:-webkit-autofill,
html[data-theme="dark"] input:-webkit-autofill:hover,
html[data-theme="dark"] input:-webkit-autofill:focus {
    -webkit-text-fill-color: var(--text);
    -webkit-box-shadow: 0 0 0 1000px var(--content-bg) inset;
    transition: background-color 9999s ease-in-out 0s;
}

/* Number inputs: hide the spin buttons until hover — quieter tables and modals. */
input[type="number"]::-webkit-inner-spin-button { opacity: 0; }
input[type="number"]:hover::-webkit-inner-spin-button,
input[type="number"]:focus::-webkit-inner-spin-button { opacity: 1; }

/* Reusable empty state (for any module). */
.empty-state {
    text-align: center;
    padding: 2.6rem 1rem;
    color: var(--muted);
}
.empty-state i { font-size: 2rem; display: block; margin-bottom: .5rem; opacity: .5; }
.empty-state b { display: block; color: var(--text-2); font-size: .95rem; margin-bottom: .2rem; }
.empty-state span { font-size: .8rem; }

/* Motion sensitivity: stop the non-essential movement everywhere. */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: .001s !important;
        animation-iteration-count: 1 !important;
        transition-duration: .001s !important;
        scroll-behavior: auto !important;
    }
}

/* ============================================================
   PREMIUM POLISH 2.0 — one visual language on every page
   Appended last so it wins ties. Everything here uses surface /
   ink tokens, so dark mode and the layout designs inherit it.
   ============================================================ */

/* ---------- Unified summary tiles ----------
   Three tile families grew up in different modules (.stat-card, .kpi-card,
   .mini-tile). They now share one geometry and one type scale, so a summary
   row reads identically on Fees, Hostel, Inventory, Admissions or the
   Dashboard. Wrap tiles in .stat-tiles for a self-balancing grid. */
.stat-tiles {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: .6rem;
    margin-bottom: .9rem;
}

.stat-card, .kpi-card, .mini-tile {
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-left: 3px solid var(--stat-color, var(--accent));
    border-radius: 10px;
    box-shadow: var(--shadow-1);
    padding: .55rem .7rem;
    display: flex;
    align-items: center;
    gap: .6rem;
    min-width: 0;
    transition: transform .15s ease, box-shadow .15s ease, border-color .15s ease;
}

.stat-card:hover, .kpi-card:hover, .mini-tile:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-3);
}

.stat-icon, .kpi-ico, .mini-tile__ico {
    width: 38px;
    height: 38px;
    border-radius: 9px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.05rem;
    color: #fff;
    flex-shrink: 0;
    background: var(--stat-color, var(--accent));
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 2px 6px -2px var(--stat-color, var(--accent));
}

.stat-value, .kpi-value, .mini-tile__val {
    font-weight: 800;
    font-size: 1.3rem;
    line-height: 1.1;
    color: var(--text);
}

.stat-label, .kpi-label, .mini-tile__lbl {
    color: var(--muted);
    font-size: .68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .06em;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.kpi-row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: .6rem;
    margin-bottom: .9rem;
}

/* ---------- Table refinements ---------- */
/* The row you're on is unmistakable: a wash plus a hairline accent rail. */
table.premium-table tbody tr {
    transition: background .12s ease, box-shadow .12s ease;
}

table.premium-table tbody tr:hover {
    background: var(--hover-tint);
    box-shadow: inset 3px 0 0 var(--accent);
}

table.premium-table tbody td {
    vertical-align: middle;
}

/* Dark theme: the header hairline surface must come from a token, not #fcfcfe. */
html[data-theme="dark"] table.premium-table thead th {
    background: var(--surface-2);
    color: var(--muted);
}

/* ---------- Dark-safe status badges ----------
   The light tints were hardcoded; in dark mode they now switch to translucent
   washes of the same hue, so a badge never glows white off a dark card. */
html[data-theme="dark"] .badge-active   { background: rgba(16, 185, 129, .16); color: #6ee7b7; }
html[data-theme="dark"] .badge-inactive { background: rgba(148, 163, 184, .14); color: #94a3b8; }
html[data-theme="dark"] .badge-warning  { background: rgba(245, 158, 11, .15); color: #fcd34d; }
html[data-theme="dark"] .badge-danger   { background: rgba(239, 68, 68, .15); color: #fca5a5; }/* ---------- Focus visibility everywhere ----------
   Keyboard users get the same confident ring on every interactive element,
not just Bootstrap buttons. Mouse clicks stay ring-free (:focus-visible). */
.icon-btn:focus-visible,
.act-btn:focus-visible,
.submenu-btn:focus-visible,
.att-btn:focus-visible,
.topbar-search:focus-visible,
.sidebar-nav .nav-link:focus-visible,
.sidebar-nav .nav-parent:focus-visible {
    outline: none;
    box-shadow: var(--ring);
}

::selection {
    background: color-mix(in srgb, var(--accent) 24%, transparent);
}

/* ---------- Themed content scrollbars ----------
   The sidebar already had refined scrollbars; the content pane and every
   scrolling card now match instead of showing the OS default. */
.app-content, .table-card, .pcard, .marks-wrap, .cmdk-list {
    scrollbar-width: thin;
    scrollbar-color: var(--border-strong) transparent;
}

.app-content::-webkit-scrollbar,
.table-card::-webkit-scrollbar,
.pcard::-webkit-scrollbar { width: 8px; height: 8px; }

.app-content::-webkit-scrollbar-thumb,
.table-card::-webkit-scrollbar-thumb,
.pcard::-webkit-scrollbar-thumb {
    background: var(--border-strong);
    border-radius: 4px;
}

.app-content::-webkit-scrollbar-thumb:hover,
.table-card::-webkit-scrollbar-thumb:hover,
.pcard::-webkit-scrollbar-thumb:hover { background: var(--muted); }

/* ---------- Dark topbar glass ----------
   The glass bar was hardcoded white; dark mode gets the same translucency
   from its own surface. */
html[data-theme="dark"] .app-topbar {
    background: color-mix(in srgb, var(--card-bg) 86%, transparent);
}

/* ---------- Device-deep responsive layer ---------- */
/* Touch devices: comfortable targets without inflating the desktop density. */
@media (pointer: coarse) {
    .icon-btn { width: 42px; height: 42px; }
    .att-btn { min-width: 42px; min-height: 42px; }
    /* …but not the four in a roster row: at 42px each they are wider than a phone's
       Status column. Only the in-table group opts out — the "mark all" buttons in the
       panel head, where there is room, keep the full touch target. */
    table.att-table .att-btn-group .att-btn { min-width: 26px; min-height: 26px; }
    .act-btn, .btn-premium { min-height: 42px; }
    table.premium-table tbody td { padding-top: .6rem; padding-bottom: .6rem; }
}

/* Small phones: the summary grid pairs up, rows tighten, and forms keep
   a 16px input size so mobile browsers never zoom-jump into a field. */
@media (max-width: 420px) {
    .stat-tiles, .kpi-row { grid-template-columns: repeat(2, 1fr); gap: .5rem; }
    .stat-value, .kpi-value, .mini-tile__val { font-size: 1.15rem; }
    .page-actions { gap: .4rem; }
    .sa-card { padding: .7rem .75rem; }
}

@media (max-width: 575.98px) {
    .form-control, .form-select { font-size: max(16px, 1rem); }

/* Modals become compact bottom sheets with the body as the only scroll region. */
    .modal:not(.modal-static) .modal-dialog:not(.modal-sm) {
        margin: auto 0 0;
        max-width: 100%;
        min-height: 100%;
        display: flex;
        align-items: flex-end;
    }
    .modal:not(.modal-static) .modal-dialog:not(.modal-sm) .modal-content {
        border-radius: 16px 16px 6px 6px;
        max-height: calc(100dvh - 1rem - env(safe-area-inset-top) - env(safe-area-inset-bottom));
        overflow: hidden;
        width: 100%;
    }
}

/* Notched phones: content and drawer respect the safe areas. */
.app-content {
    padding-left: max(1.15rem, env(safe-area-inset-left));
    padding-right: max(1.15rem, env(safe-area-inset-right));
    padding-bottom: max(1rem, env(safe-area-inset-bottom));
}

/* ---------- Print: the page is the record, not the app ----------
   Any admin screen printed via the browser drops the chrome and ships the
   content full-width on white — tables become clean registers. */
@media print {
    body { zoom: 1; background: #fff; }.app-sidebar,
.app-topbar,
.page-actions,
.pd-kpis--acts,
.list-bar,
.sidebar-backdrop,
.actions-row,
.sa-actions,
.app-progress,
.col-toggle,
.table-tools,
.impersonation-banner { display: none !important; }
    .app-main { margin: 0 !important; }
    .app-content { padding: 0 !important; }
    .table-card, .pcard, .toolbar-card {
        box-shadow: none !important;
        border: 1px solid #ddd !important;
    }
    table.premium-table thead th { background: #f3f4f6 !important; color: #111 !important; }
}

/* ---------- Avatar photos ----------
   An uploaded student/teacher photo fills the same circle the initial
   letter uses — size and shape inherit, so lists stay perfectly aligned
   whether a row has a photo or the letter fallback. */
.avatar-circle img,
.avatar-photo {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: inherit;
    display: block;
}

/* ============================================================
   DARK THEME HARMONIZATION
   A professional, low-glare dark mode. Two principles:
   1) every light-only fill (near-white gradients, pastel tints)
      maps to a surface token or a translucent wash of its hue;
   2) saturated accent chips are gently dimmed so they read as
      accents, not lamps. Appended last so it wins the cascade.
   ============================================================ */

/* ---------- Panel chrome: light gradients → flat dark surfaces ---------- */
html[data-theme="dark"] .pcard__head,
html[data-theme="dark"] .pcard__foot {
    background: var(--surface-2);
    border-color: var(--border);
}
html[data-theme="dark"] .pcard .form-select,
html[data-theme="dark"] .pcard .form-control {
    background-color: var(--surface-3);
    border-color: var(--border-strong);
    color: var(--text);
}
html[data-theme="dark"] .btn-soft:hover { background: var(--surface-3); }
html[data-theme="dark"] .trg.is-na,
html[data-theme="dark"] .wa-empty,
html[data-theme="dark"] .wa-api,
html[data-theme="dark"] .ay-empty { background: var(--surface-2); }
html[data-theme="dark"] .sa-card input.fee-discount { background: var(--surface-3); color: var(--text); }
html[data-theme="dark"] .ss-page .form-control::placeholder { color: var(--muted); }

/* ---------- Marks grid: paper whites → recessed dark surfaces ---------- */
html[data-theme="dark"] table.mk-grid thead th {
    background: var(--surface-2);
    color: var(--text-2);
}
html[data-theme="dark"] table.mk-grid .mk-sum,
html[data-theme="dark"] table.mk-grid .mk-rank,
html[data-theme="dark"] table.mk-grid .mk-pct { background: var(--surface-2); }
html[data-theme="dark"] table.mk-grid tbody tr:hover td { background: var(--hover-tint); }
html[data-theme="dark"] table.mk-grid .mk-cell:hover:not(:focus) { background: var(--hover-tint); }
html[data-theme="dark"] table.mk-grid .mk-cell.is-absent {
    background: rgba(239, 68, 68, .14);
    color: #fca5a5;
}
html[data-theme="dark"] table.mk-grid .mk-cell.is-invalid {
    background: rgba(239, 68, 68, .18);
    color: #fca5a5;
}

/* ---------- Attendance chips + monthly register: pastel → hue washes ---------- */
html[data-theme="dark"] .att-chip.is-success { background: rgba(16, 185, 129, .14); border-color: rgba(16, 185, 129, .35); color: #6ee7b7; }
html[data-theme="dark"] .att-chip.is-danger  { background: rgba(239, 68, 68, .14);  border-color: rgba(239, 68, 68, .35);  color: #fca5a5; }
html[data-theme="dark"] table.att-register td.reg-day.is-P { background: rgba(16, 185, 129, .13); color: #6ee7b7; }
html[data-theme="dark"] table.att-register td.reg-day.is-A { background: rgba(239, 68, 68, .13); color: #fca5a5; }
html[data-theme="dark"] table.att-register td.reg-day.is-L { background: rgba(245, 158, 11, .13); color: #fcd34d; }
html[data-theme="dark"] table.att-register td.reg-day.is-H { background: rgba(6, 182, 212, .13); color: #67e8f9; }

/* ---------- WhatsApp settings: mint gradients → deep green washes ---------- */
html[data-theme="dark"] .wa-link-out {
    background: rgba(16, 185, 129, .1);
    border-color: rgba(16, 185, 129, .3);
}
html[data-theme="dark"] .ay.is-current {
    background: rgba(16, 185, 129, .1);
    border-color: rgba(16, 185, 129, .3);
}
html[data-theme="dark"] .wa-icon-btn.is-danger:hover {
    background: rgba(239, 68, 68, .14);
    border-color: rgba(239, 68, 68, .4);
}

/* ---------- Accent chips: accents, not lamps ----------
   Solid colored icon tiles keep their hue but drop the glare; the highlight
   sheen is halved so surfaces feel matte under low light. */
html[data-theme="dark"] .input-group-text.pf-ico,
html[data-theme="dark"] .stat-icon,
html[data-theme="dark"] .kpi-ico,
html[data-theme="dark"] .mini-tile__ico,
html[data-theme="dark"] .kpi-tile__ico,
html[data-theme="dark"] .nav-icon-chip,
html[data-theme="dark"] .feed__ico i,
html[data-theme="dark"] .quick__item i {
    filter: saturate(.88) brightness(.92);
}
html[data-theme="dark"] .input-group-text.pf-ico {
    background-image: linear-gradient(135deg, rgba(255, 255, 255, .12), rgba(255, 255, 255, 0) 60%);
}
html[data-theme="dark"] .ss-page .input-group-text.pf-ico { box-shadow: inset 0 1px 0 rgba(255, 255, 255, .14); }

/* ---------- Dashboard: deeper banner, calmer glow ---------- */
html[data-theme="dark"] .dash-banner {
    background: linear-gradient(120deg,
        color-mix(in srgb, var(--accent-dark, #4338ca) 26%, #05070f) 0%,
        color-mix(in srgb, var(--accent-dark, #4338ca) 72%, #05070f) 58%,
        color-mix(in srgb, var(--accent-2, #6d28d9) 70%, #05070f) 100%);
    box-shadow: 0 18px 40px -20px rgba(0, 0, 0, .8);
}
html[data-theme="dark"] .dash-blob { opacity: .3; }
html[data-theme="dark"] .today-chip b { color: var(--text); }
html[data-theme="dark"] .rec__foot b { color: #fca5a5; }
html[data-theme="dark"] .tt-pulse__cap { color: #2dd4bf; }

/* ---------- Status text brightened for contrast on dark cards ---------- */
html[data-theme="dark"] .today-chip .t-abs { color: #fca5a5; }
html[data-theme="dark"] .today-chip .t-lv { color: #fcd34d; }
html[data-theme="dark"] .icon-btn-primary { color: #fbbf24; }
html[data-theme="dark"] .insight__empty u { color: #a5b4fc; }

/* ---------- Bootstrap contextual fills that bypass data-bs-theme ---------- */
html[data-theme="dark"] .alert-danger {
    background: rgba(239, 68, 68, .12);
    border-color: rgba(239, 68, 68, .35);
    color: #fca5a5;
}
html[data-theme="dark"] .alert-warning {
    background: rgba(245, 158, 11, .12);
    border-color: rgba(245, 158, 11, .35);
    color: #fcd34d;
}
html[data-theme="dark"] .alert-success {
    background: rgba(16, 185, 129, .12);
    border-color: rgba(16, 185, 129, .35);
    color: #6ee7b7;
}
html[data-theme="dark"] .alert-info {
    background: rgba(14, 165, 233, .12);
    border-color: rgba(14, 165, 233, .35);
    color: #7dd3fc;
}

/* ---------- Selection & focus keep the accent but lose the dazzle ---------- */
html[data-theme="dark"] ::selection { background: color-mix(in srgb, var(--accent) 35%, transparent); }

/* Student exam room / review: red status text brightened on dark. */
html[data-theme="dark"] .exam-timer.danger { color: #fca5a5; }
html[data-theme="dark"] .rv-opt.wrong .rv-tag { color: #fca5a5; }

/* ============================================================
   DASHBOARD COMPONENTS — shared by every role dashboard
   (SchoolAdmin index, Owner, office roles). Moved out of the
   SchoolAdmin view's local <style> so all dashboards render the
   same premium language. Page-specific pieces (today strip,
   charts, donut, rings) stay in their own views.
   ============================================================ */
.dash { display: flex; flex-direction: column; gap: 1rem; }
.dash > * { animation: dashUp .45s cubic-bezier(.2, .7, .3, 1) both; }
.dash > :nth-child(2) { animation-delay: .05s; }
.dash > :nth-child(3) { animation-delay: .1s; }
.dash > :nth-child(4) { animation-delay: .15s; }
.dash > :nth-child(5) { animation-delay: .2s; }
.dash > :nth-child(6) { animation-delay: .25s; }
.dash > :nth-child(7) { animation-delay: .3s; }
.dash > :nth-child(8) { animation-delay: .35s; }
@keyframes dashUp { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }

/* Aurora banner — follows the active design's accent. */
.dash-banner {
    position: relative; overflow: hidden;
    display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap;
    padding: 1.6rem 1.7rem; border-radius: 18px; color: #fff;
    background: linear-gradient(120deg,
        color-mix(in srgb, var(--accent-dark, #4338ca) 38%, #0b1120) 0%,
        var(--accent-dark, #4338ca) 55%,
        var(--accent-2, #6d28d9) 100%);
    box-shadow: 0 18px 40px -18px color-mix(in srgb, var(--accent-dark, #4338ca) 60%, transparent);
}
.dash-blob { position: absolute; border-radius: 50%; filter: blur(46px); opacity: .55; pointer-events: none; }
.dash-blob--1 { width: 300px; height: 300px; top: -45%; right: -4%; background: radial-gradient(circle, #a78bfa, transparent 70%); animation: blob1 14s ease-in-out infinite alternate; }
.dash-blob--2 { width: 240px; height: 240px; bottom: -55%; left: 28%; background: radial-gradient(circle, #38bdf8, transparent 70%); animation: blob2 18s ease-in-out infinite alternate; }
@keyframes blob1 { to { transform: translate(-50px, 26px) scale(1.15); } }
@keyframes blob2 { to { transform: translate(70px, -18px) scale(1.1); } }
.dash-banner__text { position: relative; z-index: 1; }
.dash-banner__hi { font-size: .82rem; font-weight: 600; color: #c7d2fe; }
.dash-banner h2 { font-weight: 800; font-size: 1.65rem; margin: .15rem 0 .3rem; letter-spacing: -.01em; }
.dash-banner p { margin: 0; color: #dbe0ff; font-size: .88rem; display: flex; align-items: center; flex-wrap: wrap; gap: .1rem .2rem; }
.dash-clock { color: #c7d2fe; }
.dash-year {
    margin-left: .55rem; display: inline-flex; align-items: center;
    font-size: .72rem; font-weight: 700; color: #e0e7ff;
    background: rgba(255, 255, 255, .12); border: 1px solid rgba(255, 255, 255, .18);
    border-radius: 999px; padding: .14rem .6rem; backdrop-filter: blur(4px);
}
.dash-banner__cta {
    position: relative; z-index: 1; display: inline-flex; align-items: center; gap: .5rem;
    padding: .6rem 1.1rem; border-radius: 11px; font-weight: 700; font-size: .9rem;
    color: #3730a3; background: #fff; text-decoration: none;
    box-shadow: 0 8px 18px -6px rgba(0,0,0,.35); transition: transform .12s ease, box-shadow .12s ease;
}
.dash-banner__cta:hover { transform: translateY(-2px); box-shadow: 0 12px 24px -8px rgba(0,0,0,.4); color: #3730a3; }

/* KPI tiles */
.kpi-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1rem; }
.kpi-tile {
    position: relative; display: flex; align-items: center; gap: .9rem; padding: 1rem 1.1rem;
    background: var(--card-bg); border: 1px solid var(--border); border-radius: 14px;
    box-shadow: var(--shadow-1); text-decoration: none; overflow: hidden;
    transition: transform .12s ease, box-shadow .12s ease, border-color .12s ease;
}
.kpi-tile::after {
    content: ''; position: absolute; inset: 0; pointer-events: none;
    background: radial-gradient(140px 90px at 110% -20%, color-mix(in srgb, var(--c) 14%, transparent), transparent 70%);
}
.kpi-tile:hover { transform: translateY(-3px); box-shadow: var(--shadow-2); border-color: color-mix(in srgb, var(--c) 40%, var(--border)); }
.kpi-tile__ico {
    width: 46px; height: 46px; flex-shrink: 0; border-radius: 12px; display: flex; align-items: center; justify-content: center;
    font-size: 1.3rem; color: #fff; background: linear-gradient(135deg, var(--c), color-mix(in srgb, var(--c) 65%, #000));
    box-shadow: 0 8px 16px -6px var(--c);
}
.kpi-tile__body { display: flex; flex-direction: column; min-width: 0; }
.kpi-tile__val { font-weight: 800; font-size: 1.35rem; line-height: 1.15; color: var(--text); white-space: nowrap; font-variant-numeric: tabular-nums; }
.kpi-tile__lbl { font-size: .74rem; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: .03em; }
.kpi-tile__lbl em { font-style: normal; color: color-mix(in srgb, var(--c) 80%, var(--muted)); text-transform: none; letter-spacing: 0; }
.kpi-tile__go { margin-left: auto; color: var(--muted); opacity: 0; transform: translate(-4px, 4px); transition: opacity .15s ease, transform .15s ease, color .15s ease; }
.kpi-tile:hover .kpi-tile__go { opacity: 1; transform: none; color: var(--c); }

/* Insight cards */
.insight-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1rem; }
.insight-row--3 { grid-template-columns: repeat(3, 1fr); }
.insight { display: block; text-decoration: none; transition: transform .12s ease, box-shadow .12s ease; }
.insight:hover { transform: translateY(-3px); box-shadow: var(--shadow-2); }
.insight__head { display: flex; align-items: center; gap: .5rem; font-weight: 800; font-size: .88rem; color: var(--text); margin-bottom: .8rem; }
.insight__flex { display: flex; align-items: center; gap: 1.1rem; }
.insight__legend { display: flex; flex-direction: column; gap: .35rem; font-size: .8rem; color: var(--text-2); }
.insight__legend b { color: var(--text); }
.insight__empty { color: var(--muted); font-size: .84rem; display: flex; align-items: center; gap: .5rem; padding: .9rem 0; }
.insight__empty u { color: var(--accent); text-decoration: none; font-weight: 700; }

/* Two-column card grid + card headers */
.dash-grid { display: grid; grid-template-columns: 2fr 1fr; gap: 1rem; }
.dash-grid--wide { grid-template-columns: 1fr 1fr; }
.pcard-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 1rem; }
.pcard-head h6 { display: flex; align-items: center; gap: .5rem; font-weight: 800; margin: 0; font-size: .95rem; }
.pcard-note { font-size: .78rem; color: var(--muted); }
.pcard-link { text-decoration: none; font-weight: 600; }
.pcard-link:hover { color: var(--accent); }

/* Quick actions */
.quick { display: grid; grid-template-columns: repeat(4, 1fr); gap: .7rem; }
.quick--2 { grid-template-columns: repeat(2, 1fr); }
.quick__item {
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .45rem;
    padding: 1rem .5rem; border-radius: 12px; text-decoration: none; text-align: center;
    color: var(--text-2); background: var(--content-bg); border: 1px solid var(--border);
    font-size: .78rem; font-weight: 600; transition: transform .12s ease, background .12s ease, color .12s ease, border-color .12s ease;
}
.quick__item i { font-size: 1.3rem; color: var(--c); transition: color .12s ease, transform .15s ease; }
.quick__item:hover { transform: translateY(-3px); background: var(--c); border-color: var(--c); color: #fff; }
.quick__item:hover i { color: #fff; transform: scale(1.12); }

/* Activity feeds */
.feed-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; }
.feed { display: flex; flex-direction: column; }
.feed__row {
    display: flex; align-items: center; gap: .7rem;
    padding: .5rem 0; border-top: 1px solid var(--border);
    text-decoration: none; min-width: 0;
}
.feed__row:first-child { border-top: none; }
.feed__row--link { border-radius: 8px; margin: 0 -.4rem; padding-left: .4rem; padding-right: .4rem; transition: background .12s ease; }
.feed__row--link:hover { background: var(--hover-tint); }
.feed__ico {
    width: 32px; height: 32px; flex-shrink: 0; border-radius: 9px;
    display: flex; align-items: center; justify-content: center; font-size: .95rem;
    color: var(--c); background: color-mix(in srgb, var(--c) 13%, transparent);
}
.feed__date {
    width: 40px; flex-shrink: 0; display: flex; flex-direction: column; align-items: center;
    border-radius: 9px; padding: .2rem 0; line-height: 1.1;
    background: color-mix(in srgb, var(--c) 12%, transparent);
}
.feed__date b { font-size: .95rem; font-weight: 800; color: var(--c); font-variant-numeric: tabular-nums; }
.feed__date em { font-style: normal; font-size: .58rem; font-weight: 700; text-transform: uppercase; color: var(--c); }
.feed__meta { display: flex; flex-direction: column; min-width: 0; margin-right: auto; }
.feed__name { font-weight: 600; font-size: .84rem; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.feed__sub { font-size: .72rem; color: var(--muted); }
.feed__count {
    min-width: 30px; text-align: center; flex-shrink: 0;
    font-size: .78rem; font-weight: 800; font-variant-numeric: tabular-nums;
    color: var(--muted); background: var(--surface-3);
    border-radius: 999px; padding: .16rem .5rem;
}
.feed__count.is-hot { color: #fff; background: var(--accent); }

/* Shared dashboard responsiveness */
@media (max-width: 1199.98px) {
    .insight-row { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 991.98px) {
    .dash-grid, .dash-grid--wide { grid-template-columns: 1fr; }
    .kpi-row { grid-template-columns: repeat(2, 1fr); }
    .feed-row { grid-template-columns: 1fr; }
}
@media (max-width: 767.98px) {
    .insight-row, .insight-row--3 { grid-template-columns: 1fr; }
}
@media (max-width: 575.98px) {
    .kpi-row { grid-template-columns: repeat(2, 1fr); }
    .quick, .quick--2 { grid-template-columns: repeat(2, 1fr); }
    .dash-banner h2 { font-size: 1.3rem; }
}

/* ============================================================
   GEOMETRY NORMALIZATION — one card system
   Every card surface shares one radius, one padding rhythm, one
   icon scale and one type scale, so mixed rows read as a single
   family. The aurora banner keeps its larger radius on
   purpose; design variants (e.g. Graphite's sharp corners) still
   override via their own scoped rules.
   ============================================================ */
:root {
    --r-card: 14px;   /* card surfaces */
    --r-el: 10px;     /* inner tiles, chips, list icons */
}

/* --- Card surfaces: one radius --- */
.pcard, .table-card, .toolbar-card, .stat-card, .kpi-tile,
.sa-card, .empty-state, .modal-content, .quick__item {
    border-radius: var(--r-card);
}
.feed__ico, .feed__date, .feed__row--link { border-radius: var(--r-el); }

/* --- Tile padding rhythm: stat tiles and KPI tiles align --- */
.stat-card { padding: .85rem 1rem; gap: .75rem; }
.kpi-tile  { padding: .85rem 1rem; gap: .75rem; }
.sa-card   { padding: .75rem .85rem; }

/* --- Icon chips: two deliberate sizes, consistent proportions ---
   Primary tile icons (stat/KPI) 44px @ 12px radius; list/feed icons
   36px @ 10px radius. Same visual weight wherever they appear. */
.stat-icon, .kpi-tile__ico {
    width: 44px; height: 44px; border-radius: 12px; font-size: 1.25rem;
}
.feed__ico { width: 36px; height: 36px; font-size: 1rem; }

/* --- Figures + labels: one type scale inside every tile --- */
.stat-value, .kpi-tile__val {
    font-size: 1.35rem; font-weight: 800; line-height: 1.15;
}
.stat-label, .kpi-tile__lbl {
    font-size: .72rem; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
}

/* --- Card headers: one rhythm --- */
.pcard-head, .insight__head { margin-bottom: 1rem; }
.pcard-head h6, .insight__head { font-size: .92rem; }

/* --- Grid gaps: every card row breathes the same --- */
.stat-tiles, .kpi-row, .insight-row, .insight-row--3,
.feed-row, .dash-grid, .dash-grid--wide, .mini-row { gap: 1rem; }
.stat-tiles { margin-bottom: 1rem; }

/* --- Empty states: same surface language as their sibling cards --- */
.empty-state { border-radius: var(--r-card); }

/* Compact contexts (list-page tiles on small phones) tighten together. */
@media (max-width: 420px) {
    .stat-tiles, .kpi-row { gap: .6rem; }
    .stat-card, .kpi-tile { padding: .65rem .8rem; }
    .stat-icon, .kpi-tile__ico { width: 38px; height: 38px; font-size: 1.05rem; }
    .stat-value, .kpi-tile__val { font-size: 1.15rem; }
}

/* ============================================================
   INSIGHT CARDS 2.0 — one strict anatomy for every insight
   header (tinted chip + micro-label + hover arrow) → body
   (fixed-height, centered figure/viz) → footer (dashed hairline
   + context line). Per-card accent flows from --c so all cards
   share identical geometry while keeping their own hue.
   ============================================================ */
.insight {
    position: relative;
    overflow: hidden;
    padding: 1.05rem 1.15rem;
    display: flex;
    flex-direction: column;
}

/* Accent rail: a precise 3px signature line, not a glow. */
.insight::before {
    content: '';
    position: absolute; top: 0; left: 0; right: 0; height: 3px;
    background: linear-gradient(90deg, var(--c, var(--accent)), color-mix(in srgb, var(--c, var(--accent)) 12%, transparent));
}

/* Soft corner wash, same treatment as KPI tiles — family resemblance. */
.insight::after {
    content: '';
    position: absolute; inset: 0; pointer-events: none;
    background: radial-gradient(150px 100px at 108% -18%, color-mix(in srgb, var(--c, var(--accent)) 10%, transparent), transparent 70%);
}
.insight:hover { border-color: color-mix(in srgb, var(--c, var(--accent)) 38%, var(--border)); }

.insight__head {
    display: flex; align-items: center; gap: .6rem;
    margin-bottom: .9rem; position: relative; z-index: 1;
}
.insight__chip {
    width: 34px; height: 34px; flex-shrink: 0; border-radius: 10px;
    display: flex; align-items: center; justify-content: center;
    font-size: 1rem; color: var(--c, var(--accent));
    background: color-mix(in srgb, var(--c, var(--accent)) 13%, transparent);
}
.insight__title {
    font-size: .7rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: .07em; color: var(--muted); line-height: 1.2;
}
.insight__go {
    margin-left: auto; color: var(--muted); font-size: .9rem;
    opacity: 0; transform: translate(-4px, 4px);
    transition: opacity .15s ease, transform .15s ease, color .15s ease;
}
.insight:hover .insight__go { opacity: 1; transform: none; color: var(--c, var(--accent)); }

/* Body: every card's content sits in the same fixed-height stage. */
.insight__body {
    min-height: 104px; flex: 1;
    display: flex; align-items: center; gap: 1.1rem;
    position: relative; z-index: 1;
}
.insight__body--col { flex-direction: column; align-items: stretch; justify-content: center; gap: .55rem; }

/* Headline figure + caption — the one type scale for big numbers. */
.insight__figure {
    font-size: 1.9rem; font-weight: 800; line-height: 1.05;
    color: var(--text); font-variant-numeric: tabular-nums; letter-spacing: -.02em;
}
.insight__cap {
    font-size: .72rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: .05em; color: var(--c, var(--accent));
}

/* Footer: dashed hairline + muted context, identical on every card. */
.insight__foot {
    margin-top: .9rem; padding-top: .65rem;
    border-top: 1px dashed var(--border);
    font-size: .74rem; color: var(--muted);
    display: flex; align-items: center; justify-content: space-between; gap: .5rem;
    position: relative; z-index: 1;
}
.insight__foot b { color: var(--text); font-variant-numeric: tabular-nums; }

/* Progress bar variant (fee recovery etc.) — consistent with own-bar tracks. */
.insight__bar { height: 9px; border-radius: 999px; background: var(--surface-3); overflow: hidden; }
.insight__bar span {
    display: block; height: 100%; width: var(--w, 0%); border-radius: inherit;
    background: linear-gradient(90deg, color-mix(in srgb, var(--c, var(--accent)) 70%, #fff), var(--c, var(--accent)));
    transition: width .8s cubic-bezier(.2, .7, .3, 1);
}

/* Empty body centers its message on the same stage. */
.insight__body .insight__empty { padding: 0; width: 100%; justify-content: center; text-align: center; }

/* Legends inherit the standard rhythm. */
.insight__legend { gap: .45rem; }
.insight__legend span { display: flex; align-items: center; }
.insight__legend b { margin-left: auto; padding-left: .8rem; font-variant-numeric: tabular-nums; }

html[data-theme="dark"] .insight__bar span {
    background: linear-gradient(90deg, color-mix(in srgb, var(--c, var(--accent)) 80%, #000), var(--c, var(--accent)));
}

/* Equal-height insight cards: the body is an exact stage (not a minimum),
   and wrapped rows share one uniform track height, so every card matches
   every other card on every breakpoint. */
.insight-row, .insight-row--3 { grid-auto-rows: 1fr; }
.insight { height: 100%; }
.insight__body { height: 116px; min-height: 116px; max-height: 116px; overflow: hidden; }
.insight__body .own-bars { width: 100%; }
.att-ring, .own-ring { width: 88px; height: 88px; }
.att-ring__val, .own-ring__val { width: 62px; height: 62px; }

/* Insight cards stay parallel (one row) on ALL desktop widths; the
   2-column fold now begins only below the tablet breakpoint. */
@media (min-width: 992px) {
    .insight-row { grid-template-columns: repeat(4, 1fr); }
    .insight-row--3 { grid-template-columns: repeat(3, 1fr); }
}
@media (min-width: 992px) and (max-width: 1399.98px) {
    /* Narrower desktop columns: tighten the stage so four still breathe. */
    .insight { padding: .95rem 1rem; }
    .insight__legend { font-size: .76rem; }
    .insight__figure { font-size: 1.6rem; }
}
@media (max-width: 991.98px) {
    .insight-row, .insight-row--3 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 767.98px) {
    .insight-row, .insight-row--3 { grid-template-columns: 1fr; }
}

/* All insight content starts on the SAME top line — a centered stage made
   short content (a lone headline figure) float lower than tall content (bars,
   rings). Top-anchored, every card begins at exactly the same y. */
.insight__body { align-items: flex-start; padding-top: .15rem; }
.insight__body--col { justify-content: flex-start; }
.insight__body .insight__empty { align-self: center; }

/* Empty insight states fill the whole stage as a designed dashed panel —
   so a card with no data occupies exactly the same box as a card with a
   figure, and all four bodies align top AND bottom in every state. */
.insight__body .insight__empty {
    align-self: stretch;
    width: 100%; height: 100%; margin: 0; padding: 0 .6rem;
    display: flex; align-items: center; justify-content: center;
    text-align: center;
    border: 1px dashed color-mix(in srgb, var(--c, var(--accent)) 30%, var(--border));
    border-radius: 10px;
    background: color-mix(in srgb, var(--c, var(--accent)) 5%, transparent);
}
.insight__body .insight__empty i { color: var(--c, var(--accent)); opacity: .8; }

/* ============================================================
   PCARD PREMIUM — dashboard panels
   Every dashboard panel adopts the insight card's exact padding
   and header anatomy (34px tinted chip + uppercase micro-label),
   so panel rows sit precisely in front of the insight columns
   above them and the whole page reads as one card family.
   ============================================================ */
.dash .pcard { padding: 1.05rem 1.15rem; display: flex; flex-direction: column; min-width: 0; }
.dash .pcard > :last-child { margin-bottom: 0; }

/* Panel headers mirror .insight__head: tinted chip, micro-label, same rhythm.
   The chip tints itself from the icon's own color via currentColor. */
.dash .pcard-head { margin-bottom: .9rem; }
.dash .pcard-head h6 {
    gap: .6rem; font-size: .7rem; font-weight: 700;
    text-transform: uppercase; letter-spacing: .07em; color: var(--muted); line-height: 1.2;
}
.dash .pcard-head h6 i {
    width: 34px; height: 34px; flex-shrink: 0; border-radius: 10px;
    display: inline-flex; align-items: center; justify-content: center;
    font-size: 1rem;
    background: color-mix(in srgb, currentColor 13%, transparent);
}
.dash .pcard-head .pcard-note { font-size: .74rem; }

/* Rows of panels stretch together; lists fill their panel so sibling
   cards bottom-align, and empty states expand into the same dashed
   stage language the insight cards use. */
.dash-grid, .dash-grid--wide, .feed-row { align-items: stretch; }
.dash .pcard .feed, .dash .pcard .recent { flex: 1; }
.dash .pcard .quick { flex: 1; grid-auto-rows: 1fr; }
.dash .pcard > .empty-state {
    flex: 1; display: flex; flex-direction: column;
    align-items: center; justify-content: center;
    margin: 0; border: 1px dashed var(--border-strong);
    background: color-mix(in srgb, var(--accent) 4%, transparent);
}

/* Re-assert the narrow-desktop insight tightening (the shared panel
   padding above would otherwise outrank it). */
@media (min-width: 992px) and (max-width: 1399.98px) {
    .dash .insight { padding: .95rem 1rem; }
}

/* ============================================================
   PD PREMIUM DASHBOARD — shared design system for the admin +
   owner dashboards (KPI/insight cards, ribbons,
   charts, feeds, quick tiles, registry band). Page views add
   only their page-specific extras locally.
   ============================================================ */
    /* ============ Premium colorful dashboard — page-scoped (.pd) ============
       Per-card accent flows from --c (chip tint, top rail, corner wash, hover
       ring), so every card is colorful yet the family stays coherent. */
    .pd { display: flex; flex-direction: column; gap: 1rem; }
    .pd > * { animation: pdIn .45s cubic-bezier(.2, .7, .3, 1) both; }
    .pd > :nth-child(2) { animation-delay: .05s; }
    .pd > :nth-child(3) { animation-delay: .1s; }
    .pd > :nth-child(4) { animation-delay: .15s; }
    .pd > :nth-child(5) { animation-delay: .2s; }
    .pd > :nth-child(6) { animation-delay: .25s; }
    .pd > :nth-child(7) { animation-delay: .3s; }
    @keyframes pdIn { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }

/* --- Card base: accent rail on top, soft corner wash, hover lift --- */
    .pd-card {
        position: relative; overflow: hidden; min-width: 0;
        background: var(--card-bg); border: 1px solid var(--border);
        border-radius: 14px; box-shadow: var(--shadow-1);
        text-decoration: none;
        transition: transform .14s ease, box-shadow .14s ease, border-color .14s ease;
    }
    .pd-card::before {
        content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px;
        background: linear-gradient(90deg, var(--c, var(--accent)), color-mix(in srgb, var(--c, var(--accent)) 12%, transparent));
    }
    .pd-card::after {
        content: ''; position: absolute; inset: 0; pointer-events: none;
        background: radial-gradient(160px 110px at 108% -18%, color-mix(in srgb, var(--c, var(--accent)) 10%, transparent), transparent 70%);
    }
    .pd-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-2); border-color: color-mix(in srgb, var(--c, var(--accent)) 38%, var(--border)); }
    section.pd-card:hover, section.pd-card { transform: none; }
    .pd-card > * { position: relative; z-index: 1; }

    .pd-chip {
        width: 36px; height: 36px; flex-shrink: 0; border-radius: 10px;
        display: inline-flex; align-items: center; justify-content: center;
        font-size: 1.05rem; color: var(--c, var(--accent));
        background: color-mix(in srgb, var(--c, var(--accent)) 13%, transparent);
    }
    .pd-badge {
        font-size: .68rem; font-weight: 800; text-transform: uppercase; letter-spacing: .05em;
        color: var(--c, var(--accent));
        border: 1px solid color-mix(in srgb, var(--c, var(--accent)) 32%, transparent);
        background: color-mix(in srgb, var(--c, var(--accent)) 8%, transparent);
        padding: .16rem .55rem; border-radius: 999px; white-space: nowrap;
    }
    .pd-tag {
        flex-shrink: 0; font-size: .64rem; font-weight: 800; text-transform: uppercase; letter-spacing: .05em;
        color: var(--c, var(--muted));
        border: 1px solid color-mix(in srgb, var(--c, var(--muted)) 35%, transparent);
        background: color-mix(in srgb, var(--c, var(--muted)) 9%, transparent);
        padding: .13rem .5rem; border-radius: 999px;
    }
    .pd-go {
        margin-left: auto; color: var(--muted); font-size: .9rem;
        opacity: 0; transform: translate(-4px, 4px);
        transition: opacity .15s ease, transform .15s ease, color .15s ease;
    }
    .pd-card:hover .pd-go { opacity: 1; transform: none; color: var(--c, var(--accent)); }

/* --- Corner ribbons --- */
    .pd-rib {
        position: absolute; top: 15px; right: -35px; z-index: 2;
        transform: rotate(45deg);
        padding: .24rem 2.8rem; font-size: .62rem; font-weight: 800;
        letter-spacing: .1em; text-transform: uppercase; color: #fff;
        background: linear-gradient(90deg, #f59e0b, #f97316);
        box-shadow: 0 2px 10px rgba(0, 0, 0, .22);
    }
    .pd-rib--live { background: linear-gradient(90deg, #10b981, #059669); animation: pdPulse 2s ease infinite; }
    @keyframes pdPulse { 0%, 100% { filter: brightness(1); } 50% { filter: brightness(1.18); } }

/* --- Dashboard quick actions + at-a-glance strip ---
       These used to sit on a gradient banner and were styled white-on-dark for
       it. The banner is gone; they now stand on the page background and take
       their colours from the same tokens every other card uses. */
    .pd-acts { display: flex; gap: .55rem; flex-wrap: wrap; align-items: center; }
    .pd-cta {
        display: inline-flex; align-items: center; gap: .45rem;
        padding: .5rem .95rem; border-radius: 10px; text-decoration: none;
        font-size: .82rem; font-weight: 700; color: var(--text);
        background: var(--card-bg); border: 1px solid var(--border);
        transition: background .12s ease, border-color .12s ease, transform .12s ease;
    }
    .pd-cta:hover { background: var(--surface); color: var(--text); border-color: var(--accent); transform: translateY(-1px); }
    .pd-cta--solid {
        color: #fff;
        background: linear-gradient(135deg, var(--accent), var(--accent-dark));
        border-color: transparent;
        box-shadow: 0 6px 14px -6px var(--accent);
    }
    .pd-cta--solid:hover { color: #fff; filter: saturate(112%); box-shadow: 0 10px 22px -8px var(--accent); }
    .pd-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: .7rem; }
    .pd-stat {
        display: flex; flex-direction: column; gap: .15rem; min-width: 0;
        padding: .7rem .85rem; border-radius: 12px; text-decoration: none; color: var(--text);
        background: var(--card-bg); border: 1px solid var(--border);
        box-shadow: var(--shadow-1);
        transition: border-color .12s ease, transform .12s ease;
    }
    .pd-stat:hover { color: var(--text); border-color: var(--accent); transform: translateY(-2px); }
    .pd-stat i { font-size: 1rem; color: var(--accent); }
    .pd-stat b { font-size: .95rem; font-weight: 800; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-variant-numeric: tabular-nums; }
    .pd-stat span { font-size: .68rem; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* --- KPI cards --- */
    .pd-kpis { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1rem; }
    .pd-kpis--2 { grid-template-columns: repeat(2, 1fr); }
    .pd-kpis--3 { grid-template-columns: repeat(3, 1fr); }
    .pd-kpis--5 { grid-template-columns: repeat(5, 1fr); }
    .pd-kpis--6 { grid-template-columns: repeat(6, 1fr); }
    .pd-kpi { display: flex; flex-direction: column; gap: .15rem; padding: .95rem 1.05rem; }
    .pd-kpi__top { display: flex; align-items: center; justify-content: space-between; gap: .5rem; margin-bottom: .45rem; }
    .pd-kpi__val { font-size: 1.5rem; font-weight: 800; line-height: 1.1; color: var(--text); font-variant-numeric: tabular-nums; letter-spacing: -.02em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
    .pd-kpi__lbl { font-size: .72rem; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); }
    .pd-kpi__spark { width: 64px; height: 24px; color: var(--c); position: absolute; right: .95rem; bottom: .9rem; opacity: .9; }
    .pd-kpi__split { display: flex; height: 6px; border-radius: 999px; overflow: hidden; margin-top: .5rem; background: var(--surface-3); }
    .pd-kpi__split span { height: 100%; }
    .pd-kpi .pd-go { position: absolute; top: .95rem; right: .95rem; }

/* --- Insight cards --- */
    .pd-insights { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1rem; grid-auto-rows: 1fr; }
    .pd-insights--3 { grid-template-columns: repeat(3, 1fr); }
    .pd-ins { display: flex; flex-direction: column; padding: 1.05rem 1.15rem; height: 100%; }
    .pd-ins__head { display: flex; align-items: center; gap: .6rem; margin-bottom: .85rem; }
    .pd-ins__title { font-size: .7rem; font-weight: 700; text-transform: uppercase; letter-spacing: .07em; color: var(--muted); line-height: 1.2; }
    .pd-ins__body { height: 112px; min-height: 112px; max-height: 112px; overflow: hidden; flex: 1; display: flex; align-items: flex-start; gap: 1rem; padding-top: .15rem; }
    .pd-ins__body--col { flex-direction: column; align-items: stretch; gap: .55rem; }
    .pd-ins__figure { font-size: 1.85rem; font-weight: 800; line-height: 1.05; color: var(--text); font-variant-numeric: tabular-nums; letter-spacing: -.02em; }
    .pd-ins__cap { display: block; margin-top: .25rem; font-size: .72rem; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--c, var(--accent)); }
    .pd-ins__foot {
        margin-top: .85rem; padding-top: .6rem; border-top: 1px dashed var(--border);
        font-size: .74rem; color: var(--muted);
        display: flex; align-items: center; justify-content: space-between; gap: .5rem;
    }
    .pd-ins__foot b { color: var(--text); font-variant-numeric: tabular-nums; }

/* Attendance ring (conic) */
    .pd-ring {
        --p: 0; --a: 0;
        width: 88px; height: 88px; border-radius: 50%; flex-shrink: 0;
        background: conic-gradient(#10b981 0 calc(var(--p) * 1%),
                                   #ef4444 calc(var(--p) * 1%) calc((var(--p) + var(--a)) * 1%),
                                   #f59e0b calc((var(--p) + var(--a)) * 1%) 100%);
        display: flex; align-items: center; justify-content: center;
    }
    .pd-ring span {
        width: 60px; height: 60px; border-radius: 50%; background: var(--card-bg);
        display: flex; align-items: center; justify-content: center;
        font-weight: 800; color: var(--text); font-size: .92rem; box-shadow: inset 0 0 0 1px var(--border);
    }

/* Progress bars */
    .pd-bar { height: 9px; border-radius: 999px; background: var(--surface-3); overflow: hidden; }
    .pd-bar--lg { height: 10px; }
    .pd-bar span {
        display: block; height: 100%; width: var(--w, 0%); border-radius: inherit;
        background: linear-gradient(90deg, color-mix(in srgb, var(--c, var(--accent)) 70%, #fff), var(--c, var(--accent)));
        transition: width .8s cubic-bezier(.2, .7, .3, 1);
    }
    html[data-theme="dark"] .pd-bar span { background: linear-gradient(90deg, color-mix(in srgb, var(--c, var(--accent)) 80%, #000), var(--c, var(--accent))); }

/* Legends */
    .pd-legend { display: flex; flex-direction: column; gap: .4rem; font-size: .78rem; color: var(--text-2); }
    .pd-legend--col { gap: .55rem; font-size: .82rem; }
    .pd-legend i { display: inline-block; width: 10px; height: 10px; border-radius: 3px; margin-right: .35rem; }
    .pd-legend b { color: var(--text); font-variant-numeric: tabular-nums; }
    .pd-legend em { font-style: normal; color: var(--muted); font-size: .7rem; }

/* --- Panels (chart / donut / feeds / quick) --- */
    .pd-panel { padding: 1.05rem 1.15rem; }
    .pd-head { display: flex; align-items: center; justify-content: space-between; gap: .8rem; margin-bottom: .9rem; }
    .pd-head h2 { display: flex; align-items: center; gap: .6rem; margin: 0; font-size: .9rem; font-weight: 800; color: var(--text); }
    .pd-more { font-size: .76rem; font-weight: 700; color: var(--muted); text-decoration: none; white-space: nowrap; }
    .pd-more:hover { color: var(--c, var(--accent)); }

    .pd-charts { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); gap: 1rem; }
    .pd-chart svg { width: 100%; height: 200px; display: block; }
    .pd-chart__grid { stroke: var(--border); stroke-width: 1; stroke-dasharray: 3 5; }
    .pd-chart__line {
        fill: none; stroke: url(#pdLine); stroke-width: 2.5; stroke-linecap: round;
        stroke-dasharray: 1600; stroke-dashoffset: 1600; animation: pdDraw 1.1s ease-out .2s forwards;
    }
    @keyframes pdDraw { to { stroke-dashoffset: 0; } }
    .pd-chart__pt { fill: var(--card-bg); stroke: #2563eb; stroke-width: 2.5; }
    .pd-chart__pt:hover { fill: #2563eb; }
    .pd-chart__x { display: flex; margin-top: .45rem; }
    .pd-chart__x span { flex: 1; text-align: center; font-size: .68rem; font-weight: 600; color: var(--muted); display: flex; flex-direction: column; }
    .pd-chart__x b { font-size: .64rem; font-weight: 700; color: var(--text-2); font-variant-numeric: tabular-nums; }
    .pd-recov { margin-top: .9rem; padding-top: .85rem; border-top: 1px dashed var(--border); }
    .pd-recov__cap { display: flex; justify-content: space-between; gap: 1rem; margin-top: .5rem; font-size: .76rem; color: var(--muted); flex-wrap: wrap; }
    .pd-recov__cap b { color: var(--text); font-variant-numeric: tabular-nums; }

/* Donut */
    .pd-donut-wrap { display: flex; flex-direction: column; align-items: center; gap: 1rem; padding: .4rem 0 .2rem; }
    .pd-donut {
        width: 150px; height: 150px; border-radius: 50%;
        background: conic-gradient(#2563eb 0 var(--male, 50%), #ec4899 var(--male, 50%) 100%);
        display: flex; align-items: center; justify-content: center;
    }
    .pd-donut__hole {
        width: 104px; height: 104px; border-radius: 50%; background: var(--card-bg);
        display: flex; flex-direction: column; align-items: center; justify-content: center;
        box-shadow: inset 0 0 0 1px var(--border);
    }
    .pd-donut__hole b { font-weight: 800; font-size: 1.45rem; line-height: 1; color: var(--text); font-variant-numeric: tabular-nums; }
    .pd-donut__hole span { font-size: .66rem; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: .05em; }

/* --- Feed lists --- */
    .pd-feeds { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; }
    .pd-feeds--2 { grid-template-columns: repeat(2, 1fr); }
    .pd-list { display: flex; flex-direction: column; }
    .pd-row { display: flex; align-items: center; gap: .7rem; padding: .52rem 0; border-top: 1px solid var(--border); min-width: 0; text-decoration: none; }
    .pd-row:first-child { border-top: none; }
    .pd-row--link { border-radius: 9px; margin: 0 -.45rem; padding-left: .45rem; padding-right: .45rem; transition: background .12s ease; }
    .pd-row--link:hover { background: var(--hover-tint); }
    .pd-row__meta { display: flex; flex-direction: column; min-width: 0; margin-right: auto; }
    .pd-row__name { font-size: .84rem; font-weight: 600; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
    .pd-row--link .pd-row__name { margin-right: auto; }
    .pd-row__sub { font-size: .72rem; color: var(--muted); }
    .pd-ico {
        width: 34px; height: 34px; flex-shrink: 0; border-radius: 10px;
        display: flex; align-items: center; justify-content: center; font-size: 1rem;
        color: var(--c); background: color-mix(in srgb, var(--c) 13%, transparent);
    }
    .pd-ava {
        width: 34px; height: 34px; flex-shrink: 0; border-radius: 50%;
        display: flex; align-items: center; justify-content: center;
        font-size: .82rem; font-weight: 800;
        background: hsla(var(--h, 220), 70%, 45%, .16); color: hsl(var(--h, 220), 70%, 42%);
    }
    html[data-theme="dark"] .pd-ava { color: hsl(var(--h, 220), 75%, 70%); }
    .pd-date {
        width: 40px; flex-shrink: 0; display: flex; flex-direction: column; align-items: center;
        border-radius: 9px; padding: .2rem 0; line-height: 1.1;
        background: color-mix(in srgb, var(--c) 12%, transparent);
    }
    .pd-date b { font-size: .95rem; font-weight: 800; color: var(--c); font-variant-numeric: tabular-nums; }
    .pd-date em { font-style: normal; font-size: .56rem; font-weight: 700; text-transform: uppercase; color: var(--c); }
    .pd-count {
        flex-shrink: 0; min-width: 30px; text-align: center;
        font-size: .76rem; font-weight: 800; font-variant-numeric: tabular-nums;
        color: var(--muted); background: var(--surface-3);
        border-radius: 999px; padding: .16rem .5rem;
    }
    .pd-count.is-hot { color: #fff; background: var(--c, var(--accent)); }

/* --- Quick actions --- */
    .pd-quick { display: grid; grid-template-columns: repeat(6, 1fr); gap: .7rem; }
    .pd-quick__item {
        display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .45rem;
        padding: 1rem .5rem; border-radius: 12px; text-decoration: none; text-align: center;
        color: var(--text-2); background: var(--content-bg); border: 1px solid var(--border);
        font-size: .78rem; font-weight: 600;
        transition: transform .12s ease, background .12s ease, color .12s ease, border-color .12s ease;
    }
    .pd-quick__item i { font-size: 1.3rem; color: var(--c); transition: color .12s ease, transform .15s ease; }
    .pd-quick__item:hover { transform: translateY(-3px); background: var(--c); border-color: var(--c); color: #fff; }
    .pd-quick__item:hover i { color: #fff; transform: scale(1.12); }

/* --- Registry tiles --- */
    .pd-reg { display: grid; grid-template-columns: repeat(8, 1fr); gap: .8rem; }
    .pd-reg--6 { grid-template-columns: repeat(6, 1fr); }
    .pd-reg__tile { display: flex; flex-direction: column; align-items: flex-start; gap: .3rem; padding: .8rem .9rem; }
    .pd-reg__tile b { font-size: 1.2rem; font-weight: 800; color: var(--text); font-variant-numeric: tabular-nums; }
    .pd-reg__lbl { font-size: .68rem; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); }
    .pd-reg__tile .pd-chip { width: 32px; height: 32px; font-size: .95rem; border-radius: 9px; }

/* --- Empty states: dashed accent-tinted stage --- */
    .pd-empty {
        display: flex; align-items: center; justify-content: center; gap: .5rem;
        width: 100%; height: 100%; padding: .8rem .6rem;
        border: 1px dashed color-mix(in srgb, var(--c, var(--accent)) 30%, var(--border));
        border-radius: 10px;
        background: color-mix(in srgb, var(--c, var(--accent)) 5%, transparent);
        font-size: .8rem; color: var(--muted); text-align: center;
    }
    .pd-empty i { color: var(--c, var(--accent)); opacity: .85; }
    .pd-empty u { color: var(--c, var(--accent)); text-decoration: none; font-weight: 700; }
    .pd-empty--fill { height: auto; min-height: 120px; }

/* --- Responsive --- */
    @media (max-width: 1399.98px) {
        .pd-ins { padding: .95rem 1rem; }
        .pd-ins__figure { font-size: 1.6rem; }
        .pd-legend { font-size: .74rem; }
    }
    @media (max-width: 1199.98px) {
        .pd-quick { grid-template-columns: repeat(4, 1fr); }
        .pd-reg { grid-template-columns: repeat(4, 1fr); }
    }
    @media (max-width: 991.98px) {
        .pd-kpis, .pd-insights { grid-template-columns: repeat(2, 1fr); }
        .pd-charts { grid-template-columns: 1fr; }
        .pd-feeds { grid-template-columns: 1fr; }
        .pd-stats { grid-template-columns: repeat(2, 1fr); }
    }
    @media (max-width: 767.98px) {
        .pd-quick { grid-template-columns: repeat(3, 1fr); }
        .pd-reg { grid-template-columns: repeat(2, 1fr); }
    }
    @media (max-width: 575.98px) {
        .pd-kpis, .pd-insights { grid-template-columns: 1fr; }
        .pd-stats { grid-template-columns: 1fr; }
        .pd-quick { grid-template-columns: repeat(2, 1fr); }

/* CTAs: always one row of three equal-width, equal-height buttons.
           Extra top padding keeps them clear of the corner ribbon. */
        .pd-acts { display: grid; grid-template-columns: repeat(3, 1fr); gap: .45rem; align-items: stretch; }
        .pd-acts .pd-cta { justify-content: center; padding: .5rem .25rem; font-size: .72rem; white-space: nowrap; }
        .pd-acts .pd-cta i { display: none; }
    }

/* ============================================================
   PD SHARP 3D — refinement pass over the PD design system.
   Three moves: SHARP (small crisp radii everywhere), 3D
   (extruded cards: inner top light + accent bottom edge +
   layered drop shadows; embossed chips; inset bar tracks;
   pressable buttons), COMPACT (minimum card heights — tighter
   paddings, smaller chips/figures, reduced gaps).
   ============================================================ */

/* --- SHARP: crisp geometry --- */
.pd-card { border-radius: 6px; }
.pd-chip { border-radius: 5px; }
.pd-cta, .pd-stat, .pd-quick__item, .pd-empty { border-radius: 6px; }
.pd-badge, .pd-tag, .pd-count { border-radius: 4px; }
.pd-ava { border-radius: 7px; }
.pd-date, .pd-ico, .pd-row--link { border-radius: 5px; }

/* --- 3D: extruded surfaces --- */
.pd-card {
    border-color: color-mix(in srgb, var(--c, var(--accent)) 14%, var(--border));
    border-bottom: 2px solid color-mix(in srgb, var(--c, var(--accent)) 32%, var(--border));
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .65),
        0 1px 2px rgba(2, 6, 23, .10),
        0 3px 8px rgba(2, 6, 23, .07);
}
.pd-card:hover {
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .65),
        0 4px 8px rgba(2, 6, 23, .12),
        0 12px 24px rgba(2, 6, 23, .13);
}
html[data-theme="dark"] .pd-card,
html[data-theme="dark"] .pd-card:hover {
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .06),
        0 1px 2px rgba(0, 0, 0, .5),
        0 4px 12px rgba(0, 0, 0, .35);
}
.pd-chip {
    background: linear-gradient(180deg,
        color-mix(in srgb, var(--c, var(--accent)) 22%, transparent),
        color-mix(in srgb, var(--c, var(--accent)) 10%, transparent));
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .35),
        inset 0 -1px 0 rgba(2, 6, 23, .08),
        0 1px 2px rgba(2, 6, 23, .08);
}
html[data-theme="dark"] .pd-chip { box-shadow: inset 0 1px 0 rgba(255, 255, 255, .08), 0 1px 2px rgba(0, 0, 0, .4); }
.pd-badge, .pd-tag { box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25); }
html[data-theme="dark"] .pd-badge, html[data-theme="dark"] .pd-tag { box-shadow: inset 0 1px 0 rgba(255, 255, 255, .05); }
.pd-cta { box-shadow: inset 0 1px 0 rgba(255, 255, 255, .28), 0 2px 4px rgba(2, 6, 23, .22); }
.pd-cta:active { transform: translateY(1px); box-shadow: inset 0 1px 3px rgba(2, 6, 23, .25); }
.pd-cta--solid { background: linear-gradient(180deg, #ffffff, #e9eff3); }
.pd-stat { box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 3px rgba(2, 6, 23, .18); }
.pd-bar, .pd-kpi__split { box-shadow: inset 0 1px 2px rgba(2, 6, 23, .18); }
.pd-bar span { box-shadow: inset 0 1px 0 rgba(255, 255, 255, .35); }
.pd-ring, .pd-donut { box-shadow: 0 3px 8px rgba(2, 6, 23, .16); }
.pd-ring span, .pd-donut__hole { box-shadow: inset 0 0 0 1px var(--border), inset 0 2px 4px rgba(2, 6, 23, .10); }
.pd-quick__item {
    box-shadow: 0 2px 0 color-mix(in srgb, var(--c) 30%, var(--border)), 0 3px 6px rgba(2, 6, 23, .07);
}
.pd-quick__item:active { transform: translateY(1px); box-shadow: 0 1px 0 color-mix(in srgb, var(--c) 30%, var(--border)); }
.pd-rib { box-shadow: 0 2px 6px rgba(2, 6, 23, .3), inset 0 1px 0 rgba(255, 255, 255, .25); }

/* --- COMPACT: minimum card heights --- */
.pd { gap: .75rem; }
.pd-kpis, .pd-insights, .pd-feeds, .pd-charts { gap: .75rem; }
.pd-reg { gap: .55rem; }
.pd-stats { gap: .55rem; }
.pd-stat { padding: .45rem .65rem; gap: .1rem; }
.pd-stat b { font-size: .88rem; }
.pd-stat i { font-size: .9rem; }
.pd-cta { padding: .4rem .8rem; font-size: .78rem; }
.pd-rib { top: 12px; right: -36px; padding: .18rem 2.6rem; font-size: .58rem; }
.pd-chip { width: 30px; height: 30px; font-size: .9rem; }
.pd-kpi { padding: .6rem .75rem; gap: .1rem; }
.pd-kpi__top { margin-bottom: .3rem; }
.pd-kpi__val { font-size: 1.22rem; }
.pd-kpi__lbl { font-size: .64rem; }
.pd-kpi__spark { width: 54px; height: 20px; right: .65rem; bottom: .55rem; }
.pd-kpi__split { height: 5px; margin-top: .35rem; }
.pd-kpi .pd-go { top: .6rem; right: .65rem; }
.pd-badge { font-size: .62rem; padding: .12rem .45rem; }
.pd-ins { padding: .65rem .8rem; }
.pd-ins__head { margin-bottom: .5rem; gap: .5rem; }
.pd-ins__title { font-size: .64rem; }
.pd-ins__body { height: 90px; min-height: 90px; max-height: 90px; gap: .8rem; padding-top: .1rem; }
.pd-ins__body--col { gap: .4rem; }
.pd-ins__figure { font-size: 1.45rem; }
.pd-ins__cap { font-size: .64rem; margin-top: .15rem; }
.pd-ins__foot { margin-top: .5rem; padding-top: .45rem; font-size: .7rem; }
.pd-ring { width: 72px; height: 72px; }
.pd-ring span { width: 50px; height: 50px; font-size: .78rem; }
.pd-legend { gap: .28rem; font-size: .72rem; }
.pd-legend--col { gap: .4rem; font-size: .76rem; }
.pd-panel { padding: .45rem .9rem; }
.pd-head { margin-bottom: .55rem; gap: .6rem; }
.pd-head h2 { font-size: .84rem; gap: .5rem; }
.pd-more { font-size: .72rem; }
.pd-row { padding: .26rem 0; gap: .55rem; }
.pd-row__name { font-size: .8rem; }
.pd-row__sub { font-size: .68rem; }
.pd-ava { width: 28px; height: 28px; font-size: .72rem; }
.pd-ico { width: 28px; height: 28px; font-size: .85rem; }
.pd-date { width: 34px; padding: .14rem 0; }
.pd-date b { font-size: .82rem; }
.pd-count { min-width: 26px; font-size: .7rem; padding: .12rem .4rem; }
.pd-tag { font-size: .6rem; padding: .11rem .4rem; }
.pd-quick { gap: .55rem; }
.pd-quick__item { padding: .55rem .4rem; gap: .3rem; font-size: .72rem; }
.pd-quick__item i { font-size: 1.05rem; }
.pd-reg__tile { padding: .5rem .65rem; gap: .18rem; }
.pd-reg__tile b { font-size: 1rem; }
.pd-reg__tile .pd-chip { width: 26px; height: 26px; font-size: .8rem; }
.pd-donut { width: 118px; height: 118px; }
.pd-donut__hole { width: 80px; height: 80px; }
.pd-donut__hole b { font-size: 1.15rem; }
.pd-chart svg { height: 158px; }
.pd-recov { margin-top: .6rem; padding-top: .55rem; }
.pd-empty { font-size: .74rem; padding: .5rem .6rem; }
.pd-empty--fill { min-height: 84px; }

/* ============================================================
   PD DARK SHINE — final pass: KPI/registry figures sit INLINE
   beside their icon chip (classic stat anatomy, minimum height),
   and every accent goes deeper + glossier: dark-toned gradients
   with a top shine on chips, rails, bars and ribbons.
   ============================================================ */

/* --- Inline stat anatomy --- */
.pd-kpi { flex-direction: row; align-items: center; gap: .6rem; padding: .5rem .7rem; }
.pd-kpi .pd-chip { width: 34px; height: 34px; font-size: 1rem; }
.pd-kpi__top { display: contents; }
.pd-kpi__body { display: flex; flex-direction: column; min-width: 0; margin-right: auto; gap: .05rem; }
.pd-kpi__val { font-size: 1.18rem; line-height: 1.12; }
.pd-kpi__side { margin-left: auto; display: flex; flex-direction: column; align-items: flex-end; gap: .3rem; flex-shrink: 0; }
.pd-kpi__spark { position: static; width: 56px; height: 18px; }
.pd-kpi__split { width: 62px; margin-top: 0; }
.pd-kpi .pd-go { display: none; }
.pd-reg__tile { flex-direction: row; align-items: center; gap: .5rem; padding: .42rem .6rem; }
.pd-reg__tile b { font-size: .95rem; }
.pd-reg__lbl { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* --- Dark accent rails with a shine tail --- */
.pd-card::before {
    background: linear-gradient(90deg,
        color-mix(in srgb, var(--c, var(--accent)) 55%, #000),
        var(--c, var(--accent)) 55%,
        color-mix(in srgb, var(--c, var(--accent)) 55%, #fff));
}

/* --- Card face gloss: top light band over the corner wash --- */
.pd-card::after {
    background:
        linear-gradient(180deg, rgba(255, 255, 255, .08), transparent 42%),
        radial-gradient(160px 110px at 108% -18%, color-mix(in srgb, var(--c, var(--accent)) 12%, transparent), transparent 70%);
}
html[data-theme="dark"] .pd-card::after {
    background:
        linear-gradient(180deg, rgba(255, 255, 255, .05), transparent 42%),
        radial-gradient(160px 110px at 108% -18%, color-mix(in srgb, var(--c, var(--accent)) 14%, transparent), transparent 70%);
}

/* --- Chips: solid dark glossy faces, white glyphs --- */
.pd-chip {
    color: #fff;
    background: linear-gradient(180deg,
        color-mix(in srgb, var(--c, var(--accent)) 72%, #fff) 0%,
        var(--c, var(--accent)) 40%,
        color-mix(in srgb, var(--c, var(--accent)) 60%, #000) 100%);
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .45),
        inset 0 -2px 3px rgba(0, 0, 0, .28),
        0 2px 5px color-mix(in srgb, var(--c, var(--accent)) 45%, transparent);
}
html[data-theme="dark"] .pd-chip {
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .2),
        inset 0 -2px 3px rgba(0, 0, 0, .4),
        0 2px 5px rgba(0, 0, 0, .45);
}

/* --- Tags, badges, counts: deeper ink --- */
.pd-tag {
    color: color-mix(in srgb, var(--c, var(--muted)) 72%, #000);
    border-color: color-mix(in srgb, var(--c, var(--muted)) 55%, transparent);
    background: linear-gradient(180deg,
        color-mix(in srgb, var(--c, var(--muted)) 16%, transparent),
        color-mix(in srgb, var(--c, var(--muted)) 8%, transparent));
}
html[data-theme="dark"] .pd-tag { color: color-mix(in srgb, var(--c, var(--muted)) 65%, #fff); }
.pd-badge {
    color: color-mix(in srgb, var(--c, var(--accent)) 70%, #000);
    border-color: color-mix(in srgb, var(--c, var(--accent)) 55%, transparent);
}
html[data-theme="dark"] .pd-badge { color: color-mix(in srgb, var(--c, var(--accent)) 65%, #fff); }
.pd-count.is-hot {
    background: linear-gradient(180deg,
        color-mix(in srgb, var(--c, var(--accent)) 78%, #fff),
        color-mix(in srgb, var(--c, var(--accent)) 72%, #000));
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .35);
}
.pd-cta--solid { color: #0a2540; }
.pd-cta--solid:hover { color: #0a2540; }

/* --- Bars: glossy 3D fills over inset tracks --- */
.pd-bar span,
html[data-theme="dark"] .pd-bar span {
    background: linear-gradient(180deg,
        color-mix(in srgb, var(--c, var(--accent)) 55%, #fff),
        var(--c, var(--accent)) 45%,
        color-mix(in srgb, var(--c, var(--accent)) 62%, #000));
}

/* --- Quick tiles: dark glossy flood on hover --- */
.pd-quick__item:hover {
    background: linear-gradient(180deg,
        color-mix(in srgb, var(--c) 80%, #fff),
        color-mix(in srgb, var(--c) 75%, #000));
    border-color: color-mix(in srgb, var(--c) 60%, #000);
}

/* --- Ribbons: vertical gloss, deeper tones --- */
.pd-rib { background: linear-gradient(180deg, #f7b32b, #c2660a); }
.pd-rib--live { background: linear-gradient(180deg, #13c08c, #036c4f); }

/* Stat chips: icon inline beside the figure + caption (same stat
   anatomy as the KPI cards). The icon gets its own small glass tile. */
.pd-stat {
    display: grid; grid-template-columns: auto 1fr;
    column-gap: .55rem; row-gap: 0; align-items: center;
}
.pd-stat i {
    grid-row: 1 / span 2;
    width: 30px; height: 30px; border-radius: 5px;
    display: flex; align-items: center; justify-content: center;
    font-size: .95rem; opacity: 1;
    background: rgba(255, 255, 255, .16);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .3), 0 1px 2px rgba(2, 6, 23, .2);
}
.pd-stat b { align-self: end; }
.pd-stat span { align-self: start; }

/* Check-chips (column toggles above tables + modal checkbox groups) —
   pd sharp/3D language: crisp corners, raised faces, and a glossy
   solid-accent flood when checked (same treatment as pd icon chips). */
.check-chip {
    border-radius: 5px;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .55), 0 1px 2px rgba(2, 6, 23, .08);
}
html[data-theme="dark"] .check-chip { box-shadow: inset 0 1px 0 rgba(255, 255, 255, .05), 0 1px 2px rgba(0, 0, 0, .4); }
.check-chip span { color: var(--text-2); }
.check-chip input { accent-color: var(--accent); }
.check-chip:hover { border-color: color-mix(in srgb, var(--accent) 45%, var(--border)); }
.check-chip:active { transform: translateY(1px); }
.check-chip:has(input:checked) {
    border-color: color-mix(in srgb, var(--accent) 70%, #000);
    background: linear-gradient(180deg,
        color-mix(in srgb, var(--accent) 78%, #fff),
        var(--accent) 45%,
        color-mix(in srgb, var(--accent) 68%, #000));
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .35),
        inset 0 -2px 3px rgba(0, 0, 0, .22),
        0 2px 5px color-mix(in srgb, var(--accent) 45%, transparent);
}
.check-chip:has(input:checked) span { color: #fff; }
.check-chip:has(input:checked) input { accent-color: #fff; }
.col-toggle .check-chip { border-radius: 4px; }

/* Table column toggles: checked chips in a very light mint green instead
   of the accent-blue flood (modal check groups keep the accent look). */
.col-toggle .check-chip input { accent-color: #10b981; }
.col-toggle .check-chip:hover { border-color: color-mix(in srgb, #10b981 45%, var(--border)); }
.col-toggle .check-chip:has(input:checked) {
    border-color: color-mix(in srgb, #10b981 45%, var(--border));
    background: linear-gradient(180deg, #ecfdf5, #d1fae5);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .8), 0 1px 3px rgba(16, 185, 129, .18);
}
.col-toggle .check-chip:has(input:checked) span { color: #047857; }
.col-toggle .check-chip:has(input:checked) input { accent-color: #10b981; }
html[data-theme="dark"] .col-toggle .check-chip:has(input:checked) {
    background: linear-gradient(180deg, rgba(16, 185, 129, .26), rgba(16, 185, 129, .14));
    border-color: rgba(16, 185, 129, .5);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .08);
}
html[data-theme="dark"] .col-toggle .check-chip:has(input:checked) span { color: #6ee7b7; }

/* --- KPI strips that stay inline, and the KPI-shaped action button ---
   `--inline` holds a strip at its desktop column count all the way down to the
   smallest phone (the responsive pass otherwise drops it to two columns, then
   one). At phone width the cards switch to column anatomy so a narrow third of
   the screen still fits the figure under its chip.
   `pd-kpi--act` is a BUTTON wearing the KPI card: same surface, same rail, but
   it performs an action rather than reporting a number — used where an action
   belongs beside the counters it affects instead of in a separate toolbar. */
.pd-kpis--inline.pd-kpis--2 { grid-template-columns: repeat(2, 1fr); }
.pd-kpis--inline.pd-kpis--3 { grid-template-columns: repeat(3, 1fr); }
.pd-kpis--inline.pd-kpis--4 { grid-template-columns: repeat(4, 1fr); }
.pd-kpis--inline.pd-kpis--5 { grid-template-columns: repeat(5, 1fr); }
.pd-kpis--inline.pd-kpis--6 { grid-template-columns: repeat(6, 1fr); }

/* `--acts` — the page's action row wearing the card strip: what used to be a
   line of `.act-btn` pills is now `pd-kpi--act` cards, so an Add or a Print
   reads with the same weight as the figures underneath it.
   A counter strip is authored knowing how many cards it has; an action row is
   not — one page has a lone Add, another has seven tools, and a `--N` per page
   would be a number to keep in sync with the buttons. `auto-fit` sizes the
   track instead of the count: the cards divide the full width between them
   however many there are, and an eighth wraps to a second row rather than
   shrinking the first seven. A strip always spans the page, never trails off
   mid-row. Doubled class so it outranks the responsive `.pd-kpis` fold below. */
.pd-kpis.pd-kpis--acts { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }

/* Phone: two tools a row. `auto-fill` would give a 360px screen a single column
   and turn seven actions into seven rows — the pair keeps the row a row, and the
   `--inline` anatomy these strips also carry keeps each card one line tall. */
@media (max-width: 575.98px) {
    .pd-kpis.pd-kpis--acts { grid-template-columns: repeat(2, 1fr); }
}

/* An action row that DOES know its count can say so, and then it holds that
   count at every width — three tools stay a row of three on a phone instead of
   folding to 2 + 1 and stranding the last one on a line of its own. Declared
   after the fold above, and with a class more, so it outranks both the
   `auto-fit` default and the phone rule without reordering either: those are
   still what an action row gets when it doesn't name a number. */
.pd-kpis.pd-kpis--acts.pd-kpis--2 { grid-template-columns: repeat(2, 1fr); }
.pd-kpis.pd-kpis--acts.pd-kpis--3 { grid-template-columns: repeat(3, 1fr); }
.pd-kpis.pd-kpis--acts.pd-kpis--4 { grid-template-columns: repeat(4, 1fr); }

/* `--static` — a strip that only reports. Its cards take no hover lift, no
   shadow bloom and no pointer, so nothing on the row reads as clickable. The
   hover state is simply re-declared as the rest state (both 3D shadow stacks),
   which is why the values below mirror the `.pd-card` rules verbatim. */
.pd-kpis--static .pd-kpi { transition: none; cursor: default; }
.pd-kpis--static .pd-kpi:hover {
    transform: none;
    border-color: color-mix(in srgb, var(--c, var(--accent)) 14%, var(--border));
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .65),
        0 1px 2px rgba(2, 6, 23, .10),
        0 3px 8px rgba(2, 6, 23, .07);
}
html[data-theme="dark"] .pd-kpis--static .pd-kpi:hover {
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .06),
        0 1px 2px rgba(0, 0, 0, .5),
        0 4px 12px rgba(0, 0, 0, .35);
}
/* …except an action card. A strip may mix readouts with the button that acts on
   them, and `--static` is a statement about the numbers only: an `--act` card
   keeps its lift, bloom and pointer, or the one thing on the row that IS
   clickable would be the only thing not looking it. Same values as `.pd-card`. */
.pd-kpis--static .pd-kpi--act {
    transition: transform .14s ease, box-shadow .14s ease, border-color .14s ease;
    cursor: pointer;
}
.pd-kpis--static .pd-kpi--act:hover {
    transform: translateY(-3px);
    border-color: color-mix(in srgb, var(--c, var(--accent)) 38%, var(--border));
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .65),
        0 4px 8px rgba(2, 6, 23, .12),
        0 12px 24px rgba(2, 6, 23, .13);
}

.pd-kpi--act { width: 100%; font: inherit; text-align: left; color: var(--text); cursor: pointer; }
.pd-kpi--act .pd-kpi__val { font-size: 1.05rem; letter-spacing: -.01em; }
.pd-kpi--act .pd-kpi__go {
    margin-left: auto; flex-shrink: 0; font-size: .9rem;
    color: var(--c, var(--accent)); transition: transform .12s ease;
}
.pd-kpi--act:hover .pd-kpi__go { transform: translateX(2px); }
.pd-kpi--act:active { transform: translateY(-1px); }
.pd-kpi--act:focus-visible { outline: 2px solid var(--c, var(--accent)); outline-offset: 2px; }

/* `pd-kpi--field` is the third face of the card: it HOLDS an input rather than
   reporting a figure. The input inherits the figure's type so a typed query sits
   exactly where a number would, and the card itself carries the focus ring —
   the input draws no box of its own. Pairs with `--act` to make a toolbar of
   cards (a search beside its action) instead of a strip of counters. */
.pd-kpi--field:focus-within {
    border-color: color-mix(in srgb, var(--c, var(--accent)) 55%, var(--border));
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .65), 0 0 0 3px color-mix(in srgb, var(--c, var(--accent)) 15%, transparent);
}
.pd-kpi__input {
    width: 100%; min-width: 0; padding: 0; border: 0; background: none; color: var(--text);
    font-size: 1.05rem; font-weight: 800; line-height: 1.2; letter-spacing: -.01em;
}
.pd-kpi__input::placeholder { color: var(--muted); font-weight: 700; }
.pd-kpi__input:focus { outline: none; box-shadow: none; }
.pd-kpi__input::-webkit-search-cancel-button { cursor: pointer; }
/* A select works as the field too — it keeps the native arrow and popup, and only
   needs its options painted, since `background: none` would otherwise leave them
   unreadable where the UA inherits the control's background (Firefox). */
select.pd-kpi__input {
    -webkit-appearance: none;
    appearance: none;
    padding-right: 1.25rem;
    background-image: var(--f-chev);
    background-repeat: no-repeat;
    background-position: right .22rem center;
    background-size: 10px 7px;
    cursor: pointer;
}
.pd-kpi__input option { color: var(--text); background: var(--card-bg); }

/* An inline strip holds its column count where the plain grid would have folded
   to two, so from the tablet down each card gets a fraction of the row rather
   than half of it. The trailing `__side` — a badge over a sparkline or split bar
   — is the first thing that stops fitting: it is decoration on a figure that
   reads fine without it, so it goes and the figure keeps the width. */
@media (max-width: 991.98px) {
    .pd-kpis--inline .pd-kpi__side { display: none; }
}

/* Phone anatomy: the card keeps its inline reading order — a chip running the
   FULL card height on the left, and the text in front of it, value over label.
   The chip narrows and the type shrinks so a third of a 360px screen still
   fits both lines.
   The label is held to ONE line and clipped with an ellipsis. Grid rows stretch
   every card to the tallest in the row, so a single label wrapping to a second
   line ("Most Common Type", "Visible to Schools") raised the whole strip — one
   long caption cost height on every card beside it. A label is a caption for the
   figure above it, not the reading itself, so it gives up its tail rather than
   the row's height. */
@media (max-width: 575.98px) {
    /* `max-width` is what makes the ellipsis fire at five across: that layout
       centres the body, and a centred flex item is sized by its content, so a
       nowrap label would run past the card instead of clipping inside it. */
    .pd-kpi__lbl {
        max-width: 100%;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    .pd-kpis--inline { gap: .45rem; }
    .pd-kpis--inline .pd-kpi { flex-direction: row; align-items: stretch; gap: .4rem; padding: .4rem .45rem; }
    .pd-kpis--inline .pd-kpi .pd-chip {
        width: 22px; height: auto; align-self: stretch; font-size: .78rem; border-radius: 4px;
    }
    .pd-kpis--inline .pd-kpi__body { justify-content: center; gap: .1rem; margin-right: 0; }
    .pd-kpis--inline .pd-kpi__val { font-size: .92rem; white-space: normal; overflow: visible; }
    .pd-kpis--inline .pd-kpi--act .pd-kpi__val,
    .pd-kpis--inline .pd-kpi__input { font-size: .78rem; line-height: 1.15; }
    .pd-kpis--inline .pd-kpi__lbl { font-size: .55rem; letter-spacing: .02em; line-height: 1.2; }
    .pd-kpis--inline .pd-kpi__go { display: none; }

    /* Five across a 360px phone is ~60px a column — not enough to seat a chip
       BESIDE the text and still read it. At five (and six) the card reverts to
       stacked anatomy: the chip on its own line, the figure and label centred
       under it, each with the column's whole width instead of a third of it. */
    .pd-kpis--inline.pd-kpis--5,
    .pd-kpis--inline.pd-kpis--6 { gap: .3rem; }
    .pd-kpis--inline.pd-kpis--5 .pd-kpi,
    .pd-kpis--inline.pd-kpis--6 .pd-kpi {
        flex-direction: column; align-items: center; text-align: center;
        gap: .18rem; padding: .4rem .2rem;
    }
    .pd-kpis--inline.pd-kpis--5 .pd-kpi .pd-chip,
    .pd-kpis--inline.pd-kpis--6 .pd-kpi .pd-chip {
        width: 20px; height: 20px; align-self: center; font-size: .68rem; border-radius: 4px;
    }
    .pd-kpis--inline.pd-kpis--5 .pd-kpi__body,
    .pd-kpis--inline.pd-kpis--6 .pd-kpi__body { align-items: center; margin-right: 0; }
    .pd-kpis--inline.pd-kpis--5 .pd-kpi__val,
    .pd-kpis--inline.pd-kpis--6 .pd-kpi__val { font-size: .82rem; }
    .pd-kpis--inline.pd-kpis--5 .pd-kpi--act .pd-kpi__val,
    .pd-kpis--inline.pd-kpis--6 .pd-kpi--act .pd-kpi__val { font-size: .62rem; line-height: 1.15; }
    .pd-kpis--inline.pd-kpis--5 .pd-kpi__lbl,
    .pd-kpis--inline.pd-kpis--6 .pd-kpi__lbl { font-size: .48rem; letter-spacing: 0; }

    /* A sixth column takes ~10px off each of the other five, which the figure
       feels before the label does — it is the only part that can be a four-digit
       number. Everything below is the `--5` sizing shaved, not a new anatomy. */
    .pd-kpis--inline.pd-kpis--6 { gap: .22rem; }
    .pd-kpis--inline.pd-kpis--6 .pd-kpi { padding: .38rem .12rem; }
    .pd-kpis--inline.pd-kpis--6 .pd-kpi .pd-chip { width: 18px; height: 18px; font-size: .62rem; }
    .pd-kpis--inline.pd-kpis--6 .pd-kpi__val { font-size: .74rem; }
    .pd-kpis--inline.pd-kpis--6 .pd-kpi--act .pd-kpi__val { font-size: .58rem; }
    .pd-kpis--inline.pd-kpis--6 .pd-kpi__lbl { font-size: .44rem; }
}

/* ============================================================
   PD PORTAL SKIN — the SchoolAdmin (and office) portal adopts
   the pd design language through its canonical shared
   components; no view markup changes. Radii stay governed by
   the global sharp corner reset above.
   ============================================================ */

/* --- Stat tiles: extruded pd cards with glossy solid chips --- */
.stat-card {
    position: relative; overflow: hidden;
    border: 1px solid color-mix(in srgb, var(--stat-color, var(--accent)) 14%, var(--border));
    border-bottom: 2px solid color-mix(in srgb, var(--stat-color, var(--accent)) 32%, var(--border));
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .65),
        0 1px 2px rgba(2, 6, 23, .10),
        0 3px 8px rgba(2, 6, 23, .07);
}
.stat-card::before {
    content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px;
    background: linear-gradient(90deg,
        color-mix(in srgb, var(--stat-color, var(--accent)) 55%, #000),
        var(--stat-color, var(--accent)) 55%,
        color-mix(in srgb, var(--stat-color, var(--accent)) 55%, #fff));
}
.stat-card::after {
    content: ''; position: absolute; inset: 0; pointer-events: none;
    background:
        linear-gradient(180deg, rgba(255, 255, 255, .08), transparent 42%),
        radial-gradient(140px 90px at 108% -18%, color-mix(in srgb, var(--stat-color, var(--accent)) 12%, transparent), transparent 70%);
}
.stat-card:hover {
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .65),
        0 4px 8px rgba(2, 6, 23, .12),
        0 12px 24px rgba(2, 6, 23, .13);
}
html[data-theme="dark"] .stat-card,
html[data-theme="dark"] .stat-card:hover {
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .06),
        0 1px 2px rgba(0, 0, 0, .5),
        0 4px 12px rgba(0, 0, 0, .35);
}
.stat-icon {
    background: linear-gradient(180deg,
        color-mix(in srgb, var(--stat-color, var(--accent)) 72%, #fff) 0%,
        var(--stat-color, var(--accent)) 40%,
        color-mix(in srgb, var(--stat-color, var(--accent)) 60%, #000) 100%);
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .45),
        inset 0 -2px 3px rgba(0, 0, 0, .28),
        0 2px 5px color-mix(in srgb, var(--stat-color, var(--accent)) 45%, transparent);
}

/* --- Cards and panels: extruded surfaces with an accent top edge --- */
.table-card, .toolbar-card, .pcard, .sa-card {
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .65),
        0 1px 2px rgba(2, 6, 23, .10),
        0 3px 8px rgba(2, 6, 23, .07);
}
.table-card { border-top: 3px solid color-mix(in srgb, var(--accent) 70%, #000); }
.sa-card { border-top: 2px solid color-mix(in srgb, var(--accent) 45%, var(--border)); }
html[data-theme="dark"] .table-card,
html[data-theme="dark"] .toolbar-card,
html[data-theme="dark"] .pcard,
html[data-theme="dark"] .sa-card {
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .06),
        0 1px 2px rgba(0, 0, 0, .5),
        0 4px 12px rgba(0, 0, 0, .35);
}

/* --- Badges: deep-ink sharp tags with a top glint --- */
.badge-status {
    font-weight: 800;
    font-size: .66rem;
    text-transform: uppercase;
    letter-spacing: .04em;
    padding: .18rem .45rem;
    border: 1px solid transparent;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .4);
}
.badge-active   { border-color: rgba(16, 185, 129, .35); }
.badge-inactive { border-color: rgba(100, 116, 139, .3); }
.badge-warning  { border-color: rgba(245, 158, 11, .4); }
.badge-danger   { border-color: rgba(239, 68, 68, .35); }
html[data-theme="dark"] .badge-status { box-shadow: inset 0 1px 0 rgba(255, 255, 255, .06); }

/* --- Buttons: raised faces that press --- */
.icon-btn { box-shadow: inset 0 1px 0 rgba(255, 255, 255, .35), 0 1px 2px rgba(2, 6, 23, .15); }
.icon-btn:active { transform: translateY(1px); box-shadow: inset 0 1px 2px rgba(2, 6, 23, .25); }
html[data-theme="dark"] .icon-btn { box-shadow: inset 0 1px 0 rgba(255, 255, 255, .06), 0 1px 2px rgba(0, 0, 0, .4); }
.btn-premium { box-shadow: inset 0 1px 0 rgba(255, 255, 255, .3), 0 4px 10px -4px var(--accent); }
.btn-premium:active { transform: translateY(1px); }

/* --- Empty states: the pd dashed accent stage --- */
.empty-state {
    border: 1px dashed color-mix(in srgb, var(--accent) 30%, var(--border));
    background: color-mix(in srgb, var(--accent) 4%, transparent);
}

/* --- Modals: accent rail + deep lift --- */
.modal-content {
    border-top: 1px solid var(--border-strong);
    box-shadow: 0 2px 5px rgba(15, 23, 42, .08),
                0 24px 60px -18px rgba(0, 0, 0, .38),
                0 48px 110px -35px color-mix(in srgb, var(--accent) 25%, transparent);
}
html[data-theme="dark"] .modal-content {
    box-shadow: 0 24px 64px -18px rgba(0, 0, 0, .72),
                0 48px 110px -35px color-mix(in srgb, var(--accent) 18%, transparent);
}

/* PD settings pages: shared card footer + empty badges collapse */
.pd-foot {
    margin-top: .75rem; padding-top: .6rem;
    border-top: 1px dashed var(--border);
    display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
}
/* `--cta` — a footer whose button IS the page's submit. On a phone it takes the
   full row (a thumb target as wide as the card) and any note beside it drops
   underneath, instead of the two splitting one cramped line. */
@media (max-width: 575.98px) {
    .pd-foot--cta { flex-direction: column; align-items: stretch; }
    .pd-foot--cta > .btn { width: 100%; }
    .pd-foot--cta > .text-muted { margin-left: 0 !important; text-align: center; }
}
.pd-badge:empty { display: none; }

/* ============================================================
   PD COMPONENT PARITY — inner controls match the dashboard 1:1.
   Trigger/module/channel cards, input addons, fields, switches,
   session tiles and WhatsApp number cards all use the exact same
   tokens as the pd dashboard components: glossy 3-stop chips
   (white glyphs), extruded faces with dark→shine accent rails +
   bottom edges, carved inset fields with accent focus glow.
   ============================================================ */

/* --- Trigger/channel/module cards: miniature pd-cards --- */
.trg {
    position: relative; overflow: hidden;
    background: var(--card-bg);
    border: 1px solid color-mix(in srgb, var(--c, var(--accent)) 14%, var(--border));
    border-bottom: 2px solid color-mix(in srgb, var(--c, var(--accent)) 32%, var(--border));
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .65),
        0 1px 2px rgba(2, 6, 23, .10),
        0 3px 8px rgba(2, 6, 23, .07);
}
.trg::before {
    content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px;
    background: linear-gradient(90deg,
        color-mix(in srgb, var(--c, var(--accent)) 55%, #000),
        var(--c, var(--accent)) 55%,
        color-mix(in srgb, var(--c, var(--accent)) 55%, #fff));
}
html[data-theme="dark"] .trg {
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .06),
        0 1px 2px rgba(0, 0, 0, .5),
        0 4px 12px rgba(0, 0, 0, .35);
}
.trg__ico {
    color: #fff;
    background: linear-gradient(180deg,
        color-mix(in srgb, var(--c, var(--accent)) 72%, #fff) 0%,
        var(--c, var(--accent)) 40%,
        color-mix(in srgb, var(--c, var(--accent)) 60%, #000) 100%);
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .45),
        inset 0 -2px 3px rgba(0, 0, 0, .28),
        0 2px 5px color-mix(in srgb, var(--c, var(--accent)) 45%, transparent);
}

/* --- Input addons (pf-ico): exactly the pd chip face --- */
.input-group-text.pf-ico {
    background-color: transparent;
    background-image: linear-gradient(180deg,
        color-mix(in srgb, var(--c, var(--accent)) 72%, #fff) 0%,
        var(--c, var(--accent)) 40%,
        color-mix(in srgb, var(--c, var(--accent)) 60%, #000) 100%);
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .45),
        inset 0 -2px 3px rgba(0, 0, 0, .28);
}

/* --- Fields: carved inset faces + accent focus glow --- */
.form-control, .form-select {
    box-shadow: inset 0 1px 2px rgba(2, 6, 23, .08);
}
.form-control:focus, .form-select:focus {
    border-color: color-mix(in srgb, var(--accent) 60%, transparent);
    box-shadow:
        inset 0 1px 2px rgba(2, 6, 23, .08),
        0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent);
}
html[data-theme="dark"] .form-control,
html[data-theme="dark"] .form-select {
    box-shadow: inset 0 1px 2px rgba(0, 0, 0, .35);
}

/* --- Switches: glossy accent when on, pressed track when off --- */
.form-switch .form-check-input {
    box-shadow: inset 0 1px 2px rgba(2, 6, 23, .15);
}
.form-switch .form-check-input:checked {
    border-color: color-mix(in srgb, var(--accent) 68%, #000);
    box-shadow:
        inset 0 1px 1px rgba(255, 255, 255, .35),
        0 1px 3px color-mix(in srgb, var(--accent) 45%, transparent);
}

/* --- Academic session tiles: pd cards; current = glossy amber flood --- */
.ay {
    position: relative; overflow: hidden;
    background: var(--card-bg);
    border: 1px solid color-mix(in srgb, #f59e0b 18%, var(--border));
    border-bottom: 2px solid color-mix(in srgb, #f59e0b 35%, var(--border));
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .65),
        0 1px 2px rgba(2, 6, 23, .10),
        0 3px 8px rgba(2, 6, 23, .07);
}
.ay:hover:not(:disabled) {
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .65),
        0 4px 8px rgba(2, 6, 23, .12),
        0 12px 24px rgba(2, 6, 23, .13);
}
.ay.is-current {
    background: linear-gradient(180deg,
        color-mix(in srgb, #f59e0b 78%, #fff),
        #f59e0b 45%,
        color-mix(in srgb, #f59e0b 68%, #000));
    border-color: color-mix(in srgb, #f59e0b 70%, #000);
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .35),
        inset 0 -2px 3px rgba(0, 0, 0, .22),
        0 4px 12px color-mix(in srgb, #f59e0b 45%, transparent);
}
html[data-theme="dark"] .ay {
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .06),
        0 1px 2px rgba(0, 0, 0, .5),
        0 4px 12px rgba(0, 0, 0, .35);
}

/* --- WhatsApp number cards: pd cards, accent follows link state --- */
.wa-num { --c: #64748b; }
.wa-num.is-on { --c: #25d366; }
.wa-num {
    position: relative; overflow: hidden;
    background: var(--card-bg);
    border: 1px solid color-mix(in srgb, var(--c) 16%, var(--border));
    border-bottom: 2px solid color-mix(in srgb, var(--c) 34%, var(--border));
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .65),
        0 1px 2px rgba(2, 6, 23, .10),
        0 3px 8px rgba(2, 6, 23, .07);
}
.wa-num::before {
    content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px;
    background: linear-gradient(90deg,
        color-mix(in srgb, var(--c) 55%, #000),
        var(--c) 55%,
        color-mix(in srgb, var(--c) 55%, #fff));
}
.wa-num__avatar {
    color: #fff;
    background: linear-gradient(180deg,
        color-mix(in srgb, var(--c) 72%, #fff) 0%,
        var(--c) 40%,
        color-mix(in srgb, var(--c) 60%, #000) 100%);
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .45),
        inset 0 -2px 3px rgba(0, 0, 0, .28),
        0 2px 5px color-mix(in srgb, var(--c) 45%, transparent);
}
html[data-theme="dark"] .wa-num {
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .06),
        0 1px 2px rgba(0, 0, 0, .5),
        0 4px 12px rgba(0, 0, 0, .35);
}

/* --- Logo tile: the pd dashed empty stage --- */
.ss-page .ss-logo {
    border: 1px dashed color-mix(in srgb, var(--accent) 35%, var(--border));
    background: color-mix(in srgb, var(--accent) 4%, transparent);
}

/* PD settings: dashboard feed-rows carrying controls (switches/selects) */
.pd-row.is-off { opacity: .55; filter: grayscale(.35); }
.pd-row .form-switch { flex-shrink: 0; margin: 0; }
.pd-row .trg__sel { width: auto; max-width: 150px; flex-shrink: 0; font-size: .7rem; padding: .18rem 1.3rem .18rem .45rem; }
.pd-row__sub { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* PD settings polish: rows glow under the pointer
   compact glass chips, and the unsaved-changes tag breathes. */
.pd-list .pd-row { margin: 0 -.45rem; padding-left: .45rem; padding-right: .45rem; border-radius: 4px; transition: background .12s ease; }
.pd-list .pd-row:hover { background: color-mix(in srgb, var(--c, var(--accent)) 5%, transparent); }
.st-dirty { display: none; }
.st-dirty.is-on { display: inline-flex; animation: stPulse 1.6s ease infinite; }
@keyframes stPulse { 0%, 100% { opacity: 1; } 50% { opacity: .5; } }
.st-search { width: 180px; font-size: .74rem; }

/* ============================================================
   PD FULL PARITY — SIZES. The whole portal reads EXACTLY like
   the pd dashboard: every canonical component adopts the pd
   metrics verbatim (pd-card 6px/rail, pd-chip 34px glossy,
   val 1.18rem, lbl .64rem, panel .75/.9, row .8/.68, tag .6rem
   @4px, ava 28px @7px, grid gap .75rem). !important only where
   the EDGY 2px corner reset must be re-pointed at pd radii.
   ============================================================ */

/* --- Radii: the pd scale, portal-wide --- */
.pcard, .table-card, .toolbar-card, .stat-card, .sa-card, .kpi-card,
.kpi-tile, .mini-tile, .list-count, .pager, .modal-content, .empty-state,
.cs-card, .quick__item, .recent { border-radius: 6px !important; }
.stat-icon, .kpi-ico, .kpi-tile__ico, .mini-tile__ico, .pcard__ico,
.feed__ico, .icon-btn, .cs-icon, .trg__ico { border-radius: 5px !important; }
.avatar-circle { border-radius: 7px !important; }
.badge-status, .att-chip { border-radius: 4px !important; }.act-btn,
.act-search-wrap,
.act-search,
.act-select { border-radius: 6px !important; }
.check-chip { border-radius: 4px !important; }/* --- Page actions row: pd rhythm --- */
.page-actions { gap: .4rem; margin-bottom: .75rem; }

/* --- Stat tiles == pd-kpi, number for number --- */
.stat-tiles { gap: .75rem; margin-bottom: .75rem; }
.kpi-row { gap: .75rem; }
.stat-card, .kpi-card, .kpi-tile, .mini-tile { padding: .5rem .7rem; gap: .6rem; }
.stat-card {
    border-left: 1px solid color-mix(in srgb, var(--stat-color, var(--accent)) 14%, var(--border));
}
.stat-card:hover, .kpi-card:hover, .mini-tile:hover {
    transform: none;
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .65),
        0 1px 2px rgba(2, 6, 23, .10),
        0 3px 8px rgba(2, 6, 23, .07);
}
html[data-theme="dark"] .stat-card:hover,
html[data-theme="dark"] .kpi-card:hover,
html[data-theme="dark"] .mini-tile:hover {
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .06),
        0 1px 2px rgba(0, 0, 0, .5),
        0 4px 12px rgba(0, 0, 0, .35);
}
.stat-icon, .kpi-ico, .kpi-tile__ico, .mini-tile__ico {
    width: 34px; height: 34px; font-size: 1rem;
}
.stat-body { gap: .05rem; }
.stat-value, .kpi-value, .kpi-tile__val, .mini-tile__val {
    font-size: 1.18rem; line-height: 1.12; letter-spacing: -.02em;
    font-variant-numeric: tabular-nums;
}
.stat-label, .kpi-label, .kpi-tile__lbl, .mini-tile__lbl {
    font-size: .64rem; letter-spacing: .05em;
}
@media (max-width: 991.98px) { .stat-tiles { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 575.98px) { .stat-tiles { grid-template-columns: 1fr; } }

/* --- Panels: pcard == pd-panel --- */
.pcard__head { padding: .55rem .9rem; gap: .5rem; }
.pcard__ico {
    width: 30px; height: 30px; font-size: .9rem; color: #fff;
    background: linear-gradient(180deg,
        color-mix(in srgb, var(--c, var(--accent)) 72%, #fff) 0%,
        var(--c, var(--accent)) 40%,
        color-mix(in srgb, var(--c, var(--accent)) 60%, #000) 100%);
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .45),
        inset 0 -2px 3px rgba(0, 0, 0, .28),
        0 2px 5px color-mix(in srgb, var(--c, var(--accent)) 45%, transparent);
}
.pcard__title { font-size: .84rem; font-weight: 800; }
.pcard__sub { font-size: .68rem; }
.pcard__body { padding: .75rem .9rem; }
.pcard__foot { padding: .55rem .9rem; }
.pcard + .pcard { margin-top: .75rem; }
.pcard-head h6 { font-size: .84rem; font-weight: 800; }
.toolbar-card { padding: .75rem .9rem; }

/* --- Tables: pd feed-row typography --- */
table.premium-table thead th { font-size: .64rem; font-weight: 700; letter-spacing: .05em; }
table.premium-table tbody td { font-size: .8rem; padding: .42rem .75rem; }
table.premium-table tbody tr:hover { background: color-mix(in srgb, var(--accent) 5%, transparent); }
.avatar-circle { width: 28px; height: 28px; min-width: 28px; font-size: .72rem; }
.icon-btn { width: 30px; height: 30px; }
.pcard .table > thead > tr > th { font-size: .64rem; font-weight: 700; letter-spacing: .05em; }
.pcard .table > tbody > tr > td { font-size: .8rem; }

/* --- Mobile cards == pd cards --- */
.sa-card { padding: .5rem .7rem; }
.sa-card .sa-name { font-size: .8rem; }
.sa-card .sa-meta { font-size: .68rem; }

/* The mobile card took the pd METRICS above — radius, padding, type scale —
   but not the pd anatomy, so it still read as a plain box: flat border, flat
   top edge, flat avatar. On a phone this card replaces the whole table, so it
   is the only surface on the page and the one thing that has to look built.
   It gets the full treatment: accent rail across the top, corner wash, tinted
   border with a weighted bottom edge, glossy chip. `--c` is unset on these,
   so every rule falls through to the theme accent and no view has to declare
   a colour. Values are lifted verbatim from `.pd-card` — parity is the point,
   and a second set of near-miss numbers is what drifts. */
.sa-card {
    position: relative;
    overflow: hidden;
    border: 1px solid color-mix(in srgb, var(--c, var(--accent)) 14%, var(--border));
    border-bottom: 2px solid color-mix(in srgb, var(--c, var(--accent)) 32%, var(--border));
}
.sa-card::before {
    content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px;
    background: linear-gradient(90deg,
        color-mix(in srgb, var(--c, var(--accent)) 55%, #000),
        var(--c, var(--accent)) 55%,
        color-mix(in srgb, var(--c, var(--accent)) 55%, #fff));
}
.sa-card::after {
    content: ''; position: absolute; inset: 0; pointer-events: none;
    background:
        linear-gradient(180deg, rgba(255, 255, 255, .08), transparent 42%),
        radial-gradient(160px 110px at 108% -18%, color-mix(in srgb, var(--c, var(--accent)) 12%, transparent), transparent 70%);
}
html[data-theme="dark"] .sa-card::after {
    background:
        linear-gradient(180deg, rgba(255, 255, 255, .05), transparent 42%),
        radial-gradient(160px 110px at 108% -18%, color-mix(in srgb, var(--c, var(--accent)) 14%, transparent), transparent 70%);
}
/* The wash is a full-bleed `::after`; without this the content sits under it. */
.sa-card > * { position: relative; z-index: 1; }

/* The initial-letter avatar is this card's `pd-chip` — same glossy face. */
.sa-card .avatar-circle {
    background: linear-gradient(180deg,
        color-mix(in srgb, var(--c, var(--accent)) 72%, #fff) 0%,
        var(--c, var(--accent)) 40%,
        color-mix(in srgb, var(--c, var(--accent)) 60%, #000) 100%);
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .45),
        inset 0 -2px 3px rgba(0, 0, 0, .28),
        0 2px 5px color-mix(in srgb, var(--c, var(--accent)) 45%, transparent);
}
html[data-theme="dark"] .sa-card .avatar-circle {
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .2),
        inset 0 -2px 3px rgba(0, 0, 0, .4),
        0 2px 5px rgba(0, 0, 0, .45);
}

/* Row separators: an accent-tinted hairline instead of the dashed grey, and
   the caption in pd micro-caps so a field label reads like a `pd-kpi__lbl`
   rather than like body text that happens to be grey. */
.sa-card .sa-card-top { margin-bottom: .5rem; gap: .55rem; }
.sa-card .sa-card-top > div { min-width: 0; }
.sa-card .sa-row {
    padding: .32rem 0;
    border-top: 1px solid color-mix(in srgb, var(--c, var(--accent)) 12%, var(--border));
}
.sa-card .sa-row span:first-child {
    font-size: .6rem; font-weight: 800; text-transform: uppercase; letter-spacing: .05em;
}
.sa-card .sa-actions { margin-top: .55rem; }

/* --- Paired fields: two on a line ---
   A `.sa-row` is label-left / value-right, which is right for one fact per
   line. Short paired fields — start and end, total and passing — waste that
   shape: each spends a whole line, and the label eats half the width to say
   "Start". `.sa-pair` puts two of them side by side, each value stacked under
   its own caption, so a six-field card is three lines instead of six and the
   inputs get real width instead of a right-hand sliver.

   Unscoped from `.sa-card` on purpose: the shape is "captioned fields on a
   line", not "something a mobile card does". A modal that edits a handful of
   fields wants the same rows, and scoping it to the card would have meant
   either nesting a card inside a dialog or writing the layout twice. */
.sa-pair {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: .4rem .5rem;
    padding: .32rem 0;
    border-top: 1px solid color-mix(in srgb, var(--c, var(--accent)) 12%, var(--border));
}
/* Three to a line, for facts short enough that a half-line is already too much
   room — a mark, a grade, a position are each a handful of characters. Past
   three the caption starts clipping before the value does, which is why there
   is no `--4`. */
.sa-pair--3 { grid-template-columns: repeat(3, 1fr); }
/* Lead field wide, the rest narrow, all sitting on one baseline: a name beside
   the small controls that belong to it. Equal thirds would give a subject name
   the same width as a checkbox. */
.sa-pair--lead { grid-template-columns: 1fr 6rem 4rem; align-items: end; }
.sa-f { min-width: 0; display: flex; flex-direction: column; gap: .1rem; }
.sa-f__lbl {
    font-size: .6rem; font-weight: 800; text-transform: uppercase; letter-spacing: .05em;
    color: var(--muted);
    /* One line, clipped — a wrapping caption would stagger the two columns. */
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.sa-f__val { font-size: .8rem; font-weight: 700; min-width: 0; overflow-wrap: anywhere; }

/* A field pinned into the header line, beside the name rather than under it. */
.sa-card .sa-card-top .sa-f { margin-left: auto; flex: 0 0 8.5rem; max-width: 46%; }
/* With an input holding 8.5rem of the header, the name takes what is left and
   clips. Only on `--fields` cards: everywhere else the name has the whole line
   and is allowed to wrap rather than lose its tail. */
.sa-card--fields .sa-card-top .sa-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* --- Badges == pd-tag (deep ink, sharp, tiny) --- */
.badge-status, .att-chip { font-size: .6rem; padding: .11rem .4rem; letter-spacing: .04em; }
.badge-active {
    color: color-mix(in srgb, #10b981 72%, #000);
    border-color: color-mix(in srgb, #10b981 55%, transparent);
    background: linear-gradient(180deg, color-mix(in srgb, #10b981 16%, transparent), color-mix(in srgb, #10b981 8%, transparent));
}
.badge-inactive {
    color: color-mix(in srgb, #64748b 72%, #000);
    border-color: color-mix(in srgb, #64748b 55%, transparent);
    background: linear-gradient(180deg, color-mix(in srgb, #64748b 16%, transparent), color-mix(in srgb, #64748b 8%, transparent));
}
.badge-warning {
    color: color-mix(in srgb, #f59e0b 60%, #000);
    border-color: color-mix(in srgb, #f59e0b 55%, transparent);
    background: linear-gradient(180deg, color-mix(in srgb, #f59e0b 16%, transparent), color-mix(in srgb, #f59e0b 8%, transparent));
}
.badge-danger {
    color: color-mix(in srgb, #ef4444 72%, #000);
    border-color: color-mix(in srgb, #ef4444 55%, transparent);
    background: linear-gradient(180deg, color-mix(in srgb, #ef4444 16%, transparent), color-mix(in srgb, #ef4444 8%, transparent));
}
html[data-theme="dark"] .badge-active   { color: color-mix(in srgb, #10b981 65%, #fff); }
html[data-theme="dark"] .badge-inactive { color: color-mix(in srgb, #64748b 65%, #fff); }
html[data-theme="dark"] .badge-warning  { color: color-mix(in srgb, #f59e0b 65%, #fff); }
html[data-theme="dark"] .badge-danger   { color: color-mix(in srgb, #ef4444 65%, #fff); }

/* --- Empty states == pd-empty (dashed accent stage) --- */
.empty-state {
    border: 1px dashed color-mix(in srgb, var(--accent) 35%, var(--border));
    background: color-mix(in srgb, var(--accent) 3%, var(--surface-2));
    padding: 1rem;
}
.empty-state i { font-size: 1.4rem; margin-bottom: .3rem; }
.empty-state b { font-size: .84rem; }
.empty-state span { font-size: .74rem; }

/* --- Feed icons (office lists) == pd-ico --- */
.feed__ico { width: 28px; height: 28px; font-size: .85rem; }

/* --- List bar + counters: pd-head scale --- */
.list-bar { margin-bottom: .55rem; }
.list-bar .list-search { font-size: .74rem; }
.list-count { font-size: .68rem; }

/* --- Modals: pd-panel rhythm inside --- */
.modal-header { padding: .9rem 1rem; }
.modal-header .modal-title { font-size: .9rem; font-weight: 800; }
.modal-body { padding: 1rem; }
.modal-footer { padding: .7rem 1rem; }
@media (max-width: 575.98px) {
    .modal-header { padding: .78rem .85rem; }
    .modal-body { padding: .9rem .85rem; }
    .modal-footer { padding: .65rem .85rem max(.65rem, env(safe-area-inset-bottom)); }
}

/* ============================================================
   Per-page Help panel (offcanvas opened by the topbar Help button)
   ============================================================ */
.help-oc { width: min(420px, 92vw); border-left: 1px solid rgba(148, 163, 184, .22); }
.help-oc .offcanvas-header { border-bottom: 1px solid rgba(148, 163, 184, .2); padding: .85rem 1rem; }
.help-oc .offcanvas-title { font-size: .98rem; font-weight: 800; display: inline-flex; align-items: center; }
.help-oc .offcanvas-body { padding: 1rem; }
.help-intro { font-size: .9rem; line-height: 1.55; color: var(--muted, #64748b); margin: 0 0 1rem; }
.help-sec { margin-bottom: 1.05rem; }
.help-sec:last-child { margin-bottom: 0; }
.help-sec__h {
    display: flex; align-items: center; gap: .4rem;
    font-size: .7rem; font-weight: 800; text-transform: uppercase; letter-spacing: .06em;
    color: #0ea5e9; margin-bottom: .5rem;
}
.help-steps, .help-tips { margin: 0; padding-left: 0; list-style: none; counter-reset: help; }
.help-steps li, .help-tips li {
    position: relative; padding: .1rem 0 .1rem 1.9rem; margin-bottom: .55rem;
    font-size: .875rem; line-height: 1.5;
}
.help-steps li { counter-increment: help; }
.help-steps li::before {
    counter-increment: help; content: counter(help);
    position: absolute; left: 0; top: .05rem;
    width: 1.35rem; height: 1.35rem; border-radius: 6px;
    display: grid; place-items: center;
    font-size: .72rem; font-weight: 800; color: #fff;
    background: linear-gradient(160deg, #0ea5e9, #0369a1);
}
.help-tips li::before {
    content: "\F335"; font-family: "bootstrap-icons"; /* bi-lightbulb-fill */
    position: absolute; left: .1rem; top: .1rem; font-size: .95rem; color: #f59e0b;
}
.help-oc__foot {
    padding: .65rem 1rem; border-top: 1px solid rgba(148, 163, 184, .2);
    font-size: .78rem; color: var(--muted, #64748b);
}
:root[data-theme="dark"] .help-oc,
[data-bs-theme="dark"] .help-oc { background: #0f1629; color: #e2e8f0; }

/* ============================================================
   First-run guided tour (spotlight + card) — no external libs
   ============================================================ */
.tour-spot {
    position: fixed; top: 50%; left: 50%; width: 0; height: 0;
    border-radius: 10px; opacity: 0; pointer-events: none; z-index: 20000;
    box-shadow: 0 0 0 9999px rgba(2, 6, 23, .72);
    transition: top .28s ease, left .28s ease, width .28s ease, height .28s ease, opacity .2s ease;
}
.tour-card {
    position: fixed; z-index: 20001; width: 320px; max-width: calc(100vw - 16px);
    background: #fff; color: #0f172a; border-radius: 12px; padding: 1rem 1.1rem 1.05rem;
    box-shadow: 0 18px 50px -12px rgba(2, 6, 23, .55), 0 0 0 1px rgba(148, 163, 184, .18);
    opacity: 0; transform: translateY(6px); transition: opacity .2s ease, transform .2s ease;
}
.tour-card.is-on { opacity: 1; transform: translateY(0); }
.tour-card--center { top: 50% !important; left: 50% !important; transform: translate(-50%, -50%); }
.tour-card--center.is-on { transform: translate(-50%, -50%); }
.tour-card__step { font-size: .68rem; font-weight: 800; text-transform: uppercase; letter-spacing: .07em; color: #0ea5e9; }
.tour-card__title { font-size: 1.02rem; font-weight: 800; margin: .3rem 0 .4rem; }
.tour-card__text { font-size: .875rem; line-height: 1.55; color: #475569; margin: 0 0 .95rem; }
.tour-card__acts { display: flex; align-items: center; justify-content: space-between; }
.tour-card__nav { display: inline-flex; gap: .5rem; }
.tour-skip { border: 0; background: transparent; color: #94a3b8; font-size: .8rem; font-weight: 600; cursor: pointer; padding: .35rem .2rem; }
.tour-skip:hover { color: #64748b; }
.tour-back, .tour-next {
    border: 0; border-radius: 7px; padding: .4rem .85rem; font-size: .82rem; font-weight: 700; cursor: pointer;
}
.tour-back { background: #eef2f7; color: #475569; }
.tour-back:hover { background: #e2e8f0; }
.tour-next { background: linear-gradient(160deg, #2563eb, #0369a1); color: #fff; }
.tour-next:hover { filter: brightness(1.06); }
:root[data-theme="dark"] .tour-card,
[data-bs-theme="dark"] .tour-card { background: #111a2e; color: #e2e8f0; }
:root[data-theme="dark"] .tour-card__text,
[data-bs-theme="dark"] .tour-card__text { color: #94a3b8; }
:root[data-theme="dark"] .tour-back,
[data-bs-theme="dark"] .tour-back { background: #1e293b; color: #cbd5e1; }

/* ============================================================
   XL MODAL CANVAS
   Every dialog uses one generous XL shell with viewport-safe
   scrolling, refined spacing and consistent controls.
   Appended as the canonical override for earlier modal variants.
   ============================================================ */
.modal {
    --modal-edge-space: clamp(.75rem, 2vw, 1.5rem);
    padding: var(--modal-edge-space) !important;
}
.modal .modal-dialog {
    width: min(1140px, calc(100vw - (var(--modal-edge-space) * 2)));
    max-width: 1140px;
    height: auto;
    min-height: calc(100% - (var(--modal-edge-space) * 2));
    margin: auto;
    display: flex;
    align-items: center;
}
.modal .modal-dialog.modal-sm,
.modal .modal-dialog.modal-lg,
.modal .modal-dialog.modal-xl { max-width: 1140px; }
.modal .modal-dialog-centered::before { display: none; }

.modal .modal-content {
    width: 100%;
    height: auto;
    max-height: calc(100dvh - (var(--modal-edge-space) * 2));
    margin: 0;
    border: 1px solid var(--border-strong);
    border-radius: 12px !important;
    background:
        radial-gradient(circle at 8% 0, color-mix(in srgb, var(--accent) 4%, transparent), transparent 24rem),
        var(--card-bg);
    box-shadow: 0 26px 70px -22px rgba(2, 6, 23, .46),
                0 45px 100px -45px color-mix(in srgb, var(--accent) 35%, transparent);
}
.modal .modal-content::before {
    position: absolute;
    inset: 0 0 auto;
    height: 3px;
    background: linear-gradient(90deg, var(--accent), var(--accent-2) 58%, transparent 94%);
    box-shadow: 0 1px 14px color-mix(in srgb, var(--accent) 18%, transparent);
}

.modal .modal-header,
.modal .modal-body,
.modal .modal-footer {
    padding-left: clamp(1rem, 2.2vw, 1.5rem);
    padding-right: clamp(1rem, 2.2vw, 1.5rem);
}
.modal .modal-header {
    min-height: 72px;
    padding-top: .9rem;
    padding-bottom: .9rem;
    background: color-mix(in srgb, var(--surface-2) 93%, transparent);
    box-shadow: 0 1px 0 rgba(255, 255, 255, .35);
}
.modal .modal-heading__icon {
    width: 42px;
    height: 42px;
    flex-basis: 42px;
    border-radius: 8px;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .45),
                0 8px 18px -12px color-mix(in srgb, var(--accent) 65%, transparent);
}
.modal .modal-title { font-size: 1rem; }
.modal .modal-heading__copy small { margin-top: .22rem; font-size: .73rem; }

.modal .modal-body {
    flex: 1 1 auto;
    min-height: 0;
    padding-top: clamp(1rem, 2vw, 1.4rem);
    padding-bottom: clamp(1rem, 2vw, 1.4rem);
    background: transparent;
    overflow-x: hidden;
    overflow-y: auto;
    overscroll-behavior: contain;
}
.modal .modal-section-title {
    color: var(--accent);
    letter-spacing: .08em;
}
.modal .modal-footer {
    min-height: 66px;
    padding-top: .75rem;
    padding-bottom: .75rem;
    background: color-mix(in srgb, var(--surface-2) 93%, transparent);
    box-shadow: 0 -1px 0 rgba(255, 255, 255, .28);
}
.modal .modal-footer .btn {
    min-height: 42px;
    padding-inline: 1.15rem;
}

/* A restrained settle-in motion keeps the XL surface feeling light. */
.modal.fade .modal-dialog {
    opacity: 0;
    transform: translateY(12px) scale(.99);
    transition: opacity .18s ease, transform .22s cubic-bezier(.2, .75, .25, 1);
}
.modal.show .modal-dialog {
    opacity: 1;
    transform: none;
}

@media (max-width: 575.98px) {
    .modal {
        --modal-edge-space: .5rem;
        padding-top: max(.5rem, env(safe-area-inset-top)) !important;
        padding-bottom: max(.5rem, env(safe-area-inset-bottom)) !important;
    }
    .modal .modal-dialog,
    .modal:not(.modal-static) .modal-dialog:not(.modal-sm) {
        width: calc(100vw - 1rem);
        max-width: calc(100vw - 1rem);
        height: auto;
        min-height: calc(100% - 1rem);
        margin: auto;
        align-items: center;
    }
    .modal .modal-content,
    .modal:not(.modal-static) .modal-dialog:not(.modal-sm) .modal-content {
        height: auto;
        max-height: calc(100dvh - 1rem - env(safe-area-inset-top) - env(safe-area-inset-bottom));
        border-radius: 10px !important;
    }
    .modal .modal-header {
        min-height: 64px;
        padding-top: .72rem;
        padding-bottom: .72rem;
    }
    .modal .modal-heading__icon {
        width: 38px;
        height: 38px;
        flex-basis: 38px;
        border-radius: 7px;
    }
    .modal .modal-title { font-size: .94rem; }
    .modal .modal-heading__copy small {
        max-width: calc(100vw - 8rem);
        overflow: hidden;
        font-size: .68rem;
        text-overflow: ellipsis;
        white-space: nowrap;
    }
    .modal .modal-body {
        padding-top: 1rem;
        padding-bottom: 1rem;
    }
    .modal .modal-footer {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(112px, 1fr));
        min-height: auto;
        padding-top: .65rem;
        padding-bottom: .65rem;
    }
    .modal .modal-footer > .text-muted { grid-column: 1 / -1; }
    .modal .modal-footer .btn {
        width: 100%;
        min-height: 44px;
        margin: 0 !important;
    }
}

@media (prefers-reduced-motion: reduce) {
    .modal.fade .modal-dialog { transform: none; transition: none; }
}

/* Dialogs pinned to the TOP of the viewport instead of centred in it — short forms
   where the eye shouldn't have to travel down from the control that opened them.
   Only the vertical placement changes; the XL shell, the body scroll region and the
   safe-area padding are untouched.

   This MUST stay after the phone block above: that block re-centres the dialog with
   the same specificity, so placing these rules any earlier makes `modal--top` a
   desktop-only modifier that silently does nothing on a phone. */
.modal--top .modal-dialog { align-items: flex-start; }
@media (max-width: 575.98px) {
    .modal--top .modal-dialog,
    .modal--top:not(.modal-static) .modal-dialog:not(.modal-sm) { align-items: flex-start; }
}

/* FULL SCREEN, at every width — for the few dialogs that are a working surface in
   their own right (a sidebar plus a grid) rather than a column of fields. The shell
   otherwise caps every dialog at 1140px and insets it; this takes the whole viewport,
   squares the corners and lets the header/footer sit against the edges.

   Same placement rule as modal--top: these must stay after the phone block above,
   which sets width/max-height at higher specificity and a !important radius — hence
   the matching :not() chains and the one !important here. Safe-area insets are added
   back onto the header and footer so a notched phone doesn't clip them.

   SIZED IN %, NEVER vw/dvh. body carries zoom:.8 and zoom does NOT rescale viewport
   units, so 100vw/100dvh here covered only ~80% of the screen and left the right and
   bottom edges showing. Percentages resolve against the fixed .modal box and do scale
   — the same fix .modal-backdrop already uses. */
.modal--full { --modal-edge-space: 0px; padding: 0 !important; }
.modal--full .modal-dialog,
.modal--full:not(.modal-static) .modal-dialog:not(.modal-sm) {
    width: 100%;
    max-width: 100%;
    height: 100%;
    min-height: 100%;
    margin: 0;
    align-items: stretch;
}
.modal--full .modal-content,
.modal--full:not(.modal-static) .modal-dialog:not(.modal-sm) .modal-content {
    width: 100%;
    height: 100%;
    max-height: 100%;
    border: 0;
    border-radius: 0 !important;
}
.modal--full .modal-header { padding-top: calc(.9rem + env(safe-area-inset-top)); }
.modal--full .modal-footer { padding-bottom: calc(.75rem + env(safe-area-inset-bottom)); }

/* Full screen is tall enough to be worth panelling: the body stops scrolling as one
   sheet and each pane inside it scrolls on its own. Phones keep the single scroll —
   a stacked column with two scroll regions is a trap. */
@media (min-width: 768px) {
    .modal--full .modal-body { overflow: hidden; }
}

/* Premium checkbox language inside every modal. */
.modal .form-check:not(.form-switch) .form-check-input[type="checkbox"],
.modal .check-chip .form-check-input[type="checkbox"] {
    width: 1.2rem;
    height: 1.2rem;
    flex: 0 0 1.2rem;
    margin: 0;
    border: 1.5px solid var(--border-strong);
    border-radius: 5px !important;
    background-color: var(--card-bg);
    box-shadow: inset 0 1px 2px rgba(15, 23, 42, .08);
    cursor: pointer;
    transition: border-color .15s ease, background-color .15s ease, box-shadow .15s ease, transform .15s ease;
}
.modal .form-check:not(.form-switch) .form-check-input[type="checkbox"]:hover,
.modal .check-chip .form-check-input[type="checkbox"]:hover {
    border-color: color-mix(in srgb, var(--accent) 65%, var(--border));
}
.modal .form-check:not(.form-switch) .form-check-input[type="checkbox"]:checked,
.modal .check-chip .form-check-input[type="checkbox"]:checked {
    border-color: var(--accent);
    background-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-soft),
                0 6px 14px -8px color-mix(in srgb, var(--accent) 70%, transparent);
}
.modal .form-check:not(.form-switch) .form-check-input[type="checkbox"]:focus-visible,
.modal .check-chip .form-check-input[type="checkbox"]:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 3px;
    box-shadow: none;
}
.modal .check-chip {
    min-height: 44px;
    border-color: var(--border);
    background: var(--surface-2);
    transition: border-color .15s ease, background-color .15s ease, box-shadow .15s ease;
}
.modal .check-chip:has(.form-check-input:checked) {
    border-color: color-mix(in srgb, var(--accent) 62%, var(--border));
    background: var(--accent-soft);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 8%, transparent);
}

/* Modal forms use icons and placeholders; labels stay available to assistive tech. */
.modal .form-label:not(.form-check-label) {
    position: absolute !important;
    width: 1px !important;
    height: 1px !important;
    padding: 0 !important;
    margin: -1px !important;
    overflow: hidden !important;
    clip: rect(0, 0, 0, 0) !important;
    white-space: nowrap !important;
    border: 0 !important;
}

/* FINAL TUTORIAL PLAYER OVERRIDE
   This must remain after the canonical XL modal rules above. On desktop the YouTube
   iframe is exactly one viewport high; the floating title/close controls consume no
   layout height. On phones the complete 16:9 frame fits without any scroll region. */
.modal.tutorial-player-modal.show {
    display: flex !important;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}
.modal.tutorial-player-modal .modal-body {
    min-height: 0;
    padding: 0;
    overflow: hidden;
    scrollbar-gutter: auto;
}
.modal.tutorial-player-modal .ratio > iframe {
    display: block;
    width: 100%;
    height: 100%;
    border: 0;
    overflow: hidden;
    touch-action: manipulation;
}

@media (min-width: 576px) {
    .modal.tutorial-player-modal {
        --modal-edge-space: 0;
        padding: 0 !important;
    }
    .modal.tutorial-player-modal .modal-dialog {
        width: 100vw;
        max-width: 100vw;
        height: 100vh;
        height: 100dvh;
        min-height: 100vh;
        min-height: 100dvh;
        max-height: none;
        margin: 0;
        align-items: stretch;
    }
    .modal.tutorial-player-modal .modal-content {
        width: 100%;
        height: 100vh;
        height: 100dvh;
        max-height: none;
        margin: 0;
        border: 0;
        border-radius: 0 !important;
        overflow: hidden;
    }
    .modal.tutorial-player-modal .modal-content::before {
        display: none;
    }
    .modal.tutorial-player-modal .modal-header {
        position: absolute;
        inset: .75rem .75rem auto;
        min-height: 0;
        padding: 0;
        border: 0;
        background: transparent;
        pointer-events: none;
        z-index: 5;
    }
    .modal.tutorial-player-modal .modal-title {
        max-width: calc(100% - 4rem);
        overflow: hidden;
        padding: .45rem .7rem;
        color: #fff;
        background: rgba(3, 7, 18, .76);
        border-radius: 8px;
        text-overflow: ellipsis;
        white-space: nowrap;
        text-shadow: 0 1px 3px #000;
        backdrop-filter: blur(8px);
        -webkit-backdrop-filter: blur(8px);
        pointer-events: auto;
    }
    .modal.tutorial-player-modal .modal-header .btn-close {
        width: 38px;
        height: 38px;
        flex: 0 0 38px;
        background-color: rgba(255, 255, 255, .92);
        border-color: rgba(255, 255, 255, .75);
        pointer-events: auto;
    }
    .modal.tutorial-player-modal .modal-body,
    .modal.tutorial-player-modal .ratio {
        width: 100%;
        height: 100vh;
        height: 100dvh;
        max-height: none;
    }
    .modal.tutorial-player-modal .ratio {
        aspect-ratio: auto;
    }
    .modal.tutorial-player-modal .ratio::before {
        display: none;
    }
    .modal.tutorial-player-modal .ratio > iframe {
        position: static;
    }
}

@media (max-width: 575.98px) {
    .modal.tutorial-player-modal {
        --modal-edge-space: .45rem;
        padding: var(--modal-edge-space) !important;
    }
    .modal.tutorial-player-modal .modal-dialog,
    .modal.tutorial-player-modal:not(.modal-static) .modal-dialog:not(.modal-sm) {
        width: min(calc(100vw - .9rem), calc(177.78vh - 8rem));
        width: min(calc(100vw - .9rem), calc(177.78dvh - 8rem));
        max-width: min(calc(100vw - .9rem), calc(177.78dvh - 8rem));
        height: auto;
        min-height: 0;
        max-height: calc(100dvh - .9rem);
        margin: auto;
        align-items: center;
    }
    .modal.tutorial-player-modal .modal-content,
    .modal.tutorial-player-modal:not(.modal-static) .modal-dialog:not(.modal-sm) .modal-content {
        height: auto;
        max-height: calc(100dvh - .9rem);
        border-radius: 12px !important;
        overflow: hidden;
    }
    .modal.tutorial-player-modal .modal-header {
        min-height: 50px;
        padding: .45rem .65rem;
        gap: .5rem;
    }
    .modal.tutorial-player-modal .modal-title {
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        font-size: .88rem;
    }
    .modal.tutorial-player-modal .modal-header .btn-close {
        width: 34px;
        height: 34px;
        flex-basis: 34px;
    }
    .modal.tutorial-player-modal .ratio {
        width: 100%;
        height: auto;
        aspect-ratio: 16 / 9;
    }
}

/* ============================================================
   CLASSIC VIEW
   A restrained, conventional administration skin. This block is deliberately last so
   it consistently flattens every newer visual layer while preserving layout and meaning.
   Classic can be used in either light or dark mode.
   ============================================================ */
@media not all {
.classic-icon-on { display: none; }
html[data-design="classic"] .classic-icon-modern { display: none; }
html[data-design="classic"] .classic-icon-on { display: inline-block; }

html[data-design="classic"] {
    --text: #202830;
    --text-2: #4b5966;
    --muted: #73808c;
    --content-bg: #edf0f3;
    --card-bg: #ffffff;
    --surface: #ffffff;
    --surface-2: #f5f6f7;
    --surface-3: #e9edf1;
    --hover-tint: #f3f6f8;
    --border: #d2d8de;
    --border-strong: #b9c2cb;
    --sidebar-bg: #26394b;
    --sidebar-bg-2: #30475d;
    --sidebar-hover: rgba(255, 255, 255, .09);
    --sidebar-text: #d1d9e0;
    --accent: #315f88;
    --accent-dark: #244968;
    --accent-2: #315f88;
    --accent-soft: #e6eef5;
    --success: #39734d;
    --success-bg: #eaf3ed;
    --danger: #a33a3a;
    --warn-bg: #f7f0de;
    --shadow-1: none;
    --shadow-2: none;
    --shadow-3: none;
    --ring: 0 0 0 2px rgba(49, 95, 136, .18);
    --radius: 3px;
}

html[data-design="classic"][data-theme="dark"] {
    --text: #e4e9ed;
    --text-2: #bdc7cf;
    --muted: #8997a3;
    --content-bg: #171c21;
    --card-bg: #22292f;
    --surface: #22292f;
    --surface-2: #283038;
    --surface-3: #303942;
    --hover-tint: #2b343c;
    --border: #3b454e;
    --border-strong: #505c66;
    --sidebar-bg: #111b24;
    --sidebar-bg-2: #182631;
    --accent: #79a4c8;
    --accent-dark: #5e8db4;
    --accent-2: #79a4c8;
    --accent-soft: rgba(121, 164, 200, .14);
    --success-bg: rgba(57, 115, 77, .2);
    --warn-bg: rgba(176, 132, 45, .16);
}

html[data-design="classic"] body {
    font-family: "Segoe UI", Arial, Helvetica, sans-serif;
    letter-spacing: 0;
    font-feature-settings: normal;
}
html[data-design="classic"] h1,
html[data-design="classic"] h2,
html[data-design="classic"] h3,
html[data-design="classic"] h4,
html[data-design="classic"] h5,
html[data-design="classic"] h6,
html[data-design="classic"] .topbar-title,
html[data-design="classic"] .modal-title {
    letter-spacing: 0;
}

/* Shell and navigation */
html[data-design="classic"] .app-sidebar {
    background: var(--sidebar-bg);
    border-right: 1px solid rgba(0, 0, 0, .24);
    box-shadow: none;
}
html[data-design="classic"] .sidebar-brand {
    min-height: 40px;
    background: var(--sidebar-bg-2);
    border-bottom-color: rgba(255, 255, 255, .14);
}
html[data-design="classic"] .brand-mark {
    border: 1px solid rgba(255, 255, 255, .28);
    border-radius: 3px !important;
    background: #f4f6f8;
    color: #26394b;
    box-shadow: none;
}
html[data-design="classic"] .brand-mark--img { background: #fff; }
html[data-design="classic"] .brand-text {
    font-weight: 600;
    letter-spacing: 0;
}
html[data-design="classic"] .nav-link,
html[data-design="classic"] .nav-parent {
    margin: 0;
    border: 1px solid transparent;
    border-radius: 2px !important;
    font-weight: 500;
    letter-spacing: 0;
    transition: background-color .1s ease, color .1s ease;
}
html[data-design="classic"] .nav-link:hover,
html[data-design="classic"] .nav-parent:hover {
    background: var(--sidebar-hover);
    border-color: rgba(255, 255, 255, .07);
}
html[data-design="classic"] .nav-link.active {
    background: #f5f7f9;
    color: #223a50;
    border-color: #fff;
    box-shadow: none;
}
html[data-design="classic"] .nav-link.active::before { display: none; }
html[data-design="classic"] .nav-icon-chip,
html[data-design="classic"] .nav-link.active .nav-icon-chip,
html[data-design="classic"] .nav-item.trail > .nav-parent .nav-icon-chip {
    border-radius: 2px !important;
    background: rgba(255, 255, 255, .1);
    color: currentColor;
    box-shadow: none;
    transform: none;
}
html[data-design="classic"] .nav-link.active .nav-icon-chip {
    background: #dce7f0;
    color: #315f88;
}
html[data-design="classic"] .nav-sub {
    transition-duration: .12s;
}
html[data-design="classic"] .nav-sub-inner {
    border-left-color: rgba(255, 255, 255, .18);
}
html[data-design="classic"] .sidebar-design {
    background: var(--sidebar-bg-2);
    border-top-color: rgba(255, 255, 255, .14);
}

html[data-design="classic"] .app-topbar {
    min-height: 49px;
    padding: .45rem .8rem;
    background: var(--card-bg);
    border-bottom: 1px solid var(--border-strong);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    box-shadow: none;
}
html[data-design="classic"] .topbar-title {
    font-size: 1rem;
    font-weight: 600;
}
html[data-design="classic"] .submenu-btn,
html[data-design="classic"] .topbar-search,
html[data-design="classic"] .topbar-toggle {
    border: 1px solid var(--border-strong);
    border-radius: 3px !important;
    background: var(--surface);
    color: var(--text-2);
    box-shadow: none;
    transition: background-color .1s ease, border-color .1s ease;
}
html[data-design="classic"] .submenu-btn:hover,
html[data-design="classic"] .topbar-search:hover,
html[data-design="classic"] .topbar-toggle:hover {
    transform: none;
    color: var(--text);
    background: var(--surface-3);
    border-color: #94a1ad;
    box-shadow: none;
}
html[data-design="classic"] .classic-toggle.active {
    color: #fff;
    background: var(--accent-dark);
    border-color: var(--accent-dark);
}
html[data-design="classic"] .cmdk-kbd { display: none; }
html[data-design="classic"] .app-content {
    padding: 1rem;
    background: var(--content-bg);
}

/* Flat, conventional surfaces */
html[data-design="classic"] .pcard,
html[data-design="classic"] .table-card,
html[data-design="classic"] .toolbar-card,
html[data-design="classic"] .stat-card,
html[data-design="classic"] .sa-card,
html[data-design="classic"] .kpi-card,
html[data-design="classic"] .kpi-tile,
html[data-design="classic"] .mini-tile,
html[data-design="classic"] .recent,
html[data-design="classic"] .quick__item,
html[data-design="classic"] .cs-card,
html[data-design="classic"] .pd-card,
html[data-design="classic"] .pd-empty,
html[data-design="classic"] .list-count,
html[data-design="classic"] .pager {
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: 3px !important;
    box-shadow: none;
}
html[data-design="classic"] .pcard:hover,
html[data-design="classic"] .table-card:hover,
html[data-design="classic"] .stat-card:hover,
html[data-design="classic"] .pd-card:hover,
html[data-design="classic"] .quick__item:hover,
html[data-design="classic"] .pd-quick__item:hover {
    transform: none;
    box-shadow: none;
}
html[data-design="classic"] .pd-card::before,
html[data-design="classic"] .pd-card::after,
html[data-design="classic"] .stat-card::before,
html[data-design="classic"] .stat-card::after {
    display: none;
}
html[data-design="classic"] .pcard__head,
html[data-design="classic"] .pd-head,
html[data-design="classic"] .modal-header,
html[data-design="classic"] .modal-footer {
    background: var(--surface-2);
    border-color: var(--border);
}

/* The dashboard banner becomes a sober page header, not a promotional one. */
html[data-design="classic"] .dash-banner {
    color: var(--text);
    background: var(--card-bg);
    border: 1px solid var(--border-strong);
    border-left: 4px solid var(--accent);
    border-radius: 3px !important;
    box-shadow: none;
}

html[data-design="classic"] .dash-banner p,
html[data-design="classic"] .dash-banner__hi {
    color: var(--text-2) !important;
}html[data-design="classic"] .act-btn,
html[data-design="classic"] .pd-cta,
html[data-design="classic"] .dash-banner__cta {
    color: var(--text-2);
    background: var(--surface-2);
    border: 1px solid var(--border-strong);
    border-radius: 3px !important;
    box-shadow: none;
    backdrop-filter: none;
}html[data-design="classic"] .act-btn:hover,
html[data-design="classic"] .pd-cta:hover,
html[data-design="classic"] .dash-banner__cta:hover {
    color: var(--text);
    background: var(--surface-3);
    transform: none;
    box-shadow: none;
}
html[data-design="classic"] .pd-rib { display: none; }/* Classic controls */
html[data-design="classic"] .btn,
html[data-design="classic"] .btn-premium,
html[data-design="classic"] .icon-btn,
html[data-design="classic"] .act-btn,
html[data-design="classic"] .pager-btn,
html[data-design="classic"] .tt-btn,
html[data-design="classic"] .check-chip {
    border-radius: 3px !important;
    box-shadow: none;
    text-shadow: none;
    transform: none;
}
html[data-design="classic"] .btn-premium {
    color: #fff;
    background: var(--accent);
    border: 1px solid var(--accent-dark);
}
html[data-design="classic"] .btn-premium:hover {
    color: #fff;
    background: var(--accent-dark);
    filter: none;
    transform: none;
    box-shadow: none;
}
html[data-design="classic"] .form-control,
html[data-design="classic"] .form-select,
html[data-design="classic"] .input-group-text,
html[data-design="classic"] .search-input,
html[data-design="classic"] .status-select,
html[data-design="classic"] .act-search,
html[data-design="classic"] .act-select {
    color: var(--text);
    background-color: var(--surface);
    border: 1px solid var(--border-strong);
    border-radius: 3px !important;
    box-shadow: none;
}
html[data-design="classic"] .form-control:focus,
html[data-design="classic"] .form-select:focus,
html[data-design="classic"] .search-input:focus,
html[data-design="classic"] .status-select:focus {
    background-color: var(--surface);
    border-color: var(--accent);
    box-shadow: var(--ring);
}

/* Tables and data density */
html[data-design="classic"] table.premium-table,
html[data-design="classic"] .pcard .table {
    border-collapse: collapse;
}
html[data-design="classic"] table.premium-table thead th,
html[data-design="classic"] .pcard .table > thead > tr > th {
    color: var(--text-2);
    background: var(--surface-3);
    border: 1px solid var(--border);
    text-transform: none;
    letter-spacing: 0;
    font-weight: 600;
}
html[data-design="classic"] table.premium-table tbody td,
html[data-design="classic"] .pcard .table > tbody > tr > td {
    border: 1px solid var(--border);
}
html[data-design="classic"] table.premium-table tbody tr:nth-child(even),
html[data-design="classic"] .pcard .table > tbody > tr:nth-child(even) {
    background: var(--surface-2);
}
html[data-design="classic"] table.premium-table tbody tr:hover,
html[data-design="classic"] .pcard .table > tbody > tr:hover {
    background: var(--accent-soft);
}

/* Replace glossy dashboard ornaments with simple labelled tiles. */
html[data-design="classic"] .pd-chip,
html[data-design="classic"] .stat-icon,
html[data-design="classic"] .pcard__ico,
html[data-design="classic"] .kpi-tile__ico,
html[data-design="classic"] .mini-tile__ico,
html[data-design="classic"] .pd-ico,
html[data-design="classic"] .pd-ava,
html[data-design="classic"] .avatar-circle {
    color: var(--accent);
    background: var(--accent-soft);
    border: 1px solid color-mix(in srgb, var(--accent) 25%, var(--border));
    border-radius: 3px !important;
    box-shadow: none;
    text-shadow: none;
}
html[data-design="classic"] .pd-badge,
html[data-design="classic"] .pd-tag,
html[data-design="classic"] .badge,
html[data-design="classic"] .badge-status {
    border-radius: 2px !important;
    box-shadow: none;
    text-shadow: none;
}
html[data-design="classic"] .pd-stat,
html[data-design="classic"] .pd-quick__item,
html[data-design="classic"] .pd-reg__tile {
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: 3px !important;
    box-shadow: none;
}
html[data-design="classic"] .pd-bar,
html[data-design="classic"] .pd-kpi__split {
    box-shadow: none;
}

/* Overlays keep conventional borders and no decorative glow. Tutorial fullscreen sizing
   remains governed by the more specific player rules immediately above this block. */
html[data-design="classic"] .modal:not(.tutorial-player-modal) .modal-content,
html[data-design="classic"] .cmdk,
html[data-design="classic"] .offcanvas {
    border: 1px solid var(--border-strong);
    border-radius: 3px !important;
    background: var(--card-bg);
    box-shadow: 0 4px 14px rgba(0, 0, 0, .16);
}
html[data-design="classic"] .modal:not(.tutorial-player-modal) .modal-content::before {
    display: none;
}
html[data-design="classic"] .modal-backdrop.show,
html[data-design="classic"] .cmdk-backdrop {
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
}
html[data-design="classic"] .cmdk-item,
html[data-design="classic"] .cmdk-item .cmdk-ico {
    border-radius: 2px;
}
html[data-design="classic"] .app-content.page-enter {
    animation: none;
}
html[data-design="classic"] .app-content.page-leave {
    opacity: 1;
    transform: none;
    transition: none;
}

@media (max-width: 767.98px) {
    html[data-design="classic"] .classic-toggle .submenu-label { display: none; }
    html[data-design="classic"] .app-content { padding: .7rem; }
}
}

/* ---------- Teacher / Parent / Student notification inbox ---------- */
.ni-page {
    width: min(920px, 100%);
    margin: 0 auto;
}

/* Page head: title, lede and the inbox's own actions. A plain row on the page
   background — the band it used to sit on is gone. */
.ni-head {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 1rem;
}
.ni-eyebrow {
    display: inline-flex;
    align-items: center;
    gap: .38rem;
    margin-bottom: .4rem;
    color: #ec4899;
    font-size: .72rem;
    font-weight: 800;
    letter-spacing: .06em;
    text-transform: uppercase;
}
.ni-head h2 { margin: 0 0 .3rem; font-size: 1.45rem; font-weight: 800; }
.ni-head p { margin: 0; color: var(--muted); font-size: .86rem; }
.ni-head__actions { display: flex; align-items: center; gap: .65rem; flex: 0 0 auto; }
.ni-count {
    padding: .32rem .58rem;
    border: 1px solid color-mix(in srgb, #ec4899 35%, var(--border));
    border-radius: 999px;
    color: #db2777;
    background: color-mix(in srgb, #ec4899 9%, var(--card-bg));
    font-size: .72rem;
    font-weight: 800;
}
.ni-list {
    display: grid;
    gap: .55rem;
}
.ni-item {
    position: relative;
    display: flex;
    align-items: flex-start;
    gap: .9rem;
    padding: .92rem 1rem;
    border: 1px solid var(--border);
    border-radius: 11px;
    color: var(--text);
    background: var(--card-bg);
    text-decoration: none;
    transition: border-color .16s ease, transform .16s ease, box-shadow .16s ease;
}
.ni-item:hover {
    color: var(--text);
    border-color: color-mix(in srgb, var(--ni-color) 42%, var(--border));
    transform: translateY(-1px);
    box-shadow: var(--shadow-sm);
}
.ni-item.is-unread {
    border-left: 4px solid var(--ni-color);
    background: color-mix(in srgb, var(--ni-color) 7%, var(--card-bg));
}
.ni-icon {
    width: 2.35rem;
    height: 2.35rem;
    flex: 0 0 2.35rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 9px;
    color: var(--ni-color);
    background: color-mix(in srgb, var(--ni-color) 13%, var(--card-bg));
    border: 1px solid color-mix(in srgb, var(--ni-color) 20%, var(--border));
}
.ni-body { min-width: 0; display: flex; flex: 1 1 auto; flex-direction: column; gap: .24rem; }
.ni-title { display: flex; align-items: center; gap: .45rem; font-size: .9rem; font-weight: 800; }
.ni-dot { width: .48rem; height: .48rem; border-radius: 50%; background: var(--ni-color); }
.ni-message { color: var(--text); font-size: .83rem; line-height: 1.48; opacity: .88; }
.ni-time { color: var(--muted); font-size: .7rem; font-weight: 600; }
.ni-arrow { align-self: center; color: var(--muted); }
.ni-empty {
    padding: 3.5rem 1rem;
    border: 1px dashed var(--border-strong);
    border-radius: 12px;
    text-align: center;
    background: var(--card-bg);
}
.ni-empty > span {
    width: 3.2rem;
    height: 3.2rem;
    margin: 0 auto .8rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    color: #ec4899;
    background: color-mix(in srgb, #ec4899 11%, var(--card-bg));
    font-size: 1.35rem;
}
.ni-empty h3 { margin: 0 0 .3rem; font-size: 1rem; font-weight: 800; }
.ni-empty p { margin: 0; color: var(--muted); font-size: .82rem; }

@media (max-width: 640px) {
    .ni-head { align-items: flex-start; flex-direction: column; }
    .ni-head__actions { width: 100%; justify-content: space-between; }
    .ni-item { padding: .8rem; gap: .7rem; }
}

/* ============================================================
   DENSE MODAL LISTS — the pd feed-row idiom, inside a modal.
   A modal body already frames its content, so the rows inside
   it drop card chrome entirely and lean on the same hairline +
   hover-tint rhythm as a panel's `.pd-list`: 28px chip, .8rem
   name over a .68rem sub, ~38px rows. Markup is plain pd —
   `.pd-list` / `.pd-row` / `.pd-ico` — so a modal list and a
   settings panel list read as the same component.

   `.mfind`  a search that stays put while the list scrolls.
   `.mpick`  the same rows as a two-column multi-select grid.
   ============================================================ */
.mfind {
    position: sticky; top: -1rem; z-index: 2;
    margin: -.35rem 0 .5rem; padding: .35rem 0 .5rem;
    background: linear-gradient(var(--card-bg) 76%, transparent);
}
.mfind .form-control { font-size: .78rem; }

/* A picker cell is its own tile, not a list row: at six across there is no room
   for a chip, so the checkbox leads and two truncating lines follow. Anything
   that will not fit (a phone number beside a name) belongs in `title`, not on
   screen. Six columns on desktop stepping down to two on a phone. */
.mpick { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: .4rem; }
@media (max-width: 1399.98px) { .mpick { grid-template-columns: repeat(5, minmax(0, 1fr)); } }
@media (max-width: 1199.98px) { .mpick { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (max-width: 991.98px)  { .mpick { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 767.98px)  { .mpick { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.mpick__row {
    display: flex; align-items: center; gap: .4rem; min-width: 0; margin: 0;
    padding: .4rem .45rem; border: 1px solid var(--border); border-radius: 5px;
    background: var(--surface-2); cursor: pointer;
    transition: border-color .12s ease, background .12s ease, box-shadow .12s ease;
}
.mpick__row:hover {
    border-color: color-mix(in srgb, var(--c, var(--accent)) 45%, var(--border));
    background: var(--hover-tint);
}
/* `.is-selected` is set by script for pickers that repaint their cells; the
   `:has()` twin keeps a plain checkbox picker correct with no script at all. */
.mpick__row:has(input:checked),
.mpick__row.is-selected {
    border-color: color-mix(in srgb, var(--c, var(--accent)) 60%, var(--border));
    background: color-mix(in srgb, var(--c, var(--accent)) 10%, var(--surface-2));
    box-shadow: inset 2px 0 0 var(--c, var(--accent));
}
.mpick__row .form-check-input { width: .95rem; height: .95rem; flex-shrink: 0; margin: 0; box-shadow: none; }
.mpick__copy { display: flex; flex-direction: column; min-width: 0; gap: .05rem; }
.mpick__name,
.mpick__sub { display: block; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mpick__name { font-size: .74rem; font-weight: 700; color: var(--text); line-height: 1.25; }
.mpick__sub { font-size: .62rem; font-weight: 600; color: var(--muted); line-height: 1.25; }
.mpick__row:has(input:checked) .mpick__sub,
.mpick__row.is-selected .mpick__sub { color: var(--c, var(--accent)); }

@media (max-width: 575.98px) { .mfind { top: -.75rem; } }

/* `.mgrid` lays the same rows out in columns instead of a stack — for a long
   roster (a sibling group) where one row per line wastes a full-screen modal's
   width. A grid has no single run to divide, so each cell carries its own
   border rather than pd-list's shared hairlines. */
.mgrid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: .4rem; }
.mgrid .pd-row {
    margin: 0; padding: .4rem .5rem; border: 1px solid var(--border); border-radius: 5px;
    background: var(--surface-2); transition: border-color .12s ease, background .12s ease;
}
.mgrid a.pd-row:hover {
    border-color: color-mix(in srgb, var(--c, var(--accent)) 45%, var(--border));
    background: var(--hover-tint);
}
@media (max-width: 1199.98px) { .mgrid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 991.98px)  { .mgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 575.98px)  { .mgrid { grid-template-columns: 1fr; } }

/* ============================================================
   FULL-SCREEN MODALS — an editor, not a dialog.
   The portal's default modal is a centred card on desktop and a
   bottom sheet on a phone, and both of those are enforced with
   margins, radii and a capped max-height. `.modal--full` on the
   modal (with Bootstrap's `.modal-fullscreen` on the dialog)
   opts out of both and takes the whole viewport at every width.
   The selectors carry both classes because the bottom-sheet
   rules they override are themselves specificity-heavy.
   ============================================================ */
.modal.modal--full { padding: 0 !important; }
.modal.modal--full .modal-dialog.modal-fullscreen {
    width: 100%; max-width: none; height: 100%; min-height: 100%;
    margin: 0; display: flex; align-items: stretch;
}
.modal.modal--full .modal-dialog.modal-fullscreen .modal-content {
    width: 100%; height: 100%; max-height: none;
    border: 0; border-radius: 0;
}
/* Header and footer hold their ground; the body is the only scroll region. */
.modal.modal--full .modal-header,
.modal.modal--full .modal-footer { flex-shrink: 0; }
.modal.modal--full .modal-header { padding-top: max(.9rem, env(safe-area-inset-top)); }
.modal.modal--full .modal-footer { padding-bottom: max(.75rem, env(safe-area-inset-bottom)); }
.modal.modal--full .modal-body { flex: 1 1 auto; min-height: 0; scrollbar-gutter: stable; }
/* A full-screen sheet slides rather than scaling — a card zoom reads wrong at
   viewport size. */
.modal.modal--full.fade .modal-dialog { transform: translateY(2%); }
.modal.modal--full.show .modal-dialog { transform: none; }
@media (prefers-reduced-motion: reduce) {
    .modal.modal--full.fade .modal-dialog { transform: none; }
}

:root {
    --f-ok:  #1e3a5f;
    --f-req: #a4262c;
    --fld-lbl-w: 5.4rem;
    --f-top: color-mix(in srgb, var(--bs-emphasis-color) 62%, transparent);
    --f-chev: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 7'%3E%3Cpath d='M1.2 1.6 5 5.2 8.8 1.6' fill='none' stroke='%23495057' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
html[data-theme="dark"] {
    --f-ok:  #7ea3d1;
    --f-req: #e0797e;
    --f-chev: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 7'%3E%3Cpath d='M1.2 1.6 5 5.2 8.8 1.6' fill='none' stroke='%23adb5bd' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

.input-group,
.form-control,
.form-select { --fi: var(--f, var(--f-ok)); }
.input-group:has([required]),
.input-group.is-required-parent,
.form-control[required],
.form-control.is-required-parent,
.form-select[required],
.form-select.is-required-parent { --f: var(--f-req); }

.input-group {
    flex-wrap: nowrap;
    overflow: hidden;
    background-color: var(--bs-body-bg);
    border: 1px solid var(--bs-border-color);
    border-top: 1px solid var(--f-top);
    border-left: 3px solid var(--fi);
    border-radius: 0;
    box-shadow: none;
    transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out;
}
.input-group:hover {
    border-color: var(--border-strong);
    border-top-color: var(--f-top);
    border-left-color: var(--fi);
}
.input-group:focus-within {
    border-color: var(--fi);
    border-top-color: var(--f-top);
    box-shadow: 0 0 0 .2rem color-mix(in srgb, var(--f, var(--f-ok)) 22%, transparent);
}
.input-group > * { margin-left: 0; }

.input-group > .form-control,
.input-group > .form-select {
    min-width: 0;
    border: 0;
    background-color: transparent;
    color: var(--text);
    box-shadow: none;
}
.input-group > .form-control:focus,
.input-group > .form-select:focus { border-color: transparent; box-shadow: none; }
.input-group > .form-control::placeholder { color: var(--bs-secondary-color); opacity: 1; }

.input-group-text {
    border: 0;
    border-right: 1px solid var(--bs-border-color);
    border-radius: 0;
    background-color: var(--bs-tertiary-bg);
    background-image: none;
    color: var(--bs-secondary-color);
    text-shadow: none;
    box-shadow: none;
    transition: color .15s ease-in-out, background-color .15s ease-in-out;
}
.input-group-text.pf-lbl {
    width: max(25%, var(--fld-lbl-w));
    flex: 0 0 max(25%, var(--fld-lbl-w));
    justify-content: center;
    text-align: center;
    padding: .1rem .35rem;
    font-size: .7rem;
    font-weight: 600;
    line-height: 1.3;
    white-space: nowrap;
    overflow: hidden;
}
.input-group:focus-within > .input-group-text {
    background-color: color-mix(in srgb, var(--f, var(--f-ok)) 10%, var(--bs-tertiary-bg));
    color: var(--fi);
}
.input-group-text.pf-lbl b {
    color: var(--f-req);
    font-weight: 700;
    font-size: .8em;
    margin-left: .16rem;
    vertical-align: super;
    line-height: 0;
}
.input-group > .input-group-text:last-child {
    border-right: 0;
    border-left: 1px solid var(--bs-border-color);
}

/* Every textual field group uses the same sharp premium shell. Page rules may
   change density, but not return the field to the older flat/neutral face. */
.input-group:has(> .input-group-text.pf-lbl) {
    border: 1px solid color-mix(in srgb, var(--fi) 22%, var(--bs-border-color));
    border-top-color: color-mix(in srgb, var(--bs-emphasis-color) 45%, transparent);
    border-radius: 2px;
    background: linear-gradient(180deg,
        color-mix(in srgb, var(--bs-body-bg) 96%, var(--bs-tertiary-bg)),
        var(--bs-body-bg));
    box-shadow:
        0 3px 8px color-mix(in srgb, var(--bs-emphasis-color) 7%, transparent),
        inset 0 1px 0 color-mix(in srgb, var(--bs-body-bg) 88%, transparent);
}
.input-group:has(> .input-group-text.pf-lbl):hover {
    border-color: color-mix(in srgb, var(--fi) 44%, var(--border-strong));
    border-top-color: color-mix(in srgb, var(--bs-emphasis-color) 55%, transparent);
    box-shadow: 0 4px 10px color-mix(in srgb, var(--bs-emphasis-color) 9%, transparent);
}
.input-group:has(> .input-group-text.pf-lbl):focus-within {
    border-color: color-mix(in srgb, var(--fi) 82%, var(--border-strong));
    border-top-color: color-mix(in srgb, var(--bs-emphasis-color) 58%, transparent);
    box-shadow:
        0 0 0 .2rem color-mix(in srgb, var(--fi) 16%, transparent),
        0 5px 12px color-mix(in srgb, var(--bs-emphasis-color) 10%, transparent);
}
.input-group:has(> .input-group-text.pf-lbl) > .input-group-text.pf-lbl {
    background: color-mix(in srgb, var(--fi) 72%, #000);
    color: #fff;
    font-size: .66rem;
    font-weight: 800;
    letter-spacing: .045em;
    text-transform: uppercase;
}
.input-group:has(> .input-group-text.pf-lbl):focus-within > .input-group-text.pf-lbl {
    background: color-mix(in srgb, var(--fi) 82%, #000);
    color: #fff;
}
.input-group:has(> .input-group-text.pf-lbl) > .input-group-text.pf-lbl b {
    color: #fff;
    opacity: .82;
}

.form-select {
    -webkit-appearance: none;
    appearance: none;
    background-image: var(--f-chev);
    cursor: pointer;
}
.form-select,
.ss-page .form-select,
.modal .form-select,
.pcard .form-select,
table.premium-table .form-select-sm,
.pcard .trg__sel.form-select {
    background-repeat: no-repeat;
    background-position: right .45rem center;
    background-size: 10px 7px;
    padding-right: 1.5rem !important;
    padding-left: .35rem;
    font-weight: 600;
}
.form-select:hover,
.input-group:hover > .form-select {
    background-image: var(--f-chev);
}
.form-select option,
.form-select optgroup { background-color: var(--bs-body-bg); color: var(--bs-body-color); }
.form-select optgroup { font-weight: 600; }

/* Reference: designs/dropdowns.png. A select group is one composed control: a
   solid semantic label block, a quiet value surface and a single clean caret. */
.input-group:has(> .form-select) {
    border-radius: 2px;
    box-shadow: 0 3px 7px color-mix(in srgb, var(--bs-emphasis-color) 9%, transparent);
}
.input-group:has(> .form-select):hover {
    box-shadow: 0 4px 9px color-mix(in srgb, var(--bs-emphasis-color) 12%, transparent);
}
.input-group:has(> .form-select):focus-within {
    box-shadow:
        0 0 0 .2rem color-mix(in srgb, var(--f, var(--f-ok)) 18%, transparent),
        0 4px 10px color-mix(in srgb, var(--bs-emphasis-color) 12%, transparent);
}
.input-group:has(> .form-select) > .input-group-text.pf-lbl {
    border-right: 0;
    padding: .06rem .26rem;
    background: color-mix(in srgb, var(--fi) 72%, #000);
    color: #fff;
    font-weight: 700;
    letter-spacing: .035em;
    text-transform: uppercase;
}
.input-group:has(> .form-select):focus-within > .input-group-text.pf-lbl {
    background: color-mix(in srgb, var(--fi) 82%, #000);
    color: #fff;
}
.input-group:has(> .form-select) > .input-group-text.pf-lbl b {
    color: #fff;
    opacity: .82;
}

/* One rhythm for every dropdown in a Bootstrap grid: four to a desktop row,
   two to a mobile row, whatever column classes the page happened to ask for. */
.row > [class*="col"]:has(> .form-select),
.row > [class*="col"]:has(> .input-group > .form-select) {
    flex: 0 0 auto;
    width: 50%;
    min-width: 0;
}
@media (min-width: 992px) {
    .row > [class*="col"]:has(> .form-select),
    .row > [class*="col"]:has(> .input-group > .form-select) { width: 25%; }
}

.input-group > .form-control[type=file]::file-selector-button {
    border: 0;
    border-right: 1px solid var(--bs-border-color);
    border-radius: 0;
    background-color: var(--bs-tertiary-bg);
    color: var(--bs-secondary-color);
    font-size: .7rem;
    font-weight: 600;
    transition: background-color .15s ease-in-out, color .15s ease-in-out;
}
.input-group > .form-control[type=file]:hover::file-selector-button {
    background-color: var(--bs-secondary-bg);
    color: var(--bs-body-color);
}

.input-group > .btn {
    flex: 0 0 auto;
    border: 0;
    border-left: 1px solid var(--bs-border-color);
    border-radius: 0;
    box-shadow: none;
}

.form-control,
.form-select {
    border-radius: 2px;
    border: 1px solid var(--bs-border-color);
    border-top: 1px solid var(--f-top);
    border-left: 3px solid var(--fi);
    background-color: var(--bs-body-bg);
    color: var(--text);
    box-shadow: none;
}
.form-control:not(.input-group > .form-control) {
    box-shadow: 0 3px 7px color-mix(in srgb, var(--bs-emphasis-color) 7%, transparent);
}
.form-select {
    border-radius: 2px;
    box-shadow: 0 3px 7px color-mix(in srgb, var(--bs-emphasis-color) 9%, transparent);
}
.form-control:hover,
.form-select:hover {
    border-color: var(--border-strong);
    border-top-color: var(--f-top);
    border-left-color: var(--fi);
}
.form-select:hover {
    box-shadow: 0 4px 9px color-mix(in srgb, var(--bs-emphasis-color) 12%, transparent);
}
.form-control:focus,
.form-select:focus {
    border-color: var(--fi);
    border-top-color: var(--f-top);
    box-shadow: 0 0 0 .2rem color-mix(in srgb, var(--f, var(--f-ok)) 22%, transparent);
}
.input-group > .form-control,
.input-group > .form-select { border-width: 0; }

.form-control:disabled,
.form-select:disabled {
    background-color: var(--bs-secondary-bg);
    color: var(--bs-secondary-color);
    box-shadow: none;
    cursor: default;
}
.form-control:disabled { background-image: none; }
.form-select:disabled {
    background-image: var(--f-chev);
    cursor: not-allowed;
    opacity: .72;
}
.form-select[multiple],
.form-select[size]:not([size="1"]) {
    padding-right: .45rem !important;
    background-image: none;
}
.input-group:has(:disabled) {
    box-shadow: none;
    border-left-color: var(--bs-border-color);
}
.input-group:has(:disabled) > .input-group-text {
    background-color: var(--bs-secondary-bg);
    color: var(--bs-secondary-color);
}
.input-group:has(> .form-select:disabled) > .input-group-text.pf-lbl {
    background: var(--bs-secondary-bg);
    color: var(--bs-secondary-color);
}
.input-group:has(:disabled):has(> .input-group-text.pf-lbl) > .input-group-text.pf-lbl {
    background: var(--bs-secondary-bg);
    color: var(--bs-secondary-color);
}
.input-group > .form-control:disabled,
.input-group > .form-select:disabled { box-shadow: none; }
.form-control[readonly] { caret-color: transparent; cursor: default; }

.form-check-input {
    border-radius: 0;
    border: 1px solid var(--border-strong);
    background-color: var(--bs-body-bg);
    box-shadow: none;
}
.form-check-input:checked { background-color: var(--f-ok); border-color: var(--f-ok); box-shadow: none; }
.form-check-input:focus {
    border-color: var(--f-ok);
    box-shadow: 0 0 0 .2rem color-mix(in srgb, var(--f-ok) 22%, transparent);
}
.form-switch .form-check-input:checked { box-shadow: none; }

html[data-design] .input-group:not(:has(> .form-select)):not(:has(> .input-group-text.pf-lbl)),
html[data-design] .input-group-text { border-radius: 0; }
html[data-design] .form-control,
html[data-design] .form-select,
html[data-design] .input-group:has(> .form-select),
html[data-design] .input-group:has(> .input-group-text.pf-lbl) { border-radius: 2px; }

html[data-design="classic"] .input-group:not(:has(> .form-select)):not(:has(> .input-group-text.pf-lbl)),
html[data-design="classic"] .input-group-text { border-radius: 0 !important; }
html[data-design="classic"] .form-control,
html[data-design="classic"] .form-select,
html[data-design="classic"] .input-group:has(> .form-select),
html[data-design="classic"] .input-group:has(> .input-group-text.pf-lbl) { border-radius: 2px !important; }
html[data-design="classic"] .form-control,
html[data-design="classic"] .form-select,
html[data-design="classic"] .input-group { border-left: 3px solid var(--fi); border-top-color: var(--f-top); }
html[data-design="classic"] .input-group:has(> .form-select) { border-left-width: 1px; }
html[data-design="classic"] .input-group { box-shadow: none; }
html[data-design="classic"] .input-group > .form-control,
html[data-design="classic"] .input-group > .form-select { border-width: 0; box-shadow: none; }
html[data-design="classic"] .input-group-text { background-color: var(--bs-tertiary-bg); }
html[data-design="classic"] .input-group > .input-group-text { border-width: 0 1px 0 0; }
html[data-design="classic"] .input-group > .input-group-text:last-child { border-width: 0 0 0 1px; }

.input-group-text.pf-ico {
    min-width: 26px;
    justify-content: center;
    color: var(--fi);
    border-color: transparent;
}

@media (prefers-reduced-motion: reduce) {
    .input-group, .input-group-text, .form-control, .form-select { transition: none; }
}

.fee-fields { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: .4rem .42rem; }
.fee-fields > * { min-width: 0; }
.fee-fields .fee-wide { grid-column: 1 / -1; }
@media (max-width: 767.98px) { .fee-fields { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .25rem .25rem; } }

@media (max-width: 575.98px) {
    :root { --fld-lbl-w: 3.4rem; }
    .fee-fields { gap: .2rem .2rem; }
    .input-group-text.pf-lbl {
        padding: .06rem .14rem;
        font-size: .56rem;
        font-weight: 600;
        line-height: 1.05;
        white-space: normal;
        word-break: break-word;
    }
    .input-group > .form-control,
    .input-group > .form-select,
    .form-control,
    .form-select {
        font-size: .78rem;
        padding: .16rem .3rem;
        min-height: 28px;
    }
    .form-select,
    .ss-page .form-select,
    .modal .form-select,
    .pcard .form-select,
    table.premium-table .form-select-sm,
    .pcard .trg__sel.form-select {
        padding-right: 1.35rem !important;
        padding-left: .24rem;
        background-position: right .38rem center;
    }
    .input-group > .form-control[type=file]::file-selector-button { padding: .16rem .3rem; font-size: .58rem; }
    .input-group > .btn { padding: .16rem .35rem; font-size: .7rem; }
    .app-content { padding: .3rem .3rem !important; }
    .pd-panel { padding: .35rem .35rem; }
    .pcard__head, .pcard__foot { padding: .35rem .4rem; }
    .pcard__body { padding: .4rem .4rem; }
    .pd-head { padding-bottom: .25rem; }
    .modal-body { padding: .5rem .45rem; }
    .table-card { margin-left: -.1rem; margin-right: -.1rem; }
}

/* ============================================================
   STUDENTS → ADD (#stuForm, #fatherModal) — moved out of the view 2026-08-05.
   Page-scoped CSS lives here, not inline: BandwidthFilter meters the PHP body and never
   meters public/assets, so 18 KB inline was charged to the school on every load.
   ============================================================ */
#stuForm {
    --stu-h: 40px;
    --fld-lbl-w: 5.2rem;
    --stu-shell-radius: 2px;
    --stu-field-radius: 2px;
    max-width: 1560px;
    margin-inline: auto;
}
#stuForm form { display: flex; flex-direction: column; gap: .85rem; }
#stuForm, #fatherModal { --radius: 0; }
#stuForm .pd-card,
#stuForm .btn,
#stuForm .btn-premium,
#fatherModal .modal-content,
#fatherModal .btn,
#fatherModal .btn-premium,
#fatherModal .table-card { border-radius: 0; }
#stuForm ::selection { background: var(--accent-soft); color: var(--accent-dark); }
#stuForm .pd-panel { position: relative; overflow: hidden; }
#stuForm .stu-sheet {
    isolation: isolate;
    padding: 1.25rem;
    border: 1px solid color-mix(in srgb, var(--f-ok) 23%, var(--border));
    border-radius: var(--stu-shell-radius);
    background:
        radial-gradient(circle at 8% 0%, color-mix(in srgb, var(--f-ok) 10%, transparent), transparent 25rem),
        radial-gradient(circle at 96% 100%, color-mix(in srgb, var(--f-req) 6%, transparent), transparent 24rem),
        linear-gradient(145deg, color-mix(in srgb, var(--card-bg) 94%, var(--surface-2)), var(--card-bg));
    box-shadow:
        0 24px 55px color-mix(in srgb, var(--bs-emphasis-color) 11%, transparent),
        0 4px 14px color-mix(in srgb, var(--bs-emphasis-color) 7%, transparent),
        inset 0 1px 0 color-mix(in srgb, var(--bs-body-bg) 82%, transparent);
}
#stuForm .stu-sheet::before {
    content: "";
    position: absolute;
    z-index: -1;
    inset: 0 12% auto;
    height: 4px;
    border-radius: 0;
    background: linear-gradient(90deg, transparent, var(--f-ok) 20% 78%, var(--f-req) 92%, transparent);
    box-shadow: 0 5px 20px color-mix(in srgb, var(--f-ok) 22%, transparent);
}
#stuForm .stu-alert {
    border: 1px solid color-mix(in srgb, var(--danger) 34%, var(--border));
    border-left: 3px solid var(--danger);
    border-radius: var(--radius);
    background: color-mix(in srgb, var(--danger) 7%, var(--card-bg));
    color: color-mix(in srgb, var(--danger) 72%, var(--text));
    font-size: .78rem; padding: .42rem .7rem; margin-bottom: .5rem;
    box-shadow: var(--shadow-1);
}
#stuForm .stu-note { font-size: .72rem; color: var(--muted); margin: .5rem 0 0; }
#stuForm .stu-note--warn { color: var(--text-2); }
#stuForm .stu-fields {
    position: relative;
    z-index: 1;
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: .25rem;
}
#stuForm .stu-field { min-width: 0; }
#stuForm .stu-field > .input-group,
#stuForm .stu-docrow .input-group {
    min-height: var(--stu-h);
    overflow: hidden;
    border: 1px solid color-mix(in srgb, var(--fi) 22%, var(--bs-border-color));
    border-left: 4px solid var(--fi);
    border-top-color: color-mix(in srgb, var(--bs-emphasis-color) 45%, transparent);
    border-radius: var(--stu-field-radius);
    background:
        linear-gradient(180deg, color-mix(in srgb, var(--bs-body-bg) 95%, var(--surface-2)), var(--bs-body-bg));
    box-shadow:
        0 8px 18px color-mix(in srgb, var(--bs-emphasis-color) 7%, transparent),
        0 2px 5px color-mix(in srgb, var(--bs-emphasis-color) 6%, transparent),
        inset 0 1px 0 color-mix(in srgb, var(--bs-body-bg) 88%, transparent);
    transition: border-color .18s ease, box-shadow .18s ease, transform .18s ease, background-color .18s ease;
}
#stuForm .stu-field > .input-group:has(> .form-select) { border-left-width: 1px; }
#stuForm .stu-field > .input-group:hover,
#stuForm .stu-docrow .input-group:hover {
    border-color: color-mix(in srgb, var(--fi) 48%, var(--border-strong));
    border-left-color: var(--fi);
    border-top-color: color-mix(in srgb, var(--bs-emphasis-color) 58%, transparent);
    background: color-mix(in srgb, var(--fi) 2.5%, var(--bs-body-bg));
    box-shadow:
        0 13px 26px color-mix(in srgb, var(--bs-emphasis-color) 10%, transparent),
        0 3px 7px color-mix(in srgb, var(--bs-emphasis-color) 7%, transparent);
    transform: translateY(-2px);
}
#stuForm .stu-field > .input-group:focus-within,
#stuForm .stu-docrow .input-group:focus-within {
    border-color: color-mix(in srgb, var(--fi) 85%, var(--border-strong));
    border-left-color: var(--fi);
    border-top-color: color-mix(in srgb, var(--bs-emphasis-color) 58%, transparent);
    background: color-mix(in srgb, var(--fi) 3.5%, var(--bs-body-bg));
    box-shadow:
        0 0 0 .24rem color-mix(in srgb, var(--fi) 16%, transparent),
        0 16px 30px color-mix(in srgb, var(--bs-emphasis-color) 12%, transparent);
    transform: translateY(-2px);
}
#stuForm .input-group > .form-control,
#stuForm .input-group > .form-select {
    min-height: var(--stu-h);
    padding: .18rem .38rem;
    font-size: .78rem;
    font-weight: 560;
}
#stuForm .input-group > .form-select { padding: .18rem 1.5rem .18rem .38rem; }
#stuForm .input-group-text.pf-lbl { padding: .12rem .22rem; }
#stuForm .input-group > .form-control[type=file] { padding: .1rem .32rem; font-size: .68rem; }
#stuForm .form-control[type=file]::file-selector-button { padding: .18rem .34rem; margin: -.1rem .34rem -.1rem -.32rem; }
#stuForm .stu-prefix {
    min-width: 2.7rem; justify-content: center;
    padding: .12rem .22rem;
    border: 0; border-right: 1px solid var(--bs-border-color); border-radius: 0;
    background-color: var(--bs-tertiary-bg);
    color: var(--bs-body-color);
    font-weight: 600; font-size: .74rem; font-variant-numeric: tabular-nums;
}
#stuForm .stu-mini {
    flex: 0 0 auto; padding: 0 .38rem;
    border: 0; border-left: 1px solid var(--bs-border-color); border-radius: 0;
    background-color: var(--bs-tertiary-bg);
    color: var(--bs-body-color);
    font-size: .66rem; font-weight: 500;
    transition: background-color .18s ease, color .18s ease;
}
#stuForm .stu-mini:hover { background-color: var(--bs-secondary-bg); color: var(--fi); }
#stuForm .stu-mini:active { background-color: var(--fi); color: #fff; }
#stuForm .stu-thumb {
    flex: 0 0 auto; width: 32px; padding: 0; overflow: hidden;
    border: 0; border-left: 1px solid var(--border); border-radius: 0;
    background-image: none; background-color: var(--surface-3); box-shadow: none; justify-content: center;
}
#stuForm .stu-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
#stuForm .stu-pct__val {
    border: 0; background: transparent; box-shadow: none;
    font-weight: 800; font-size: .79rem; font-variant-numeric: tabular-nums;
    color: var(--muted);
    transition: color .18s ease;
}
#stuForm .stu-pct.is-good { border-color: var(--fi); background: color-mix(in srgb, var(--f-ok) 9%, var(--card-bg)); }
#stuForm .stu-pct.is-good .pf-lbl { background-color: color-mix(in srgb, var(--f-ok) 14%, var(--bs-tertiary-bg)); color: var(--fi); }
#stuForm .stu-pct.is-good .stu-pct__val { color: var(--fi); }
#stuForm .stu-pct.is-bad { border-color: var(--danger); background: color-mix(in srgb, var(--danger) 8%, var(--card-bg)); }
#stuForm .stu-pct.is-bad .pf-lbl { background-color: color-mix(in srgb, var(--danger) 14%, var(--bs-tertiary-bg)); color: var(--danger); }
#stuForm .stu-pct.is-bad .stu-pct__val { color: var(--danger); }
#stuForm .stu-docwrap, #stuForm .stu-addwrap { grid-column: 1 / -1; }
#stuForm .stu-docrow { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) auto; gap: .42rem; margin-bottom: .4rem; }
#stuForm .stu-docrow:last-child { margin-bottom: 0; }
#stuForm .stu-docrow__rm {
    display: flex; align-items: center; justify-content: center;
    width: 2rem; padding: 0; font-size: 1rem; line-height: 1;
    border: 1px solid var(--border); border-radius: var(--radius);
    background: var(--surface); color: var(--muted);
    transition: color .18s ease, border-color .18s ease, background .18s ease;
}
#stuForm .stu-docrow__rm:hover {
    color: var(--danger); border-color: var(--danger);
    background: color-mix(in srgb, var(--danger) 7%, var(--card-bg));
}
#stuForm .stu-addwrap { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; }
#stuForm .stu-adddoc {
    border: 1px dashed var(--border-strong); background: transparent; color: var(--text-2);
    font-size: .68rem; font-weight: 700; letter-spacing: .01em; padding: .22rem .6rem;
    transition: color .18s ease, border-color .18s ease, background .18s ease;
}
#stuForm .stu-adddoc::before { content: "+"; margin-right: .35rem; font-weight: 800; }
#stuForm .stu-adddoc:hover:not(:disabled) {
    color: var(--f-ok);
    border-color: var(--f-ok);
    background: color-mix(in srgb, var(--f-ok) 9%, var(--surface-2));
}
#stuForm .stu-adddoc:disabled { border-style: solid; opacity: .5; }
#stuForm .stu-adddoc:disabled::before { content: ""; margin: 0; }
#stuForm .stu-cap { font-size: .68rem; color: var(--muted); letter-spacing: .01em; }
#stuForm .stu-doclist { display: flex; flex-direction: column; gap: .3rem; margin-top: .5rem; }
#stuForm .stu-doc {
    display: flex; align-items: center; gap: .6rem; padding: .32rem .5rem;
    border: 1px solid var(--border); border-left: 2px solid var(--f-ok);
    border-radius: var(--radius); background: var(--surface-2);
    transition: border-color .18s ease, background .18s ease, box-shadow .18s ease;
}
#stuForm .stu-doc:hover {
    border-color: var(--border-strong);
    border-left-color: var(--f-ok);
    background: var(--surface); box-shadow: var(--shadow-1);
}
#stuForm .stu-doc__ext {
    flex-shrink: 0; min-width: 2.8rem; text-align: center; padding: .18rem .35rem;
    border-radius: var(--radius);
    background: color-mix(in srgb, var(--f-ok) 12%, var(--surface-3));
    color: var(--f-ok);
    font-size: .6rem; font-weight: 800; letter-spacing: .07em;
}
#stuForm .stu-doc__meta { display: flex; flex-direction: column; min-width: 0; flex: 1 1 auto; }
#stuForm .stu-doc__name { font-weight: 700; font-size: .8rem; color: var(--text); text-decoration: none; }
#stuForm .stu-doc__name:hover { text-decoration: underline; color: var(--f-ok); }
#stuForm .stu-doc__sub { font-size: .68rem; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#stuForm .stu-doc__rm { display: flex; align-items: center; gap: .35rem; font-size: .7rem; color: var(--muted); cursor: pointer; flex-shrink: 0; }
#stuForm .stu-doc__rm:hover { color: var(--danger); }
#stuForm .stu-bar {
    position: sticky; bottom: 0; z-index: 5;
    display: flex; align-items: center; justify-content: space-between; gap: 1rem;
    padding: .52rem .55rem .52rem .8rem;
    background: color-mix(in srgb, var(--card-bg) 86%, transparent);
    -webkit-backdrop-filter: saturate(180%) blur(12px);
    backdrop-filter: saturate(180%) blur(12px);
    border: 1px solid var(--border);
    border-left: 3px solid var(--f-ok); border-bottom: 2px solid var(--f-ok);
    border-radius: var(--radius);
    box-shadow: var(--shadow-3);
}
#stuForm .stu-bar__hint { font-size: .72rem; color: var(--muted); letter-spacing: .005em; }
#stuForm .stu-bar__hint b { color: var(--danger); }
#stuForm .stu-bar__hint .stu-id { color: var(--f-ok); font-variant-numeric: tabular-nums; }
#stuForm .stu-bar__act { display: flex; gap: .45rem; flex-shrink: 0; }
#stuForm .stu-bar__act .btn { font-size: .76rem; padding: .34rem .95rem; }
@supports not (background: color-mix(in srgb, red 50%, blue)) {
    #stuForm .stu-bar { background: var(--card-bg); }
}
@media (max-width: 991px) {
    #stuForm .stu-fields { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 767px) {
    #stuForm { --stu-h: 36px; --fld-lbl-w: 3.4rem; --stu-shell-radius: 2px; --stu-field-radius: 2px; }
    #stuForm .stu-sheet { padding: .42rem; }
    #stuForm .stu-fields { grid-template-columns: 1fr; gap: .18rem; }
    #stuForm .input-group > .form-control,
    #stuForm .input-group > .form-select { padding-top: .08rem; padding-bottom: .08rem; padding-left: .2rem; font-size: .68rem; }
    #stuForm .input-group-text.pf-lbl { padding: .04rem .1rem; font-size: .54rem; letter-spacing: .025em; }
    #stuForm .stu-prefix { min-width: 1.9rem; padding: .06rem .1rem; font-size: .6rem; }
    #stuForm .stu-mini { padding-inline: .2rem; font-size: .56rem; }
    #stuForm .input-group > .form-control[type=file] { padding: .06rem .18rem; font-size: .58rem; }
    #stuForm .form-control[type=file]::file-selector-button { padding: .12rem .2rem; margin: -.06rem .2rem -.06rem -.18rem; }
    #stuForm .stu-field > .input-group:hover,
    #stuForm .stu-docrow .input-group:hover { transform: none; }
    #stuForm .stu-field > .input-group:focus-within,
    #stuForm .stu-docrow .input-group:focus-within { transform: none; }
    #stuForm .stu-docrow { grid-template-columns: 1fr; }
    #stuForm .stu-docrow__rm { width: 100%; height: 34px; }
    #stuForm .stu-bar { flex-direction: column; align-items: stretch; gap: .5rem; }
    #stuForm .stu-bar__act .btn { flex: 1 1 0; }
    #stuForm .stu-bar__hint { order: 2; text-align: center; }
}
@media (prefers-reduced-motion: reduce) {
    #stuForm .stu-field > .input-group, #stuForm .stu-docrow .input-group,
    #stuForm .stu-doc,
    #stuForm .stu-mini, #stuForm .stu-adddoc, #stuForm .stu-docrow__rm { transition: none; }
}
#fatherModal { --fld-lbl-w: 4.5rem; }
.fm-pair{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.45rem;}
.fm-trio{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:.45rem;}
.fm-docrow{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr) auto;gap:.45rem;margin-bottom:.4rem;}
.fm-docrow:last-child{margin-bottom:0;}
#fatherModal .input-group > .form-control { min-height: 32px; padding: .3rem .55rem; font-size: .79rem; }
#fatherModal .input-group-text.pf-lbl { padding: .3rem .3rem; }
#fatherModal .input-group > .form-control[type=file] { padding: .22rem .5rem; font-size: .72rem; }
#fatherModal .form-control[type=file]::file-selector-button { padding: .3rem .55rem; margin: -.22rem .55rem -.22rem -.5rem; }
#fatherModal .fm-docrow__rm{
    display:flex;align-items:center;justify-content:center;width:2rem;padding:0;
    font-size:1rem;line-height:1;border:1px solid var(--border);border-radius:var(--radius);
    background:var(--surface);color:var(--muted);
    transition:color .18s ease,border-color .18s ease,background .18s ease;
}
#fatherModal .fm-docrow__rm:hover{color:var(--danger);border-color:var(--danger);
    background:color-mix(in srgb,var(--danger) 7%,var(--card-bg));}
#fatherModal .modal-section-title{
    display:flex;align-items:center;gap:.6rem;margin:1rem 0 .5rem;
    font-size:.63rem;font-weight:800;text-transform:uppercase;letter-spacing:.1em;color:var(--muted);
}
#fatherModal .modal-section-title::before{content:"";width:14px;height:2px;flex:0 0 auto;
    background:var(--f-ok);}
#fatherModal .modal-section-title::after{content:"";flex:1 1 auto;height:1px;background:var(--border);}
#fatherModal .modal-section-title.mt-0{margin-top:0;}
.fm-sub{display:flex;align-items:baseline;gap:.5rem;flex-wrap:wrap;margin:.7rem 0 .4rem;
    font-size:.66rem;font-weight:700;text-transform:uppercase;letter-spacing:.07em;color:var(--text-2);}
.fm-cap{font-size:.66rem;font-weight:400;text-transform:none;letter-spacing:0;color:var(--muted);}
.fm-act{display:flex;justify-content:flex-end;align-items:center;gap:.5rem;margin-top:.6rem;}
.fm-adddoc{margin-right:auto;border:1px dashed var(--border-strong);background:transparent;
    color:var(--text-2);font-size:.68rem;font-weight:700;padding:.22rem .6rem;
    transition:color .18s ease,border-color .18s ease,background .18s ease;}
.fm-adddoc::before{content:"+";margin-right:.35rem;font-weight:800;}
.fm-adddoc:hover:not(:disabled){color:var(--f-ok);
    border-color:var(--f-ok);background:color-mix(in srgb,var(--f-ok) 9%,var(--surface-2));}
.fm-adddoc:disabled{border-style:solid;opacity:.5;}
.fm-adddoc:disabled::before{content:"";margin:0;}
.fm-kids{max-width:16rem;font-size:.74rem;color:var(--text-2);}
#fatherModal .premium-table th{font-size:.6rem;text-transform:uppercase;letter-spacing:.08em;}
#fatherModal .premium-table td{font-size:.78rem;vertical-align:middle;}
@media (max-width:767px){ .fm-trio{grid-template-columns:1fr;} }
@media (max-width:575px){
    .fm-pair{grid-template-columns:1fr;gap:.4rem;}
    .fm-docrow{grid-template-columns:1fr;}
    #fatherModal .fm-docrow__rm{width:100%;height:34px;}
    .fm-act{flex-direction:column-reverse;align-items:stretch;}
    .fm-adddoc{margin-right:0;}
    .fm-act .btn{width:100%;}
}
@media (prefers-reduced-motion: reduce){
    #fatherModal .fm-docrow__rm,.fm-adddoc{transition:none;}
}

.fee-sheet {
    font-size: .8rem;
    border-collapse: collapse;
    --bs-table-bg: transparent;
    --bs-table-hover-bg: transparent;
    --bs-table-striped-bg: transparent;
}
.fee-sheet > :not(caption) > * > * {
    padding: .16rem .3rem;
    border: 1px solid var(--bs-border-color);
    background-color: transparent;
    box-shadow: none;
    color: var(--bs-body-color);
}
.fee-sheet thead th {
    background-color: var(--bs-tertiary-bg);
    font-weight: 600;
    font-size: .72rem;
    white-space: nowrap;
}
.fee-sheet th,
.fee-sheet td { text-align: center; }
.fee-sheet tbody tr,
.fee-sheet tbody tr:hover { background-color: transparent; }
.fee-sheet .num { font-variant-numeric: tabular-nums; white-space: nowrap; }
.fee-sheet td.trunc {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 0;
}
.fee-sheet td:has(> .form-control) { padding: 0; }
.fee-sheet td > .form-control {
    width: 100%;
    max-width: none;
    min-height: 0;
    border: 0;
    border-radius: 0;
    background-color: transparent;
    box-shadow: none;
    outline: 0;
    padding: .16rem .3rem;
    font-size: inherit;
    font-family: inherit;
    line-height: inherit;
    color: inherit;
    font-variant-numeric: tabular-nums;
    transition: none;
    -moz-appearance: textfield;
    appearance: textfield;
}
.fee-sheet td > .form-control::-webkit-outer-spin-button,
.fee-sheet td > .form-control::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.fee-sheet td > .form-control:focus { outline: 2px solid var(--bs-body-color); outline-offset: -2px; }
.fee-sheet .form-check-input { margin: 0; vertical-align: middle; float: none; box-shadow: none; }
.fee-sheet .form-check-input:focus { box-shadow: none; outline: 2px solid var(--bs-body-color); outline-offset: 1px; }
.fee-sheet th.sel,
.fee-sheet td.sel { width: 2rem; padding-left: .2rem; padding-right: .2rem; }
.fee-sheet .icon-btn {
    width: 22px;
    height: 22px;
    border-radius: 0;
    box-shadow: none;
}
.fee-sheet .actions-row { display: inline-flex; gap: .2rem; justify-content: center; }
.fee-sheet .pd-tag { border-radius: 0; }

.fee-tabs .btn {
    --bs-btn-border-radius: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .4rem;
    padding: .48rem .6rem;
    font-size: .82rem;
    font-weight: 600;
    letter-spacing: .01em;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .16), 0 1px 2px rgba(0, 0, 0, .08);
}
.fee-tabs .btn:focus { box-shadow: inset 0 1px 0 rgba(255, 255, 255, .16), 0 0 0 .2rem rgba(var(--bs-btn-focus-shadow-rgb), .4); }
.fee-tabs .btn.active { box-shadow: inset 0 2px 4px rgba(0, 0, 0, .22); }
.fee-tabs .btn .badge {
    border-radius: 0;
    padding: .2rem .38rem;
    font-size: .72rem;
    font-weight: 700;
    color: inherit;
    background-color: color-mix(in srgb, currentColor 16%, transparent);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, currentColor 30%, transparent);
}
.fee-tabs .btn.active .badge {
    background-color: rgba(255, 255, 255, .22);
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .35);
}
.fee-tabs .btn i { font-size: .95rem; line-height: 1; }

@media (max-width: 767.98px) {
    .fee-sheet { font-size: .74rem; }
    .fee-sheet > :not(caption) > * > * { padding: .1rem .2rem; }
    .fee-sheet thead th { font-size: .68rem; }
    .fee-sheet td > .form-control { padding: .1rem .2rem; }
}

/* ============================================================
   TABLES — the field system's data companion.
   Sharp shell, solid semantic header, compact grid and the same restrained depth.
   ============================================================ */
:is(
    .app-content table.table,
    table.premium-table,
    table.fee-sheet,
    .pcard table.table
) {
    --ti: var(--c, var(--f-ok));
    width: 100%;
    margin-bottom: 0;
    border-collapse: collapse;
    border: 1px solid color-mix(in srgb, var(--ti) 28%, var(--bs-border-color));
    border-top-color: color-mix(in srgb, var(--bs-emphasis-color) 48%, transparent);
    border-radius: 0;
    background: var(--bs-body-bg);
    color: var(--bs-body-color);
    box-shadow: 0 3px 8px color-mix(in srgb, var(--bs-emphasis-color) 7%, transparent);
}

:is(
    .app-content table.table,
    table.premium-table,
    table.fee-sheet,
    .pcard table.table
) > thead > tr > th {
    padding: .08rem .18rem;
    border: 1px solid color-mix(in srgb, var(--ti) 82%, #000) !important;
    background: color-mix(in srgb, var(--ti) 72%, #000) !important;
    color: #fff !important;
    font-size: .64rem;
    font-weight: 800;
    line-height: 1.25;
    letter-spacing: .045em;
    text-transform: uppercase;
    white-space: nowrap;
    vertical-align: middle;
}

:is(
    .app-content table.table,
    table.premium-table,
    table.fee-sheet,
    .pcard table.table
) > tbody > tr > td {
    padding: .08rem .18rem;
    border: 1px solid var(--bs-border-color) !important;
    background-color: var(--bs-body-bg);
    color: var(--bs-body-color);
    font-size: .78rem;
    line-height: 1.28;
    vertical-align: middle;
}

:is(
    .app-content table.table,
    table.premium-table,
    table.fee-sheet,
    .pcard table.table
) > tbody > tr:nth-child(even) > td {
    background-color: color-mix(in srgb, var(--ti) 2.5%, var(--bs-body-bg));
}

:is(
    .app-content table.table,
    table.premium-table,
    table.fee-sheet,
    .pcard table.table
) > tbody > tr:hover > td {
    background-color: color-mix(in srgb, var(--ti) 7%, var(--bs-body-bg));
}

:is(.table-card, .table-responsive):has(> table.table),
:is(.table-card, .table-responsive):has(> table.premium-table),
:is(.table-card, .table-responsive):has(> table.fee-sheet) {
    --ti: var(--c, var(--f-ok));
    overflow: auto;
    border: 1px solid color-mix(in srgb, var(--ti) 24%, var(--border));
    border-left: 4px solid var(--ti);
    border-radius: 2px !important;
    background: var(--card-bg);
    box-shadow:
        0 3px 8px color-mix(in srgb, var(--bs-emphasis-color) 7%, transparent),
        inset 0 1px 0 color-mix(in srgb, var(--bs-body-bg) 88%, transparent);
}

:is(
    .app-content table.table,
    table.premium-table,
    table.fee-sheet,
    .pcard table.table
) thead .sort-icon {
    color: #fff;
}

:is(
    .app-content table.table,
    table.premium-table,
    table.fee-sheet,
    .pcard table.table
) > tbody > tr:hover {
    box-shadow: inset 3px 0 0 var(--ti);
}

@media (max-width: 575.98px) {
    :is(
        .app-content table.table,
        table.premium-table,
        table.fee-sheet,
        .pcard table.table
    ) > thead > tr > th,
    :is(
        .app-content table.table,
        table.premium-table,
        table.fee-sheet,
        .pcard table.table
    ) > tbody > tr > td {
        padding: .05rem .1rem;
    }
}

/* ============================================================
   CARDS — shared shell matching fields and tables.
   ============================================================ */
:is(
    .app-content .card,
    .pd-card,
    .pcard,
    .toolbar-card,
    .table-card,
    .sa-card,
    .stat-card,
    .kpi-card,
    .kpi-tile,
    .mini-tile,
    .recent,
    .quick__item,
    .cs-card,
    .empty-state,
    .pd-empty,
    .list-count
) {
    --ci: var(--c, var(--stat-color, var(--accent, var(--f-ok))));
    border: 1px solid color-mix(in srgb, var(--ci) 22%, var(--border));
    border-top-color: color-mix(in srgb, var(--bs-emphasis-color) 45%, transparent);
    border-left: 4px solid var(--ci);
    border-radius: 2px !important;
    background-color: var(--card-bg);
    box-shadow:
        0 3px 8px color-mix(in srgb, var(--bs-emphasis-color) 7%, transparent),
        inset 0 1px 0 color-mix(in srgb, var(--bs-body-bg) 88%, transparent);
}

:is(
    .app-content .card,
    .pd-card,
    .pcard,
    .toolbar-card,
    .table-card,
    .sa-card,
    .stat-card,
    .kpi-card,
    .kpi-tile,
    .mini-tile,
    .recent,
    .quick__item,
    .cs-card,
    .empty-state,
    .pd-empty,
    .list-count
):hover {
    border-color: color-mix(in srgb, var(--ci) 38%, var(--border-strong));
    border-top-color: color-mix(in srgb, var(--bs-emphasis-color) 55%, transparent);
    border-left-color: var(--ci);
    transform: none !important;
    box-shadow:
        0 4px 10px color-mix(in srgb, var(--bs-emphasis-color) 9%, transparent),
        inset 0 1px 0 color-mix(in srgb, var(--bs-body-bg) 88%, transparent);
}

:is(.pd-card:not(.stu-sheet), .stat-card, .sa-card, .kpi-tile)::before,
:is(.pd-card:not(.stu-sheet), .stat-card, .sa-card, .kpi-tile)::after {
    display: none !important;
}

:is(.pd-head, .pcard__head, .app-content .card-header) {
    border-bottom: 1px solid color-mix(in srgb, var(--ci, var(--c, var(--accent))) 22%, var(--border));
    border-radius: 0 !important;
    background: color-mix(in srgb, var(--ci, var(--c, var(--accent))) 6%, var(--card-bg));
}

:is(.pcard__foot, .app-content .card-footer) {
    border-top: 1px solid var(--border);
    border-radius: 0 !important;
    background: color-mix(in srgb, var(--ci, var(--c, var(--accent))) 3%, var(--card-bg));
}

.pd-panel { padding: .4rem .5rem; }
.pd-head { margin-bottom: .35rem; padding: .12rem .2rem .28rem; }
.toolbar-card { padding: .4rem .5rem; }
.pcard__head, .pcard__body, .pcard__foot { padding-left: .5rem; padding-right: .5rem; }

/* ============================================================
   UI COHERENCE — every remaining component follows the same
   sharp, semantic and restrained language. Functional circles
   (radio buttons, charts and spinners) intentionally stay round.
   ============================================================ */
:is(
    .btn,
    .btn-sm,
    .btn-premium,
    .btn-soft,
    .submenu-btn,
    .act-btn,
    .icon-btn,
    .pager-btn,
    .pager-per,
    .tt-btn,
    .pd-cta,
    .check-chip,
    .topbar-toggle,
    .sidebar-close,
    .mobile-nav-btn,
    .nav-link,
    .nav-parent,
    .page-link
) {
    border-radius: 2px !important;
    transform: none !important;
}

:is(
    .btn,
    .btn-premium,
    .btn-soft,
    .submenu-btn,
    .act-btn,
    .icon-btn,
    .pager-btn,
    .tt-btn,
    .pd-cta,
    .page-link
):hover,
:is(
    .btn,
    .btn-premium,
    .btn-soft,
    .submenu-btn,
    .act-btn,
    .icon-btn,
    .pager-btn,
    .tt-btn,
    .pd-cta,
    .page-link
):active {
    transform: none !important;
    filter: none;
}

.btn-premium {
    border: 1px solid color-mix(in srgb, var(--accent) 82%, #000) !important;
    background: color-mix(in srgb, var(--accent) 72%, #000) !important;
    color: #fff !important;
    box-shadow:
        0 2px 5px color-mix(in srgb, var(--accent) 22%, transparent),
        inset 0 1px 0 color-mix(in srgb, #fff 18%, transparent) !important;
}
.btn-premium:hover,
.btn-premium:focus-visible {
    border-color: color-mix(in srgb, var(--accent) 92%, #000) !important;
    background: color-mix(in srgb, var(--accent) 82%, #000) !important;
}
.btn-soft {
    border: 1px solid color-mix(in srgb, var(--accent) 24%, var(--border)) !important;
    background: color-mix(in srgb, var(--accent) 7%, var(--surface-2)) !important;
    box-shadow: none !important;
}

:is(
    .pd-chip,
    .pd-ico,
    .pcard__ico,
    .stat-icon,
    .kpi-ico,
    .kpi-tile__ico,
    .mini-tile__ico,
    .cs-icon,
    .trg__ico,
    .alert-bubble__ico,
    .app-toast__ico,
    .avatar-circle,
    .pd-ava,
    .brand-mark,
    .nav-icon-chip
) {
    border-radius: 2px !important;
}

:is(.pd-chip, .pd-ico, .pcard__ico, .stat-icon, .kpi-ico, .kpi-tile__ico, .mini-tile__ico, .cs-icon, .trg__ico) {
    --ui: var(--c, var(--stat-color, var(--accent)));
    border: 1px solid color-mix(in srgb, var(--ui) 82%, #000);
    background: color-mix(in srgb, var(--ui) 72%, #000) !important;
    color: #fff !important;
    box-shadow:
        0 2px 5px color-mix(in srgb, var(--ui) 22%, transparent),
        inset 0 1px 0 color-mix(in srgb, #fff 18%, transparent) !important;
}

:is(.badge, .badge-status, .pd-badge, .pd-tag, .pd-count, .att-chip, .list-count) {
    border-radius: 2px !important;
    box-shadow: none !important;
}

:is(.modal-content, .dropdown-menu, .popover, .offcanvas, .cmdk, .app-toast, .alert-bubble, .alert) {
    --ui: var(--c, var(--accent));
    border: 1px solid color-mix(in srgb, var(--ui) 24%, var(--border));
    border-left: 4px solid var(--ui);
    border-radius: 2px !important;
    background-color: var(--card-bg);
    box-shadow:
        0 6px 18px color-mix(in srgb, var(--bs-emphasis-color) 13%, transparent),
        inset 0 1px 0 color-mix(in srgb, var(--bs-body-bg) 88%, transparent);
}
.alert-danger, .app-toast.is-error { --ui: var(--danger); }
.alert-success, .app-toast.is-success { --ui: var(--success); }
.alert-warning, .app-toast.is-warning { --ui: #d97706; }
.alert-info { --ui: #0369a1; }

.modal-content::before,
.dropdown-menu::before,
.cmdk::before { display: none !important; }

:is(.modal-header, .modal-footer, .dropdown-header, .cmdk-input-wrap, .cmdk-foot) {
    border-radius: 0 !important;
    background: color-mix(in srgb, var(--ui, var(--accent)) 5%, var(--card-bg));
}
.modal-header { border-bottom: 1px solid color-mix(in srgb, var(--ui, var(--accent)) 22%, var(--border)); }
.modal-footer { border-top: 1px solid var(--border); }

.dropdown-item {
    border-radius: 0 !important;
    padding: .32rem .5rem;
}
.dropdown-item:hover,
.dropdown-item:focus { background: color-mix(in srgb, var(--accent) 8%, var(--surface-2)); }
.dropdown-item.active,
.dropdown-item:active {
    background: color-mix(in srgb, var(--accent) 72%, #000);
    color: #fff;
}

:is(.nav-tabs, .nav-pills, .fee-tabs) { gap: .16rem; }
:is(.nav-tabs .nav-link, .nav-pills .nav-link, .fee-tabs .btn) {
    border-radius: 2px !important;
    box-shadow: none !important;
}
:is(.nav-tabs .nav-link.active, .nav-pills .nav-link.active, .fee-tabs .btn.active) {
    border-color: color-mix(in srgb, var(--accent) 82%, #000) !important;
    background: color-mix(in srgb, var(--accent) 72%, #000) !important;
    color: #fff !important;
}

:is(.pagination, .pager, .list-group, .accordion) { border-radius: 2px !important; }
:is(.list-group-item, .accordion-item, .accordion-button) { border-radius: 0 !important; }
.accordion-button:not(.collapsed) {
    background: color-mix(in srgb, var(--accent) 7%, var(--surface-2));
    color: var(--text);
    box-shadow: inset 4px 0 0 var(--accent);
}

.form-check-input:not([type="radio"]),
.form-switch .form-check-input {
    border-radius: 2px !important;
}
.form-check-input[type="radio"] { border-radius: 50% !important; }
:is(.progress, .progress-bar) { border-radius: 0 !important; }

:is(.tooltip-inner, .popover-header, .popover-body) { border-radius: 2px !important; }
.toast-container, .toast-stack { gap: .3rem; }

/* ============================================================
   MODALS — compact executive surfaces. The semantic rail and
   title marker make hierarchy obvious without decorative bulk.
   ============================================================ */
.modal-backdrop {
    background: color-mix(in srgb, #020617 88%, var(--accent));
}
.modal-backdrop.show {
    opacity: .68;
    backdrop-filter: blur(3px);
}
.modal-dialog {
    margin-top: .75rem;
    margin-bottom: .75rem;
}
.modal-content {
    position: relative;
    overflow: hidden;
    border-top: 1px solid color-mix(in srgb, var(--ui, var(--accent)) 44%, var(--border)) !important;
    box-shadow:
        0 24px 70px color-mix(in srgb, #020617 34%, transparent),
        0 7px 18px color-mix(in srgb, var(--ui, var(--accent)) 16%, transparent),
        inset 0 1px 0 color-mix(in srgb, #fff 16%, transparent) !important;
}
.modal-content::after {
    content: '';
    position: absolute;
    z-index: 2;
    inset: 0 0 auto 0;
    height: 2px;
    background: var(--ui, var(--accent));
    pointer-events: none;
}
.modal-header {
    min-height: 3.15rem;
    padding: .56rem .7rem .52rem .78rem;
    gap: .65rem;
}
.modal-header > :first-child { min-width: 0; }
.modal-title {
    display: flex;
    align-items: center;
    gap: .45rem;
    margin: 0;
    color: var(--text);
    font-size: .94rem;
    font-weight: 800;
    letter-spacing: -.012em;
    line-height: 1.2;
}
.modal-title::before {
    content: '';
    flex: 0 0 .46rem;
    width: .46rem;
    height: 1.08rem;
    border: 1px solid color-mix(in srgb, var(--ui, var(--accent)) 82%, #000);
    border-radius: 1px;
    background: color-mix(in srgb, var(--ui, var(--accent)) 72%, #000);
    box-shadow: 0 2px 4px color-mix(in srgb, var(--ui, var(--accent)) 22%, transparent);
}
.modal-subtitle {
    display: block;
    margin: .12rem 0 0 .93rem;
    color: var(--muted);
    font-size: .68rem;
    font-weight: 550;
    line-height: 1.3;
}
.modal-header .btn-close {
    flex: 0 0 1.72rem;
    width: 1.72rem;
    height: 1.72rem;
    margin: 0 0 0 auto;
    padding: 0;
    border: 1px solid color-mix(in srgb, var(--ui, var(--accent)) 22%, var(--border));
    border-radius: 2px !important;
    background-color: color-mix(in srgb, var(--ui, var(--accent)) 5%, var(--surface-2));
    background-size: .62rem;
    opacity: .72;
    box-shadow: none;
}
.modal-header .btn-close:hover,
.modal-header .btn-close:focus-visible {
    border-color: color-mix(in srgb, var(--ui, var(--accent)) 55%, var(--border));
    background-color: color-mix(in srgb, var(--ui, var(--accent)) 11%, var(--surface-2));
    opacity: 1;
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--ui, var(--accent)) 15%, transparent);
}
.modal-body {
    padding: .62rem .72rem;
    background: color-mix(in srgb, var(--ui, var(--accent)) 2.5%, var(--card-bg));
}
.modal-footer {
    min-height: 2.85rem;
    padding: .42rem .7rem;
    gap: .35rem;
}
.modal-footer .btn {
    min-height: 1.88rem;
    padding: .26rem .68rem;
    font-size: .72rem;
    font-weight: 750;
}
.modal-body > :last-child { margin-bottom: 0 !important; }
.modal-body .mb-3 { margin-bottom: .55rem !important; }
.modal-body .mb-2 { margin-bottom: .38rem !important; }

@media (max-width: 575.98px) {
    .modal-dialog { margin: .42rem; }
    .modal-header { padding: .48rem .55rem .45rem .62rem; }
    .modal-body { padding: .52rem .56rem; }
    .modal-footer { padding: .38rem .54rem; }
}

/* ============================================================
   FEES / EXCEL MODALS — one dense worksheet language for every
   modal owned by Allocate, Invoices, Fine Settings and OTF.
   ============================================================ */
:is(.fee-modal, .fee-sheet) {
    --ui: #217346 !important;
    --xl-green: #217346;
    --xl-green-dark: #185c37;
    --xl-sheet: #f7faf8;
    --xl-cell: #ffffff;
    --xl-head: #e2f0d9;
    --xl-grid: #aebfb4;
    --xl-grid-soft: #d6e0da;
    --xl-ink: #17251c;
    --xl-muted: #52665a;
}
.fee-modal .modal-dialog.fee-modal-dialog-top {
    width: calc(100% - 1rem);
    max-width: 1140px !important;
    margin: .55rem auto;
    align-items: flex-start !important;
}
html[data-theme="dark"] :is(.fee-modal, .fee-sheet) {
    --xl-green: #217346;
    --xl-green-dark: #174f31;
    --xl-sheet: #111814;
    --xl-cell: #18211b;
    --xl-head: #21372a;
    --xl-grid: #486052;
    --xl-grid-soft: #2e4035;
    --xl-ink: #e4eee7;
    --xl-muted: #a9bbae;
}
.fee-modal .modal-content {
    border: 1px solid var(--xl-green-dark) !important;
    border-left-width: 1px !important;
    border-top-color: var(--xl-green-dark) !important;
    border-radius: 0 !important;
    background: var(--xl-sheet) !important;
    box-shadow: 0 18px 42px color-mix(in srgb, #07130c 38%, transparent) !important;
}
.fee-modal .modal-content::after { display: none !important; }
.fee-modal .modal-header {
    min-height: 2.8rem;
    padding: .42rem .5rem .4rem .58rem;
    border-bottom: 1px solid var(--xl-green-dark) !important;
    background: var(--xl-green) !important;
}
.fee-modal .modal-title {
    gap: .38rem;
    color: #fff !important;
    font-size: .86rem;
    font-weight: 750;
    letter-spacing: 0;
}
.fee-modal .modal-title::before {
    content: '▦';
    display: grid;
    place-items: center;
    flex: 0 0 1.28rem;
    width: 1.28rem;
    height: 1.28rem;
    border: 1px solid rgba(255,255,255,.9);
    border-radius: 0;
    background: #fff;
    color: var(--xl-green);
    font-size: .91rem;
    line-height: 1;
    box-shadow: none;
}
.fee-modal .modal-title i { color: #fff !important; }
.fee-modal .modal-header .modal-subtitle {
    margin: .08rem 0 0 1.66rem;
    color: rgba(255,255,255,.78) !important;
    font-size: .62rem;
}
.fee-modal .modal-header .btn-close {
    width: 1.55rem;
    height: 1.55rem;
    flex-basis: 1.55rem;
    border: 1px solid rgba(255,255,255,.55);
    border-radius: 0 !important;
    background-color: transparent;
    filter: invert(1) grayscale(1) brightness(2);
    opacity: .88;
}
.fee-modal .modal-header .btn-close:hover,
.fee-modal .modal-header .btn-close:focus-visible {
    border-color: #fff;
    background-color: rgba(255,255,255,.14);
    box-shadow: 0 0 0 2px rgba(255,255,255,.22);
    opacity: 1;
}
.fee-modal .modal-body {
    padding: .48rem;
    background-color: var(--xl-sheet) !important;
    color: var(--xl-ink);
}
.fee-modal .modal-footer {
    min-height: 2.55rem;
    padding: .32rem .45rem;
    gap: .24rem;
    border-top: 1px solid var(--xl-green) !important;
    background: var(--xl-head) !important;
}
.fee-modal .modal-footer .modal-subtitle { color: var(--xl-muted) !important; }
.fee-modal .modal-footer .btn {
    min-height: 1.72rem;
    padding: .2rem .52rem;
    border-radius: 0 !important;
    font-size: .67rem;
    box-shadow: none !important;
}
.fee-modal .modal-footer .btn-premium {
    border-color: var(--xl-green-dark) !important;
    background: var(--xl-green) !important;
    color: #fff !important;
}
.fee-modal .modal-footer .btn-premium:hover,
.fee-modal .modal-footer .btn-premium:focus-visible { background: var(--xl-green-dark) !important; }
.fee-modal .modal-footer .btn-soft,
.fee-modal .modal-footer .btn-secondary {
    border-color: var(--xl-grid) !important;
    background: var(--xl-cell) !important;
    color: var(--xl-ink) !important;
}
.fee-modal .modal-footer .btn-soft:hover,
.fee-modal .modal-footer .btn-secondary:hover { background: var(--xl-head) !important; }
.fee-modal .modal-footer .btn-soft.text-danger {
    border-color: color-mix(in srgb, var(--danger) 38%, var(--xl-grid)) !important;
    color: var(--danger) !important;
}

.fee-modal :is(
    .in-student-action-hero, .in-detail-hero, .in-otf-student, .in-fine-student,
    .in-forgive-summary, .in-pay-hero, .in-pay-after, .in-edit-all-head,
    .in-item-edit-intro, .in-edit-line, .in-item-edit-row
) {
    border-color: var(--xl-grid) !important;
    border-radius: 0 !important;
    background: var(--xl-cell) !important;
    box-shadow: none !important;
}
.fee-modal :is(.in-student-action-icon, .in-detail-icon, .in-pay-hero-icon, .in-edit-all-icon) {
    border-color: var(--xl-green-dark) !important;
    border-radius: 0 !important;
    background: var(--xl-green) !important;
    box-shadow: none !important;
}
.fee-modal :is(
    .in-student-action-totals, .in-detail-totals, .in-detail-info,
    .in-otf-totals, .in-fine-totals, .in-pay-totals, .in-pay-modes,
    .in-fine-breakdown, .in-otf-breakdown
) {
    border-color: var(--xl-grid) !important;
    border-radius: 0 !important;
    background: var(--xl-cell) !important;
}
.fee-modal :is(
    .in-student-action-total, .in-detail-total, .in-detail-info > div,
    .in-otf-total, .in-fine-total, .in-pay-total
) { border-color: var(--xl-grid-soft) !important; }
.fee-modal :is(.in-pay-mode, .in-forgive-mode) {
    border-radius: 0 !important;
    box-shadow: none !important;
}
.fee-modal :is(.in-pay-mode.is-on, .in-forgive-mode.is-on) {
    border-color: var(--xl-green-dark) !important;
    background: var(--xl-green) !important;
    color: #fff !important;
}
.fee-modal :is(.in-student-action-row, .in-edit-line, .in-item-edit-row) {
    border-top-color: var(--xl-grid) !important;
    border-right-color: var(--xl-grid) !important;
    border-bottom-color: var(--xl-grid) !important;
}
:is(.fee-modal, .fee-sheet) table { border-collapse: collapse; background: var(--xl-cell); color: var(--xl-ink); }
:is(.fee-modal, .fee-sheet) table > :not(caption) > * > * {
    padding: .22rem .3rem !important;
    border: 1px solid var(--xl-grid-soft) !important;
    background-color: var(--xl-cell);
    color: var(--xl-ink);
}
:is(.fee-modal, .fee-sheet) table thead th {
    border-color: var(--xl-grid) !important;
    background: var(--xl-head) !important;
    color: var(--xl-ink) !important;
    font-size: .59rem !important;
    font-weight: 750;
    letter-spacing: .025em;
}
:is(.fee-modal, .fee-sheet) .table-responsive { border-radius: 0 !important; }
:is(.fee-modal, .fee-sheet) .fee-excel-table {
    width: 100%;
    margin: 0;
    table-layout: fixed;
    border: 1px solid var(--xl-grid) !important;
    font-size: .68rem;
}
:is(.fee-modal, .fee-sheet) .fee-excel-table tr,
:is(.fee-modal, .fee-sheet) .fee-excel-table .in-edit-line,
:is(.fee-modal, .fee-sheet) .fee-excel-table .in-item-edit-row { display: table-row !important; }
:is(.fee-modal, .fee-sheet) .fee-excel-table th,
:is(.fee-modal, .fee-sheet) .fee-excel-table td { display: table-cell !important; }
:is(.fee-modal, .fee-sheet) .fee-excel-table th {
    height: 1.58rem;
    padding: .18rem .28rem !important;
    vertical-align: middle;
    text-align: left;
    white-space: nowrap;
}
:is(.fee-modal, .fee-sheet) .fee-excel-table td {
    height: 1.78rem;
    padding: 0 !important;
    vertical-align: middle;
}
:is(.fee-modal, .fee-sheet) .fee-excel-table td:has(> :is(input, select, textarea)):focus-within {
    position: relative;
    z-index: 1;
    outline: 2px solid var(--xl-green);
    outline-offset: -2px;
}
/* Checkboxes and radios are excluded: this rule strips border, background and box-shadow to make
   a cell look like a bare spreadsheet field, which for a tick box removes the box itself. */
:is(.fee-modal, .fee-sheet) .fee-excel-table :is(input:not([type="hidden"]):not([type="checkbox"]):not([type="radio"]), select, textarea) {
    display: block;
    width: 100%;
    min-width: 0;
    min-height: 1.72rem;
    margin: 0;
    padding: .16rem .28rem;
    border: 0 !important;
    border-radius: 0 !important;
    outline: 0;
    background: transparent !important;
    color: var(--xl-ink) !important;
    font: inherit;
    box-shadow: none !important;
}
:is(.fee-modal, .fee-sheet) .fee-excel-table :is(input, select, textarea):disabled {
    background: color-mix(in srgb, var(--xl-grid-soft) 42%, var(--xl-cell)) !important;
    color: var(--xl-muted) !important;
}
:is(.fee-modal, .fee-sheet) .fee-date-seg {
    display: inline-flex;
    align-items: center;
    justify-content: flex-start;
    width: 100%;
    min-height: 1.72rem;
    padding: 0 .2rem;
    background: transparent;
    white-space: nowrap;
}
:is(.fee-modal, .fee-sheet) .fee-excel-table .fee-date-seg .fee-date-part {
    display: inline-block;
    flex: 0 0 auto;
    width: 1.55rem !important;
    min-height: 1.5rem;
    padding: .08rem .05rem !important;
    text-align: center;
    font-variant-numeric: tabular-nums;
}
:is(.fee-modal, .fee-sheet) .fee-excel-table .fee-date-seg .fee-date-y { width: 2.75rem !important; }
:is(.fee-modal, .fee-sheet) .fee-date-sep {
    flex: 0 0 auto;
    padding: 0 .02rem;
    color: var(--xl-muted);
    font-weight: 750;
}
:is(.fee-modal, .fee-sheet) .fee-excel-table td > strong { display: block; padding: .16rem .28rem; }
:is(.fee-modal, .fee-sheet) .fee-excel-table .in-edit-chip { padding: .16rem .28rem !important; text-align: left; }
:is(.fee-modal, .fee-sheet) .fee-excel-table .in-edit-paid { padding: 0 .28rem .12rem; }
:is(.fee-modal, .fee-sheet) .fee-excel-table .in-item-edit-empty { padding: .65rem !important; }
:is(.fee-modal, .fee-sheet) .fee-excel-form { min-width: 28rem; }
#inBulkEditModal .fee-excel-form { min-width: 46rem; }

@media (max-width: 575.98px) {
    .fee-modal { --modal-edge-space: 0px; padding: 0 !important; }
    .fee-modal .modal-dialog,
    .fee-modal .modal-dialog.fee-modal-dialog-top {
        width: 96% !important;
        max-width: 96% !important;
        margin: 0 auto !important;
    }
    .fee-modal .modal-content { width: 100% !important; }
    .fee-modal .modal-content { border-radius: 0 !important; }
    .fee-modal .modal-header { padding: .38rem .42rem .36rem .48rem; }
    .fee-modal .modal-body { padding: .3rem; }
    .fee-modal .modal-footer {
        flex-wrap: nowrap !important;
        gap: .16rem;
        padding: .3rem .26rem max(.3rem, env(safe-area-inset-bottom));
    }
    .fee-modal .modal-footer > .modal-subtitle { display: none !important; }
    .fee-modal .modal-footer .btn {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        flex: 1 1 0;
        min-width: 0 !important;
        margin: 0 !important;
        padding: .4rem .1rem !important;
        font-size: 0 !important;
        line-height: 1;
        white-space: nowrap;
        overflow: hidden;
    }
    .fee-modal .modal-footer .btn i {
        display: inline-block !important;
        margin: 0 !important;
        font-size: .88rem !important;
        line-height: 1;
    }
    :is(.fee-modal, .fee-sheet) .table-responsive { overflow-x: visible !important; }
    :is(.fee-modal, .fee-sheet) .fee-excel-table,
    :is(.fee-modal, .fee-sheet) .fee-excel-form,
    #inBulkEditModal .fee-excel-form {
        width: 100% !important;
        min-width: 0 !important;
        table-layout: fixed;
    }
    :is(.fee-modal, .fee-sheet) .fee-excel-table :is(th, td) {
        padding: .2rem .18rem !important;
        font-size: .56rem !important;
        line-height: 1.15;
        overflow-wrap: anywhere;
        word-break: break-word;
        white-space: normal !important;
    }
    :is(.fee-modal, .fee-sheet) .fee-excel-table :is(input:not([type="hidden"]):not([type="checkbox"]):not([type="radio"]), select, textarea) {
        width: 100% !important;
        min-width: 0 !important;
        padding: .14rem .18rem !important;
        font-size: .58rem !important;
    }
    :is(.fee-modal, .fee-sheet) .fee-date-seg { padding: 0; }
    :is(.fee-modal, .fee-sheet) .fee-excel-table .fee-date-seg .fee-date-part {
        width: 1.25rem !important;
        padding: .08rem .02rem !important;
        font-size: .56rem !important;
    }
    :is(.fee-modal, .fee-sheet) .fee-excel-table .fee-date-seg .fee-date-y { width: 1.95rem !important; }
    :is(.fee-modal, .fee-sheet) .fee-excel-table td > strong { padding: .16rem .1rem; }
    .fee-modal .in-invoice-status { display: block; margin: 0 !important; padding: .04rem .1rem; font-size: .5rem; text-align: center; }
}
