/* ==========================================================================
   Tangaza University Student Portal - shared design system
   --------------------------------------------------------------------------
   Every page in the portal is built from the components in this file. Before
   adding a <style> block to a view, check whether the thing you need is
   already here - the point of this file is that a table on the Fee Statement
   looks like a table on the Results page without anybody having to remember
   the hex codes.

   Palette is the official Tangaza University website palette:

       Primary          #c52127   red      - primary actions, active nav, links
       Secondary        #d19c2c   gold     - accents, rails, icons on dark
       Secondary Purple #51506E            - card and table headers
       Secondary Black  #444444            - chrome, body text

   Prefix is tz- so nothing collides with Bootstrap 4 or the pcoded theme.
   Change a colour here and it changes everywhere; do not hard-code hex values
   in a view.
   ========================================================================== */

:root {
    /* Brand - primary red */
    --tz-crimson: #c52127;
    --tz-crimson-dark: #a41a1f;
    --tz-crimson-soft: #fbeaeb;

    /* Brand - secondary gold */
    --tz-gold: #d19c2c;
    --tz-gold-dark: #b08222;
    --tz-gold-soft: #fbf3e3;

    /* Brand - secondary purple, used for headers */
    --tz-purple: #51506E;
    --tz-purple-dark: #414058;
    --tz-purple-soft: #eeeef3;

    /* Brand - secondary black */
    --tz-ink: #444444;
    --tz-ink-deep: #333333;
    --tz-header: #444444;

    /* Neutrals */
    --tz-text: #2f3337;
    --tz-text-muted: #6b7280;
    --tz-text-faint: #98a0ab;
    --tz-border: #e3e6ec;
    --tz-border-soft: #edeff3;
    --tz-surface: #ffffff;
    --tz-surface-alt: #fafbfc;
    --tz-canvas: #f4f6f9;

    /* Semantic */
    --tz-success: #2e7d32;
    --tz-success-soft: #e8f5e9;
    --tz-warn: #9a6100;
    --tz-warn-soft: #fff3e0;
    --tz-danger: #c62828;
    --tz-danger-soft: #fdecea;
    --tz-info: #1565c0;
    --tz-info-soft: #e8f1fb;

    --tz-radius: 6px;
    --tz-radius-sm: 4px;
    --tz-shadow: 0 1px 3px rgba(16, 24, 40, .06), 0 1px 2px rgba(16, 24, 40, .04);
    --tz-shadow-lg: 0 4px 16px rgba(16, 24, 40, .10);

    /* Typeface. Linked from Google Fonts in SiteMaster and LoginMaster.
       The fallback stack is load-bearing, not decoration: if fonts.googleapis.com is
       blocked or slow the page renders in the platform UI face instead of dropping to
       an arbitrary serif. Do not add "feather" or "FontAwesome" here - those are icon
       fonts and the theme sets them per-element. */
    --tz-font: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
               "Helvetica Neue", Arial, sans-serif;
}

/* ==========================================================================
   0b. Typography
   The pcoded theme asks for "open sans" on body and "quicksand" on headings, the
   header and the sidebar, but never loaded either - both silently fell back to the
   browser default. These rules replace all four with Inter.
   portal.css is the last stylesheet in the document, so it wins on equal specificity;
   the selectors below match the theme's own so no !important is needed except where
   the theme used a heavier hand.
   ========================================================================== */

body,
.pcoded .pcoded-header,
.pcoded .pcoded-navbar {
    font-family: var(--tz-font);
    /* Inter ships contextual alternates that tighten spacing around punctuation. */
    -webkit-font-feature-settings: "cv05", "cv11";
    font-feature-settings: "cv05", "cv11";
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3, h4, h5, h6 {
    font-family: var(--tz-font);
    /* Inter runs optically larger than Quicksand at the same size, so headings need a
       tighter fit to keep the vertical rhythm the cards were spaced for. */
    letter-spacing: -.011em;
    text-wrap: balance;
}

/* Form controls do not inherit the document face on any browser. */
input, select, textarea, button, .form-control, .btn {
    font-family: inherit;
}

/* --- File-type icons -----------------------------------------------------
   Used by the Important Documents table. Font Awesome 4.7 glyphs, coloured by
   type so the list is scannable without reading the Type column. These replace
   img/pdf.png and img/word.png, which the markup referenced but which have
   never existed in the project. */

.tz-fileicon {
    font-size: 21px;
    line-height: 1;
    vertical-align: middle;
    color: var(--tz-text-muted);
}

.tz-fileicon-pdf {
    color: #c52127;
}

.tz-fileicon-word {
    color: #2b579a;
}

.tz-fileicon-excel {
    color: #217346;
}

.tz-fileicon-ppt {
    color: #c55a11;
}

.tz-fileicon-image {
    color: #51506e;
}

.tz-fileicon-archive {
    color: #b07d16;
}

.tz-fileicon-other {
    color: #6b7280;
}

/* The icon is the download control, so it needs a visible affordance. */
.tz-table a:hover .tz-fileicon,
.tz-table a:focus-visible .tz-fileicon {
    opacity: .72;
}

/* ==========================================================================
   1. Page shell
   ========================================================================== */

.tz-page {
    padding: 22px 26px 60px 26px;
    background: var(--tz-canvas);
    min-height: calc(100vh - 70px);
    color: var(--tz-text);
    font-size: 13.5px;
}

/* Page title bar. Sits at the top of every page, above the first card. */
.tz-page-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 12px;
    margin-bottom: 20px;
}

    .tz-page-head h1 {
        margin: 0;
        font-size: 21px;
        font-weight: 600;
        letter-spacing: .2px;
        color: var(--tz-ink);
        line-height: 1.25;
    }

        .tz-page-head h1 i {
            color: var(--tz-crimson);
            margin-right: 9px;
            vertical-align: -2px;
        }

    .tz-page-head .tz-sub {
        margin: 5px 0 0 0;
        font-size: 13px;
        color: var(--tz-text-muted);
    }

    .tz-page-head .tz-page-actions {
        display: flex;
        flex-wrap: wrap;
        gap: 8px;
        align-items: center;
    }

/* Dark identity banner - student number, name, programme, semester. */
.tz-banner {
    background: linear-gradient(135deg, var(--tz-purple) 0%, var(--tz-purple-dark) 100%);
    border-left: 4px solid var(--tz-gold);
    color: #fff;
    border-radius: var(--tz-radius);
    padding: 18px 22px;
    margin-bottom: 22px;
    box-shadow: var(--tz-shadow);
}

.tz-facts {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 30px;
}

.tz-fact .k {
    display: block;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: .9px;
    text-transform: uppercase;
    color: var(--tz-gold);
    margin-bottom: 3px;
}

.tz-fact .v {
    display: block;
    font-size: 13.5px;
    font-weight: 600;
    color: #fff;
    word-break: break-word;
}

/* ==========================================================================
   2. Cards
   ========================================================================== */

.tz-card {
    background: var(--tz-surface);
    border: 1px solid var(--tz-border);
    border-radius: var(--tz-radius);
    margin-bottom: 22px;
    box-shadow: var(--tz-shadow);
    overflow: hidden;
}

