/* ------------------------------------------------------------------------------------------
   Admin design system.

   Plain (non-scoped) stylesheet on purpose: these classes are shared by many components, and
   Blazor scoped CSS cannot share a class across components without ::deep gymnastics.

   Everything is nested under .admin-shell / .ad-auth so the public site (PublicLayout and its
   --ln-* tokens) is untouched.

   THEMING — light is the default, dark is opt-in.

   Every colour in this file resolves through a token below, so a theme is a swap of this one
   block and nothing else. The light values are the dashboard's light palette (--dash-* in
   dashboard.css) under --ad-* names, and the dark values are this file's original palette,
   which mirrors PublicLayout.razor.css. Both halves of the product therefore agree in either
   theme rather than one shell being light while the other is dark.

   The dark block below is an override keyed on <html data-theme="dark">, which theme.js sets
   before first paint. No media query: the choice is the user's explicit one, and the documented
   default is light regardless of what the OS prefers.

   Colours here are measured, not picked by eye. In light, status text uses the -ink steps
   (#006300 / #85560a / #a12626) rather than the vivid marks, which fall under 3:1 on white;
   the accent is #256abf so it clears 4.5:1 both as link text on white and behind white button
   text. In dark, every mark clears 4.5:1 on --ad-elev. The one place a status colour is not
   self-sufficient is the amber family, which is why status always ships with a visible label.

   Visual reference: .ai/reference/initial-landing.png (dark)
   ------------------------------------------------------------------------------------------ */

/* .dash-shell is listed here because the sidebar is one component (AdminNavMenu) rendered in
   both shells — it needs its --ad-* tokens wherever it lands. dashboard.css defines --dash-* on
   the same element; the two sets never collide because they never share a name. */
.admin-shell,
.ad-auth,
.dash-shell {
    /* surfaces */
    --ad-bg: #f4f6f9;
    --ad-elev: #ffffff;
    --ad-panel: #ffffff;
    --ad-panel-soft: #f8fafc;
    --ad-border: #e6eaf0;
    --ad-border-soft: #eef1f5;

    /* ink */
    --ad-text: #0b0b0b;
    --ad-text-dim: #52514e;
    --ad-text-faint: #6e6d68;

    /* accent */
    --ad-accent: #256abf;
    --ad-accent-hover: #1f5aa6;
    --ad-accent-soft: #eaf2fc;
    --ad-accent-line: #b9d3f2;
    --ad-accent-glow: rgba(37, 106, 191, .07);
    /* Ink that sits ON an accent fill (buttons, brand mark), never on the page. */
    --ad-on-accent: #ffffff;

    /* status — mark, chip fill, chip border */
    --ad-green: #006300;
    --ad-green-soft: #e7f6e7;
    --ad-green-line: #b7e4b7;
    --ad-amber: #85560a;
    --ad-amber-soft: #fdf4de;
    --ad-amber-line: #f0d9a4;
    --ad-red: #a12626;
    --ad-red-soft: #fbeaea;
    --ad-red-line: #f2c2c2;

    /* chrome */
    /* Opaque, not translucent: the sidebar is a surface the content scrolls beside, and the
       shell's background grid must not show through it. */
    --ad-sidebar-bg: #ffffff;
    --ad-topbar-bg: rgba(255, 255, 255, .86);
    --ad-thead-bg: #f8fafc;
    --ad-row-hover: #f4f6f9;
    /* The faint engineering grid: dark ruling on light, light ruling on dark. */
    --ad-grid: rgba(11, 11, 11, .032);
    --ad-grid-soft: rgba(11, 11, 11, .024);

    /* single-hue heat scale, light -> dark */
    --ad-heat-1: #dbe9f9;
    --ad-heat-2: #a9caf0;
    --ad-heat-3: #5b93d9;
    --ad-heat-4: #256abf;

    --ad-sans: "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
    --ad-mono: ui-monospace, "Cascadia Mono", "Segoe UI Mono", "SF Mono", Menlo, Consolas, monospace;

    --ad-radius: 10px;
    --ad-radius-sm: 6px;
    /* The sidebar runs a slightly rounder radius than the rest of the shell — it is the
       dashboard's sidebar, and these two numbers are what make it read as one component in both
       shells rather than two that nearly agree. */
    --ad-nav-radius: 8px;
    --ad-sidebar-w: 240px;

    color-scheme: light;
}

[data-theme="dark"] :is(.admin-shell, .ad-auth, .dash-shell) {
    --ad-bg: #0f1216;
    --ad-elev: #171b21;
    --ad-panel: #1b1f26;
    --ad-panel-soft: #21262e;
    --ad-border: #272d36;
    --ad-border-soft: #1f242b;

    --ad-text: #e9ecf1;
    --ad-text-dim: #a3acb9;
    --ad-text-faint: #7d8590;

    --ad-accent: #4d9fff;
    --ad-accent-hover: #74b4ff;
    --ad-accent-soft: rgba(77, 159, 255, .14);
    --ad-accent-line: #33507a;
    --ad-accent-glow: rgba(77, 159, 255, .10);
    --ad-on-accent: #08101c;

    --ad-green: #4ade80;
    --ad-green-soft: rgba(74, 222, 128, .13);
    --ad-green-line: rgba(74, 222, 128, .28);
    --ad-amber: #fbbf24;
    --ad-amber-soft: rgba(251, 191, 36, .13);
    --ad-amber-line: rgba(251, 191, 36, .28);
    --ad-red: #f87171;
    --ad-red-soft: rgba(248, 113, 113, .13);
    --ad-red-line: rgba(248, 113, 113, .28);

    --ad-sidebar-bg: #171b21;
    --ad-topbar-bg: rgba(15, 18, 22, .82);
    --ad-thead-bg: rgba(33, 38, 46, .5);
    --ad-row-hover: rgba(33, 38, 46, .38);
    --ad-grid: rgba(255, 255, 255, .022);
    --ad-grid-soft: rgba(255, 255, 255, .018);

    --ad-heat-1: rgba(77, 159, 255, .28);
    --ad-heat-2: rgba(77, 159, 255, .48);
    --ad-heat-3: rgba(77, 159, 255, .68);
    --ad-heat-4: rgba(77, 159, 255, .90);

    color-scheme: dark;
}

/* ---------------------------------------------------------------- shell / layout ---------- */

.admin-shell {
    display: flex;
    min-height: 100vh;
    font-family: var(--ad-sans);
    color: var(--ad-text);
    background-color: var(--ad-bg);
    /* Faint engineering grid, matching the reference. */
    background-image:
        linear-gradient(to right, var(--ad-grid) 1px, transparent 1px),
        linear-gradient(to bottom, var(--ad-grid) 1px, transparent 1px);
    background-size: 44px 44px;
}

/* ---------------------------------------------------------------- sidebar ----------------- */

/* One sidebar, two shells. AdminNavMenu renders inside .admin-shell and inside .dash-shell
   alike, so everything below is written against --ad-* only — which .dash-shell also defines,
   per the token block at the top of this file.

   The treatment is the dashboard's, deliberately: ink stays black through every state and the
   active row is a raised, bordered surface rather than an accent wash. Accent appears in exactly
   two places in the whole sidebar — the brand badge and the active row's icon — so the menu
   reads as a list of places, not a list of links. */

