/* ==========================================================================
   School ERP — one stylesheet, committed, no build step.

   There is no Node on a cPanel account and no reason to trust a CDN with a
   school's pages. Everything that varies per school is a CSS variable set from
   the branding settings and injected by branding_css_variables(); everything
   else is here.
   ========================================================================== */

:root {
  --brand:        #1f9d55;
  --brand-dark:   #197f45;
  --brand-soft:   #eaf7f0;
  --sidebar:      #101f17;
  --sidebar-soft: #1b3226;
  --accent:       #f2a03d;

  --ink:          #16211c;
  --ink-soft:     #5d6d65;
  --ink-faint:    #8b9992;
  --page:         #f4f7f5;
  --panel:        #ffffff;
  --line:         #e3eae6;
  --line-strong:  #cdd9d3;

  --ok:           #1f9d55;
  --warn:         #b9761c;
  --bad:          #c2432f;

  --radius:       10px;
  --radius-sm:    6px;
  --shadow:       0 1px 2px rgba(16, 31, 23, .05), 0 6px 18px rgba(16, 31, 23, .05);

  --sidebar-w:    248px;
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

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

h1, h2, h3 { margin: 0; font-weight: 650; letter-spacing: -.01em; }
p { margin: 0 0 10px; }
a { color: var(--brand-dark); text-decoration: none; }
a:hover { text-decoration: underline; }
code { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: .86em; }

:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; border-radius: 3px; }

.skip-link {
  position: absolute; left: -9999px; top: 8px; z-index: 100;
  background: #fff; padding: 10px 14px; border-radius: var(--radius-sm);
}
.skip-link:focus { left: 8px; }

.muted { color: var(--ink-faint); font-size: 13px; margin: 2px 0 0; }
.nowrap { white-space: nowrap; }
.r { text-align: right; }
.c { text-align: center; }
.dot { opacity: .4; margin: 0 6px; }

/* ------------------------------------------------------------------ shell */

.shell { display: flex; min-height: 100vh; }

.sidebar {
  width: var(--sidebar-w);
  flex: 0 0 var(--sidebar-w);
  background: var(--sidebar);
  color: #cfe0d6;
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
}