.tz-card-head {
    background: var(--tz-purple);
    color: #fff;
    padding: 12px 18px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 8px;
}

    .tz-card-head h2,
    .tz-card-head .tz-card-title {
        margin: 0;
        font-size: 13px;
        font-weight: 600;
        letter-spacing: .5px;
        text-transform: uppercase;
        color: #fff;
        display: flex;
        align-items: center;
    }

        .tz-card-head h2 i,
        .tz-card-head .tz-card-title i {
            color: var(--tz-gold);
            margin-right: 8px;
        }

.tz-card-body {
    padding: 18px;
}

    .tz-card-body > :last-child {
        margin-bottom: 0;
    }

/* Numbered step marker used on multi-stage pages (course registration). */
.tz-step {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: var(--tz-gold);
    color: var(--tz-ink);
    font-weight: 700;
    font-size: 11.5px;
    margin-right: 10px;
    flex: 0 0 auto;
}

/* Small count chip that follows a card title. */
.tz-count {
    display: inline-block;
    background: var(--tz-crimson);
    color: #fff;
    border-radius: 20px;
    padding: 1px 10px;
    font-size: 11px;
    font-weight: 700;
    margin-left: 9px;
}

.tz-count-zero {
    background: #6d6d6d;
}

/* Chip in a dark card header, e.g. the current semester. */
.tz-chip {
    background: rgba(255,255,255,.10);
    border: 1px solid rgba(229,169,59,.45);
    border-radius: 20px;
    padding: 3px 14px;
    font-size: 11.5px;
    font-weight: 600;
    color: #fff;
    white-space: nowrap;
}

    .tz-chip i {
        color: var(--tz-gold);
        margin-right: 5px;
    }

/* ==========================================================================
   3. Tables
   ========================================================================== */

.tz-scroll {
    max-height: 420px;
    overflow: auto;
    border: 1px solid var(--tz-border);
    border-radius: var(--tz-radius-sm);
    background: var(--tz-surface);
}

.tz-scroll-tall {
    max-height: 620px;
}

.tz-scroll-auto {
    max-height: none;
    overflow-x: auto;
}

.tz-table {
    width: 100%;
    margin: 0;
    font-size: 12.5px;
    border-collapse: separate;
    border-spacing: 0;
    background: var(--tz-surface);
}

    .tz-table thead th {
        position: sticky;
        top: 0;
        z-index: 2;
        background: var(--tz-purple);
        color: #fff;
        font-size: 10.5px;
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: .6px;
        padding: 10px 12px;
        border: 0;
        white-space: nowrap;
        text-align: left;
    }

    /* A header carrying .tz-num or .tz-center has to beat ".tz-table thead th" above,
       which is more specific than the bare .tz-num / .tz-center utilities. Without these
       the heading sat left while its numbers sat right, so every numeric column looked
       shifted against its own title. */
    .tz-table thead th.tz-num {
        text-align: right;
    }

    .tz-table thead th.tz-center {
        text-align: center;
    }

    .tz-table tbody td {
        padding: 9px 12px;
        border-top: 1px solid var(--tz-border-soft);
        vertical-align: middle;
        color: var(--tz-text);
    }

    .tz-table tbody tr:nth-child(even) {
        background: var(--tz-surface-alt);
    }

    .tz-table tbody tr:hover {
        background: var(--tz-gold-soft);
    }

    .tz-table tfoot td {
        background: var(--tz-purple-dark);
        color: var(--tz-gold);
        font-weight: 700;
        padding: 10px 12px;
        border: 0;
    }

    /* Row emphasis */
    .tz-table tr.tz-row-fail td {
        background: var(--tz-danger-soft);
    }

    .tz-table tr.tz-row-total td {
        font-weight: 700;
        background: #f1f3f7;
    }

.tz-num {
    text-align: right;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.tz-code {
    font-weight: 600;
    color: var(--tz-ink);
    white-space: nowrap;
}

.tz-nowrap {
    white-space: nowrap;
}

/* ==========================================================================
   4. Pills / status badges
   ========================================================================== */

.tz-pill {
    display: inline-block;
    padding: 3px 10px;
    border-radius: 20px;
    font-size: 10.5px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .4px;
    white-space: nowrap;
    line-height: 1.6;
}

    .tz-pill i {
        font-size: 11px;
        margin-right: 4px;
        vertical-align: -1px;
    }

.tz-pill-neutral {
    background: #eceff3;
    color: #4a5158;
}

.tz-pill-info {
    background: var(--tz-info-soft);
    color: var(--tz-info);
}

.tz-pill-success {
    background: var(--tz-success-soft);
    color: var(--tz-success);
}

.tz-pill-warn {
    background: var(--tz-warn-soft);
    color: var(--tz-warn);
}

.tz-pill-danger {
    background: var(--tz-danger-soft);
    color: var(--tz-danger);
}

.tz-pill-gold {
    background: var(--tz-gold-soft);
    color: var(--tz-gold-dark);
}

/* ==========================================================================
   5. Buttons
   ========================================================================== */

.tz-btn {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    border: 1px solid transparent;
    border-radius: var(--tz-radius-sm);
    padding: 9px 17px;
    font-size: 12.5px;
    font-weight: 600;
    line-height: 1.2;
    cursor: pointer;
    text-decoration: none;
    transition: background .15s ease, border-color .15s ease, color .15s ease;
    white-space: nowrap;
}

    .tz-btn:focus {
        outline: 2px solid var(--tz-gold);
        outline-offset: 2px;
    }

    .tz-btn:disabled,
    .tz-btn.tz-btn-disabled {
        opacity: .45;
        cursor: not-allowed;
    }

    .tz-btn i {
        font-size: 14px;
    }

.tz-btn-primary {
    background: var(--tz-crimson);
    color: #fff;
}

    .tz-btn-primary:hover:not(:disabled) {
        background: var(--tz-crimson-dark);
        color: #fff;
        text-decoration: none;
    }

.tz-btn-gold {
    background: var(--tz-gold);
    color: var(--tz-ink);
}

    .tz-btn-gold:hover:not(:disabled) {
        background: var(--tz-gold-dark);
        color: var(--tz-ink);
        text-decoration: none;
    }

.tz-btn-dark {
    background: var(--tz-ink);
    color: #fff;
}

    .tz-btn-dark:hover:not(:disabled) {
        background: #333;
        color: #fff;
        text-decoration: none;
    }

.tz-btn-ghost {
    background: var(--tz-surface);
    color: var(--tz-ink);
    border-color: #c9cfd9;
}

    .tz-btn-ghost:hover:not(:disabled) {
        background: #f1f3f7;
        color: var(--tz-ink);
        text-decoration: none;
    }

.tz-btn-sm {
    padding: 5px 11px;
    font-size: 11.5px;
}

.tz-btn-block {
    width: 100%;
    justify-content: center;
}

.tz-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 9px;
    align-items: center;
}