.admin-sidebar {
    flex: 0 0 var(--ad-sidebar-w);
    width: var(--ad-sidebar-w);
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
    padding: 1.125rem .875rem;
    background-color: var(--ad-sidebar-bg);
    border-right: 1px solid var(--ad-border);
    position: sticky;
    top: 0;
    height: 100vh;
    overflow-y: auto;
}

.admin-brand {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .25rem .375rem;
    color: var(--ad-text);
    text-decoration: none;
    font-weight: 700;
    letter-spacing: -.01em;
}

.admin-brand:hover {
    color: var(--ad-text);
}

.admin-brand-mark {
    display: grid;
    place-items: center;
    width: 26px;
    height: 26px;
    flex: 0 0 26px;
    border-radius: 7px;
    /* Carries a letter, so it takes the flat text-safe accent step rather than a gradient. */
    background-color: var(--ad-accent);
    color: var(--ad-on-accent);
    font-size: .8125rem;
    font-weight: 700;
}

/* The IntelliSchool logomark when the badge carries the logo instead of an initial (root only).
   Global, not scoped: BrandMark renders the <svg>, so a rule in any .razor.css would be stamped
   with that component's scope and miss it. Everything is currentColor, which the badge above
   already set to --ad-on-accent. */
.admin-brand-glyph {
    width: 16px;
    height: 16px;
}

.admin-brand-text {
    display: flex;
    flex-direction: column;
    line-height: 1.2;
    min-width: 0;
}

.admin-brand-name {
    font-size: 1.0625rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.admin-brand-scope {
    font-size: .625rem;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--ad-text-faint);
    font-weight: 600;
}

.admin-nav {
    display: flex;
    flex-direction: column;
    gap: .125rem;
}

.admin-nav-heading {
    margin: .875rem .5rem .25rem;
    font-size: .6875rem;
    font-weight: 600;
    letter-spacing: .04em;
    color: var(--ad-text-faint);
}

/* First heading sits directly under the brand, so it does not need the group spacing above. */
.admin-nav-heading:first-child {
    margin-top: 0;
}

.admin-nav-link {
    display: flex;
    align-items: center;
    gap: .625rem;
    padding: .5rem .625rem;
    border-radius: var(--ad-nav-radius);
    color: var(--ad-text-dim);
    text-decoration: none;
    font-size: .875rem;
    font-weight: 500;
    border: 1px solid transparent;
    transition: background-color .12s ease, color .12s ease;
}

.admin-nav-link:hover {
    background-color: var(--ad-panel-soft);
    color: var(--ad-text);
}

.admin-nav-link.active {
    background-color: var(--ad-panel-soft);
    border-color: var(--ad-border);
    color: var(--ad-text);
    font-weight: 600;
}

.admin-nav-icon {
    flex: 0 0 17px;
    width: 17px;
    height: 17px;
    color: var(--ad-text-faint);
}

.admin-nav-link.active .admin-nav-icon {
    color: var(--ad-accent);
}

.admin-sidebar-foot {
    margin-top: auto;
    padding-top: 1rem;
    display: flex;
    flex-direction: column;
    gap: .5rem;
}

.admin-user {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .5rem;
    border-radius: var(--ad-nav-radius);
    border: 1px solid var(--ad-border);
    background-color: var(--ad-panel-soft);
    color: var(--ad-text);
    text-decoration: none;
    font-size: .8125rem;
    font-weight: 500;
    min-width: 0;
}

.admin-user span:last-child {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.admin-avatar {
    display: grid;
    place-items: center;
    width: 26px;
    height: 26px;
    flex: 0 0 26px;
    border-radius: 50%;
    background-color: var(--ad-accent-soft);
    font-size: .75rem;
    font-weight: 700;
    color: var(--ad-accent);
    text-transform: uppercase;
}

.admin-logout {
    display: block;
}

.admin-logout button {
    width: 100%;
    padding: .4375rem .625rem;
    border-radius: var(--ad-nav-radius);
    border: 1px solid var(--ad-border);
    background: none;
    color: var(--ad-text-dim);
    font: inherit;
    font-size: .8125rem;
    cursor: pointer;
}

.admin-logout button:hover {
    background-color: var(--ad-panel-soft);
    color: var(--ad-text);
}

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

.admin-topbar {
    position: sticky;
    top: 0;
    z-index: 20;
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: .875rem 1.75rem;
    border-bottom: 1px solid var(--ad-border);
    background-color: var(--ad-topbar-bg);
    backdrop-filter: blur(10px);
}

.admin-topbar-title {
    font-family: var(--ad-mono);
    font-size: .6875rem;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--ad-text-faint);
}

.admin-topbar-spacer {
    flex: 1 1 auto;
}

.admin-content {
    padding: 1.75rem;
    max-width: 1440px;
    width: 100%;
}

/* Mobile: the sidebar collapses to a horizontal strip above the content. */
.admin-nav-toggle {
    display: none;
}

@media (max-width: 900px) {
    /* Both shells stack here, because both wear the same sidebar. */
    .admin-shell,
    .dash-shell {
        flex-direction: column;
    }

    .admin-sidebar {
        flex: 0 0 auto;
        width: 100%;
        height: auto;
        position: static;
        padding: .875rem 1rem;
        gap: .875rem;
        border-right: 0;
        border-bottom: 1px solid var(--ad-border);
    }

    .admin-nav {
        flex-direction: row;
        flex-wrap: wrap;
        gap: .25rem;
    }

    /* Headings still separate the groups, but on their own full-width line — the links wrap
       beneath them instead of beside them. */
    .admin-nav-heading {
        width: 100%;
        margin: .5rem .5rem 0;
    }

    .admin-sidebar-foot {
        margin-top: .5rem;
        padding-top: 0;
        flex-direction: row;
        align-items: center;
        gap: .5rem;
    }

    .admin-user {
        flex: 1 1 auto;
    }

    .admin-logout {
        flex: 0 0 auto;
    }

    .admin-content {
        padding: 1.25rem 1rem;
    }

    .admin-topbar {
        padding: .75rem 1rem;
    }
}

/* ---------------------------------------------------------------- page furniture ---------- */

.ad-page-head {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    margin-bottom: 1.5rem;
}

.ad-page-title {
    margin: 0;
    font-size: 1.75rem;
    font-weight: 650;
    letter-spacing: -.025em;
    color: var(--ad-text);
}

.ad-page-sub {
    margin: .375rem 0 0;
    font-size: .875rem;
    color: var(--ad-text-dim);
}

.ad-eyebrow {
    font-family: var(--ad-mono);
    font-size: .625rem;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--ad-text-faint);
    margin-bottom: .375rem;
}

.ad-toolbar {
    display: flex;
    align-items: center;
    gap: .5rem;
    flex-wrap: wrap;
    margin-bottom: 1rem;
}

.ad-toolbar-spacer {
    flex: 1 1 auto;
}

/* ---------------------------------------------------------------- panels ------------------ */

