:root {
    /* Core palette - a deep institutional teal, not a SaaS purple-blue gradient. Named tokens
       first; the --accent-purple/-2 and --purple-bg names below are kept only because dozens of
       templates still reference them inline - they alias straight onto the new palette so every
       old reference repaints correctly without hunting down each usage. */
    --ink: #1C1E20;
    --ink-soft: #56595D;
    --paper: #EAEDED;
    --card-bg: #FFFFFF;  /* pure white, so cards step off the grey */
    --line: #D5D9D9;

    --accent: #10629E;
    --accent-2: #1B7AC0;
    --accent-soft: #E3EEF7;

    --gold: #B58A2B;
    --gold-bg: #F6EFDF;

    --sidebar-bg: #0B2F4F;
    --sidebar-bg-2: #0B2F4F;
    --sidebar-text: #EDF3F8;
    --sidebar-muted: #9FB6CA;

    /* Status colours keep the green/yellow/red meaning but in earthy tones - moss, mustard
       and brick - instead of the bright emerald/amber/scarlet every dashboard ships with. */
    --accent-blue: #3F6076;
    --blue-bg: #E7ECEF;

    /* Two shades per status. The first is the one text is set in, so it stays dark enough
       to read on its own tint; the -vivid pair is for dots, bars and icons, where nothing
       sits on top and brightness is the whole point. The old single earthy tone had to do
       both jobs, which is why approved/pending/rejected all looked muddy. */
    --green: #0B7D3E;
    --green-bg: #E4F4EA;
    --green-vivid: #10A85B;
    --yellow: #8F6100;
    --yellow-bg: #FCF0D5;
    --yellow-vivid: #E9A41A;
    --red: #C62828;
    --red-bg: #FBE6E4;
    --red-vivid: #E8382B;

    /* Lifted straight out of the JPPKK rubric PDFs - the green they fill a chosen rating with.
       Using their exact colour means a marker comparing screen to paper sees the same thing. */
    --rubric-green: #92D050;
    --rubric-green-line: #6FA838;
    --rubric-green-ink: #1F3308;

    /* Legacy aliases - point old variable names at the new palette instead of renaming every
       usage across ~40 templates. */
    --accent-purple: var(--accent);
    --accent-purple-2: var(--accent-2);
    --purple-bg: var(--accent-soft);
    --page-bg: var(--paper);
    --border: var(--line);
    --text-main: var(--ink);
    --text-muted: var(--ink-soft);

    /* Plain system UI stack - Segoe UI on Windows, San Francisco on Mac, Roboto on Android.
       The normal font people already read every day, not a downloaded display face. */
    --font-serif: system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
    --font-sans: 'Satoshi', system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
    --font-mono: ui-monospace, 'Segoe UI Mono', 'SFMono-Regular', Consolas, monospace;

    --radius: 3px;
}

* { box-sizing: border-box; }

body {
    margin: 0;
    font-family: var(--font-sans);
    background: var(--page-bg);
    color: var(--text-main);
}

h1, h2, h3,
.page-welcome h1, .panel-head h2, .panel-head h3, .form-section-title,
.auth-split-headline, .auth-split-form-wrap h1, .auth-logo,
.sidebar-logo, .auth-split-logo .logo-text {
    font-family: var(--font-serif);
    font-weight: 600;
}

.stat-number, .donut-center .num, table.data-table th, .badge,
.upload-file-ext, .week-pill, .day-pill {
    font-family: var(--font-mono);
    letter-spacing: 0.02em;
}

a { text-decoration: none; color: inherit; }
ul { list-style: none; margin: 0; padding: 0; }

.icon { width: 18px; height: 18px; }

.app-shell {
    display: flex;
    min-height: 100vh;
}

/* Sidebar */
.sidebar {
    width: 250px;
    flex-shrink: 0;
    /* Pinned to the viewport at a fixed 100vh rather than stretching with page content: a flex
       child would otherwise grow as tall as the (much taller) main column on content-heavy pages
       like the dashboard, which zoomed and re-cropped the bottom-anchored background image so it
       looked different from page to page. Sticky + fixed height keeps the same crop everywhere and
       keeps the menu in view while the content scrolls. */
    position: sticky;
    top: 0;
    align-self: flex-start;
    height: 100vh;
    background:
        linear-gradient(180deg, rgba(11,47,79,0.97) 0%, rgba(11,47,79,0.88) 45%, rgba(8,32,54,0.80) 100%),
        var(--sidebar-bg) url('/assets/img/sidebar-bg.jpg') bottom center / cover no-repeat;
    color: var(--sidebar-text);
    overflow-y: auto;
    /* No width/padding transition - animating either relayouts the page every frame. */
    display: flex;
    flex-direction: column;
    padding: 22px 16px;
}

.sidebar-logo, .sidebar-nav { position: relative; z-index: 1; }
.sidebar-logo {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 0 8px 20px;
    margin-bottom: 12px;
    border-bottom: 1px solid rgba(255,255,255,0.08);
    font-weight: 700;
    font-size: 18.5px;
}

