/*
 * MathiPen — the design system.
 *
 * Loaded after Bootstrap and before every per-module stylesheet, so it is the
 * one place the platform's look is decided.
 *
 * Bootstrap 5.3 is built on CSS custom properties, which is why this file can
 * restyle 133 views without touching any of them: overriding `--bs-*` changes
 * every button, card, table, badge and form control the framework renders. The
 * alternative — editing markup screen by screen — would be a far larger change
 * and a far larger chance of breaking something no test can see.
 *
 * Two rules for anyone extending this:
 *
 *   1. Add a token, then use it. A hard-coded colour in a module stylesheet is
 *      a colour that will not follow the theme into dark mode.
 *   2. Never define a colour only inside the dark block. Light is the base;
 *      dark redefines. A token that exists in one and not the other is a bug
 *      that only appears for half the users.
 */

/* ========================================================================
   Tokens — light
   ======================================================================== */

:root,
[data-bs-theme="light"] {
    /* Indigo. Chosen to read as considered rather than loud: this is a page
       that tells somebody whether they passed, and it should look like it can
       be trusted with that. */
    --mp-accent:           #4f46e5;
    --mp-accent-strong:    #4338ca;
    --mp-accent-soft:      #eef2ff;
    --mp-accent-border:    #c7d2fe;

    --mp-surface:          #ffffff;
    --mp-surface-sunken:   #f8fafc;
    --mp-surface-raised:   #ffffff;
    --mp-border:           #e2e8f0;
    --mp-border-strong:    #cbd5e1;

    --mp-text:             #1e293b;
    --mp-text-muted:       #64748b;
    --mp-text-faint:       #94a3b8;

    --mp-success:          #059669;
    --mp-success-soft:     #ecfdf5;
    --mp-warning:          #d97706;
    --mp-warning-soft:     #fffbeb;
    --mp-danger:           #dc2626;
    --mp-danger-soft:      #fef2f2;
    --mp-info:             #0284c7;
    --mp-info-soft:        #f0f9ff;

    /* A four-step scale for the password strength meter. It needs a distinct
       mid-tone that neither `--mp-warning` nor `--mp-success` provides, and the
       ramp has to stay legible on a dark surface, so it is its own token set
       rather than a reuse of the status colours. */
    --mp-meter-1:          #dc2626;
    --mp-meter-2:          #ea580c;
    --mp-meter-3:          #ca8a04;
    --mp-meter-4:          #059669;

    /* The admin sidebar stays dark in both themes — a dark rail against light
       content is the whole reason the shell reads as an admin console, and
       inverting it in light mode would lose that. It gets its own tokens so
       dark mode can deepen it to sit with the page instead of glowing against
       it. */
    --mp-sidebar-bg:       #131c31;
    --mp-sidebar-text:     #aab8ce;
    --mp-sidebar-heading:  #6f819c;
    --mp-sidebar-hover:    rgba(255, 255, 255, .06);
    --mp-sidebar-rule:     rgba(255, 255, 255, .08);
    --mp-sidebar-active-bg:   #4f46e5;
    --mp-sidebar-active-text: #ffffff;

    /* A filled accent *surface* — the landing hero, the role badge — as opposed
       to accent used as ink. It cannot be `--mp-accent`: the dark accent is a
       pale indigo picked to be readable *on* a dark page, and filling a block
       with it puts white text at about 2.3:1 and makes the brightest thing on
       a dark screen the one nobody needs to read. */
    --mp-accent-fill:      #4f46e5;
    --mp-accent-fill-text: #ffffff;
    /* The lecturer shell keeps its green rail. Somebody who holds both a
       lecturer and an admin account should be able to tell at a glance which
       one they are signed into. */
    --mp-sidebar-lecturer-bg: #123a2e;

    /* Exam palette states. Fixed in both themes on purpose: these are the
       colours anyone who has sat an online exam already reads without a
       legend, and re-tinting them per theme would cost that recognition for
       no gain. They are tokens so they are named and findable, not so they
       vary. Anything printed on them uses a fixed dark or light foreground for
       the same reason. */
    --mp-state-answered:        #40c057;
    --mp-state-answered-marked: #7048e8;
    --mp-state-marked:          #d0bfff;
    --mp-state-not-answered:    #ffa94d;

    /* Barely-there depth. A card should sit on the page, not hover above it. */
    --mp-shadow-sm:        0 1px 2px rgba(15, 23, 42, .04);
    --mp-shadow:           0 1px 3px rgba(15, 23, 42, .06), 0 1px 2px rgba(15, 23, 42, .04);
    --mp-shadow-lg:        0 10px 24px -6px rgba(15, 23, 42, .10), 0 2px 6px rgba(15, 23, 42, .04);

    --mp-radius-sm:        6px;
    --mp-radius:           8px;
    --mp-radius-lg:        12px;

    /* Bootstrap's own variables, so every framework component follows. */
    --bs-primary:            #4f46e5;
    --bs-primary-rgb:        79, 70, 229;
    --bs-link-color:         #4f46e5;
    --bs-link-color-rgb:     79, 70, 229;
    --bs-link-hover-color:   #4338ca;
    --bs-body-color:         #1e293b;
    --bs-body-color-rgb:     30, 41, 59;
    --bs-body-bg:            #f8fafc;
    --bs-body-bg-rgb:        248, 250, 252;
    --bs-secondary-color:    rgba(100, 116, 139, .95);
    --bs-border-color:       #e2e8f0;
    --bs-border-radius:      8px;
    --bs-border-radius-sm:   6px;
    --bs-border-radius-lg:   12px;
    --bs-emphasis-color:     #0f172a;
    --bs-tertiary-bg:        #f1f5f9;
    --bs-secondary-bg:       #f1f5f9;
}