.ad-panel {
    position: relative;
    background-color: var(--ad-panel);
    border: 1px solid var(--ad-border);
    border-radius: var(--ad-radius);
    padding: 1.125rem 1.25rem;
}

.ad-panel-head {
    display: flex;
    align-items: center;
    gap: .625rem;
    margin-bottom: 1rem;
}

.ad-panel-title {
    font-family: var(--ad-mono);
    font-size: .6875rem;
    font-weight: 600;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--ad-text-dim);
    margin: 0;
}

.ad-panel-meta {
    margin-left: auto;
    font-family: var(--ad-mono);
    font-size: .6875rem;
    letter-spacing: .06em;
    color: var(--ad-text-faint);
}

.ad-panel-body > :last-child {
    margin-bottom: 0;
}

/* Blue L-shaped bracket corners from the reference. Applied to a wrapper. */
.ad-bracketed {
    position: relative;
    padding: .75rem;
}

.ad-bracket {
    position: absolute;
    width: 1.5rem;
    height: 1.5rem;
    border: 2px solid var(--ad-accent-line);
    pointer-events: none;
}

.ad-bracket-tl {
    top: 0;
    left: 0;
    border-right: 0;
    border-bottom: 0;
}

.ad-bracket-tr {
    top: 0;
    right: 0;
    border-left: 0;
    border-bottom: 0;
}

.ad-bracket-bl {
    bottom: 0;
    left: 0;
    border-right: 0;
    border-top: 0;
}

.ad-bracket-br {
    bottom: 0;
    right: 0;
    border-left: 0;
    border-top: 0;
}

/* ---------------------------------------------------------------- grids ------------------- */

.ad-grid {
    display: grid;
    gap: 1rem;
}

.ad-grid-2 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
}

.ad-grid-3 {
    grid-template-columns: repeat(3, minmax(0, 1fr));
}

.ad-grid-4 {
    grid-template-columns: repeat(4, minmax(0, 1fr));
}

/* Auto-fitting card grid for tenants. */
.ad-card-grid {
    display: grid;
    gap: 1rem;
    grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
}

@media (max-width: 1200px) {
    .ad-grid-4 {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (max-width: 860px) {
    .ad-grid-2,
    .ad-grid-3,
    .ad-grid-4 {
        grid-template-columns: minmax(0, 1fr);
    }

    .ad-card-grid {
        grid-template-columns: minmax(0, 1fr);
    }
}

.ad-stack {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.ad-row {
    display: flex;
    align-items: center;
    gap: .5rem;
    flex-wrap: wrap;
}

/* ---------------------------------------------------------------- stat tiles -------------- */

.ad-stat {
    background-color: var(--ad-panel);
    border: 1px solid var(--ad-border);
    border-radius: var(--ad-radius);
    padding: 1rem 1.125rem;
    display: flex;
    flex-direction: column;
    gap: .375rem;
}

.ad-stat-label {
    font-family: var(--ad-mono);
    font-size: .625rem;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--ad-text-faint);
}

.ad-stat-value {
    font-size: 1.875rem;
    font-weight: 650;
    letter-spacing: -.03em;
    line-height: 1.1;
    color: var(--ad-text);
    font-variant-numeric: tabular-nums;
}

.ad-stat-hint {
    font-size: .75rem;
    color: var(--ad-text-dim);
}

.ad-stat-accent .ad-stat-value {
    color: var(--ad-accent);
}

.ad-stat-warn .ad-stat-value {
    color: var(--ad-amber);
}

.ad-stat-danger .ad-stat-value {
    color: var(--ad-red);
}

/* ---------------------------------------------------------------- badges ------------------ */

.ad-badge {
    display: inline-flex;
    align-items: center;
    gap: .375rem;
    padding: .1875rem .5rem;
    border-radius: 999px;
    border: 1px solid transparent;
    font-family: var(--ad-mono);
    font-size: .625rem;
    font-weight: 600;
    letter-spacing: .1em;
    text-transform: uppercase;
    white-space: nowrap;
}

.ad-badge::before {
    content: "";
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background-color: currentColor;
}

.ad-badge-plain::before {
    display: none;
}

.ad-badge-active {
    color: var(--ad-green);
    background-color: var(--ad-green-soft);
    border-color: var(--ad-green-line);
}

.ad-badge-pending {
    color: var(--ad-amber);
    background-color: var(--ad-amber-soft);
    border-color: var(--ad-amber-line);
}

.ad-badge-danger {
    color: var(--ad-red);
    background-color: var(--ad-red-soft);
    border-color: var(--ad-red-line);
}

.ad-badge-info {
    color: var(--ad-accent);
    background-color: var(--ad-accent-soft);
    border-color: var(--ad-accent-line);
}

.ad-badge-muted {
    color: var(--ad-text-faint);
    background-color: var(--ad-panel-soft);
    border-color: var(--ad-border);
}

/* Pulsing "live" dot, as on the reference status pill. */
.ad-badge-live::before {
    animation: ad-pulse 2s ease-in-out infinite;
}

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

/* ---------------------------------------------------------------- buttons ----------------- */

.ad-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .4375rem;
    padding: .5rem .875rem;
    border-radius: var(--ad-radius-sm);
    border: 1px solid var(--ad-border);
    background-color: var(--ad-panel-soft);
    color: var(--ad-text);
    font-family: var(--ad-sans);
    font-size: .8125rem;
    font-weight: 550;
    line-height: 1.2;
    text-decoration: none;
    cursor: pointer;
    transition: background-color .12s ease, border-color .12s ease, color .12s ease;
}

.ad-btn:hover {
    background-color: var(--ad-border);
    color: var(--ad-text);
}

.ad-btn:disabled,
.ad-btn[disabled] {
    opacity: .5;
    cursor: not-allowed;
}

.ad-btn-primary {
    background-color: var(--ad-accent);
    border-color: var(--ad-accent);
    color: var(--ad-on-accent);
    font-weight: 650;
}

.ad-btn-primary:hover {
    background-color: var(--ad-accent-hover);
    border-color: var(--ad-accent-hover);
    color: var(--ad-on-accent);
}

.ad-btn-ghost {
    background-color: transparent;
    color: var(--ad-text-dim);
}

.ad-btn-ghost:hover {
    background-color: var(--ad-panel-soft);
    color: var(--ad-text);
}

.ad-btn-success {
    background-color: var(--ad-green-soft);
    border-color: var(--ad-green-line);
    color: var(--ad-green);
}

.ad-btn-success:hover {
    background-color: var(--ad-green-line);
    color: var(--ad-green);
}

.ad-btn-danger {
    background-color: transparent;
    border-color: var(--ad-red-line);
    color: var(--ad-red);
}

.ad-btn-danger:hover {
    background-color: var(--ad-red-soft);
    color: var(--ad-red);
}

.ad-btn-sm {
    padding: .3125rem .625rem;
    font-size: .75rem;
}

.ad-btn-block {
    width: 100%;
}

.ad-link {
    color: var(--ad-accent);
    text-decoration: none;
}

.ad-link:hover {
    color: var(--ad-accent-hover);
    text-decoration: underline;
}

/* ---------------------------------------------------------------- tables / grids ---------- */

.ad-table-wrap {
    background-color: var(--ad-panel);
    border: 1px solid var(--ad-border);
    border-radius: var(--ad-radius);
    overflow-x: auto;
}

.ad-table {
    width: 100%;
    border-collapse: collapse;
    font-size: .875rem;
    color: var(--ad-text);
}

.ad-table thead th {
    text-align: left;
    padding: .75rem 1rem;
    font-family: var(--ad-mono);
    font-size: .625rem;
    font-weight: 600;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--ad-text-faint);
    background-color: var(--ad-thead-bg);
    border-bottom: 1px solid var(--ad-border);
    white-space: nowrap;
}