/* Inline table links */
.tz-link {
    color: var(--tz-crimson);
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
}

    .tz-link:hover {
        color: var(--tz-crimson-dark);
        text-decoration: underline;
    }

.tz-link-muted {
    color: var(--tz-text-muted);
    font-weight: 600;
    text-decoration: none;
}

    .tz-link-muted:hover {
        color: var(--tz-ink);
        text-decoration: underline;
    }

/* ==========================================================================
   6. Callouts and empty states
   ========================================================================== */

.tz-hint {
    background: var(--tz-gold-soft);
    border-left: 3px solid var(--tz-gold);
    border-radius: var(--tz-radius-sm);
    padding: 12px 16px;
    margin-bottom: 18px;
    font-size: 12.5px;
    color: #5c4a1e;
}

    .tz-hint ol,
    .tz-hint ul {
        margin: 0;
        padding-left: 18px;
    }

    .tz-hint li {
        margin-bottom: 3px;
    }

        .tz-hint li:last-child {
            margin-bottom: 0;
        }

.tz-note {
    background: var(--tz-info-soft);
    border-left: 3px solid var(--tz-info);
    color: #14406e;
}

.tz-warning {
    background: var(--tz-warn-soft);
    border-left: 3px solid #ef9a00;
    color: #6d4500;
}

.tz-alert {
    background: var(--tz-danger-soft);
    border-left: 3px solid var(--tz-danger);
    color: #8c1d18;
}

.tz-empty {
    text-align: center;
    padding: 38px 18px;
    color: var(--tz-text-faint);
    font-size: 13px;
}

    .tz-empty i {
        font-size: 32px;
        display: block;
        margin-bottom: 10px;
        opacity: .45;
    }

    .tz-empty strong {
        color: var(--tz-text-muted);
    }

/* ==========================================================================
   7. Stat tiles (dashboard)
   ========================================================================== */

.tz-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    /*  A bare 190px floor cannot shrink, so on a narrow phone the track stays
        190px wide and the grid runs past the screen - which is why cards lost
        their right-hand edge. min() lets the track fall back to the full width
        of its container when that is the smaller of the two. The plain
        declaration above stays as a fallback for anything without min(). */
    grid-template-columns: repeat(auto-fit, minmax(min(190px, 100%), 1fr));
    gap: 16px;
    margin-bottom: 22px;
}

.tz-stat {
    background: var(--tz-surface);
    border: 1px solid var(--tz-border);
    border-left: 4px solid var(--tz-crimson);
    border-radius: var(--tz-radius);
    padding: 16px 18px;
    box-shadow: var(--tz-shadow);
}

.tz-stat-gold {
    border-left-color: var(--tz-gold);
}

.tz-stat-success {
    border-left-color: var(--tz-success);
}

.tz-stat-info {
    border-left-color: var(--tz-info);
}

.tz-stat .tz-stat-label {
    display: block;
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: .8px;
    text-transform: uppercase;
    color: var(--tz-text-muted);
    margin-bottom: 6px;
}

.tz-stat .tz-stat-value {
    display: block;
    font-size: 23px;
    font-weight: 700;
    color: var(--tz-ink);
    font-variant-numeric: tabular-nums;
    line-height: 1.15;
}

.tz-stat .tz-stat-foot {
    display: block;
    font-size: 11.5px;
    color: var(--tz-text-faint);
    margin-top: 5px;
}

/* ==========================================================================
   7b. Profile photo
   ========================================================================== */

.tz-avatar-row {
    display: flex;
    align-items: center;
    gap: 16px;
    padding-bottom: 16px;
    margin-bottom: 4px;
    border-bottom: 1px solid var(--tz-border-soft);
}

.tz-avatar {
    width: 78px;
    height: 78px;
    border-radius: 50%;
    object-fit: cover;
    border: 3px solid var(--tz-gold);
    background: var(--tz-surface-alt);
    flex: 0 0 auto;
}

.tz-avatar-empty {
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--tz-text-faint);
    font-size: 30px;
}

.tz-avatar-actions {
    min-width: 0;
}

    .tz-avatar-actions .tz-file {
        display: none;
    }

    .tz-avatar-actions label.tz-btn {
        margin: 0;
    }

/* ==========================================================================
   7c. Dashboard: hero tiles, quick actions, identity grid
   ========================================================================== */

/* Greeting strip above the page title. */
.tz-greeting {
    font-size: 13px;
    color: var(--tz-text-muted);
    margin: 0 0 2px 0;
}

    .tz-greeting strong {
        color: var(--tz-ink);
    }

    .tz-greeting i {
        margin-right: 5px;
        color: var(--tz-gold-dark);
    }

/* Dismissible banner. */
.tz-hint {
    position: relative;
}

.tz-dismiss {
    position: absolute;
    top: 8px;
    right: 10px;
    background: none;
    border: 0;
    padding: 2px 6px;
    line-height: 1;
    font-size: 18px;
    color: inherit;
    opacity: .45;
    cursor: pointer;
}

    .tz-dismiss:hover {
        opacity: 1;
    }

/* Filled headline tiles for the two unit counts. */
.tz-hero {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    /*  A bare 210px floor cannot shrink, so on a narrow phone the track stays
        210px wide and the grid runs past the screen - which is why cards lost
        their right-hand edge. min() lets the track fall back to the full width
        of its container when that is the smaller of the two. The plain
        declaration above stays as a fallback for anything without min(). */
    grid-template-columns: repeat(auto-fit, minmax(min(210px, 100%), 1fr));
    gap: 16px;
    margin-bottom: 22px;
    align-items: stretch;
}

.tz-hero-tile {
    border-radius: var(--tz-radius);
    padding: 18px 20px;
    color: #fff;
    box-shadow: var(--tz-shadow);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    min-height: 104px;
}

.tz-hero-red {
    background: linear-gradient(135deg, var(--tz-crimson) 0%, var(--tz-crimson-dark) 100%);
}

.tz-hero-gold {
    background: linear-gradient(135deg, var(--tz-gold) 0%, var(--tz-gold-dark) 100%);
}

.tz-hero-tile .tz-hero-label {
    display: block;
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: .9px;
    text-transform: uppercase;
    opacity: .92;
    margin-bottom: 6px;
}

.tz-hero-tile .tz-hero-value {
    display: block;
    /*  Was a flat 34px. The unit counts are one or two characters so they never
        cared, but the fee balance runs to eleven - "-244,700.00" - which at 34px
        tabular is about 212px of text. Once the grid goes to two columns (around
        470px upwards) the track is ~215px, and after the tile padding, the icon
        and the gap the figure has roughly 135px to live in, so it overflowed.
        The tile's div already carries min-width:0, so it shrank and the number
        spilled out of it rather than widening the tile.

        Fluid instead: 20px at phone width, growing with the viewport, capped just
        below the original size. Checked against the tightest case, which is the
        three-column layout around 900px, not the phone. */
    font-size: 34px; /* fallback for anything without clamp() */
    font-size: clamp(20px, 3.4vw, 32px);
    font-weight: 700;
    line-height: 1;
    font-variant-numeric: tabular-nums;
    /*  Last resort: a figure of this shape offers no natural break opportunity,
        so without this an unexpectedly long value would still escape the tile. */
    overflow-wrap: anywhere;
}