.brand {
  display: flex; align-items: center; gap: 10px;
  padding: 18px 18px 16px;
  border-bottom: 1px solid rgba(255, 255, 255, .07);
}
.brand-logo { max-width: 34px; max-height: 34px; border-radius: 6px; background: #fff; }
.brand-mark {
  width: 34px; height: 34px; flex: none;
  display: grid; place-items: center;
  background: var(--brand); color: #fff;
  border-radius: 8px; font-weight: 700; font-size: 13px;
}
.brand-mark-lg { width: 52px; height: 52px; font-size: 18px; }
.brand-name { font-weight: 640; color: #fff; font-size: 14.5px; line-height: 1.25; }

.nav { padding: 10px 10px 4px; }
.nav-group {
  margin: 14px 8px 6px;
  font-size: 10.5px; letter-spacing: .09em; text-transform: uppercase;
  color: #6f8a7c;
}
.nav-link {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px; margin-bottom: 2px;
  border-radius: var(--radius-sm);
  color: #cfe0d6; font-size: 14px;
}
.nav-link:hover { background: var(--sidebar-soft); text-decoration: none; color: #fff; }
.nav-link.is-current { background: var(--brand); color: #fff; font-weight: 600; }
.nav-icon { width: 18px; height: 18px; flex: none; opacity: .9; }

.nav-later { margin-top: auto; padding: 16px 18px 20px; border-top: 1px solid rgba(255, 255, 255, .07); }
.nav-later ul { margin: 0; padding-left: 16px; color: #7e9689; font-size: 13px; }
.nav-later li { margin-bottom: 3px; }
.nav-later-note { margin-top: 10px; font-size: 11.5px; color: #5f7a6c; line-height: 1.5; }

.main-column { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }

.topbar {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 14px 26px;
  background: var(--panel);
  border-bottom: 1px solid var(--line);
  position: sticky; top: 0; z-index: 20;
}
.topbar-left { display: flex; align-items: center; gap: 12px; }
.page-title { font-size: 19px; }
.page-date { margin: 0; font-size: 12.5px; color: var(--ink-faint); }
.topbar-right { display: flex; align-items: center; gap: 10px; }
.who { text-align: right; line-height: 1.2; }
.who-name { display: block; font-size: 13.5px; font-weight: 600; }
.who-type { display: block; font-size: 11.5px; color: var(--ink-faint); }
.avatar {
  width: 34px; height: 34px; border-radius: 50%;
  background: var(--brand-soft); color: var(--brand-dark);
  display: grid; place-items: center; font-size: 12.5px; font-weight: 700;
}
.inline-form { display: inline; }

.menu-toggle { display: none; background: none; border: 0; padding: 6px; color: var(--ink); cursor: pointer; }
.menu-toggle svg { width: 22px; height: 22px; }

.content { padding: 22px 26px 34px; flex: 1 1 auto; }

.app-foot {
  padding: 14px 26px 22px;
  color: var(--ink-faint); font-size: 12.5px;
  border-top: 1px solid var(--line);
}
.dev-badge { color: var(--warn); font-weight: 600; }

/* ------------------------------------------------------------------ cards */

.card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 18px 20px;
  margin-bottom: 18px;
}
.card-head { margin-bottom: 14px; position: relative; }
.card-head h2 { font-size: 16px; }
.card-head .btn { position: absolute; right: 0; top: -2px; }
.card-sub { margin: 5px 0 0; color: var(--ink-soft); font-size: 13px; max-width: 68ch; }
.card-foot { margin: 14px 0 0; padding-top: 12px; border-top: 1px solid var(--line); font-size: 12.5px; color: var(--ink-soft); }
.card-warn { border-left: 3px solid var(--warn); }
.card-setup { border-left: 3px solid var(--brand); }

.grid-2 { display: grid; grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); gap: 18px; align-items: start; }

/* -------------------------------------------------------------------- kpi */

.kpi-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 16px; margin-bottom: 18px; }
.kpi { padding: 16px 18px; margin: 0; }
.kpi-label { margin: 0; font-size: 12px; letter-spacing: .04em; text-transform: uppercase; color: var(--ink-faint); }
.kpi-value { margin: 4px 0 2px; font-size: 30px; font-weight: 680; letter-spacing: -.02em; line-height: 1.1; }
.kpi-note { margin: 0; font-size: 12.5px; color: var(--ink-soft); }
.kpi-chart { margin: 6px 0 4px; }
.kpi-attention { border-left: 3px solid var(--warn); }
.spark { display: block; width: 100%; height: 34px; }
.chart-empty { color: var(--ink-faint); font-size: 12.5px; }

.donut-value { font-size: 20px; font-weight: 700; fill: var(--ink); }
.donut-label { font-size: 10px; fill: var(--ink-faint); }
.linechart { width: 100%; height: auto; }
.axis { font-size: 10px; fill: var(--ink-faint); }

/* ------------------------------------------------------------------ lists */

.setup-list, .waiting-list, .blank-list, .feed, .plain-list, .bar-list, .health-list { list-style: none; margin: 0; padding: 0; }

.setup-item { display: flex; align-items: flex-start; gap: 12px; padding: 11px 0; border-bottom: 1px solid var(--line); }
.setup-item:last-child { border-bottom: 0; }
.setup-item > div { flex: 1 1 auto; }
.setup-tick {
  width: 22px; height: 22px; flex: none; margin-top: 1px;
  border-radius: 50%; border: 2px solid var(--line-strong);
  display: grid; place-items: center; font-size: 12px; color: #fff;
}
.is-done .setup-tick { background: var(--brand); border-color: var(--brand); }
.setup-label { margin: 0; font-weight: 600; font-size: 14px; }
.is-done .setup-label { color: var(--ink-faint); font-weight: 500; }
.setup-why { margin: 2px 0 0; font-size: 12.5px; color: var(--ink-soft); }

.waiting-list li, .blank-list li { display: flex; justify-content: space-between; gap: 12px; padding: 9px 0; border-bottom: 1px solid var(--line); }
.waiting-list li:last-child, .blank-list li:last-child { border-bottom: 0; }
.waiting-label, .blank-label { font-weight: 560; font-size: 14px; }
.blank-where { color: var(--ink-faint); font-size: 12.5px; text-align: right; max-width: 55%; }

.feed li { display: flex; gap: 10px; align-items: baseline; padding: 7px 0; border-bottom: 1px solid var(--line); font-size: 13px; }
.feed li:last-child { border-bottom: 0; }
.feed-action { font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 12px; color: var(--brand-dark); }
.feed-who { flex: 1 1 auto; color: var(--ink-soft); }
.feed-when { color: var(--ink-faint); font-size: 12px; }

.plain-list li { padding: 6px 0; border-bottom: 1px solid var(--line); }
.plain-list li:last-child { border-bottom: 0; }

.bar-list li { display: grid; grid-template-columns: 1fr 40% 44px; align-items: center; gap: 10px; padding: 7px 0; }
.bar-label { font-size: 13.5px; }
.bar-track { height: 8px; background: var(--line); border-radius: 99px; overflow: hidden; }
.bar-fill { display: block; height: 100%; background: var(--brand); border-radius: 99px; }
.bar-value { text-align: right; font-size: 13px; font-variant-numeric: tabular-nums; color: var(--ink-soft); }

.quick-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 12px; }
.quick {
  display: block; padding: 13px 14px;
  background: var(--brand-soft); border: 1px solid transparent;
  border-radius: var(--radius-sm); color: var(--ink);
}
.quick:hover { text-decoration: none; border-color: var(--brand); }
.quick-label { display: block; font-weight: 620; font-size: 14px; }
.quick-blurb { display: block; font-size: 12.5px; color: var(--ink-soft); margin-top: 2px; }

.query-note { font-size: 12px; color: var(--ink-faint); }

/* ----------------------------------------------------------------- tables */

.table { width: 100%; border-collapse: collapse; font-size: 14px; }
.table th {
  text-align: left; font-size: 11.5px; letter-spacing: .05em; text-transform: uppercase;
  color: var(--ink-faint); font-weight: 620;
  padding: 8px 10px; border-bottom: 1px solid var(--line-strong);
}
.table td { padding: 10px; border-bottom: 1px solid var(--line); vertical-align: top; }
.table tr:last-child td { border-bottom: 0; }
.table tr.is-off td { opacity: .6; }
.table-scroll { overflow-x: auto; }
.table-matrix td, .table-matrix th { padding: 7px 8px; }
.table-matrix .rot { font-size: 11px; white-space: nowrap; }
.tick { color: var(--brand); font-size: 15px; }
.untick { color: var(--line-strong); }
.table-perms td { vertical-align: middle; }
.table-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.chip { background: var(--page); border: 1px solid var(--line); border-radius: 99px; padding: 3px 9px; font-size: 12px; }

.empty { color: var(--ink-faint); padding: 18px 0; text-align: center; }

.pager { display: flex; gap: 16px; align-items: center; justify-content: center; padding: 14px 0 2px; font-size: 13px; }

/* ------------------------------------------------------------------ forms */

.form .field { margin-bottom: 16px; max-width: 560px; }
.form-wide .field { max-width: 620px; }
.form-narrow { max-width: 520px; }
.form-inline { display: flex; align-items: flex-end; gap: 12px; flex-wrap: wrap; }
.form-inline .field { margin-bottom: 0; }

label { display: block; font-size: 13px; font-weight: 600; margin-bottom: 5px; }

input[type=text], input[type=email], input[type=password], input[type=number],
input[type=search], input[type=file], select, textarea {
  width: 100%; padding: 9px 11px;
  border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  background: #fff; color: var(--ink); font: inherit; font-size: 14px;
}
input:focus, select:focus, textarea:focus { border-color: var(--brand); outline-offset: 0; }
textarea { resize: vertical; }
input[readonly] { background: var(--page); color: var(--ink-soft); }

.field-help { margin: 5px 0 0; font-size: 12.5px; color: var(--ink-soft); }
.field-where { margin: 5px 0 0; font-size: 12px; color: var(--ink-faint); }
.field-error { margin: 5px 0 0; font-size: 12.5px; color: var(--bad); font-weight: 550; }
.has-error input, .has-error select, .has-error textarea { border-color: var(--bad); }
.static-value { padding: 9px 0; font-size: 14px; }

.switch { display: inline-flex; align-items: center; gap: 8px; font-weight: 500; }
.switch input { width: auto; }

.colour-field { display: flex; align-items: center; gap: 10px; }
.colour-field input[type=color] { width: 52px; height: 34px; padding: 2px; border-radius: var(--radius-sm); border: 1px solid var(--line-strong); }

.file-current { display: flex; align-items: center; gap: 14px; margin-bottom: 10px; }
.file-preview { max-height: 54px; max-width: 160px; border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 4px; background: #fff; }

.form-actions { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--line); }
.sticky-actions {
  position: sticky; bottom: 0; background: var(--panel);
  border: 1px solid var(--line); border-radius: var(--radius);
  padding: 12px 20px; box-shadow: var(--shadow); margin-top: 0;
}
.button-row { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }

.filters { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 14px; }
.filters input, .filters select { width: auto; min-width: 160px; }

.perm-group { border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 12px 14px; margin: 0 0 12px; }
.perm-group legend { font-size: 12px; text-transform: uppercase; letter-spacing: .05em; color: var(--ink-faint); font-weight: 620; padding: 0 6px; }
.perm { display: flex; align-items: baseline; gap: 9px; padding: 5px 0; font-weight: 500; }
.perm input { width: auto; }
.perm-label { flex: 1 1 auto; font-size: 14px; }
.perm-key { color: var(--ink-faint); font-size: 11.5px; display: block; margin-top: 2px; }

/* --------------------------------------------------------------- buttons */

.btn {
  display: inline-block; padding: 8px 14px;
  border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  background: #fff; color: var(--ink);
  font: inherit; font-size: 13.5px; font-weight: 600;
  cursor: pointer; text-align: center;
}
.btn:hover { border-color: var(--ink-faint); text-decoration: none; }
.btn-primary { background: var(--brand); border-color: var(--brand); color: #fff; }
.btn-primary:hover { background: var(--brand-dark); border-color: var(--brand-dark); }
.btn-danger { background: #fff; border-color: var(--bad); color: var(--bad); }
.btn-danger:hover { background: var(--bad); color: #fff; }
.btn-quiet { background: transparent; border-color: transparent; color: var(--ink-soft); }
.btn-quiet:hover { background: var(--page); border-color: var(--line); }
.btn-block { display: block; width: 100%; }
.btn-small { padding: 5px 10px; font-size: 12.5px; }

/* ----------------------------------------------------------------- pills */

.pill {
  display: inline-block; padding: 2px 9px; border-radius: 99px;
  font-size: 11.5px; font-weight: 620; letter-spacing: .01em;
  background: var(--page); color: var(--ink-soft); border: 1px solid var(--line);
}
.pill-ok    { background: var(--brand-soft); color: var(--brand-dark); border-color: transparent; }
.pill-warn  { background: #fdf2e3; color: var(--warn); border-color: transparent; }
.pill-bad   { background: #fbeae7; color: var(--bad); border-color: transparent; }
.pill-quiet { background: var(--page); color: var(--ink-faint); }

/* --------------------------------------------------------------- notices */

.flash {
  padding: 11px 15px; border-radius: var(--radius-sm);
  margin-bottom: 16px; font-size: 14px; border-left: 3px solid;
}
.flash-success { background: var(--brand-soft); border-color: var(--brand); }
.flash-error   { background: #fbeae7; border-color: var(--bad); }
.flash-warn    { background: #fdf2e3; border-color: var(--warn); }
.flash-info    { background: #eef2f6; border-color: #7d93a8; }

.notice { padding: 12px 15px; border-radius: var(--radius-sm); background: var(--page); border-left: 3px solid var(--line-strong); font-size: 13.5px; margin-bottom: 14px; }
.notice-warn { background: #fdf2e3; border-color: var(--warn); }
.notice-ok   { background: var(--brand-soft); border-color: var(--brand); }
.notice-bad  { background: #fbeae7; border-color: var(--bad); }

/* ---------------------------------------------------------------- health */

.health-summary { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 4px; }
.health-item { display: flex; gap: 12px; align-items: flex-start; padding: 10px 0; border-bottom: 1px solid var(--line); }
.health-item:last-child { border-bottom: 0; }
.health-badge {
  flex: none; width: 46px; text-align: center;
  padding: 2px 0; border-radius: 99px;
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
}
.health-ok   .health-badge { background: var(--brand-soft); color: var(--brand-dark); }
.health-warn .health-badge { background: #fdf2e3; color: var(--warn); }
.health-fail .health-badge { background: #fbeae7; color: var(--bad); }
.health-skip .health-badge { background: var(--page); color: var(--ink-faint); }
.health-label { margin: 0; font-weight: 600; font-size: 14px; }
.health-detail { margin: 2px 0 0; font-size: 12.5px; color: var(--ink-soft); word-break: break-word; }
.health-fix { margin: 4px 0 0; font-size: 12.5px; color: var(--warn); }

/* ------------------------------------------------------------------ tabs */

.tabs { display: flex; gap: 4px; flex-wrap: wrap; margin-bottom: 18px; border-bottom: 1px solid var(--line); }
.tab {
  padding: 9px 14px; font-size: 13.5px; font-weight: 580;
  color: var(--ink-soft); border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.tab:hover { color: var(--ink); text-decoration: none; }
.tab.is-current { color: var(--brand-dark); border-bottom-color: var(--brand); }

/* ------------------------------------------------------- sign-in and errors */

.auth-page, .error-page {
  display: grid; place-items: center; min-height: 100vh; padding: 24px;
  background: linear-gradient(160deg, var(--sidebar) 0%, var(--sidebar) 42%, var(--page) 42%, var(--page) 100%);
}
.auth-wrap { width: 100%; max-width: 400px; }
.auth-card { background: var(--panel); border-radius: var(--radius); box-shadow: 0 12px 40px rgba(16, 31, 23, .18); padding: 28px 26px 24px; }
.auth-brand { text-align: center; margin-bottom: 20px; }
/* .brand-mark is display:grid so the initials sit dead centre inside it — but
   that makes it a block, which text-align:center cannot move. In the sidebar it
   is a flex child so it never showed; on the sign-in card it sat hard left
   under a centred title. inline-grid keeps the centring and lets the parent
   place it. */
.auth-brand .brand-mark { display: inline-grid; }
.auth-brand .auth-logo { display: inline-block; }
.auth-brand h1 { font-size: 17px; margin-top: 10px; }
.auth-logo { max-height: 54px; max-width: 190px; }
.auth-heading { font-size: 16px; margin-bottom: 6px; }
.auth-lead { color: var(--ink-soft); font-size: 13.5px; }
.auth-link { text-align: center; margin: 16px 0 0; font-size: 13.5px; }
.auth-note { color: #cfe0d6; font-size: 13px; text-align: center; margin-top: 16px; }
.auth-foot { color: var(--ink-soft); font-size: 12.5px; text-align: center; margin-top: 14px; }
.auth-card .field { max-width: none; }

.error-page { background: var(--page); }
.error-card { background: var(--panel); border-radius: var(--radius); box-shadow: var(--shadow); padding: 30px 32px; max-width: 520px; }
.error-card-wide { max-width: 760px; }
.error-code { margin: 0; font-size: 12px; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-faint); }
.error-card h1 { font-size: 21px; margin: 6px 0 12px; }
.error-detail { background: var(--page); padding: 12px; border-radius: var(--radius-sm); font-size: 12.5px; overflow-x: auto; white-space: pre-wrap; }
.error-note { font-size: 12.5px; color: var(--ink-faint); }
.error-actions { display: flex; gap: 10px; margin-top: 18px; flex-wrap: wrap; }
.error-list { margin: 14px 0; padding-left: 20px; font-size: 13.5px; color: var(--bad); }
.error-list li { margin-bottom: 6px; }

/* ------------------------------------------------------------- installer */

.install-page { background: var(--page); padding: 30px 20px; display: block; }
.install-wrap { max-width: 640px; margin: 0 auto; }
.install-step { font-size: 12px; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-faint); }

/* ------------------------------------------------------------- responsive */

/* ============================================================================
   THE SIDEBAR BREAKPOINT, corrected.

   It used to vanish below 900px, and 900 is far too high. A perfectly ordinary
   1366-wide laptop at Windows 150% scaling reports about 910 CSS pixels; nudge
   the browser zoom one step and the menu disappears on a desktop machine with
   no obvious way back. That reads as "the sidebar is broken", and fairly.

   Two changes:

     * Off-canvas now starts at 760px — phones and small tablets, where it is
       genuinely the right answer.

     * Between 760 and 1120 the sidebar becomes a NARROW RAIL of icons instead
       of disappearing. The navigation stays reachable, the labels go, and the
       main content gets the width back. Hovering or focusing the rail widens
       it again, so nobody has to memorise the icons.
   ========================================================================== */

@media (min-width: 761px) and (max-width: 1120px) {
  .sidebar {
    width: 68px;
    flex: 0 0 68px;
    overflow: visible;
    transition: width .15s ease, flex-basis .15s ease;
  }
  .sidebar:hover, .sidebar:focus-within {
    width: var(--sidebar-w);
    flex-basis: var(--sidebar-w);
    z-index: 30;
    box-shadow: 0 0 30px rgba(0, 0, 0, .22);
  }
  /* Everything that is only words collapses; the icons stay. */
  .sidebar .brand-name,
  .sidebar .nav-group,
  .sidebar .nav-later,
  .sidebar .nav-link > span { display: none; }
  .sidebar:hover .brand-name,
  .sidebar:focus-within .brand-name,
  .sidebar:hover .nav-group,
  .sidebar:focus-within .nav-group,
  .sidebar:hover .nav-later,
  .sidebar:focus-within .nav-later,
  .sidebar:hover .nav-link > span,
  .sidebar:focus-within .nav-link > span { display: block; }
  .sidebar .nav-link { justify-content: center; }
  .sidebar:hover .nav-link,
  .sidebar:focus-within .nav-link { justify-content: flex-start; }
}

@media (max-width: 760px) {
  .sidebar {
    position: fixed; left: 0; top: 0; z-index: 40;
    transform: translateX(-100%); transition: transform .18s ease;
    box-shadow: 0 0 40px rgba(0, 0, 0, .3);
  }
  body.menu-open .sidebar { transform: translateX(0); }
  .menu-toggle { display: inline-flex; }
  /* The way back in. The top bar is sticky, so it is always on screen. */
  .content { padding: 18px 16px 30px; }
  .topbar { padding: 12px 16px; }
  .who { display: none; }
  .card-head .btn { position: static; display: inline-block; margin-top: 10px; }
  .blank-where { max-width: none; text-align: left; }
  .waiting-list li, .blank-list li { flex-direction: column; gap: 4px; }
}

@media print {
  .sidebar, .topbar, .app-foot, .btn, .filters, .tabs { display: none !important; }
  .card { box-shadow: none; border-color: #ccc; break-inside: avoid; }
  body { background: #fff; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

/* ------------------------------------------------------- phase 1: profiles */

.profile-head { display: flex; gap: 22px; align-items: flex-start; flex-wrap: wrap; }
.profile-photo { flex: 0 0 130px; text-align: center; }
.profile-photo .photo {
  width: 130px; height: 160px; object-fit: cover;
  border-radius: var(--radius-sm); border: 1px solid var(--line); background: var(--page);
}
.photo-form { margin-top: 10px; }
.photo-form input[type=file] { font-size: 11.5px; margin-bottom: 6px; }

.facts { flex: 1 1 320px; display: grid; grid-template-columns: minmax(130px, auto) 1fr; gap: 8px 18px; margin: 0; }
.facts dt { font-size: 12px; text-transform: uppercase; letter-spacing: .04em; color: var(--ink-faint); font-weight: 620; padding-top: 2px; }
.facts dd { margin: 0; font-size: 14px; }
.facts dd p { margin: 2px 0 0; }

@media (max-width: 620px) {
  .facts { grid-template-columns: 1fr; gap: 2px 0; }
  .facts dt { margin-top: 10px; }
  .profile-photo { flex: 1 1 100%; text-align: left; }
}

/* --------------------------------------------------------- phase 2: register */

.table-register td, .table-register th { padding: 7px 8px; }
.table-register input[type=radio] { width: 18px; height: 18px; }
.table-register input[type=text] { min-width: 140px; padding: 6px 9px; font-size: 13px; }
.table-register tbody tr:hover { background: var(--brand-soft); }
.table-register td.c { min-width: 62px; }

/* ============================================================================
   MODERN CONTROLS — the date picker and the select.

   Every rule below only bites once JavaScript has added `.is-ready`. Until then
   the native <input type="date"> and <select> are visible and fully working, so
   a browser that never runs app.js loses the styling and nothing else.
   ============================================================================ */

.dp, .ss { position: relative; }

.dp.is-ready .dp-native,
.ss.is-ready .ss-native {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%);
  white-space: nowrap; border: 0;
}

.dp-button, .ss-button {
  display: none;
  width: 100%;
  align-items: center; justify-content: space-between; gap: 10px;
  padding: 9px 11px;
  border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  background: #fff; color: var(--ink);
  font: inherit; font-size: 14px; text-align: left;
  cursor: pointer;
}
.dp.is-ready .dp-button, .ss.is-ready .ss-button { display: flex; }
.dp-button:hover, .ss-button:hover { border-color: var(--ink-faint); }
.dp.is-open .dp-button, .ss.is-open .ss-button { border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-soft); }
.dp.is-empty .dp-value, .ss.is-empty .ss-value { color: var(--ink-faint); }
.dp-icon, .ss-caret { color: var(--ink-faint); display: flex; flex: none; }
.ss-button:disabled { background: var(--page); color: var(--ink-faint); cursor: not-allowed; }
.ss-value { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.dp-panel, .ss-panel {
  position: absolute; z-index: 60; top: calc(100% + 5px); left: 0;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: 0 12px 34px rgba(16, 31, 23, .16);
  padding: 12px;
}

/* ------------------------------------------------------------ date picker */

.dp-panel { width: 286px; }

.dp-head { display: flex; align-items: center; gap: 6px; margin-bottom: 10px; }
.dp-nav {
  flex: none; width: 30px; height: 30px;
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: #fff; color: var(--ink); font-size: 17px; line-height: 1; cursor: pointer;
}
.dp-nav:hover { background: var(--page); }
.dp-select {
  flex: 1 1 auto; width: auto;
  padding: 6px 7px; font-size: 13px;
  border: 1px solid var(--line); border-radius: var(--radius-sm); background: #fff;
}

.dp-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.dp-dow {
  text-align: center; font-size: 10.5px; font-weight: 700;
  color: var(--ink-faint); text-transform: uppercase; padding-bottom: 4px;
}
.dp-pad { height: 34px; }
.dp-day {
  height: 34px; border: 0; border-radius: var(--radius-sm);
  background: transparent; color: var(--ink);
  font: inherit; font-size: 13.5px; cursor: pointer;
}
.dp-day:hover:not(:disabled) { background: var(--brand-soft); }
.dp-day.is-today { box-shadow: inset 0 0 0 1px var(--line-strong); font-weight: 700; }
.dp-day.is-chosen { background: var(--brand); color: #fff; font-weight: 700; }
.dp-day:disabled { color: var(--line-strong); cursor: not-allowed; }

.dp-foot {
  display: flex; gap: 8px; justify-content: flex-end;
  margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line);
}
.dp-link {
  border: 0; background: none; color: var(--brand-dark);
  font: inherit; font-size: 13px; font-weight: 620; cursor: pointer; padding: 3px 6px;
  border-radius: var(--radius-sm);
}
.dp-link:hover { background: var(--brand-soft); }

/* ---------------------------------------------------------------- select */

.ss-panel { width: 100%; min-width: 220px; max-width: 420px; padding: 8px; }
.ss-search {
  width: 100%; margin-bottom: 6px;
  padding: 8px 10px; font-size: 13.5px;
  border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
}
.ss-list { max-height: 260px; overflow-y: auto; }
.ss-group {
  margin: 8px 6px 3px; font-size: 10.5px; font-weight: 700;
  letter-spacing: .07em; text-transform: uppercase; color: var(--ink-faint);
}
.ss-option {
  display: block; width: 100%; text-align: left;
  padding: 8px 10px; border: 0; border-radius: var(--radius-sm);
  background: transparent; color: var(--ink);
  font: inherit; font-size: 14px; cursor: pointer;
}
.ss-option:hover:not(:disabled), .ss-option:focus { background: var(--brand-soft); }
.ss-option.is-chosen { background: var(--brand); color: #fff; font-weight: 600; }
.ss-option:disabled { color: var(--ink-faint); cursor: not-allowed; }
.ss-empty { padding: 14px 10px; margin: 0; text-align: center; color: var(--ink-faint); font-size: 13px; }

/* In a filter bar the controls sit side by side and must not stretch. */
.filters .dp, .filters .ss { display: inline-block; min-width: 175px; }
.filters .ss-panel { min-width: 200px; }

/* The panel would be cut off by a scrolling table wrapper. */
.table-scroll { overflow-x: auto; overflow-y: visible; }

@media (max-width: 620px) {
  .dp-panel { width: min(286px, calc(100vw - 48px)); }
  .filters .dp, .filters .ss { display: block; width: 100%; }
}

.dp.is-missing .dp-button, .ss.is-missing .ss-button { border-color: var(--bad); }
.field-required-note { margin-top: 5px; }

/* --------------------------------------------- phase 4: messages and consent */

.message-body {
  padding: 16px 18px;
  background: var(--page);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  font-size: 14.5px; line-height: 1.6;
  max-width: 72ch;
}
.message-body p:last-child { margin-bottom: 0; }
.message-body h1, .message-body h2, .message-body h3 { font-size: 16px; margin: 14px 0 6px; }
.message-body ul, .message-body ol { padding-left: 22px; }

.consent-wording { margin-bottom: 20px; background: #fff; max-width: none; }
.auth-card .form .field { max-width: none; }

/* ============================================================== the portal
   A separate shell rather than the staff layout with things hidden — a parent
   should never be one CSS rule away from a menu of school administration.     */

body.portal { background: var(--page); }

.portal-top { background: var(--panel); border-bottom: 1px solid var(--line); }
.portal-top-inner {
  max-width: 980px; margin: 0 auto;
  display: flex; align-items: center; gap: 18px; flex-wrap: wrap;
  padding: 14px 20px;
}
.portal-brand { display: flex; align-items: center; gap: 10px; font-weight: 650; color: var(--ink); font-size: 15px; }
.portal-brand:hover { text-decoration: none; }
.portal-logo { max-height: 34px; max-width: 120px; }
.portal-nav { display: flex; gap: 4px; flex-wrap: wrap; flex: 1 1 auto; }
.portal-link {
  padding: 7px 12px; border-radius: 99px;
  font-size: 14px; font-weight: 560; color: var(--ink-soft);
}
.portal-link:hover { background: var(--page); text-decoration: none; color: var(--ink); }
.portal-link.is-current { background: var(--brand); color: #fff; }
.portal-account { display: flex; align-items: center; gap: 8px; }

.portal-main { max-width: 980px; margin: 0 auto; padding: 22px 20px 34px; }
.portal-heading { font-size: 22px; margin-bottom: 18px; }

.portal-children { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 16px; margin-bottom: 18px; }
.portal-child {
  display: flex; flex-direction: column; align-items: flex-start; gap: 6px;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow); padding: 18px 20px; color: var(--ink);
}
.portal-child:hover { border-color: var(--brand); text-decoration: none; }
.portal-child-name { font-weight: 650; font-size: 16px; }
.portal-child-meta { font-size: 13px; color: var(--ink-soft); }

.portal-foot {
  max-width: 980px; margin: 0 auto; padding: 18px 20px 30px;
  border-top: 1px solid var(--line); font-size: 13px; color: var(--ink-soft);
}

@media (max-width: 620px) {
  .portal-top-inner { padding: 12px 14px; }
  .portal-account .who-name { display: none; }
  .portal-main { padding: 16px 14px 28px; }
}

/* ============================================================================
   USING THE WIDTH.

   Every .field is capped at 560px so a text input never becomes an unreadable
   30cm line — which is right for the field and wrong for the page: on a wide
   monitor it left one narrow column of controls and a screen of nothing beside
   it. Two fixes, and neither touches a single view:

   1. The content column is capped and centred. Prose and tables past about
      1360px are harder to read, not easier, so the page stops growing and sits
      in the middle instead of drifting left.

   2. Above 1024px, fields inside a full-width card lay out in TWO COLUMNS.
      Everything that is not a field — headings, tables, notices, buttons —
      still spans the full width, so the rule can apply to every card in the
      software without any of them needing a new class.
   ========================================================================== */

.content {
  width: 100%;
  max-width: 1360px;
  margin: 0 auto;
}
.portal-main { max-width: 1100px; }

@media (min-width: 1024px) {

  /* Pattern A: <form class="form"><section class="card"><div class="field">  */
  .card { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 26px; align-content: start; }
  /* min-width:0 matters: without it a wide table inside a grid item refuses to
     shrink and pushes the whole card past the window. */
  .card > * { grid-column: 1 / -1; min-width: 0; }
  .card > .field { grid-column: auto; max-width: none; }

  /* Pattern B: <section class="card"><form class="form"><div class="field">  */
  .card > .form:not(.form-inline):not(.form-narrow) {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 26px; align-content: start;
  }
  .card > .form > * { grid-column: 1 / -1; min-width: 0; }
  .card > .form > .field { grid-column: auto; max-width: none; }

  /* Things that need the whole row whatever else is true. */
  .card > .field:has(textarea),
  .card > .form > .field:has(textarea),
  .card > .field:has(.switch),
  .card > .form > .field:has(.switch),
  .card > .field.field-full,
  .card > .form > .field.field-full { grid-column: 1 / -1; }

  .card > .field:has(textarea) textarea { max-width: 860px; }

  /* Help text is prose. It wraps at a readable measure rather than running the
     full width of a two-column card. */
  .field-help, .field-where { max-width: 62ch; }

  /* A card that is already sharing the row with another one is narrow enough.
     Two columns of fields inside half a screen is worse than one. */
  .grid-2 .card, .grid-2 .card > .form { display: block; }
  .grid-2 .card > .field, .grid-2 .card > .form > .field { max-width: 560px; }

  /* KPI cards hold no fields; keep them as they were. */
  .kpi { display: block; }
}

/* A browser without :has() gets one column of fields rather than a broken
   layout — the same as before this rule existed. */
@supports not (selector(:has(*))) {
  @media (min-width: 1024px) {
    .card, .card > .form { display: block; }
    .card > .field, .card > .form > .field { max-width: 560px; }
  }
}

/* The child's portal reuses the parent shell, with one difference: a wider
   reading measure for instructions, because homework text is prose. */
body.learn .portal-main { max-width: 900px; }
body.learn .portal-heading { font-size: 24px; }

/* A heading inside a settings form. Separates one transport's boxes from
   another's, which is the whole point of sectioning the tab. */
.field-section {
  margin: 22px 0 2px;
  padding-top: 16px;
  border-top: 1px solid var(--line);
  font-size: 13px;
  font-weight: 650;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.field-section:first-of-type { border-top: 0; padding-top: 0; }

/* ============================================================================
   THE DASHBOARD, as the mockup draws it.

   Every chart on it is hand-drawn SVG — polylines for the sparklines and the
   attendance line, stroke-dasharray for the donut, plain divs for the bars. No
   chart library and no build step, because the target is a cPanel account with
   no Node on it.
   ========================================================================== */

:root {
  --violet: #7c5cff;
  --blue:   #2f80ed;
  --amber:  #f2a03d;
  --red:    #e05252;
}

/* ------------------------------------------------------------- KPI strip */
.kpi-strip {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 16px;
  margin-bottom: 18px;
}
.kpi-tile { display: block; padding: 18px 20px 12px; position: relative; }
.kpi-tile.is-attention { border-color: var(--warn); }
.kpi-icon {
  display: inline-grid; place-items: center;
  width: 40px; height: 40px; border-radius: 12px; margin-bottom: 12px;
}
.kpi-icon svg { width: 21px; height: 21px; }
.kpi-icon-violet { background: rgba(124, 92, 255, .12); color: var(--violet); }
.kpi-icon-blue   { background: rgba(47, 128, 237, .12); color: var(--blue); }
.kpi-icon-green  { background: rgba(31, 157, 85, .12);  color: var(--brand); }
.kpi-icon-amber  { background: rgba(242, 160, 61, .16); color: var(--amber); }
.kpi-icon-red    { background: rgba(224, 82, 82, .12);  color: var(--red); }
.kpi-tile-label { font-size: 13px; color: var(--ink-soft); margin: 0 0 2px; }
.kpi-tile-value { font-size: 27px; font-weight: 680; line-height: 1.15; margin: 0; }
.kpi-tile-note  { font-size: 12.5px; color: var(--ink-soft); margin: 4px 0 0; }
.kpi-tile-note .up   { color: var(--brand); font-weight: 620; }
.kpi-tile-note .down { color: var(--red); font-weight: 620; }
.kpi-spark { margin: 10px -20px -12px; opacity: .85; }
.kpi-spark svg { width: 100%; height: 40px; display: block; }

/* ------------------------------------------------------------ the panels */
.dash-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 16px;
  align-items: start;
}
.dash-grid > .card { display: block; }          /* the two-column field rule is for forms */
@media (min-width: 1100px) {
  .dash-grid { grid-template-columns: 2fr 1fr; }
  .dash-wide { grid-column: 1 / -1; }
}

.mini-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 12px; margin-top: 14px; }
.mini-tile { background: var(--page); border: 1px solid var(--line); border-radius: 10px; padding: 12px 14px; }
.mini-tile.mini-good { border-color: rgba(31, 157, 85, .4); }
.mini-tile.mini-bad  { border-color: rgba(224, 82, 82, .4); }
.mini-label { font-size: 12px; color: var(--ink-soft); margin: 0; }
.mini-value { font-size: 19px; font-weight: 660; margin: 2px 0 0; }

.donut-wrap { display: flex; gap: 20px; align-items: center; flex-wrap: wrap; }
.donut-key { display: grid; grid-template-columns: auto auto; gap: 6px 16px; margin: 0; font-size: 13.5px; }
.donut-key dt { color: var(--ink-soft); display: flex; align-items: center; gap: 8px; }
.donut-key dd { margin: 0; font-weight: 640; text-align: right; }
.key-dot { width: 9px; height: 9px; border-radius: 50%; display: inline-block; }
.key-dot-brand { background: var(--brand); }
.key-dot-line  { background: var(--line); }
.key-dot-quiet { background: var(--ink-soft); opacity: .5; }

.bar-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 9px; }
.bar-list li { display: grid; grid-template-columns: 84px 1fr auto; align-items: center; gap: 12px; font-size: 13.5px; }
.bar-label { color: var(--ink-soft); }
.bar-track { background: var(--page); border-radius: 99px; height: 9px; overflow: hidden; }
.bar-fill  { display: block; height: 100%; background: var(--brand); border-radius: 99px; }
.bar-value { font-weight: 620; font-variant-numeric: tabular-nums; }
.bar-list-months li { grid-template-columns: 44px 1fr auto; }

.person-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }
.person-list li { display: grid; grid-template-columns: 36px 1fr auto; align-items: center; gap: 12px; }
.person-photo { width: 36px; height: 36px; border-radius: 50%; object-fit: cover; }
.person-name { display: grid; font-size: 14px; }
.person-sub  { font-size: 12px; color: var(--ink-soft); }
.person-value { font-weight: 660; font-variant-numeric: tabular-nums; }

/* -------------------------------------------------------------- top bar */
/* THE CLASS THE LABEL WAS RELYING ON, WHICH WAS NEVER WRITTEN.
   "Search" was sitting on top of the magnifier in the top bar because .sr-only
   did nothing. A label a screen reader needs still has to leave the screen. */
.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;
}

.topbar-search { flex: 1 1 260px; max-width: 420px; position: relative; display: flex; align-items: center; }
.topbar-search svg { position: absolute; left: 12px; width: 17px; height: 17px; color: var(--ink-soft); pointer-events: none; }
.topbar-search input {
  width: 100%; padding: 9px 12px 9px 36px;
  border: 1px solid var(--line); border-radius: 99px; background: var(--page); font-size: 14px;
}
.topbar-search input:focus { outline: 2px solid var(--brand); outline-offset: 1px; background: var(--panel); }

.topbar-year { display: grid; line-height: 1.2; font-size: 13px; text-align: right; }
.topbar-year-label { font-size: 11px; color: var(--ink-soft); }

.bell { position: relative; display: inline-grid; place-items: center; width: 36px; height: 36px; border-radius: 10px; color: var(--ink-soft); }
.bell:hover { background: var(--page); color: var(--ink); }
.bell svg { width: 20px; height: 20px; }
.bell-count {
  position: absolute; top: 1px; right: 1px; min-width: 17px; height: 17px;
  background: var(--red); color: #fff; border-radius: 99px;
  font-size: 10.5px; font-weight: 700; display: grid; place-items: center; padding: 0 4px;
}
.bell-count-quiet { background: var(--ink-soft); }

.who-link { display: flex; align-items: center; gap: 10px; color: var(--ink); }
.who-link:hover { text-decoration: none; }

@media (max-width: 760px) {
  .topbar-search { order: 3; flex-basis: 100%; max-width: none; }
  .topbar-year { display: none; }
}

/* The line left behind when the setup checklist is put away. Quiet, but the
   number stays on screen — a reminder that hides itself completely is not one. */
.setup-strip {
  display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap;
  background: var(--panel); border: 1px solid var(--line); border-left: 3px solid var(--warn);
  border-radius: var(--radius); padding: 10px 16px; margin-bottom: 16px;
  font-size: 13.5px; color: var(--ink-soft);
}
.setup-strip strong { color: var(--ink); }
.setup-foot { display: flex; align-items: flex-start; gap: 14px; flex-wrap: wrap; margin-top: 16px;
              padding-top: 14px; border-top: 1px solid var(--line); }
.setup-foot p { flex: 1 1 320px; font-size: 12.5px; margin: 0; }

/* The figure printed above each point on the attendance line. Reading a
   percentage off a gridline is guesswork. */
.axis-value { font-size: 11px; font-weight: 650; fill: var(--ink); }

/* The dashboard's opening line, and the date chip in the top bar. */
.dash-welcome { margin-bottom: 18px; }
.dash-welcome h1 { font-size: 22px; margin: 0 0 2px; }
.dash-welcome p { margin: 0; font-size: 14px; }

.topbar-when { display: flex; align-items: center; gap: 9px; font-size: 13px; line-height: 1.25; }
.topbar-when svg { width: 20px; height: 20px; color: var(--ink-soft); }
.topbar-when strong { display: block; }

/* Quick actions as icon tiles, the way the mockup draws them: a square, an
   icon in a circle, one short label under it. */
.quick-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(132px, 1fr)); gap: 12px; }
.quick {
  display: grid; justify-items: center; gap: 9px;
  background: var(--page); border: 1px solid var(--line); border-radius: 12px;
  padding: 18px 12px; text-align: center; color: var(--ink);
}
.quick:hover { border-color: var(--brand); background: var(--panel); text-decoration: none; }
.quick-icon {
  display: grid; place-items: center; width: 42px; height: 42px;
  border-radius: 50%; background: var(--panel); border: 1px solid var(--line); color: var(--brand);
}
.quick:hover .quick-icon { background: var(--brand); color: #fff; border-color: var(--brand); }
.quick-icon svg { width: 20px; height: 20px; }
.quick-label { font-size: 13.5px; font-weight: 600; line-height: 1.3; }

/* The band under the attendance line. Carries no extra information; makes the
   shape readable at a glance, which on a dashboard is the job. */
.linechart-fill { fill: var(--brand); opacity: .10; }

/* ------------------------------------------------- the activity panel
   Icon, sentence, time. The audit log keeps the machine-readable key; a head
   teacher reading the dashboard gets the sentence. */
.activity { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.activity li {
  display: grid; grid-template-columns: 34px 1fr auto; align-items: center; gap: 12px;
  padding: 9px 0; border-bottom: 1px solid var(--line);
}
.activity li:last-child { border-bottom: 0; }
.activity-icon { display: grid; place-items: center; width: 34px; height: 34px; border-radius: 9px; }
.activity-icon svg { width: 17px; height: 17px; }
.activity-quiet { background: var(--page); color: var(--ink-soft); }
.activity-good  { background: rgba(31, 157, 85, .12); color: var(--brand); }
.activity-warn  { background: rgba(242, 160, 61, .16); color: var(--amber); }
.activity-bad   { background: rgba(224, 82, 82, .12); color: var(--red); }
.activity-text { display: grid; font-size: 13.5px; line-height: 1.35; min-width: 0; }
.activity-text strong { font-weight: 600; }
.activity-text .muted { font-size: 12px; }
.activity-when { font-size: 12px; color: var(--ink-soft); white-space: nowrap; }

/* The amount a family owes reads as the number that needs doing something about. */
.person-owing { color: var(--red); }

/* The pastel behind a quick-action icon, borrowed from the KPI tiles. */
.quick-icon.kpi-icon-violet, .quick-icon.kpi-icon-blue, .quick-icon.kpi-icon-green,
.quick-icon.kpi-icon-amber, .quick-icon.kpi-icon-red { border: 0; }
.quick:hover .quick-icon { background: var(--brand); color: #fff; }

/* ============================================================================
   PHASE 12 — THE DASHBOARD REDESIGN (v3.6.0)
   ----------------------------------------------------------------------------
   Everything here is scoped under .dashx, the wrapper the dashboard view puts
   around itself, so restyling the first screen cannot move a pixel on any
   other page. Later rules of equal specificity win, which is why this section
   sits at the END of the file — it overrides the older dashboard styles above
   without editing them, and the diff between versions stays readable.
   ========================================================================== */

/* Cards: softer, rounder, closer to the mockup's white tiles. */
.dashx .card {
  border-radius: 14px;
  border-color: #e7eeea;
  box-shadow: 0 1px 2px rgba(16, 31, 23, .04), 0 10px 26px rgba(16, 31, 23, .05);
}

/* A quiet caption where the mockup draws a dropdown ("This Week", "This
   Month"). A select that changes nothing would be a control that lies, so it
   is a label — the range it names is the range the card actually shows. */
.dashx .card-tools { position: absolute; right: 0; top: -2px; display: flex; align-items: center; gap: 10px; }
.dashx .card-tools .btn { position: static; }
.dashx .card-when {
  font-size: 12.5px; color: var(--ink-soft);
  background: var(--page); border: 1px solid var(--line);
  border-radius: 8px; padding: 4px 10px; white-space: nowrap;
}

/* ------------------------------------------------------------ the KPI row */
.dashx .kpi-strip {
  grid-template-columns: repeat(auto-fit, minmax(205px, 1fr));
  gap: 14px;
}
.dashx .kpi-tile { padding: 16px 18px 10px; overflow: hidden; }
.dashx .kpi-head { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.dashx .kpi-icon { width: 42px; height: 42px; border-radius: 50%; margin-bottom: 0; flex: 0 0 auto; }
.dashx .kpi-icon svg { width: 20px; height: 20px; }
.dashx .kpi-tile-label { font-size: 13px; font-weight: 560; color: var(--ink-soft); margin: 0; line-height: 1.3; }
.dashx .kpi-when { font-weight: 400; color: var(--ink-faint); }
.dashx .kpi-tile-value { font-size: 27px; font-weight: 700; letter-spacing: -.01em; }
.dashx .kpi-spark { margin: 10px -18px -10px; }

/* -------------------------------------------------------------- the bands */
.dashx .dash-band {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 16px;
  align-items: start;
  margin-bottom: 16px;
}
.dashx .dash-band > .card { display: block; margin-bottom: 0; }

/* Band A on a wide screen: attendance carries the row; the donut and the feed
   share the rest — the mockup's proportions, near enough. */
@media (min-width: 1240px) {
  .dashx .band-a { grid-template-columns: minmax(0, 1.9fr) minmax(0, 1.25fr) minmax(0, 1.15fr); }
}
@media (min-width: 860px) and (max-width: 1239.98px) {
  .dashx .band-a { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .dashx .band-a-wide { grid-column: 1 / -1; }
}

/* Band B: four across on a wide screen, two in the middle, one on a phone. */
@media (min-width: 1240px) {
  .dashx .band-b { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
@media (min-width: 760px) and (max-width: 1239.98px) {
  .dashx .band-b { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ------------------------------------- attendance mini tiles, now tinted */
.dashx .mini-tiles { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); }
.dashx .mini-tile { border-radius: 12px; }
.dashx .mini-tile.mini-good { background: #effaf3; border-color: #d4eddd; }
.dashx .mini-tile.mini-good .mini-value { color: var(--brand-dark); }
.dashx .mini-tile.mini-bad  { background: #fdf1ef; border-color: #f3d8d3; }
.dashx .mini-tile.mini-bad  .mini-value { color: var(--bad); }

/* --------------------------------------------------- fee collection card */
.dashx .donut-stack { display: flex; flex-direction: column; align-items: center; gap: 16px; }
.dashx .donut-stack .donut-key { width: 100%; grid-template-columns: 1fr auto; }
.dashx .key-dot-pending { background: #9db7e8; }
.dashx .donut-target {
  display: flex; align-items: center; gap: 9px;
  margin: 14px 0 0; padding: 10px 12px;
  background: #effaf3; border: 1px solid #d4eddd; border-radius: 10px;
  color: #14532d; font-size: 13px; font-weight: 600; line-height: 1.35;
}
.dashx .donut-target svg { width: 18px; height: 18px; flex: 0 0 auto; color: var(--brand); }

/* -------------------------------------------------- recent activity feed */
.dashx .activity li { grid-template-columns: 38px 1fr auto; padding: 10px 0; }
.dashx .activity-icon { width: 38px; height: 38px; border-radius: 11px; }
.dashx .activity-icon svg { width: 18px; height: 18px; }

/* -------------------------------------------- strength-by-class bars */
.dashx .bar-list { gap: 11px; }
.dashx .bar-track { height: 10px; }
.dashx .bar-fill { background: linear-gradient(90deg, var(--brand), #35b56d); }

/* --------------------------------- monthly collection as VERTICAL bars.
   Plain divs: no chart library, prints fine, scales with the card. The
   compact figure sits on top of each bar; the full amount is the tooltip. */
.dashx .vbars {
  display: flex; align-items: flex-end; gap: 8px;
  height: 190px; padding-top: 18px;
}
.dashx .vbar-col {
  flex: 1 1 0; min-width: 0; height: 100%;
  display: flex; flex-direction: column; align-items: center; justify-content: flex-end;
  gap: 5px;
}
.dashx .vbar-amount {
  font-size: 10.5px; font-weight: 620; color: var(--ink-soft);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.dashx .vbar-track {
  width: 100%; max-width: 30px; flex: 1 1 auto; min-height: 0;
  display: flex; flex-direction: column; justify-content: flex-end;
  background: var(--page); border-radius: 7px; overflow: hidden;
}
.dashx .vbar-fill {
  display: block; width: 100%;
  background: linear-gradient(180deg, #35b56d, var(--brand));
  border-radius: 7px 7px 0 0;
}
.dashx .vbar-label { font-size: 11.5px; color: var(--ink-soft); }

/* ------------------------------------------------------- quick actions */
.dashx .quick-grid-sm { grid-template-columns: repeat(auto-fit, minmax(104px, 1fr)); gap: 10px; }
.dashx .quick-grid-sm .quick { padding: 14px 8px; gap: 7px; border-radius: 12px; }
.dashx .quick-grid-sm .quick-icon { width: 40px; height: 40px; }
.dashx .quick-grid-sm .quick-label { font-size: 12.5px; }

/* On a narrow phone the KPI sparkline bleed and the five-across row both
   give way: one column, everything full width, nothing clipped. */
@media (max-width: 560px) {
  .dashx .kpi-strip { grid-template-columns: 1fr; }
  .dashx .vbar-amount { display: none; }
}

/* ============================================================================
   v3.6.1 — THE NOTIFICATION BELL'S PANEL
   ----------------------------------------------------------------------------
   A <details> element, so it needs no JavaScript to open or close; app.js
   only adds closing it when you click elsewhere or press Escape.
   ========================================================================== */
.bell-menu { position: relative; display: inline-block; }
.bell-menu > summary { list-style: none; cursor: pointer; }
.bell-menu > summary::-webkit-details-marker { display: none; }
.bell-menu[open] > summary.bell { background: var(--page); color: var(--ink); }

.bell-panel {
  position: absolute; right: 0; top: calc(100% + 10px);
  width: min(360px, calc(100vw - 24px));
  background: var(--panel); border: 1px solid var(--line);
  border-radius: 14px;
  box-shadow: 0 4px 10px rgba(16, 31, 23, .08), 0 18px 46px rgba(16, 31, 23, .14);
  z-index: 60;
  overflow: hidden;
}
.bell-panel-head { padding: 13px 16px 11px; border-bottom: 1px solid var(--line); }
.bell-panel-head strong { display: block; font-size: 14px; }
.bell-panel-head .muted { display: block; font-size: 12px; line-height: 1.35; margin-top: 2px; }
.bell-panel-empty { margin: 0; padding: 22px 16px; font-size: 13.5px; color: var(--ink-soft); text-align: center; }

.notice-list { list-style: none; margin: 0; padding: 4px 6px; max-height: 380px; overflow: auto; }
.notice-list li + li { border-top: 1px solid var(--line); }
.notice-list a {
  display: grid; grid-template-columns: 38px 1fr 16px; align-items: center; gap: 12px;
  padding: 11px 10px; border-radius: 10px; color: var(--ink);
}
.notice-list a:hover { background: var(--page); text-decoration: none; }
.notice-text { display: grid; font-size: 13.5px; line-height: 1.35; min-width: 0; }
.notice-text strong { font-weight: 600; }
.notice-text .muted { font-size: 12px; }
.notice-go { color: var(--ink-faint); }
.notice-go svg { width: 15px; height: 15px; display: block; }

.bell-panel-foot {
  display: block; padding: 11px 16px; border-top: 1px solid var(--line);
  font-size: 13px; font-weight: 600; color: var(--brand-dark); text-align: center;
  background: var(--page);
}
.bell-panel-foot:hover { text-decoration: none; background: var(--brand-soft); }

/* On a phone the panel hugs the screen edge rather than the bell. */
@media (max-width: 480px) {
  .bell-menu { position: static; }
  .bell-panel { right: 12px; left: 12px; width: auto; }
}

/* ============================================================================
   v3.7.0 — COURSES AND LESSONS (Phase 13)
   ========================================================================== */

/* The child's course cards. */
.course-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 14px; }
.course-card { display: block; color: var(--ink); padding: 16px 18px; }
.course-card:hover { text-decoration: none; border-color: var(--brand); }
.course-card-subject { font-size: 11.5px; font-weight: 650; letter-spacing: .06em; text-transform: uppercase; color: var(--brand-dark); margin: 0 0 4px; }
.course-card-title { font-size: 16.5px; margin: 0 0 6px; line-height: 1.3; }
.course-progress { display: block; height: 7px; border-radius: 4px; background: var(--page); margin-top: 10px; overflow: hidden; }
.course-progress-fill { display: block; height: 100%; border-radius: 4px; background: linear-gradient(90deg, var(--brand), #35b56d); }
.course-card-done { font-size: 12px; color: var(--ink-soft); margin: 6px 0 0; }

/* The lesson list, with ticks and locks. */
.lesson-list { list-style: none; margin: 0; padding: 0; }
.lesson-list li { display: grid; grid-template-columns: 30px 1fr auto; align-items: center; gap: 12px; padding: 11px 0; }
.lesson-list li + li { border-top: 1px solid var(--line); }
.lesson-tick {
  width: 26px; height: 26px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1.6px solid var(--line); color: var(--ink-faint);
  font-size: 13px; font-weight: 700;
}
.lesson-list li.is-done .lesson-tick { background: var(--brand); border-color: var(--brand); color: #fff; }
.lesson-list li.is-locked { opacity: .55; }
.lesson-name { display: grid; min-width: 0; }
.lesson-kind { font-size: 12px; }

/* The player. A 16:9 box the iframe fills; nothing else is allowed in a
   frame by the Content-Security-Policy. */
.video-frame { position: relative; aspect-ratio: 16 / 9; border-radius: 12px; overflow: hidden; background: #0b1512; }
.video-frame iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.lesson-body { max-width: 70ch; line-height: 1.65; }
.lesson-body img { max-width: 100%; height: auto; }

/* The little rename/reorder form on the course manage page. */
.unit-rename { display: inline-flex; gap: 6px; align-items: center; }
.unit-rename input[type="text"] { width: 200px; }
.unit-rename input[type="number"] { width: 70px; }
tr.row-quiet { opacity: .55; }

/* ============================================================================
   v3.8.0 — QUIZZES, GRADEBOOK, CERTIFICATES, TIMETABLE (Phase 14)
   ========================================================================== */

/* Quiz building and sitting. */
.quiz-question-list > li, .quiz-sit > li, .quiz-review > li { margin: 0 0 18px; }
.quiz-q-prompt { font-weight: 600; margin: 0 0 8px; }
.quiz-q-options { list-style: none; margin: 0; padding: 0; }
.quiz-q-options li { padding: 3px 0 3px 14px; color: var(--ink-soft); }
.quiz-q-options li.is-right { color: var(--brand-dark); font-weight: 600; }
.quiz-option-row { display: flex; gap: 10px; align-items: center; }
.quiz-option-row input[type="text"] { flex: 1; }
.quiz-option-correct { display: inline-flex; gap: 5px; align-items: center; font-size: 12.5px; color: var(--ink-soft); white-space: nowrap; }
.quiz-choice { display: flex; gap: 10px; align-items: flex-start; padding: 9px 12px; border: 1px solid var(--line); border-radius: 10px; margin: 0 0 8px; cursor: pointer; }
.quiz-choice:hover { border-color: var(--brand); }
.quiz-review li.is-right .quiz-q-prompt { color: var(--brand-dark); }
.quiz-review li.is-wrong .quiz-q-prompt { color: var(--bad); }

/* The gradebook matrix. */
.table-scroll { overflow-x: auto; }
.gradebook-table th, .gradebook-table td { white-space: nowrap; }
.mark-input { width: 90px; text-align: right; }

/* The timetable grid: six day columns, wrapping on narrow screens. */
.timetable-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; margin-top: 14px; }
.timetable-day-name { font-weight: 650; font-size: 13px; margin: 0 0 8px; color: var(--ink-soft); text-transform: uppercase; letter-spacing: .04em; }
.timetable-slot { border: 1px solid var(--line); border-radius: 10px; padding: 9px 11px; margin: 0 0 8px; background: var(--panel); }
.timetable-time { font-size: 12px; font-weight: 650; color: var(--brand-dark); margin: 0; font-variant-numeric: tabular-nums; }
.timetable-subject { font-weight: 600; margin: 2px 0; }
.timetable-slot .muted { font-size: 12px; margin: 0 0 4px; }
.field-pair { display: flex; gap: 8px; }

/* The certificate: a sheet on screen, and ONLY the sheet in print. */
.cert-page { max-width: 860px; margin: 0 auto; }
.cert-sheet {
  background: var(--panel); border: 3px double var(--brand);
  border-radius: 6px; padding: 56px 40px; text-align: center;
}
.cert-logo { height: 64px; margin-bottom: 10px; }
.cert-school { font-size: 15px; font-weight: 650; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-soft); margin: 0 0 22px; }
.cert-title { font-size: 34px; font-weight: 700; letter-spacing: .01em; margin: 0 0 26px; }
.cert-lead { font-size: 14px; color: var(--ink-soft); margin: 0 0 6px; }
.cert-name { font-size: 30px; font-weight: 700; margin: 0 0 18px; }
.cert-course { font-size: 21px; font-weight: 650; margin: 0 0 14px; }
.cert-final { font-size: 15px; margin: 0 0 22px; }
.cert-date { font-size: 14px; color: var(--ink-soft); margin: 0 0 30px; }
.cert-serial { font-size: 12px; color: var(--ink-faint); letter-spacing: .05em; margin: 0; }
.cert-actions { display: flex; gap: 10px; justify-content: center; margin: 18px 0; }

@media print {
  .sidebar, .topbar, .portal-top, .cert-actions, .flash, .skip-link { display: none !important; }
  .cert-page { max-width: none; }
  .cert-sheet { border-color: #1f7a4d; }
  body { background: #fff; }
}