.ad-table tbody td {
    padding: .8125rem 1rem;
    border-bottom: 1px solid var(--ad-border-soft);
    vertical-align: middle;
}

.ad-table tbody tr:last-child td {
    border-bottom: 0;
}

.ad-table tbody tr:hover td {
    background-color: var(--ad-row-hover);
}

.ad-table td.ad-nowrap,
.ad-table th.ad-nowrap {
    white-space: nowrap;
}

.ad-table-actions {
    display: flex;
    gap: .375rem;
    justify-content: flex-end;
}

.ad-cell-primary {
    font-weight: 550;
    color: var(--ad-text);
}

.ad-cell-sub {
    display: block;
    font-size: .75rem;
    color: var(--ad-text-faint);
    margin-top: .125rem;
}

.ad-mono {
    font-family: var(--ad-mono);
    font-size: .8125rem;
    color: var(--ad-text-dim);
}

/* Inside a filled button the mono count sits on the accent, not on the page, where --ad-text-dim
   lands at 1.5:1 (light) and 1.2:1 (dark) — a count nobody can read. Take the button's own ink.
   On ghost buttons the dim step is correct and stays. */
.ad-btn-primary .ad-mono {
    color: inherit;
}

.ad-identity {
    display: flex;
    align-items: center;
    gap: .625rem;
}

/* ---------------------------------------------------------------- tenant cards ------------ */

.ad-card {
    display: flex;
    flex-direction: column;
    gap: .875rem;
    background-color: var(--ad-panel);
    border: 1px solid var(--ad-border);
    border-radius: var(--ad-radius);
    padding: 1.125rem;
    transition: border-color .12s ease, transform .12s ease;
}

.ad-card:hover {
    border-color: var(--ad-accent-line);
}

.ad-card-head {
    display: flex;
    align-items: flex-start;
    gap: .75rem;
}

.ad-card-mark {
    display: grid;
    place-items: center;
    width: 38px;
    height: 38px;
    flex: 0 0 38px;
    border-radius: 9px;
    background-color: var(--ad-accent-soft);
    border: 1px solid var(--ad-accent-line);
    color: var(--ad-accent);
    font-family: var(--ad-mono);
    font-size: .875rem;
    font-weight: 700;
    text-transform: uppercase;
}

.ad-card-heading {
    min-width: 0;
    flex: 1 1 auto;
}

.ad-card-title {
    margin: 0;
    font-size: 1rem;
    font-weight: 600;
    letter-spacing: -.01em;
    color: var(--ad-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ad-card-sub {
    margin: .125rem 0 0;
    font-family: var(--ad-mono);
    font-size: .75rem;
    color: var(--ad-text-faint);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ad-card-facts {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: .625rem .875rem;
    padding: .75rem 0;
    border-top: 1px solid var(--ad-border-soft);
    border-bottom: 1px solid var(--ad-border-soft);
}

.ad-fact-label {
    font-family: var(--ad-mono);
    font-size: .5625rem;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--ad-text-faint);
    margin-bottom: .1875rem;
}

.ad-fact-value {
    font-size: .8125rem;
    color: var(--ad-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ad-card-foot {
    display: flex;
    align-items: center;
    gap: .5rem;
    flex-wrap: wrap;
}

.ad-card-foot .ad-toolbar-spacer,
.ad-card-foot .ad-spacer {
    flex: 1 1 auto;
}

.ad-card-error {
    font-size: .75rem;
    color: var(--ad-red);
    background-color: var(--ad-red-soft);
    border: 1px solid var(--ad-red-line);
    border-radius: var(--ad-radius-sm);
    padding: .4375rem .625rem;
    word-break: break-word;
}

/* ---------------------------------------------------------------- donut / meters ---------- */

.ad-donut {
    display: grid;
    place-items: center;
    position: relative;
    width: 128px;
    height: 128px;
    margin: 0 auto;
    border-radius: 50%;
}

.ad-donut::after {
    content: "";
    position: absolute;
    inset: 14px;
    border-radius: 50%;
    background-color: var(--ad-panel);
}

.ad-donut-center {
    position: relative;
    z-index: 1;
    text-align: center;
    line-height: 1.15;
}

.ad-donut-value {
    display: block;
    font-size: 1.375rem;
    font-weight: 650;
    letter-spacing: -.02em;
    color: var(--ad-text);
    font-variant-numeric: tabular-nums;
}

.ad-donut-caption {
    display: block;
    font-family: var(--ad-mono);
    font-size: .5625rem;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--ad-text-faint);
    margin-top: .1875rem;
}

.ad-meter {
    height: 6px;
    border-radius: 999px;
    background-color: var(--ad-panel-soft);
    overflow: hidden;
}

.ad-meter-fill {
    height: 100%;
    border-radius: 999px;
    background-color: var(--ad-accent);
}

/* Heat cells, echoing the reference's attendance grid. */
.ad-heat {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
    gap: 3px;
}

.ad-heat-cell {
    aspect-ratio: 1;
    border-radius: 2px;
    background-color: var(--ad-panel-soft);
}

.ad-heat-1 { background-color: var(--ad-heat-1); }
.ad-heat-2 { background-color: var(--ad-heat-2); }
.ad-heat-3 { background-color: var(--ad-heat-3); }
.ad-heat-4 { background-color: var(--ad-heat-4); }

/* ---------------------------------------------------------------- feed / activity --------- */

.ad-feed {
    display: flex;
    flex-direction: column;
}

.ad-feed-item {
    display: flex;
    align-items: flex-start;
    gap: .625rem;
    padding: .625rem 0;
    border-bottom: 1px solid var(--ad-border-soft);
}

.ad-feed-item:last-child {
    border-bottom: 0;
    padding-bottom: 0;
}

.ad-feed-dot {
    flex: 0 0 auto;
    width: 7px;
    height: 7px;
    margin-top: .4375rem;
    border-radius: 50%;
    background-color: var(--ad-accent);
}

.ad-feed-dot-green { background-color: var(--ad-green); }
.ad-feed-dot-amber { background-color: var(--ad-amber); }
.ad-feed-dot-red { background-color: var(--ad-red); }
.ad-feed-dot-muted { background-color: var(--ad-text-faint); }

.ad-feed-text {
    flex: 1 1 auto;
    min-width: 0;
    font-size: .8125rem;
    color: var(--ad-text);
}

.ad-feed-sub {
    display: block;
    font-size: .75rem;
    color: var(--ad-text-faint);
    margin-top: .0625rem;
}

.ad-feed-time {
    flex: 0 0 auto;
    font-family: var(--ad-mono);
    font-size: .6875rem;
    color: var(--ad-text-faint);
    white-space: nowrap;
}

/* ---------------------------------------------------------------- forms ------------------- */

.ad-form {
    display: grid;
    gap: 1rem;
}

.ad-form-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 1rem;
}

.ad-form-grid .ad-field-full {
    grid-column: 1 / -1;
}

@media (max-width: 640px) {
    .ad-form-grid {
        grid-template-columns: minmax(0, 1fr);
    }
}

.ad-field {
    display: flex;
    flex-direction: column;
    gap: .375rem;
    min-width: 0;
}

.ad-label {
    font-family: var(--ad-mono);
    font-size: .625rem;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--ad-text-faint);
}

.ad-input,
.ad-select,
.ad-textarea {
    width: 100%;
    padding: .5625rem .75rem;
    border-radius: var(--ad-radius-sm);
    border: 1px solid var(--ad-border);
    background-color: var(--ad-bg);
    color: var(--ad-text);
    font-family: var(--ad-sans);
    font-size: .875rem;
    line-height: 1.4;
    transition: border-color .12s ease, box-shadow .12s ease;
}

.ad-input::placeholder,
.ad-textarea::placeholder {
    color: var(--ad-text-faint);
}

.ad-input:focus,
.ad-select:focus,
.ad-textarea:focus {
    outline: none;
    border-color: var(--ad-accent);
    box-shadow: 0 0 0 3px var(--ad-accent-soft);
}

.ad-select {
    appearance: none;
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%237d8590'%3E%3Cpath d='M4.5 6.5 8 10l3.5-3.5z'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right .5rem center;
    background-size: 16px;
    padding-right: 2rem;
}

.ad-select option {
    background-color: var(--ad-elev);
    color: var(--ad-text);
}

.ad-check {
    display: flex;
    align-items: center;
    gap: .5rem;
    font-size: .8125rem;
    color: var(--ad-text-dim);
    cursor: pointer;
}

.ad-check input[type="checkbox"] {
    width: 15px;
    height: 15px;
    accent-color: var(--ad-accent);
    cursor: pointer;
}

.ad-hint {
    font-size: .75rem;
    color: var(--ad-text-faint);
}

/* Validation output from DataAnnotationsValidator / ValidationSummary. */
.ad-form .validation-message,
.ad-auth .validation-message,
.ad-form .validation-errors,
.ad-auth .validation-errors {
    color: var(--ad-red);
    font-size: .75rem;
    list-style: none;
    padding: 0;
    margin: 0;
}

.ad-input.invalid,
.ad-select.invalid {
    border-color: var(--ad-red);
}

.ad-input.modified.valid,
.ad-select.modified.valid {
    border-color: var(--ad-border);
}

/* ---------------------------------------------------------------- alerts ------------------ */

.ad-alert {
    display: flex;
    gap: .625rem;
    padding: .75rem .875rem;
    border-radius: var(--ad-radius-sm);
    border: 1px solid var(--ad-border);
    background-color: var(--ad-panel);
    font-size: .8125rem;
    color: var(--ad-text-dim);
    margin-bottom: 1rem;
}

.ad-alert-info {
    border-color: var(--ad-accent-line);
    background-color: var(--ad-accent-soft);
    color: var(--ad-text);
}

.ad-alert-success {
    border-color: var(--ad-green-line);
    background-color: var(--ad-green-soft);
    color: var(--ad-text);
}

.ad-alert-warning {
    border-color: var(--ad-amber-line);
    background-color: var(--ad-amber-soft);
    color: var(--ad-text);
}

.ad-alert-danger {
    border-color: var(--ad-red-line);
    background-color: var(--ad-red-soft);
    color: var(--ad-text);
}

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

.ad-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .625rem;
    text-align: center;
    padding: 3rem 1.5rem;
    background-color: var(--ad-panel);
    border: 1px dashed var(--ad-border);
    border-radius: var(--ad-radius);
}