.tz-hero-tile .tz-hero-foot {
    display: block;
    font-size: 11.5px;
    opacity: .9;
    margin-top: 5px;
}

.tz-hero-tile > i {
    font-size: 30px;
    opacity: .35;
    flex: 0 0 auto;
}

/*  The fee tile. Same shape as its two siblings - label, figure, footnote, icon -
    but on a white surface with a gold edge, because it is the one tile that is a
    link rather than a statistic. It used to be a wide panel spanning two grid
    columns with three figures in it; with one figure that left a lot of empty
    tile for very little information. */
.tz-hero-fee {
    background: var(--tz-surface);
    border: 1px solid var(--tz-border);
    border-left: 4px solid var(--tz-gold);
    color: var(--tz-text);
    text-decoration: none;
}

    .tz-hero-fee:hover,
    .tz-hero-fee:focus {
        text-decoration: none;
        border-left-color: var(--tz-crimson);
    }

    .tz-hero-fee .tz-hero-label {
        color: var(--tz-crimson);
        opacity: 1;
    }

    .tz-hero-fee .tz-hero-value.owing {
        color: var(--tz-crimson);
    }

    .tz-hero-fee .tz-hero-value.credit {
        color: var(--tz-success);
    }

    .tz-hero-fee .tz-hero-foot {
        color: var(--tz-text-muted);
        opacity: 1;
    }

    .tz-hero-fee > i {
        color: var(--tz-gold);
        opacity: .5;
    }

    /*  Keyboard focus has to be visible - this is a link, not a panel. */
    .tz-hero-fee:focus-visible {
        outline: 2px solid var(--tz-gold);
        outline-offset: 2px;
    }

/* Fee summary tile: three figures side by side on a white card. */
.tz-fee-tile {
    grid-column: span 2;
    background: var(--tz-surface);
    border: 1px solid var(--tz-border);
    border-left: 4px solid var(--tz-gold);
    border-radius: var(--tz-radius);
    padding: 16px 20px;
    box-shadow: var(--tz-shadow);
    min-height: 104px;
}

    .tz-fee-tile h3 {
        margin: 0 0 12px 0;
        font-size: 10.5px;
        font-weight: 700;
        letter-spacing: .9px;
        text-transform: uppercase;
        color: var(--tz-crimson);
        text-align: center;
    }

.tz-fee-split {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}

    .tz-fee-split > div {
        flex: 1 1 110px;
        text-align: center;
    }

    .tz-fee-split .k {
        display: block;
        font-size: 11px;
        color: var(--tz-text-muted);
        margin-bottom: 3px;
    }

    .tz-fee-split .v {
        display: block;
        font-size: 18px;
        font-weight: 700;
        font-variant-numeric: tabular-nums;
        color: var(--tz-ink);
    }

    .tz-fee-split .v.paid {
        color: var(--tz-success);
    }

    .tz-fee-split .v.owing {
        color: var(--tz-crimson);
    }

    .tz-fee-split .v.credit {
        color: var(--tz-success);
    }

/*  Single-value variant of the fee tile. The tile used to carry Total Billed and
    Total Paid alongside the balance; with one figure it gets the room to be read
    at a glance, which is the point - the balance is the number a student acts on. */
.tz-fee-one {
    text-align: center;
}

    .tz-fee-one .k {
        display: block;
        font-size: 11px;
        color: var(--tz-text-muted);
        margin-bottom: 4px;
    }

    .tz-fee-one .v {
        display: block;
        font-size: 30px;
        font-weight: 700;
        line-height: 1.05;
        font-variant-numeric: tabular-nums;
        color: var(--tz-ink);
    }

        .tz-fee-one .v.owing {
            color: var(--tz-crimson);
        }

        .tz-fee-one .v.credit {
            color: var(--tz-success);
        }

.tz-fee-note {
    display: block;
    margin-top: 6px;
    font-size: 11.5px;
    color: var(--tz-text-muted);
}

@media (max-width: 700px) {
    .tz-fee-tile {
        grid-column: span 1;
    }
}

/* Two-column dashboard body: content left, quick actions right. */
.tz-dash-split {
    display: grid;
    grid-template-columns: minmax(0, 1.7fr) minmax(0, 1fr);
    gap: 20px;
    align-items: start;
}

@media (max-width: 1100px) {
    .tz-dash-split {
        grid-template-columns: 1fr;
    }
}

/* Identity grid: labelled value tiles with an icon. */
.tz-info-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
    /*  A bare 230px floor cannot shrink, so on a narrow phone the track stays
        230px wide and the grid runs past the screen - which is why cards lost
        their right-hand edge. min() lets the track fall back to the full width
        of its container when that is the smaller of the two. The plain
        declaration above stays as a fallback for anything without min(). */
    grid-template-columns: repeat(auto-fit, minmax(min(230px, 100%), 1fr));
    gap: 12px;
}

.tz-info-item {
    display: flex;
    align-items: flex-start;
    gap: 11px;
    border: 1px solid var(--tz-border);
    border-radius: var(--tz-radius-sm);
    padding: 11px 13px;
    background: var(--tz-surface);
    min-width: 0;
}

    .tz-info-item > i {
        color: var(--tz-crimson);
        font-size: 16px;
        margin-top: 2px;
        flex: 0 0 auto;
    }

    .tz-info-item .k {
        display: block;
        font-size: 10px;
        font-weight: 700;
        letter-spacing: .7px;
        text-transform: uppercase;
        color: var(--tz-text-muted);
        margin-bottom: 3px;
    }

    .tz-info-item .v {
        display: block;
        font-size: 13px;
        font-weight: 600;
        color: var(--tz-ink);
        word-break: break-word;
    }

        .tz-info-item .v.ok {
            color: var(--tz-success);
        }
/*  The text column inside a flex row must be told it may shrink.

    .tz-info-item and .tz-hero-tile are flex rows holding an icon and a bare
    <div> of label + value. A flex item defaults to min-width:auto, so that div
    refused to shrink below its content: the school email and the two mobile
    numbers are long unbroken strings, and they pushed each card wider than its
    grid column, which pushed the grid past the screen. That is what cut the
    right-hand cards off on a phone.

    word-break on .v could not help - it only applies once the box is actually
    constrained, and min-width:auto meant it never was. */
.tz-info-item > div,
.tz-hero-tile > div {
    min-width: 0;
}

    /*  break-word will not split a long token that has no break opportunity, and
        an email address is exactly that. anywhere will. */
    .tz-info-item .v {
        overflow-wrap: anywhere;
    }

/* Quick actions: a stack of tappable rows. */
.tz-quick {
    display: flex;
    flex-direction: column;
    gap: 9px;
}

