/* ==========================================================================
   Board Examination System — design system
   --------------------------------------------------------------------------
   Self-hosted on purpose. Earlier drafts pulled Bootstrap from a CDN, but a
   system that must stay usable during a live national exam should not depend
   on a third-party host being reachable: a CDN outage, a school firewall, or
   a slow international link would leave candidates staring at an unstyled
   page mid-exam. Everything below ships with the app.

   The palette is taken directly from the CPB crest supplied by the board:
   the deep institutional blue of the emblem background, with the Kenyan flag
   colours used only as accents (status, alerts, the header rule) so they
   read as national identity rather than decoration.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Tokens
   -------------------------------------------------------------------------- */
:root {
    /* Brand — sampled from the supplied crest */
    --brand:            #0b5179;
    --brand-dark:       #073a58;
    --brand-darker:     #052a41;
    --brand-light:      #0e6396;
    --brand-tint:       #e9f1f7;
    --brand-tint-2:     #d3e3ef;

    /* Kenyan flag accents */
    --ke-black:         #221f1f;
    --ke-red:           #d2313b;
    --ke-green:         #12a650;

    /* Semantic */
    --success:          #12a650;
    --success-tint:     #e6f6ec;
    --danger:           #d2313b;
    --danger-tint:      #fdecec;
    --warning:          #b8730c;
    --warning-tint:     #fdf3e2;
    --info:             var(--brand);
    --info-tint:        var(--brand-tint);

    /* Neutrals */
    --ink:              #16202a;
    --ink-soft:         #48586a;
    --ink-muted:        #6b7a8a;
    --line:             #dde5ec;
    --line-strong:      #c5d2de;
    --surface:          #ffffff;
    --surface-sunken:   #f5f8fa;
    --page:             #eef3f7;

    /* Shape & depth */
    --radius:           8px;
    --radius-lg:        12px;
    --shadow-sm:        0 1px 2px rgba(16, 32, 45, .06), 0 1px 3px rgba(16, 32, 45, .05);
    --shadow:           0 2px 4px rgba(16, 32, 45, .05), 0 4px 12px rgba(16, 32, 45, .07);
    --shadow-lg:        0 8px 28px rgba(16, 32, 45, .14);

    --sidebar-w:        250px;
}

/* --------------------------------------------------------------------------
   2. Base
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

body {
    margin: 0;
    background: var(--page);
    color: var(--ink);
    font-family: "Segoe UI", Roboto, -apple-system, BlinkMacSystemFont, "Helvetica Neue", Arial, sans-serif;
    font-size: 15px;
    line-height: 1.55;
    -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 { margin: 0 0 .5rem; line-height: 1.25; font-weight: 600; color: var(--ink); }
h1 { font-size: 1.5rem; }
h2 { font-size: 1.2rem; }
h3 { font-size: 1.05rem; }
p  { margin: 0 0 1rem; }
a  { color: var(--brand); text-decoration: none; }
a:hover { text-decoration: underline; }

.muted      { color: var(--ink-muted); }
.small      { font-size: .85rem; }
.tiny       { font-size: .78rem; }
.strong     { font-weight: 600; }
.mono       { font-family: "SFMono-Regular", Consolas, "Liberation Mono", monospace; }
.text-right { text-align: right; }
.text-center{ text-align: center; }
.nowrap     { white-space: nowrap; }

.mt-0 { margin-top: 0; }
.mt-1 { margin-top: .5rem; }
.mt-2 { margin-top: 1rem; }
.mt-3 { margin-top: 1.5rem; }
.mt-4 { margin-top: 2rem; }
.mb-0 { margin-bottom: 0; }
.mb-1 { margin-bottom: .5rem; }
.mb-2 { margin-bottom: 1rem; }
.mb-3 { margin-bottom: 1.5rem; }
.mb-4 { margin-bottom: 2rem; }

/* --------------------------------------------------------------------------
   3. Masthead — the national/board identity band
   -------------------------------------------------------------------------- */
.masthead {
    background: var(--surface);
    border-bottom: 1px solid var(--line);
}

.masthead__inner {
    max-width: 1240px;
    margin: 0 auto;
    padding: .85rem 1.5rem;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1.5rem;
}

.masthead__brand { display: flex; align-items: center; gap: .9rem; text-decoration: none; }
.masthead__brand:hover { text-decoration: none; }
.masthead__logo { height: 52px; width: auto; display: block; }

.masthead__titles { display: flex; flex-direction: column; }
.masthead__title {
    font-size: 1.02rem; font-weight: 700; color: var(--brand-darker);
    letter-spacing: -.01em; line-height: 1.2;
}
.masthead__subtitle { font-size: .76rem; color: var(--ink-muted); letter-spacing: .04em; text-transform: uppercase; }