.ad-empty-mark {
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    border-radius: 11px;
    background-color: var(--ad-panel-soft);
    border: 1px solid var(--ad-border);
    color: var(--ad-text-faint);
}

.ad-empty-title {
    margin: 0;
    font-size: .9375rem;
    font-weight: 600;
    color: var(--ad-text);
}

.ad-empty-text {
    margin: 0;
    font-size: .8125rem;
    color: var(--ad-text-dim);
    max-width: 42ch;
}

.ad-loading {
    font-family: var(--ad-mono);
    font-size: .75rem;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--ad-text-faint);
    padding: 2rem 0;
    text-align: center;
}

/* ---------------------------------------------------------------- auth (login) ------------ */

.ad-auth {
    display: grid;
    grid-template-columns: 1.05fr .95fr;
    min-height: 100vh;
    font-family: var(--ad-sans);
    color: var(--ad-text);
    background-color: var(--ad-bg);
}

.ad-auth-aside {
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    gap: 2rem;
    padding: 2.5rem;
    border-right: 1px solid var(--ad-border);
    background-color: var(--ad-elev);
    background-image:
        radial-gradient(90% 70% at 12% 8%, var(--ad-accent-glow), transparent 60%),
        linear-gradient(to right, var(--ad-grid) 1px, transparent 1px),
        linear-gradient(to bottom, var(--ad-grid) 1px, transparent 1px);
    background-size: auto, 44px 44px, 44px 44px;
    overflow: hidden;
}

.ad-auth-headline {
    font-size: 2.5rem;
    font-weight: 650;
    letter-spacing: -.035em;
    line-height: 1.08;
    margin: 1.25rem 0 .75rem;
    max-width: 16ch;
}

.ad-auth-lede {
    font-size: .9375rem;
    color: var(--ad-text-dim);
    max-width: 44ch;
    margin: 0;
}

.ad-auth-caret {
    display: inline-block;
    width: .5rem;
    height: 1.75rem;
    margin-left: .25rem;
    vertical-align: -.25rem;
    background-color: var(--ad-accent);
    animation: ad-blink 1.1s step-end infinite;
}

@keyframes ad-blink {
    0%, 100% { opacity: 1; }
    50% { opacity: 0; }
}

.ad-auth-points {
    list-style: none;
    padding: 0;
    margin: 1.75rem 0 0;
    display: flex;
    flex-direction: column;
    gap: .625rem;
}

.ad-auth-points li {
    display: flex;
    align-items: flex-start;
    gap: .5rem;
    font-size: .875rem;
    color: var(--ad-text-dim);
}

.ad-auth-tick {
    color: var(--ad-accent);
    flex: 0 0 auto;
    margin-top: .0625rem;
}

.ad-auth-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    font-family: var(--ad-mono);
    font-size: .6875rem;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--ad-text-faint);
}

/* The theme switch rides here so the choice is reachable before sign-in — the sign-in screen is
   the first thing a visitor to the root site sees, and it is themed like everything else. */
.ad-auth-foot .theme-toggle {
    font-family: var(--ad-sans);
    letter-spacing: normal;
    text-transform: none;
}