.sidebar-logo .icon { width: 26px; height: 26px; color: #6FB3E0; } /* 6.0:1 on the navy */
.sidebar-logo-img { height: 30px; width: auto; flex: none; }

.sidebar-nav { display: flex; flex-direction: column; gap: 4px; flex: 1; }

.sidebar-nav a {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 10px 14px;
    border-radius: 6px;
    color: var(--sidebar-muted);
    font-size: 16px;
    font-weight: 500;
    transition: background 0.15s, color 0.15s;
}

.sidebar-nav a .icon { width: 18px; height: 18px; flex-shrink: 0; }
.sidebar-nav a:hover { background: rgba(255,255,255,0.06); color: #fff; }

.sidebar-nav a.active {
    background: var(--accent);
    color: #fff;
}

/* Main / Topbar */
.main { flex: 1; display: flex; flex-direction: column; min-width: 0; }

.topbar {
    height: 74px;
    color: var(--ink);
    background: #F7F9FB;
    border-bottom: 1px solid var(--border);
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 32px;
    flex-shrink: 0;
    position: relative; z-index: 5;
}

.topbar-student-search {
    display: flex;
    align-items: center;
    gap: 8px;
    background: var(--page-bg);
    border: 1px solid var(--border);
    border-radius: 999px;
    padding: 7px 14px;
    min-width: 320px;
}
.topbar-student-search .icon { width: 15px; height: 15px; color: var(--text-muted); flex-shrink: 0; }
.topbar-student-search input {
    border: none;
    background: none;
    outline: none;
    font-size: 14.5px;
    width: 100%;
    color: var(--text-main);
}
@media (max-width: 860px) {
    .topbar-student-search { display: none; }
}

.topbar-right { display: flex; align-items: center; gap: 20px; }

.notif-wrap { position: relative; }
.topbar-bell {
    position: relative; color: var(--text-muted); background: none; border: none; cursor: pointer;
    padding: 6px; display: flex; align-items: center; border-radius: 8px;
}
.topbar-bell { color: var(--ink-soft); }
.topbar-bell:hover { background: var(--accent-soft); }
.topbar .topbar-profile-info .name { color: var(--ink); }
.topbar .topbar-profile-info .role { color: var(--ink-soft); }
.topbar .sidebar-toggle-btn { color: var(--ink-soft); }
.topbar .sidebar-toggle-btn:hover { background: var(--accent-soft); }
/* The search box sits on a dark band now, so it needs its own light surface. */
.topbar .topbar-student-search input::placeholder { color: var(--ink-soft); }
.topbar-bell .badge-count {
    position: absolute; top: -2px; right: -2px;
    background: var(--red); color: #fff; font-size: 12px; font-weight: 700;
    border-radius: 999px; padding: 1px 5px; line-height: 1.3;
}

.notif-dropdown {
    display: none;
    position: absolute; top: calc(100% + 8px); right: 0;
    width: 320px; max-width: 90vw;
    background: #fff; border: 1px solid var(--border); border-radius: 12px;
    box-shadow: 0 6px 16px rgba(0,0,0,0.13);
    z-index: 100; padding: 14px;
}
.notif-dropdown.open { display: block; }
.notif-dropdown-head { font-weight: 700; font-size: 16px; margin-bottom: 10px; }
.notif-list { max-height: 320px; overflow-y: auto; margin-bottom: 12px; }
.notif-item { display: block; padding: 10px 4px; border-bottom: 1px solid var(--border); }
.notif-item:last-child { border-bottom: none; }
.notif-item.unread { background: var(--purple-bg); border-radius: 8px; padding: 10px 8px; }
a.notif-item:hover { background: var(--accent-soft); border-radius: 8px; }
.notif-msg { font-size: 15px; }
.notif-time { font-size: 12.5px; color: var(--text-muted); margin-top: 3px; }
.notif-empty { font-size: 14.5px; color: var(--text-muted); padding: 12px 4px; text-align: center; }
.notif-all-btn { display: block; text-align: center; width: 100%; }

.profile-wrap { position: relative; }
.topbar-profile {
    display: flex; align-items: center; gap: 10px; cursor: pointer; text-align: left;
    background: none; border: none; padding: 0; font-family: inherit; color: inherit;
}
.topbar-profile .icon:last-child { width: 15px; height: 15px; color: var(--text-muted); }

.profile-dropdown {
    display: none;
    position: absolute; top: calc(100% + 8px); right: 0;
    width: 190px;
    background: #fff; border: 1px solid var(--border); border-radius: 12px;
    box-shadow: 0 6px 16px rgba(0,0,0,0.13);
    z-index: 100; padding: 6px;
}
.profile-dropdown.open { display: block; }
.profile-dropdown a {
    display: flex; align-items: center; gap: 10px;
    padding: 9px 10px; border-radius: 8px; font-size: 15px; font-weight: 500; color: var(--text-main);
}
.profile-dropdown a:hover { background: var(--accent-soft); color: var(--accent); }
.profile-dropdown a .icon { width: 16px; height: 16px; }

.avatar {
    width: 40px; height: 40px; border-radius: 50%;
    background: var(--accent);
    color: #fff; display: flex; align-items: center; justify-content: center;
    font-weight: 700; font-size: 16px; flex-shrink: 0; overflow: hidden;
}
.avatar img { width: 100%; height: 100%; object-fit: cover; }

.topbar-profile-info { line-height: 1.25; }
.topbar-profile-info .name { font-weight: 600; font-size: 15.5px; }
.topbar-profile-info .role { font-size: 14px; color: var(--text-muted); }

.content { padding: 26px 32px 40px; }

/* Dashboard welcome banner. The artwork already carries its own rounded card and padding, so it
   needs no frame of its own - it fills the content column, and supplies the space below that
   .page-welcome would otherwise have given the heading. The file is 2172px wide, which covers a
   full-width content column on any ordinary desktop without upscaling. */
.welcome-banner {
    display: block;
    width: 100%;
    height: auto;
    margin: 0 0 22px;
}

@media (max-width: 700px) {
    /* At phone width the strapline and the campus photo become unreadable slivers, so the banner
       is dropped rather than shrunk - the page heading below says the same thing in less space. */
    .welcome-banner { display: none; }
}

.page-welcome h1 { margin: 0 0 4px; font-size: 25.5px; }
.page-welcome p { margin: 0 0 22px; color: var(--text-muted); font-size: 16px; }

/* Stat cards */
/* One shared box (not separate floating cards) - each stat is a compact horizontal segment
   (icon beside the number, not stacked above it), and the whole segment is the link - no
   repeated "View details" on every single one when they all go to the same page. */
.stat-cards {
    display: flex;
    flex-wrap: wrap;
    background: var(--card-bg);
    border-radius: var(--radius);
    border: 1px solid var(--border);
    margin-bottom: 16px;
    overflow: hidden;
}

.stat-card {
    flex: 1 1 170px;
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 16px 20px;
    border-left: 1px solid var(--border);
    text-decoration: none;
    color: inherit;
    transition: background 0.12s ease;
}
.stat-card:first-child { border-left: none; }
.stat-card:hover { background: var(--purple-bg); }

/* Flat monochrome icon, not a pastel rounded chip. */
.stat-card .stat-icon {
    width: 20px; height: 20px;
    display: flex; align-items: center; justify-content: center;
    flex-shrink: 0;
    color: var(--text-muted);
}
.stat-card .stat-icon .icon { width: 17px; height: 17px; }

.stat-card.purple .stat-icon,
.stat-card.blue .stat-icon { color: var(--accent-blue); }
.stat-card.green .stat-icon { color: var(--green-vivid); }
.stat-card.yellow .stat-icon { color: var(--yellow-vivid); }
.stat-card.red .stat-icon { color: var(--red-vivid); }

.stat-card .stat-number { font-size: 27.5px; font-weight: 700; line-height: 1.05; letter-spacing: -0.01em; }
.stat-card .stat-label {
    color: var(--text-muted); font-size: 12.5px; margin-top: 4px;
    letter-spacing: 0.09em; text-transform: uppercase; font-weight: 600;
}
.stat-card .stat-link .icon { width: 13px; height: 13px; }

/* Panel grid layout */
.dashboard-grid {
    display: grid;
    grid-template-columns: 1.4fr 1fr 0.85fr;
    gap: 18px;
    align-items: start;
}

.progress-panels-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    /* start, not stretch - otherwise a collapsed panel is still held open to the height of
       whatever sits beside it, which reads as an empty box. */
    align-items: start;
    gap: 18px;
    margin-bottom: 18px;
}

.dashboard-grid-2 { grid-template-columns: 1.6fr 1fr; }

/* Page heading carries the headline figure on the right, instead of that figure needing a
   card of its own with a single number inside it. */
.page-welcome-split {
    display: flex; align-items: flex-end; justify-content: space-between;
    gap: 18px; flex-wrap: wrap;
}
.headline-figure { display: flex; align-items: baseline; gap: 7px; padding-bottom: 20px; }
.headline-figure b { font-family: var(--font-mono); font-size: 31px; font-weight: 600; letter-spacing: -0.01em; }
.headline-figure .of { font-family: var(--font-mono); font-size: 17px; color: var(--text-muted); }
.headline-figure .lbl { font-size: 14.5px; color: var(--text-muted); margin-left: 3px; }

/* Per-document progress table */
.doc-progress { padding-bottom: 0; margin-bottom: 16px; }
.doc-table { margin: 0 -18px; width: calc(100% + 36px); }
.doc-table th, .doc-table td { padding-left: 18px; padding-right: 18px; }
.doc-table td { border-bottom: 1px solid var(--line); vertical-align: middle; }
.doc-table tbody tr:last-child td { border-bottom: none; }
.doc-table .doc-i { width: 26px; color: var(--text-muted); font-family: var(--font-mono); font-size: 14px; }
.doc-table .doc-nm { font-weight: 600; min-width: 200px; }
.doc-table .col-bar { width: 22%; min-width: 110px; }
.doc-table .doc-frac { font-family: var(--font-mono); font-weight: 600; white-space: nowrap; }
.doc-table .doc-frac .of { color: var(--text-muted); font-weight: 400; }

.mini-bar { height: 7px; background: #E3E1D9; border-radius: 2px; overflow: hidden; display: flex; }
.mini-bar i { display: block; height: 100%; }
.mini-bar .b-ok { background: var(--green-vivid); }
.mini-bar .b-wait { background: var(--yellow-vivid); }
.mini-bar .b-bad { background: var(--red-vivid); }

.chips { display: flex; gap: 12px; white-space: nowrap; font-size: 14.5px; }
.chip { display: inline-flex; align-items: center; gap: 5px; color: var(--text-muted); }
.chip i { width: 7px; height: 7px; border-radius: 50%; display: block; flex-shrink: 0; }
.chip.c-ok i { background: var(--green-vivid); }
.chip.c-wait i { background: var(--yellow-vivid); }
.chip.c-bad i { background: var(--red-vivid); }
.chip b { color: var(--ink); font-weight: 600; font-family: var(--font-mono); }
.chip.nil { opacity: 0.45; }
.chip.nil b { color: var(--text-muted); font-weight: 400; }

.doc-table tr.lagging .doc-nm { color: var(--yellow); }
.doc-table tr.lagging td:first-child { box-shadow: inset 3px 0 0 var(--yellow); }

@media (max-width: 1100px) {
    .doc-table .col-bar { display: none; }
    .dashboard-grid-2 { grid-template-columns: 1fr; }
}

@media (max-width: 900px) {
    /* Drop the bleed-to-edge margins so the panel's own horizontal scroll behaves normally. */
    .doc-progress { padding-bottom: 18px; }
    .doc-table { margin: 0; width: 100%; }
    .doc-table th, .doc-table td { padding-left: 10px; padding-right: 10px; }
    .headline-figure { padding-bottom: 8px; }
}

/* Related counts on one line inside a single container, rather than one card per number. */
.count-row { display: flex; flex-wrap: wrap; gap: 10px 34px; }
.count-row > a, .count-row > span {
    display: flex; align-items: baseline; gap: 7px;
    text-decoration: none; color: inherit;
}
.count-row a:hover b { color: var(--accent); }
.count-row b { font-family: var(--font-mono); font-size: 25.5px; font-weight: 600; letter-spacing: -0.01em; }
.count-row > a span, .count-row > span span { font-size: 14.5px; color: var(--text-muted); }

@media (max-width: 520px) {
    .chips { flex-direction: column; gap: 3px; }
    .headline-figure b { font-size: 25.5px; }
    .count-row { gap: 10px 22px; }
    .count-row b { font-size: 22px; }
}

/* Messages page: contact list + chat panel */
.messages-layout { display: flex; gap: 18px; align-items: flex-start; }
.messages-contact-panel { width: 230px; flex-shrink: 0; padding: 12px; }
.messages-chat-panel { flex: 1; min-width: 0; }

/* Flat sheet, no accent stripe and no card shadow - the heading sits above a hairline rule
   rather than the panel being a floating rounded box. */
.panel {
    background: var(--card-bg);
    border-radius: var(--radius);
    border: 1px solid var(--border);
    padding: 16px 18px 18px;
}

.panel-head {
    display: flex; align-items: baseline; justify-content: space-between;
    gap: 12px; flex-wrap: wrap;
    margin: -16px -18px 16px;
    padding: 13px 18px 12px;
    border-bottom: 1px solid var(--border);
}
.panel-head h2, .panel-head h3 {
    margin: 0;
    font-family: var(--font-sans);
    font-size: 12.5px; font-weight: 700;
    letter-spacing: 0.1em; text-transform: uppercase;
    color: var(--text-muted);
}
.panel-head .view-all { font-size: 14.5px; color: var(--accent); font-weight: 600; }

/* Stepper */
.stepper { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 26px; position: relative; }
.stepper::before {
    content: ''; position: absolute; top: 19px; left: 30px; right: 30px; height: 2px; background: var(--border); z-index: 0;
}
.step { display: flex; flex-direction: column; align-items: center; gap: 8px; position: relative; z-index: 1; width: 90px; text-align: center; }
.step-circle {
    width: 40px; height: 40px; border-radius: 50%; background: #fff; border: 2px solid var(--border);
    display: flex; align-items: center; justify-content: center; color: var(--text-muted);
}
.step-circle .icon { width: 17px; height: 17px; }
.step.done .step-circle { background: var(--accent); border-color: var(--accent); color: #fff; }
.step.current .step-circle { border-color: var(--accent-purple); color: var(--accent-purple); background: #fff; }
/* Distinct from "done" (green check) - everything is in, but nothing's approved yet. Using the
   done/green checkmark here would wrongly tell the student the step is fully finished. */
.step.submitted .step-circle { background: var(--yellow-bg); border-color: var(--yellow); color: var(--yellow); }
a.step { cursor: pointer; }
a.step:hover .step-circle { box-shadow: 0 0 0 4px var(--purple-bg); }
a.step:hover .step-label { color: var(--accent-purple); }
.step-label { font-size: 14.5px; font-weight: 600; }
.step-meta { font-size: 12.5px; color: var(--text-muted); }

.progress-track {
    height: 9px; background: var(--border); border-radius: 999px; overflow: hidden; flex: 1;
}
.progress-fill { height: 100%; background: var(--accent); border-radius: 999px; }
.progress-row { display: flex; align-items: center; gap: 12px; }
.progress-row .progress-pct { font-weight: 700; color: var(--accent-purple); font-size: 15.5px; width: 40px; text-align: right; }
.progress-title { font-size: 15.5px; font-weight: 600; margin-bottom: 10px; color: var(--text-muted); }

/* Announcements */
.announcement-item { padding: 12px 0; border-bottom: 1px solid var(--border); scroll-margin-top: 20px; }
.announcement-item:target { background: var(--accent-soft); border-radius: 8px; padding: 12px 10px; margin: 0 -10px; }
.announcement-item:last-child { border-bottom: none; padding-bottom: 0; }
/* Scheduled / ended / expired items on the coordinator board read as not-currently-live. */
.announcement-item.is-dim { opacity: 0.62; }
.announcement-item .a-top { display: flex; justify-content: space-between; gap: 10px; }
.announcement-item .a-title { font-weight: 700; font-size: 15.5px; }
.announcement-item .a-date { font-size: 14px; color: var(--text-muted); white-space: nowrap; }
.announcement-item .a-body { font-size: 14.5px; color: var(--text-muted); margin-top: 3px; }

/* Quick access */
.quick-access a {
    display: flex; align-items: center; justify-content: space-between;
    padding: 12px 14px; border-radius: 10px; border: 1px solid var(--border);
    margin-bottom: 10px; font-size: 15.5px; font-weight: 600;
}
.quick-access a:last-child { margin-bottom: 0; }
.quick-access a:hover { background: var(--purple-bg); }
.quick-access a .qa-left { display: flex; align-items: center; gap: 10px; }
.quick-access a .qa-left .icon { color: var(--accent-purple); width: 17px; height: 17px; }
.quick-access a .chevron { color: var(--text-muted); width: 15px; height: 15px; }

/* Table */
table.data-table { width: 100%; border-collapse: collapse; font-size: 15.5px; }
table.data-table th {
    text-align: left; font-size: 14px; color: var(--text-muted); text-transform: uppercase;
    letter-spacing: 0.3px; padding: 10px 8px; border-bottom: 1px solid var(--border);
}
table.data-table td { padding: 12px 8px; border-bottom: 1px solid var(--border); }
table.data-table tr:last-child td { border-bottom: none; }
table.data-table tr[id] { scroll-margin-top: 90px; }
table.data-table tr:target td { background: var(--accent-soft); }
table.data-table tr:target td:first-child { box-shadow: inset 3px 0 0 var(--accent); }

/* Badges */
.badge { display: inline-block; padding: 4px 11px; border-radius: 999px; font-size: 14px; font-weight: 700; }
.badge-green { background: var(--green-bg); color: var(--green); }
.badge-yellow { background: var(--yellow-bg); color: var(--yellow); }
.badge-red { background: var(--red-bg); color: var(--red); }
.badge-gray { background: #eee; color: #777; }

/* Buttons */
.btn {
    display: inline-flex; align-items: center; gap: 6px; justify-content: center;
    padding: 8px 16px; border-radius: 8px; font-size: 15px; font-weight: 600;
    border: none; cursor: pointer; transition: opacity 0.15s;
}
.btn:hover { opacity: 0.88; }
.btn-primary { background: var(--accent-purple); color: #fff; }
.btn-blue { background: var(--accent-blue); color: #fff; }
.btn-green { background: var(--green); color: #fff; }
.btn-red { background: var(--red); color: #fff; }
.btn-outline { background: #fff; border: 1px solid var(--border); color: var(--text-main); }
.btn-sm { padding: 6px 12px; font-size: 14.5px; }

/* Donut chart */
.donut-wrap { display: flex; align-items: center; gap: 24px; justify-content: center; }
.donut {
    width: 150px; height: 150px; border-radius: 50%; position: relative;
    display: flex; align-items: center; justify-content: center;
}
.donut-hole {
    width: 68%; height: 68%; border-radius: 50%; background: #fff;
    display: flex; align-items: center; justify-content: center;
}
.donut-center { text-align: center; }
.donut-center .num { font-size: 30px; font-weight: 800; }
.donut-center .lbl { font-size: 12.5px; color: var(--text-muted); }
.donut-legend { display: flex; flex-direction: column; gap: 12px; }
.donut-legend .legend-item { display: flex; align-items: center; gap: 8px; font-size: 15px; }
.donut-legend .dot { width: 10px; height: 10px; border-radius: 50%; }
.donut-legend .legend-label { font-weight: 700; }
.donut-legend .legend-sub { color: var(--text-muted); font-size: 14px; }

/* Forms */
.form-card {
    background: var(--card-bg); border-radius: var(--radius); border: 1px solid var(--border);
    padding: 24px; max-width: 520px;
}
.form-grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 0 16px; }
.form-section-title { font-weight: 700; font-size: 16px; margin: 22px 0 14px; padding-top: 18px; border-top: 1px solid var(--border); }
.form-section-title:first-child { margin-top: 0; padding-top: 0; border-top: none; }
.form-group { margin-bottom: 16px; }
.form-group label { display: block; font-size: 15px; font-weight: 600; margin-bottom: 6px; }
.form-group input, .form-group select, .form-group textarea {
    width: 100%; padding: 10px 12px; border-radius: 8px; border: 1px solid var(--border);
    font-size: 15.5px; font-family: inherit; background: #fbfbfd;
}
.form-group input:focus, .form-group select:focus, .form-group textarea:focus {
    outline: none; border-color: var(--accent-purple);
}
.form-group input:disabled, .form-group select:disabled, .form-group textarea:disabled {
    background: var(--border); color: var(--text-muted); cursor: not-allowed; opacity: 0.75;
}
.required-star { color: var(--red); font-weight: 700; }
.form-group.field-missing label { color: var(--red); }
.form-group.field-missing input, .form-group.field-missing select, .form-group.field-missing textarea {
    border-color: var(--red);
    background: var(--red-bg);
}

/* Login page (simple centered card - used by signup) */
.auth-page {
    min-height: 100vh; display: flex; align-items: center; justify-content: center;
    background: var(--sidebar-bg);
    padding: 24px;
}
/* Campus photo behind the sign-up card. The dark scrim keeps the card readable and stops the
   sky competing with the form - the photo sets the place, the form stays the focus. */
.auth-page-campus {
    position: relative;
    background:
        linear-gradient(rgba(18, 26, 22, 0.72), rgba(18, 26, 22, 0.82)),
        url('/assets/img/campus.jpg') center / cover no-repeat fixed;
}

.auth-card {
    background: var(--card-bg); border-radius: 14px; padding: 38px 36px; width: 380px;
    max-width: 100%;
    border: 1px solid rgba(0,0,0,0.08);
    box-shadow: 0 18px 44px rgba(0,0,0,0.32);
}

/* Split-screen auth layout (login page) */
.auth-split {
    min-height: 100vh; display: flex;
}
.auth-split-left {
    flex: 1 1 46%;
    background:
        linear-gradient(165deg, rgba(11,47,79,0.93) 0%, rgba(11,47,79,0.86) 55%, rgba(8,32,54,0.78) 100%),
        var(--sidebar-bg) url('/assets/img/hero.jpg') left center / cover no-repeat;
    color: #fff;
    padding: 56px 56px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    position: relative;
    overflow: hidden;
}
.auth-split-left > * { position: relative; z-index: 1; }
.auth-split-logo { display: flex; align-items: center; gap: 12px; margin-bottom: 40px; }
.auth-split-logo .logo-badge-img { width: 44px; height: 44px; flex-shrink: 0; object-fit: contain; }
.auth-split-logo .logo-text { font-weight: 800; font-size: 19.5px; line-height: 1.3; }
.auth-split-logo .logo-text small { display: block; font-weight: 500; font-size: 14px; color: #6FB3E0; }
.auth-split-headline { font-size: 39px; font-weight: 800; line-height: 1.25; margin: 0 0 18px; color: #fff; }
.auth-split-desc { color: #c7c7de; font-size: 16.5px; line-height: 1.6; margin: 0 0 28px; max-width: 440px; }
.auth-split-features { display: flex; flex-direction: column; gap: 14px; margin-bottom: 30px; }
.auth-split-features .feat { display: flex; align-items: center; gap: 10px; font-size: 15.5px; color: #e4e4f0; }
.auth-split-features .feat .check {
    width: 20px; height: 20px; border-radius: 50%; background: rgba(31,122,108,0.3); color: #6FB3E0;
    display: flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.auth-split-features .feat .check .icon { width: 12px; height: 12px; }
.auth-split-footnote { color: #8484a0; font-size: 14px; line-height: 1.6; }

.auth-split-right {
    flex: 1 1 54%;
    display: flex; align-items: center; justify-content: center;
    background: var(--page-bg);
    padding: 40px 24px;
}
.auth-split-form-wrap { width: 100%; max-width: 420px; }
.auth-split-form-wrap h1 { font-size: 32px; margin: 0 0 6px; }
.auth-split-form-wrap .auth-split-sub { color: var(--text-muted); font-size: 16px; margin: 0 0 28px; }
.auth-split-form-wrap .form-group label { text-transform: uppercase; font-size: 13px; letter-spacing: 0.4px; color: var(--text-muted); }
/* Reusable input-with-icon(s) wrapper - not scoped to one page, used by any form-group. */
.input-icon-wrap { position: relative; }
.input-icon-wrap > .icon {
    position: absolute; left: 12px; top: 50%; transform: translateY(-50%);
    width: 16px; height: 16px; color: var(--text-muted); pointer-events: none;
}
.input-icon-wrap input { padding-left: 38px; }
.input-icon-wrap .toggle-pw {
    position: absolute; right: 10px; top: 50%; transform: translateY(-50%);
    background: none; border: none; cursor: pointer; color: var(--text-muted); padding: 4px;
}

.auth-split-divider { display: flex; align-items: center; gap: 12px; margin: 22px 0; color: var(--text-muted); font-size: 14px; }
.auth-split-divider::before, .auth-split-divider::after { content: ''; flex: 1; height: 1px; background: var(--border); }

.demo-role-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin-bottom: 20px; }
.demo-role-tile {
    background: #fff; border: 1px solid var(--border); border-radius: 12px;
    padding: 14px 8px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px;
    font-size: 14.5px; font-weight: 600; color: var(--text-main); cursor: pointer; text-decoration: none;
    text-align: center; transition: border-color 0.15s, background 0.15s;
}
.demo-role-tile:hover { border-color: var(--accent); background: var(--accent-soft); }
.demo-role-tile .emoji { font-size: 23px; }
.demo-role-tile .demo-tile-main { line-height: 1.1; }
.demo-role-tile .demo-tile-sub { font-size: 11.5px; font-weight: 400; color: var(--text-muted); text-align: center; line-height: 1.2; }

@media (max-width: 900px) {
    .auth-split { flex-direction: column; }
    .auth-split-left { padding: 36px 28px; flex: none; }
    .auth-split-headline { font-size: 30px; }
    .auth-split-features { margin-bottom: 10px; }
    .auth-split-right { padding: 32px 20px; }
}
.auth-logo { display: flex; align-items: center; gap: 10px; justify-content: center; margin-bottom: 6px; font-weight: 800; font-size: 20.5px; }
.auth-logo .icon { width: 28px; height: 28px; color: var(--accent-purple); }
.auth-logo img { width: 32px; height: 32px; object-fit: contain; display: block; }
.auth-sub { text-align: center; color: var(--text-muted); font-size: 15px; margin-bottom: 24px; }
.auth-error { background: var(--red-bg); color: var(--red); padding: 10px 14px; border-radius: 8px; font-size: 15px; margin-bottom: 16px; }
.auth-hint { background: var(--purple-bg); color: var(--accent-purple); padding: 10px 14px; border-radius: 8px; font-size: 14px; margin-bottom: 16px; line-height: 1.5; }
.auth-submit { width: 100%; padding: 11px; margin-top: 6px; }
.remember-me {
    display: flex; align-items: center; gap: 8px;
    font-size: 15px; color: var(--text-muted); cursor: pointer;
    margin: -4px 0 14px;
}
.remember-me input { width: 15px; height: 15px; accent-color: var(--accent); cursor: pointer; flex-shrink: 0; }

/* Announcement footer row: who posted it, and the delete action. */
.a-foot {
    display: flex; align-items: center; justify-content: space-between;
    gap: 12px; margin-top: 6px; font-size: 14px;
}
.a-foot form { margin: 0; }
.btn-delete {
    appearance: none; background: none; border: 1px solid var(--border);
    border-radius: var(--radius); padding: 3px 10px; cursor: pointer;
    font-family: var(--font-sans); font-size: 14px; font-weight: 600; color: var(--text-muted);
}
.btn-delete:hover { border-color: var(--red); color: var(--red); background: var(--red-bg); }

.rubric-list { list-style: none; margin: 0; padding: 0; }
.rubric-list li { border-bottom: 1px solid var(--border); }
.rubric-list li:last-child { border-bottom: 0; }
.rubric-list a {
    display: flex; align-items: center; justify-content: space-between; gap: 14px;
    padding: 12px 2px; font-size: 15.5px; font-weight: 500;
}
.rubric-list a:hover { background: var(--card-head, var(--purple-bg)); padding-left: 8px; }
.rubric-list .icon { width: 15px; height: 15px; color: var(--text-muted); flex-shrink: 0; }
.rubric-list a:hover .icon { color: var(--accent); }

/* Rubric marking form */
.rubric-section { margin-bottom: 16px; padding-bottom: 0; }
.rubric-progress { font-size: 14px; color: var(--text-muted); font-family: var(--font-mono); }
.rubric-progress b { color: var(--ink); }
/* One criterion, with every rating level spelled out the way the paper form does - the
   assessor picks the wording that matches, instead of guessing what a "4" means. */
.rb-item { padding: 16px 0; border-top: 1px solid var(--border); }
.rb-item:first-of-type { border-top: 0; padding-top: 6px; }
.rb-head { font-size: 15.5px; font-weight: 600; margin-bottom: 10px; }
.rb-head .rb-no {
    display: inline-block; min-width: 20px; margin-right: 4px;
    font-family: var(--font-mono); font-size: 14px; color: var(--text-muted); font-weight: 400;
}

.rb-levels { display: grid; grid-template-columns: repeat(5, 1fr); gap: 6px; }
.rb-level {
    display: block; cursor: pointer; position: relative;
    border: 1px solid var(--border); border-radius: var(--radius);
    padding: 8px 9px; background: var(--card-bg);
}
.rb-level:hover { border-color: var(--accent); }
.rb-level:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
.rb-level input { position: absolute; opacity: 0; pointer-events: none; }
.rb-level .rb-lv {
    display: block; font-size: 12.5px; font-weight: 700;
    letter-spacing: 0.04em; text-transform: uppercase; color: var(--text-muted);
    margin-bottom: 5px;
}
.rb-level .rb-desc { display: block; font-size: 13px; line-height: 1.45; color: var(--ink); }
.rb-level.on,
.rb-level:has(input:checked) {
    background: var(--rubric-green);
    border-color: var(--rubric-green-line);
    box-shadow: inset 0 0 0 1px var(--rubric-green-line);
}
.rb-level.on .rb-lv,
.rb-level:has(input:checked) .rb-lv { color: var(--rubric-green-ink); }
.rb-level.on .rb-desc,
.rb-level:has(input:checked) .rb-desc { color: var(--rubric-green-ink); }

/* The English block rates a plain 1-5 with no descriptor paragraph, so its cells sit centred. */
.rb-level-plain { text-align: center; padding: 10px 9px; }
.rb-level-plain .rb-lv { font-size: 17px; margin-bottom: 3px; }

/* Quick feedback, comments and sign-off - recorded but never counted toward the mark. */
.rb-tail .rubric-progress { font-style: italic; }
.rb-signoff {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: 14px; margin-bottom: 14px;
}
.rb-confirm {
    display: flex; align-items: center; gap: 9px;
    font-size: 15px; cursor: pointer;
}
.rb-confirm input { width: 15px; height: 15px; accent-color: var(--accent); flex-shrink: 0; }

/* Roster bar above the student list / marking form. */
.rb-bar {
    display: flex; align-items: center; justify-content: space-between;
    gap: 16px; flex-wrap: wrap; margin-bottom: 16px;
}
.rb-bar-end { justify-content: flex-end; }
.rb-dl { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; font-size: 14.5px; }
.rb-dl-label { color: var(--text-muted); }
.rb-dl a { display: inline-flex; align-items: center; gap: 5px; color: var(--accent); font-weight: 600; }
.rb-dl a:hover { text-decoration: underline; }
.rb-dl .icon { width: 13px; height: 13px; }

/* Written feedback on the student's own evaluation page. */
.fb-block { padding: 14px 0; border-top: 1px solid var(--border); }
.fb-block:first-of-type { border-top: 0; padding-top: 4px; }
.fb-who { font-size: 12.5px; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase; color: var(--text-muted); margin-bottom: 7px; }
.fb-eng { font-size: 14.5px; color: var(--ink-soft); margin-bottom: 7px; }
.fb-eng span { color: var(--text-muted); margin-right: 4px; }
.fb-eng b { font-weight: 600; color: var(--ink); margin-left: 8px; }
.fb-comment { font-size: 15.5px; line-height: 1.6; margin: 0 0 7px; max-width: 62ch; }
/* Admin > Companies: a short preview of who a company hosts, instead of dumping every name. */
.co-names { list-style: none; margin: 6px 0 0; padding: 0; font-size: 14px; line-height: 1.6; }
.co-names li { color: var(--ink-soft); }
.co-names .mono { font-family: var(--font-mono); font-size: 12.5px; color: var(--text-muted); }
.co-names .more { color: var(--text-muted); font-style: italic; }

/* Admin > Companies > Manage interns: the placement picker. */
.pick-tools { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-bottom: 4px; }
.pick-tools input[type="search"] {
    flex: 1 1 240px; min-width: 200px; padding: 8px 11px; font: inherit; font-size: 15px;
    border: 1px solid var(--border); border-radius: var(--radius); background: #fff; color: var(--ink);
}
.pick-tools input[type="search"]:focus { outline: none; border-color: var(--accent); }
.pick-table { margin-top: 10px; }
.pick-table td { vertical-align: middle; }
.pick-table input[type="checkbox"] { width: 15px; height: 15px; accent-color: var(--accent); }
.pick-table tbody tr:hover td { background: var(--accent-soft); }
.pick-save {
    display: flex; align-items: center; justify-content: space-between;
    gap: 16px; flex-wrap: wrap; margin-top: 16px;
}

/* Welcome band. Carries a generated artwork when one is dropped in at
   /assets/img/hero.jpg, and reads correctly on the plain gradient until then. */
.hero {
    position: relative; overflow: hidden;
    background: var(--sidebar-bg) url('/assets/img/hero.jpg') center/cover no-repeat;
    border-radius: var(--radius);
    padding: 26px 26px 24px;
    margin-bottom: 18px;
    color: #fff;
}
/* Keeps the text legible whatever the artwork behind it turns out to be. */
.hero::before {
    content: ''; position: absolute; inset: 0;
    background: linear-gradient(100deg, rgba(11,47,79,0.94) 0%, rgba(11,47,79,0.78) 48%, rgba(11,47,79,0.32) 100%);
}
.hero-copy { position: relative; }
.hero-hi { margin: 0 0 2px; font-size: 15px; color: #B9CEDF; }
.hero h1 { margin: 0 0 5px; font-size: 28.5px; font-weight: 700; letter-spacing: -0.02em; color: #fff; }
.hero-sub { margin: 0; font-size: 15.5px; color: #CBDCE9; }
.hero-dot { margin: 0 7px; opacity: 0.55; }
.hero-matric { font-family: var(--font-mono); }

/* Module grid, in the shape polytechnic students already know from SPMP - but each tile
   carries its own status, so the grid says where you are up to instead of only where to go. */
/* Only the screen reader needs the page title now the welcome band is gone. */
.sr-only {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* Module tiles: an artwork band on top, name and status beneath. Shaped after the SPMP module
   grid students already use. Each tile carries its own blue so the eight read as distinct
   modules rather than eight copies of the same card. */
.tiles { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; }

.tile-art {
    position: relative; display: flex; flex-direction: column;
    align-items: center; justify-content: center; gap: 7px;
    min-height: 92px; padding: 14px 10px 12px;
    background: var(--tile-shade, var(--accent));
    color: #fff; text-align: center;
}
/* Artwork sits behind the name rather than beside it, so the label reads either way. */
.tile-art img {
    position: absolute; inset: 0; width: 100%; height: 100%;
    object-fit: fill; display: block;
}
/* Only needed once real artwork is behind the text - keeps the name legible over any image. */
/* The artwork has the module name drawn into it, so the HTML label would duplicate it.
   Hidden only when a real image is behind - the icon fallback still needs its label. */
.tile-art:has(img) .tile-name { display: none; }
.tile-art:has(img) { min-height: 0; padding: 0; aspect-ratio: 256 / 140; }
.tile-art:has(img)::after { content: none; }

.tile-art:not(:has(img))::after {
    content: ''; position: absolute; inset: 0;
    background: linear-gradient(to top, rgba(11,47,79,0.82) 0%, rgba(11,47,79,0.28) 60%, rgba(11,47,79,0.12) 100%);
}
.tile-art .icon { width: 26px; height: 26px; position: relative; z-index: 1; }
.tile-name {
    position: relative; z-index: 1;
    display: block; font-size: 15px; font-weight: 700; line-height: 1.25;
    color: #fff; text-shadow: 0 1px 2px rgba(0,0,0,0.28);
}
.tile-body { padding: 9px 12px 10px; text-align: center; }
.tile-label { display: block; font-size: 15px; font-weight: 600; line-height: 1.3; }


/* One shade per module. All inside the same blue family, all readable with white on top. */
.tile-profile      { --tile-shade: #1E3A5F; }
.tile-documents      { --tile-shade: #1E8FD5; }
.tile-placement      { --tile-shade: #128B8B; }
.tile-logbook      { --tile-shade: #22A45D; }
.tile-schedule      { --tile-shade: #2F6B3A; }
.tile-evaluation      { --tile-shade: #D2662A; }
.tile-announcement      { --tile-shade: #C62335; }
.tile-help      { --tile-shade: #A81F63; }
.tile-students      { --tile-shade: #6B3FA0; }
.tile-verify      { --tile-shade: #4B3BA8; }
.tile-report      { --tile-shade: #D9A322; }
.tile-activity      { --tile-shade: #5A7A96; }
.tile-users      { --tile-shade: #7A2233; }
.tile-period      { --tile-shade: #1F5E63; }

/* A finished module keeps its own colour but gains a tick-green edge, so "done" is legible
   without eight tiles collapsing to one colour. */
/* Only the student dashboard uses this, where four of eight lighting up reads as progress.
   On the staff dashboards the tiles are navigation, so a single green one among seven read
   as a rendering fault rather than a signal. */
.tile.is-done { border-color: var(--green); }
.tile.is-done .tile-label { color: var(--green); }
.quick-tiles { margin-bottom: 18px; }
.tile {
    display: flex; flex-direction: column; align-items: stretch;
    background: var(--card-bg); border: 1px solid var(--border);
    border-radius: var(--radius); padding: 0; overflow: hidden;
    text-decoration: none; color: var(--ink);
}
.tile:hover { border-color: var(--accent); }


.tile-name { font-size: 15.5px; font-weight: 600; line-height: 1.3; }
.tile-meta { font-size: 14px; color: var(--text-muted); margin-top: 3px; }


@media (max-width: 1000px) { .tiles { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 700px)  { .tiles { grid-template-columns: repeat(2, 1fr); } }

/* "What is left to do" - one row per thing actually standing between the student and starting.
   A row sent back by the coordinator is marked, because that one needs redoing not doing. */
.todo-list { list-style: none; margin: 0; padding: 0; }
.todo-list li { border-bottom: 1px solid var(--border); }
.todo-list li:last-child { border-bottom: none; }
.todo-list a { display: block; padding: 9px 0; text-decoration: none; color: var(--ink); }
.todo-list a:hover b { color: var(--accent); }
.todo-list b { display: block; font-size: 15px; font-weight: 600; }
.todo-list span { display: block; font-size: 14px; color: var(--text-muted); margin-top: 1px; }
.todo-list li.is-back b, .todo-list li.is-back:hover b { color: var(--red); }

/* The finished state: the mark first, then the few facts a student wants alongside it. */
.result-card { display: flex; flex-direction: column; gap: 14px; }
.result-mark { display: flex; align-items: baseline; gap: 12px; }
.result-mark b {
    font-family: var(--font-mono); font-size: 37px; font-weight: 600;
    letter-spacing: -0.02em; line-height: 1;
}
.result-mark .grade {
    font-size: 15px; font-weight: 700; padding: 3px 11px; border-radius: 999px;
    background: var(--accent-soft); color: var(--accent);
}
.result-meta { display: grid; grid-template-columns: auto 1fr; gap: 5px 14px; margin: 0; font-size: 14.5px; }
.result-meta dt { color: var(--text-muted); }
.result-meta dd { margin: 0; }

/* A panel that folds away, using the same disclosure as an approved document slot. */
.panel-fold { padding-top: 0; }
.panel-summary {
    list-style: none; cursor: pointer;
    margin: 0 -18px 16px; padding: 13px 18px 12px;
}
.panel-summary::-webkit-details-marker { display: none; }
/* Nothing to fold until the work is done, so the header stays inert until then. */
.panel-fold:not([data-foldable]) > .panel-summary { cursor: default; pointer-events: none; }
.panel-chevron { width: 15px; height: 15px; color: var(--text-muted); transition: transform 0.15s ease; }
.panel-fold[open] .panel-chevron { transform: rotate(180deg); }
/* Closed: the summary is the whole card, so it should not keep a divider or a gap below. */
.panel-fold:not([open]) > .panel-summary { margin-bottom: -16px; border-bottom: none; }

/* Student dashboard: one week at a time, drawn with the same day cells as the logbook and
   stepped with the same arrows. The week label sits inside the container with its days. */
.wk-strip {
    display: flex; align-items: center; gap: 6px;
    /* No box around the week - the day cells are the objects here, and an outer edge just
       competes with the panel border already around all of it. */
}
.wk-strip .wk-arrow { border: none; background: none; font-size: 23px; line-height: 1; width: 26px; }
.wk-strip .wk-arrow:hover { background: var(--accent-soft); border-radius: var(--radius); }
.wk-strip-body { flex: 1; min-width: 0; }
/* The dashboard strip is narrower than the logbook page, so the five days have to share the
   width rather than wrap and leave the last one stranded on a row of its own. */
.wk-strip .day-row { flex-wrap: nowrap; gap: 7px; }
.wk-strip .day-cell { min-width: 0; padding: 14px 4px 12px; }
.wk-strip .day-cell b { font-size: 18.5px; margin-bottom: 3px; }
.wk-strip .day-cell span { font-size: 14.5px; }
.wk-strip .day-cell .day-dot { width: 6px; height: 6px; margin-top: 6px; }
.wk-strip-label {
    font-size: 14.5px; font-weight: 600; color: var(--text-muted);
    margin-bottom: 9px; display: flex; align-items: baseline; gap: 7px;
}
/* Today reads as a filled cell, not just an outline - it is the one a student acts on. */
.day-cell.is-today { border-color: var(--accent); background: var(--accent-soft); }
/* Weekend and not-yet-reached days in the dashboard week strip are shown at full strength -
   dimming them read as "disabled" and looked unfinished. Today (border+fill), logged days (dot)
   and missed days (red) already stand out on their own, so no fading is needed here. */
.day-cell.is-today b { color: var(--accent); }
/* Brief fade while a week is being fetched and swapped in (logbook). */
#logbookWeek.is-loading { opacity: 0.55; pointer-events: none; }

.this-week-meta {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    flex-wrap: wrap; margin-top: 12px; font-size: 14.5px; color: var(--text-muted);
}

/* Coordinator > Training Period */
.period-fields { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.holiday-fields { display: grid; grid-template-columns: 150px 1fr 180px; gap: 14px; }
@media (max-width: 640px) { .holiday-fields { grid-template-columns: 1fr; } }
.period-current { font-size: 15px; margin: 14px 0 0; }
.period-who { list-style: none; margin: 0; padding: 0; }
.period-who li {
    display: flex; gap: 11px; align-items: baseline;
    padding: 9px 0; border-bottom: 1px solid var(--border); font-size: 15.5px;
}
.period-who li:last-child { border-bottom: none; }
.period-who b { font-family: var(--font-mono); font-size: 19.5px; min-width: 44px; }
.period-who span { color: var(--text-muted); }

@media (max-width: 560px) {
    .this-week { grid-template-columns: repeat(3, 1fr); }
    .period-fields { grid-template-columns: 1fr; }
}
td.mono { font-family: var(--font-mono); font-size: 14.5px; }
.rb-frac { font-family: var(--font-mono); font-weight: 600; margin-right: 8px; }
.rb-frac .of { color: var(--text-muted); font-weight: 400; }
.rb-frac.done { color: var(--green); }

@media (max-width: 1000px) {
    .rb-levels { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
    .rb-levels { grid-template-columns: 1fr; }
}

.final-mark { display: flex; align-items: baseline; gap: 14px; }
.final-mark b { font-family: var(--font-mono); font-size: 43.5px; font-weight: 600; letter-spacing: -0.02em; }
.final-mark .grade {
    font-size: 17px; font-weight: 700; padding: 3px 12px; border-radius: 20px;
    background: var(--green-bg); color: var(--green);
}



/* Missed working days - red so it's impossible to scroll past. */
.miss-alert {
    display: flex; align-items: baseline; gap: 8px 16px; flex-wrap: wrap;
    max-width: 760px; margin-bottom: 18px;
    padding: 11px 14px; border-radius: var(--radius);
    background: var(--red-bg); border: 1px solid var(--red);
    font-size: 15px; color: var(--red);
}
.miss-alert b { font-weight: 700; }
.miss-alert a {
    display: inline-block; margin-right: 6px;
    font-weight: 600; text-decoration: underline; color: var(--red);
}
.miss-alert .more { opacity: 0.75; }

.day-cell.is-missed { border-color: var(--red); background: var(--red-bg); }
.day-cell.is-missed b { color: var(--red); }
.day-cell .day-dot.missed { background: var(--red-vivid); }
.day-cell.is-missed.is-selected { background: var(--red); border-color: var(--red); }
.day-cell.is-missed.is-selected b, .day-cell.is-missed.is-selected { color: #fff; }
.day-cell.is-missed.is-selected .day-dot.missed { background: #fff; }

/* Proper back/forward buttons instead of a bare text link. */
.btn-back, .btn-forward {
    display: inline-flex; align-items: center; gap: 6px;
    margin-bottom: 16px;
}
.btn-back:hover, .btn-forward:hover { border-color: var(--accent); color: var(--accent); }

/* Utility */
.empty-state { text-align: center; padding: 40px 20px; color: var(--text-muted); font-size: 15.5px; }
.dashboard-grid .empty-state { padding: 20px 16px; }
/* Three announcements at a glance; the full text lives on the Announcement page. */
.dashboard-grid .announcement-item { padding: 8px 0; }
.dashboard-grid .announcement-item .a-title { font-size: 15px; }
.dashboard-grid .announcement-item .a-body {
    display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical;
    overflow: hidden; max-width: 80ch; font-size: 14px; margin-top: 1px;
}
.flex-between { display: flex; align-items: center; justify-content: space-between; }
.mb-0 { margin-bottom: 0 !important; }
.text-muted { color: var(--text-muted); }
.mt-16 { margin-top: 16px; }

/* Document upload redesign */
.upload-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 18px;
    max-width: 1100px;
}
.upload-slot {
    background: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 16px 18px;
    display: flex;
    flex-direction: column;
}
.upload-slot-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 12px;
}
.upload-slot-title {
    display: flex;
    align-items: center;
    gap: 8px;
    font-weight: 700;
    font-size: 16px;
}
.upload-slot-title .icon { width: 16px; height: 16px; color: var(--accent-purple); }

.upload-file-list { margin: 0 0 12px; padding-left: 0; list-style: none; }
.upload-file-item {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 0;
    border-bottom: 1px solid var(--border);
    font-size: 14.5px;
}
.upload-file-item:last-child { border-bottom: none; }
.upload-file-ext {
    flex-shrink: 0;
    background: var(--purple-bg);
    color: var(--accent-purple);
    font-size: 12.5px;
    font-weight: 700;
    padding: 3px 6px;
    border-radius: 5px;
}
.upload-file-name {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--text-main);
}
.upload-file-name:hover { color: var(--accent-purple); }
.upload-file-size { flex-shrink: 0; color: var(--text-muted); font-size: 12.5px; }
.upload-file-remove-form { flex-shrink: 0; }
.upload-file-remove {
    background: none; border: none; cursor: pointer;
    color: var(--text-muted); font-size: 20.5px; line-height: 1; padding: 0 2px;
}
.upload-file-remove:hover { color: var(--red); }
.upload-file-drive {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    gap: 3px;
    font-size: 12.5px;
    color: var(--green);
    text-decoration: none;
}
.upload-file-drive:hover { text-decoration: underline; }
.upload-file-drive .icon { width: 12px; height: 12px; }

.reject-reason-note {
    background: var(--red-bg);
    color: var(--red);
    border-radius: 6px;
    padding: 8px 10px;
    font-size: 14px;
    margin-top: 6px;
    line-height: 1.4;
}

.upload-validation-error {
    background: var(--red-bg);
    color: var(--red);
    border-radius: 6px;
    padding: 8px 10px;
    font-size: 13px;
    margin-top: 6px;
    line-height: 1.4;
}

.upload-file-input { display: none; }
.upload-dropzone {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    text-align: center;
    border: 2px dashed var(--border);
    border-radius: 10px;
    padding: 20px 10px;
    cursor: pointer;
    color: var(--text-muted);
    font-size: 14px;
    transition: border-color 0.15s, background 0.15s, color 0.15s;
}
.upload-dropzone .icon { width: 22px; height: 22px; }
.upload-dropzone:hover, .upload-dropzone.dragover {
    border-color: var(--accent-purple);
    background: var(--purple-bg);
    color: var(--accent-purple);
}
.upload-dropzone.has-staged {
    border-style: solid;
    border-color: var(--green);
    background: var(--green-bg);
    color: var(--green);
}
.upload-staged-list {
    font-size: 13px;
    color: var(--text-muted);
    margin-top: 8px;
    word-break: break-word;
}
.upload-staged-item {
    display: flex; align-items: center; justify-content: space-between; gap: 8px;
    background: var(--green-bg); border-radius: 6px; padding: 5px 8px; margin-bottom: 5px;
}
.upload-staged-item .upload-staged-name {
    flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-main);
}
.upload-staged-item .upload-staged-remove {
    background: none; border: none; cursor: pointer; color: var(--text-muted); font-size: 18.5px; line-height: 1; padding: 0 2px; flex-shrink: 0;
}
.upload-staged-item .upload-staged-remove:hover { color: var(--red); }
.upload-submit-btn { width: 100%; margin-top: 8px; }

/* Grid rows stretch every item to the tallest, which dragged a collapsed strip to the full
   height of an open card beside it. Only the collapsed variant opts out, so two open cards
   in one row still line up. */
.upload-slot-collapsed { align-self: start; }
.upload-slot-collapsed {
    padding: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
}
.upload-slot-collapsed-summary {
    list-style: none;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 14px 18px;
    font-size: 15px;
    font-weight: 600;
}
.upload-slot-collapsed-summary::-webkit-details-marker { display: none; }
.upload-slot-collapsed-summary span:first-child { display: flex; align-items: center; gap: 8px; }
.upload-slot-collapsed-summary .icon { width: 15px; height: 15px; color: var(--green, #22c55e); flex-shrink: 0; }
.upload-slot-collapsed[open] .upload-slot-collapsed-summary { border-bottom: 1px solid var(--border); }
.upload-slot-collapsed .upload-file-list { padding: 0 18px 14px; }

/* The chevron signals "this is clickable to expand," distinct from the green check (status). */
.upload-slot-collapsed-chevron { color: var(--text-muted) !important; transition: transform 0.15s ease; }
.upload-slot-collapsed[open] .upload-slot-collapsed-chevron { transform: rotate(180deg); }

.upload-progress-track {
    height: 6px;
    border-radius: 999px;
    background: var(--border);
    margin-top: 8px;
    overflow: hidden;
}
.upload-progress-fill {
    height: 100%;
    width: 100%;
    transform: scaleX(0);
    transform-origin: left;
    background: var(--accent);
    transition: transform 0.15s ease;
}

/* Mobile-only: opens the off-canvas sidebar. Lives in the white topbar because the sidebar
   itself is hidden off-screen at this width, so a button inside it would be unreachable. */
.sidebar-toggle-btn {
    display: none;
    background: none; border: none; cursor: pointer; padding: 6px;
    color: var(--text-main); border-radius: 8px; flex-shrink: 0;
}
.sidebar-toggle-btn:hover { background: var(--purple-bg); }
@media (min-width: 901px) {
    /* Only needed once the sidebar has been closed - otherwise it duplicates the X. */
    body.sidebar-closed .sidebar-toggle-btn { display: flex; align-items: center; }
}

/* Desktop-only: lives inside the dark sidebar itself so it visibly belongs to what it
   controls. Collapses to a slim icon-only rail rather than width:0, so this same button
   stays visible (and clickable) to expand it again. */
/* Sits first in the sidebar header, so the collapse control is on the left edge. */
.sidebar-collapse-btn {
    display: flex; align-items: center; justify-content: center;
    background: none; border: none; cursor: pointer; padding: 6px;
    color: var(--sidebar-muted); border-radius: 8px; flex-shrink: 0;
}
.sidebar-collapse-btn:hover { background: rgba(255,255,255,0.08); color: #fff; }
.sidebar-collapse-btn .icon { width: 18px; height: 18px; }

@media (min-width: 901px) {
    /* Closed means gone, not a narrow rail - the topbar button brings it back. */
    .sidebar.collapsed { display: none; }
}

.sidebar-close-btn {
    display: none;
    background: none; border: none; cursor: pointer; padding: 4px;
    color: #fff; margin-left: auto;
}
.sidebar-overlay {
    display: none;
    position: fixed; inset: 0; background: rgba(0,0,0,0.45); z-index: 199;
}

@media (max-width: 1200px) {
    .dashboard-grid { grid-template-columns: 1fr 1fr; }
}

/* Tablet / mobile: off-canvas sidebar + stacked layouts */
@media (max-width: 900px) {
    .sidebar-toggle-btn { display: flex; align-items: center; }
    .sidebar-close-btn { display: block; }
    .sidebar-collapse-btn { display: none; }

    .sidebar {
        position: fixed;
        top: 0; left: 0; bottom: 0;
        z-index: 200;
        width: 260px;
        max-width: 82vw;
        transform: translateX(-100%);
        transition: transform 0.2s ease;
        box-shadow: 0 0 18px rgba(0,0,0,0.28);
    }
    .sidebar.open { transform: translateX(0); }
    .sidebar-overlay.open { display: block; }

    .topbar { padding: 0 16px; }
    .topbar-profile-info { display: none; }
    .content { padding: 18px 16px 32px; }

    .dashboard-grid { grid-template-columns: 1fr; }
    .progress-panels-grid { grid-template-columns: 1fr; }
    .form-grid-2 { grid-template-columns: 1fr; }
    .form-card { padding: 20px 18px; }
    .upload-grid { grid-template-columns: 1fr; }
    .donut-wrap { flex-direction: column; }

    .messages-layout { flex-direction: column; }
    .messages-contact-panel { width: 100%; }

    .panel:has(> table.data-table) {
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }
    table.data-table { min-width: 640px; }
}

@media (max-width: 520px) {
    .stat-cards { flex-direction: column; }
    .stat-card { border-left: none; border-top: 1px solid var(--border); }
    .stat-card:first-child { border-top: none; }
    table.data-table { font-size: 14.5px; }
    table.data-table th, table.data-table td { padding: 8px 6px; }
}

/* Profile photo preview on My Profile pages (Basic Information section) */
.profile-photo-row { display: flex; align-items: center; gap: 18px; margin-bottom: 18px; }
.profile-photo-preview {
    width: 84px; height: 84px; border-radius: 50%;
    background: var(--accent);
    color: #fff; display: flex; align-items: center; justify-content: center;
    font-weight: 700; font-size: 30px; flex-shrink: 0; overflow: hidden;
    border: 2px solid var(--border);
}
.profile-photo-preview img { width: 100%; height: 100%; object-fit: cover; }

.photo-crop-stage {
    width: 240px; height: 240px; border-radius: 12px; overflow: hidden;
    border: 1px solid var(--border); background: #eee;
}
.photo-crop-stage canvas { display: block; cursor: grab; touch-action: none; }
.photo-crop-stage canvas:active { cursor: grabbing; }

/* Small (i)-style info tooltip next to field labels/section headers */
.tooltip-info {
    display: inline-flex; align-items: center; justify-content: center;
    width: 15px; height: 15px; border-radius: 50%;
    background: var(--purple-bg); color: var(--accent-purple);
    font-size: 12px; font-weight: 700; cursor: help; position: relative;
    vertical-align: middle;
}
.tooltip-info::after {
    content: attr(data-tooltip);
    position: absolute; bottom: calc(100% + 7px); left: 50%; transform: translateX(-50%);
    background: var(--ink); color: var(--card-bg); font-weight: 400;
    font-size: 13px; line-height: 1.5; padding: 8px 10px; border-radius: 3px;
    /* Sized to content but never wider than the screen, so it stays readable on a phone. */
    width: max-content; max-width: min(260px, 78vw);
    text-align: left; text-transform: none; letter-spacing: 0;
    opacity: 0; visibility: hidden; transition: opacity 0.15s ease;
    z-index: 50; pointer-events: none;
    white-space: normal;
}
/* Anchored to whichever edge has room - set by the auto-flip script in footer.php so a
   tooltip near the right or left edge of the screen never gets clipped off. */
.tooltip-info.tip-right::after { left: auto; right: 0; transform: none; }
.tooltip-info.tip-left::after  { left: 0; right: auto; transform: none; }
/* No room above (top of the page) - drop it underneath instead. */
.tooltip-info.tip-below::after { bottom: auto; top: calc(100% + 7px); }

.tooltip-info:hover::after, .tooltip-info:focus::after, .tooltip-info:focus-visible::after {
    opacity: 1; visibility: visible;
}

/* Week-by-week internship progress grid (dashboard + logbook) */
.week-grid { display: flex; flex-wrap: wrap; gap: 8px; }
.week-pill {
    width: 34px; height: 34px; border-radius: 8px;
    display: flex; align-items: center; justify-content: center;
    font-size: 14.5px; font-weight: 600; text-decoration: none;
    border: 1.5px solid var(--border); color: var(--text-muted);
    background: #fff; transition: transform 0.1s ease;
}
.week-pill:hover { transform: translateY(-2px); }
.week-pill.week-done { background: var(--green-bg); border-color: var(--green); color: var(--green); }
.week-pill.week-current {
    background: var(--accent-purple); border-color: var(--accent-purple); color: #fff;
    box-shadow: 0 0 0 3px var(--purple-bg);
}
.week-pill.week-future { opacity: 0.6; }
.week-pill.week-selected { outline: 2px solid var(--accent-purple); outline-offset: 2px; }
.internship-panel-locked { opacity: 0.85; }
.internship-panel-locked .empty-state .icon { width: 22px; height: 22px; color: var(--text-muted); }

/* Day-of-week picker on the Digital Logbook add-entry form */
/* One-week-at-a-time navigator: arrows step a week, the week itself sits in the middle. */
.wk-nav { display: flex; align-items: stretch; gap: 10px; }

.wk-arrow {
    flex-shrink: 0; width: 40px;
    display: flex; align-items: center; justify-content: center;
    border: 1px solid var(--border); border-radius: var(--radius);
    background: var(--card-bg); color: var(--text-muted);
    font-size: 25.5px; line-height: 1; text-decoration: none;
}
.wk-arrow:hover { border-color: var(--accent); color: var(--accent); }
.wk-arrow.is-off { opacity: 0.3; pointer-events: none; }

.wk-current {
    flex: 1; min-width: 0; text-align: center;
    border: 1px solid var(--border); border-radius: var(--radius);
    background: var(--card-bg); padding: 12px 14px;
}
.wk-current.is-now { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.wk-current b { display: block; font-size: 19.5px; font-weight: 700; letter-spacing: -0.01em; }
.wk-current b .of { font-weight: 400; font-size: 15px; color: var(--text-muted); }
.wk-current .wk-range { display: block; font-family: var(--font-mono); font-size: 14px; color: var(--text-muted); margin-top: 2px; }
.wk-current .wk-tag {
    display: inline-block; margin-top: 7px;
    font-size: 12.5px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
    padding: 2px 8px; border-radius: 10px;
    background: var(--accent-soft); color: var(--accent);
}
.wk-current .wk-tag.past { background: var(--border); color: var(--text-muted); }
.wk-current .wk-tag.future { background: transparent; color: var(--text-muted); border: 1px solid var(--border); }

.wk-back { margin-top: 10px; text-align: center; font-size: 14.5px; }
.wk-back a { color: var(--accent); font-weight: 600; }

/* Shortcut to the weeks that actually have something written in them. */
.wk-jump {
    display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
    margin-top: 12px; padding-top: 11px; border-top: 1px solid var(--border);
}
.wk-jump .lbl { font-size: 12.5px; color: var(--text-muted); margin-right: 2px; }
.wk-jump a {
    min-width: 24px; padding: 2px 6px; text-align: center;
    font-family: var(--font-mono); font-size: 13px;
    border: 1px solid var(--border); border-radius: var(--radius);
    color: var(--text-muted);
}
.wk-jump a:hover { border-color: var(--accent); color: var(--accent); }
.wk-jump a.on { background: var(--accent); border-color: var(--accent); color: #fff; }


/* Day row - one cell per day, showing the real date and whether it's already written. */
.day-row { display: flex; gap: 6px; flex-wrap: wrap; }
.day-cell {
    flex: 1; min-width: 62px;
    border: 1px solid var(--border); border-radius: var(--radius);
    background: var(--card-bg); cursor: pointer;
    padding: 8px 4px; text-align: center;
    font-family: var(--font-sans); font-size: 13px; color: var(--text-muted);
}
.day-cell b { display: block; font-size: 15.5px; font-weight: 600; color: var(--text-main); margin-bottom: 1px; }
.day-cell .day-dot {
    display: block; width: 5px; height: 5px; border-radius: 50%;
    background: var(--green); margin: 4px auto 0;
}
.day-cell.day-extra { border-style: dashed; }
/* The dashboard renders the same cells as links rather than form buttons. */
a.day-cell { display: block; text-decoration: none; }
/* Future days are shown at full strength (not dimmed) - a faded cell read as disabled. */
.day-cell.is-future { opacity: 1; }
.day-cell:hover { border-color: var(--accent); }
.day-cell.is-selected { background: var(--accent); border-color: var(--accent); }
.day-cell.is-selected b, .day-cell.is-selected { color: #fff; }
.day-cell.is-selected .day-dot { background: #fff; }

@media (max-width: 560px) {
    .day-cell { min-width: 44px; font-size: 12.5px; }
    .day-cell b { font-size: 14px; }
    .wk-arrow { width: 34px; }
}

/* Small modal dialog (used for single logbook-entry review with a comment) */
.modal-overlay {
    position: fixed; inset: 0; background: rgba(20, 20, 30, 0.45);
    display: flex; align-items: center; justify-content: center; z-index: 100;
}
.modal-box {
    background: #fff; border-radius: 12px; padding: 22px; width: 90%; max-width: 420px;
    box-shadow: 0 20px 60px rgba(0,0,0,0.25);
}

/* The one instruction a student needs, above every panel. A new account opens a dashboard of
   status readouts that answer "where am I up to" but never "what do I do now" - this answers
   that, and disappears the moment registration is finished. */
.next-step {
    display: flex; align-items: center; gap: 10px 18px; flex-wrap: wrap;
    max-width: 900px; margin-bottom: 18px; padding: 14px 16px;
    text-decoration: none; color: var(--ink);
    background: var(--accent-soft);
    border: 1px solid var(--accent); border-left-width: 4px;
    border-radius: var(--radius);
}
.next-step:hover { background: #D8E7F4; }
/* A clearly visible red pulse on the next-step banner so a new student cannot miss the call to
   fill in their profile. The border and glow both animate to red and back. */
@keyframes next-step-pulse {
    0%, 100% {
        box-shadow: 0 0 0 0 rgba(220, 38, 38, 0.0);
        border-color: #dc2626; background: var(--accent-soft);
    }
    50% {
        box-shadow: 0 0 0 9px rgba(220, 38, 38, 0.45);
        border-color: #dc2626; background: #fde3e3;
    }
}
.next-step {
    animation: next-step-pulse 1.15s ease-in-out infinite;
    border: 2px solid #dc2626; border-left-width: 5px;
}
.next-step .ns-step {
    font-size: 13px; padding: 5px 11px;
    background: #dc2626;
}
@media (prefers-reduced-motion: reduce) {
    .next-step { animation: none; border-color: #dc2626; box-shadow: 0 0 0 3px rgba(220,38,38,0.22); }
}

/* Training countdown strip. Quieter than .next-step - it is a status line, not an action - so
   it uses a neutral surface and only a coloured left edge that shifts with the phase. */
.li-timeline {
    display: flex; align-items: center; gap: 12px;
    max-width: 900px; margin-bottom: 18px; padding: 12px 16px;
    background: var(--card-bg);
    border: 1px solid var(--border); border-left: 4px solid var(--accent);
    border-radius: var(--radius);
}
.li-timeline--before { border-left-color: #C08A1E; }
.li-timeline--during { border-left-color: var(--accent); }
.li-timeline--after  { border-left-color: #2F9E5F; }
.li-timeline-icon { flex-shrink: 0; width: 22px; height: 22px; color: var(--ink-soft); }
.li-timeline-text { flex: 1 1 auto; min-width: 0; }
.li-timeline-text b { display: block; font-size: 15.5px; font-weight: 700; }
.li-timeline-text span { display: block; margin-top: 1px; font-size: 13.5px; color: var(--ink-soft); }
.li-timeline-bar {
    flex: 0 0 140px; height: 7px; border-radius: 999px;
    background: var(--border); overflow: hidden;
}
.li-timeline-bar span { display: block; height: 100%; background: var(--accent); border-radius: 999px; }
@media (max-width: 620px) {
    .li-timeline-bar { display: none; }
}

.ns-step {
    flex-shrink: 0; padding: 4px 9px; border-radius: 999px;
    background: var(--accent); color: #fff;
    font-size: 12px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
}
.ns-text { flex: 1 1 280px; }
.ns-text b { display: block; font-size: 16.5px; font-weight: 700; }
.ns-text span { display: block; margin-top: 2px; font-size: 14.5px; color: var(--ink-soft); }
.ns-go {
    flex-shrink: 0; display: inline-flex; align-items: center; gap: 6px;
    font-size: 15px; font-weight: 600; color: var(--accent);
}
.ns-go .icon { width: 15px; height: 15px; }
/* Nothing here is the student's to do - same shape, quieter, so a wait doesn't read as a task. */
.next-step.is-waiting { background: var(--card-bg); border-color: var(--border); border-left-color: var(--yellow); }
.next-step.is-waiting .ns-step { background: var(--yellow); }
.next-step.is-waiting .ns-go { color: var(--ink-soft); }

/* Until registration is done, this is the panel that matters; the accent edge says so without
   adding another block of text to a page that already has enough. */
.panel.is-focus { border-color: var(--accent); }
.panel.is-focus > .panel-head h2, .panel.is-focus > .panel-summary h2 { color: var(--accent); }

/* Slot status. A pending slot used to say "waiting" in a pill the size of a word, directly above
   a full-size drop target - so the card read as "nothing uploaded yet" when in fact everything
   had been. Both states now state plainly what happened and whether the student owes anything. */
.slot-status {
    display: flex; align-items: flex-start; gap: 10px;
    margin-bottom: 12px; padding: 10px 12px;
    border: 1px solid; border-radius: var(--radius);
}
.slot-status .icon { width: 17px; height: 17px; flex-shrink: 0; margin-top: 1px; }
.slot-status .ss-text { min-width: 0; }
.slot-status b { display: block; font-size: 15.5px; font-weight: 700; }
.slot-status .ss-text span { display: block; margin-top: 2px; font-size: 14.5px; line-height: 1.45; }
.slot-status.is-pending { background: var(--yellow-bg); border-color: var(--yellow); color: var(--yellow); }
/* The instruction, set apart from the coordinator's reason above it - a student who reads
   only the reason is exactly the one who leaves the old PDF behind. */
.slot-status .ss-warn {
    display: block; margin-top: 7px; padding-top: 7px;
    border-top: 1px solid currentColor;
    font-size: 14.5px; font-weight: 600; line-height: 1.45; opacity: 0.95;
}
.slot-status.is-rejected { background: var(--red-bg); border-color: var(--red); color: var(--red); }

/* Once a file is in, the drop target shrinks to a plain button. It is the same <label for> as
   the big version, so clicking still opens the file picker and a drag onto it still works. */
.upload-dropzone.is-compact {
    display: inline-flex; flex-direction: row; align-items: center; gap: 7px;
    width: auto; align-self: flex-start;
    padding: 7px 13px; text-align: left;
    border: 1px solid var(--border); border-radius: 8px;
    background: var(--card-bg);
    font-size: 14.5px; font-weight: 600; color: var(--accent);
}
.upload-dropzone.is-compact:hover { border-color: var(--accent); background: var(--accent-soft); }
.upload-dropzone.is-compact .icon { width: 15px; height: 15px; }

/* The service-account address has to be pasted into Drive's share dialog exactly as it is, and
   it is long enough that retyping it is how people get it wrong. */
.copy-chip {
    display: inline-flex; align-items: center; gap: 6px; vertical-align: baseline;
    padding: 2px 8px; border-radius: var(--radius);
    border: 1px solid var(--accent-soft); background: var(--accent-soft);
    font-family: var(--font-mono); font-size: 13px; font-weight: 600; color: var(--accent);
    cursor: pointer;
}
.copy-chip:hover, .copy-chip:focus-visible { border-color: var(--accent); outline: none; }
.copy-chip .icon { width: 13px; height: 13px; flex-shrink: 0; }
.copy-chip .copy-done { display: none; }
.copy-chip.is-copied { background: var(--green-bg); border-color: var(--green); color: var(--green); }
.copy-chip.is-copied .copy-idle { display: none; }
.copy-chip.is-copied .copy-done { display: inline-flex; }

/* A field the student cannot change, shown as a fact rather than a disabled input - a greyed-out
   date picker still invites clicking and still looks like something went wrong. */
.ro-field {
    padding: 9px 12px; border: 1px solid var(--border); border-radius: 8px;
    background: var(--paper);
}
.ro-field b { display: block; font-size: 15.5px; font-weight: 700; color: var(--ink); }
.ro-field span {
    display: block; margin-top: 3px;
    font-size: 14px; line-height: 1.45; color: var(--ink-soft);
}

/* The demo date switch. Deliberately unlike the rest of the interface - a hazard stripe rather
   than a panel - because it is a testing tool sitting on a real page, and nobody should mistake
   it for part of the product. */
.demo-date {
    display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
    padding: 7px 16px;
    background: repeating-linear-gradient(135deg, #2A2E33 0 12px, #23272B 12px 24px);
    color: #E6EAEE; font-size: 14.5px;
}
.demo-date.is-on { background: repeating-linear-gradient(135deg, #7D5D12 0 12px, #6B4F0E 12px 24px); }
.demo-date .dd-tag {
    padding: 2px 7px; border-radius: 3px; background: rgba(255,255,255,0.16);
    font-size: 12px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
}
.demo-date label { font-weight: 600; }
.demo-date input[type="date"] {
    padding: 3px 7px; border: 1px solid rgba(255,255,255,0.28); border-radius: 4px;
    background: rgba(255,255,255,0.10); color: #fff;
    font: inherit; font-size: 14.5px;
    /* The picker glyph is near-black by default, which is invisible on this strip. */
    color-scheme: dark;
}
.demo-date button {
    padding: 4px 11px; border: 1px solid rgba(255,255,255,0.32); border-radius: 4px;
    background: rgba(255,255,255,0.14); color: #fff;
    font: inherit; font-size: 14px; font-weight: 600; cursor: pointer;
}
.demo-date button:hover { background: rgba(255,255,255,0.24); }
.demo-date .dd-reset { border-style: dashed; }

/* The three stage buttons sit together as one control, separated from the date picker beside
   them, so it reads as "jump to a point in the year" rather than three loose buttons. */
.demo-date .dd-stages { display: inline-flex; gap: 0; margin-right: 4px; }
.demo-date .dd-stages button { border-radius: 0; margin: 0; }
.demo-date .dd-stages button:first-child { border-radius: 5px 0 0 5px; }
.demo-date .dd-stages button:last-child { border-radius: 0 5px 5px 0; }
.demo-date .dd-stages button + button { border-left: none; }

@media (max-width: 700px) { .demo-date { font-size: 13px; padding: 6px 12px; } }

/* Close button on the demo bar - sits hard right, away from Apply, so the two are not confused. */
.demo-date .dd-close {
    margin-left: auto; padding: 2px 9px;
    border-color: rgba(255,255,255,0.28); background: transparent;
    font-size: 17px; line-height: 1.2;
}
.demo-date .dd-close:hover { background: rgba(255,255,255,0.22); }
.demo-open-form { margin: 0; }
/* The opener as a row in the profile menu, matching the links either side of it. */
.profile-dropdown .demo-open-form button.profile-dropdown-action {
    display: flex; align-items: center; gap: 10px; width: 100%;
    padding: 9px 14px; border: none; border-radius: 0;
    background: none; color: var(--ink);
    font: inherit; font-size: 15px; text-align: left; cursor: pointer;
}
.profile-dropdown .demo-open-form button.profile-dropdown-action:hover { background: var(--accent-soft); }
.profile-dropdown .demo-open-form .icon { width: 16px; height: 16px; color: var(--ink-soft); flex-shrink: 0; }

/* Sync progress. The bar moves a batch at a time rather than continuously - each step is a real
   round of uploads that has actually completed, not an animation guessing at progress. */
.sync-progress { margin: 0 0 14px; }
.sync-bar {
    height: 8px; border-radius: 999px; overflow: hidden;
    background: var(--paper); border: 1px solid var(--border);
}
.sync-bar span {
    display: block; height: 100%;
    background: var(--accent); border-radius: 999px;
    transition: width 0.4s ease;
}
.sync-figures {
    display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
    margin-top: 8px; font-size: 14.5px; color: var(--ink-soft);
}
.sync-figures b { color: var(--ink); font-weight: 700; }
.sync-count, .sync-figures .sync-timer { font-variant-numeric: tabular-nums; }
.sync-timer { font-size: 13px; color: var(--text-muted); font-weight: 500; white-space: nowrap; font-variant-numeric: tabular-nums; }
.sync-session-pick { display: inline-flex; align-items: center; gap: 6px; }
.sync-session-pick select { padding: 5px 8px; border: 1px solid var(--border); border-radius: 6px; font-size: 13.5px; }

/* Shown only while a run is in progress. */
.sync-warn {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 4px 10px; border-radius: var(--radius);
    background: var(--yellow-bg); border: 1px solid var(--yellow);
    font-size: 14px; font-weight: 600; color: var(--yellow);
}
.sync-warn .icon { width: 14px; height: 14px; flex-shrink: 0; }
.sync-warn.is-error { background: var(--red-bg); border-color: var(--red); color: var(--red); }
.sync-warn.is-done { background: #e6f4ea; border-color: var(--green); color: var(--green); }

/* The three steps on the password-reset page. Numbered because the order genuinely matters -
   people email before knowing what to include, and then the exchange takes three messages. */
.reset-steps {
    margin: 0 0 16px; padding-left: 20px;
    font-size: 15px; line-height: 1.6; color: var(--ink-soft);
}
.reset-steps li { margin-bottom: 5px; }
.reset-steps strong { color: var(--ink); }

/* A readable document page for public notices - no sidebar, no app chrome, because someone may
   be reading this before they have an account at all. Measure kept near 70 characters. */
.doc-page { min-height: 100vh; padding: 40px 20px 60px; background: var(--paper); }
.doc-sheet {
    max-width: 760px; margin: 0 auto; padding: 40px 44px 34px;
    background: var(--card-bg); border: 1px solid var(--border); border-radius: var(--radius);
}
.doc-back {
    display: inline-flex; align-items: center; gap: 6px; margin-bottom: 22px;
    font-size: 15px; font-weight: 600; color: var(--accent); text-decoration: none;
}
.doc-back:hover { text-decoration: underline; }
.doc-back-icon { width: 15px; height: 15px; transform: rotate(180deg); }
.doc-sheet h1 { font-size: 31px; font-weight: 700; letter-spacing: -0.02em; margin: 0 0 10px; }
.doc-lede { margin: 0 0 28px; font-size: 15.5px; line-height: 1.65; color: var(--ink-soft); }
.doc-sheet h2 {
    margin: 30px 0 10px; padding-top: 18px; border-top: 1px solid var(--border);
    font-size: 18.5px; font-weight: 700;
}
.doc-sheet h3 { margin: 18px 0 6px; font-size: 15.5px; font-weight: 700; color: var(--ink-soft); }
.doc-sheet p { margin: 0 0 12px; font-size: 15.5px; line-height: 1.65; }
.doc-sheet ul { margin: 0 0 14px; padding-left: 20px; }
.doc-sheet li { margin-bottom: 6px; font-size: 15.5px; line-height: 1.6; }
.doc-sheet a { color: var(--accent); }
.doc-foot {
    margin: 32px 0 0; padding-top: 16px; border-top: 1px solid var(--border);
    font-size: 14px; color: var(--ink-soft);
}
@media (max-width: 700px) { .doc-sheet { padding: 28px 20px 24px; } }

/* A standing clarification on a public page - reads as a notice rather than body text,
   because someone skimming needs to see it without reading the paragraph. */
.doc-note {
    margin: 0 0 18px; padding: 12px 14px;
    background: var(--yellow-bg); border: 1px solid var(--yellow); border-radius: var(--radius);
    font-size: 15px; line-height: 1.6; color: var(--yellow);
}
.doc-note strong { color: var(--yellow); }

/* Gate in front of the demo login tiles. Small and unobtrusive - it is a convenience lock,
   not a security boundary, and it should not look like the main sign-in form. */
.demo-gate { display: flex; gap: 8px; margin-bottom: 14px; }
.demo-gate input {
    flex: 1; min-width: 0; padding: 8px 11px;
    border: 1px solid var(--border); border-radius: 8px;
    font: inherit; font-size: 15px; background: #fff; color: var(--ink);
}
.demo-gate button { flex-shrink: 0; white-space: nowrap; }

/* Logbook: the Today shortcut sits with the computed-date readout under the day row. */
.day-today-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 10px; }

/* Login-page disclaimer. Says plainly this is a student project, not an official polytechnic
   system - both because it is true and because institutional branding plus a password form on an
   unofficial domain is exactly what a phishing scanner flags. */
.auth-split-disclaimer {
    margin-top: 22px; padding: 12px 14px;
    background: rgba(255,255,255,0.10); border: 1px solid rgba(255,255,255,0.22);
    border-radius: 10px; font-size: 13px; line-height: 1.55; color: rgba(255,255,255,0.9);
    max-width: 420px;
}
.auth-split-disclaimer a { color: #fff; text-decoration: underline; }
.auth-split-note {
    text-align: center; margin-top: 18px; font-size: 12.5px; color: var(--text-muted);
}

/* EN / BM language toggle in the top bar (and on the login page). */
.lang-toggle { display: inline-flex; border: 1px solid var(--border); border-radius: 999px; overflow: hidden; }
.lang-toggle a {
    padding: 4px 10px; font-size: 12.5px; font-weight: 700; text-decoration: none;
    color: var(--text-muted); background: var(--card-bg); line-height: 1.6;
}
.lang-toggle a.is-on { background: var(--accent); color: #fff; }
.lang-toggle a + a { border-left: 1px solid var(--border); }
.auth-lang-toggle { position: absolute; top: 18px; right: 20px; z-index: 5; }

/* A class-level display must never override the hidden attribute (it did on .sync-warn). */
[hidden] { display: none !important; }

/* Student announcement bar: one announcement at a time, cross-fading. Rendered only when there is
   an announcement to show. */
.ann-bar {
    display: flex; align-items: stretch; margin: 0 0 16px;
    border: 1px solid var(--border); border-radius: var(--radius);
    background: var(--accent-soft); overflow: hidden;
}
.ann-bar-tag {
    display: inline-flex; align-items: center; gap: 6px; flex-shrink: 0;
    padding: 8px 14px; background: var(--accent); color: #fff;
    font-size: 12.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em;
}
.ann-bar-tag .icon { width: 15px; height: 15px; }
.ann-bar-stage { position: relative; flex: 1; min-width: 0; }
.ann-bar-item {
    position: absolute; inset: 0; display: flex; align-items: center;
    opacity: 0; visibility: hidden; transition: opacity 0.5s ease;
}
.ann-bar-item.is-active { opacity: 1; visibility: visible; }
.ann-bar-link {
    flex: 1; min-width: 0; display: flex; align-items: center; gap: 8px;
    padding: 8px 8px 8px 16px; font-size: 14px; color: var(--ink); font-weight: 500; text-decoration: none;
}
.ann-bar-link span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ann-bar-link .icon { width: 15px; height: 15px; color: var(--accent); flex-shrink: 0; }
.ann-bar-link:hover span { text-decoration: underline; }
.ann-bar-x {
    flex-shrink: 0; border: none; background: none; cursor: pointer;
    padding: 4px 14px; font-size: 20px; line-height: 1; color: var(--text-muted);
}
.ann-bar-x:hover { color: var(--ink); }
/* Which intake a student belongs to, shown at the top of their dashboard. Neutral by default,
   tinted by where the session sits in time (upcoming / current / finished). */
.session-chip {
    display: inline-flex; align-items: center; gap: 8px; margin-bottom: 14px;
    padding: 7px 14px; border: 1px solid var(--border); border-radius: 999px;
    background: var(--card-bg); font-size: 13.5px; color: var(--ink);
}
.session-chip-icon { width: 15px; height: 15px; color: var(--text-muted); flex-shrink: 0; }
.session-chip-text b { font-weight: 700; }
.session-chip-badge {
    font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em;
    padding: 2px 8px; border-radius: 999px; background: #eee; color: #666;
}
.session-chip--current  { border-color: var(--green); }
.session-chip--current  .session-chip-badge  { background: var(--green-bg); color: var(--green); }
.session-chip--current  .session-chip-icon   { color: var(--green); }
.session-chip--upcoming .session-chip-badge  { background: var(--accent-soft); color: var(--accent); }
.session-chip--upcoming .session-chip-icon   { color: var(--accent); }

/* Empty state: no announcements to show. A normal flex child (not the absolute stage), so the
   bar keeps its height and the note sits neatly beside the tag. */
.ann-bar-empty-text {
    flex: 1; min-width: 0; display: flex; align-items: center;
    padding: 8px 16px; font-size: 14px; color: var(--text-muted);
}

/* Greyed-out, unclickable sidebar items for a student who has not filled their profile yet. */
.sidebar-nav a.nav-locked { opacity: 0.42; pointer-events: none; cursor: not-allowed; }
.sidebar-nav a.nav-locked .nav-lock-icon { width: 14px; height: 14px; margin-left: auto; opacity: 0.8; }

/* Announcement attachments: images inline as thumbnails, other files as a labelled link. */
.a-files { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 10px; }
.a-file-img img {
    height: 96px; width: auto; max-width: 220px; object-fit: cover;
    border-radius: 8px; border: 1px solid var(--border); display: block;
}
.a-file-doc {
    display: inline-flex; align-items: center; gap: 7px;
    padding: 8px 12px; border: 1px solid var(--border); border-radius: 8px;
    background: var(--card-bg); color: var(--accent); text-decoration: none; font-size: 13.5px; font-weight: 600;
}
.a-file-doc:hover { background: var(--accent-soft); }
.a-file-doc .icon { width: 16px; height: 16px; }

/* Reusable 3-dots (kebab) menu: a button that drops a small action menu. */
.kebab-wrap { position: relative; display: inline-block; }
.kebab-btn {
    border: none; background: none; cursor: pointer; font-size: 20px; line-height: 1;
    padding: 4px 10px; color: var(--text-muted); border-radius: 6px;
}
.kebab-btn:hover, .kebab-wrap.is-open .kebab-btn { background: var(--accent-soft); color: var(--ink); }
.kebab-menu {
    position: absolute; right: 0; top: calc(100% + 4px); min-width: 160px;
    background: var(--card-bg); border: 1px solid var(--border); border-radius: 10px;
    box-shadow: 0 10px 28px rgba(0,0,0,0.14); padding: 5px; z-index: 40; display: none;
}
.kebab-wrap.is-open .kebab-menu { display: block; }
.kebab-menu a, .kebab-menu button {
    display: flex; align-items: center; gap: 8px; width: 100%; text-align: left;
    padding: 9px 12px; border: none; background: none; font-size: 13.5px; font-weight: 500;
    color: var(--ink); text-decoration: none; cursor: pointer; border-radius: 6px; font-family: inherit;
}
.kebab-menu a:hover, .kebab-menu button:hover { background: var(--accent-soft); }
.kebab-menu .icon { width: 15px; height: 15px; }
.kebab-menu .danger, .kebab-menu .danger:hover { color: var(--red); }

/* Scrolling disclaimer bar pinned to the bottom of the login page - a moving strip is noticed
   where side-panel text is skipped. Red so it clearly reads as "not the official system". It can
   be closed, and reopened from a small tab. */
.login-notice {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 100;
    height: 40px; overflow: hidden; white-space: nowrap; display: flex; align-items: center;
    background: #b91c1c; color: #fff; font-size: 13px; font-weight: 600;
    box-shadow: 0 -2px 10px rgba(0,0,0,0.15);
}
.login-notice-viewport { flex: 1; min-width: 0; overflow: hidden; display: flex; align-items: center; }
.login-notice-track { display: inline-flex; white-space: nowrap; will-change: transform; animation: login-notice-scroll 34s linear infinite; }
.login-notice-run { padding-left: 24px; }
.login-notice a { color: #fff; text-decoration: underline; }
.login-notice-x {
    flex-shrink: 0; border: none; background: rgba(0,0,0,0.18); color: #fff;
    font-size: 20px; line-height: 1; cursor: pointer; align-self: stretch; padding: 0 16px;
}
.login-notice-x:hover { background: rgba(0,0,0,0.32); }
.login-notice-open {
    position: fixed; right: 14px; bottom: 14px; z-index: 100;
    border: none; background: #b91c1c; color: #fff; cursor: pointer;
    font-size: 12.5px; font-weight: 700; padding: 8px 14px; border-radius: 999px;
    box-shadow: 0 3px 10px rgba(0,0,0,0.2);
}
@keyframes login-notice-scroll { from { transform: translateX(0); } to { transform: translateX(-50%); } }
@media (prefers-reduced-motion: reduce) {
    .login-notice-track { animation: none; }
    .login-notice { overflow-x: auto; }
}