.tz-quick-item {
    display: flex;
    align-items: center;
    gap: 12px;
    border: 1px solid var(--tz-border);
    border-left: 3px solid var(--tz-crimson);
    border-radius: var(--tz-radius-sm);
    padding: 12px 14px;
    background: var(--tz-surface);
    color: var(--tz-ink);
    font-size: 13px;
    font-weight: 600;
    text-decoration: none;
    transition: background .15s ease, border-color .15s ease, transform .15s ease;
}

    .tz-quick-item:hover {
        background: var(--tz-gold-soft);
        border-left-color: var(--tz-gold);
        color: var(--tz-ink);
        text-decoration: none;
        transform: translateX(2px);
    }

    .tz-quick-item > i:first-child {
        color: var(--tz-crimson);
        font-size: 17px;
        flex: 0 0 auto;
    }

    .tz-quick-item .tz-quick-label {
        flex: 1 1 auto;
        min-width: 0;
    }

    .tz-quick-item .tz-quick-go {
        color: var(--tz-text-faint);
        font-size: 15px;
        flex: 0 0 auto;
    }

/* Reg-no chip under the student's name. */
.tz-regchip {
    display: inline-block;
    background: var(--tz-ink);
    color: #fff;
    border-radius: var(--tz-radius-sm);
    padding: 3px 11px;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: .3px;
}

/* ==========================================================================
   8. Forms
   ========================================================================== */

.tz-label {
    display: block;
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .5px;
    color: var(--tz-text-muted);
    margin-bottom: 5px;
}

    .tz-label .tz-req {
        color: var(--tz-crimson);
        margin-left: 3px;
    }

.tz-field {
    margin-bottom: 16px;
}

.tz-input,
.tz-select,
.tz-textarea {
    width: 100%;
    border: 1px solid #c9cfd9;
    border-radius: var(--tz-radius-sm);
    padding: 9px 12px;
    font-size: 13px;
    color: var(--tz-text);
    background: var(--tz-surface);
}

    .tz-input:focus,
    .tz-select:focus,
    .tz-textarea:focus {
        border-color: var(--tz-gold);
        outline: none;
        box-shadow: 0 0 0 3px rgba(229,169,59,.18);
    }

    .tz-input:disabled,
    .tz-input[readonly] {
        background: #f4f5f7;
        color: var(--tz-text-muted);
    }

.tz-help {
    font-size: 11.5px;
    color: var(--tz-text-faint);
    margin-top: 4px;
}

.tz-error-text {
    font-size: 11.5px;
    color: var(--tz-danger);
    margin-top: 4px;
}

/* ==========================================================================
   9. Utilities
   ========================================================================== */

.tz-grid-2 {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    /*  A bare 260px floor cannot shrink, so on a narrow phone the track stays
        260px wide and the grid runs past the screen - which is why cards lost
        their right-hand edge. min() lets the track fall back to the full width
        of its container when that is the smaller of the two. The plain
        declaration above stays as a fallback for anything without min(). */
    grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
    gap: 18px;
}

.tz-grid-3 {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    /*  A bare 220px floor cannot shrink, so on a narrow phone the track stays
        220px wide and the grid runs past the screen - which is why cards lost
        their right-hand edge. min() lets the track fall back to the full width
        of its container when that is the smaller of the two. The plain
        declaration above stays as a fallback for anything without min(). */
    grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr));
    gap: 18px;
}

.tz-mt-0 {
    margin-top: 0;
}

.tz-mb-0 {
    margin-bottom: 0 !important;
}

.tz-mb-16 {
    margin-bottom: 16px;
}

.tz-mt-16 {
    margin-top: 16px;
}

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

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

.tz-strong {
    font-weight: 700;
}

.tz-center {
    text-align: center;
}

.tz-right {
    text-align: right;
}

/* Embedded PDF viewer body used by the document modals. */
.tz-pdf {
    width: 100%;
    height: 460px;
    background: #f4f5f7;
    border-radius: var(--tz-radius-sm);
}

/* ==========================================================================
   9b. Classes the existing markup still references
   --------------------------------------------------------------------------
   These were each redefined in a per-view <style> block. Their definitions were
   identical everywhere they appeared, so they live here once instead. Prefer the
   tz- components above for anything new.
   ========================================================================== */

/* Larger tick target for unit-selection tables. */
.checkboxClass {
    width: 18px;
    height: 18px;
    padding: 0;
    cursor: pointer;
    accent-color: var(--tz-crimson);
    vertical-align: middle;
}

/* Compact in-table buttons. Note .BtnPadding and .btnPadding are two different
   classes - CSS is case-sensitive and both spellings are used in the views. */
.BtnPadding,
.btnPadding,
.btnClass {
    padding: 5px 11px;
    font-size: 11.5px;
    line-height: 1.2;
    border-radius: var(--tz-radius-sm);
}

/* Section heading inside partials loaded into a modal. */
.spanClass {
    font-size: 15px;
    font-weight: 600;
    color: var(--tz-ink);
}

/* Row the user has clicked in a pick-list. */
.selectedTableRow,
.tz-table tbody tr.selectedTableRow,
.tz-table tbody tr.selectedTableRow:hover {
    background: var(--tz-purple) !important;
    color: #fff !important;
}

    .selectedTableRow td {
        color: #fff !important;
    }

/* ==========================================================================
   10. Modals - align the Bootstrap modal with the card look
   ========================================================================== */

.tz-modal .modal-header {
    background: var(--tz-purple);
    color: #fff;
    border-bottom: 3px solid var(--tz-gold);
    padding: 13px 18px;
    align-items: center;
}

    .tz-modal .modal-header .modal-title {
        font-size: 14px;
        font-weight: 600;
        letter-spacing: .4px;
        text-transform: uppercase;
        color: #fff;
        margin: 0;
    }

    .tz-modal .modal-header .close {
        color: #fff;
        opacity: .8;
        text-shadow: none;
        font-size: 26px;
        line-height: 1;
    }

        .tz-modal .modal-header .close:hover {
            opacity: 1;
            color: var(--tz-gold);
        }

.tz-modal .modal-body {
    padding: 18px;
}

.tz-modal .modal-footer {
    border-top: 1px solid var(--tz-border);
    padding: 12px 18px;
}

/* ==========================================================================
   10b. Sign-in pages (Login, Forgot Password, Reset Password)
   ========================================================================== */

.tz-auth-body {
    background: #2b2b33 url('../img/login-bg2.jpg') center / cover no-repeat fixed;
    min-height: 100vh;
    margin: 0;
}

    /* Darken the photo so white text on it stays readable whatever the image is. */
    .tz-auth-body::before {
        content: "";
        position: fixed;
        inset: 0;
        background: linear-gradient(135deg, rgba(30,30,36,.82) 0%, rgba(30,30,36,.62) 100%);
        z-index: 0;
    }

.tz-auth-wrap {
    position: relative;
    z-index: 1;
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 30px 16px;
}

.tz-auth-card {
    width: 100%;
    max-width: 410px;
    background: #fff;
    border-radius: 10px;
    box-shadow: 0 18px 50px rgba(0,0,0,.35);
    overflow: hidden;
}