.ad-auth-main {
    display: grid;
    place-items: center;
    padding: 2.5rem 1.5rem;
    background-image:
        linear-gradient(to right, var(--ad-grid-soft) 1px, transparent 1px),
        linear-gradient(to bottom, var(--ad-grid-soft) 1px, transparent 1px);
    background-size: 44px 44px;
}

.ad-auth-card {
    width: 100%;
    max-width: 400px;
    background-color: var(--ad-panel);
    border: 1px solid var(--ad-border);
    border-radius: 14px;
    padding: 2rem 1.75rem;
}

.ad-auth-title {
    margin: 0 0 .375rem;
    font-size: 1.5rem;
    font-weight: 650;
    letter-spacing: -.025em;
}

.ad-auth-sub {
    margin: 0 0 1.5rem;
    font-size: .8125rem;
    color: var(--ad-text-dim);
}

.ad-auth-divider {
    display: flex;
    align-items: center;
    gap: .75rem;
    margin: 1.25rem 0;
    font-family: var(--ad-mono);
    font-size: .625rem;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--ad-text-faint);
}

.ad-auth-divider::before,
.ad-auth-divider::after {
    content: "";
    flex: 1 1 auto;
    height: 1px;
    background-color: var(--ad-border);
}

.ad-auth-links {
    display: flex;
    flex-direction: column;
    gap: .5rem;
    margin-top: 1.25rem;
    padding-top: 1.25rem;
    border-top: 1px solid var(--ad-border-soft);
    font-size: .8125rem;
}

@media (max-width: 900px) {
    .ad-auth {
        grid-template-columns: minmax(0, 1fr);
    }

    .ad-auth-aside {
        display: none;
    }
}

/* Bootstrap form classes still ship inside LoginForm / Identity pages. Re-skin them for the
   dark shell rather than rewriting the shared component's markup. */
.ad-auth .form-control,
.ad-auth .form-select {
    background-color: var(--ad-bg);
    border: 1px solid var(--ad-border);
    color: var(--ad-text);
    border-radius: var(--ad-radius-sm);
}

.ad-auth .form-control:focus,
.ad-auth .form-select:focus {
    background-color: var(--ad-bg);
    color: var(--ad-text);
    border-color: var(--ad-accent);
    box-shadow: 0 0 0 3px var(--ad-accent-soft);
}

.ad-auth .form-floating > label {
    color: var(--ad-text-faint);
}

.ad-auth .form-floating > .form-control:focus ~ label,
.ad-auth .form-floating > .form-control:not(:placeholder-shown) ~ label {
    color: var(--ad-text-faint);
}

.ad-auth .form-floating > .form-control:focus ~ label::after,
.ad-auth .form-floating > .form-control:not(:placeholder-shown) ~ label::after {
    background-color: transparent !important;
}

.ad-auth .btn-primary {
    background-color: var(--ad-accent);
    border-color: var(--ad-accent);
    color: var(--ad-on-accent);
    font-weight: 650;
}

.ad-auth .btn-primary:hover,
.ad-auth .btn-primary:focus {
    background-color: var(--ad-accent-hover);
    border-color: var(--ad-accent-hover);
    color: var(--ad-on-accent);
}

/* Body links only — see the note on .admin-shell a:not(.ad-btn). */
.ad-auth .btn-link,
.ad-auth a:not(.ad-btn) {
    color: var(--ad-accent);
    text-decoration: none;
}

.ad-auth .btn-link:hover,
.ad-auth a:not(.ad-btn):hover {
    color: var(--ad-accent-hover);
    text-decoration: underline;
}

.ad-auth h2 {
    font-size: .8125rem;
    font-weight: 500;
    color: var(--ad-text-dim);
}

.ad-auth hr {
    border-color: var(--ad-border);
    opacity: 1;
}

.ad-auth .text-secondary,
.ad-auth .text-muted {
    color: var(--ad-text-faint) !important;
}

.ad-auth .text-danger {
    color: var(--ad-red) !important;
}

.ad-auth .alert-danger {
    background-color: var(--ad-red-soft);
    border-color: var(--ad-red-line);
    color: var(--ad-text);
}

.ad-auth .checkbox .form-check-input {
    background-color: var(--ad-bg);
    border-color: var(--ad-border);
}

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

/* Same treatment for Bootstrap markup that appears inside the admin shell (Identity's
   Account/Manage pages, mainly), so nothing renders as a white box on black. */
.admin-shell .form-control,
.admin-shell .form-select {
    background-color: var(--ad-bg);
    border: 1px solid var(--ad-border);
    color: var(--ad-text);
}

.admin-shell .form-control:focus,
.admin-shell .form-select:focus {
    background-color: var(--ad-bg);
    color: var(--ad-text);
    border-color: var(--ad-accent);
    box-shadow: 0 0 0 3px var(--ad-accent-soft);
}

.admin-shell .form-floating > label,
.admin-shell .form-label {
    color: var(--ad-text-faint);
}

.admin-shell .btn-primary {
    background-color: var(--ad-accent);
    border-color: var(--ad-accent);
    color: var(--ad-on-accent);
    font-weight: 650;
}

.admin-shell .btn-primary:hover {
    background-color: var(--ad-accent-hover);
    border-color: var(--ad-accent-hover);
    color: var(--ad-on-accent);
}

/* Body links only — hence .admin-content and not .admin-shell. Anchored at the shell this rule
   (0,2,1) outranks .admin-nav-link, .admin-brand and .admin-user (0,1,0) and painted the whole
   sidebar accent-blue; the sidebar owns its own ink, which stays black through every state.

   Without the :not(), it also outranks .ad-btn-primary (0,1,0) and paints an
   <a class="ad-btn ad-btn-primary"> accent-on-accent — an invisible label. The button classes
   own their own colour in every variant. */
.admin-content a:not(.ad-btn) {
    color: var(--ad-accent);
}

.admin-shell .text-secondary,
.admin-shell .text-muted {
    color: var(--ad-text-faint) !important;
}

.admin-shell .text-danger {
    color: var(--ad-red) !important;
}

.admin-shell .list-group-item {
    background-color: var(--ad-panel);
    border-color: var(--ad-border);
    color: var(--ad-text);
}

.admin-shell .nav-pills .nav-link {
    color: var(--ad-text-dim);
}

.admin-shell .nav-pills .nav-link.active {
    background-color: var(--ad-accent-soft);
    color: var(--ad-text);
}

/* ---------------------------------------------------------------- a11y ---------------------- */

.admin-shell :focus-visible,
.ad-auth :focus-visible {
    outline: 2px solid var(--ad-accent);
    outline-offset: 2px;
    border-radius: 3px;
}

.ad-visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

@media (prefers-reduced-motion: reduce) {
    .admin-shell *,
    .ad-auth * {
        animation-duration: .001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .001ms !important;
    }
}

/* ---------------------------------------------------------------- grid: sorting + paging --- */

/* Sortable column headers. The arrow is generated so the markup stays a plain link — these
   grids are static SSR, and sorting is navigation, not an interaction. */
.ad-sort {
    color: inherit;
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    white-space: nowrap;
}

.ad-sort:hover {
    color: var(--ad-text-dim);
}

.ad-sort::after {
    content: "";
    font-size: .7em;
    opacity: .55;
}

