/* ==========================================================================
   EXAMI DESIGN SYSTEM  —  public/css/exami.css
   --------------------------------------------------------------------------
   ONE canonical, hand-authored stylesheet. No build step, no npm, no Vite:
   production is Hostinger shared hosting and the deploy is a file copy, so
   this file is served as a plain static asset (`asset('css/exami.css')`).

   LOAD ORDER MATTERS. Every layout loads Bootstrap 5 first and this file
   second, because §6 below deliberately overrides Bootstrap's defaults so
   the existing Bootstrap markup across ~90 blade views inherits the new
   design system without being rewritten.

   Contents
     1. Font face (self-hosted Inter variable)
     2. Design tokens (:root)
     3. Reset + base elements
     4. Typography scale
     5. Layout primitives (container, section, grid, stack)
     6. Bootstrap 5 de-Bootstrapping overrides
     7. Components (.ex-*)
     8. Public site shell (header, nav, footer)
     9. Decorative, photo-free visual system (CSS/SVG motifs)
    9b. Public marketing page composition kit (hero, timelines, schedule, …)
    10. .app-shell — dense enterprise dashboard scope
    11. Utilities
    12. Reduced motion + print
   ========================================================================== */


/* ==========================================================================
   1. FONT — Inter, self-hosted variable woff2
   --------------------------------------------------------------------------
   Self-hosted rather than Google-Fonts-CDN: no third-party request, no
   render-blocking DNS+TLS to a foreign host on Indian mobile networks, and
   it keeps working if fonts.gstatic.com is slow or blocked. Two files,
   ~133 KB total, variable weight 100-900 so all five weights cost nothing
   extra. `font-display: swap` so text paints immediately in the fallback.
   ========================================================================== */