.tz-auth-head {
    /*  Crimson is held through the top half - where the crest sits - before the
        ramp to gold. Same two brand colours and the same warmth as before; it
        just no longer puts a pale crest on a pale ground. */
    background: linear-gradient(160deg, var(--tz-crimson) 0%, var(--tz-crimson) 52%, var(--tz-gold) 100%);
    padding: 26px 26px 22px 26px;
    text-align: center;
}

    /*  No white plate behind the crest. Logo2.png is a transparent PNG, so the
        plate was turning it into a sticker plaqued onto the header.

        It does mean the crest has to sit on a ground it can be seen against, and
        it cannot sit on the gold end of the ramp: 52% of its opaque pixels are
        near-white (it averages #bdac9b) and light-on-gold measures 1.12:1, so
        half the crest would simply vanish. That is why .tz-auth-head below holds
        crimson for the top portion and only turns to gold underneath. */
    .tz-auth-head img {
        max-height: 74px;
        width: auto;
        background: none;
        padding: 0;
        filter: drop-shadow(0 2px 4px rgba(0, 0, 0, .35));
    }

    .tz-auth-head h1 {
        margin: 14px 0 0 0;
        font-size: 16px;
        font-weight: 700;
        letter-spacing: 1.4px;
        text-transform: uppercase;
        color: #fff;
    }

    .tz-auth-head p {
        margin: 5px 0 0 0;
        font-size: 12.5px;
        color: rgba(255,255,255,.9);
    }

.tz-auth-body-inner {
    padding: 26px;
}

.tz-auth-foot {
    padding: 14px 26px 22px 26px;
    text-align: center;
    font-size: 12px;
    color: var(--tz-text-faint);
}

/* Separated from the sign-in options above by a rule, so an external destination does not read
   as another way of getting into the portal. */
.tz-auth-alt {
    margin-top: 14px;
    padding-top: 14px;
    border-top: 1px solid var(--tz-border);
}

.tz-auth-alt-label {
    display: block;
    margin-bottom: 8px;
    font-size: 11.5px;
    color: var(--tz-text-faint);
}

    .tz-auth-foot a {
        color: var(--tz-crimson);
        font-weight: 600;
        text-decoration: none;
    }

        .tz-auth-foot a:hover {
            text-decoration: underline;
        }

/* "or" separator between the password and magic-link sign-in options */
.tz-auth-divider {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 18px 0 14px 0;
    color: var(--tz-text-faint);
    font-size: 11.5px;
    text-transform: uppercase;
    letter-spacing: .8px;
}

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

/* Password field with a reveal toggle */
.tz-password-wrap {
    position: relative;
}

    .tz-password-wrap .tz-input {
        padding-right: 40px;
    }

.tz-toggle-password {
    position: absolute;
    right: 12px;
    bottom: 9px;
    cursor: pointer;
    color: var(--tz-text-faint);
    z-index: 5;
    background: none;
    border: 0;
    padding: 0;
    line-height: 1;
}

    .tz-toggle-password:hover {
        color: var(--tz-ink);
    }

/* Live password-rule checklist on the reset page. The .valid / .invalid class
   names are set by that page's script, so they are kept as-is. */
.tz-pwrules {
    background: var(--tz-surface-alt);
    border: 1px solid var(--tz-border);
    border-radius: var(--tz-radius-sm);
    padding: 12px 14px;
    margin-bottom: 16px;
    font-size: 12px;
}

    .tz-pwrules div {
        padding: 2px 0;
    }

    .tz-pwrules i {
        margin-right: 8px;
        width: 13px;
        display: inline-block;
        text-align: center;
    }

    .tz-pwrules .valid {
        color: var(--tz-success) !important;
        font-weight: 600;
    }

    .tz-pwrules .invalid {
        color: var(--tz-text-faint);
    }

/* Text inputs must stay selectable - a previous rule elsewhere disabled it. */
.tz-auth-card input {
    -webkit-user-select: text !important;
    -moz-user-select: text !important;
    -ms-user-select: text !important;
    user-select: text !important;
    pointer-events: auto !important;
}

/* ==========================================================================
   10c. Motion and polish
   --------------------------------------------------------------------------
   Everything here hangs off class names the views already use, so no view needs
   editing to pick it up. Keep it restrained - this is a records system students
   use under deadline pressure, not a marketing site. Movement should tell them
   something arrived or responded, never decorate.

   The whole section is switched off under prefers-reduced-motion at the end.
   ========================================================================== */

@keyframes tz-fade-up {
    from {
        opacity: 0;
        transform: translateY(10px);
    }

    to {
        opacity: 1;
        transform: none;
    }
}

@keyframes tz-fade-in {
    from {
        opacity: 0;
    }

    to {
        opacity: 1;
    }
}

@keyframes tz-slide-down {
    from {
        opacity: 0;
        transform: translateY(-8px);
    }

    to {
        opacity: 1;
        transform: none;
    }
}

@keyframes tz-shimmer {
    from {
        background-position: -420px 0;
    }

    to {
        background-position: 420px 0;
    }
}

@keyframes tz-pop {
    0% {
        transform: scale(.94);
        opacity: 0;
    }

    60% {
        transform: scale(1.02);
    }

    100% {
        transform: scale(1);
        opacity: 1;
    }
}

/* --- Page entrance ------------------------------------------------------- */

.tz-page-head {
    animation: tz-slide-down .32s ease-out both;
}

.tz-banner {
    animation: tz-fade-up .38s ease-out both;
}

/* Cards arrive in sequence rather than all at once. Capped at six so a long
   page never leaves the reader waiting on the last one. */
.tz-card {
    animation: tz-fade-up .38s ease-out both;
}

    .tz-card:nth-of-type(1) {
        animation-delay: .02s;
    }

    .tz-card:nth-of-type(2) {
        animation-delay: .07s;
    }

    .tz-card:nth-of-type(3) {
        animation-delay: .12s;
    }

    .tz-card:nth-of-type(4) {
        animation-delay: .17s;
    }

    .tz-card:nth-of-type(5) {
        animation-delay: .22s;
    }

    .tz-card:nth-of-type(n+6) {
        animation-delay: .26s;
    }

.tz-stat,
.tz-hero-tile,
.tz-fee-tile {
    animation: tz-fade-up .34s ease-out both;
}

.tz-stats .tz-stat:nth-child(2),
.tz-hero > *:nth-child(2) {
    animation-delay: .06s;
}

.tz-stats .tz-stat:nth-child(3),
.tz-hero > *:nth-child(3) {
    animation-delay: .12s;
}

.tz-stats .tz-stat:nth-child(4) {
    animation-delay: .18s;
}

.tz-stats .tz-stat:nth-child(5) {
    animation-delay: .24s;
}

/* Callouts slide in - they usually appear in response to something. */
.tz-hint {
    animation: tz-slide-down .3s ease-out both;
}