/* ========================================================================
   Tokens — dark
   ========================================================================
   `docs/exams.md` asks for dark mode and nothing implemented it. It is a
   preference, not a gimmick: candidates revise at night, and an invigilation
   screen that is the only bright thing in a room is a screen people avoid.

   Slate rather than black. True black against white text is high-contrast to
   the point of glare, and a long exam is exactly when that matters.
   ======================================================================== */

[data-bs-theme="dark"] {
    --mp-accent:           #818cf8;
    --mp-accent-strong:    #a5b4fc;
    --mp-accent-soft:      #1e1b4b;
    --mp-accent-border:    #3730a3;

    --mp-surface:          #1e293b;
    --mp-surface-sunken:   #0f172a;
    --mp-surface-raised:   #263449;
    --mp-border:           #334155;
    --mp-border-strong:    #475569;

    --mp-text:             #e2e8f0;
    --mp-text-muted:       #94a3b8;
    --mp-text-faint:       #64748b;

    --mp-success:          #34d399;
    --mp-success-soft:     #052e2b;
    --mp-warning:          #fbbf24;
    --mp-warning-soft:     #2e1f05;
    --mp-danger:           #f87171;
    --mp-danger-soft:      #300f0f;
    --mp-info:             #38bdf8;
    --mp-info-soft:        #05243a;

    --mp-meter-1:          #f87171;
    --mp-meter-2:          #fb923c;
    --mp-meter-3:          #fbbf24;
    --mp-meter-4:          #34d399;

    --mp-sidebar-bg:       #0b1220;
    --mp-sidebar-text:     #94a3b8;
    --mp-sidebar-heading:  #64748b;
    --mp-sidebar-hover:    rgba(255, 255, 255, .05);
    --mp-sidebar-rule:     rgba(255, 255, 255, .07);
    /* Not the dark accent: `#818cf8` is a light indigo, and white on it lands
       near 2.3:1. Deep indigo with a pale label instead. */
    --mp-sidebar-active-bg:   #3730a3;
    --mp-sidebar-active-text: #e0e7ff;

    --mp-accent-fill:      #312e81;
    --mp-accent-fill-text: #e0e7ff;
    --mp-sidebar-lecturer-bg: #0a2620;

    /* Shadows do almost nothing on a dark surface; borders carry the
       separation instead. Keeping them tiny avoids muddy edges. */
    --mp-shadow-sm:        0 1px 2px rgba(0, 0, 0, .30);
    --mp-shadow:           0 1px 3px rgba(0, 0, 0, .40);
    --mp-shadow-lg:        0 12px 28px -8px rgba(0, 0, 0, .55);

    --bs-primary:            #818cf8;
    --bs-primary-rgb:        129, 140, 248;
    --bs-link-color:         #a5b4fc;
    --bs-link-color-rgb:     165, 180, 252;
    --bs-link-hover-color:   #c7d2fe;
    --bs-body-color:         #e2e8f0;
    --bs-body-color-rgb:     226, 232, 240;
    --bs-body-bg:            #0f172a;
    --bs-body-bg-rgb:        15, 23, 42;
    --bs-secondary-color:    rgba(148, 163, 184, .95);
    --bs-border-color:       #334155;
    --bs-emphasis-color:     #f8fafc;
    --bs-tertiary-bg:        #1e293b;
    --bs-secondary-bg:       #1e293b;
}