.ad-sort-asc::after {
    content: "\2191";
}

.ad-sort-desc::after {
    content: "\2193";
}

.ad-pager {
    display: flex;
    align-items: center;
    gap: .5rem;
    flex-wrap: wrap;
    margin-top: 1rem;
}

.ad-pager-count,
.ad-pager-page {
    font-family: var(--ad-mono);
    font-size: .6875rem;
    letter-spacing: .08em;
    color: var(--ad-text-faint);
    white-space: nowrap;
}

/* Disabled pager steps stay in place rather than disappearing, so the controls do not jump
   between the first, middle and last page. */
.ad-disabled {
    opacity: .4;
    pointer-events: none;
}

/* ---------------------------------------------------------------- printable roll ----------- */

/* The print view renders outside .admin-shell, so it cannot use the --ad-* palette and is
   deliberately self-contained: ink on paper, readable in the browser beforehand. */
.ad-print {
    max-width: 60rem;
    margin: 0 auto;
    padding: 2rem 1.5rem;
    background: #fff;
    color: #111;
    font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
    font-size: .875rem;
}

.ad-print-head {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 1rem;
    border-bottom: 2px solid #111;
    padding-bottom: .75rem;
    margin-bottom: 1.25rem;
}

.ad-print-head h1 {
    margin: 0;
    font-size: 1.25rem;
}

.ad-print-head p {
    margin: .25rem 0 0;
    color: #555;
}

.ad-print-meta {
    text-align: right;
    color: #555;
    font-size: .8125rem;
    white-space: nowrap;
}

.ad-print-table {
    width: 100%;
    border-collapse: collapse;
}

.ad-print-table th,
.ad-print-table td {
    text-align: left;
    padding: .4rem .5rem;
    border-bottom: 1px solid #ccc;
    vertical-align: top;
}

.ad-print-table thead th {
    border-bottom: 1.5px solid #111;
    font-size: .75rem;
    text-transform: uppercase;
    letter-spacing: .06em;
}

.ad-print-note {
    margin-top: 1rem;
    color: #555;
    font-style: italic;
}

.ad-print-actions {
    display: flex;
    gap: .5rem;
    margin-top: 1.5rem;
}

/* ==========================================================================
   Records and registers
   Shared by the student roll, the staff register and the attendance sheets.
   Every colour resolves through an --ad-* token, so the dark block at the top
   of this file themes them without a second rule down here.
   ========================================================================== */

/* The one number a panel is about — an attendance percentage, a total. Sized
   to be read before the label beside it, never as the only thing said. */
.ad-hero {
    font-size: 2rem;
    font-weight: 650;
    line-height: 1;
    letter-spacing: -.02em;
    color: var(--ad-text);
    font-variant-numeric: tabular-nums;
}

/* A compact field for use inside a table row, where the full-height input
   would make every row twice as tall as it needs to be. */
.ad-input-sm {
    padding: .3125rem .5rem;
    font-size: .8125rem;
}

/* A row's worth of radio options, laid out inline. Attendance puts all four
   statuses in one cell because an InputRadioGroup has to enclose every radio
   it owns, and a group cannot span table cells without invalid markup. */
.ad-radio-set {
    display: inline-flex;
    align-items: center;
    gap: .625rem;
    flex-wrap: wrap;
}

.ad-radio {
    display: inline-flex;
    align-items: center;
    gap: .3125rem;
    font-size: .8125rem;
    color: var(--ad-text-dim);
    cursor: pointer;
    white-space: nowrap;
}

.ad-radio input {
    accent-color: var(--ad-accent);
    margin: 0;
    cursor: pointer;
}

.ad-radio:hover {
    color: var(--ad-text);
}

/* Label/value pairs on a record page. Two columns on anything wide enough,
   stacked below that — a definition list is the honest markup for this. */
.ad-detail-list {
    display: grid;
    grid-template-columns: minmax(7rem, auto) 1fr;
    gap: .5rem 1rem;
    margin: 0;
    font-size: .875rem;
}

.ad-detail-list dt {
    color: var(--ad-text-faint);
}

.ad-detail-list dd {
    margin: 0;
    color: var(--ad-text);
}

@media (max-width: 30rem) {
    .ad-detail-list {
        grid-template-columns: 1fr;
        gap: .125rem 0;
    }

    .ad-detail-list dd {
        margin-bottom: .5rem;
    }
}

/* A short editable list — departments, designations — where a full table
   would be more chrome than content. */
.ad-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.ad-list-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: .5rem 0;
    border-bottom: 1px solid var(--ad-border-soft);
    font-size: .875rem;
}

.ad-list-row:last-child {
    border-bottom: 0;
}

/* Separates a list from the form that adds to it, inside one panel. */
.ad-rule {
    border: 0;
    border-top: 1px solid var(--ad-border-soft);
    margin: 1.25rem 0;
}

/* Validation summary. Red is not the only channel: the summary sits above the
   form with role="alert", so it is announced as well as coloured. */
.ad-validation {
    margin: 0 0 1rem;
    padding: .625rem .75rem;
    border-radius: var(--ad-radius-sm);
    border: 1px solid var(--ad-red-line);
    background-color: var(--ad-red-soft);
    color: var(--ad-red);
    font-size: .8125rem;
}

.ad-validation ul {
    margin: 0;
    padding-left: 1.125rem;
}

/* ---------------------------------------------------------------- timetable grid ----------- */

/* A week: periods down the side, days across the top. Fixed layout on purpose —
   every day column gets the same width whatever it happens to hold, so the grid
   reads as a timetable rather than as a table that has been sorted. */
.ad-tt {
    width: 100%;
    border-collapse: collapse;
    table-layout: fixed;
    font-size: .8125rem;
}

.ad-tt th,
.ad-tt td {
    border: 1px solid var(--ad-border);
    padding: 0;
    vertical-align: top;
}

.ad-tt thead th {
    background-color: var(--ad-thead-bg);
    color: var(--ad-text-dim);
    padding: .5rem;
    font-size: .75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .06em;
    text-align: center;
}

/* The period column. Narrow, and it carries the times, so it stays legible when
   the day columns are full. */
.ad-tt-period {
    width: 8.5rem;
    background-color: var(--ad-panel-soft);
    padding: .5rem !important;
    text-align: left;
}

.ad-tt-period-name {
    display: block;
    font-weight: 600;
    color: var(--ad-text);
}

.ad-tt-period-time {
    display: block;
    margin-top: .125rem;
    font-size: .6875rem;
    color: var(--ad-text-faint);
    font-variant-numeric: tabular-nums;
}

/* A cell is a link across its whole area, so the target is the cell the eye is
   already on rather than a word inside it. */
.ad-tt-cell {
    display: block;
    min-height: 3.5rem;
    padding: .5rem;
    text-decoration: none;
    color: inherit;
}

.ad-tt-cell:hover {
    background-color: var(--ad-row-hover);
}

.ad-tt-cell:focus-visible {
    outline: 2px solid var(--ad-accent);
    outline-offset: -2px;
}

.ad-tt-subject {
    display: block;
    font-weight: 600;
    color: var(--ad-text);
}