/* Quick-action rows cascade down the panel. */
.tz-quick-item {
    animation: tz-fade-up .3s ease-out both;
}

    .tz-quick-item:nth-child(1) {
        animation-delay: .04s;
    }

    .tz-quick-item:nth-child(2) {
        animation-delay: .08s;
    }

    .tz-quick-item:nth-child(3) {
        animation-delay: .12s;
    }

    .tz-quick-item:nth-child(4) {
        animation-delay: .16s;
    }

    .tz-quick-item:nth-child(5) {
        animation-delay: .20s;
    }

    .tz-quick-item:nth-child(6) {
        animation-delay: .24s;
    }

    .tz-quick-item:nth-child(7) {
        animation-delay: .28s;
    }

    .tz-quick-item:nth-child(n+8) {
        animation-delay: .32s;
    }

/* Empty states and the sign-in card get a gentler treatment. */
.tz-empty {
    animation: tz-fade-in .4s ease-out both;
}

.tz-auth-card {
    animation: tz-pop .34s cubic-bezier(.2, .8, .3, 1) both;
}

/* --- Response to touch --------------------------------------------------- */

.tz-card {
    transition: box-shadow .2s ease, transform .2s ease;
}

.tz-stat,
.tz-info-item {
    transition: box-shadow .18s ease, transform .18s ease, border-color .18s ease;
}

    .tz-stat:hover,
    .tz-info-item:hover {
        transform: translateY(-2px);
        box-shadow: var(--tz-shadow-lg);
    }

.tz-hero-tile {
    transition: transform .18s ease, box-shadow .18s ease;
}

    .tz-hero-tile:hover {
        transform: translateY(-3px);
        box-shadow: 0 10px 24px rgba(16, 24, 40, .18);
    }

.tz-btn {
    transform: translateZ(0);
}

    .tz-btn:hover:not(:disabled) {
        box-shadow: 0 4px 10px rgba(16, 24, 40, .12);
    }

    .tz-btn:active:not(:disabled) {
        transform: translateY(1px);
        box-shadow: none;
    }

/* Table rows settle rather than snap. */
.tz-table tbody tr {
    transition: background .15s ease;
}

/* Pills pop when they first render - they are the thing the eye should find.
   Not inside tables: a results table can hold hundreds of them, and animating
   every one at once stutters badly on the low-end machines students use. */
.tz-pill {
    animation: tz-pop .26s ease-out both;
}

.tz-table .tz-pill {
    animation: none;
}

/* Photo: hint that it can be replaced. */
.tz-avatar {
    transition: transform .2s ease, border-color .2s ease;
}

.tz-avatar-row:hover .tz-avatar {
    transform: scale(1.04);
    border-color: var(--tz-crimson);
}

/* --- Keyboard focus ------------------------------------------------------
   Visible focus is not decoration. Anyone navigating by keyboard needs to see
   where they are, and the browser default is nearly invisible on dark chrome. */

.tz-btn:focus-visible,
.tz-quick-item:focus-visible,
.tz-link:focus-visible,
.tz-input:focus-visible,
.tz-select:focus-visible,
.tz-nav-link:focus-visible {
    outline: 2px solid var(--tz-gold);
    outline-offset: 2px;
    border-radius: var(--tz-radius-sm);
}

/* --- Loading placeholder -------------------------------------------------
   Add class="tz-skeleton" to a block being filled by AJAX so the space is
   visibly reserved instead of collapsing and then jumping. */

.tz-skeleton {
    min-height: 90px;
    border-radius: var(--tz-radius-sm);
    background: linear-gradient(90deg, #f2f4f7 25%, #e9ecf2 37%, #f2f4f7 63%);
    background-size: 840px 100%;
    animation: tz-shimmer 1.3s linear infinite;
}

/* --- Loading overlay -----------------------------------------------------
   Overrides CSS/Loader.css, which is loaded before this file. The original was
   a black 80% sheet behind a 300x100 white box with a 5px light-blue border and
   an animated GIF, positioned by JavaScript arithmetic on every show. This is
   the same two elements, restyled and centred by CSS. */

.modalLoader {
    background: rgba(28, 28, 34, .55) !important;
    opacity: 1 !important;
    filter: none !important;
    backdrop-filter: blur(2px);
    animation: tz-fade-in .15s ease-out both;
}

.loading {
    width: auto !important;
    height: auto !important;
    min-width: 168px;
    border: 0 !important;
    border-top: 3px solid var(--tz-gold) !important;
    border-radius: var(--tz-radius) !important;
    background: #fff !important;
    box-shadow: 0 12px 34px rgba(0,0,0,.28) !important;
    padding: 22px 26px !important;
    font-family: inherit !important;
    font-size: 12.5px !important;
    color: var(--tz-text-muted);
    text-align: center;
    /* Centred here rather than by the inline top/left the script used to set. */
    top: 50% !important;
    left: 50% !important;
    transform: translate(-50%, -50%);
}

.tz-spinner {
    width: 34px;
    height: 34px;
    margin: 0 auto 10px auto;
    border: 3px solid var(--tz-border);
    border-top-color: var(--tz-crimson);
    border-right-color: var(--tz-gold);
    border-radius: 50%;
    animation: tz-spin .7s linear infinite;
}

@keyframes tz-spin {
    to {
        transform: rotate(360deg);
    }
}

/* --- Reduced motion ------------------------------------------------------
   Honour the operating-system setting. Some people get motion sickness or
   migraines from movement on screen; for them everything below simply appears. */

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

        .tz-card,
        .tz-stat,
        .tz-hero-tile,
        .tz-fee-tile,
        .tz-hint,
        .tz-quick-item,
        .tz-pill,
        .tz-auth-card,
        .tz-page-head,
        .tz-banner,
        .tz-empty {
            animation: none !important;
            opacity: 1 !important;
            transform: none !important;
        }

        .tz-stat:hover,
        .tz-info-item:hover,
        .tz-hero-tile:hover,
        .tz-btn:active:not(:disabled) {
            transform: none;
        }
}

/* ==========================================================================
   11. Print
   ========================================================================== */

@media print {
    .pcoded-navbar,
    .pcoded-header,
    .tz-page-actions,
    .tz-btn,
    #styleSelector {
        display: none !important;
    }

    .tz-page {
        background: #fff;
        padding: 0;
    }

    .tz-card {
        box-shadow: none;
        border: 1px solid #999;
        break-inside: avoid;
    }

    .tz-scroll {
        max-height: none;
        overflow: visible;
        border: 0;
    }

    .tz-card-head {
        background: #fff !important;
        color: #000 !important;
        border-bottom: 2px solid #000;
    }

        .tz-card-head h2,
        .tz-card-head .tz-card-title {
            color: #000 !important;
        }

    .tz-table thead th {
        background: #ddd !important;
        color: #000 !important;
        position: static;
    }
}

/* Styling for the explicit download button */
.tz-download-btn {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    background-color: #007bff;
    color: #ffffff;
    border: none;
    padding: 4px 10px;
    font-size: 12px;
    font-weight: 500;
    border-radius: 4px;
    cursor: pointer;
    transition: background-color 0.2s ease-in-out;
}

    .tz-download-btn:hover {
        background-color: #0056b3;
        color: #ffffff;
    }

    .tz-download-btn i {
        font-size: 13px;
    }