/* ========================================================================
   Foundations
   ======================================================================== */

body {
    /* The system stack: no webfont request, so first paint is not waiting on a
       CDN, and text never reflows once it arrives. */
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
                 "Helvetica Neue", Arial, "Noto Sans", sans-serif;
    font-size: .9375rem;
    line-height: 1.6;
    background-color: var(--bs-body-bg);
    color: var(--bs-body-color);
    -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
    font-weight: 600;
    letter-spacing: -.011em;
    color: var(--bs-emphasis-color);
}

.display-1, .display-2, .display-3, .display-4 {
    font-weight: 700;
    letter-spacing: -.025em;
}

/* Figures line up in a column when every digit is the same width — which is
   most of this platform: scores, marks, ranks, money, countdowns. */
.font-monospace,
.table td .badge,
.text-tabular {
    font-variant-numeric: tabular-nums;
}

a {
    text-decoration-thickness: 1px;
    text-underline-offset: .15em;
}

/* ========================================================================
   Components
   ======================================================================== */

.card {
    border-color: var(--mp-border);
    border-radius: var(--mp-radius-lg);
    background-color: var(--mp-surface);
}

/* The codebase uses .shadow-sm on nearly every card. Softening it here is what
   turns "Bootstrap default" into something considered, without touching a view. */
.card.shadow-sm,
.shadow-sm {
    box-shadow: var(--mp-shadow) !important;
}

.shadow {
    box-shadow: var(--mp-shadow-lg) !important;
}

.card-header {
    background-color: transparent;
    border-bottom-color: var(--mp-border);
    padding-top: .875rem;
    padding-bottom: .875rem;
    font-weight: 600;
}

.card-footer {
    background-color: transparent;
    border-top-color: var(--mp-border);
}

.btn {
    --bs-btn-border-radius: var(--mp-radius);
    font-weight: 500;
    padding-inline: 1rem;
}

.btn-primary {
    --bs-btn-bg: var(--mp-accent);
    --bs-btn-border-color: var(--mp-accent);
    --bs-btn-hover-bg: var(--mp-accent-strong);
    --bs-btn-hover-border-color: var(--mp-accent-strong);
    --bs-btn-active-bg: var(--mp-accent-strong);
    --bs-btn-active-border-color: var(--mp-accent-strong);
    --bs-btn-disabled-bg: var(--mp-accent);
    --bs-btn-disabled-border-color: var(--mp-accent);
}

.btn-outline-secondary {
    --bs-btn-color: var(--mp-text-muted);
    --bs-btn-border-color: var(--mp-border-strong);
    --bs-btn-hover-bg: var(--mp-surface-sunken);
    --bs-btn-hover-border-color: var(--mp-border-strong);
    --bs-btn-hover-color: var(--mp-text);
}

.form-control,
.form-select {
    border-color: var(--mp-border-strong);
    border-radius: var(--mp-radius);
    background-color: var(--mp-surface);
    color: var(--bs-body-color);
    padding-block: .5rem;
}

.form-control:focus,
.form-select:focus {
    border-color: var(--mp-accent);
    /* One ring, thin. Bootstrap's default .25rem halo is loud on a form with
       fifteen fields, which several of these screens have. */
    box-shadow: 0 0 0 3px rgba(var(--bs-primary-rgb), .16);
}

.form-label {
    font-weight: 500;
    margin-bottom: .35rem;
    color: var(--mp-text);
}

.form-text {
    color: var(--mp-text-muted);
}

.table {
    --bs-table-border-color: var(--mp-border);
    --bs-table-bg: transparent;
}

.table > thead th {
    font-size: .8125rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--mp-text-muted);
    border-bottom-width: 1px;
}

