/* =============================================================================
   ExamON — UI KIT  (Apple-Glass design system)
   -----------------------------------------------------------------------------
   WHAT THIS IS
     The shared visual foundation for every ExamON screen: design tokens, the
     top chrome, the page shell, and the reusable component vocabulary
     (buttons, cards, tables, forms, badges, empty states, overlays).

   WHERE IT CAME FROM
     Ported 2026-08-11 from the ClassON ERP module kit
         superadmin/backend/usertemplate/assets/moduleui/module-ui.css
     which already skins that app's Attendance and Payroll modules.
     A LOCAL CLONE is kept here on purpose: ExamON deploys standalone (one
     install per school), so linking an asset out of the other application's
     document root would break in production. Never reference that path.

   DELIBERATE DEVIATIONS FROM THE REFERENCE  (each one is a decision, not drift)
     1. Semantic text colours use darkened twins (--mod-*-tx). Apple's #34C759
        is ~2.2:1 on white; the reference gets away with it, ExamON renders far
        more small semantic text (badges, table cells, hints).
     2. The page gradient sits on a fixed `body::before` layer instead of
        `background-attachment:fixed` — identical look, but no full-viewport
        repaint while scrolling a 2,000-row marks grid.
     3. Icons are FontAwesome 6.5 classes, not inline SVG. The reference uses
        SVG because its host loads FA 4.7, which lacks the glyphs ExamON needs.
     4. Class prefix is .eo-  (not the reference's own att- or fin- prefixes)
        so nothing collides if ExamON is ever embedded in the ERP shell.
     5. The reference styles Bootstrap hooks (.form-control, table.table).
        ExamON uses no CSS framework, so those values are mapped onto ExamON's
        own class vocabulary instead.

   LOAD ORDER  (application/views/includes/header.php)
     examon_ui.css  →  examon_module.css  →  examon_analytics.css (analytics only)
     This file owns the shared layer; examon_module.css owns per-screen blocks.
     A per-screen block must never redefine a component that lives here.

   STRUCTURE
     §1 Tokens · §2 Reset + body · §3 Top chrome · §4 Shell · §5 Page furniture
     §6 Buttons · §7 Data display · §8 Forms · §9 Overlays
   ============================================================================= */


/* ═══════════════════════════════════════════════════════════════════════════
   §1  TOKENS
   ═══════════════════════════════════════════════════════════════════════════ */
:root{
    /* Which way the browser should paint everything CSS never reaches:
       native field backgrounds, scrollbars, <select> popups, date pickers.
       Without the dark twin in §1b, any control that declares no background
       of its own keeps painting the OS's WHITE field on a dark page. */
    color-scheme: light;

    /* ── Apple-Glass source palette ─────────────────────────────────────── */
    --mod-accent:      #007AFF;                 /* every interactive element */
    --mod-accent-d:    #0062cc;                 /* hover / pressed           */
    --mod-accent-soft: rgba(0,122,255,.12);     /* tint fill                 */
    --mod-accent-ring: rgba(0,122,255,.20);     /* focus ring / tint border  */
    /* The TEXT twin, same idea as --mod-green-tx / --mod-danger-tx below.
       Accent was the one colour without one, so every blue chip painted its
       label in the FILL blue — on the blue tint it sits on, that is ~4:1 and
       reads as blue-on-blue. Identical to --mod-accent here, so light mode is
       unchanged by construction; §1b brightens it for dark. */
    --mod-accent-tx:   #007AFF;

    --mod-red:   #AC3D3C;                       /* BRANDBAR ONLY — never interactive */
    --mod-red-d: #8f2f2e;

    /* Semantic: Apple system colours for FILLS, darkened twins for TEXT. */
    --mod-green:  #34C759; --mod-green-soft: rgba(52,199,89,.12);   --mod-green-tx: #248A3D;
    --mod-danger: #FF3B30; --mod-danger-soft: rgba(255,59,48,.12);  --mod-danger-tx: #D70015;
    --mod-amber:  #FF9500; --mod-amber-soft: rgba(255,149,0,.12);   --mod-amber-tx:  #B25000;
    --mod-purple: #AF52DE; --mod-purple-soft:rgba(175,82,222,.12);  --mod-purple-tx: #8944AB;
    --mod-teal:   #5AC8FA; --mod-teal-soft:  rgba(90,200,250,.12);  --mod-teal-tx:   #0071A4;

    /* ── Ink + surfaces ─────────────────────────────────────────────────── */
    --mod-ink:         rgba(0,0,0,.85);
    --mod-ink-2:       rgba(0,0,0,.60);
    --mod-ink-3:       rgba(0,0,0,.40);
    --mod-ink-4:       rgba(0,0,0,.25);
    --mod-hair:        rgba(0,0,0,.08);         /* default hairline          */
    --mod-hair-strong: rgba(0,0,0,.15);         /* nav bottom edge           */
    --mod-card-line:   rgba(0,0,0,.05);         /* card border               */
    --mod-surface:     #fff;
    --mod-surface-2:   rgba(0,0,0,.02);         /* zebra / row hover         */
    --mod-track:       rgba(118,118,128,.12);   /* segmented control track   */
    --mod-fill:        rgba(0,0,0,.05);         /* ghost button / table head */
    --mod-fill-h:      rgba(0,0,0,.10);

    /* ── Radii ──────────────────────────────────────────────────────────── */
    --r-xs:6px; --r-seg:7px; --r-btn:8px; --r-md:10px;
    --r-card:14px; --r-lg:16px; --r-pill:999px;

    /* ── Shadows + motion ───────────────────────────────────────────────── */
    --sh-card:  0 1px 3px rgba(0,0,0,.05), 0 2px 8px rgba(0,0,0,.03);
    --sh-pill:  0 1px 3px rgba(0,0,0,.08), 0 1px 1px rgba(0,0,0,.04), 0 0 0 .5px rgba(0,0,0,.04);
    --sh-pop:   0 8px 32px rgba(0,0,0,.12), 0 2px 8px rgba(0,0,0,.06);
    --sh-modal: 0 8px 40px rgba(0,0,0,.15), 0 2px 8px rgba(0,0,0,.08), 0 0 0 .5px rgba(0,0,0,.08);
    --sh-ring:  0 0 0 3px var(--mod-accent-ring);
    --ease:     .2s cubic-bezier(.2,.8,.2,1);

    /* ── Spacing scale ──────────────────────────────────────────────────── */
    --sp-1:4px; --sp-2:6px; --sp-3:8px; --sp-4:12px; --sp-5:16px;
    --sp-6:20px; --sp-7:24px; --sp-8:32px; --sp-9:46px;

    /* ── Type scale ─────────────────────────────────────────────────────── */
    --font: -apple-system,BlinkMacSystemFont,"SF Pro Text","Segoe UI",Roboto,Helvetica,Arial,sans-serif;
    --font-mono: ui-monospace,"SF Mono","Fira Code",Menlo,monospace;
    --fs-h1:22px;   --fw-h1:800;  --ls-h1:-.01em;
    --fs-h2:17px;   --fs-h3:15px;
    --fs-body:14px; --fs-ui:13.5px; --fs-sm:13px; --fs-xs:12px; --fs-cap:11px;

    /* ── Layout ─────────────────────────────────────────────────────────── */
    --shell-w:    1240px;
    --brandbar-h: 46px;
    --navbar-h:   60px;
    --top-h:      106px;   /* brandbar + nav — for sticky offsets */

    /* ══ BACK-COMPAT ALIASES ═════════════════════════════════════════════
       ~2,100 lines of per-screen CSS in examon_module.css plus thousands of
       inline styles still reference these names. Same aliasing trick the
       reference kit uses, where its own prefixed names point at one shared
       source palette.
       (Do not write a star immediately followed by a slash anywhere in a CSS
       comment — it closes the comment early. That exact typo, in this very
       block, silently invalidated the whole :root rule on first deploy and
       left every var() empty.)

       DO NOT ADD NEW USAGES. New code uses the --mod-* names above.

       Note on --red: in the old theme it was the INTERACTIVE accent (primary
       buttons, focus rings, active nav, count pills, checked radio cards) —
       it was never "danger". So it aliases to the Apple accent. The handful
       of places where it genuinely meant danger are re-pointed by hand below
       (.alert-err, .act-d, .status-inactive, .stat-red, .req). */
    --red:      var(--mod-accent);
    --red-dark: var(--mod-accent-d);
    --red-glow: var(--mod-accent-ring);
    --red-soft: var(--mod-accent-soft);

    /* The only true red left. New name so it cannot be reused by accident. */
    --brand-red:   var(--mod-red);
    --brand-red-d: var(--mod-red-d);

    --navy:  #17302a;  --navy2: #17302a;
    --surface: var(--mod-surface);
    --bg:      #f5f7fa;
    --border:  var(--mod-hair);
    --t1: var(--mod-ink);  --t2: var(--mod-ink-2);  --t3: var(--mod-ink-3);

    --green: var(--mod-green-tx);   --green-soft: var(--mod-green-soft);
    --amber: var(--mod-amber-tx);   --amber-soft: var(--mod-amber-soft);
    /* These aliases are the TEXT twins — that is how views use them:
       `color:var(--green)` on `background:var(--green-soft)`. --blue pointed
       at the FILL blue only because no --mod-accent-tx existed. The few
       places that genuinely want a blue FILL say var(--mod-accent). */
    --blue:  var(--mod-accent-tx);  --blue-soft:  var(--mod-accent-soft);
    --purple:var(--mod-purple-tx);  --purple-soft:var(--mod-purple-soft);

    --r:      var(--r-card);
    --r-sm:   var(--r-btn);
    --nav-h:  var(--navbar-h);
}