/* Ensure long text wraps instead of forcing horizontal overflow */
.tz-table td {
    vertical-align: middle;
}

/* ==========================================================================
   12. Small screens
   ========================================================================== */

@media (max-width: 768px) {
    /*  Containment guard... */
    .pcoded-main-container,
    .pcoded-content,
    .pcoded-inner-content,
    .tz-page {
        max-width: 100%;
        overflow-x: hidden; /* Prevents card horizontal overflow */
    }

    /*  The guard above stops the page itself scrolling sideways, but it does that
        by CLIPPING - so anything wider than the viewport was cut off with no way
        to reach it. The documents table is the clearest case: Action is a fixed
        110px, File a fixed 60px, and Type and Date Uploaded are both tz-nowrap,
        which gives the table a hard floor of roughly 460-500px. On a 393px phone
        it cannot shrink to fit, so it overflowed and the guard then hid the last
        two columns entirely.

        Letting the table scroll inside its own box fixes that without touching
        the guard: the table no longer overflows its parent, so nothing gets
        clipped, and the columns that do not fit are reachable by swiping.
        display:block is what makes a table scrollable - its rows and cells still
        lay out as a table inside an anonymous table box. */
    .tz-table {
        display: block;
        width: 100%;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }

    .tz-page {
        padding: 16px 14px 50px 14px;
    }

    .tz-page-head h1 {
        font-size: 18px;
    }

    .tz-facts {
        gap: 10px 18px;
    }

    .tz-card-body {
        padding: 14px;
    }

    .tz-btn {
        padding: 8px 13px;
        font-size: 12px;
    }

    .tz-stat .tz-stat-value {
        font-size: 20px;
    }
}

/* --- MOBILE SPECIFIC FIX FOR PERSONAL INFORMATION GRID --- */
@media (max-width: 576px) {
    /* Force 1-column layout on mobile so cards fit comfortably */
    .tz-info-grid {
        grid-template-columns: 1fr !important;
        gap: 8px;
    }

    /* Force full-width card boxes with standard padding */
    .tz-info-item {
        width: 100%;
        box-sizing: border-box;
        padding: 10px 12px;
    }

        /* Ensure text wrapping breaks properly on ultra-long values */
        .tz-info-item .v {
            word-break: break-word !important;
            overflow-wrap: anywhere !important;
            white-space: normal !important;
        }
}

/* ==========================================================================
   Unit picker (Course Registration dialog)
   ========================================================================== */

.tz-units-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 14px;
}

.tz-units-title {
    display: block;
    font-size: 14px;
    font-weight: 700;
    color: var(--tz-ink);
}

.tz-units-sub {
    display: block;
    font-size: 12px;
    color: var(--tz-text-muted);
}

/*  The credit budget. It used to be invisible until you exceeded it and got a
    warning; showing it while choosing is the whole point. */
.tz-credit-meter {
    display: inline-flex;
    align-items: baseline;
    gap: 6px;
    padding: 7px 14px;
    border-radius: 999px;
    background: var(--tz-gold-soft);
    border: 1px solid rgba(209, 156, 44, .45);
    white-space: nowrap;
}

    .tz-credit-meter .tz-credit-count {
        font-size: 15px;
        font-weight: 700;
        color: var(--tz-ink);
        font-variant-numeric: tabular-nums;
    }

    .tz-credit-meter .tz-credit-label {
        font-size: 10.5px;
        font-weight: 700;
        letter-spacing: .07em;
        text-transform: uppercase;
        color: var(--tz-text-muted);
    }

    /*  At the ceiling. Not an error - a full basket is a normal, correct state -
        so this reads as "done", not "wrong". */
    .tz-credit-meter.tz-credit-full {
        background: var(--tz-success-soft);
        border-color: rgba(46, 125, 50, .4);
    }

        .tz-credit-meter.tz-credit-full .tz-credit-count {
            color: var(--tz-success);
        }

/* --- The table ---------------------------------------------------------- */

.tz-units-table .tz-pick-col {
    width: 56px;
    text-align: center;
    vertical-align: middle;
}

.tz-units-table input[type="checkbox"] {
    width: 16px;
    height: 16px;
    cursor: pointer;
    accent-color: var(--tz-crimson);
}

.tz-units-table .tz-code {
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.tz-units-table .tz-num {
    text-align: center;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.tz-units-table tbody tr:hover {
    background: var(--tz-gold-soft);
}

/*  A unit already sitting in the basket. Left visible rather than filtered out,
    so the list still matches what the student expects to see, but it cannot be
    picked twice. */
.tz-units-table tbody tr.tz-already {
    opacity: .55;
}

    .tz-units-table tbody tr.tz-already:hover {
        background: transparent;
    }

.tz-already-tag {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 999px;
    background: var(--tz-success-soft);
    color: var(--tz-success);
    font-size: 9.5px;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    white-space: nowrap;
}

.tz-units-table .tz-stream {
    min-width: 110px;
}

/* --- Action row ---------------------------------------------------------- */

.tz-units-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-top: 16px;
    padding-top: 16px;
    border-top: 1px solid var(--tz-border);
}

.tz-units-status {
    font-size: 12.5px;
    color: var(--tz-text-muted);
}

.tz-units-actions .tz-btn:disabled {
    opacity: .45;
    cursor: not-allowed;
}

@media (max-width: 575px) {
    .tz-units-head,
    .tz-units-actions {
        flex-direction: column;
        align-items: stretch;
    }

        .tz-units-actions .tz-btn {
            width: 100%;
            justify-content: center;
        }
}

/* ==========================================================================
   Empty / unavailable states
   --------------------------------------------------------------------------
   A panel for "this is not available to you", as distinct from "something
   broke". Most reasons a form is withheld are ordinary - not yet graduating,
   window not open - and reporting those as errors tells a student the portal
   is broken when it is working exactly as intended.
   ========================================================================== */

.tz-state {
    display: flex;
    align-items: flex-start;
    gap: 16px;
    padding: 22px 24px;
    border-radius: var(--tz-radius);
    border: 1px solid var(--tz-border);
    border-left: 4px solid var(--tz-gold);
    background: var(--tz-surface);
}

.tz-state-icon {
    flex: 0 0 auto;
    width: 42px;
    height: 42px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--tz-gold-soft);
    color: var(--tz-gold-dark);
    font-size: 20px;
}

.tz-state-body {
    min-width: 0;
}

    .tz-state-body h3 {
        margin: 2px 0 6px 0;
        font-size: 15px;
        font-weight: 700;
        color: var(--tz-ink);
    }

    .tz-state-body p {
        margin: 0 0 6px 0;
        font-size: 13px;
        line-height: 1.55;
        color: var(--tz-text);
        max-width: 70ch;
    }

    .tz-state-body .tz-state-next {
        color: var(--tz-text-muted);
        margin-bottom: 0;
    }

/*  The error treatment, for when something genuinely did go wrong. */
.tz-state-error {
    border-left-color: var(--tz-danger);
}

    .tz-state-error .tz-state-icon {
        background: var(--tz-danger-soft);
        color: var(--tz-danger);
    }