@font-face {
    font-family: 'Inter';
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url('../fonts/inter-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
        U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191,
        U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'Inter';
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url('../fonts/inter-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
        U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
        U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}


/* ==========================================================================
   2. DESIGN TOKENS
   ========================================================================== */

:root {
    /* ---- Brand palette (fixed, agreed values) ---------------------------- */
    --navy: #0B1F3A;
    --blue: #155EEF;
    --cyan: #00B8D9;
    --success: #16A34A;
    --warning: #F59E0B;
    --danger: #DC2626;
    --bg: #F7F9FC;
    --surface: #FFFFFF;
    --text: #111827;
    --muted: #667085;
    --border: #E4E7EC;

    /* ---- Derived: navy ramp + tints -------------------------------------- */
    --navy-900: #06121F;
    --navy-800: #081829;
    --navy-700: #123055;
    --navy-600: #1A4272;
    --navy-500: #24568F;
    --navy-300: #7B93B2;
    --navy-100: #D6DEE8;
    --navy-50: #EEF2F7;
    --navy-tint-4: rgba(11, 31, 58, .04);
    --navy-tint-8: rgba(11, 31, 58, .08);
    --navy-tint-12: rgba(11, 31, 58, .12);
    --navy-tint-24: rgba(11, 31, 58, .24);

    /* ---- Derived: blue ramp ---------------------------------------------- */
    --blue-900: #0A2E7D;
    --blue-800: #0C3B9E;
    --blue-700: #0F49C4;
    --blue-600: #1355DA;
    --blue-400: #4A82F3;
    --blue-300: #86AAF7;
    --blue-200: #BDD1FB;
    --blue-100: #DCE7FE;
    --blue-50: #EEF4FF;
    --blue-tint-8: rgba(21, 94, 239, .08);
    --blue-tint-16: rgba(21, 94, 239, .16);

    /* ---- Derived: cyan / status ------------------------------------------ */
    --cyan-700: #008DA6;
    --cyan-600: #00A3BF;
    --cyan-200: #9BE6F2;
    --cyan-50: #E6F8FC;

    --success-700: #15803D;
    --success-200: #A6E9BF;
    --success-50: #ECFDF3;

    --warning-700: #B45309;
    --warning-200: #FCDE9B;
    --warning-50: #FFFAEB;

    --danger-700: #B42318;
    --danger-200: #F6BAB5;
    --danger-50: #FEF3F2;

    /* ---- Derived: neutrals ------------------------------------------------ */
    --surface-2: #F1F5F9;
    --surface-3: #E8EDF4;
    --border-strong: #D0D5DD;
    --border-subtle: #EFF2F6;
    --text-2: #344054;
    /* DECORATIVE ONLY — 3.06:1 on white, i.e. below WCAG AA for text. Use it for
       placeholders, disabled affordances and inert icons (all AA-exempt). Any
       text that carries meaning uses --muted (4.97:1 on white, 4.72:1 on --bg). */
    --muted-2: #8A94A6;
    --on-dark: #FFFFFF;
    --on-dark-muted: #B4C4DA;
    --on-dark-border: rgba(255, 255, 255, .14);

    /* ---- Typography ------------------------------------------------------- */
    --font-sans: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
    --font-mono: ui-monospace, 'SFMono-Regular', 'Cascadia Mono', Consolas, 'Liberation Mono', monospace;

    /* Fluid scale. H1 30-36 mobile / 36-42 tablet / 48-64 desktop. */
    --fs-h1: clamp(1.875rem, 1.15rem + 3vw, 4rem);
    --fs-h2: clamp(1.75rem, 1.1rem + 1.9vw, 2.75rem);
    --fs-h3: clamp(1.3125rem, 1.05rem + .72vw, 1.875rem);
    --fs-h4: clamp(1.125rem, 1.03rem + .3vw, 1.375rem);
    --fs-h5: clamp(1rem, .97rem + .18vw, 1.125rem);
    --fs-lead: clamp(1.0625rem, 1rem + .38vw, 1.3125rem);
    --fs-body: clamp(1rem, .96rem + .16vw, 1.125rem);
    --fs-sm: clamp(.8125rem, .795rem + .09vw, .875rem);
    --fs-xs: .75rem;
    --fs-eyebrow: .75rem;
    --fs-display: clamp(2.5rem, 1.4rem + 4.4vw, 5rem);

    --lh-tight: 1.1;
    --lh-heading: 1.16;
    --lh-snug: 1.35;
    --lh-body: 1.62;
    --lh-relaxed: 1.72;

    --fw-regular: 400;
    --fw-medium: 500;
    --fw-semibold: 600;
    --fw-bold: 700;
    --fw-extrabold: 800;

    --tracking-tight: -.022em;
    --tracking-snug: -.012em;
    --tracking-wide: .06em;
    --tracking-eyebrow: .13em;

    /* ---- Spacing ramp (4px base) ------------------------------------------ */
    --sp-0: 0;
    --sp-1: .25rem;   /*  4 */
    --sp-2: .5rem;    /*  8 */
    --sp-3: .75rem;   /* 12 */
    --sp-4: 1rem;     /* 16 */
    --sp-5: 1.25rem;  /* 20 */
    --sp-6: 1.5rem;   /* 24 */
    --sp-7: 2rem;     /* 32 */
    --sp-8: 2.5rem;   /* 40 */
    --sp-9: 3rem;     /* 48 */
    --sp-10: 4rem;    /* 64 */
    --sp-11: 5rem;    /* 80 */
    --sp-12: 6rem;    /* 96 */
    --sp-13: 7.5rem;  /* 120 */

    /* ---- Radius ----------------------------------------------------------- */
    --r-xs: 6px;
    --r-sm: 8px;    /* inputs (8-12) */
    --r-md: 12px;   /* buttons (10-12) */
    --r-lg: 16px;   /* cards (16-24) */
    --r-xl: 20px;
    --r-2xl: 24px;
    --r-3xl: 32px;
    --r-pill: 999px;

    /* ---- Shadows — deliberately restrained ------------------------------- */
    --shadow-xs: 0 1px 2px rgba(11, 31, 58, .05);
    --shadow-sm: 0 1px 3px rgba(11, 31, 58, .06), 0 1px 2px rgba(11, 31, 58, .04);
    --shadow-md: 0 4px 12px rgba(11, 31, 58, .06), 0 1px 3px rgba(11, 31, 58, .04);
    --shadow-lg: 0 12px 28px rgba(11, 31, 58, .08), 0 3px 8px rgba(11, 31, 58, .04);
    --shadow-xl: 0 24px 48px rgba(11, 31, 58, .10), 0 6px 12px rgba(11, 31, 58, .04);
    --shadow-header: 0 1px 2px rgba(11, 31, 58, .04);
    --shadow-header-compact: 0 2px 12px rgba(11, 31, 58, .07);
    --shadow-inset-top: inset 0 1px 0 rgba(255, 255, 255, .06);

    /* ---- Layout ----------------------------------------------------------- */
    --container: 1240px;
    --container-narrow: 880px;
    --container-pad: clamp(1rem, 3.5vw, 2rem);
    --section-y: clamp(3rem, 6.5vw, 7rem);      /* 48 -> 112 */
    --section-y-sm: clamp(2rem, 4vw, 4rem);
    --header-h: 78px;
    --header-h-compact: 62px;
    --sidebar-w: 258px;

    /* ---- Breakpoints (documentation; CSS media queries hard-code these) --- */
    --bp-sm: 576px;
    --bp-md: 768px;
    --bp-lg: 992px;
    --bp-xl: 1200px;
    --bp-2xl: 1400px;

    /* ---- Motion ----------------------------------------------------------- */
    --ease: cubic-bezier(.4, 0, .2, 1);
    --ease-out: cubic-bezier(.16, 1, .3, 1);
    --dur-fast: .14s;
    --dur: .22s;
    --dur-slow: .38s;

    /* ---- Focus ------------------------------------------------------------ */
    --focus-color: var(--blue);
    --focus-ring: 0 0 0 3px rgba(21, 94, 239, .32);
    --focus-ring-on-dark: 0 0 0 3px rgba(255, 255, 255, .55);
    --focus-outline: 2px solid var(--blue);
    --focus-offset: 2px;

    /* ---- Z-index ---------------------------------------------------------- */
    --z-header: 1030;
    --z-drawer: 1055;
    --z-backdrop: 1050;
    --z-toast: 1080;

    /* ---- Glass surfaces (§9b hero compositions over the dark mesh) -------- */
    --glass-bg: rgba(255, 255, 255, .10);
    --glass-bg-strong: rgba(255, 255, 255, .16);
    --glass-border: rgba(255, 255, 255, .18);
    --glass-blur: 14px;
    /* A deeper float shadow than --shadow-xl: the hero cards sit on navy, where
       the light-surface shadows are invisible. */
    --shadow-float: 0 18px 40px rgba(6, 18, 31, .34), 0 4px 12px rgba(6, 18, 31, .22);
}


/* ==========================================================================
   3. RESET + BASE
   ========================================================================== */

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

html {
    -webkit-text-size-adjust: 100%;
    scroll-behavior: smooth;
    /* Anchor targets clear the sticky header. */
    scroll-padding-top: calc(var(--header-h) + var(--sp-4));
}

body {
    margin: 0;
    /* Bootstrap sets these too; we win on load order. */
    font-family: var(--font-sans);
    font-size: var(--fs-body);
    line-height: var(--lh-body);
    font-weight: var(--fw-regular);
    color: var(--text);
    background-color: var(--surface);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    font-feature-settings: 'cv05' 1, 'ss03' 1;
    /*
     | Nothing in this design system may cause a sideways scrollbar. `clip`
     | rather than `hidden` on purpose: `hidden` turns <body> into a scroll
     | container, which silently breaks `position: sticky` on the header and
     | on the portal topbars. `clip` crops without creating one.
     */
    overflow-x: clip;
    overflow-y: visible;
}
@supports not (overflow: clip) {
    body { overflow-x: hidden; }
}

img, svg, video, canvas { max-width: 100%; }
img, video { height: auto; }

hr {
    border: 0;
    border-top: 1px solid var(--border);
    opacity: 1;
    margin: var(--sp-6) 0;
}

::selection { background: var(--blue-100); color: var(--navy); }

/* One global, visible focus treatment. Keyboard-only via :focus-visible so
   mouse clicks never show a ring, but keyboard users always do. */
:focus-visible {
    outline: var(--focus-outline);
    outline-offset: var(--focus-offset);
    border-radius: var(--r-xs);
}
.ex-on-dark :focus-visible,
.ex-dark :focus-visible { outline-color: #fff; }


/* ==========================================================================
   4. TYPOGRAPHY
   ========================================================================== */

h1, h2, h3, h4, h5, h6,
.ex-h1, .ex-h2, .ex-h3, .ex-h4, .ex-h5 {
    margin: 0 0 var(--sp-4);
    color: var(--navy);
    font-weight: var(--fw-bold);
    line-height: var(--lh-heading);
    letter-spacing: var(--tracking-snug);
    text-wrap: balance;
}

h1, .ex-h1 {
    font-size: var(--fs-h1);
    font-weight: var(--fw-extrabold);
    line-height: var(--lh-tight);
    letter-spacing: var(--tracking-tight);
}
h2, .ex-h2 {
    font-size: var(--fs-h2);
    font-weight: var(--fw-bold);
    line-height: 1.14;
    letter-spacing: var(--tracking-tight);
}
h3, .ex-h3 { font-size: var(--fs-h3); }
h4, .ex-h4 { font-size: var(--fs-h4); font-weight: var(--fw-semibold); }
h5, .ex-h5 { font-size: var(--fs-h5); font-weight: var(--fw-semibold); }
h6 { font-size: var(--fs-sm); font-weight: var(--fw-semibold); }

.ex-display {
    font-size: var(--fs-display);
    font-weight: var(--fw-extrabold);
    line-height: 1.02;
    letter-spacing: -.03em;
    color: var(--navy);
}

p { margin: 0 0 var(--sp-4); }
p:last-child { margin-bottom: 0; }

.ex-lead {
    font-size: var(--fs-lead);
    line-height: var(--lh-snug);
    color: var(--muted);
    font-weight: var(--fw-regular);
    text-wrap: pretty;
}

.ex-body-lg { font-size: var(--fs-lead); line-height: var(--lh-body); }
.ex-small, small { font-size: var(--fs-sm); line-height: 1.5; }
.ex-xs { font-size: var(--fs-xs); line-height: 1.45; }
.ex-muted { color: var(--muted); }
.ex-mono { font-family: var(--font-mono); font-size: .92em; letter-spacing: 0; }

/* Numerals in tables/stats line up column-to-column. */
.ex-tnum, table td, table th, .ex-stat__value { font-variant-numeric: tabular-nums; }

.ex-eyebrow {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    margin: 0 0 var(--sp-3);
    font-size: var(--fs-eyebrow);
    font-weight: var(--fw-bold);
    letter-spacing: var(--tracking-eyebrow);
    text-transform: uppercase;
    color: var(--blue);
    line-height: 1;
}
.ex-eyebrow::before {
    content: '';
    width: 22px;
    height: 2px;
    background: linear-gradient(90deg, var(--blue), var(--cyan));
    border-radius: 2px;
    flex: none;
}
.ex-eyebrow--plain::before { display: none; }
.ex-on-dark .ex-eyebrow { color: var(--cyan-200); }
.ex-on-dark .ex-eyebrow::before { background: linear-gradient(90deg, var(--cyan), transparent); }

a {
    color: var(--blue);
    text-decoration: none;
    transition: color var(--dur) var(--ease);
}
a:hover { color: var(--blue-700); }
.ex-link {
    color: var(--blue);
    font-weight: var(--fw-semibold);
    text-decoration: none;
    background-image: linear-gradient(currentColor, currentColor);
    background-size: 0 1.5px;
    background-repeat: no-repeat;
    background-position: 0 100%;
    transition: background-size var(--dur) var(--ease), color var(--dur) var(--ease);
}
.ex-link:hover { background-size: 100% 1.5px; }
/* A link that IS the whole list item is navigation, not prose, so WCAG 2.2's
   inline-link exemption does not cover it. Give those a real touch target on
   small screens; links inside a sentence keep their natural 20px line box. */
@media (max-width: 767.98px) {
    li > .ex-link:only-child { display: inline-flex; align-items: center; min-height: 40px; }
}

.ex-on-dark { color: var(--on-dark-muted); }
.ex-on-dark h1, .ex-on-dark h2, .ex-on-dark h3,
.ex-on-dark h4, .ex-on-dark h5, .ex-on-dark h6,
.ex-on-dark .ex-h1, .ex-on-dark .ex-h2, .ex-on-dark .ex-h3,
.ex-on-dark .ex-display { color: #fff; }
.ex-on-dark .ex-lead, .ex-on-dark .ex-muted { color: var(--on-dark-muted); }
/* Plain links on a dark surface go white — but NOT buttons. `.ex-on-dark a` is
   (0,1,1) and beat `.ex-btn--on-dark` (0,1,0), which paints a white background:
   the hero's primary CTA was rendering white-on-white. Each .ex-btn variant owns
   its own foreground, so exclude them here rather than escalating specificity. */
.ex-on-dark a:not(.ex-btn) { color: var(--on-dark); }
.ex-on-dark hr { border-top-color: var(--on-dark-border); }

/* Bulleted feature list with a drawn check — no icon font dependency. */
.ex-check-list { list-style: none; margin: 0; padding: 0; }
.ex-check-list > li {
    position: relative;
    padding-left: 2rem;
    margin-bottom: var(--sp-3);
    line-height: var(--lh-snug);
}
.ex-check-list > li::before {
    content: '';
    position: absolute;
    left: 0;
    top: .18em;
    width: 1.25rem;
    height: 1.25rem;
    border-radius: var(--r-pill);
    background: var(--blue-50) center / .7rem .7rem no-repeat;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23155EEF' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
}
.ex-on-dark .ex-check-list > li::before {
    background-color: rgba(0, 184, 217, .18);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2300B8D9' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
}


/* ==========================================================================
   5. LAYOUT PRIMITIVES
   ========================================================================== */

.ex-container {
    width: 100%;
    max-width: var(--container);
    margin-inline: auto;
    padding-inline: var(--container-pad);
}
.ex-container--narrow { max-width: var(--container-narrow); }
.ex-container--wide { max-width: 1440px; }

.ex-section { padding-block: var(--section-y); }
.ex-section--sm { padding-block: var(--section-y-sm); }
.ex-section--flush-top { padding-top: 0; }
.ex-section--flush-bottom { padding-bottom: 0; }
.ex-section--bg { background: var(--bg); }
.ex-section--surface2 { background: var(--surface-2); }
.ex-section--dark { background: var(--navy); color: var(--on-dark-muted); }

/* Auto-fit card grid: pass the minimum track width. */
.ex-grid {
    display: grid;
    gap: var(--sp-6);
    grid-template-columns: repeat(auto-fit, minmax(min(var(--ex-grid-min, 260px), 100%), 1fr));
}
.ex-grid--2 { --ex-grid-min: 420px; }
.ex-grid--3 { --ex-grid-min: 300px; }
.ex-grid--4 { --ex-grid-min: 220px; }
.ex-grid--tight { gap: var(--sp-4); }

.ex-stack { display: flex; flex-direction: column; gap: var(--sp-4); }
.ex-cluster { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3); }
.ex-measure { max-width: 62ch; }
.ex-measure-sm { max-width: 46ch; }
.ex-center { margin-inline: auto; text-align: center; }

/* Wide content scrolls inside itself, never the page. */
.ex-scroll-x {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
}


/* ==========================================================================
   6. BOOTSTRAP 5 OVERRIDES
   --------------------------------------------------------------------------
   Bootstrap is kept for its grid, utility classes and three JS behaviours
   already wired into ~90 existing views (modal, dropdown, collapse). What is
   NOT kept is its look: everything below re-skins the components Bootstrap
   renders so that legacy markup reads as EXAMI, not as a Bootstrap template.
   Later agents may keep using .row/.col-* freely.
   ========================================================================== */

:root {
    /* Re-point Bootstrap's own CSS variables at our tokens where possible. */
    --bs-body-font-family: var(--font-sans);
    --bs-body-color: var(--text);
    --bs-body-bg: var(--surface);
    --bs-border-color: var(--border);
    --bs-border-radius: var(--r-md);
    --bs-primary: #155EEF;
    --bs-primary-rgb: 21, 94, 239;
    --bs-link-color: #155EEF;
    --bs-link-color-rgb: 21, 94, 239;
    --bs-link-hover-color: #0F49C4;
    --bs-secondary-color: var(--muted);
    --bs-heading-color: var(--navy);
    --bs-font-sans-serif: var(--font-sans);
}

/* ---- Buttons ------------------------------------------------------------ */
.btn {
    --bs-btn-border-radius: var(--r-md);
    --bs-btn-font-weight: var(--fw-semibold);
    --bs-btn-padding-y: .625rem;
    --bs-btn-padding-x: 1.15rem;
    --bs-btn-font-size: .9375rem;
    border-radius: var(--r-md);
    font-weight: var(--fw-semibold);
    letter-spacing: -.005em;
    transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease),
                color var(--dur) var(--ease), box-shadow var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.btn:focus-visible { box-shadow: var(--focus-ring); }
.btn-lg { --bs-btn-padding-y: .8125rem; --bs-btn-padding-x: 1.5rem; --bs-btn-font-size: 1rem; }
.btn-sm { --bs-btn-padding-y: .4rem; --bs-btn-padding-x: .8rem; --bs-btn-font-size: .8125rem; border-radius: var(--r-sm); }

.btn-primary {
    --bs-btn-bg: var(--blue); --bs-btn-border-color: var(--blue);
    --bs-btn-hover-bg: var(--blue-700); --bs-btn-hover-border-color: var(--blue-700);
    --bs-btn-active-bg: var(--blue-800); --bs-btn-active-border-color: var(--blue-800);
    --bs-btn-disabled-bg: var(--blue-300); --bs-btn-disabled-border-color: var(--blue-300);
}
.btn-secondary {
    --bs-btn-bg: var(--surface); --bs-btn-color: var(--navy); --bs-btn-border-color: var(--border-strong);
    --bs-btn-hover-bg: var(--navy-50); --bs-btn-hover-color: var(--navy); --bs-btn-hover-border-color: var(--navy-300);
    --bs-btn-active-bg: var(--surface-2); --bs-btn-active-color: var(--navy);
}
.btn-success { --bs-btn-bg: var(--success); --bs-btn-border-color: var(--success); --bs-btn-hover-bg: var(--success-700); --bs-btn-hover-border-color: var(--success-700); }
.btn-danger  { --bs-btn-bg: var(--danger);  --bs-btn-border-color: var(--danger);  --bs-btn-hover-bg: var(--danger-700);  --bs-btn-hover-border-color: var(--danger-700); }
.btn-warning { --bs-btn-bg: var(--warning); --bs-btn-border-color: var(--warning); --bs-btn-color: #fff; --bs-btn-hover-color: #fff; --bs-btn-hover-bg: var(--warning-700); --bs-btn-hover-border-color: var(--warning-700); }
.btn-light   { --bs-btn-bg: var(--surface); --bs-btn-border-color: var(--border); --bs-btn-color: var(--navy); --bs-btn-hover-bg: var(--navy-50); }
.btn-dark    { --bs-btn-bg: var(--navy); --bs-btn-border-color: var(--navy); --bs-btn-hover-bg: var(--navy-700); --bs-btn-hover-border-color: var(--navy-700); }
.btn-outline-primary   { --bs-btn-color: var(--blue); --bs-btn-border-color: var(--blue-200); --bs-btn-hover-bg: var(--blue); --bs-btn-hover-border-color: var(--blue); }
.btn-outline-secondary { --bs-btn-color: var(--navy); --bs-btn-border-color: var(--border-strong); --bs-btn-hover-bg: var(--navy); --bs-btn-hover-border-color: var(--navy); }
.btn-outline-light     { --bs-btn-color: #fff; --bs-btn-border-color: rgba(255,255,255,.35); --bs-btn-hover-bg: #fff; --bs-btn-hover-color: var(--navy); --bs-btn-hover-border-color: #fff; }
.btn-outline-danger    { --bs-btn-color: var(--danger); --bs-btn-border-color: var(--danger-200); --bs-btn-hover-bg: var(--danger); --bs-btn-hover-border-color: var(--danger); }
/* Legacy aliases from the pre-redesign stylesheet, kept so old markup is not
   left unstyled. Both now resolve to the new tokens. */
.btn-exami { --bs-btn-bg: var(--navy); --bs-btn-border-color: var(--navy); --bs-btn-color: #fff; --bs-btn-hover-bg: var(--navy-700); --bs-btn-hover-border-color: var(--navy-700); --bs-btn-hover-color: #fff; background: var(--navy); border-color: var(--navy); color: #fff; }
.btn-exami:hover { background: var(--navy-700); border-color: var(--navy-700); color: #fff; }
.btn-outline-exami { border-color: var(--border-strong); color: var(--navy); background: transparent; }
.btn-outline-exami:hover { background: var(--navy); border-color: var(--navy); color: #fff; }

/* ---- Cards -------------------------------------------------------------- */
.card {
    --bs-card-border-color: var(--border);
    --bs-card-border-radius: var(--r-lg);
    --bs-card-inner-border-radius: calc(var(--r-lg) - 1px);
    --bs-card-bg: var(--surface);
    --bs-card-spacer-x: var(--sp-6);
    --bs-card-spacer-y: var(--sp-6);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-xs);
}
.card-header {
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    font-weight: var(--fw-semibold);
    color: var(--navy);
    padding: var(--sp-4) var(--sp-6);
}
.card-footer { background: var(--bg); border-top: 1px solid var(--border); }
/* Legacy: the old stylesheet gave .card-exami a navy header bar. */
.card-exami { border: 1px solid var(--border); border-radius: var(--r-lg); box-shadow: var(--shadow-xs); }
.card-exami > .card-header {
    background: var(--navy);
    color: #fff;
    border-bottom: 0;
    border-radius: calc(var(--r-lg) - 1px) calc(var(--r-lg) - 1px) 0 0;
}
.shadow-sm { box-shadow: var(--shadow-sm) !important; }
.shadow { box-shadow: var(--shadow-md) !important; }
.shadow-lg { box-shadow: var(--shadow-lg) !important; }

/* ---- Forms -------------------------------------------------------------- */
.form-control, .form-select {
    min-height: 48px;
    border-radius: var(--r-sm);
    border: 1px solid var(--border-strong);
    background-color: var(--surface);
    color: var(--text);
    font-size: .9375rem;
    padding: .625rem .875rem;
    box-shadow: none;
    transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
textarea.form-control { min-height: 120px; }
.form-control-sm, .form-select-sm { min-height: 38px; font-size: .8125rem; padding: .35rem .6rem; border-radius: var(--r-xs); }
.form-control:focus, .form-select:focus {
    border-color: var(--blue);
    box-shadow: var(--focus-ring);
    outline: none;
}
.form-control::placeholder { color: var(--muted-2); }
.form-control:disabled, .form-select:disabled { background: var(--surface-2); color: var(--muted); }
.form-control.is-invalid, .form-select.is-invalid { border-color: var(--danger); background-image: none; }
.form-control.is-invalid:focus { box-shadow: 0 0 0 3px rgba(220, 38, 38, .22); }
.form-label { font-size: var(--fs-sm); font-weight: var(--fw-semibold); color: var(--text-2); margin-bottom: var(--sp-2); }
.form-text { font-size: var(--fs-xs); color: var(--muted); }
.invalid-feedback { font-size: var(--fs-xs); color: var(--danger); }
.form-check-input { border-color: var(--border-strong); }
.form-check-input:checked { background-color: var(--blue); border-color: var(--blue); }
.form-check-input:focus { border-color: var(--blue); box-shadow: var(--focus-ring); }
.input-group-text { background: var(--surface-2); border-color: var(--border-strong); color: var(--muted); border-radius: var(--r-sm); }

/* ---- Tables ------------------------------------------------------------- */
.table {
    --bs-table-color: var(--text);
    --bs-table-border-color: var(--border);
    --bs-table-striped-bg: var(--bg);
    --bs-table-hover-bg: var(--blue-50);
    margin-bottom: 0;
}
.table > thead > tr > th {
    background: var(--bg);
    color: var(--muted);
    font-size: var(--fs-xs);
    font-weight: var(--fw-bold);
    letter-spacing: .05em;
    text-transform: uppercase;
    white-space: nowrap;
    border-bottom: 1px solid var(--border);
    padding: var(--sp-3) var(--sp-4);
}
.table > tbody > tr > td {
    padding: var(--sp-3) var(--sp-4);
    vertical-align: middle;
    font-size: .9rem;
    border-bottom: 1px solid var(--border-subtle);
}
.table > tbody > tr:last-child > td { border-bottom: 0; }
/* Legacy schedule tables from the public pages. */
.table-schedule > thead > tr > th { background: var(--navy); color: #fff; border-bottom: 0; }
.table-responsive { -webkit-overflow-scrolling: touch; }

/* ---- Badges ------------------------------------------------------------- */
.badge {
    font-weight: var(--fw-semibold);
    font-size: var(--fs-xs);
    letter-spacing: .01em;
    padding: .35em .7em;
    border-radius: var(--r-pill);
}
.badge.bg-primary   { background: var(--blue-50) !important; color: var(--blue-700) !important; }
.badge.bg-secondary { background: var(--surface-2) !important; color: var(--text-2) !important; }
.badge.bg-success   { background: var(--success-50) !important; color: var(--success-700) !important; }
.badge.bg-warning   { background: var(--warning-50) !important; color: var(--warning-700) !important; }
.badge.bg-danger    { background: var(--danger-50) !important; color: var(--danger-700) !important; }
.badge.bg-info      { background: var(--cyan-50) !important; color: var(--cyan-700) !important; }
.badge.bg-dark      { background: var(--navy) !important; color: #fff !important; }
.badge.bg-light     { background: var(--surface-2) !important; color: var(--text-2) !important; }

/* ---- Alerts ------------------------------------------------------------- */
.alert {
    border-radius: var(--r-md);
    border: 1px solid transparent;
    border-left-width: 3px;
    padding: var(--sp-4) var(--sp-5);
    font-size: .9375rem;
}
.alert-success { background: var(--success-50); border-color: var(--success-200); border-left-color: var(--success); color: var(--success-700); }
.alert-warning { background: var(--warning-50); border-color: var(--warning-200); border-left-color: var(--warning); color: var(--warning-700); }
.alert-danger  { background: var(--danger-50);  border-color: var(--danger-200);  border-left-color: var(--danger);  color: var(--danger-700); }
.alert-info    { background: var(--blue-50);    border-color: var(--blue-200);    border-left-color: var(--blue);    color: var(--blue-800); }
.alert-primary { background: var(--blue-50);    border-color: var(--blue-200);    border-left-color: var(--blue);    color: var(--blue-800); }

/* ---- Dropdowns / modals / pagination ------------------------------------ */
.dropdown-menu {
    --bs-dropdown-border-color: var(--border);
    --bs-dropdown-border-radius: var(--r-md);
    --bs-dropdown-link-active-bg: var(--blue-50);
    --bs-dropdown-link-active-color: var(--blue-700);
    --bs-dropdown-link-hover-bg: var(--bg);
    box-shadow: var(--shadow-lg);
    padding: var(--sp-2);
    font-size: .9rem;
}
.dropdown-item { border-radius: var(--r-xs); padding: .5rem .75rem; }
.dropdown-header { font-size: var(--fs-xs); color: var(--muted); }
.modal-content { border: 0; border-radius: var(--r-lg); box-shadow: var(--shadow-xl); }
.modal-header, .modal-footer { border-color: var(--border); }
.pagination {
    --bs-pagination-border-color: var(--border);
    --bs-pagination-border-radius: var(--r-sm);
    --bs-pagination-color: var(--text-2);
    --bs-pagination-hover-bg: var(--bg);
    --bs-pagination-active-bg: var(--blue);
    --bs-pagination-active-border-color: var(--blue);
    --bs-pagination-focus-box-shadow: var(--focus-ring);
    font-size: .875rem;
}
.nav-tabs { --bs-nav-tabs-border-color: var(--border); --bs-nav-tabs-link-active-color: var(--blue); }
.progress { background: var(--surface-2); border-radius: var(--r-pill); }
.progress-bar { background: var(--blue); }
.list-group-item { border-color: var(--border); }
.text-muted { color: var(--muted) !important; }
.bg-light { background-color: var(--bg) !important; }
.border { border-color: var(--border) !important; }
.rounded { border-radius: var(--r-sm) !important; }
.rounded-3 { border-radius: var(--r-md) !important; }
.min-w-0 { min-width: 0; }


/* ==========================================================================
   6b. LEGACY PAGE CLASSES
   --------------------------------------------------------------------------
   The pre-redesign public pages emit .hero / .section-eyebrow / .surface /
   .stat-strip / .list-check / .topper-tile. Those pages have NOT been
   redesigned yet (each gets its own agent). Re-implementing the classes here
   with the new tokens means they inherit the new look immediately instead of
   rendering unstyled. DELETE a rule here once no view uses it any more.
   ========================================================================== */

.hero {
    position: relative;
    background-color: var(--navy);
    background-image:
        radial-gradient(62% 78% at 82% 8%, rgba(0, 184, 217, .26) 0%, transparent 58%),
        radial-gradient(58% 72% at 6% 0%, rgba(21, 94, 239, .34) 0%, transparent 60%);
    color: var(--on-dark-muted);
    overflow: hidden;
}
.hero::before {
    content: '';
    position: absolute; inset: 0; pointer-events: none;
    background-image:
        linear-gradient(rgba(255, 255, 255, .05) 1px, transparent 1px),
        linear-gradient(90deg, rgba(255, 255, 255, .05) 1px, transparent 1px);
    background-size: 34px 34px;
    -webkit-mask-image: radial-gradient(110% 90% at 60% 0%, #000 5%, transparent 72%);
            mask-image: radial-gradient(110% 90% at 60% 0%, #000 5%, transparent 72%);
}
.hero > * { position: relative; }
.hero h1, .hero h2, .hero h3, .hero h4, .hero h5, .hero .display-3, .hero .display-5 { color: #fff; letter-spacing: var(--tracking-tight); }
.hero .lead, .hero p { color: var(--on-dark-muted); }
.hero .tagline { color: var(--cyan); font-weight: var(--fw-semibold); }
.hero .btn-light { --bs-btn-bg: #fff; --bs-btn-color: var(--navy); --bs-btn-hover-bg: var(--navy-50); --bs-btn-hover-color: var(--navy); --bs-btn-border-color: #fff; }
.hero .badge.bg-light { background: rgba(255,255,255,.14) !important; color: #fff !important; }

.section-eyebrow {
    display: inline-block;
    text-transform: uppercase;
    letter-spacing: var(--tracking-eyebrow);
    font-size: var(--fs-eyebrow);
    font-weight: var(--fw-bold);
    color: var(--blue);
}
.hero .section-eyebrow { color: var(--cyan-200) !important; }

.surface { background: var(--bg) !important; }
.stat-strip { background: var(--bg); border-block: 1px solid var(--border); }

.list-check { list-style: none; padding-left: 0; }
.list-check li { padding-left: 2rem; position: relative; margin-bottom: var(--sp-3); }
.list-check li::before {
    content: '';
    position: absolute; left: 0; top: .18em;
    width: 1.25rem; height: 1.25rem; border-radius: var(--r-pill);
    background: var(--blue-50) center / .7rem .7rem no-repeat;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23155EEF' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
    font-family: inherit;
}

.topper-tile {
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    text-align: center;
    padding: var(--sp-5) var(--sp-4);
    height: 100%;
    background: var(--surface);
    transition: box-shadow var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.topper-tile:hover { box-shadow: var(--shadow-md); border-color: var(--blue-200); }
.topper-tile .score { font-size: 1.6rem; font-weight: var(--fw-extrabold); color: var(--navy); line-height: 1.1; }
.topper-tile .name { font-size: var(--fs-sm); color: var(--muted); margin-top: var(--sp-2); }

/* The old layout's dark footer/topbar classes, in case a stray view uses them. */
.footer-exami { background: var(--navy); color: var(--on-dark-muted); }
.footer-exami h6 { color: #fff; text-transform: uppercase; letter-spacing: var(--tracking-eyebrow); font-size: var(--fs-xs); }
.footer-exami a { color: var(--on-dark-muted); }
.footer-exami a:hover { color: #fff; }


/* ==========================================================================
   7. COMPONENTS  (.ex-*)  — consumed by resources/views/components/*.blade.php
   ========================================================================== */

/* ---- 7.1 Button --------------------------------------------------------- */
.ex-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .5em;
    border: 1px solid transparent;
    border-radius: var(--r-md);
    font-family: inherit;
    font-weight: var(--fw-semibold);
    font-size: .9375rem;
    line-height: 1.2;
    letter-spacing: -.005em;
    padding: .78rem 1.25rem;
    min-height: 46px;
    text-decoration: none;
    cursor: pointer;
    white-space: nowrap;
    background: none;
    transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease),
                color var(--dur) var(--ease), box-shadow var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.ex-btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.ex-btn[disabled], .ex-btn[aria-disabled='true'] { opacity: .55; pointer-events: none; }
/* A button must never be wider than what contains it. `white-space: nowrap`
   above keeps labels on one line wherever there is room, but on a 320px phone a
   long label ("Enquire about this programme") was rendering 281px wide inside a
   238px card foot and getting clipped. Below 480px the label is allowed to wrap
   instead; above it, nowrap still holds. */
.ex-btn { max-width: 100%; }
@media (max-width: 479.98px) {
    .ex-btn { white-space: normal; }
}

.ex-btn--primary {
    background: var(--blue);
    border-color: var(--blue);
    color: #fff;
    box-shadow: 0 1px 2px rgba(11, 31, 58, .12);
}
.ex-btn--primary:hover { background: var(--blue-700); border-color: var(--blue-700); color: #fff; box-shadow: var(--shadow-md); }
.ex-btn--primary:active { background: var(--blue-800); border-color: var(--blue-800); }

.ex-btn--secondary {
    background: var(--surface);
    border-color: var(--border-strong);
    color: var(--navy);
}
.ex-btn--secondary:hover { background: var(--navy-50); border-color: var(--navy-300); color: var(--navy); }

.ex-btn--ghost { background: transparent; border-color: transparent; color: var(--blue); padding-inline: .75rem; }
.ex-btn--ghost:hover { background: var(--blue-50); color: var(--blue-700); }

.ex-btn--navy { background: var(--navy); border-color: var(--navy); color: #fff; }
.ex-btn--navy:hover { background: var(--navy-700); border-color: var(--navy-700); color: #fff; }

.ex-btn--danger { background: var(--danger); border-color: var(--danger); color: #fff; }
.ex-btn--danger:hover { background: var(--danger-700); border-color: var(--danger-700); color: #fff; }

/* on-dark: for use inside .ex-on-dark / navy sections */
.ex-btn--on-dark { background: #fff; border-color: #fff; color: var(--navy); }
.ex-btn--on-dark:hover { background: var(--navy-50); border-color: var(--navy-50); color: var(--navy); }
.ex-btn--on-dark-outline { background: transparent; border-color: rgba(255, 255, 255, .34); color: #fff; }
.ex-btn--on-dark-outline:hover { background: rgba(255, 255, 255, .12); border-color: rgba(255, 255, 255, .6); color: #fff; }
.ex-on-dark .ex-btn:focus-visible, .ex-btn--on-dark:focus-visible, .ex-btn--on-dark-outline:focus-visible { box-shadow: var(--focus-ring-on-dark); }

.ex-btn--sm { min-height: 38px; padding: .45rem .85rem; font-size: .8125rem; border-radius: var(--r-sm); }
.ex-btn--lg { min-height: 54px; padding: .95rem 1.65rem; font-size: 1rem; }
.ex-btn--block { display: flex; width: 100%; }
.ex-btn--icon { padding: .6rem; min-height: 42px; aspect-ratio: 1; }

/* Trailing arrow that slides on hover. */
.ex-btn__arrow {
    flex: none;
    width: 1em;
    height: 1em;
    transition: transform var(--dur) var(--ease-out);
}
.ex-btn:hover .ex-btn__arrow { transform: translateX(3px); }

/* ---- 7.2 Badge ---------------------------------------------------------- */
.ex-badge {
    display: inline-flex;
    align-items: center;
    gap: .4em;
    padding: .3rem .6rem;
    border-radius: var(--r-pill);
    font-size: var(--fs-xs);
    font-weight: var(--fw-semibold);
    line-height: 1.35;
    letter-spacing: .01em;
    border: 1px solid transparent;
    white-space: nowrap;
}
.ex-badge--neutral   { background: var(--surface-2); color: var(--text-2); border-color: var(--border); }
.ex-badge--accent    { background: var(--blue-50); color: var(--blue-700); border-color: var(--blue-100); }
.ex-badge--cyan      { background: var(--cyan-50); color: var(--cyan-700); border-color: var(--cyan-200); }
.ex-badge--success   { background: var(--success-50); color: var(--success-700); border-color: var(--success-200); }
.ex-badge--warning   { background: var(--warning-50); color: var(--warning-700); border-color: var(--warning-200); }
.ex-badge--danger    { background: var(--danger-50); color: var(--danger-700); border-color: var(--danger-200); }
.ex-badge--navy      { background: var(--navy); color: #fff; }
.ex-badge--on-dark   { background: rgba(255,255,255,.12); color: #fff; border-color: rgba(255,255,255,.2); }
/* Status semantics used across programme/test listings. */
.ex-badge--upcoming  { background: var(--warning-50); color: var(--warning-700); border-color: var(--warning-200); }
.ex-badge--live      { background: var(--success-50); color: var(--success-700); border-color: var(--success-200); }
.ex-badge--completed { background: var(--surface-2); color: var(--muted); border-color: var(--border); }
.ex-badge--lg { font-size: var(--fs-sm); padding: .4rem .8rem; }

.ex-badge__dot { width: .5em; height: .5em; border-radius: 50%; background: currentColor; flex: none; }
.ex-badge--live .ex-badge__dot { animation: ex-pulse 1.9s var(--ease) infinite; }
@keyframes ex-pulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: .45; transform: scale(.82); } }

/* ---- 7.3 Card ----------------------------------------------------------- */
.ex-card {
    position: relative;
    display: flex;
    flex-direction: column;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-xs);
    overflow: hidden;
    transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.ex-card__body { padding: var(--sp-6); flex: 1 1 auto; }
.ex-card__body--tight { padding: var(--sp-4); }
.ex-card__header { padding: var(--sp-5) var(--sp-6); border-bottom: 1px solid var(--border); font-weight: var(--fw-semibold); color: var(--navy); }
.ex-card__footer { padding: var(--sp-4) var(--sp-6); border-top: 1px solid var(--border); background: var(--bg); }
.ex-card--hover:hover { transform: translateY(-3px); box-shadow: var(--shadow-lg); border-color: var(--blue-200); }
.ex-card--flat { box-shadow: none; }
.ex-card--muted { background: var(--bg); }
.ex-card--dark { background: var(--navy); border-color: var(--navy-700); color: var(--on-dark-muted); }
.ex-card--accent { border-top: 3px solid var(--blue); }
/* Whole card clickable via a stretched link, keyboard-focusable. */
.ex-card__link::after { content: ''; position: absolute; inset: 0; }
.ex-card:focus-within { border-color: var(--blue-300); }

/* ---- 7.4 Section header ------------------------------------------------- */
.ex-section-header { margin-bottom: var(--sp-8); max-width: 56rem; }
.ex-section-header--center { margin-inline: auto; text-align: center; }
.ex-section-header--center .ex-eyebrow { justify-content: center; }
.ex-section-header__title { margin: 0 0 var(--sp-3); }
.ex-section-header__desc { margin: 0; font-size: var(--fs-lead); line-height: var(--lh-snug); color: var(--muted); text-wrap: pretty; }
.ex-on-dark .ex-section-header__desc { color: var(--on-dark-muted); }

/* ---- 7.5 Stat ----------------------------------------------------------- */
.ex-stat { display: flex; flex-direction: column; gap: var(--sp-1); min-width: 0; }
.ex-stat__icon {
    display: inline-flex; align-items: center; justify-content: center;
    width: 40px; height: 40px; margin-bottom: var(--sp-2);
    border-radius: var(--r-md);
    background: var(--blue-50); color: var(--blue);
    flex: none;
}
.ex-stat__value {
    font-size: clamp(1.75rem, 1.3rem + 1.5vw, 2.75rem);
    font-weight: var(--fw-extrabold);
    line-height: 1.05;
    letter-spacing: var(--tracking-tight);
    color: var(--navy);
    overflow-wrap: anywhere;
}
.ex-stat__label { font-size: var(--fs-sm); color: var(--muted); font-weight: var(--fw-medium); }
.ex-stat__hint { font-size: var(--fs-xs); color: var(--muted); }
.ex-stat--center { align-items: center; text-align: center; }
.ex-on-dark .ex-stat__value { color: #fff; }
.ex-on-dark .ex-stat__label { color: var(--on-dark-muted); }
.ex-on-dark .ex-stat__icon { background: rgba(255,255,255,.1); color: var(--cyan-200); }

/* ---- 7.6 Empty state ---------------------------------------------------- */
.ex-empty {
    display: flex; flex-direction: column; align-items: center; text-align: center;
    padding: clamp(2.5rem, 6vw, 4.5rem) var(--sp-6);
    border: 1px dashed var(--border-strong);
    border-radius: var(--r-lg);
    background:
        radial-gradient(120% 90% at 50% 0%, var(--blue-50) 0%, transparent 62%),
        var(--surface);
}
.ex-empty--plain { border: 0; background: none; }
.ex-empty__art {
    position: relative;
    display: inline-flex; align-items: center; justify-content: center;
    width: 68px; height: 68px; margin-bottom: var(--sp-5);
    border-radius: var(--r-xl);
    background: var(--surface);
    border: 1px solid var(--border);
    box-shadow: var(--shadow-sm);
    color: var(--blue);
}
.ex-empty__art::before {
    content: ''; position: absolute; inset: -10px;
    border-radius: var(--r-2xl);
    border: 1px solid var(--border-subtle);
}
.ex-empty__title { margin: 0 0 var(--sp-2); font-size: var(--fs-h4); color: var(--navy); font-weight: var(--fw-semibold); }
.ex-empty__message { margin: 0; max-width: 44ch; color: var(--muted); font-size: .9375rem; }
.ex-empty__actions { margin-top: var(--sp-5); display: flex; flex-wrap: wrap; gap: var(--sp-3); justify-content: center; }

/* ---- 7.7 Loading skeleton ----------------------------------------------- */
.ex-skeleton { display: block; border-radius: var(--r-xs); background: var(--surface-2); position: relative; overflow: hidden; }
.ex-skeleton::after {
    content: ''; position: absolute; inset: 0; transform: translateX(-100%);
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .75), transparent);
    animation: ex-shimmer 1.5s infinite;
}
@keyframes ex-shimmer { 100% { transform: translateX(100%); } }
.ex-skeleton__line { height: .8rem; margin-bottom: .6rem; }
.ex-skeleton__line:last-child { margin-bottom: 0; width: 62%; }
.ex-skeleton__title { height: 1.35rem; width: 52%; margin-bottom: var(--sp-4); border-radius: var(--r-xs); }
.ex-skeleton__card { border: 1px solid var(--border); border-radius: var(--r-lg); padding: var(--sp-6); background: var(--surface); }
.ex-skeleton__row { display: flex; gap: var(--sp-4); padding: var(--sp-3) 0; border-bottom: 1px solid var(--border-subtle); }
.ex-skeleton__row > .ex-skeleton { height: 1rem; flex: 1; }
.ex-skeleton__avatar { width: 44px; height: 44px; border-radius: var(--r-pill); flex: none; }

/* ---- 7.8 Alert ---------------------------------------------------------- */
.ex-alert {
    display: flex; gap: var(--sp-3); align-items: flex-start;
    padding: var(--sp-4) var(--sp-5);
    border: 1px solid transparent;
    border-left-width: 3px;
    border-radius: var(--r-md);
    font-size: .9375rem;
    line-height: 1.5;
}
.ex-alert__icon { flex: none; margin-top: .1em; }
.ex-alert__title { font-weight: var(--fw-semibold); margin: 0 0 .15rem; }
.ex-alert__body { min-width: 0; flex: 1; }
.ex-alert__body > :last-child { margin-bottom: 0; }
.ex-alert--success { background: var(--success-50); border-color: var(--success-200); border-left-color: var(--success); color: var(--success-700); }
.ex-alert--warning { background: var(--warning-50); border-color: var(--warning-200); border-left-color: var(--warning); color: var(--warning-700); }
.ex-alert--danger  { background: var(--danger-50);  border-color: var(--danger-200);  border-left-color: var(--danger);  color: var(--danger-700); }
.ex-alert--info    { background: var(--blue-50);    border-color: var(--blue-200);    border-left-color: var(--blue);    color: var(--blue-800); }
.ex-alert__close { margin-left: auto; background: none; border: 0; color: inherit; opacity: .55; cursor: pointer; padding: 0 .15rem; line-height: 1; }
.ex-alert__close:hover { opacity: 1; }

/* ---- 7.9 Form field ----------------------------------------------------- */
.ex-field { display: flex; flex-direction: column; gap: var(--sp-2); margin-bottom: var(--sp-5); }
.ex-field__label { font-size: var(--fs-sm); font-weight: var(--fw-semibold); color: var(--text-2); line-height: 1.4; }
.ex-field__req { color: var(--danger); margin-left: .15em; }
.ex-field__help { font-size: var(--fs-xs); color: var(--muted); }
.ex-field__error { font-size: var(--fs-xs); color: var(--danger); font-weight: var(--fw-medium); }

.ex-input, .ex-select, .ex-textarea {
    width: 100%;
    min-height: 48px;
    padding: .7rem .875rem;
    font-family: inherit;
    font-size: .9375rem;
    line-height: 1.4;
    color: var(--text);
    background-color: var(--surface);
    border: 1px solid var(--border-strong);
    border-radius: var(--r-sm);
    transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
    appearance: none;
}
.ex-textarea { min-height: 128px; resize: vertical; }
.ex-select {
    padding-right: 2.5rem;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23667085' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right .8rem center;
    background-size: 1.1rem;
    cursor: pointer;
}
.ex-input::placeholder, .ex-textarea::placeholder { color: var(--muted-2); }
.ex-input:hover, .ex-select:hover, .ex-textarea:hover { border-color: var(--navy-300); }
.ex-input:focus, .ex-select:focus, .ex-textarea:focus {
    outline: none;
    border-color: var(--blue);
    box-shadow: var(--focus-ring);
}
.ex-input:disabled, .ex-select:disabled, .ex-textarea:disabled { background: var(--surface-2); color: var(--muted); cursor: not-allowed; }
.ex-field--error .ex-input,
.ex-field--error .ex-select,
.ex-field--error .ex-textarea { border-color: var(--danger); }
.ex-field--error .ex-input:focus,
.ex-field--error .ex-select:focus,
.ex-field--error .ex-textarea:focus { box-shadow: 0 0 0 3px rgba(220, 38, 38, .22); }
.ex-input--sm, .ex-select--sm { min-height: 40px; padding: .4rem .65rem; font-size: .875rem; }

/* ---- 7.10 Avatar -------------------------------------------------------- */
.ex-avatar {
    display: inline-flex; align-items: center; justify-content: center;
    width: var(--ex-avatar-size, 40px);
    height: var(--ex-avatar-size, 40px);
    flex: none;
    border-radius: var(--r-pill);
    background: var(--navy-50);
    color: var(--navy);
    font-weight: var(--fw-semibold);
    font-size: calc(var(--ex-avatar-size, 40px) * .38);
    line-height: 1;
    letter-spacing: .01em;
    overflow: hidden;
    text-transform: uppercase;
    user-select: none;
}
.ex-avatar > img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ex-avatar--xs { --ex-avatar-size: 26px; }
.ex-avatar--sm { --ex-avatar-size: 32px; }
.ex-avatar--md { --ex-avatar-size: 40px; }
.ex-avatar--lg { --ex-avatar-size: 56px; }
.ex-avatar--xl { --ex-avatar-size: 80px; }
.ex-avatar--2xl { --ex-avatar-size: 112px; }
.ex-avatar--square { border-radius: var(--r-md); }
.ex-avatar--accent { background: var(--blue-50); color: var(--blue-700); }
.ex-avatar--navy { background: var(--navy); color: #fff; }
.ex-avatar--ring { box-shadow: 0 0 0 3px var(--surface), 0 0 0 4px var(--border); }

/* ---- 7.11 Media (aspect-locked image box, branded fallback) ------------- */
.ex-media {
    position: relative;
    display: block;
    width: 100%;
    aspect-ratio: var(--ex-media-ratio, 16 / 9);
    overflow: hidden;
    border-radius: var(--r-md);
    background: var(--surface-2);
}
.ex-media > img {
    width: 100%; height: 100%;
    object-fit: var(--ex-media-fit, cover);
    object-position: var(--ex-media-pos, center);
    display: block;
}
.ex-media--contain { --ex-media-fit: contain; }
.ex-media--plain { border-radius: 0; }
/* Branded, photo-free fallback: brand gradient + graph-paper motif + monogram.
   Used whenever `src` is null so a missing asset never shows a broken icon. */
.ex-media__fallback {
    position: absolute; inset: 0;
    display: flex; align-items: center; justify-content: center;
    background:
        linear-gradient(140deg, var(--navy) 0%, var(--navy-600) 58%, var(--blue-800) 100%);
    color: rgba(255, 255, 255, .9);
}
.ex-media__fallback::before {
    content: '';
    position: absolute; inset: 0;
    opacity: .5;
    background-image:
        linear-gradient(rgba(255, 255, 255, .07) 1px, transparent 1px),
        linear-gradient(90deg, rgba(255, 255, 255, .07) 1px, transparent 1px);
    background-size: 26px 26px;
    -webkit-mask-image: radial-gradient(120% 90% at 30% 20%, #000 10%, transparent 78%);
            mask-image: radial-gradient(120% 90% at 30% 20%, #000 10%, transparent 78%);
}
.ex-media__fallback-mark {
    position: relative;
    font-weight: var(--fw-extrabold);
    letter-spacing: .22em;
    font-size: clamp(.9rem, 2.2vw, 1.35rem);
    text-transform: uppercase;
    opacity: .92;
}


/* ==========================================================================
   8. PUBLIC SITE SHELL — header, nav, footer
   --------------------------------------------------------------------------
   Hand-rolled, with its own vanilla JS (public/js/exami.js). It deliberately
   does NOT use Bootstrap's navbar/collapse/dropdown so the marketing header
   is not hostage to Bootstrap's look or its JS.
   ========================================================================== */

/* Sticky-footer page frame for the public site. */
.ex-site { display: flex; flex-direction: column; min-height: 100vh; }
.ex-site > main { flex: 1 0 auto; }
.ex-site > .ex-footer { flex: none; }

.ex-skip-link {
    position: absolute; left: var(--sp-4); top: -100px; z-index: 1090;
    background: var(--navy); color: #fff;
    padding: .7rem 1.1rem; border-radius: var(--r-sm);
    font-size: .875rem; font-weight: var(--fw-semibold);
    transition: top var(--dur) var(--ease);
}
.ex-skip-link:focus { top: var(--sp-3); color: #fff; }

/* ---- 8.1 Utility bar (above header, desktop only) ----------------------- */
.ex-utilitybar {
    background: var(--navy);
    color: var(--on-dark-muted);
    font-size: var(--fs-xs);
    line-height: 1;
}
.ex-utilitybar .ex-container { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--sp-4); padding-block: .6rem; }
.ex-utilitybar a { color: var(--on-dark-muted); display: inline-flex; align-items: center; gap: .35rem; }
.ex-utilitybar a:hover { color: #fff; }
.ex-utilitybar__group { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-5); }
@media (max-width: 991.98px) { .ex-utilitybar { display: none; } }

/* ---- 8.2 Header --------------------------------------------------------- */
.ex-header {
    position: sticky;
    top: 0;
    z-index: var(--z-header);
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    box-shadow: var(--shadow-header);
    transition: box-shadow var(--dur) var(--ease), background-color var(--dur) var(--ease);
}
.ex-header__inner {
    display: flex;
    align-items: center;
    gap: var(--sp-4);
    height: var(--header-h);
    transition: height var(--dur) var(--ease);
}
.ex-header.is-compact { box-shadow: var(--shadow-header-compact); }
.ex-header.is-compact .ex-header__inner { height: var(--header-h-compact); }
.ex-header.is-compact .ex-header__logo { height: 34px; }

.ex-header__brand { display: inline-flex; align-items: center; flex: none; }
.ex-header__logo { height: 42px; width: auto; display: block; transition: height var(--dur) var(--ease); }

.ex-header__nav { display: flex; align-items: center; gap: var(--sp-1); margin-left: auto; }
.ex-header__actions { display: flex; align-items: center; gap: var(--sp-2); flex: none; margin-left: var(--sp-3); }

.ex-nav { display: flex; align-items: center; gap: 2px; list-style: none; margin: 0; padding: 0; }
.ex-nav__item { position: relative; }
.ex-nav__link {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    padding: .5rem .6rem;
    border-radius: var(--r-sm);
    font-size: .875rem;
    font-weight: var(--fw-medium);
    color: var(--text-2);
    background: none;
    border: 0;
    font-family: inherit;
    cursor: pointer;
    white-space: nowrap;
    transition: color var(--dur) var(--ease), background-color var(--dur) var(--ease);
}
.ex-nav__link:hover { color: var(--blue); background: var(--blue-50); }
.ex-nav__link::after {
    content: '';
    position: absolute;
    left: .6rem; right: .6rem; bottom: -1px;
    height: 2px;
    border-radius: 2px;
    background: linear-gradient(90deg, var(--blue), var(--cyan));
    transform: scaleX(0);
    transform-origin: left;
    transition: transform var(--dur) var(--ease-out);
}
.ex-nav__link.is-active { color: var(--navy); font-weight: var(--fw-semibold); }
.ex-nav__link.is-active::after { transform: scaleX(1); }
.ex-nav__caret { width: 14px; height: 14px; transition: transform var(--dur) var(--ease); opacity: .7; }
.ex-nav__item.is-open > .ex-nav__link { color: var(--blue); background: var(--blue-50); }
.ex-nav__item.is-open .ex-nav__caret { transform: rotate(180deg); }

/* Dropdown — hand-rolled, keyboard-driven (see exami.js). */
.ex-nav__menu {
    position: absolute;
    top: calc(100% + 10px);
    left: 0;
    min-width: 248px;
    padding: var(--sp-2);
    margin: 0;
    list-style: none;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    box-shadow: var(--shadow-lg);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-6px);
    transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease), visibility var(--dur);
}
.ex-nav__item.is-open > .ex-nav__menu { opacity: 1; visibility: visible; transform: translateY(0); }
.ex-nav__menu a {
    display: block;
    padding: .55rem .7rem;
    border-radius: var(--r-xs);
    font-size: .875rem;
    font-weight: var(--fw-medium);
    color: var(--text-2);
}
.ex-nav__menu a:hover, .ex-nav__menu a:focus-visible { background: var(--bg); color: var(--blue); }
.ex-nav__menu a.is-active { color: var(--blue); background: var(--blue-50); }
.ex-nav__menu-desc { display: block; font-size: var(--fs-xs); color: var(--muted); font-weight: var(--fw-regular); margin-top: .1rem; }

.ex-header__burger {
    display: none;
    align-items: center;
    justify-content: center;
    width: 44px; height: 44px;
    margin-left: auto;
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    background: var(--surface);
    color: var(--navy);
    cursor: pointer;
}
.ex-header__burger:hover { background: var(--bg); }

@media (max-width: 1259.98px) {
    .ex-header__nav, .ex-header__actions { display: none; }
    .ex-header__burger { display: inline-flex; }
}

/* ---- 8.3 Mobile drawer -------------------------------------------------- */
.ex-drawer-backdrop {
    position: fixed; inset: 0;
    background: rgba(6, 18, 31, .5);
    z-index: var(--z-backdrop);
    opacity: 0; visibility: hidden;
    transition: opacity var(--dur) var(--ease), visibility var(--dur);
}
body.ex-drawer-open .ex-drawer-backdrop { opacity: 1; visibility: visible; }
body.ex-drawer-open { overflow: hidden; }

.ex-drawer {
    position: fixed;
    top: 0; right: 0; bottom: 0;
    width: min(400px, 100%);
    z-index: var(--z-drawer);
    background: var(--surface);
    display: flex;
    flex-direction: column;
    transform: translateX(100%);
    /* `visibility: hidden` while closed is not cosmetic: without it the drawer's
       links stay in the tab order even though they are off-screen, so a keyboard
       user tabbing the header falls into an invisible menu. */
    visibility: hidden;
    transition: transform var(--dur-slow) var(--ease-out), visibility var(--dur-slow);
    box-shadow: var(--shadow-xl);
}
body.ex-drawer-open .ex-drawer { transform: translateX(0); visibility: visible; }
.ex-drawer__head {
    display: flex; align-items: center; justify-content: space-between;
    gap: var(--sp-4);
    padding: var(--sp-4) var(--sp-5);
    border-bottom: 1px solid var(--border);
    flex: none;
}
.ex-drawer__head img { height: 36px; width: auto; }
.ex-drawer__close {
    display: inline-flex; align-items: center; justify-content: center;
    width: 44px; height: 44px;
    border: 1px solid var(--border); border-radius: var(--r-sm);
    background: var(--surface); color: var(--navy); cursor: pointer;
}
.ex-drawer__close:hover { background: var(--bg); }
.ex-drawer__body { flex: 1 1 auto; overflow-y: auto; padding: var(--sp-4) var(--sp-5) var(--sp-8); -webkit-overflow-scrolling: touch; }
.ex-drawer__list { list-style: none; margin: 0 0 var(--sp-5); padding: 0; }
.ex-drawer__list a {
    display: flex; align-items: center; justify-content: space-between;
    padding: .95rem .25rem;
    font-size: 1rem;
    font-weight: var(--fw-medium);
    color: var(--text-2);
    border-bottom: 1px solid var(--border-subtle);
    min-height: 52px;
}
.ex-drawer__list a:hover { color: var(--blue); }
.ex-drawer__list a.is-active { color: var(--blue); font-weight: var(--fw-semibold); }
.ex-drawer__list a.is-sub { padding-left: var(--sp-5); font-size: .9375rem; color: var(--muted); }
.ex-drawer__list a.is-sub::before {
    content: '';
    width: 6px; height: 1px; background: var(--border-strong);
    margin-right: var(--sp-3); margin-left: calc(var(--sp-5) * -1 + 2px);
    flex: none;
}
.ex-drawer__group-label {
    font-size: var(--fs-xs); font-weight: var(--fw-bold);
    letter-spacing: var(--tracking-eyebrow); text-transform: uppercase;
    color: var(--muted);
    padding: var(--sp-5) 0 var(--sp-2);
}
.ex-drawer__actions { display: grid; gap: var(--sp-3); margin-top: var(--sp-6); }
.ex-drawer__meta { margin-top: var(--sp-6); padding-top: var(--sp-5); border-top: 1px solid var(--border); font-size: var(--fs-sm); color: var(--muted); display: grid; gap: var(--sp-2); }
/* The drawer is a touch-only surface, so its tel: links get a full 44px target
   rather than the 21px the bare text line gave them. */
.ex-drawer__meta a { display: flex; align-items: center; min-height: 44px; }

/* ---- 8.4 Footer --------------------------------------------------------- */
.ex-footer {
    position: relative;
    background: var(--navy);
    color: var(--on-dark-muted);
    padding-top: clamp(3rem, 6vw, 5.5rem);
    overflow: hidden;
}
.ex-footer::before {
    content: '';
    position: absolute; inset: 0;
    pointer-events: none;
    background-image:
        radial-gradient(60% 70% at 88% 0%, rgba(0, 184, 217, .16) 0%, transparent 62%),
        radial-gradient(50% 60% at 6% 8%, rgba(21, 94, 239, .18) 0%, transparent 60%);
}
.ex-footer > * { position: relative; }
.ex-footer__grid {
    display: grid;
    gap: var(--sp-8) var(--sp-6);
    grid-template-columns: 1fr;
    padding-bottom: var(--sp-9);
}
@media (min-width: 576px) { .ex-footer__grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 992px) { .ex-footer__grid { grid-template-columns: 1.6fr 1fr 1fr 1.3fr; gap: var(--sp-8); } }

.ex-footer__logo-plate {
    display: inline-flex; padding: .55rem .75rem;
    background: #fff; border-radius: var(--r-md); margin-bottom: var(--sp-4);
}
.ex-footer__logo-plate img { height: 40px; width: auto; display: block; }
.ex-footer__blurb { font-size: .9375rem; line-height: var(--lh-body); color: var(--on-dark-muted); max-width: 34ch; }
.ex-footer__tagline { color: #fff; font-weight: var(--fw-semibold); font-size: 1.05rem; margin-bottom: var(--sp-3); }
.ex-footer h3, .ex-footer__coltitle {
    color: #fff;
    font-size: var(--fs-xs);
    font-weight: var(--fw-bold);
    letter-spacing: var(--tracking-eyebrow);
    text-transform: uppercase;
    margin: 0 0 var(--sp-4);
}
.ex-footer__list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-3); }
.ex-footer__list a { color: var(--on-dark-muted); font-size: .9rem; display: inline-block; }
.ex-footer__list a:hover { color: #fff; transform: translateX(2px); }
.ex-footer__list a { transition: color var(--dur) var(--ease), transform var(--dur) var(--ease); }
/* Touch targets. On a phone the footer is thumb-operated, so trade the grid gap
   for padding on the link itself: same ~38px visual pitch, but the whole row is
   now tappable (was a 23px text box). Desktop spacing is deliberately untouched. */
@media (max-width: 767.98px) {
    .ex-footer__list { gap: 0; }
    .ex-footer__list a { display: flex; align-items: center; min-height: 40px; }
}
.ex-footer__contact { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-3); font-size: .9rem; }
.ex-footer__contact li { display: flex; gap: var(--sp-3); align-items: flex-start; }
.ex-footer__contact svg { flex: none; margin-top: .18em; color: var(--cyan); }
/* The tel:/mailto: links here had no colour of their own, so they fell back to
   the global link blue — 3.05:1 against the navy footer. Match .ex-footer__list. */
.ex-footer__contact a { color: var(--on-dark-muted); }
.ex-footer__contact a:hover { color: var(--on-dark); }
/* Same touch-target rule as .ex-footer__list: the tel:/mailto: rows here are
   the most likely thing a phone user taps in the footer. */
@media (max-width: 767.98px) {
    .ex-footer__contact a { display: inline-flex; align-items: center; min-height: 40px; }
}
.ex-footer__stats { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-top: var(--sp-5); }
.ex-footer__stat {
    padding: .35rem .7rem;
    border: 1px solid var(--on-dark-border);
    border-radius: var(--r-pill);
    font-size: var(--fs-xs);
    color: #fff;
}
.ex-footer__bar {
    border-top: 1px solid var(--on-dark-border);
    padding-block: var(--sp-5);
    display: flex; flex-wrap: wrap; gap: var(--sp-3);
    align-items: center; justify-content: space-between;
    font-size: var(--fs-xs);
    color: var(--on-dark-muted);
}


/* ==========================================================================
   9. PHOTO-FREE VISUAL SYSTEM
   --------------------------------------------------------------------------
   There is no photography for this project and the 6 legacy programme banners
   are off-brand. Everything decorative is therefore CSS/SVG: brand gradient
   meshes, an academic graph-paper grid, dot fields, and "real UI element"
   floating cards (rank / score / sparkline) for hero compositions.
   ========================================================================== */

.ex-surface-navy { background: var(--navy); color: var(--on-dark-muted); }

/* Gradient mesh — the default hero/CTA background. */
.ex-mesh {
    position: relative;
    background-color: var(--navy);
    background-image:
        radial-gradient(62% 78% at 82% 12%, rgba(0, 184, 217, .26) 0%, transparent 58%),
        radial-gradient(58% 72% at 8% 4%, rgba(21, 94, 239, .34) 0%, transparent 60%),
        radial-gradient(70% 90% at 50% 108%, rgba(21, 94, 239, .20) 0%, transparent 62%);
    color: var(--on-dark-muted);
    isolation: isolate;
}
.ex-mesh--light {
    background-color: var(--bg);
    background-image:
        radial-gradient(58% 70% at 88% 0%, rgba(0, 184, 217, .13) 0%, transparent 60%),
        radial-gradient(52% 64% at 4% 6%, rgba(21, 94, 239, .12) 0%, transparent 58%);
    color: var(--text);
}

/* Academic graph paper. Apply to a ::before-capable decorative layer. */
.ex-pattern-grid { position: relative; overflow: hidden; }
.ex-pattern-grid::before {
    content: '';
    position: absolute; inset: 0;
    pointer-events: none;
    background-image:
        linear-gradient(var(--ex-pattern-color, rgba(255, 255, 255, .06)) 1px, transparent 1px),
        linear-gradient(90deg, var(--ex-pattern-color, rgba(255, 255, 255, .06)) 1px, transparent 1px);
    background-size: var(--ex-pattern-size, 34px) var(--ex-pattern-size, 34px);
    -webkit-mask-image: var(--ex-pattern-mask, radial-gradient(110% 90% at 50% 0%, #000 5%, transparent 72%));
            mask-image: var(--ex-pattern-mask, radial-gradient(110% 90% at 50% 0%, #000 5%, transparent 72%));
    z-index: -1;
}
.ex-pattern-grid--dark { --ex-pattern-color: rgba(11, 31, 58, .07); }

/* Dot field. */
.ex-pattern-dots { position: relative; overflow: hidden; }
.ex-pattern-dots::before {
    content: '';
    position: absolute; inset: 0;
    pointer-events: none;
    background-image: radial-gradient(var(--ex-dot-color, rgba(11, 31, 58, .13)) 1.1px, transparent 1.1px);
    background-size: var(--ex-dot-size, 22px) var(--ex-dot-size, 22px);
    -webkit-mask-image: var(--ex-pattern-mask, radial-gradient(90% 80% at 50% 50%, #000 5%, transparent 74%));
            mask-image: var(--ex-pattern-mask, radial-gradient(90% 80% at 50% 50%, #000 5%, transparent 74%));
    z-index: -1;
}

/* Soft brand glow blob for corners of light sections. */
.ex-glow { position: absolute; border-radius: 50%; filter: blur(60px); opacity: .55; pointer-events: none; z-index: -1; }
.ex-glow--blue { background: radial-gradient(circle, rgba(21, 94, 239, .45), transparent 70%); }
.ex-glow--cyan { background: radial-gradient(circle, rgba(0, 184, 217, .42), transparent 70%); }

/* Thin brand rule used to divide sections. */
.ex-rule { height: 3px; width: 56px; border-radius: 3px; background: linear-gradient(90deg, var(--blue), var(--cyan)); border: 0; margin: 0 0 var(--sp-5); }
.ex-hairline { height: 1px; background: linear-gradient(90deg, transparent, var(--border), transparent); border: 0; margin: 0; }

/* "Real UI element" floating cards for hero compositions. */
.ex-floatcard {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-lg);
    padding: var(--sp-4) var(--sp-5);
    display: flex;
    align-items: center;
    gap: var(--sp-4);
    color: var(--text);
}
.ex-floatcard__label { font-size: var(--fs-xs); color: var(--muted); text-transform: uppercase; letter-spacing: .08em; font-weight: var(--fw-bold); }
.ex-floatcard__value { font-size: 1.5rem; font-weight: var(--fw-extrabold); color: var(--navy); line-height: 1.1; }
.ex-floatcard--drift { animation: ex-drift 6s ease-in-out infinite; }
.ex-floatcard--drift-slow { animation: ex-drift 8.5s ease-in-out infinite reverse; }
@keyframes ex-drift { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-9px); } }

/* Sparkline: pure SVG, stroke uses currentColor. */
.ex-sparkline { display: block; width: 100%; height: auto; color: var(--blue); }
.ex-sparkline path { vector-effect: non-scaling-stroke; }

/* Ring / donut progress meter, no JS. Set --ex-ring-pct: 0-100. */
.ex-ring {
    --ex-ring-pct: 0;
    width: var(--ex-ring-size, 96px);
    height: var(--ex-ring-size, 96px);
    border-radius: 50%;
    display: grid; place-items: center;
    background:
        conic-gradient(var(--blue) calc(var(--ex-ring-pct) * 1%), var(--surface-3) 0);
    position: relative;
}
.ex-ring::before {
    content: '';
    position: absolute;
    inset: 9px;
    border-radius: 50%;
    background: var(--surface);
}
.ex-ring__value { position: relative; font-weight: var(--fw-bold); color: var(--navy); font-size: .95rem; }


/* ==========================================================================
   9b. PUBLIC MARKETING PAGE COMPOSITION KIT
   --------------------------------------------------------------------------
   Built ON TOP of §9. §9 supplies the raw ingredients (mesh, patterns, glow,
   floatcard, sparkline, ring); this section assembles them into the repeating
   page structures the public site actually needs — heroes, page headers, stat
   strips, programme cards, process/phase timelines, the responsive test
   schedule, the accordion, the scorecard, topper/faculty tiles and the auth
   split screen.

   Everything here is layout + surface. No page-specific one-offs, so a later
   page can reuse a block without copying CSS into a <style> tag.
   ========================================================================== */

/* ---- 9b.1 Marketing hero ------------------------------------------------ */
.ex-hero {
    position: relative;
    isolation: isolate;
    overflow: hidden;
    padding-block: clamp(2.5rem, 6vw, 5.5rem);
}
.ex-hero__inner {
    display: grid;
    gap: clamp(2.5rem, 5vw, 4rem);
    align-items: center;
    grid-template-columns: 1fr;
}
@media (min-width: 992px) {
    .ex-hero__inner { grid-template-columns: minmax(0, 1.08fr) minmax(0, 1fr); }
}
.ex-hero__copy { min-width: 0; position: relative; z-index: 2; }
.ex-hero__title { margin: 0 0 var(--sp-5); }
.ex-hero__title em { font-style: normal; color: var(--cyan); }
.ex-hero__lead { max-width: 44ch; margin-bottom: var(--sp-7); }
.ex-hero__actions { display: flex; flex-wrap: wrap; gap: var(--sp-3); }

/* Eyebrow rendered as a bordered pill — the hero's own kicker treatment. */
.ex-hero-badge {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-3);
    padding: .45rem .95rem .45rem .7rem;
    margin-bottom: var(--sp-5);
    border: 1px solid var(--glass-border);
    border-radius: var(--r-pill);
    background: var(--glass-bg);
    font-size: var(--fs-eyebrow);
    font-weight: var(--fw-bold);
    letter-spacing: var(--tracking-eyebrow);
    text-transform: uppercase;
    color: #fff;
    line-height: 1.4;
    max-width: 100%;
}
.ex-hero-badge__dot {
    width: 7px; height: 7px; flex: none;
    border-radius: 50%;
    background: var(--cyan);
    box-shadow: 0 0 0 4px rgba(0, 184, 217, .22);
}
.ex-hero-badge--light {
    background: var(--blue-50);
    border-color: var(--blue-100);
    color: var(--blue-700);
}

/* Checkmark trio under the hero CTAs. */
.ex-checktrio {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-4) var(--sp-6);
    margin: var(--sp-8) 0 0;
    padding: var(--sp-6) 0 0;
    border-top: 1px solid var(--glass-border);
    list-style: none;
}
.ex-checktrio > li {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    font-size: var(--fs-sm);
    font-weight: var(--fw-medium);
    color: #fff;
}
.ex-checktrio__tick {
    display: inline-flex; align-items: center; justify-content: center;
    width: 22px; height: 22px; flex: none;
    border-radius: 50%;
    background: rgba(0, 184, 217, .18);
    color: var(--cyan);
}

/* ---- 9b.2 Hero art: layered "real UI" float cards ----------------------- */
/*
 | The composition is a grid, not absolute positioning: absolute children can
 | overflow the viewport at odd widths, and this page must have zero horizontal
 | overflow at 320px. Cards are nudged with margins inside their own cell, so
 | the container always measures them.
 */
.ex-hero__art {
    position: relative;
    min-width: 0;
    display: grid;
    gap: var(--sp-4);
    grid-template-columns: repeat(2, minmax(0, 1fr));
    align-content: center;
}
.ex-hero__art > * { min-width: 0; }
.ex-hero__art .ex-floatcard { flex-direction: column; align-items: stretch; gap: var(--sp-3); }
.ex-hero__art-wide { grid-column: 1 / -1; }
@media (min-width: 992px) {
    /* Stagger on desktop for depth without absolute positioning. */
    .ex-hero__art-lift { transform: translateY(-18px); }
    .ex-hero__art-drop { transform: translateY(18px); }
}
@media (prefers-reduced-motion: reduce) {
    .ex-hero__art-lift, .ex-hero__art-drop { transform: none; }
}

/* A float card whose head is a label + status chip row. */
.ex-floatcard__head {
    display: flex; align-items: center; justify-content: space-between;
    gap: var(--sp-3);
}
.ex-floatcard__sub { font-size: var(--fs-xs); color: var(--muted); }
.ex-floatcard__bar {
    height: 6px; border-radius: var(--r-pill);
    background: var(--surface-3);
    overflow: hidden;
}
.ex-floatcard__bar > span {
    display: block; height: 100%;
    border-radius: inherit;
    background: linear-gradient(90deg, var(--blue), var(--cyan));
}
.ex-floatcard__rows { display: grid; gap: var(--sp-2); }
.ex-floatcard__row {
    display: flex; align-items: center; justify-content: space-between;
    gap: var(--sp-3);
    font-size: var(--fs-xs);
    color: var(--text-2);
}
.ex-floatcard__row b { color: var(--navy); font-weight: var(--fw-bold); }
/* Glass variant, for a card that should read as part of the dark composition. */
.ex-floatcard--glass {
    background: var(--glass-bg-strong);
    border-color: var(--glass-border);
    -webkit-backdrop-filter: blur(var(--glass-blur));
            backdrop-filter: blur(var(--glass-blur));
    box-shadow: var(--shadow-float);
    color: #fff;
}
.ex-floatcard--glass .ex-floatcard__label { color: var(--cyan-200); }
.ex-floatcard--glass .ex-floatcard__value,
.ex-floatcard--glass .ex-floatcard__row b { color: #fff; }
.ex-floatcard--glass .ex-floatcard__sub,
.ex-floatcard--glass .ex-floatcard__row { color: var(--on-dark-muted); }
.ex-floatcard--glass .ex-floatcard__bar { background: rgba(255, 255, 255, .16); }
.ex-floatcard--solid { box-shadow: var(--shadow-float); }

/* ---- 9b.3 Compact page header (replaces the legacy .hero on inner pages) - */
.ex-pagehead {
    position: relative;
    isolation: isolate;
    overflow: hidden;
    padding-block: clamp(2.25rem, 5vw, 4.25rem);
}
.ex-pagehead__inner { max-width: 62rem; }
.ex-pagehead h1 { margin-bottom: var(--sp-4); }
.ex-pagehead__lead { max-width: 58ch; margin: 0; font-size: var(--fs-lead); line-height: var(--lh-snug); }
.ex-pagehead__meta { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-top: var(--sp-5); }
.ex-pagehead__actions { display: flex; flex-wrap: wrap; gap: var(--sp-3); margin-top: var(--sp-7); }
/* Breadcrumb-ish trail above the H1. */
.ex-crumbs {
    display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2);
    margin: 0 0 var(--sp-4); padding: 0; list-style: none;
    font-size: var(--fs-xs); color: var(--on-dark-muted);
}
.ex-crumbs a { color: var(--on-dark-muted); }
.ex-crumbs a:hover { color: var(--on-dark); }
/* The crumb type is --fs-xs, which gives a 19px-tall hit box. On touch that is
   below the 24px WCAG 2.2 minimum, so pad the link out on small screens without
   moving the trail (the row keeps its own line-height). */
@media (max-width: 767.98px) {
    .ex-crumbs a { display: inline-flex; align-items: center; min-height: 32px; }
    .ex-crumbs { margin-bottom: var(--sp-2); }
}
.ex-crumbs li + li::before { content: '/'; margin-right: var(--sp-2); opacity: .5; }
.ex-crumbs li { display: flex; align-items: center; }
.ex-crumbs [aria-current] { color: #fff; }

/* ---- 9b.4 Statistics strip ---------------------------------------------- */
.ex-statstrip {
    display: grid;
    gap: var(--sp-6);
    grid-template-columns: repeat(auto-fit, minmax(min(150px, 100%), 1fr));
}
.ex-statstrip > * {
    position: relative;
    padding-inline: var(--sp-5);
    text-align: center;
}
.ex-statstrip > * + *::before {
    content: '';
    position: absolute;
    left: 0; top: 12%; bottom: 12%;
    width: 1px;
    background: linear-gradient(180deg, transparent, var(--border), transparent);
}
.ex-on-dark .ex-statstrip > * + *::before {
    background: linear-gradient(180deg, transparent, var(--on-dark-border), transparent);
}
.ex-statstrip .ex-stat { align-items: center; text-align: center; }
.ex-statstrip .ex-stat__value { white-space: nowrap; }

/* ---- 9b.5 Premium programme card ---------------------------------------- */
.ex-progcard {
    position: relative;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    border: 1px solid var(--border);
    border-radius: var(--r-2xl);
    background: var(--surface);
    box-shadow: var(--shadow-sm);
    transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.ex-progcard:hover { transform: translateY(-4px); box-shadow: var(--shadow-xl); border-color: var(--blue-200); }
.ex-progcard:focus-within { border-color: var(--blue-300); }
/* Motif band across the top — a drawn academic/scientific graphic, never a photo. */
.ex-progcard__motif {
    position: relative;
    height: clamp(128px, 20vw, 168px);
    background: var(--navy);
    background-image:
        radial-gradient(70% 100% at 88% 0%, rgba(0, 184, 217, .3) 0%, transparent 60%),
        radial-gradient(60% 90% at 4% 100%, rgba(21, 94, 239, .38) 0%, transparent 62%);
    overflow: hidden;
    display: flex;
    align-items: flex-end;
    padding: var(--sp-5);
}
.ex-progcard__motif svg.ex-motif-art {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    color: rgba(255, 255, 255, .34);
}
.ex-progcard__motif-badges { position: relative; display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.ex-progcard__body { padding: var(--sp-7) var(--sp-6) var(--sp-6); display: flex; flex-direction: column; flex: 1 1 auto; }
.ex-progcard__title { margin: 0 0 var(--sp-3); font-size: var(--fs-h3); }
.ex-progcard__desc { color: var(--muted); font-size: .9375rem; margin-bottom: var(--sp-5); }
.ex-progcard__list { margin: 0 0 var(--sp-6); }
.ex-progcard__foot { margin-top: auto; display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-4); }
.ex-progcard__meta { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-5); font-size: var(--fs-xs); color: var(--muted); }
.ex-progcard__meta b { color: var(--navy); font-weight: var(--fw-bold); font-size: var(--fs-sm); }
/* Whole card clickable, one real focusable link. */
.ex-progcard__link::after { content: ''; position: absolute; inset: 0; z-index: 1; }
.ex-progcard .ex-btn { position: relative; z-index: 2; }

/* ---- 9b.6 Icon feature card --------------------------------------------- */
.ex-feature {
    display: flex;
    flex-direction: column;
    gap: var(--sp-3);
    padding: var(--sp-6);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    background: var(--surface);
    height: 100%;
    transition: box-shadow var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.ex-feature:hover { box-shadow: var(--shadow-md); border-color: var(--blue-200); }
.ex-feature__icon {
    display: inline-flex; align-items: center; justify-content: center;
    width: 44px; height: 44px; flex: none;
    border-radius: var(--r-md);
    background: var(--blue-50);
    color: var(--blue);
}
.ex-feature__title { margin: 0; font-size: var(--fs-h5); color: var(--navy); font-weight: var(--fw-semibold); }
.ex-feature__text { margin: 0; font-size: .9375rem; color: var(--muted); }
.ex-on-dark .ex-feature {
    background: var(--glass-bg);
    border-color: var(--glass-border);
    -webkit-backdrop-filter: blur(var(--glass-blur));
            backdrop-filter: blur(var(--glass-blur));
}
.ex-on-dark .ex-feature:hover { border-color: rgba(255, 255, 255, .36); box-shadow: none; }
.ex-on-dark .ex-feature__icon { background: rgba(0, 184, 217, .16); color: var(--cyan-200); }
.ex-on-dark .ex-feature__title { color: #fff; }
.ex-on-dark .ex-feature__text { color: var(--on-dark-muted); }

/* ---- 9b.7 Numbered process timeline ------------------------------------- */
/*
 | Mobile: a vertical rail with the connector drawn between the step numbers.
 | >= 768px: the same list becomes a horizontal track. The connector is a
 | ::before on the <li>, so it can never be longer than the list itself.
 */
.ex-steps { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-6); }
.ex-steps__item { position: relative; display: grid; grid-template-columns: 52px minmax(0, 1fr); gap: var(--sp-4); }
.ex-steps__item::before {
    content: '';
    position: absolute;
    left: 25px; top: 52px; bottom: calc(var(--sp-6) * -1);
    width: 2px;
    background: linear-gradient(180deg, var(--blue-200), var(--border));
}
.ex-steps__item:last-child::before { display: none; }
.ex-steps__num {
    display: inline-flex; align-items: center; justify-content: center;
    width: 52px; height: 52px; flex: none;
    border-radius: var(--r-lg);
    background: var(--surface);
    border: 1px solid var(--border);
    box-shadow: var(--shadow-xs);
    color: var(--blue);
    position: relative;
    z-index: 1;
}
.ex-steps__index {
    display: block;
    font-size: var(--fs-xs);
    font-weight: var(--fw-bold);
    letter-spacing: var(--tracking-eyebrow);
    color: var(--blue);
    margin-bottom: var(--sp-1);
}
.ex-steps__title { margin: 0 0 var(--sp-1); font-size: var(--fs-h5); color: var(--navy); font-weight: var(--fw-semibold); }
.ex-steps__text { margin: 0; font-size: .9375rem; color: var(--muted); }
@media (min-width: 768px) {
    .ex-steps {
        grid-auto-flow: column;
        grid-auto-columns: minmax(0, 1fr);
        gap: var(--sp-5);
    }
    .ex-steps--wrap {
        grid-auto-flow: row;
        grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr));
    }
    .ex-steps__item { grid-template-columns: minmax(0, 1fr); gap: var(--sp-4); }
    .ex-steps__item::before {
        left: 52px; right: calc(var(--sp-5) * -1);
        top: 25px; bottom: auto;
        width: auto; height: 2px;
        background: linear-gradient(90deg, var(--blue-200), var(--border));
    }
}

/* ---- 9b.8 Phase timeline (AITS test phases) ----------------------------- */
/* `min-width: 0` on the items is load-bearing: a grid item defaults to
   `min-width: auto`, so the wide schedule table inside a phase would refuse to
   shrink and would push the whole page sideways between 768px and ~900px. */
.ex-phases { display: grid; gap: var(--sp-5); }
.ex-phases > * { min-width: 0; }
.ex-phase {
    position: relative;
    min-width: 0;
    padding-left: var(--sp-8);
    padding-bottom: var(--sp-2);
}
.ex-phase::before {
    content: '';
    position: absolute;
    left: 7px; top: 22px; bottom: calc(var(--sp-5) * -1 - var(--sp-2));
    width: 2px;
    background: linear-gradient(180deg, var(--blue-200), var(--border-subtle));
}
.ex-phases > .ex-phase:last-child::before { display: none; }
.ex-phase__dot {
    position: absolute;
    left: 0; top: 8px;
    width: 16px; height: 16px;
    border-radius: 50%;
    background: var(--surface);
    border: 3px solid var(--blue);
}
.ex-phase__head {
    display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--sp-3);
    margin-bottom: var(--sp-4);
}
.ex-phase__title { margin: 0; font-size: var(--fs-h4); color: var(--navy); }
.ex-phase__range { font-size: var(--fs-sm); color: var(--muted); }

/* ---- 9b.9 Premium data table + mobile card transformation --------------- */
.ex-table-wrap {
    min-width: 0;
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    background: var(--surface);
    overflow: hidden;
    box-shadow: var(--shadow-xs);
}
.ex-table-wrap > .ex-scroll-x { max-width: 100%; }
.ex-table { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }
.ex-table th, .ex-table td { text-align: left; }
.ex-table thead th {
    position: sticky; top: 0; z-index: 1;
    background: var(--bg);
    padding: var(--sp-3) var(--sp-5);
    font-size: var(--fs-xs);
    font-weight: var(--fw-bold);
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--muted);
    white-space: nowrap;
    border-bottom: 1px solid var(--border);
}
.ex-table tbody td {
    padding: var(--sp-4) var(--sp-5);
    font-size: .9rem;
    color: var(--text-2);
    border-bottom: 1px solid var(--border-subtle);
    vertical-align: top;
}
.ex-table tbody tr:last-child td { border-bottom: 0; }
.ex-table tbody tr { transition: background-color var(--dur) var(--ease); }
.ex-table tbody tr:hover { background: var(--blue-50); }
.ex-table__strong { color: var(--navy); font-weight: var(--fw-semibold); }
.ex-table__nowrap { white-space: nowrap; }
.ex-table__syllabus { max-width: 30rem; font-size: var(--fs-sm); color: var(--muted); }
.ex-table__num { width: 3.5rem; color: var(--muted); font-variant-numeric: tabular-nums; }

/*
 | MOBILE: the same <table> markup renders as a stack of cards. Every <td>
 | carries data-label="…" which becomes the row's key. This is a real
 | transformation, not a squashed table — the table roles are dropped so a
 | screen reader reads the cards as a list of groups rather than as a table
 | whose header association has been visually destroyed.
 */
@media (max-width: 767.98px) {
    .ex-table--cards { display: block; }
    /* thead stays in the a11y tree but leaves the page visually. `clip-path` is
       the modern half of the pattern; `clip` is kept for older engines. The
       `position: static` on the cells matters: .ex-table thead th is sticky, and
       a sticky descendant of a clipped box is exactly the case engines disagree
       about — pinning it back to static keeps the header's 675px-wide row from
       laying out past the viewport edge on a 320px phone. */
    .ex-table--cards thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0,0,0,0); clip-path: inset(50%); white-space: nowrap; }
    .ex-table--cards thead th { position: static; }
    .ex-table--cards tbody { display: grid; gap: var(--sp-4); }
    .ex-table--cards tbody tr {
        display: block;
        border: 1px solid var(--border);
        border-radius: var(--r-lg);
        background: var(--surface);
        padding: var(--sp-5);
        box-shadow: var(--shadow-xs);
    }
    .ex-table--cards tbody tr:hover { background: var(--surface); }
    .ex-table--cards tbody td {
        display: grid;
        grid-template-columns: minmax(7.5rem, 40%) minmax(0, 1fr);
        gap: var(--sp-3);
        align-items: baseline;
        padding: var(--sp-2) 0;
        border-bottom: 1px solid var(--border-subtle);
        white-space: normal;
    }
    .ex-table--cards tbody td:last-child { border-bottom: 0; padding-bottom: 0; }
    .ex-table--cards tbody td::before {
        content: attr(data-label);
        font-size: var(--fs-xs);
        font-weight: var(--fw-bold);
        letter-spacing: .05em;
        text-transform: uppercase;
        color: var(--muted);
    }
    /* The lead cell becomes the card's title row. */
    .ex-table--cards tbody td.ex-table__lead {
        display: block;
        padding-top: 0;
        margin-bottom: var(--sp-2);
        font-size: var(--fs-h5);
        color: var(--navy);
        font-weight: var(--fw-semibold);
    }
    .ex-table--cards tbody td.ex-table__lead::before { display: none; }
    .ex-table--cards .ex-table__num { display: none; }
    .ex-table--cards .ex-table__syllabus { max-width: none; }
    .ex-table-wrap--cards { border: 0; border-radius: 0; background: none; box-shadow: none; overflow: visible; }
}

/* ---- 9b.10 Key/value fact list ------------------------------------------ */
.ex-facts { margin: 0; display: grid; gap: 0; }
.ex-facts > div {
    display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between;
    gap: var(--sp-3);
    padding: var(--sp-3) 0;
    border-bottom: 1px solid var(--border-subtle);
}
.ex-facts > div:last-child { border-bottom: 0; padding-bottom: 0; }
.ex-facts dt { font-size: var(--fs-sm); color: var(--muted); margin: 0; }
.ex-facts dd { margin: 0; font-weight: var(--fw-semibold); color: var(--navy); font-size: .9375rem; text-align: right; }

/* ---- 9b.11 Accessible accordion (no Bootstrap collapse) ----------------- */
.ex-accordion { display: grid; gap: var(--sp-3); }
.ex-accordion__item {
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    background: var(--surface);
    overflow: hidden;
    transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.ex-accordion__item:has(.ex-accordion__trigger[aria-expanded='true']) {
    border-color: var(--blue-200);
    box-shadow: var(--shadow-sm);
}
.ex-accordion__heading { margin: 0; }
.ex-accordion__trigger {
    display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-4);
    width: 100%;
    padding: var(--sp-5) var(--sp-5);
    background: none;
    border: 0;
    font-family: inherit;
    font-size: 1rem;
    font-weight: var(--fw-semibold);
    line-height: var(--lh-snug);
    color: var(--navy);
    text-align: left;
    cursor: pointer;
}
.ex-accordion__trigger:hover { color: var(--blue); }
.ex-accordion__trigger:focus-visible { outline: var(--focus-outline); outline-offset: -3px; }
.ex-accordion__icon {
    flex: none; margin-top: .15em;
    color: var(--blue);
    transition: transform var(--dur) var(--ease);
}
.ex-accordion__trigger[aria-expanded='true'] .ex-accordion__icon { transform: rotate(180deg); }
.ex-accordion__panel { padding: 0 var(--sp-5) var(--sp-5); color: var(--muted); font-size: .9375rem; line-height: var(--lh-body); }
.ex-accordion__panel[hidden] { display: none; }

/* ---- 9b.12 Public scorecard --------------------------------------------- */
.ex-scorecard { border: 1px solid var(--border); border-radius: var(--r-xl); background: var(--surface); overflow: hidden; box-shadow: var(--shadow-md); }
.ex-scorecard__head {
    position: relative;
    padding: var(--sp-6);
    background: var(--navy);
    background-image:
        radial-gradient(70% 120% at 92% 0%, rgba(0, 184, 217, .3) 0%, transparent 58%),
        radial-gradient(60% 100% at 0% 100%, rgba(21, 94, 239, .34) 0%, transparent 60%);
    color: #fff;
    display: flex; flex-wrap: wrap; gap: var(--sp-5) var(--sp-8); justify-content: space-between;
}
.ex-scorecard__who { min-width: 0; }
.ex-scorecard__name { margin: 0; font-size: var(--fs-h3); color: #fff; }
.ex-scorecard__ids { margin: var(--sp-2) 0 0; font-size: var(--fs-sm); color: var(--on-dark-muted); }
.ex-scorecard__ids code { color: #fff; background: rgba(255, 255, 255, .12); padding: .1rem .4rem; border-radius: var(--r-xs); }
.ex-scorecard__exam { text-align: right; min-width: 0; }
@media (max-width: 575.98px) { .ex-scorecard__exam { text-align: left; } }
.ex-scorecard__metrics {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(150px, 45%), 1fr));
    border-bottom: 1px solid var(--border);
}
.ex-scorecard__metric {
    padding: var(--sp-5) var(--sp-6);
    border-right: 1px solid var(--border-subtle);
    border-bottom: 1px solid var(--border-subtle);
}
.ex-scorecard__metric:last-child { border-right: 0; }
.ex-scorecard__metric-label { display: block; font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: .07em; font-weight: var(--fw-bold); color: var(--muted); }
.ex-scorecard__metric-value { display: block; margin-top: var(--sp-2); font-size: clamp(1.5rem, 1.2rem + 1vw, 2rem); font-weight: var(--fw-extrabold); color: var(--navy); line-height: 1.1; letter-spacing: var(--tracking-tight); }
.ex-scorecard__metric-value small { font-size: .55em; font-weight: var(--fw-medium); color: var(--muted); }
.ex-scorecard__metric--hero { background: var(--blue-50); }
.ex-scorecard__metric--hero .ex-scorecard__metric-value { color: var(--blue-800); }
.ex-scorecard__body { padding: var(--sp-6); }
.ex-scorecard__chart { position: relative; height: 260px; }

/* ---- 9b.13 Topper / person tile ----------------------------------------- */
.ex-person {
    position: relative;
    display: flex; flex-direction: column;
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    background: var(--surface);
    overflow: hidden;
    transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.ex-person:hover { transform: translateY(-3px); box-shadow: var(--shadow-lg); border-color: var(--blue-200); }
.ex-person__body { padding: var(--sp-4); display: grid; gap: var(--sp-1); }
.ex-person__score { font-size: 1.35rem; font-weight: var(--fw-extrabold); color: var(--navy); line-height: 1.1; font-variant-numeric: tabular-nums; }
.ex-person__name { font-size: .9375rem; font-weight: var(--fw-semibold); color: var(--text-2); line-height: var(--lh-snug); }
.ex-person__meta { font-size: var(--fs-xs); color: var(--muted); }
.ex-person__rankchip {
    position: absolute; top: var(--sp-3); left: var(--sp-3);
    z-index: 1;
}

/* Faculty card — designed to look intentional with a single entry. */
.ex-facultycard {
    display: grid;
    gap: var(--sp-6);
    grid-template-columns: 1fr;
    align-items: start;
    padding: clamp(1.5rem, 4vw, 2.5rem);
    border: 1px solid var(--border);
    border-radius: var(--r-2xl);
    background: var(--surface);
    box-shadow: var(--shadow-sm);
}
@media (min-width: 768px) { .ex-facultycard { grid-template-columns: 200px minmax(0, 1fr); gap: var(--sp-8); } }
.ex-facultycard__name { margin: 0 0 var(--sp-1); font-size: var(--fs-h3); }
.ex-facultycard__role { margin: 0 0 var(--sp-5); color: var(--blue); font-weight: var(--fw-semibold); font-size: .9375rem; }
.ex-facultycard__tags { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-bottom: var(--sp-5); }
.ex-facultycard__bio { color: var(--muted); margin: 0; }

/* ---- 9b.14 Quick-link tile ---------------------------------------------- */
.ex-quicklink {
    position: relative;
    display: flex; flex-direction: column; gap: var(--sp-3);
    height: 100%;
    padding: var(--sp-6);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    background: var(--surface);
    transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.ex-quicklink:hover { transform: translateY(-3px); box-shadow: var(--shadow-lg); border-color: var(--blue-200); }
.ex-quicklink__icon {
    display: inline-flex; align-items: center; justify-content: center;
    width: 44px; height: 44px;
    border-radius: var(--r-md);
    background: var(--blue-50); color: var(--blue);
}
.ex-quicklink__title { margin: 0; font-size: var(--fs-h5); color: var(--navy); font-weight: var(--fw-semibold); }
.ex-quicklink__text { margin: 0; font-size: var(--fs-sm); color: var(--muted); }
.ex-quicklink__arrow { margin-top: auto; padding-top: var(--sp-3); color: var(--blue); display: inline-flex; align-items: center; gap: .35rem; font-size: var(--fs-sm); font-weight: var(--fw-semibold); }
.ex-quicklink:hover .ex-quicklink__arrow svg { transform: translateX(3px); }
.ex-quicklink__arrow svg { transition: transform var(--dur) var(--ease-out); }

/* ---- 9b.15 Prose block (About storytelling) ----------------------------- */
.ex-prose { max-width: 68ch; }
.ex-prose > p { color: var(--muted); font-size: var(--fs-lead); line-height: var(--lh-body); }
.ex-prose > p:first-of-type { color: var(--text-2); }
.ex-pullquote {
    margin: 0;
    padding: var(--sp-6) var(--sp-7);
    border-left: 3px solid var(--blue);
    border-radius: 0 var(--r-lg) var(--r-lg) 0;
    background: var(--blue-50);
    color: var(--navy);
    font-size: var(--fs-lead);
    line-height: var(--lh-snug);
    font-weight: var(--fw-medium);
}

/* ---- 9b.16 CTA band ------------------------------------------------------ */
.ex-cta {
    position: relative;
    isolation: isolate;
    overflow: hidden;
    border-radius: var(--r-2xl);
    padding: clamp(2rem, 5vw, 3.5rem);
    display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
    gap: var(--sp-6);
}
.ex-cta__copy { max-width: 46ch; min-width: 0; }
.ex-cta__copy h2 { margin-bottom: var(--sp-3); }
.ex-cta__copy p { margin: 0; }
.ex-cta__actions { display: flex; flex-wrap: wrap; gap: var(--sp-3); }

/* ---- 9b.17 Auth split screen -------------------------------------------- */
.ex-auth { display: grid; grid-template-columns: 1fr; min-height: 100vh; }
@media (min-width: 992px) { .ex-auth { grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); } }
.ex-auth__brand {
    position: relative;
    isolation: isolate;
    overflow: hidden;
    display: flex; flex-direction: column; justify-content: space-between;
    gap: var(--sp-8);
    padding: clamp(2rem, 5vw, 4rem);
    min-height: 220px;
}
.ex-auth__logo-plate { display: inline-flex; padding: .55rem .8rem; background: #fff; border-radius: var(--r-md); }
.ex-auth__logo-plate img { height: 40px; width: auto; display: block; }
.ex-auth__form-side {
    display: flex; align-items: center; justify-content: center;
    padding: clamp(2rem, 5vw, 4rem) var(--container-pad);
    background: var(--surface);
}
.ex-auth__form { width: 100%; max-width: 27rem; }
.ex-auth__switch {
    display: inline-flex;
    padding: 3px;
    gap: 3px;
    border-radius: var(--r-pill);
    background: var(--surface-2);
    border: 1px solid var(--border);
    margin-bottom: var(--sp-6);
}
.ex-auth__switch a {
    padding: .45rem 1rem;
    border-radius: var(--r-pill);
    font-size: var(--fs-sm);
    font-weight: var(--fw-semibold);
    color: var(--muted);
}
.ex-auth__switch a.is-active { background: var(--surface); color: var(--navy); box-shadow: var(--shadow-xs); }

/* ---- 9b.18 Verification result states ----------------------------------- */
.ex-verdict {
    display: flex; align-items: center; gap: var(--sp-4);
    padding: var(--sp-6);
    border-radius: var(--r-lg) var(--r-lg) 0 0;
    color: #fff;
}
.ex-verdict__icon {
    display: inline-flex; align-items: center; justify-content: center;
    width: 48px; height: 48px; flex: none;
    border-radius: 50%;
    background: rgba(255, 255, 255, .18);
}
.ex-verdict__title { margin: 0; color: #fff; font-size: var(--fs-h4); }
.ex-verdict__sub { margin: .15rem 0 0; font-size: var(--fs-sm); color: rgba(255, 255, 255, .82); }
.ex-verdict--valid { background: linear-gradient(120deg, var(--success-700), var(--success)); }
.ex-verdict--revoked { background: linear-gradient(120deg, var(--danger-700), var(--danger)); }
.ex-verdict--unknown { background: linear-gradient(120deg, var(--navy), var(--navy-600)); }

/* ---- 9b.19 Form section (long multi-section forms) ---------------------- */
.ex-formsection { border-top: 1px solid var(--border); padding-top: var(--sp-7); margin-top: var(--sp-7); }
.ex-formsection:first-of-type { border-top: 0; padding-top: 0; margin-top: 0; }
.ex-formsection__head { margin-bottom: var(--sp-5); }
.ex-formsection__title { margin: 0 0 var(--sp-1); font-size: var(--fs-h4); }
.ex-formsection__hint { margin: 0; font-size: var(--fs-sm); color: var(--muted); }
/* Two-column field grid that collapses cleanly. */
.ex-formgrid { display: grid; gap: 0 var(--sp-5); grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr)); }
.ex-formgrid--full > * { grid-column: 1 / -1; }
.ex-form-span-all { grid-column: 1 / -1; }
.ex-checkfield {
    display: flex; gap: var(--sp-3); align-items: flex-start;
    padding: var(--sp-4) var(--sp-5);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    background: var(--bg);
}
.ex-checkfield input { margin-top: .2rem; width: 18px; height: 18px; flex: none; accent-color: var(--blue); }
.ex-checkfield label { font-weight: var(--fw-semibold); color: var(--text-2); font-size: .9375rem; }
.ex-checkfield p { margin: var(--sp-1) 0 0; font-size: var(--fs-xs); color: var(--muted); }

/* ---- 9b.20 Search hero panel (results / certificate) -------------------- */
.ex-searchpanel {
    padding: clamp(1.5rem, 4vw, 2.25rem);
    border-radius: var(--r-xl);
    background: var(--surface);
    border: 1px solid var(--border);
    box-shadow: var(--shadow-xl);
}
.ex-searchpanel .ex-field:last-of-type { margin-bottom: var(--sp-5); }

/* ---- 9b.21 Disclosure ("show all …") ------------------------------------
   A <details>/<summary> reveal styled as a button. <details> is used rather
   than JS so the extra content is present, findable and keyboard operable with
   scripting disabled. `white-space: normal` because these labels are long
   sentences, unlike a normal .ex-btn, and must wrap at 320px. */
.ex-more { margin-top: var(--sp-6); }
.ex-more > summary {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .5em;
    white-space: normal;
    text-align: center;
    max-width: 100%;
    list-style: none;
    cursor: pointer;
}
.ex-more > summary::-webkit-details-marker { display: none; }
.ex-more > summary::marker { content: ''; }
.ex-more[open] > summary .ex-more__closed,
.ex-more:not([open]) > summary .ex-more__open { display: none; }

/* ---- 9b.22 Counter animation hook --------------------------------------- */
/* Values start at their final text; JS only animates when it can and when
   reduced motion is off, so a no-JS visitor sees the real number. */
[data-ex-count] { font-variant-numeric: tabular-nums; }


/* ==========================================================================
   10. .app-shell — ENTERPRISE DASHBOARD SCOPE
   --------------------------------------------------------------------------
   Admin / student / school portals add `class="app-shell"` to <body>. Same
   tokens, different density and voice: tighter type, smaller radii, flatter
   surfaces, tabular data first. This is the base a later dashboard-redesign
   agent should build on — add to this section, do not fork it.
   ========================================================================== */

.app-shell {
    --fs-body: .9375rem;
    --fs-h1: 1.5rem;
    --fs-h2: 1.25rem;
    --fs-h3: 1.0625rem;
    --fs-h4: 1rem;
    --fs-lead: 1rem;
    --r-lg: 12px;
    --r-md: 10px;
    --section-y: var(--sp-6);
    --lh-body: 1.55;

    background: var(--bg);
    color: var(--text);
    font-size: var(--fs-body);
}
.app-shell h1, .app-shell h2, .app-shell h3, .app-shell h4, .app-shell h5, .app-shell h6 {
    letter-spacing: -.008em;
    font-weight: var(--fw-semibold);
    margin-bottom: var(--sp-3);
    text-wrap: initial;
}
.app-shell h1 { font-weight: var(--fw-bold); }
.app-shell .card { border-radius: var(--r-lg); box-shadow: none; }
.app-shell .card:hover { box-shadow: var(--shadow-xs); }
.app-shell .card-header { padding: var(--sp-3) var(--sp-5); font-size: .9375rem; }
.app-shell .card-body { padding: var(--sp-5); }
.app-shell .btn { --bs-btn-padding-y: .45rem; --bs-btn-padding-x: .9rem; --bs-btn-font-size: .875rem; border-radius: var(--r-sm); }
.app-shell .btn-lg { --bs-btn-padding-y: .6rem; --bs-btn-padding-x: 1.1rem; --bs-btn-font-size: .9375rem; }
.app-shell .form-control, .app-shell .form-select { min-height: 42px; font-size: .875rem; padding: .45rem .7rem; }
.app-shell .table > tbody > tr > td { padding: .6rem var(--sp-4); font-size: .875rem; }
.app-shell .table > thead > tr > th { padding: .55rem var(--sp-4); }
.app-shell .ex-card { border-radius: var(--r-lg); box-shadow: none; }
.app-shell .ex-card__body { padding: var(--sp-5); }
.app-shell .ex-btn { min-height: 40px; padding: .5rem 1rem; font-size: .875rem; border-radius: var(--r-sm); }
.app-shell .ex-btn--sm { min-height: 34px; padding: .3rem .7rem; }
.app-shell .ex-empty { padding: var(--sp-9) var(--sp-5); }
.app-shell .ex-stat__value { font-size: 1.6rem; }
.app-shell .ex-section-header { margin-bottom: var(--sp-5); }

/* Portal chrome shared by all three sidebars. Sidebar/topbar geometry stays
   in each layout for now; the *colours* come from here. */
.app-shell .admin-sidebar,
.app-shell .student-sidebar,
.app-shell .school-sidebar {
    background: var(--navy);
    border-right: 1px solid rgba(255, 255, 255, .06);
}
.app-shell .admin-sidebar .nav-link,
.app-shell .student-sidebar .nav-link,
.app-shell .school-sidebar .nav-link {
    color: #A9BAD0;
    border-radius: 0 var(--r-sm) var(--r-sm) 0;
    margin-right: var(--sp-3);
    font-weight: var(--fw-medium);
    transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.app-shell .admin-sidebar .nav-link:hover,
.app-shell .student-sidebar .nav-link:hover,
.app-shell .school-sidebar .nav-link:hover { background: rgba(255, 255, 255, .07); color: #fff; }
.app-shell .admin-sidebar .nav-link.active,
.app-shell .student-sidebar .nav-link.active,
.app-shell .school-sidebar .nav-link.active {
    background: rgba(21, 94, 239, .26);
    border-left-color: var(--cyan) !important;
    color: #fff;
}
.app-shell .admin-sidebar .nav-section,
.app-shell .student-sidebar .nav-section,
.app-shell .school-sidebar .nav-section { color: #6E8299; letter-spacing: var(--tracking-eyebrow); }
.app-shell .admin-topbar,
.app-shell .student-topbar,
.app-shell .school-topbar {
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    box-shadow: var(--shadow-header);
    min-height: 60px;
}
/* Legacy portal empty state, restyled so old pages do not look abandoned. */
.app-shell .empty-state { padding: var(--sp-9) var(--sp-5); color: var(--muted); }
.app-shell .empty-state i { color: var(--navy-300); }
.app-shell .empty-state .title { color: var(--navy); font-weight: var(--fw-semibold); }
.app-shell .stat-card .stat-value { color: var(--navy); font-weight: var(--fw-extrabold); }
.app-shell .stat-card .stat-label { color: var(--muted); letter-spacing: .06em; }
.app-shell .stat-card .stat-icon { color: var(--blue); }


/* ==========================================================================
   10b. DASHBOARD KIT  —  added by the dashboard-redesign pass
   --------------------------------------------------------------------------
   Everything below is scoped inside `.app-shell` (or a portal modifier of it)
   so nothing here can reach the public marketing pages. It EXTENDS §10; §10
   itself is untouched.

   Portal voice is set by ONE modifier class on <body>:
     .app-shell--admin    enterprise: squarest radii, tinted panel heads,
                          uppercase micro-labels, densest tables
     .app-shell--school   operational: same skeleton, softer, action-forward
     .app-shell--student  friendliest: largest radii, tinted icon plates,
                          a greeting band instead of a plain page title

   Naming: `.ex-` prefix, BEM for internals, tokens only — no literal colours,
   sizes, radii or shadows anywhere in this section.
   ========================================================================== */

/* ---- 10b.1 Portal voice -------------------------------------------------- */
.app-shell--admin   { --ex-portal: var(--blue); --r-lg: 10px; --r-md: 8px; }
.app-shell--school  { --ex-portal: var(--blue); --r-lg: 12px; }
.app-shell--student { --ex-portal: var(--cyan); --r-lg: 14px; }

/* Content column: caps line length on ultrawide monitors so a 2560px screen
   does not stretch a data table to an unreadable 2400px. */
.app-shell .ex-page { max-width: 1560px; }
.app-shell--student .ex-page { max-width: 1320px; }

/* ---- 10b.2 Page header --------------------------------------------------- */
.ex-pagehead {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--sp-3) var(--sp-4);
    margin-bottom: var(--sp-5);
}
.ex-pagehead__main { min-width: 0; flex: 1 1 20rem; }
.ex-pagehead__title { margin: 0; font-size: 1.375rem; font-weight: var(--fw-bold); color: var(--navy); line-height: 1.2; }
.ex-pagehead__sub { margin: var(--sp-2) 0 0; font-size: var(--fs-sm); color: var(--muted); }
.ex-pagehead__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); }
.app-shell--admin .ex-pagehead { padding-bottom: var(--sp-4); border-bottom: 1px solid var(--border); }

/* Small uppercase group label between blocks of a long dashboard. */
.ex-grouplabel {
    display: flex; align-items: center; gap: var(--sp-3);
    margin: var(--sp-7) 0 var(--sp-3);
    font-size: var(--fs-xs);
    font-weight: var(--fw-bold);
    letter-spacing: var(--tracking-eyebrow);
    text-transform: uppercase;
    color: var(--muted);
}
.ex-grouplabel::after { content: ''; flex: 1; height: 1px; background: var(--border); }
.ex-grouplabel:first-child { margin-top: 0; }

/* ---- 10b.3 Greeting band (student / school dashboards) ------------------- */
.ex-greeting {
    position: relative;
    overflow: hidden;
    border-radius: var(--r-lg);
    padding: var(--sp-6);
    margin-bottom: var(--sp-6);
    background-color: var(--navy);
    background-image:
        radial-gradient(62% 120% at 88% 6%, rgba(0, 184, 217, .30) 0%, transparent 60%),
        radial-gradient(58% 110% at 4% 0%, rgba(21, 94, 239, .34) 0%, transparent 62%);
    color: var(--on-dark-muted);
}
.ex-greeting::before {
    content: '';
    position: absolute; inset: 0; pointer-events: none;
    background-image:
        linear-gradient(rgba(255, 255, 255, .05) 1px, transparent 1px),
        linear-gradient(90deg, rgba(255, 255, 255, .05) 1px, transparent 1px);
    background-size: 30px 30px;
    -webkit-mask-image: radial-gradient(110% 120% at 78% 0%, #000 5%, transparent 74%);
            mask-image: radial-gradient(110% 120% at 78% 0%, #000 5%, transparent 74%);
}
.ex-greeting > * { position: relative; }
.ex-greeting__inner { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-4) var(--sp-6); }
.ex-greeting__text { min-width: 0; flex: 1 1 18rem; }
.ex-greeting__hello { margin: 0; font-size: 1.375rem; font-weight: var(--fw-bold); color: #fff; line-height: 1.2; }
.ex-greeting__meta { margin: var(--sp-2) 0 0; font-size: var(--fs-sm); color: var(--on-dark-muted); display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2) var(--sp-4); }
.ex-greeting__code {
    font-family: var(--font-mono); font-size: var(--fs-xs);
    padding: .18rem .5rem; border-radius: var(--r-xs);
    background: rgba(255, 255, 255, .12); color: #fff;
    border: 1px solid var(--on-dark-border);
}
.ex-greeting__actions { display: flex; flex-wrap: wrap; gap: var(--sp-2); }

/* ---- 10b.4 Stat tiles ---------------------------------------------------- */
.ex-tiles {
    display: grid;
    gap: var(--sp-3);
    grid-template-columns: repeat(auto-fill, minmax(min(var(--ex-tile-min, 200px), 100%), 1fr));
}
.ex-tiles--wide { --ex-tile-min: 250px; }
.ex-tiles--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }

.ex-tile {
    position: relative;
    display: flex;
    align-items: flex-start;
    gap: var(--sp-3);
    min-width: 0;
    padding: var(--sp-4);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    color: inherit;
    text-decoration: none;
    transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
a.ex-tile:hover { border-color: var(--blue-200); box-shadow: var(--shadow-sm); color: inherit; }
a.ex-tile:hover .ex-tile__label { color: var(--blue-700); }
.ex-tile__icon {
    display: inline-flex; align-items: center; justify-content: center;
    width: 34px; height: 34px; flex: none;
    border-radius: var(--r-sm);
    background: var(--blue-50);
    color: var(--blue);
}
.ex-tile__body { min-width: 0; flex: 1; }
.ex-tile__value {
    display: block;
    font-size: 1.5rem;
    font-weight: var(--fw-extrabold);
    line-height: 1.15;
    letter-spacing: var(--tracking-tight);
    color: var(--navy);
    font-variant-numeric: tabular-nums;
    overflow-wrap: anywhere;
}
.ex-tile__value--sm { font-size: 1.0625rem; font-weight: var(--fw-bold); letter-spacing: var(--tracking-snug); }
.ex-tile__label { display: block; margin-top: var(--sp-1); font-size: var(--fs-xs); color: var(--muted); font-weight: var(--fw-medium); }
.ex-tile__hint { display: block; margin-top: var(--sp-1); font-size: var(--fs-xs); color: var(--muted); }
.ex-tile__empty { display: block; font-size: var(--fs-sm); color: var(--muted); font-weight: var(--fw-medium); line-height: 1.5; }

/* Per-portal tile personality. */
.app-shell--admin .ex-tile { padding: var(--sp-3) var(--sp-4); }
.app-shell--admin .ex-tile__label { text-transform: uppercase; letter-spacing: .07em; }
.app-shell--student .ex-tile,
.app-shell--school .ex-tile { flex-direction: column; gap: var(--sp-3); padding: var(--sp-5) var(--sp-4); }
.app-shell--student .ex-tile__icon { width: 38px; height: 38px; border-radius: var(--r-md); }
.app-shell--student .ex-tile__value { font-size: 1.625rem; }

/* Status accents for a tile's icon plate. */
.ex-tile__icon--success { background: var(--success-50); color: var(--success-700); }
.ex-tile__icon--warning { background: var(--warning-50); color: var(--warning-700); }
.ex-tile__icon--danger  { background: var(--danger-50);  color: var(--danger-700); }
.ex-tile__icon--cyan    { background: var(--cyan-50);    color: var(--cyan-700); }
.ex-tile__icon--navy    { background: var(--navy-50);    color: var(--navy); }

/* ---- 10b.5 Panel (the dashboard/section surface) ------------------------- */
.ex-panel {
    display: flex;
    flex-direction: column;
    min-width: 0;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    overflow: hidden;
}
.ex-panel--full { height: 100%; }
.ex-panel__head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-2) var(--sp-3);
    padding: var(--sp-3) var(--sp-4);
    border-bottom: 1px solid var(--border);
    background: var(--surface);
}
.app-shell--admin .ex-panel__head { background: var(--bg); }
.ex-panel__title {
    display: flex; align-items: center; gap: var(--sp-2);
    margin: 0; min-width: 0;
    font-size: .9375rem;
    font-weight: var(--fw-semibold);
    color: var(--navy);
    line-height: 1.3;
}
.ex-panel__title > .ex-icon { color: var(--blue); }
.ex-panel__count {
    font-size: var(--fs-xs); font-weight: var(--fw-semibold);
    color: var(--muted); background: var(--surface-2);
    border-radius: var(--r-pill); padding: .1rem .45rem;
    font-variant-numeric: tabular-nums;
}
.ex-panel__tools { margin-left: auto; display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); }
.ex-panel__link { font-size: var(--fs-sm); font-weight: var(--fw-semibold); color: var(--blue); display: inline-flex; align-items: center; gap: .25rem; }
.ex-panel__body { padding: var(--sp-4); flex: 1 1 auto; min-width: 0; }
.ex-panel__body--flush { padding: 0; }
.ex-panel__foot {
    padding: var(--sp-3) var(--sp-4);
    border-top: 1px solid var(--border);
    background: var(--bg);
    font-size: var(--fs-sm);
    color: var(--muted);
    display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2);
}

/* ---- 10b.6 Data table ---------------------------------------------------- */
/* Wide tables scroll inside .ex-tablewrap; the page never scrolls sideways. */
.ex-tablewrap {
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
    max-width: 100%;
}
.ex-tablewrap--sticky { max-height: 70vh; overflow-y: auto; }

.ex-dt {
    width: 100%;
    margin: 0;
    border-collapse: separate;
    border-spacing: 0;
    font-size: .875rem;
    font-variant-numeric: tabular-nums;
}
.ex-dt th, .ex-dt td { text-align: left; }
.ex-dt > thead > tr > th {
    position: sticky;
    top: 0;
    z-index: 2;
    padding: var(--sp-3) var(--sp-4);
    background: var(--bg);
    color: var(--muted);
    font-size: var(--fs-xs);
    font-weight: var(--fw-bold);
    letter-spacing: .06em;
    text-transform: uppercase;
    white-space: nowrap;
    border-bottom: 1px solid var(--border);
}
.ex-dt > tbody > tr > td {
    padding: var(--sp-3) var(--sp-4);
    vertical-align: middle;
    border-bottom: 1px solid var(--border-subtle);
    color: var(--text-2);
}
.ex-dt > tbody > tr:nth-child(even) > td { background: rgba(11, 31, 58, .012); }
.ex-dt > tbody > tr:hover > td { background: var(--blue-50); }
.ex-dt > tbody > tr:last-child > td { border-bottom: 0; }
.ex-dt__id { color: var(--muted); font-family: var(--font-mono); font-size: var(--fs-xs); width: 1%; white-space: nowrap; }
.ex-dt__strong { color: var(--navy); font-weight: var(--fw-semibold); }
.ex-dt__sub { display: block; font-size: var(--fs-xs); color: var(--muted); font-weight: var(--fw-regular); margin-top: .1rem; }
.ex-dt__num { text-align: right; }
.ex-dt__nowrap { white-space: nowrap; }
.ex-dt__actions { width: 1%; white-space: nowrap; text-align: right; }
.ex-dt__actions > * { vertical-align: middle; }
.ex-dt--compact > tbody > tr > td { padding: var(--sp-2) var(--sp-4); }
.ex-dt__empty { padding: 0 !important; background: var(--surface) !important; }
.ex-dt__empty:hover { background: var(--surface) !important; }
.app-shell--admin .ex-dt { font-size: .8125rem; }
.app-shell--admin .ex-dt > tbody > tr > td { padding: var(--sp-2) var(--sp-4); }

/* Icon-only row action buttons, optically aligned in a row. */
.ex-rowactions { display: inline-flex; align-items: center; gap: var(--sp-1); justify-content: flex-end; }
.ex-rowactions form { display: inline; margin: 0; }
.ex-iconbtn {
    display: inline-flex; align-items: center; justify-content: center;
    width: 32px; height: 32px; flex: none;
    padding: 0;
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    background: var(--surface);
    color: var(--text-2);
    cursor: pointer;
    line-height: 1;
    transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.ex-iconbtn:hover { background: var(--navy-50); border-color: var(--navy-300); color: var(--navy); }
.ex-iconbtn:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.ex-iconbtn--primary:hover { background: var(--blue-50); border-color: var(--blue-200); color: var(--blue-700); }
.ex-iconbtn--success:hover { background: var(--success-50); border-color: var(--success-200); color: var(--success-700); }
.ex-iconbtn--warning:hover { background: var(--warning-50); border-color: var(--warning-200); color: var(--warning-700); }
.ex-iconbtn--danger { color: var(--danger); }
.ex-iconbtn--danger:hover { background: var(--danger-50); border-color: var(--danger-200); color: var(--danger-700); }

/* ---- 10b.7 Mobile "table as cards" -------------------------------------- */
/* For listings where a table would squash below ~640px: render the SAME data
   twice is wasteful, so instead the table cells carry `data-label` and the
   table itself flips to a stacked card layout. */
@media (max-width: 639.98px) {
    .ex-dt--stack, .ex-dt--stack > tbody, .ex-dt--stack > tbody > tr, .ex-dt--stack > tbody > tr > td { display: block; width: auto; }
    .ex-dt--stack > thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; }
    .ex-dt--stack > tbody > tr {
        border: 1px solid var(--border);
        border-radius: var(--r-md);
        padding: var(--sp-2) var(--sp-3);
        margin-bottom: var(--sp-3);
        background: var(--surface);
    }
    .ex-dt--stack > tbody > tr:hover > td { background: none; }
    .ex-dt--stack > tbody > tr:nth-child(even) > td { background: none; }
    .ex-dt--stack > tbody > tr > td {
        display: flex;
        align-items: baseline;
        justify-content: space-between;
        gap: var(--sp-4);
        padding: var(--sp-2) 0;
        border-bottom: 1px solid var(--border-subtle);
        text-align: right;
    }
    .ex-dt--stack > tbody > tr > td:last-child { border-bottom: 0; }
    .ex-dt--stack > tbody > tr > td::before {
        content: attr(data-label);
        flex: none;
        font-size: var(--fs-xs);
        font-weight: var(--fw-bold);
        letter-spacing: .05em;
        text-transform: uppercase;
        color: var(--muted);
        text-align: left;
    }
    .ex-dt--stack > tbody > tr > td[data-label='']::before { display: none; }
    .ex-dt--stack .ex-dt__actions { width: auto; }
    .ex-dt--stack .ex-dt__empty { display: block; }
}

/* ---- 10b.8 Filter / search toolbar -------------------------------------- */
.ex-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: var(--sp-3);
    padding: var(--sp-4);
    margin-bottom: var(--sp-4);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
}
.ex-toolbar__field { display: flex; flex-direction: column; gap: var(--sp-1); min-width: 0; flex: 1 1 12rem; }
.ex-toolbar__field--grow { flex: 2 1 16rem; }
.ex-toolbar__label { font-size: var(--fs-xs); font-weight: var(--fw-semibold); color: var(--muted); letter-spacing: .03em; }
.ex-toolbar__control {
    width: 100%;
    min-height: 40px;
    padding: .4rem .7rem;
    font-family: inherit;
    font-size: .875rem;
    color: var(--text);
    background: var(--surface);
    border: 1px solid var(--border-strong);
    border-radius: var(--r-sm);
    appearance: none;
    transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.ex-toolbar__control:focus { outline: none; border-color: var(--blue); box-shadow: var(--focus-ring); }
select.ex-toolbar__control {
    padding-right: 2.2rem; cursor: pointer;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23667085' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat; background-position: right .6rem center; background-size: 1rem;
}
.ex-toolbar__search { position: relative; }
.ex-toolbar__search > .ex-icon { position: absolute; left: .65rem; top: 50%; transform: translateY(-50%); color: var(--muted-2); pointer-events: none; }
.ex-toolbar__search .ex-toolbar__control { padding-left: 2.2rem; }
.ex-toolbar__actions { display: flex; flex-wrap: wrap; gap: var(--sp-2); flex: none; }

/* ---- 10b.9 Quick actions (school dashboard) ----------------------------- */
.ex-quick {
    display: grid;
    gap: var(--sp-3);
    grid-template-columns: repeat(auto-fit, minmax(min(210px, 100%), 1fr));
}
.ex-quick__item {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    padding: var(--sp-4);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    text-decoration: none;
    color: inherit;
    min-width: 0;
    transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.ex-quick__item:hover { border-color: var(--blue-200); box-shadow: var(--shadow-md); transform: translateY(-2px); color: inherit; }
.ex-quick__icon {
    display: inline-flex; align-items: center; justify-content: center;
    width: 40px; height: 40px; flex: none;
    border-radius: var(--r-md);
    background: linear-gradient(140deg, var(--navy) 0%, var(--blue-800) 100%);
    color: #fff;
}
.ex-quick__text { min-width: 0; }
.ex-quick__title { display: block; font-weight: var(--fw-semibold); color: var(--navy); font-size: .9375rem; line-height: 1.3; }
.ex-quick__desc { display: block; margin-top: .1rem; font-size: var(--fs-xs); color: var(--muted); }
.ex-quick__item > .ex-icon:last-child { margin-left: auto; color: var(--muted-2); flex: none; }

/* ---- 10b.10 Key/value detail list --------------------------------------- */
.ex-kv { margin: 0; display: grid; grid-template-columns: minmax(7rem, auto) 1fr; gap: var(--sp-2) var(--sp-4); font-size: var(--fs-sm); }
.ex-kv > dt { color: var(--muted); font-weight: var(--fw-regular); min-width: 0; }
.ex-kv > dd { margin: 0; color: var(--text-2); font-weight: var(--fw-medium); min-width: 0; overflow-wrap: anywhere; }
.ex-kv--stack { grid-template-columns: 1fr; gap: var(--sp-1); }
.ex-kv--stack > dd { margin-bottom: var(--sp-3); }

/* ---- 10b.11 Row list (recent activity, notices, programmes) ------------- */
.ex-rows { list-style: none; margin: 0; padding: 0; }
.ex-rows > li {
    display: flex;
    align-items: flex-start;
    gap: var(--sp-3);
    padding: var(--sp-3) var(--sp-4);
    border-bottom: 1px solid var(--border-subtle);
    min-width: 0;
}
.ex-rows > li:last-child { border-bottom: 0; }
.ex-rows--hover > li { transition: background-color var(--dur) var(--ease); }
.ex-rows--hover > li:hover { background: var(--bg); }
.ex-row__body { min-width: 0; flex: 1; }
.ex-row__title { display: block; font-weight: var(--fw-semibold); color: var(--navy); font-size: .875rem; line-height: 1.35; }
.ex-row__meta { display: block; margin-top: .15rem; font-size: var(--fs-xs); color: var(--muted); }
.ex-row__aside { flex: none; text-align: right; font-size: var(--fs-xs); color: var(--muted); display: flex; flex-direction: column; align-items: flex-end; gap: var(--sp-1); }
.ex-row__marker {
    display: inline-flex; align-items: center; justify-content: center;
    width: 28px; height: 28px; flex: none;
    border-radius: var(--r-sm);
    background: var(--surface-2); color: var(--muted);
}

/* ---- 10b.12 Chart frame ------------------------------------------------- */
/* Chart.js needs a block-level box with a real height or it grows forever on
   resize. `position: relative` + a fixed height is the documented fix. */
.ex-chart { position: relative; width: 100%; height: var(--ex-chart-h, 240px); min-width: 0; }
.ex-chart--tall { --ex-chart-h: 300px; }
.ex-chart > canvas { max-width: 100%; }

/* ---- 10b.13 Pagination + result count ----------------------------------- */
.app-shell .pagination {
    --bs-pagination-padding-x: .6rem;
    --bs-pagination-padding-y: .3rem;
    --bs-pagination-font-size: .8125rem;
    --bs-pagination-border-radius: var(--r-sm);
    --bs-pagination-color: var(--text-2);
    --bs-pagination-bg: var(--surface);
    --bs-pagination-border-color: var(--border);
    --bs-pagination-hover-bg: var(--bg);
    --bs-pagination-hover-color: var(--navy);
    --bs-pagination-hover-border-color: var(--border-strong);
    --bs-pagination-active-bg: var(--blue);
    --bs-pagination-active-border-color: var(--blue);
    --bs-pagination-disabled-color: var(--muted-2);
    --bs-pagination-disabled-bg: var(--surface);
    --bs-pagination-disabled-border-color: var(--border-subtle);
    margin: 0;
    flex-wrap: wrap;
    gap: var(--sp-1);
}
.app-shell .pagination .page-link { border-radius: var(--r-sm); min-width: 32px; text-align: center; }
.app-shell .pagination .page-item:not(:first-child) .page-link { margin-left: 0; }
.ex-pager {
    display: flex; flex-wrap: wrap; align-items: center;
    justify-content: space-between; gap: var(--sp-3);
    margin-top: var(--sp-4);
}
.ex-pager__count { font-size: var(--fs-xs); color: var(--muted); font-variant-numeric: tabular-nums; }

/* ---- 10b.14 Portal chrome refinements ----------------------------------- */
.app-shell .admin-sidebar,
.app-shell .student-sidebar,
.app-shell .school-sidebar {
    background: var(--navy-900);
    background-image: linear-gradient(180deg, var(--navy) 0%, var(--navy-900) 100%);
    scrollbar-width: thin;
    scrollbar-color: rgba(255, 255, 255, .18) transparent;
}
.app-shell .admin-sidebar::-webkit-scrollbar,
.app-shell .student-sidebar::-webkit-scrollbar,
.app-shell .school-sidebar::-webkit-scrollbar { width: 8px; }
.app-shell .admin-sidebar::-webkit-scrollbar-thumb,
.app-shell .student-sidebar::-webkit-scrollbar-thumb,
.app-shell .school-sidebar::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, .16); border-radius: var(--r-pill); }

.ex-side__brand {
    display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3);
    padding: var(--sp-4);
    border-bottom: 1px solid var(--on-dark-border);
}
.ex-side__logo { display: inline-flex; background: #fff; border-radius: var(--r-sm); padding: .3rem .5rem; }
.ex-side__logo img { height: 28px; width: auto; display: block; }
.ex-side__close {
    display: inline-flex; align-items: center; justify-content: center;
    width: 38px; height: 38px; flex: none;
    border: 1px solid var(--on-dark-border); border-radius: var(--r-sm);
    background: rgba(255, 255, 255, .06); color: #fff; cursor: pointer;
}
.ex-side__close:hover { background: rgba(255, 255, 255, .14); }

.ex-side__identity {
    display: flex; align-items: center; gap: var(--sp-3);
    padding: var(--sp-3) var(--sp-4);
    border-bottom: 1px solid var(--on-dark-border);
    min-width: 0;
}
.ex-side__identity .ex-avatar { background: rgba(255, 255, 255, .12); color: #fff; }
.ex-side__identity-text { min-width: 0; }
.ex-side__name { display: block; color: #fff; font-weight: var(--fw-semibold); font-size: .875rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ex-side__code { display: block; font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--navy-300); letter-spacing: .02em; }

.ex-side__group {
    padding: var(--sp-5) var(--sp-4) var(--sp-2);
    font-size: .65rem;
    font-weight: var(--fw-bold);
    letter-spacing: var(--tracking-eyebrow);
    text-transform: uppercase;
    color: #67809A;
}
.ex-side__list { list-style: none; margin: 0; padding: 0; }
.ex-side__link {
    position: relative;
    display: flex; align-items: center; gap: .65rem;
    width: 100%;
    padding: .5rem var(--sp-4);
    margin-right: var(--sp-3);
    border: 0;
    border-radius: 0 var(--r-sm) var(--r-sm) 0;
    background: none;
    font-family: inherit;
    font-size: .8125rem;
    font-weight: var(--fw-medium);
    text-align: left;
    color: #A9BAD0;
    text-decoration: none;
    cursor: pointer;
    transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.ex-side__link > .ex-icon { flex: none; opacity: .85; }
.ex-side__link:hover { background: rgba(255, 255, 255, .07); color: #fff; }
.ex-side__link:focus-visible { outline: none; box-shadow: var(--focus-ring-on-dark); }
.ex-side__link::before {
    content: '';
    position: absolute; left: 0; top: 0; bottom: 0;
    width: 3px;
    background: var(--ex-portal, var(--cyan));
    transform: scaleY(0);
    transform-origin: center;
    transition: transform var(--dur) var(--ease);
}
.ex-side__link.is-active {
    background: rgba(21, 94, 239, .22);
    color: #fff;
    font-weight: var(--fw-semibold);
}
.ex-side__link.is-active::before { transform: scaleY(1); }
.ex-side__link.is-active > .ex-icon { opacity: 1; color: var(--ex-portal, var(--cyan)); }
.ex-side__link.is-disabled { color: #5A6B80; cursor: not-allowed; }
.ex-side__link.is-disabled:hover { background: none; color: #5A6B80; }
.ex-side__soon {
    margin-left: auto; flex: none;
    font-size: .58rem; letter-spacing: .04em;
    background: rgba(255, 255, 255, .08); color: #8296AE;
    padding: .1rem .35rem; border-radius: var(--r-xs);
}
.ex-side__label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ex-side__divider { margin: var(--sp-3) var(--sp-4); border: 0; border-top: 1px solid var(--on-dark-border); }

/* Topbar */
.app-shell .admin-topbar,
.app-shell .student-topbar,
.app-shell .school-topbar { gap: var(--sp-3); }
.ex-topbar__burger {
    display: inline-flex; align-items: center; justify-content: center;
    width: 38px; height: 38px; flex: none;
    border: 1px solid var(--border); border-radius: var(--r-sm);
    background: var(--surface); color: var(--navy); cursor: pointer;
}
.ex-topbar__burger:hover { background: var(--bg); }
.ex-topbar__title { min-width: 0; font-weight: var(--fw-semibold); color: var(--navy); font-size: .9375rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ex-topbar__right { margin-left: auto; display: flex; align-items: center; gap: var(--sp-2); }
.ex-topbar__ghost {
    display: inline-flex; align-items: center; gap: .35rem;
    padding: .35rem .55rem;
    border-radius: var(--r-sm);
    font-size: var(--fs-xs);
    font-weight: var(--fw-medium);
    color: var(--muted);
    text-decoration: none;
}
.ex-topbar__ghost:hover { background: var(--bg); color: var(--navy); }
.ex-topbar__user {
    display: inline-flex; align-items: center; gap: var(--sp-2);
    padding: .25rem .5rem .25rem .3rem;
    border: 1px solid var(--border); border-radius: var(--r-pill);
    background: var(--surface); color: var(--text-2);
    font-family: inherit; font-size: var(--fs-xs); font-weight: var(--fw-semibold);
    cursor: pointer;
}
.ex-topbar__user:hover { background: var(--bg); border-color: var(--border-strong); }
.ex-topbar__user::after { display: none; }
.app-shell .dropdown-menu { font-size: var(--fs-sm); }
.ex-userpop { min-width: 15rem; }
.ex-userpop__head { padding: var(--sp-2) var(--sp-3) var(--sp-3); }
.ex-userpop__name { font-weight: var(--fw-semibold); color: var(--navy); }
.ex-userpop__mail { font-size: var(--fs-xs); color: var(--muted); overflow-wrap: anywhere; }

/* Footer */
.ex-appfoot {
    padding: var(--sp-4);
    border-top: 1px solid var(--border);
    font-size: var(--fs-xs);
    color: var(--muted);
    text-align: center;
}

/* ---- 10b.15 Misc dashboard atoms ---------------------------------------- */
.ex-progress { height: 6px; border-radius: var(--r-pill); background: var(--surface-3); overflow: hidden; }
.ex-progress__bar { display: block; height: 100%; border-radius: var(--r-pill); background: linear-gradient(90deg, var(--blue), var(--cyan)); }

.ex-note {
    display: flex; gap: var(--sp-3); align-items: flex-start;
    padding: var(--sp-3) var(--sp-4);
    border: 1px solid var(--border);
    border-left: 3px solid var(--blue);
    border-radius: var(--r-md);
    background: var(--blue-50);
    font-size: var(--fs-sm);
    color: var(--blue-800);
}
.ex-note > .ex-icon { flex: none; margin-top: .1em; }
.ex-note--muted { background: var(--bg); border-left-color: var(--border-strong); color: var(--muted); }
.ex-note--warning { background: var(--warning-50); border-color: var(--warning-200); border-left-color: var(--warning); color: var(--warning-700); }

.ex-code { font-family: var(--font-mono); font-size: var(--fs-xs); background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--r-xs); padding: .1rem .35rem; color: var(--text-2); }

/* A legend swatch for chart/status keys. */
.ex-legend { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-4); font-size: var(--fs-xs); color: var(--muted); }
.ex-legend__item { display: inline-flex; align-items: center; gap: var(--sp-2); }
.ex-legend__swatch { width: .75rem; height: .75rem; border-radius: var(--r-xs); flex: none; border: 1px solid var(--border); }

/* Two-column dashboard split that collapses cleanly. */
.ex-split { display: grid; gap: var(--sp-4); grid-template-columns: 1fr; align-items: start; }
@media (min-width: 992px) {
    .ex-split { grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr); }
    .ex-split--even { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
    .ex-split--reverse { grid-template-columns: minmax(0, 1fr) minmax(0, 1.55fr); }
}
.ex-stack-4 { display: grid; gap: var(--sp-4); align-content: start; }

/* Form layout used by the CRUD engine and every portal form. */
.ex-formgrid { display: grid; gap: 0 var(--sp-5); grid-template-columns: repeat(12, minmax(0, 1fr)); }
.ex-formgrid > * { grid-column: span 12; min-width: 0; }
@media (min-width: 768px) {
    .ex-formgrid > .ex-col-2 { grid-column: span 2; }
    .ex-formgrid > .ex-col-3 { grid-column: span 3; }
    .ex-formgrid > .ex-col-4 { grid-column: span 4; }
    .ex-formgrid > .ex-col-6 { grid-column: span 6; }
    .ex-formgrid > .ex-col-8 { grid-column: span 8; }
    .ex-formgrid > .ex-col-9 { grid-column: span 9; }
    .ex-formgrid > .ex-col-12 { grid-column: span 12; }
}
.ex-formactions {
    display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3);
    padding-top: var(--sp-5);
    margin-top: var(--sp-2);
    border-top: 1px solid var(--border);
}
.ex-fieldset { border: 0; padding: 0; margin: 0 0 var(--sp-5); min-width: 0; }
.ex-fieldset__legend {
    padding: 0; margin: 0 0 var(--sp-4);
    font-size: var(--fs-xs); font-weight: var(--fw-bold);
    letter-spacing: var(--tracking-eyebrow); text-transform: uppercase;
    color: var(--muted);
}
/* Checkbox field styled to match .ex-input's box. */
.ex-check {
    display: flex; align-items: flex-start; gap: var(--sp-3);
    padding: var(--sp-3);
    border: 1px solid var(--border-strong);
    border-radius: var(--r-sm);
    background: var(--surface);
    cursor: pointer;
    min-height: 48px;
}
.ex-check:hover { border-color: var(--navy-300); }
.ex-check input { width: 1.05rem; height: 1.05rem; flex: none; margin-top: .12rem; accent-color: var(--blue); }
.ex-check__text { font-size: var(--fs-sm); font-weight: var(--fw-medium); color: var(--text-2); line-height: 1.4; }
/* Read-only "static" field that visually matches an input but is clearly inert. */
.ex-static {
    min-height: 48px;
    display: flex; align-items: center;
    padding: .7rem .875rem;
    border: 1px dashed var(--border-strong);
    border-radius: var(--r-sm);
    background: var(--bg);
    color: var(--text-2);
    font-size: .9375rem;
    overflow-wrap: anywhere;
}

/* File input + current-file preview. */
.ex-filepreview { display: flex; align-items: center; gap: var(--sp-3); margin-bottom: var(--sp-2); font-size: var(--fs-sm); }
.ex-filepreview img { height: 44px; width: auto; border-radius: var(--r-xs); border: 1px solid var(--border); display: block; }

/* ---- 10b.16 Exam-taking screen ------------------------------------------ */
/* Scoped to .ex-exam (the take page is a standalone document, not a portal
   layout, so it opts in explicitly). Class names the page JS depends on
   (.question-card, .nav-btn, .option-row, .timer, .save-badge) are preserved. */
.ex-exam { background: var(--bg); color: var(--text); min-height: 100vh; }

.ex-exam__topbar {
    position: sticky; top: 0; z-index: var(--z-header);
    background: var(--navy-900);
    background-image: linear-gradient(100deg, var(--navy) 0%, var(--navy-900) 100%);
    color: #fff;
    border-bottom: 1px solid rgba(255, 255, 255, .08);
}
.ex-exam__topbar-inner {
    display: flex; flex-wrap: wrap; align-items: center;
    gap: var(--sp-3) var(--sp-4);
    padding: var(--sp-3) var(--sp-4);
    max-width: 1560px; margin-inline: auto;
}
.ex-exam__ident { min-width: 0; flex: 1 1 12rem; }
.ex-exam__name { font-weight: var(--fw-semibold); font-size: .9375rem; color: #fff; line-height: 1.25; overflow-wrap: anywhere; }
.ex-exam__meta { font-size: var(--fs-xs); color: var(--on-dark-muted); margin-top: .1rem; }
.ex-exam__clock {
    display: flex; align-items: center; gap: var(--sp-3);
    padding: .3rem var(--sp-3);
    border: 1px solid var(--on-dark-border);
    border-radius: var(--r-md);
    background: rgba(255, 255, 255, .07);
    flex: none;
}
.ex-exam__clock-label { font-size: .6rem; letter-spacing: var(--tracking-eyebrow); text-transform: uppercase; color: var(--navy-300); line-height: 1.2; }
.ex-exam .timer {
    font-variant-numeric: tabular-nums;
    font-size: 1.25rem;
    font-weight: var(--fw-bold);
    letter-spacing: .04em;
    color: #fff;
    line-height: 1.15;
}
.ex-exam .timer.warn { color: var(--warning); }
.ex-exam .timer.danger { color: #FF8A80; animation: ex-pulse 1.4s var(--ease) infinite; }

.ex-exam .save-badge {
    display: inline-flex; align-items: center; gap: .35rem;
    font-size: var(--fs-xs);
    color: var(--cyan-200);
    opacity: 0;
    transition: opacity var(--dur) var(--ease);
    flex: none;
}
.ex-exam .save-badge.show { opacity: 1; }
.ex-exam .save-badge.error { color: #FF8A80; }

.ex-exam__main { max-width: 1560px; margin-inline: auto; padding: var(--sp-4); }
.ex-exam__grid { display: grid; gap: var(--sp-4); grid-template-columns: 1fr; align-items: start; }
@media (min-width: 992px) {
    .ex-exam__grid { grid-template-columns: minmax(0, 1fr) 320px; }
    .ex-exam__aside { position: sticky; top: calc(64px + var(--sp-4)); }
}

.ex-exam .question-card {
    display: none;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    padding: var(--sp-5);
    min-width: 0;
}
.ex-exam .question-card.active { display: block; }
.ex-exam__qhead { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); margin-bottom: var(--sp-4); }
.ex-exam__qnum {
    display: inline-flex; align-items: center;
    padding: .2rem .6rem; border-radius: var(--r-pill);
    background: var(--navy); color: #fff;
    font-size: var(--fs-xs); font-weight: var(--fw-bold); letter-spacing: .02em;
}
.ex-exam__marks { margin-left: auto; font-size: var(--fs-xs); color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.ex-exam__marks b { color: var(--success-700); font-weight: var(--fw-semibold); }
.ex-exam__marks i { color: var(--danger); font-style: normal; font-weight: var(--fw-semibold); }
.ex-exam .question-text { font-size: 1rem; line-height: 1.65; color: var(--text); white-space: pre-wrap; margin: 0 0 var(--sp-4); overflow-wrap: anywhere; }
.ex-exam .question-image { max-width: 100%; max-height: 320px; height: auto; border: 1px solid var(--border); border-radius: var(--r-sm); display: block; margin-bottom: var(--sp-4); }

.ex-exam .option-row {
    display: flex; align-items: flex-start; gap: var(--sp-3);
    padding: var(--sp-3) var(--sp-4);
    margin-bottom: var(--sp-2);
    border: 1px solid var(--border-strong);
    border-radius: var(--r-md);
    background: var(--surface);
    cursor: pointer;
    min-height: 48px;
    transition: border-color var(--dur) var(--ease), background-color var(--dur) var(--ease);
}
.ex-exam .option-row:hover { border-color: var(--blue-300); background: var(--blue-50); }
.ex-exam .option-row.selected { border-color: var(--blue); background: var(--blue-50); box-shadow: inset 0 0 0 1px var(--blue); }
.ex-exam .option-row input { width: 1.05rem; height: 1.05rem; flex: none; margin: .25rem 0 0; accent-color: var(--blue); }
.ex-exam__opt-letter { font-weight: var(--fw-bold); color: var(--navy); flex: none; }
.ex-exam__opt-text { min-width: 0; font-size: .9375rem; line-height: 1.5; overflow-wrap: anywhere; }

.ex-exam__qfoot { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-top: var(--sp-5); padding-top: var(--sp-4); border-top: 1px solid var(--border); }
.ex-exam__qfoot .ex-exam__next { margin-left: auto; }
/* Review toggle: the page JS flips `.is-review`, so both states live here. */
.ex-exam__review.is-review { background: var(--warning-50); border-color: var(--warning-200); color: var(--warning-700); }
.ex-exam__review.is-review:hover { background: var(--warning-200); border-color: var(--warning); color: var(--warning-700); }

.ex-exam .nav-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(38px, 1fr)); gap: var(--sp-2); }
.ex-exam .nav-btn {
    min-height: 38px;
    border: 1px solid var(--border-strong);
    border-radius: var(--r-sm);
    background: var(--surface);
    color: var(--text-2);
    font-family: inherit;
    font-size: .8125rem;
    font-weight: var(--fw-semibold);
    font-variant-numeric: tabular-nums;
    cursor: pointer;
    transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.ex-exam .nav-btn:hover { border-color: var(--navy-300); background: var(--bg); }
.ex-exam .nav-btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.ex-exam .nav-btn.answered { background: var(--success); border-color: var(--success); color: #fff; }
.ex-exam .nav-btn.review { background: var(--warning); border-color: var(--warning); color: #fff; }
.ex-exam .nav-btn.answered.review { background: var(--warning); border-color: var(--success); color: #fff; box-shadow: inset 0 -3px 0 var(--success); }
.ex-exam .nav-btn.current { border-color: var(--blue); box-shadow: 0 0 0 2px var(--blue-200); }

.ex-exam__legend { display: grid; gap: var(--sp-2); margin-top: var(--sp-4); font-size: var(--fs-xs); color: var(--muted); }
.ex-exam__legend-item { display: flex; align-items: center; gap: var(--sp-2); }
.ex-exam__legend-swatch { width: .8rem; height: .8rem; border-radius: var(--r-xs); flex: none; border: 1px solid var(--border-strong); }
.ex-exam__legend-swatch--answered { background: var(--success); border-color: var(--success); }
.ex-exam__legend-swatch--review { background: var(--warning); border-color: var(--warning); }
.ex-exam__legend-count { margin-left: auto; font-weight: var(--fw-semibold); color: var(--text-2); font-variant-numeric: tabular-nums; }

/* Mobile: the navigator goes first (a candidate needs the map before the
   question), the topbar compresses, and the footer buttons stay thumb-sized. */
@media (max-width: 991.98px) {
    .ex-exam__aside { order: -1; }
    .ex-exam__main { padding: var(--sp-3); }
    .ex-exam .question-card { padding: var(--sp-4); }
}
@media (max-width: 575.98px) {
    .ex-exam__topbar-inner { padding: var(--sp-2) var(--sp-3); gap: var(--sp-2) var(--sp-3); }
    .ex-exam__ident { flex: 1 1 100%; order: -1; }
    .ex-exam .timer { font-size: 1.125rem; }
    .ex-exam__qfoot > * { flex: 1 1 auto; }
    .ex-exam__qfoot .ex-exam__next { margin-left: 0; }
    .ex-exam .nav-grid { grid-template-columns: repeat(auto-fill, minmax(40px, 1fr)); }
}


/* ==========================================================================
   11. UTILITIES
   ========================================================================== */

.ex-visually-hidden {
    position: absolute !important;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}
.ex-hide-desktop { display: none; }
@media (max-width: 767.98px) {
    .ex-hide-mobile { display: none !important; }
    .ex-hide-desktop { display: revert; }
}
.ex-text-center { text-align: center; }
.ex-text-navy { color: var(--navy); }
.ex-text-blue { color: var(--blue); }
.ex-text-muted { color: var(--muted); }
.ex-text-success { color: var(--success); }
.ex-text-danger { color: var(--danger); }
.ex-text-warning { color: var(--warning); }
.ex-bg { background: var(--bg); }
.ex-bg-surface { background: var(--surface); }
.ex-bg-navy { background: var(--navy); }
.ex-relative { position: relative; }
.ex-full { width: 100%; }
.ex-nowrap { white-space: nowrap; }
.ex-truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.ex-mt-0 { margin-top: 0; } .ex-mb-0 { margin-bottom: 0; }
.ex-mb-2 { margin-bottom: var(--sp-2); } .ex-mb-3 { margin-bottom: var(--sp-3); }
.ex-mb-4 { margin-bottom: var(--sp-4); } .ex-mb-5 { margin-bottom: var(--sp-5); }
.ex-mb-6 { margin-bottom: var(--sp-6); } .ex-mb-7 { margin-bottom: var(--sp-7); }
.ex-mb-8 { margin-bottom: var(--sp-8); }
.ex-mt-4 { margin-top: var(--sp-4); } .ex-mt-6 { margin-top: var(--sp-6); }
.ex-mt-8 { margin-top: var(--sp-8); }

/* Icons: sized by their host's font-size by default. */
.ex-icon { display: inline-block; vertical-align: -.125em; flex: none; }


/* ==========================================================================
   12. REDUCED MOTION + PRINT
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
    *, *::before, *::after {
        animation-duration: .001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .001ms !important;
        scroll-behavior: auto !important;
    }
    .ex-skeleton::after { animation: none; opacity: .4; }
    .ex-floatcard--drift, .ex-floatcard--drift-slow { animation: none; }
    .ex-btn:hover .ex-btn__arrow { transform: none; }
    .ex-card--hover:hover { transform: none; }
    .ex-footer__list a:hover { transform: none; }
    /* §9b hover lifts and slides. */
    .ex-progcard:hover, .ex-person:hover, .ex-quicklink:hover { transform: none; }
    .ex-quicklink:hover .ex-quicklink__arrow svg { transform: none; }
    .ex-accordion__trigger[aria-expanded='true'] .ex-accordion__icon { transform: rotate(180deg); }
}

@media print {
    .ex-header, .ex-utilitybar, .ex-footer, .ex-drawer, .ex-drawer-backdrop,
    .ex-skip-link, .admin-sidebar, .student-sidebar, .school-sidebar { display: none !important; }
    .admin-main, .student-main, .school-main { margin-left: 0 !important; }
    body { background: #fff; }
    .ex-card, .card { box-shadow: none; border-color: #ccc; }
}