/* ═══════════════════════════════════════════════════════════════════════════
   §1b  DARK THEME — redefines the primitives everything above derives from.
   Toggled by header.php ([data-theme="dark"] on <html>, persisted in
   localStorage 'examon-theme'). Component classes that hardcode rgba(0,0,0/
   255,255,255,..) instead of a token (the nav glass + dropdown — the two
   places built before the token system existed) get their own direct
   overrides at the bottom of this block. Per-module inline hex colors (the
   hundreds of `style="background:#fef2f2"` etc. scattered through the views)
   are handled separately by examon_dark_sweep.css, loaded last in header.php.
   ═══════════════════════════════════════════════════════════════════════════ */
:root[data-theme="dark"] {
    color-scheme: dark;

    /* ── Ink + surfaces (light-on-dark) ─────────────────────────────────── */
    --mod-ink:         rgba(255,255,255,.92);
    --mod-ink-2:       rgba(255,255,255,.68);
    --mod-ink-3:       rgba(255,255,255,.48);
    --mod-ink-4:       rgba(255,255,255,.32);
    --mod-hair:        rgba(255,255,255,.12);
    --mod-hair-strong: rgba(255,255,255,.20);
    --mod-card-line:   rgba(255,255,255,.09);
    --mod-surface:     #1b1e24;
    --mod-surface-2:   rgba(255,255,255,.04);
    --mod-track:       rgba(140,140,150,.24);
    --mod-fill:        rgba(255,255,255,.08);
    --mod-fill-h:      rgba(255,255,255,.14);

    /* ── System accents — Apple's own dark-mode shades; the "-tx" (darkened
       for light-bg text) variants brighten back up toward the base color so
       they still pass contrast on a dark surface. ──────────────────────── */
    --mod-accent:      #0A84FF;  --mod-accent-d: #409CFF;
    --mod-accent-soft: rgba(10,132,255,.20); --mod-accent-ring: rgba(10,132,255,.32);
    /* Labels sit ON --mod-accent-soft, so this has to clear that tint, not
       the page behind it. */
    --mod-accent-tx:   #6CB4FF;

    --mod-green:  #30D158; --mod-green-soft: rgba(48,209,88,.18);   --mod-green-tx: #32D74B;
    --mod-danger: #FF453A; --mod-danger-soft: rgba(255,69,58,.18);  --mod-danger-tx: #FF8A80;
    --mod-amber:  #FF9F0A; --mod-amber-soft: rgba(255,159,10,.18);  --mod-amber-tx:  #FF9F0A;
    --mod-purple: #BF5AF2; --mod-purple-soft:rgba(191,90,242,.18);  --mod-purple-tx: #BF5AF2;
    --mod-teal:   #64D2FF; --mod-teal-soft:  rgba(100,210,255,.18); --mod-teal-tx:   #64D2FF;

    /* Brandbar red is a brand flag, not a surface — left unchanged on purpose. */

    --bg: #0d0f13;

    /* ══ REFERENCED-BUT-NEVER-DECLARED ═══════════════════════════════════
       These six are used across the app as `var(--bg-body, #f8fafc)` — with
       a hex fallback — but were declared NOWHERE, so the light fallback won
       100% of the time in BOTH themes. That is why e.g. the Class-to-Subjects
       table head stayed a white band while the card around it went dark.

       Declared here ONLY, never in the light :root: --bg2 and --primary carry
       DIFFERENT fallbacks at different call sites (#eef2f7 / #f8fafc /
       #f1f5f9), so a single light value would silently repaint whichever
       sites disagreed with it. Leaving them undeclared in light keeps every
       call site exactly as it renders today; declaring them here is enough,
       because a declared value beats the fallback. */
    --bg-body:      #22262c;
    --bg2:          #21252b;
    --bd:           rgba(255,255,255,.20);
    --border-light: rgba(255,255,255,.12);
    --primary:      var(--mod-accent);
    --primary-dark: var(--mod-accent-d);

    /* Attendance / health grid column-header tints. Declared here only, same
       reasoning as the block above: the views say
       `background:var(--grid-head-accent, #e0f2fe) !important`, so light keeps
       its exact fallback. They need a variable at all because the inline
       declaration carries !important — and an important INLINE style outranks
       an important rule from any stylesheet, so examon_dark_sweep.css cannot
       reach them. A variable is the one hook that still works. */
    --grid-head-accent: #16283a;
    --grid-head-muted:  #1f262d;
}

/* Nav glass + dropdown were built with hardcoded rgba(0,0,0/255,255,255,..)
   before the --mod-* tokens existed, so they need direct dark overrides. */