.ad-tt-teacher,
.ad-tt-room {
    display: block;
    margin-top: .125rem;
    font-size: .75rem;
    color: var(--ad-text-dim);
}

/* An unassigned slot is a real problem — nobody is teaching that period — so it
   says so in words as well as in colour. */
.ad-tt-unassigned {
    color: var(--ad-amber);
}

/* An empty cell shows its affordance only on hover, so a mostly-empty grid does
   not read as a wall of plus signs. */
.ad-tt-empty {
    color: var(--ad-text-faint);
    font-size: 1rem;
    text-align: center;
    line-height: 2.5rem;
    opacity: 0;
}

.ad-tt-cell:hover .ad-tt-empty,
.ad-tt-cell:focus-visible .ad-tt-empty {
    opacity: 1;
}

/* Break rows span the week: nothing is taught in them, so they are not cells. */
.ad-tt-break {
    background-color: var(--ad-panel-soft);
    color: var(--ad-text-faint);
    text-align: center;
    padding: .375rem !important;
    font-size: .75rem;
    letter-spacing: .04em;
}

/* The same grid on paper. Self-contained like the rest of the print styles,
   because the print layout renders outside .admin-shell and its palette. */
.ad-print-grid {
    width: 100%;
    border-collapse: collapse;
    table-layout: fixed;
    font-size: .75rem;
}

.ad-print-grid th,
.ad-print-grid td {
    border: 1px solid #999;
    padding: .375rem .4rem;
    vertical-align: top;
    text-align: left;
}

.ad-print-grid thead th {
    background: #eee;
    text-align: center;
    font-size: .6875rem;
    text-transform: uppercase;
    letter-spacing: .06em;
}

.ad-print-grid .ad-print-subject {
    display: block;
    font-weight: 700;
}

.ad-print-grid .ad-print-sub {
    display: block;
    color: #555;
}

/* --- Marks ------------------------------------------------------------------
   A mark box is narrow and right-aligned: a column of numbers is read by its
   last digit, and a wide box invites a sentence where a figure belongs. */
.ad-mark {
    max-width: 5.5rem;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* A figure below the pass mark. Colour alone would not say so on a printed or
   colour-blind reading, which is why the result sheet also carries a key. */
.ad-mark-fail {
    color: var(--ad-red);
    font-weight: 600;
}

/* Where a report card gets signed. Three columns, ruled, and only on paper —
   on screen they are just labels under an empty line. */
.ad-print-signatures {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 2rem;
    margin-top: 3rem;
    font-size: .75rem;
    color: #555;
}

.ad-print-signatures > div {
    border-top: 1px solid #999;
    padding-top: .375rem;
    text-align: center;
}

/* The second line of a printed cell: an admission number under a name, a phone
   number under a guardian. Already scoped to the timetable grid above; a
   receipt and a chaser list want the same thing inside an ordinary table. */
.ad-print-table .ad-print-sub {
    display: block;
    font-size: .6875rem;
    color: #555;
}

/* A signature block with two names rather than three. A receipt is signed by
   whoever took the money and whoever handed it over, and nobody else. */
.ad-print-signatures:has(> div:nth-child(2):last-child) {
    grid-template-columns: repeat(2, 1fr);
}

/* ------------------------------------------------------------------------------------
   Messaging

   Global rather than scoped to a component, because two pages render the same thread markup
   (ViewThread and the oversight read) and a scoped rule reaches only the component it was
   written in. Every colour resolves through an --ad-* token, so the dark block at the top of
   this file themes all of it and there is nothing to keep in step by hand.
   ------------------------------------------------------------------------------------ */

/* The unread count on the sidebar's Messages link. messaging.js unhides it. */
.admin-nav-badge {
    margin-left: auto;
    min-width: 1.375rem;
    padding: .0625rem .375rem;
    border-radius: 999px;
    background-color: var(--ad-accent);
    color: var(--ad-on-accent);
    font-family: var(--ad-mono);
    font-size: .6875rem;
    font-weight: 700;
    line-height: 1.4;
    text-align: center;
}

.msg-thread {
    max-width: 52rem;
}

.msg-list {
    display: flex;
    flex-direction: column;
    gap: .75rem;
    /* Bounded so the compose box stays reachable without scrolling a long thread first. */
    max-height: 60vh;
    overflow-y: auto;
    margin: 0 0 1rem;
    padding: .25rem;
    list-style: none;
}

.msg {
    max-width: 40rem;
    padding: .625rem .875rem;
    border: 1px solid var(--ad-border-soft);
    border-radius: var(--ad-radius);
    background-color: var(--ad-panel-soft);
}

/* Own messages sit right and take the accent tint. Position carries it as well as colour, so
   the distinction survives for anybody who cannot tell the two tints apart. */
.msg-mine {
    margin-left: auto;
    background-color: var(--ad-accent-soft);
    border-color: var(--ad-accent-line);
}

.msg-meta {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: .25rem;
}

.msg-sender {
    font-size: .8125rem;
    font-weight: 600;
    color: var(--ad-text);
}

.msg-time {
    font-family: var(--ad-mono);
    font-size: .6875rem;
    color: var(--ad-text-faint);
    white-space: nowrap;
}

.msg-body {
    font-size: .875rem;
    color: var(--ad-text);
    /* Newlines somebody typed are meaningful, and a pasted URL must not widen the page. */
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.msg-compose {
    padding-top: .75rem;
    border-top: 1px solid var(--ad-border-soft);
}

.msg-input {
    resize: vertical;
    min-height: 4.5rem;
}

/* Chips: what the compose page shows for the people chosen so far. */
.ad-chip-list {
    display: flex;
    flex-wrap: wrap;
    gap: .375rem;
    margin: 0 0 .75rem;
    padding: 0;
    list-style: none;
}

.ad-chip {
    display: inline-flex;
    align-items: center;
    gap: .375rem;
    padding: .1875rem .5rem .1875rem .625rem;
    border: 1px solid var(--ad-accent-line);
    border-radius: 999px;
    background-color: var(--ad-accent-soft);
    font-size: .8125rem;
    color: var(--ad-text);
}

.ad-chip-remove {
    color: var(--ad-text-dim);
    font-size: 1rem;
    line-height: 1;
    text-decoration: none;
}

.ad-chip-remove:hover,
.ad-chip-remove:focus-visible {
    color: var(--ad-red);
}

.ad-plain-list {
    margin: 0;
    padding: 0;
    list-style: none;
}

.ad-plain-list > li {
    padding: .375rem 0;
    border-bottom: 1px solid var(--ad-border-soft);
    font-size: .875rem;
}

.ad-plain-list > li:last-child {
    border-bottom: 0;
}

.ad-muted {
    color: var(--ad-text-faint);
}

/* Repeat the header on every sheet, and keep the on-screen buttons off the paper. */
@media print {
    .ad-print {
        padding: 0;
        max-width: none;
    }

    .ad-print-actions {
        display: none;
    }

    .ad-print-table thead {
        display: table-header-group;
    }

    .ad-print-table tr {
        break-inside: avoid;
    }

    /* A week has to land on one sheet to be usable as a wall chart. */
    .ad-print-grid {
        break-inside: avoid;
    }
}