/* The tricolour rule under the masthead — a thin nod to the flag stripes
   that appear between the two crests in the supplied artwork. */
.masthead__rule { height: 3px; display: flex; }
.masthead__rule span { flex: 1; }
.masthead__rule span:nth-child(1) { background: var(--ke-black); }
.masthead__rule span:nth-child(2) { background: var(--ke-red); }
.masthead__rule span:nth-child(3) { background: var(--ke-green); }

.masthead__user { display: flex; align-items: center; gap: .85rem; }
.masthead__identity { text-align: right; line-height: 1.3; }
.masthead__identity .name { font-weight: 600; font-size: .9rem; }
.masthead__identity .role { font-size: .75rem; color: var(--ink-muted); text-transform: capitalize; }

/* --------------------------------------------------------------------------
   4. Layout shells
   -------------------------------------------------------------------------- */
.shell { max-width: 1240px; margin: 0 auto; padding: 1.75rem 1.5rem 4rem; }

.shell--split { display: grid; grid-template-columns: var(--sidebar-w) 1fr; gap: 1.75rem; align-items: start; }

/* Centred narrow column for login / registration / status pages */
.shell--narrow { max-width: 560px; margin: 0 auto; padding: 2.5rem 1.5rem 4rem; }
.shell--wide   { max-width: 1600px; }

/* A multi-field form: wider than a sign-in box, narrower than a dashboard.
   Registration has fourteen fields; at 560px they stack into a column so
   long that the submit button is three screens down. */
.shell--form   { max-width: 880px; margin: 0 auto; padding: 2.5rem 1.5rem 4rem; }

/* --------------------------------------------------------------------------
   5. Sidebar navigation (staff area)
   -------------------------------------------------------------------------- */
.sidebar {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    padding: .6rem;
    box-shadow: var(--shadow-sm);
    position: sticky;
    top: 1.5rem;
}

.sidebar__heading {
    font-size: .7rem; font-weight: 700; letter-spacing: .09em; text-transform: uppercase;
    color: var(--ink-muted); padding: .85rem .75rem .35rem;
}