:root[data-theme="dark"] .eo-nav { background: rgba(20,22,27,.80); }
:root[data-theme="dark"] .eo-nav-title { color: rgba(255,255,255,.92); border-right-color: rgba(255,255,255,.14); }
:root[data-theme="dark"] .eo-pill:hover { color: rgba(255,255,255,.92); }
:root[data-theme="dark"] .eo-pill.active { background: #2a2d35; color: rgba(255,255,255,.95); }
:root[data-theme="dark"] .eo-dd-panel { background: var(--mod-surface); border-color: rgba(255,255,255,.14); }
:root[data-theme="dark"] .eo-dd-item { color: rgba(255,255,255,.82); }
:root[data-theme="dark"] .eo-dd-item:hover { background: rgba(255,255,255,.06); color: rgba(255,255,255,.95); }
:root[data-theme="dark"] .eo-dd-sep { background: rgba(255,255,255,.10); }
/* Apple's own dark mode is near-neutral — iOS systemBackground #000, macOS
   window #1e1e1e — never a coloured wash. A tinted gradient here (tried
   2026-08-27, rejected same day) bleeds through every translucent surface
   above it and the whole app reads purple. Keep it monochrome: a whisper of
   cool grey, lifted at the top so the page still has depth. */
:root[data-theme="dark"] body::before {
    background: linear-gradient(180deg, #1c1e22 0%, #141619 55%, #0e0f11 100%);
}
@supports not ((backdrop-filter: blur(2px)) or (-webkit-backdrop-filter: blur(2px))) {
    :root[data-theme="dark"] .eo-nav { background: #14161b; }
}


/* ═══════════════════════════════════════════════════════════════════════════
   §2  RESET + BODY
   ═══════════════════════════════════════════════════════════════════════════ */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; overflow-y: scroll; }

body {
    font-family: var(--font);
    color: var(--mod-ink);
    background: var(--bg);
    -webkit-font-smoothing: antialiased;
    min-height: 100vh;
    position: relative;
}

html:fullscreen { background: var(--bg); }
html:-webkit-full-screen { background: var(--bg); }
html:-moz-full-screen { background: var(--bg); }

/* Apple-Glass gradient on a fixed pseudo-layer — see deviation #2 up top. */
body::before {
    content: '';
    position: fixed; inset: 0;
    z-index: -1; pointer-events: none;
    background: linear-gradient(180deg,
        rgba(255,160,137,.35) 0%,
        rgba(240,244,248,.35) 50%,
        rgba(106,179,230,.35) 100%), #fff;
}

/* Low specificity on purpose so component classes (.eo-pill, .eo-dd-item)
   win without !important, exactly as the reference does. */
a { color: var(--mod-accent-tx); }


/* ═══════════════════════════════════════════════════════════════════════════
   §3  TOP CHROME — brandbar + glass nav + segmented pills
   ═══════════════════════════════════════════════════════════════════════════ */
.eo-top { position: sticky; top: 0; z-index: 1000; }

/* Screens with their own sticky table heads + fixed save bars cannot afford
   106px of permanent chrome. header.php adds .eo-compact for those. */
body.eo-compact .eo-top { position: relative; }

/* ── Brandbar ───────────────────────────────────────────────────────────── */
.eo-brandbar {
    background: linear-gradient(90deg, var(--brand-red), var(--brand-red-d));
    color: #fff;
    height: var(--brandbar-h);
    box-shadow: 0 1px 0 rgba(0,0,0,.08);
}
.eo-brandbar-inner {
    max-width: var(--shell-w); margin: 0 auto; padding: 0 var(--sp-6);
    width: 100%; height: 100%;
    display: flex; align-items: center; justify-content: space-between;
}
.eo-brand { display: flex; align-items: center; gap: var(--sp-5); }
.eo-brand b { font-weight: 700; letter-spacing: .02em; font-size: 15px; }
.eo-brand a {
    color: rgba(255,255,255,.86); text-decoration: none !important;
    font-size: var(--fs-ui); padding: 4px 2px; transition: .15s;
}
.eo-brand a:hover { color: #fff; }

.eo-user {
    display: flex; align-items: center; gap: var(--sp-3);
    font-size: var(--fs-sm); color: rgba(255,255,255,.92);
}
.eo-avatar {
    width: 24px; height: 24px; border-radius: 50%;
    background: rgba(255,255,255,.18);
    display: flex; align-items: center; justify-content: center;
    font-size: var(--fs-cap); font-weight: 700; letter-spacing: .02em;
    flex-shrink: 0;
}

/* ── Dark-mode toggle — lives in the brandbar, always visible ─────────── */
.eo-theme-toggle {
    width: 26px; height: 26px; border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    background: rgba(255,255,255,.14); border: none; cursor: pointer;
    color: rgba(255,255,255,.92); font-size: 12px; flex-shrink: 0;
    transition: background var(--ease);
}
.eo-theme-toggle:hover { background: rgba(255,255,255,.24); }
.eo-theme-toggle .eo-theme-icon-light { display: none; }
:root[data-theme="dark"] .eo-theme-toggle .eo-theme-icon-dark  { display: none; }
:root[data-theme="dark"] .eo-theme-toggle .eo-theme-icon-light { display: block; }

/* ── Glass nav ──────────────────────────────────────────────────────────── */
.eo-nav {
    background: rgba(255,255,255,.82);
    -webkit-backdrop-filter: blur(30px) saturate(200%);
    backdrop-filter: blur(30px) saturate(200%);
    border-bottom: .5px solid var(--mod-hair-strong);
}
@supports not ((backdrop-filter: blur(2px)) or (-webkit-backdrop-filter: blur(2px))) {
    .eo-nav { background: #fff; }
}
.eo-nav-inner {
    max-width: var(--shell-w); margin: 0 auto; padding: 0 var(--sp-6);
    width: 100%;
    display: flex; align-items: center; height: var(--navbar-h);
    /* CRITICAL: must stay visible so dropdown panels render outside the bar. */
    overflow: visible;
}
.eo-nav-title {
    font-weight: 600; font-size: var(--fs-h2); color: rgba(0,0,0,.9);
    letter-spacing: -.02em;
    display: flex; align-items: center; white-space: nowrap;
    margin-right: var(--sp-7); padding-right: var(--sp-7);
    border-right: 1px solid rgba(0,0,0,.1); height: 24px; flex-shrink: 0;
}

/* Segmented pill strip — the iOS control */
.eo-nav-links {
    background: var(--mod-track);
    border-radius: 9px; padding: 3px;
    display: flex; align-items: center; gap: 2px;
    overflow: visible; position: relative;
}
.eo-pill {
    display: inline-flex; align-items: center; gap: var(--sp-2);
    text-decoration: none !important; white-space: nowrap;
    padding: 0 14px; height: 32px; border-radius: var(--r-seg);
    font-family: var(--font); font-size: var(--fs-ui); font-weight: 500;
    color: var(--mod-ink-2);
    cursor: pointer; transition: all var(--ease);
    background: transparent; border: none;
}
.eo-pill i { font-size: 13px; opacity: .7; flex-shrink: 0; transition: var(--ease); }
.eo-pill:hover { color: rgba(0,0,0,.9); text-decoration: none !important; }
.eo-pill:hover i { opacity: .9; }
.eo-pill.active {
    background: #fff; color: rgba(0,0,0,.9); font-weight: 600;
    box-shadow: var(--sh-pill);
}
.eo-pill.active i { opacity: 1; }

/* ── Dropdown ───────────────────────────────────────────────────────────── */
.eo-dd { position: relative; display: inline-flex; align-items: center; }
.eo-caret {
    font-size: 9px !important; opacity: .5 !important;
    margin-left: -2px; transition: transform .2s;
}
.eo-dd.open .eo-caret { transform: rotate(180deg); }

.eo-dd-panel {
    display: none;
    position: absolute; top: calc(100% + 8px); left: 0;
    min-width: 230px;
    background: #fff;
    border-radius: var(--r-card);
    border: .5px solid rgba(0,0,0,.1);
    box-shadow: var(--sh-pop);
    padding: var(--sp-2);
    z-index: 9999;
}
.eo-dd-panel.open { display: block; }

.eo-dd-item {
    display: flex; align-items: center; gap: var(--sp-3);
    padding: 10px 14px; border-radius: 9px;
    font-size: var(--fs-ui); font-weight: 500; color: rgba(0,0,0,.75);
    text-decoration: none !important; transition: .12s;
    white-space: nowrap;
}
.eo-dd-item i { width: 16px; text-align: center; font-size: 13px; opacity: .65; flex-shrink: 0; }
.eo-dd-item:hover { background: rgba(0,0,0,.04); color: rgba(0,0,0,.9); text-decoration: none !important; }
.eo-dd-item:hover i { opacity: 1; }
.eo-dd-item.active { background: var(--mod-accent-soft); color: var(--mod-accent-tx); font-weight: 600; }
.eo-dd-item.active i { opacity: 1; }

/* Section labels + separators. The reference has no equivalent (its menus are
   flat); ExamON's Masters menu has 3 groups, so these are defined here in the
   same Apple idiom rather than inventing a second style language. */
.eo-dd-sec {
    padding: var(--sp-3) 14px var(--sp-1);
    font-size: var(--fs-cap); font-weight: 600;
    text-transform: uppercase; letter-spacing: .06em;
    color: var(--mod-ink-3);
}
.eo-dd-sep { height: 1px; background: rgba(0,0,0,.06); margin: var(--sp-2) var(--sp-3); }


/* ═══════════════════════════════════════════════════════════════════════════
   §4  SHELL
   ═══════════════════════════════════════════════════════════════════════════ */
/* Top padding is 20px — the breathing room under the sticky nav. Holiday
   Rules (Exam Rules module) is the reference for "correct": this 20px is its
   ONLY source of top spacing, and the owner confirmed it looks right. Views
   elsewhere that still look like they have too much gap have a SECOND,
   redundant top-spacing source stacked on top of this one (the same disease
   the 2026-08-13 fix already removed from Exam Rules' own views) — fix those
   at the view level, never by changing this shared 20px, or every page that
   is currently correct (Exam Rules) breaks instead. */
.eo-main {
    max-width: var(--shell-w);
    margin: 0 auto;
    padding: var(--sp-6) var(--sp-6) var(--sp-9);
}

/* 2026-08-18: the `eo-wide` full-bleed shell (marks grids, rcard builders,
   analytics reports) was removed — every screen uses this same 1240px shell
   now, no exceptions. `.eo-main`'s max-width above is the ONLY place page
   width is set, for every page. See `$WIDE`'s removal in header.php. */

@media (max-width: 900px) {
    .eo-main { padding-left: var(--sp-5); padding-right: var(--sp-5); }
}
@media (max-width: 640px) {
    .eo-brand a { display: none; }
}


/* ═══════════════════════════════════════════════════════════════════════════
   §5  PAGE FURNITURE — breadcrumb, page head
   ═══════════════════════════════════════════════════════════════════════════ */
/* No top padding — .eo-main owns the space under the nav (see above), so views
   that override this padding inline still get the same gap.
   2026-08-18: 12 form views had grown a stray inline `style="margin-bottom:18px"`
   on this div, giving forms a 24px gap under the breadcrumb vs 8px on every list
   page (see .page-head below) — removed. Never add margin/padding inline on a
   .bcrumb div in a view; this rule is the ONLY place breadcrumb spacing may be
   set, so every add/edit/listing page stays identical by construction. */
/* The last hardcoded survivors of the pre-Apple green theme (#8a978f /
   #5a6b64 / #17302a). On a dark page the trail read as near-invisible
   dark-green-on-black, the current page's own name worst of all. On the ink
   tokens both themes come out of one definition. */
.bcrumb {
    display: flex; align-items: center; gap: var(--sp-3);
    font-size: 12.5px; color: var(--mod-ink-3);
    padding: 0 0 2px;
}
.bcrumb a { color: var(--mod-ink-2); text-decoration: none; font-weight: 400; transition: color .15s; }
.bcrumb a:hover { color: var(--mod-accent-d); }
.bcrumb i { font-size: 9px; opacity: .5; color: currentColor; }
.bcrumb span { color: var(--mod-ink); font-weight: 600; }

.page-head {
    display: flex; align-items: center; justify-content: space-between;
    gap: var(--sp-5); flex-wrap: wrap;
    margin: var(--sp-2) 0 18px;
}
.page-title {
    font-size: var(--fs-h1); font-weight: var(--fw-h1);
    letter-spacing: var(--ls-h1); color: var(--mod-ink);
    line-height: 1.2; margin-bottom: 2px;
}
/* The old theme rendered the second word in maroon. The reference has no
   two-tone title, so the span now inherits. Kept as a selector (not deleted)
   because 58 views still emit the markup. */
.page-title span { color: inherit; }
.page-sub {
    font-size: var(--fs-sm); color: var(--mod-ink-2);
    display: flex; align-items: center; gap: var(--sp-3); margin-top: 2px;
}
.page-title.compact { font-size: 18px; letter-spacing: -.2px; }
.page-title.compact span {
    display: block; font-size: var(--fs-xs); color: var(--mod-ink-2);
    font-weight: 500; margin-top: 3px;
}

.sess-tag {
    display: inline-flex; align-items: center; gap: 5px;
    padding: 3px 10px;
    background: var(--mod-accent-soft); color: var(--mod-accent-tx);
    border: none; border-radius: var(--r-pill);
    font-size: 11.5px; font-weight: 600;
}

hr.sep { border: none; border-top: .5px solid var(--mod-hair); margin: var(--sp-7) 0; }


/* ═══════════════════════════════════════════════════════════════════════════
   §6  BUTTONS
   Flat fills, no gradients, no lift, no coloured glow — the Apple idiom.
   ═══════════════════════════════════════════════════════════════════════════ */
.btn {
    display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
    font-family: var(--font); font-size: var(--fs-body); font-weight: 600;
    padding: 8px 16px;
    border-radius: var(--r-btn);
    border: none; cursor: pointer;
    text-decoration: none !important;
    transition: var(--ease); white-space: nowrap;
}
.btn-primary { background: var(--mod-accent); color: #fff; }
.btn-primary:hover { background: var(--mod-accent-d); color: #fff; }

/* Tokens, not hardcoded rgba(0,0,0,..): these are the Cancel / secondary
   buttons, and a black label on a dark fill was unreadable. */
.btn-ghost { background: var(--mod-fill); color: var(--mod-ink); border: none; }
.btn-ghost:hover { background: var(--mod-fill-h); color: var(--mod-ink); }

/* .fcard2-hdr is no longer a dark bar, so the back button is a light ghost. */
.btn-back {
    display: inline-flex; align-items: center; gap: 7px;
    padding: 8px 14px;
    background: var(--mod-fill); border: none;
    border-radius: var(--r-btn); color: var(--mod-ink-2);
    font-size: var(--fs-sm); font-weight: 500; font-family: var(--font);
    text-decoration: none !important; transition: var(--ease); flex-shrink: 0;
}
.btn-back:hover { background: var(--mod-fill-h); color: var(--mod-ink); }
.btn-back i { font-size: 11px; }

.btn-clr {
    display: inline-flex; align-items: center; gap: var(--sp-2);
    padding: 8px 14px;
    font-size: var(--fs-sm); font-weight: 500; font-family: var(--font);
    color: var(--mod-ink-2); background: transparent; border: none;
    border-radius: var(--r-btn); cursor: pointer;
    transition: background .15s, color .15s;
}
.btn-clr:hover { background: var(--mod-fill); color: var(--mod-ink); }

/* Save-bar pair (marks grids) — aliases onto the same two looks. */
.btn-sec { background: var(--mod-fill); color: var(--mod-ink); border: none; }
.btn-sec:hover { background: var(--mod-fill-h); }
.btn-sv { background: var(--mod-accent); color: #fff; border: none; }
.btn-sv:hover { background: var(--mod-accent-d); color: #fff; }

/* ── Compact row-action button ──────────────────────────────────────────────
   Single definition replacing three that had drifted apart:
   examon_module.css had .btn-setup-marks twice (different padding AND different
   font-weight), and attendance/index.php had .btn-att-action as a fourth copy
   with identical geometry but its own palette.
   The two legacy names are kept as aliases so views keep working; they are
   swapped for .btn-act as each module's views are re-skinned. */
.btn-act,
.btn-setup-marks,
.btn-att-action {
    display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
    height: 30px; padding: 0 14px;
    border-radius: var(--r-xs);
    font-family: var(--font); font-size: var(--fs-xs); font-weight: 600;
    border: none; cursor: pointer; white-space: nowrap;
    text-decoration: none !important; transition: var(--ease);
    /* Accent fill by default — matches the old .btn-setup-marks, which shipped
       blue out of the box. Variant classes below (and the per-screen
       .btn-test-entry / .btn-exam-entry / .btn-setup-pending) override it. */
    background: var(--mod-accent); color: #fff;
}
.btn-act:hover, .btn-setup-marks:hover, .btn-att-action:hover { background: var(--mod-accent-d); color: #fff; }
.btn-act-blue  { background: var(--mod-accent); color: #fff; }
.btn-act-blue:hover  { background: var(--mod-accent-d); color: #fff; }
.btn-act-green { background: var(--mod-green); color: #fff; }
.btn-act-green:hover { background: var(--mod-green-tx); color: #fff; }
.btn-act-amber { background: var(--mod-amber); color: #fff; }
.btn-act-amber:hover { background: var(--mod-amber-tx); color: #fff; }
.btn-act-cyan  { background: var(--mod-teal); color: #fff; }
.btn-act-cyan:hover  { background: var(--mod-teal-tx); color: #fff; }
.btn-act-ghost { background: var(--mod-fill); color: var(--mod-ink-2); }
.btn-act-ghost:hover { background: var(--mod-fill-h); color: var(--mod-ink); }


/* ═══════════════════════════════════════════════════════════════════════════
   §7  DATA DISPLAY
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── KPI stat tiles ─────────────────────────────────────────────────────── */
.stats-row {
    display: grid; grid-template-columns: repeat(4, 1fr);
    gap: var(--sp-5); margin-bottom: var(--sp-7);
}
.stat {
    background: var(--mod-surface);
    border: .5px solid var(--mod-card-line);
    border-radius: var(--r-card);
    box-shadow: var(--sh-card);
    padding: var(--sp-6);
    display: flex; align-items: center; justify-content: space-between;
    position: relative; overflow: hidden;
}
/* Accent rail. Flat fills — the reference has no gradients. */
.stat::before {
    content: ''; position: absolute; top: 0; left: 0;
    width: 3px; height: 100%; border-radius: 3px 0 0 3px;
}
.stat-red::before   { background: var(--mod-danger); }
.stat-blue::before  { background: var(--mod-accent); }
.stat-amber::before { background: var(--mod-amber); }
.stat-green::before { background: var(--mod-green); }

.stat-num {
    font-size: 28px; font-weight: 700; line-height: 1;
    letter-spacing: -.02em; font-variant-numeric: tabular-nums;
    color: var(--mod-ink); margin-bottom: var(--sp-1);
}
.stat-red   .stat-num { color: var(--mod-danger-tx); }
.stat-blue  .stat-num { color: var(--mod-accent-tx); }
.stat-amber .stat-num { color: var(--mod-amber-tx); }
.stat-green .stat-num { color: var(--mod-green-tx); }
.stat-lbl { font-size: var(--fs-sm); font-weight: 500; color: var(--mod-ink-3); }

.stat-icon-wrap {
    width: 44px; height: 44px; border-radius: var(--r-md);
    display: flex; align-items: center; justify-content: center;
    font-size: 19px; flex-shrink: 0;
}
.stat-red   .stat-icon-wrap { background: var(--mod-danger-soft); color: var(--mod-danger-tx); }
.stat-blue  .stat-icon-wrap { background: var(--mod-accent-soft); color: var(--mod-accent-tx); }
.stat-amber .stat-icon-wrap { background: var(--mod-amber-soft);  color: var(--mod-amber-tx); }
.stat-green .stat-icon-wrap { background: var(--mod-green-soft);  color: var(--mod-green-tx); }

/* ── Toolbar ────────────────────────────────────────────────────────────── */
.toolbar { display: flex; align-items: center; gap: var(--sp-3); margin-bottom: 18px; flex-wrap: wrap; }

.search-box { flex: 1; min-width: 220px; max-width: 380px; position: relative; }
.search-box i {
    position: absolute; left: 13px; top: 50%; transform: translateY(-50%);
    color: var(--mod-ink-3); font-size: var(--fs-sm); pointer-events: none;
}
.search-inp {
    width: 100%; height: 36px;
    padding: 6px 12px 6px 36px;
    border: 1px solid rgba(0,0,0,.12);
    border-radius: var(--r-xs);
    font-size: var(--fs-sm); font-family: var(--font);
    color: var(--mod-ink); background: #fff; outline: none;
    transition: border-color .2s, box-shadow .2s;
}
.search-inp:focus { border-color: var(--mod-accent); box-shadow: 0 0 0 3px rgba(0,122,255,.15); }
.search-inp::placeholder { color: var(--mod-ink-3); }

/* Mostly invisible in practice — examon_module.js rewrites select.filter-sel
   into the .csel-* control below. Kept correct for the no-JS path. */
.filter-sel {
    padding: 10px 36px 10px 13px;
    border: 1px solid rgba(0,0,0,.1);
    border-radius: var(--r-btn);
    font-size: var(--fs-sm); font-family: var(--font); font-weight: 500;
    color: var(--mod-ink-2); background-color: #fff;
    outline: none; cursor: pointer; appearance: none; -webkit-appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='11' height='11' viewBox='0 0 24 24' fill='none' stroke='%236b6b6b' stroke-width='2.5' stroke-linecap='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
    background-repeat: no-repeat; background-position: right 12px center;
    transition: border-color .2s, box-shadow .2s;
}
.filter-sel:focus { border-color: var(--mod-accent); box-shadow: var(--sh-ring); outline: none; }

/* ── Table card ─────────────────────────────────────────────────────────── */
.tcard {
    background: var(--mod-surface);
    border: .5px solid var(--mod-card-line);
    border-radius: var(--r-card);
    box-shadow: var(--sh-card);
    overflow: visible;
}
.tcard > :first-child { border-top-left-radius: inherit; border-top-right-radius: inherit; }
.tcard > :last-child  { border-bottom-left-radius: inherit; border-bottom-right-radius: inherit; }

/* The flex row here used to be repeated as an inline style on ~20 views. */
.tcard-top {
    display: flex; align-items: center; justify-content: space-between;
    flex-wrap: wrap; gap: var(--sp-4);
    padding: var(--sp-5) var(--sp-6);
    border-bottom: .5px solid var(--mod-hair);
}
.tcard-title {
    font-size: var(--fs-h3); font-weight: 700; color: var(--mod-ink);
    display: flex; align-items: center; gap: var(--sp-3);
}
.count-pill {
    font-size: var(--fs-xs); font-weight: 600;
    color: var(--mod-accent-tx); background: var(--mod-accent-soft);
    padding: 3px var(--sp-3); border-radius: 12px; border: none;
}

/* ── Table ──────────────────────────────────────────────────────────────── */
table.xtable { width: 100%; border-collapse: collapse; background: transparent; }
table.xtable thead tr { background: transparent; border: none; }
table.xtable thead th {
    text-align: left;
    background: var(--mod-fill);
    padding: 14px var(--sp-5);
    font-size: var(--fs-cap); font-weight: 700;
    color: var(--mod-ink-2);
    text-transform: uppercase; letter-spacing: .5px;
    border: none;
}
table.xtable tbody tr { border: none; transition: background .12s; }
table.xtable tbody td {
    padding: 14px var(--sp-5);
    font-size: var(--fs-sm); color: var(--mod-ink);
    vertical-align: middle;
    border: none; border-bottom: 1px solid var(--mod-hair);
}
table.xtable tbody tr:last-child td { border-bottom: none; }
table.xtable tbody tr:hover td { background: var(--mod-surface-2); }

/* Deactivated rows (status=0) stay visible — never deleted, only hidden —
   so the "All" list view tints them instead of dropping them. Higher
   specificity than the plain :hover rule above, so hovering keeps the tint. */
table.xtable tbody tr[data-s="0"] td { background: var(--mod-danger-soft); }
table.xtable tbody tr[data-s="0"]:hover td { background: var(--mod-danger-soft); }
table.xtable tbody tr[data-s="0"] .subj-name { color: var(--mod-danger-tx); }

/* The row-number cell. Every list view inlined this same three-property rule. */
.xtable-idx { color: var(--mod-ink-3); font-size: var(--fs-xs); font-weight: 600; }

.subj-name { font-weight: 600; color: var(--mod-ink); }
.subj-code {
    font-size: 11.5px; font-family: var(--font-mono);
    background: var(--mod-fill); color: var(--mod-ink-2);
    padding: 3px var(--sp-3); border-radius: 5px; font-weight: 600;
}

/* ── Type badges ────────────────────────────────────────────────────────── */
.tbadge {
    display: inline-flex; align-items: center; gap: 5px;
    padding: 3px var(--sp-3); border-radius: 12px;
    font-size: var(--fs-xs); font-weight: 600;
    border: none;
}
.tbadge i { font-size: 9px; }
.tb-scholastic { background: var(--mod-accent-soft); color: var(--mod-accent-tx); }
.tb-grade      { background: var(--mod-amber-soft);  color: var(--mod-amber-tx); }
.tb-text       { background: var(--mod-purple-soft); color: var(--mod-purple-tx); }
.tb-dropdown   { background: var(--mod-green-soft);  color: var(--mod-green-tx); }

/* ── Status badge (circular icon) ───────────────────────────────────────── */
.status-badge {
    display: inline-flex; align-items: center; justify-content: center;
    width: 28px; height: 28px; border-radius: 50%;
    font-size: var(--fs-sm);
}
.status-active   { background: var(--mod-green-soft);  color: var(--mod-green-tx); }
.status-inactive { background: var(--mod-danger-soft); color: var(--mod-danger-tx); }

/* ── Toggles ────────────────────────────────────────────────────────────── */
.tog { position: relative; width: 38px; height: 21px; cursor: pointer; display: inline-block; }
.tog input { opacity: 0; width: 0; height: 0; position: absolute; }
.tog-track {
    position: absolute; inset: 0; border-radius: 21px;
    background: rgba(120,120,128,.16);   /* iOS off-state */
    transition: background .2s;
}
.tog-track::after {
    content: ''; position: absolute; top: 3px; left: 3px;
    width: 15px; height: 15px; border-radius: 50%;
    background: #fff; transition: transform .22s cubic-bezier(.4,0,.2,1);
    box-shadow: 0 1px 3px rgba(0,0,0,.15);
}
/* Status on/off → green. */
.tog input:checked + .tog-track { background: var(--mod-green); }
.tog input:checked + .tog-track::after { transform: translateX(17px); }

.toggle-row { display: flex; align-items: center; gap: var(--sp-4); padding: 5px 0; }
.toggle-lbl { font-size: var(--fs-body); color: var(--mod-ink); font-weight: 500; }

.tog-form { position: relative; width: 44px; height: 24px; cursor: pointer; display: inline-block; }
.tog-form input { opacity: 0; width: 0; height: 0; position: absolute; }
.tog-form-track {
    position: absolute; inset: 0; border-radius: 24px;
    background: rgba(120,120,128,.16); transition: background .22s;
}
.tog-form-track::after {
    content: ''; position: absolute; top: 3px; left: 3px;
    width: 18px; height: 18px; border-radius: 50%;
    background: #fff; transition: transform .22s cubic-bezier(.4,0,.2,1);
    box-shadow: 0 1px 3px rgba(0,0,0,.15);
}
/* A preference toggle, not a status → accent. */
.tog-form input:checked + .tog-form-track { background: var(--mod-accent); }
.tog-form input:checked + .tog-form-track::after { transform: translateX(20px); }

/* ── Row action icons ───────────────────────────────────────────────────── */
.acts { display: flex; align-items: center; gap: 2px; justify-content: flex-end; }
.act {
    width: 32px; height: 32px; border-radius: var(--r-btn);
    display: flex; align-items: center; justify-content: center;
    font-size: var(--fs-sm); text-decoration: none !important;
    transition: var(--ease); color: var(--mod-ink-3); background: transparent;
    border: none; cursor: pointer; position: relative;
}
.act-v:hover { background: var(--mod-accent-soft); color: var(--mod-accent-tx); }
.act-e:hover { background: var(--mod-amber-soft);  color: var(--mod-amber-tx); }
.act-d:hover { background: var(--mod-danger-soft); color: var(--mod-danger-tx); }
.act-a:hover { background: var(--mod-green-soft);  color: var(--mod-green-tx); }

/* ── Empty state ────────────────────────────────────────────────────────── */
.empty { text-align: center; padding: 60px var(--sp-6); color: var(--mod-ink-3); }
.empty-icon {
    width: 72px; height: 72px; border-radius: 50%;
    background: var(--mod-accent-soft); color: var(--mod-accent-tx);
    display: flex; align-items: center; justify-content: center;
    font-size: 30px; margin: 0 auto 18px;
}
.empty h3 { font-size: var(--fs-h2); font-weight: 700; color: var(--mod-ink); margin-bottom: var(--sp-2); }
.empty p  { font-size: var(--fs-ui); color: var(--mod-ink-2); margin-bottom: var(--sp-6); }

/* ── Pagination bar ─────────────────────────────────────────────────────────
   Ported from the reference kit's DataTables pagination block. Replaces 11
   hand-rolled, fully-inline pagination bars that each hardcoded the same
   #eff6ff / #bfdbfe / #1d4ed8 palette. */
.xpager {
    display: flex; justify-content: space-between; align-items: center;
    flex-wrap: wrap; gap: var(--sp-3);
    padding: var(--sp-5) var(--sp-6);
    border-top: .5px solid var(--mod-hair);
    font-size: var(--fs-sm); color: var(--mod-ink-2);
}
.xpager-info { display: flex; align-items: center; gap: var(--sp-5); flex-wrap: wrap; }
.xpager-rows { display: flex; align-items: center; gap: var(--sp-2); }
.xpager-rows select {
    padding: 3px var(--sp-2); border-radius: 5px;
    border: 1px solid var(--mod-hair); background: #fff;
    font-size: var(--fs-sm); font-family: var(--font); color: var(--mod-ink);
    outline: none; cursor: pointer;
}
.xpager-nav { display: flex; align-items: center; gap: var(--sp-2); }
/* Solid accent fill rather than the reference's outlined pagination buttons —
   these are the page's only navigation control, and the outlined version read
   as disabled next to the solid primary buttons elsewhere on the same screen. */
.xpager-btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 6px;
    padding: 7px 14px;
    border-radius: var(--r-btn);
    border: none;
    background: var(--mod-accent); color: #fff;
    font-family: var(--font); font-size: var(--fs-sm); font-weight: 600;
    line-height: 1;
    cursor: pointer; transition: var(--ease);
}
.xpager-btn i { font-size: 11px; transform: translateY(1px); }
.xpager-btn:hover { background: var(--mod-accent-d); color: #fff; }
.xpager-btn:disabled,
.xpager-btn[disabled] {
    background: var(--mod-fill); color: rgba(0,0,0,.3);
    pointer-events: none;
}

/* ── List active/inactive switch ────────────────────────────────────────────
   Replaces the hand-built track/knob that list views inlined and then
   restyled from JS (subjects/list.php had ~8 inline styles for this alone). */
.tlist-switch { display: inline-flex; align-items: center; gap: var(--sp-2); cursor: pointer; }
.tlist-switch input { display: none; }
.tlist-switch .tls-track {
    position: relative; width: 32px; height: 18px; border-radius: 18px;
    background: var(--mod-green); transition: background .3s; flex-shrink: 0;
}
.tlist-switch .tls-track::after {
    content: ''; position: absolute; top: 2px; left: 2px;
    width: 14px; height: 14px; border-radius: 50%; background: #fff;
    box-shadow: 0 1px 3px rgba(0,0,0,.2);
    transform: translateX(14px); transition: transform .3s;
}
.tlist-switch .tls-lbl { font-size: var(--fs-xs); font-weight: 600; color: var(--mod-green-tx); }
.tlist-switch.is-off .tls-track { background: var(--mod-danger); }
.tlist-switch.is-off .tls-track::after { transform: translateX(0); }
.tlist-switch.is-off .tls-lbl { color: var(--mod-danger-tx); }

/* ── Audit trail / last-updated (rendered by application/helpers/ui_helper.php) ── */
.upd-date { font-size: var(--fs-xs); color: var(--mod-ink-2); font-weight: 500; }
.upd-user { font-size: var(--fs-cap); color: var(--mod-ink-3); display: block; margin-top: 1px; }

/* Sits between .fcard2-body and .fcard2-foot, so it supplies its own margins —
   the horizontal ones match .fcard2-body's padding to keep the left edge lined
   up with the section labels above it. */
.audit-box {
    margin: var(--sp-6) var(--sp-7); padding: var(--sp-5);
    background: var(--mod-surface-2);
    border: .5px solid var(--mod-hair);
    border-radius: var(--r-md);
    display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: var(--sp-5);
}
.audit-cell .ac-lbl {
    font-size: var(--fs-cap); font-weight: 600;
    text-transform: uppercase; letter-spacing: .5px;
    color: var(--mod-ink-3); margin-bottom: 3px;
}
.audit-cell .ac-val { font-size: var(--fs-sm); color: var(--mod-ink); font-weight: 500; }

/* ── Hub cards (module landing pages) ───────────────────────────────────── */
.hubcard {
    display: block; text-decoration: none !important;
    background: var(--mod-surface);
    border: .5px solid var(--mod-card-line);
    border-radius: var(--r-card);
    box-shadow: var(--sh-card);
    padding: var(--sp-6);
    transition: var(--ease);
}
.hubcard:hover { box-shadow: var(--sh-pop); }
.hubcard-ico {
    width: 44px; height: 44px; border-radius: var(--r-md);
    display: flex; align-items: center; justify-content: center;
    font-size: 19px; margin-bottom: var(--sp-4);
    background: var(--mod-accent-soft); color: var(--mod-accent-tx);
}
.hubcard-ico.hc-green  { background: var(--mod-green-soft);  color: var(--mod-green-tx); }
.hubcard-ico.hc-amber  { background: var(--mod-amber-soft);  color: var(--mod-amber-tx); }
.hubcard-ico.hc-purple { background: var(--mod-purple-soft); color: var(--mod-purple-tx); }
.hubcard-ico.hc-teal   { background: var(--mod-teal-soft);   color: var(--mod-teal-tx); }
.hubcard-ico.hc-danger { background: var(--mod-danger-soft); color: var(--mod-danger-tx); }
.hubcard h3 { font-size: var(--fs-h3); font-weight: 700; color: var(--mod-ink); margin-bottom: var(--sp-1); }
.hubcard p  { font-size: var(--fs-sm); color: var(--mod-ink-2); }


/* ═══════════════════════════════════════════════════════════════════════════
   §8  FORMS
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Form card (v1) ─────────────────────────────────────────────────────── */
.fcard {
    background: var(--mod-surface);
    border: .5px solid var(--mod-card-line);
    border-radius: var(--r-card);
    box-shadow: var(--sh-card);
    overflow: hidden;
    max-width: 740px;
}
.fcard-head {
    padding: var(--sp-6) var(--sp-7);
    border-bottom: .5px solid var(--mod-hair);
    display: flex; align-items: center; gap: 14px;
    background: transparent;
}
.fcard-head-icon {
    width: 40px; height: 40px; border-radius: var(--r-md);
    background: var(--mod-accent-soft); color: var(--mod-accent-tx);
    display: flex; align-items: center; justify-content: center;
    font-size: var(--fs-h2);
}
.fcard-head h2 { font-size: var(--fs-h2); font-weight: 700; color: var(--mod-ink); margin-bottom: 2px; }
.fcard-head p  { font-size: 12.5px; color: var(--mod-ink-2); }
.fcard-body { padding: var(--sp-7); }
.fcard-foot {
    padding: 18px var(--sp-7);
    border-top: .5px solid var(--mod-hair);
    display: flex; justify-content: flex-end; gap: var(--sp-3);
    background: transparent;
}

.fgrid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-6); margin-bottom: var(--sp-6); }
.fgrid-3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: var(--sp-6); margin-bottom: var(--sp-6); }
.fgrid-1 { margin-bottom: var(--sp-6); }

/* ── Form card (v2 — the current master-form shell) ─────────────────────── */
.form-page-wrap  { display: flex; justify-content: center; padding: 4px 0 48px; }
.form-page-inner { width: 100%; max-width: 1300px; }

/* 2026-08-18: add/edit forms have no .page-head — the title lives inside
   .fcard2-hdr instead — so .bcrumb itself is the only thing that can supply
   the gap before the card. 12 views were doing this with a duplicated inline
   `style="margin-bottom:18px"` on their own .bcrumb div; removing those
   earlier today (as a "fix" for a different, real bug — an inline override
   inconsistency) collapsed this gap to 2px on every form. Scoped here so
   every current and future .form-page-inner view gets it from one place,
   matching .page-head's own 18px bottom margin used everywhere else. */
.form-page-inner > .bcrumb { margin-bottom: 18px; }

.fcard2 {
    background: var(--mod-surface);
    border: .5px solid var(--mod-card-line);
    border-radius: var(--r-card);
    box-shadow: var(--sh-card);
    overflow: hidden;
}
/* Was a dark maroon gradient bar. Apple cards do not have chrome headers. */
.fcard2-hdr {
    background: transparent;
    padding: var(--sp-6) var(--sp-7);
    border-bottom: .5px solid var(--mod-hair);
    display: flex; align-items: center; justify-content: space-between; gap: var(--sp-4);
}
.fcard2-hdr-left { display: flex; align-items: center; gap: 14px; }
.fcard2-hdr-ico {
    width: 44px; height: 44px; border-radius: var(--r-md);
    background: var(--mod-accent-soft); color: var(--mod-accent-tx);
    border: none;
    display: flex; align-items: center; justify-content: center;
    font-size: 18px; flex-shrink: 0;
}
.fcard2-hdr h2 { font-size: var(--fs-h2); font-weight: 700; color: var(--mod-ink); margin-bottom: 2px; letter-spacing: -.01em; }
.fcard2-hdr p  { font-size: var(--fs-xs); color: var(--mod-ink-2); }
.fcard2-body { padding: var(--sp-7) var(--sp-7) var(--sp-6); }
.fcard2-foot {
    padding: var(--sp-5) var(--sp-7);
    border-top: .5px solid var(--mod-hair);
    background: transparent;
    display: flex; align-items: center; justify-content: space-between; gap: var(--sp-4);
}
.foot-note { font-size: var(--fs-xs); color: var(--mod-ink-3); }
.foot-note .req-star { color: var(--mod-danger); }

/* ── Section label + field grids ────────────────────────────────────────── */
.fsec {
    font-size: var(--fs-cap); font-weight: 700;
    text-transform: uppercase; letter-spacing: .06em;
    color: var(--mod-ink-3); margin-bottom: 14px;
    display: flex; align-items: center; gap: var(--sp-3);
}
.fsec::after { content: ''; flex: 1; height: 1px; background: var(--mod-hair); }

.fg2 { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; margin-bottom: 18px; }
.fg3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 18px; margin-bottom: 18px; }
.fg1 { margin-bottom: 18px; }
.ff  { display: flex; flex-direction: column; }

/* ── Labels + inputs ────────────────────────────────────────────────────── */
.flabel {
    font-size: var(--fs-sm); font-weight: 500;
    color: var(--mod-ink-2);
    text-transform: none; letter-spacing: 0;
    margin-bottom: var(--sp-2);
    display: flex; align-items: center; gap: 5px;
}
.flabel .req { color: var(--mod-danger); font-size: var(--fs-body); line-height: 1; }
.flabel .opt {
    font-size: 10px; color: var(--mod-ink-3); font-weight: 400;
    text-transform: none; letter-spacing: 0;
    background: var(--mod-fill); padding: 1px var(--sp-2); border-radius: 4px;
}

.finput, .fselect {
    width: 100%;
    padding: 10px 12px;
    background: #fff;
    border: 1px solid rgba(0,0,0,.1);
    border-radius: var(--r-btn);
    font-size: var(--fs-body); font-family: var(--font);
    color: var(--mod-ink); outline: none;
    -webkit-appearance: none; appearance: none;
    box-shadow: inset 0 1px 2px rgba(0,0,0,.02);
    transition: border-color .2s, box-shadow .2s;
}
.finput:focus, .fselect:focus { border-color: var(--mod-accent); box-shadow: var(--sh-ring); }
.finput::placeholder { color: var(--mod-ink-3); }
.fselect:disabled { background: var(--mod-surface-2); color: var(--mod-ink-3); cursor: not-allowed; }
.field-hint { font-size: var(--fs-cap); color: var(--mod-ink-3); margin-top: 5px; }

/* Small stacked label used by the assign / settings / analytics filter rows. */
.s-label {
    display: block; margin-bottom: var(--sp-1);
    font-size: var(--fs-cap); font-weight: 600;
    text-transform: uppercase; letter-spacing: .5px;
    color: var(--mod-ink-3);
}

/* ── Custom select engine ───────────────────────────────────────────────────
   examon_module.js hides every select.finput / .fselect / .filter-sel and
   renders this control in its place. THE VISIBLE CONTROL IS .csel-trigger —
   styling the <select> alone has no effect on screen. */
.csel-wrap { position: relative; width: 100%; display: inline-block; vertical-align: middle; }
.csel-wrap.csel-filter { width: auto; min-width: 160px; }
.csel-hidden { display: none !important; }

.csel-wrap .csel-trigger {
    width: 100%; height: 100%; min-height: 40px;
    display: flex; align-items: center; justify-content: space-between;
    padding: 10px 12px;
    background: #fff;
    border: 1px solid rgba(0,0,0,.1);
    border-radius: var(--r-btn);
    font-family: var(--font); font-size: var(--fs-body); font-weight: 400;
    color: var(--mod-ink);
    box-shadow: inset 0 1px 2px rgba(0,0,0,.02);
    cursor: pointer;
    transition: border-color .2s, box-shadow .2s;
    user-select: none; -webkit-user-select: none;
}
.csel-wrap .csel-trigger:hover { border-color: rgba(0,0,0,.2); }
/* Apple dropdowns float clear of the trigger, so the menu no longer joins it
   and the trigger keeps its full radius when open. */
.csel-wrap .csel-trigger.open {
    border-color: var(--mod-accent);
    box-shadow: var(--sh-ring);
    border-radius: var(--r-btn);
}
.csel-wrap .csel-trigger .csel-val {
    flex: 1; text-align: left;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.csel-wrap .csel-chevron {
    width: auto; height: auto;
    display: flex; align-items: center; justify-content: center;
    background: transparent; border: none;
    color: var(--mod-ink-3); font-size: 10px;
    transition: transform .22s ease, color .15s;
    flex-shrink: 0; margin-left: var(--sp-3);
}
.csel-wrap .csel-trigger.open .csel-chevron { transform: rotate(180deg); color: var(--mod-accent-tx); }

.csel-wrap .csel-menu {
    display: none;
    position: absolute; top: calc(100% + 6px); left: 0; right: 0;
    background: #fff;
    border: .5px solid rgba(0,0,0,.1);
    border-radius: var(--r-card);
    box-shadow: var(--sh-pop);
    padding: var(--sp-2);
    z-index: 1050;
    max-height: 280px; overflow-y: auto;
}
.csel-wrap .csel-menu.open { display: block; }

/* "Dropup" — when there isn't room below the trigger (e.g. a field low in a
   tall form), examon_module.js adds this class and the menu opens upward
   instead, same as a native <select> would reposition itself. */
.csel-wrap.csel-drop-up .csel-menu { top: auto; bottom: calc(100% + 6px); }
.csel-wrap .csel-menu::-webkit-scrollbar { width: 4px; }
.csel-wrap .csel-menu::-webkit-scrollbar-track { background: transparent; }
.csel-wrap .csel-menu::-webkit-scrollbar-thumb { background: var(--mod-hair); border-radius: 4px; }

.csel-wrap .csel-opt {
    display: flex; align-items: center; justify-content: space-between;
    padding: 10px 14px;
    border: none; border-radius: 9px;
    font-family: var(--font); font-size: var(--fs-ui); font-weight: 500;
    color: rgba(0,0,0,.75);
    cursor: pointer; transition: background .12s;
}
.csel-wrap .csel-opt:hover { background: rgba(0,0,0,.04); color: rgba(0,0,0,.9); }
.csel-wrap .csel-opt.selected {
    background: var(--mod-accent-soft); color: var(--mod-accent-tx); font-weight: 600;
}
.csel-wrap .csel-opt .csel-check { color: var(--mod-accent-tx); font-size: var(--fs-sm); opacity: 0; flex-shrink: 0; }
.csel-wrap .csel-opt.selected .csel-check { opacity: 1; }

.csel-wrap.disabled .csel-trigger {
    background: var(--mod-surface-2) !important;
    color: var(--mod-ink-3) !important;
    cursor: not-allowed !important;
    border-color: var(--mod-hair) !important;
    box-shadow: none !important;
    pointer-events: none !important;
}

/* ── Radio "cards" ──────────────────────────────────────────────────────── */
.status-cards { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-4); }
.scard { position: relative; }
.scard input[type="radio"], .scard input[type="checkbox"] { position: absolute; opacity: 0; width: 0; height: 0; }
.scard-lbl {
    display: flex; align-items: center; gap: var(--sp-4);
    padding: 13px var(--sp-5);
    border: 1px solid var(--mod-hair);
    border-radius: var(--r-md);
    cursor: pointer; transition: var(--ease);
}
.scard-lbl:hover { border-color: rgba(0,0,0,.2); background: var(--mod-surface-2); }
.scard input:checked + .scard-lbl { border-color: var(--mod-accent); background: var(--mod-accent-soft); }
.scard-ico {
    width: 34px; height: 34px; border-radius: var(--r-btn);
    background: var(--mod-fill); color: var(--mod-ink-3);
    display: flex; align-items: center; justify-content: center;
    font-size: var(--fs-h3); flex-shrink: 0; transition: var(--ease);
}
.scard input:checked + .scard-lbl .scard-ico { background: var(--mod-accent-soft); color: var(--mod-accent-tx); }
.scard-title { font-size: var(--fs-body); font-weight: 600; color: var(--mod-ink); margin-bottom: 1px; }
.scard-sub   { font-size: 11.5px; color: var(--mod-ink-3); }
.scard input:checked + .scard-lbl .scard-title { color: var(--mod-accent-tx); }

/* Green variant — "include in calculation / annual" */
.gcard input:checked + .scard-lbl { border-color: var(--mod-green); background: var(--mod-green-soft); }
.gcard input:checked + .scard-lbl .scard-ico { background: var(--mod-green-soft); color: var(--mod-green-tx); }
.gcard input:checked + .scard-lbl .scard-title { color: var(--mod-green-tx); }

/* Blue variant — scholastic / parent-head. Same as the base now that the
   accent IS blue; kept so existing markup keeps resolving. */
.bcard input:checked + .scard-lbl { border-color: var(--mod-accent); background: var(--mod-accent-soft); }
.bcard input:checked + .scard-lbl .scard-ico { background: var(--mod-accent-soft); color: var(--mod-accent-tx); }
.bcard input:checked + .scard-lbl .scard-title { color: var(--mod-accent-tx); }

/* ── Alerts ─────────────────────────────────────────────────────────────── */
.alert {
    display: flex; align-items: flex-start; gap: var(--sp-3);
    padding: var(--sp-4) var(--sp-5);
    border-radius: var(--r-card);
    font-size: var(--fs-ui); font-weight: 600;
    margin-bottom: var(--sp-5);
    border: none;
}
.alert i { margin-top: 1px; flex-shrink: 0; }
.alert-ok  { background: var(--mod-green-soft);  color: var(--mod-green-tx); }
.alert-err { background: var(--mod-danger-soft); color: var(--mod-danger-tx); }

@media (max-width: 900px) {
    .stats-row { grid-template-columns: 1fr 1fr; }
    .fgrid-2, .fgrid-3, .fg2, .fg3 { grid-template-columns: 1fr; }
}


/* ═══════════════════════════════════════════════════════════════════════════
   §9  OVERLAYS — modal + SweetAlert skin
   ═══════════════════════════════════════════════════════════════════════════ */
.modal {
    display: none; position: fixed; z-index: 1060; inset: 0;
    width: 100%; height: 100%; overflow: auto;
    background-color: rgba(0,0,0,.28);
    -webkit-backdrop-filter: blur(20px) saturate(180%);
    backdrop-filter: blur(20px) saturate(180%);
    align-items: center; justify-content: center;
}
.modal.show { display: flex; }
.modal-dialog {
    position: relative; width: 100%; margin: var(--sp-6);
    animation: modalfadeIn .18s cubic-bezier(.2,.8,.2,1) both;
}
.modal-content {
    background: #fff;
    border-radius: var(--r-lg);
    box-shadow: var(--sh-modal);
    overflow: hidden;
}
@keyframes modalfadeIn {
    from { opacity: 0; transform: translateY(-6px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* SweetAlert2 skin — used by window.examonToast and the confirm dialogs. */
.modern-swal-popup {
    border-radius: var(--r-lg) !important;
    box-shadow: var(--sh-modal) !important;
    font-family: var(--font) !important;
}
.modern-swal-title { font-size: var(--fs-h2) !important; font-weight: 700 !important; color: var(--mod-ink) !important; }
.modern-swal-html  { font-size: var(--fs-body) !important; color: var(--mod-ink-2) !important; }
/* These dialogs are confirm-before-destroy prompts, so the icon stays a warning
   colour even though the default button is the accent. */
.modern-swal-icon  { color: var(--mod-danger) !important; border-color: var(--mod-danger-soft) !important; }
.modern-swal-btn {
    border-radius: var(--r-btn) !important;
    font-family: var(--font) !important; font-size: var(--fs-body) !important; font-weight: 600 !important;
    padding: 8px 16px !important; box-shadow: none !important;
    background: var(--mod-accent) !important; color: #fff !important;
}
.modern-swal-btn:hover { background: var(--mod-accent-d) !important; }
.modern-swal-btn-cancel {
    background: var(--mod-fill) !important; color: rgba(0,0,0,.8) !important;
}
.modern-swal-btn-cancel:hover { background: var(--mod-fill-h) !important; }

.swal2-toast {
    border-radius: var(--r-card) !important;
    box-shadow: var(--sh-pop) !important;
    font-family: var(--font) !important;
}
.swal2-timer-progress-bar { background: var(--mod-accent) !important; }

/* ═══════════════════════════════════════════════════════════════════════════
   §10  DARK THEME — shared component overrides
   These components hardcode #fff / rgba(0,0,0,..) instead of the --mod-*
   tokens (built before the token system existed, like the nav in §1b), so
   the root variable flip in §1b doesn't reach them. Every one of these
   renders on nearly every page (inputs, the custom select, pagination,
   modals, SweetAlert), so fixing them here — rather than per-module — is
   what actually makes the shared UI kit dark-mode-correct everywhere.
   ═══════════════════════════════════════════════════════════════════════════ */
:root[data-theme="dark"] .search-inp,
:root[data-theme="dark"] .filter-sel,
:root[data-theme="dark"] .xpager-rows select,
:root[data-theme="dark"] .finput,
:root[data-theme="dark"] .fselect,
:root[data-theme="dark"] .csel-wrap .csel-trigger,
:root[data-theme="dark"] .csel-wrap .csel-menu {
    background: var(--mod-surface);
    border-color: rgba(255,255,255,.14);
    color: var(--mod-ink);
}
:root[data-theme="dark"] .csel-wrap .csel-trigger:hover { border-color: rgba(255,255,255,.24); }
:root[data-theme="dark"] .csel-wrap .csel-opt { color: rgba(255,255,255,.82); }
:root[data-theme="dark"] .csel-wrap .csel-opt:hover { background: rgba(255,255,255,.06); color: rgba(255,255,255,.95); }
:root[data-theme="dark"] .xpager-btn:disabled,
:root[data-theme="dark"] .xpager-btn[disabled] { color: rgba(255,255,255,.32); }
:root[data-theme="dark"] .scard-lbl:hover { border-color: rgba(255,255,255,.24); }
:root[data-theme="dark"] .modal-content,
:root[data-theme="dark"] .swal2-popup {
    background: var(--mod-surface) !important;
    color: var(--mod-ink);
}
:root[data-theme="dark"] .modern-swal-btn-cancel { color: rgba(255,255,255,.85) !important; }