.table > tbody > tr:hover > * {
    background-color: var(--mp-surface-sunken);
}

/* Bootstrap's pill badges read as tags rather than shouted labels, which is
   right for statuses that appear a dozen to a page. */
.badge {
    font-weight: 500;
    padding: .35em .65em;
    border-radius: 999px;
}

.alert {
    border-radius: var(--mp-radius);
    border-width: 1px;
}

.list-group-item {
    background-color: var(--mp-surface);
    border-color: var(--mp-border);
    color: var(--bs-body-color);
}

.list-group-item-action:hover {
    background-color: var(--mp-surface-sunken);
}

.list-group-item.active {
    background-color: var(--mp-accent);
    border-color: var(--mp-accent);
}

.dropdown-menu {
    border-color: var(--mp-border);
    border-radius: var(--mp-radius);
    box-shadow: var(--mp-shadow-lg);
    background-color: var(--mp-surface-raised);
}

.modal-content,
.offcanvas {
    border-color: var(--mp-border);
    border-radius: var(--mp-radius-lg);
    background-color: var(--mp-surface);
}

.progress {
    background-color: var(--mp-surface-sunken);
    border-radius: 999px;
    height: .5rem;
}

.progress-bar {
    background-color: var(--mp-accent);
    border-radius: 999px;
}

.navbar {
    border-bottom: 1px solid transparent;
}

.nav-tabs {
    border-bottom-color: var(--mp-border);
}

.nav-tabs .nav-link.active {
    border-bottom-color: var(--mp-surface);
    color: var(--mp-accent);
}

hr {
    border-color: var(--mp-border);
    opacity: 1;
}

/*
 * Bootstrap treats `.bg-light` and `.bg-white` as fixed colours rather than
 * theme-relative ones, so in dark mode they stay bright. The views use both as
 * "a panel, slightly set back from the page" — dozens of times — so they are
 * repointed at surface tokens here rather than edited screen by screen.
 *
 * `.text-dark` and `.text-black` follow for the same reason: a view that pairs
 * them with one of these backgrounds would otherwise end up dark-on-dark.
 */
[data-bs-theme="dark"] .bg-light {
    background-color: var(--mp-surface-sunken) !important;
}

[data-bs-theme="dark"] .bg-white {
    background-color: var(--mp-surface) !important;
}

[data-bs-theme="dark"] .text-dark,
[data-bs-theme="dark"] .text-black {
    color: var(--mp-text) !important;
}

[data-bs-theme="dark"] .border {
    border-color: var(--mp-border) !important;
}

/* Accent-filled blocks take the fill token in both themes, not `--bs-primary`.
   `.btn-primary` is unaffected: it sets its own `--bs-btn-bg` above. */
.bg-primary {
    background-color: var(--mp-accent-fill) !important;
}

.text-bg-primary {
    background-color: var(--mp-accent-fill) !important;
    color: var(--mp-accent-fill-text) !important;
}

code {
    background-color: var(--mp-surface-sunken);
    padding: .1em .35em;
    border-radius: var(--mp-radius-sm);
    color: var(--mp-accent-strong);
}

/* ========================================================================
   Accessibility
   ======================================================================== */

/* A visible focus ring on anything reachable by keyboard. Several screens here
   are long forms, and an exam is sat under time pressure — losing track of
   where focus is costs a candidate real minutes. */
:focus-visible {
    outline: 2px solid var(--mp-accent);
    outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: .01ms !important;
        transition-duration: .01ms !important;
        scroll-behavior: auto !important;
    }
}

/* The toggle sits in navbars of several different colours, so it borrows the
   surrounding text colour rather than declaring one. */
.mp-theme-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    padding: 0;
    border: 1px solid transparent;
    border-radius: var(--mp-radius);
    background: transparent;
    color: inherit;
    opacity: .85;
    line-height: 1;
}

.mp-theme-toggle:hover {
    opacity: 1;
    border-color: currentColor;
}

.mp-theme-toggle .mp-icon-dark { display: none; }
[data-bs-theme="dark"] .mp-theme-toggle .mp-icon-dark { display: inline; }
[data-bs-theme="dark"] .mp-theme-toggle .mp-icon-light { display: none; }

@media print {
    .mp-theme-toggle,
    .admin-sidebar,
    .navbar {
        display: none !important;
    }
}