.sidebar__link {
    display: flex; align-items: center; justify-content: space-between; gap: .5rem;
    padding: .55rem .75rem; border-radius: var(--radius);
    color: var(--ink-soft); font-size: .9rem; font-weight: 500;
    text-decoration: none;
}
.sidebar__link:hover { background: var(--surface-sunken); color: var(--brand); text-decoration: none; }
.sidebar__link.is-active { background: var(--brand); color: #fff; font-weight: 600; }
.sidebar__link.is-active .pill { background: rgba(255,255,255,.22); color: #fff; }

/* --------------------------------------------------------------------------
   6. Page header + back button
   -------------------------------------------------------------------------- */
.page-head {
    display: flex; align-items: flex-start; justify-content: space-between;
    gap: 1rem; margin-bottom: 1.25rem; flex-wrap: wrap;
}
.page-head__text { min-width: 0; }
.page-head h1 { margin-bottom: .15rem; }
.page-head__sub { color: var(--ink-muted); font-size: .88rem; margin: 0; }
.page-head__actions { display: flex; gap: .5rem; flex-wrap: wrap; }

/* Back link — used on every screen that has a logical parent, so a user
   always has a way out that doesn't rely on the browser's back button
   (which would re-submit forms on POST-redirect pages). */
.back-link {
    display: inline-flex; align-items: center; gap: .4rem;
    font-size: .86rem; font-weight: 600; color: var(--ink-soft);
    margin-bottom: .9rem; padding: .3rem .6rem .3rem .35rem;
    border-radius: var(--radius); border: 1px solid transparent;
}
.back-link:hover { color: var(--brand); background: var(--surface); border-color: var(--line); text-decoration: none; }
.back-link::before { content: "←"; font-size: 1rem; line-height: 1; }

/* --------------------------------------------------------------------------
   7. Cards
   -------------------------------------------------------------------------- */
.card {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    margin-bottom: 1.25rem;
    overflow: hidden;
}
.card__head {
    padding: .9rem 1.15rem; border-bottom: 1px solid var(--line);
    display: flex; align-items: center; justify-content: space-between; gap: 1rem;
    background: var(--surface);
}
.card__head h2, .card__head h3 { margin: 0; font-size: 1rem; }
.card__body { padding: 1.15rem; }
.card__body > :last-child { margin-bottom: 0; }
.card__foot { padding: .85rem 1.15rem; border-top: 1px solid var(--line); background: var(--surface-sunken); }

.card--accent { border-top: 3px solid var(--brand); }
.card--danger { border-color: #f0c2c5; }
.card--danger .card__head { background: var(--danger-tint); color: #8f1f26; }

/* --------------------------------------------------------------------------
   8. Stat tiles
   -------------------------------------------------------------------------- */
.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 1rem; margin-bottom: 1.5rem; }

.stat {
    background: var(--surface); border: 1px solid var(--line);
    border-radius: var(--radius-lg); padding: 1.05rem 1.15rem;
    box-shadow: var(--shadow-sm); border-left: 3px solid var(--brand);
}
.stat__value { font-size: 1.9rem; font-weight: 700; line-height: 1.1; color: var(--brand-darker); }
.stat__label { font-size: .8rem; color: var(--ink-muted); margin-top: .2rem; }
.stat--warn   { border-left-color: var(--warning); }
.stat--warn   .stat__value { color: var(--warning); }
.stat--danger { border-left-color: var(--danger); }
.stat--danger .stat__value { color: var(--danger); }
.stat--ok     { border-left-color: var(--success); }
.stat--ok     .stat__value { color: #0d7d3c; }

/* Grid of full cards (as opposed to the compact stat tiles above) — used
   where each item needs a heading, body text and its own action. */
.card-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 1.25rem; }
.card-grid .card { margin-bottom: 0; }

/* --------------------------------------------------------------------------
   9. Tables
   -------------------------------------------------------------------------- */
.table-wrap { overflow-x: auto; }

.table { width: 100%; border-collapse: collapse; font-size: .9rem; }
.table th {
    text-align: left; padding: .7rem .9rem;
    background: var(--surface-sunken); color: var(--ink-soft);
    font-size: .74rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
    border-bottom: 1px solid var(--line); white-space: nowrap;
}
.table td { padding: .75rem .9rem; border-bottom: 1px solid var(--line); vertical-align: middle; }
.table tbody tr:last-child td { border-bottom: 0; }
.table tbody tr:hover { background: var(--brand-tint); }
.table .actions { display: flex; gap: .4rem; justify-content: flex-end; flex-wrap: wrap; }

.table__empty { padding: 2.5rem 1rem; text-align: center; color: var(--ink-muted); }

/* --------------------------------------------------------------------------
   10. Buttons
   -------------------------------------------------------------------------- */
.btn {
    display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
    padding: .5rem .95rem; border-radius: var(--radius);
    border: 1px solid transparent; background: var(--brand); color: #fff;
    font-size: .88rem; font-weight: 600; font-family: inherit; line-height: 1.4;
    cursor: pointer; text-decoration: none; white-space: nowrap;
    transition: background .12s ease, border-color .12s ease, color .12s ease;
}
.btn:hover { background: var(--brand-dark); color: #fff; text-decoration: none; }
.btn:focus-visible { outline: 3px solid var(--brand-tint-2); outline-offset: 1px; }
.btn:disabled, .btn[disabled] { opacity: .5; cursor: not-allowed; }

.btn--outline { background: transparent; color: var(--brand); border-color: var(--line-strong); }
.btn--outline:hover { background: var(--brand-tint); color: var(--brand-dark); border-color: var(--brand); }

.btn--ghost { background: transparent; color: var(--ink-soft); border-color: transparent; }
.btn--ghost:hover { background: var(--surface-sunken); color: var(--ink); }

.btn--danger { background: var(--danger); }
.btn--danger:hover { background: #ab2028; }
.btn--danger-outline { background: transparent; color: var(--danger); border-color: #eab6ba; }
.btn--danger-outline:hover { background: var(--danger-tint); color: #8f1f26; border-color: var(--danger); }

.btn--success { background: var(--success); }
.btn--success:hover { background: #0d7d3c; }

.btn--sm { padding: .32rem .65rem; font-size: .8rem; }
.btn--lg { padding: .7rem 1.4rem; font-size: .98rem; }
.btn--block { width: 100%; }

.btn-row { display: flex; gap: .6rem; align-items: center; flex-wrap: wrap; }

/* --------------------------------------------------------------------------
   11. Forms
   -------------------------------------------------------------------------- */
.field { margin-bottom: 1.05rem; }
.field:last-child { margin-bottom: 0; }

.label { display: block; font-size: .84rem; font-weight: 600; color: var(--ink-soft); margin-bottom: .32rem; }
.label .req { color: var(--danger); }

.input, .select, .textarea {
    width: 100%; padding: .55rem .7rem;
    border: 1px solid var(--line-strong); border-radius: var(--radius);
    background: var(--surface); color: var(--ink);
    font-size: .92rem; font-family: inherit; line-height: 1.5;
}
.input:focus, .select:focus, .textarea:focus {
    outline: none; border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-tint-2);
}
.input[readonly] { background: var(--surface-sunken); color: var(--ink-muted); }
.textarea { resize: vertical; min-height: 80px; }

.hint { font-size: .79rem; color: var(--ink-muted); margin-top: .3rem; }

.field-error { font-size: .79rem; color: var(--danger); margin-top: .3rem; font-weight: 500; }
.input.has-error, .select.has-error, .textarea.has-error { border-color: var(--danger); }

.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 0 1rem; }

/* ---------------------------------------------------------------------------
   Evenly aligned form columns
   ---------------------------------------------------------------------------
   The problem this solves: in a plain two-column grid the two fields in a
   row are independent boxes, so a label that wraps to two lines ("Index
   number / certificate number") pushes its own input down while the input
   beside it stays put, and a long hint under one field pushes the NEXT row
   down on one side only. The form ends up visibly ragged.

   Each field becomes a flex column with a reserved label height and the
   hint pinned to the bottom, so inputs line up across a row and every row
   starts level regardless of how much explanatory text sits under it.
--------------------------------------------------------------------------- */
.form-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
    gap: 0 1.4rem;

    /* Cells align to the TOP, not stretched.
       The first version stretched them and pushed each hint to the foot of
       its cell, so that the bottoms of two side-by-side fields lined up.
       On screen that read badly: "This is also your first-time password."
       ended up floating an inch beneath the box it describes, because the
       hint beside it ran to three lines. Bottom alignment is not worth
       separating a hint from its own field — the row heights differing is
       normal and reads fine. What must line up is the INPUTS, and the
       reserved label height below does that. */
    align-items: start;
}

.form-grid > .field {
    display: flex;
    flex-direction: column;
    margin-bottom: 1.05rem;
}

/* Two lines of label reserved, so a wrapping label does not shove its own
   input out of line with its neighbour's. */
.form-grid > .field > .label { min-height: 2.55em; }

.form-grid > .field > .hint { padding-top: .3rem; }

/* A field that should span the whole width (institution, level, uploads). */
.form-grid > .field--full { grid-column: 1 / -1; }

@media (max-width: 620px) {
    .form-grid { grid-template-columns: 1fr; }
    .form-grid > .field > .label { min-height: 0; }
}
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0 1rem; }

.check { display: flex; align-items: flex-start; gap: .55rem; margin-bottom: .5rem; }
.check input { margin-top: .25rem; flex: none; width: 16px; height: 16px; accent-color: var(--brand); }
.check label { font-size: .9rem; cursor: pointer; }

/* Password preview toggle. The button is positioned inside the field's
   right-hand edge, and the input gets extra right padding so long passwords
   never run underneath it. See public/js/password-toggle.js — the markup is
   created at runtime, so no form template needs to know about this. */
.password-field { position: relative; display: block; }
.password-field .input { padding-right: 2.75rem; }

.password-field__toggle {
    position: absolute; top: 50%; right: .4rem; transform: translateY(-50%);
    display: flex; align-items: center; justify-content: center;
    width: 2rem; height: 2rem; padding: 0;
    background: transparent; border: 1px solid transparent; border-radius: 5px;
    color: var(--ink-muted); cursor: pointer;
}
.password-field__toggle:hover { color: var(--brand); background: var(--brand-tint); }
.password-field__toggle:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; }
.password-field__toggle.is-revealed { color: var(--brand); }

/* --------------------------------------------------------------------------
   Checkbox group — "what needs correcting?"
   --------------------------------------------------------------------------
   A grid rather than a list, because the seven correctable fields fit two
   columns comfortably and a reviewer picking two of them should not have to
   scan a tall single column to find the second.
   -------------------------------------------------------------------------- */
.checkbox-grid {
    display: grid; gap: .4rem .9rem;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
}
.checkbox {
    display: flex; align-items: center; gap: .5rem; cursor: pointer;
    font-size: .9rem; padding: .35rem .5rem; border-radius: var(--radius);
}
.checkbox:hover { background: var(--surface-sunken); }
.checkbox input { width: 16px; height: 16px; accent-color: var(--brand); flex: 0 0 auto; }

/* The middle option between approve and reject. Amber rather than red: it
   asks for a change, it does not refuse an application. */
.btn--warn { background: var(--warning); }
.btn--warn:hover { background: #96600a; }

/* A command to copy and run. Monospaced and scrollable rather than
   wrapped, because a wrapped shell command that somebody pastes with a
   line break in the middle silently does the wrong thing. */
.code-block {
    background: var(--brand-darker); color: #dbe9f3; padding: .75rem 1rem;
    border-radius: var(--radius); font-family: "SFMono-Regular", Consolas, monospace;
    font-size: .85rem; overflow-x: auto; margin: 0 0 1rem;
}

/* The two-factor code box. Wide-spaced and large because it is read off a
   phone and typed on another screen, usually in a hurry. */
.input--code {
    font-family: "SFMono-Regular", Consolas, monospace;
    font-size: 1.6rem; letter-spacing: .5rem; text-align: center; font-weight: 700;
}

/* File input styled to match the rest of the form controls */
.file-input {
    width: 100%; padding: .5rem; border: 1px dashed var(--line-strong);
    border-radius: var(--radius); background: var(--surface-sunken); font-size: .86rem;
}

/* --------------------------------------------------------------------------
   11b. Passport photograph
   --------------------------------------------------------------------------
   The preview box is fixed at the 35:45 passport ratio and its image uses
   object-fit: cover, which is the SAME centre crop the server applies before
   storing. That is the point of it: the candidate sees the crop while they
   can still choose a better photograph, rather than discovering it when an
   officer struggles to recognise them.
   -------------------------------------------------------------------------- */
.photo-field { display: flex; gap: 1rem; align-items: flex-start; flex-wrap: wrap; }
.photo-field__controls { flex: 1 1 260px; min-width: 240px; }

.photo-field__preview {
    flex: 0 0 auto;
    width: 124px; aspect-ratio: 35 / 45;
    border: 1px dashed var(--line-strong); border-radius: var(--radius);
    background: var(--surface-sunken); overflow: hidden;
    display: flex; align-items: center; justify-content: center;
}
.photo-field__preview img { width: 100%; height: 100%; object-fit: cover; display: block; }
.photo-field__placeholder {
    font-size: .72rem; color: var(--ink-soft); text-align: center; line-height: 1.4; padding: .4rem;
}

/* The officer's side: photograph beside the live video tile. */
.identity-panel { display: flex; gap: .75rem; align-items: flex-start; }
.identity-panel__photo {
    flex: 0 0 auto; width: 84px; aspect-ratio: 35 / 45;
    border-radius: var(--radius); overflow: hidden; background: var(--surface-sunken);
    border: 1px solid var(--line);
    display: flex; align-items: center; justify-content: center;
}
.identity-panel__photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.identity-panel__none {
    font-size: .66rem; color: var(--ink-soft); text-align: center; line-height: 1.3; padding: .3rem;
}
.identity-panel__actions { flex: 1 1 auto; min-width: 0; }

/* A recorded mismatch is the one thing on a monitoring wall that must not be
   missed at a glance, so it gets the danger colour rather than a badge. */
.identity-panel--mismatch .identity-panel__photo { border-color: var(--danger); border-width: 2px; }

/* --------------------------------------------------------------------------
   12. Badges & pills
   -------------------------------------------------------------------------- */
.badge {
    display: inline-block; padding: .18rem .55rem; border-radius: 999px;
    font-size: .74rem; font-weight: 700; letter-spacing: .02em; white-space: nowrap;
    background: var(--surface-sunken); color: var(--ink-soft); border: 1px solid var(--line);
}
.badge--ok      { background: var(--success-tint); color: #0d7d3c; border-color: #b6e4c7; }
.badge--danger  { background: var(--danger-tint);  color: #a8242c; border-color: #f0c2c5; }
.badge--warn    { background: var(--warning-tint); color: #8f5a09; border-color: #f0d9ac; }
.badge--info    { background: var(--brand-tint);   color: var(--brand-dark); border-color: var(--brand-tint-2); }
.badge--neutral { background: #eceff2; color: var(--ink-soft); }

.pill {
    display: inline-block; min-width: 20px; padding: .05rem .4rem; border-radius: 999px;
    background: var(--brand-tint-2); color: var(--brand-dark);
    font-size: .72rem; font-weight: 700; text-align: center;
}
.pill--alert { background: var(--danger); color: #fff; }

/* `pill--muted` was in use in three templates with no rule behind it, so
   "Withdrawn" and "Not released" were rendering in the same brand tint as
   a live count. A muted pill should read as background information. */
.pill--muted { background: #eceff2; color: var(--ink-soft); }

/* Used for "this is on and working" — deliberately quiet rather than a
   success banner, because it belongs beside a candidate's name and must
   not compete with a flag. */
.pill--ok { background: #e4f3ea; color: #1d6b40; }

/* --------------------------------------------------------------------------
   13. Alerts
   -------------------------------------------------------------------------- */
.alert {
    padding: .8rem 1rem; border-radius: var(--radius); margin-bottom: 1.1rem;
    border: 1px solid; font-size: .9rem;
}
.alert p:last-child, .alert ul:last-child { margin-bottom: 0; }
.alert ul { margin: 0; padding-left: 1.15rem; }

.alert--success { background: var(--success-tint); border-color: #b6e4c7; color: #0b6c34; }
.alert--danger  { background: var(--danger-tint);  border-color: #f0c2c5; color: #96222a; }
.alert--warn    { background: var(--warning-tint); border-color: #f0d9ac; color: #7d4f08; }
.alert--info    { background: var(--brand-tint);   border-color: var(--brand-tint-2); color: var(--brand-dark); }

/* --------------------------------------------------------------------------
   14. Auth / public pages
   -------------------------------------------------------------------------- */
.auth-page { min-height: 100vh; display: flex; flex-direction: column; background: var(--page); }

.auth-hero {
    background: linear-gradient(160deg, var(--brand-darker), var(--brand) 65%, var(--brand-light));
    color: #fff; padding: 2.5rem 1.5rem; text-align: center;
}
.auth-hero img { height: 84px; width: auto; background: #fff; padding: .5rem .75rem; border-radius: var(--radius); }
.auth-hero h1 { color: #fff; font-size: 1.45rem; margin: 1rem 0 .3rem; }
.auth-hero p  { color: rgba(255,255,255,.85); margin: 0; font-size: .93rem; }

.auth-card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-lg); box-shadow: var(--shadow); padding: 1.75rem; }

.auth-switch { text-align: center; font-size: .88rem; color: var(--ink-muted); margin-top: 1.25rem; }

/* Choice cards on the landing page */
.portal-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 1.25rem; }
.portal-card {
    display: block; background: var(--surface); border: 1px solid var(--line);
    border-radius: var(--radius-lg); padding: 1.5rem; text-align: center;
    box-shadow: var(--shadow-sm); text-decoration: none; color: inherit;
    border-top: 3px solid var(--brand);
}
.portal-card:hover { box-shadow: var(--shadow); text-decoration: none; border-top-color: var(--ke-red); }
.portal-card h2 { color: var(--brand-darker); margin-bottom: .35rem; }
.portal-card p { color: var(--ink-muted); font-size: .88rem; margin-bottom: 1rem; }

/* --------------------------------------------------------------------------
   15. Exam-taking screen
   -------------------------------------------------------------------------- */
.exam-bar {
    position: sticky; top: 0; z-index: 30;
    background: var(--brand-darker); color: #fff;
    border-bottom: 3px solid var(--ke-red);
}
.exam-bar__inner {
    max-width: 1240px; margin: 0 auto; padding: .7rem 1.5rem;
    display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap;
}
.exam-bar__title { font-weight: 600; font-size: .98rem; }
.exam-bar__meta { font-size: .78rem; color: rgba(255,255,255,.7); }

.timer {
    font-family: "SFMono-Regular", Consolas, monospace;
    font-size: 1.5rem; font-weight: 700; letter-spacing: .02em;
    padding: .2rem .7rem; border-radius: var(--radius);
    background: rgba(255,255,255,.12);
}
.timer.is-warning { background: var(--warning); color: #fff; }
.timer.is-critical { background: var(--ke-red); color: #fff; animation: pulse 1s ease-in-out infinite; }
@keyframes pulse { 50% { opacity: .65; } }

.question-card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-lg); margin-bottom: 1rem; box-shadow: var(--shadow-sm); }
.question-card.is-answered { border-left: 3px solid var(--success); }
.question-card__head { display: flex; justify-content: space-between; gap: 1rem; padding: .85rem 1.15rem .35rem; }
.question-card__num { font-weight: 700; color: var(--brand); font-size: .82rem; letter-spacing: .05em; text-transform: uppercase; }
.question-card__body { padding: 0 1.15rem 1.15rem; }
.question-text { font-size: 1rem; font-weight: 500; margin: .35rem 0 .9rem; }

.option {
    display: flex; align-items: flex-start; gap: .65rem;
    padding: .6rem .8rem; margin-bottom: .45rem;
    border: 1px solid var(--line); border-radius: var(--radius);
    cursor: pointer; font-size: .93rem;
}
.option:hover { border-color: var(--brand); background: var(--brand-tint); }
.option input { margin-top: .22rem; flex: none; width: 16px; height: 16px; accent-color: var(--brand); }
.option__letter { font-weight: 700; color: var(--brand); flex: none; }

.question-card.is-unsaved { border-left: 3px solid var(--danger); }
.question-card__state { display: flex; gap: .4rem; align-items: center; margin-top: .7rem; min-height: 22px; }

/* Progress counter in the exam bar */
.exam-progress {
    font-size: .82rem; font-weight: 600; color: rgba(255,255,255,.85);
    background: rgba(255,255,255,.12); padding: .35rem .7rem; border-radius: var(--radius);
    white-space: nowrap;
}

/* Autosave status line */
.save-status {
    font-size: .84rem; font-weight: 500; padding: .5rem .85rem; border-radius: var(--radius);
    margin-bottom: 1rem; border: 1px solid var(--line); background: var(--surface); color: var(--ink-muted);
}
.save-status--saving { background: var(--brand-tint);   border-color: var(--brand-tint-2); color: var(--brand-dark); }
.save-status--saved  { background: var(--success-tint); border-color: #b6e4c7; color: #0b6c34; }
.save-status--error  { background: var(--danger-tint);  border-color: #f0c2c5; color: #96222a; }

/* Question navigator strip */
.qnav { display: flex; flex-wrap: wrap; gap: .3rem; }
.qnav__item {
    display: flex; align-items: center; justify-content: center;
    width: 32px; height: 32px; border-radius: 5px;
    border: 1px solid var(--line-strong); background: var(--surface);
    font-size: .76rem; font-weight: 600; color: var(--ink-soft); text-decoration: none;
}
.qnav__item:hover { border-color: var(--brand); color: var(--brand); text-decoration: none; }
.qnav__item.is-answered { background: var(--success); border-color: var(--success); color: #fff; }
/* Ring marks which page the candidate is currently on, so a 120-question
   strip still shows them where they are. */
.qnav__item.is-current-page { box-shadow: 0 0 0 2px var(--brand-tint-2); }

.qnav__key { display: inline-block; width: 11px; height: 11px; border-radius: 3px; vertical-align: -1px; margin: 0 .25rem 0 .6rem; }
.qnav__key--answered { background: var(--success); }
.qnav__key--blank { background: var(--surface); border: 1px solid var(--line-strong); }

/* Page-to-page navigation */
.pager {
    display: flex; align-items: center; justify-content: space-between; gap: 1rem;
    background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-lg);
    padding: .85rem 1.15rem; box-shadow: var(--shadow-sm); margin-bottom: 1.25rem;
}
.pager__meta { font-size: .85rem; font-weight: 600; color: var(--ink-muted); }

/* --------------------------------------------------------------------------
   16. Live monitoring video
   -------------------------------------------------------------------------- */
.video-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 1rem; }

.video-tile {
    background: #0d1620; border: 1px solid var(--line); border-radius: var(--radius-lg);
    overflow: hidden; box-shadow: var(--shadow-sm); position: relative;
}
.video-tile.is-flagged { border-color: var(--warning); box-shadow: 0 0 0 2px var(--warning-tint); }

.video-tile__frame { position: relative; aspect-ratio: 4 / 3; background: #0d1620; }
.video-tile__frame video { width: 100%; height: 100%; object-fit: cover; display: block; }

.video-tile__placeholder {
    position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
    color: rgba(255,255,255,.45); font-size: .82rem; text-align: center; padding: 1rem;
}

.video-tile__bar {
    background: var(--surface); padding: .6rem .8rem;
    display: flex; align-items: center; justify-content: space-between; gap: .6rem;
}
.video-tile__who { min-width: 0; }
.video-tile__name { font-weight: 600; font-size: .88rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.video-tile__idx  { font-size: .76rem; color: var(--ink-muted); }

.live-dot {
    display: inline-flex; align-items: center; gap: .3rem;
    font-size: .7rem; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
    color: #fff; background: rgba(0,0,0,.55); padding: .18rem .45rem; border-radius: 4px;
    position: absolute; top: .5rem; left: .5rem; z-index: 2;
}
.live-dot::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--ke-red); }
.live-dot.is-live::before { animation: pulse 1.4s ease-in-out infinite; }
.live-dot.is-offline { color: rgba(255,255,255,.6); }
.live-dot.is-offline::before { background: var(--ink-muted); animation: none; }

/* Candidate's own self-view during an exam */
.selfview {
    position: fixed; bottom: 1rem; right: 1rem; z-index: 40;
    width: 180px; border-radius: var(--radius); overflow: hidden;
    border: 2px solid var(--brand); background: #0d1620; box-shadow: var(--shadow-lg);
}
.selfview video { width: 100%; display: block; aspect-ratio: 4/3; object-fit: cover; }
.selfview__label {
    background: var(--brand); color: #fff; font-size: .68rem; font-weight: 700;
    padding: .18rem .45rem; text-align: center; letter-spacing: .04em; text-transform: uppercase;
}
.selfview.is-error { border-color: var(--ke-red); }
.selfview.is-error .selfview__label { background: var(--ke-red); }

/* --------------------------------------------------------------------------
   17. Misc
   -------------------------------------------------------------------------- */
.divider { height: 1px; background: var(--line); border: 0; margin: 1.25rem 0; }

.dl { display: grid; grid-template-columns: 190px 1fr; gap: .55rem 1rem; font-size: .91rem; }
.dl dt { color: var(--ink-muted); font-weight: 500; }
.dl dd { margin: 0; font-weight: 500; }

.pagination { display: flex; gap: .3rem; list-style: none; padding: 0; margin: 1.15rem 0 0; flex-wrap: wrap; font-size: .86rem; }
.pagination li span, .pagination li a {
    display: block; padding: .35rem .65rem; border: 1px solid var(--line);
    border-radius: var(--radius); background: var(--surface); color: var(--ink-soft); text-decoration: none;
}
.pagination li a:hover { border-color: var(--brand); color: var(--brand); }
.pagination .active span { background: var(--brand); border-color: var(--brand); color: #fff; font-weight: 600; }
.pagination .disabled span { opacity: .45; }

.result-hero { text-align: center; padding: 2rem 1rem; }
.result-hero__outcome { font-size: 2.6rem; font-weight: 800; letter-spacing: .04em; line-height: 1; }
.result-hero__outcome.is-pass { color: var(--success); }
.result-hero__outcome.is-fail { color: var(--danger); }
.result-hero__score { font-size: 1.35rem; font-weight: 600; color: var(--ink-soft); margin-top: .5rem; }

/* --------------------------------------------------------------------------
   Wide tables that must not push the page sideways
   --------------------------------------------------------------------------
   The access log carries eight columns including a full IPv6 address. On a
   laptop it fits; on a narrow window it must scroll inside its own box
   rather than making the whole page scroll horizontally, which breaks the
   navigation along with it.
   -------------------------------------------------------------------------- */
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.table-scroll .table { min-width: 900px; }

/* A row worth a second look: a failed sign-in, an address that changed
   mid-examination. Tinted rather than badged alone, so a run of them is
   visible while scrolling quickly. */
.row--alert > td { background: var(--danger-tint); }

.filter-bar { display: flex; gap: .5rem; flex-wrap: wrap; align-items: center; margin-bottom: 1rem; }
.filter-bar .input, .filter-bar .select { width: auto; min-width: 200px; }

.tabs { display: flex; gap: .3rem; border-bottom: 1px solid var(--line); margin-bottom: 1.25rem; flex-wrap: wrap; }
.tabs a {
    padding: .55rem .95rem; font-size: .89rem; font-weight: 600; color: var(--ink-muted);
    border-bottom: 2px solid transparent; margin-bottom: -1px; text-decoration: none;
}
.tabs a:hover { color: var(--brand); text-decoration: none; }
.tabs a.is-active { color: var(--brand); border-bottom-color: var(--brand); }

.footer { text-align: center; padding: 1.5rem; color: var(--ink-muted); font-size: .8rem; }

/* --------------------------------------------------------------------------
   18. Responsive
   -------------------------------------------------------------------------- */
@media (max-width: 900px) {
    .shell--split { grid-template-columns: 1fr; }
    .sidebar { position: static; }
    .grid-2, .grid-3 { grid-template-columns: 1fr; }
    .dl { grid-template-columns: 1fr; gap: .15rem; }
    .dl dd { margin-bottom: .6rem; }
}

@media (max-width: 640px) {
    .masthead__inner { flex-direction: column; align-items: flex-start; gap: .75rem; }
    .masthead__user { width: 100%; justify-content: space-between; }
    .masthead__identity { text-align: left; }
    .masthead__logo { height: 42px; }
    .shell { padding: 1.25rem 1rem 3rem; }
    .selfview { width: 128px; }
    .timer { font-size: 1.2rem; }
}

/* Print — used when a registrar prints an approval record or a result slip */
@media print {
    .sidebar, .masthead__user, .back-link, .btn, .exam-bar, .selfview { display: none !important; }
    body { background: #fff; }
    .card { box-shadow: none; border-color: #999; }
}

/* --------------------------------------------------------------------------
   Evidence review
   --------------------------------------------------------------------------
   A grid of stills and clips an officer scans before deciding whether any
   of it means anything. Sized so a face is recognisable without the page
   becoming a wall of video: the whole point is to glance across twenty
   captures and find the two worth opening. */
.evidence-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 1.1rem;
}

.evidence {
    margin: 0;
    border: 1px solid var(--line, #dde5eb);
    border-radius: 6px;
    overflow: hidden;
    background: #fff;
}

.evidence__media {
    display: block;
    width: 100%;
    aspect-ratio: 4 / 3;
    max-width: 100%;
    object-fit: cover;
    background: #1b232b;
}

.evidence__caption {
    padding: .55rem .7rem .65rem;
    display: flex;
    flex-direction: column;
    gap: .15rem;
    font-size: .88rem;
}

@media (max-width: 480px) {
    .evidence-grid { grid-template-columns: 1fr; }
}
