/* ==========================================================================
   Concept Portal — Shared Design System ("Slate mist")
   Single source of truth for design tokens and UI primitives.
   Link from every template:  <link rel="stylesheet" href="/css/design-system.css">
   Do NOT redefine these tokens inline per-page — extend here instead.
   ========================================================================== */

@import url('https://fonts.googleapis.com/css2?family=Outfit:wght@400;500;600;700;800&family=Inter:wght@400;500;600;700&display=swap');

/* ── Design tokens ───────────────────────────────────────────────────────── */
:root {
    /* Surfaces */
    --bg:#F4F6FB; --surface:#FFFFFF; --surface-2:#F8FAFC;
    --line:#E7EAF2; --line-strong:#D9DFEA;

    /* Ink. --text-3 was #94A0B4, which sits at about 2.6:1 on white -- below
       the 4.5:1 minimum, and it is used for field labels and row labels rather
       than decoration. Darkened to clear the bar without losing the muted feel. */
    --text:#0F172A; --text-2:#475569; --text-3:#64748B;

    /* Brand (indigo) */
    --brand:#4F46E5; --brand-50:#EEF0FF; --brand-100:#E0E3FF; --brand-700:#4338CA;

    /* Semantic */
    --success:#059669; --success-50:#ECFDF5; --success-200:#A7F3D0;
    --warn:#D97706;    --warn-50:#FFFBEB;    --warn-200:#FDE68A;
    --danger:#DC2626;  --danger-50:#FEF2F2;  --danger-200:#FECACA;
    --info:#2563EB;    --info-50:#EFF6FF;    --info-200:#BFDBFE;

    /* Neutral fill for progress tracks and untinted icon tiles. */
    --track:#F1F4F9;

    /* Decoration only -- sidebar group headings, inactive nav dots. This is the
       value --text-3 used to be, about 2.6:1 on white. It is below the contrast
       minimum, so it must never carry label text a user has to read; every real
       label uses --text-3. */
    --text-4:#94A0B4;

    /* Radius & elevation */
    --r:16px; --r-sm:12px; --r-xs:10px;
    --sh-1:0 1px 2px rgba(16,24,40,.05);
    --sh-2:0 8px 24px rgba(16,24,40,.07);
}

/* ── Base ────────────────────────────────────────────────────────────────── */
/* 15px rather than the browser's 16px default: the portals are dense, but 14px
   utility text on top of a 16px root was reading small on a laptop at arm's
   length. Everything sized in rem moves with this. */
body { font-family:'Outfit','Inter',sans-serif; background:var(--bg); color:var(--text); font-size:15px; line-height:1.5; }

/* Figures that can change -- balances, percentages, XP, counts -- must not
   jitter as digits swap width. Applied at the roles rather than globally so
   prose keeps proportional numerals. */
.stat-value, .kpi-value, .hero-value, .mono, td, th, .tabular { font-variant-numeric:tabular-nums; }

/* ── App shell ───────────────────────────────────────────────────────────────
   Replaces the per-page header + "Quick Action Hub" tile grid. Navigation
   becomes a persistent rail, so a page stops having to re-explain where you
   are. Only .shell-body scrolls: the sidebar and top bar are fixed panes, which
   is what keeps the roster's own scroll container from fighting the page.

   min-width is deliberate. Below ~1360px the roster's grid tracks crush into
   each other, so the shell scrolls horizontally instead of clipping. That makes
   these admin pages desktop-only -- .shell-narrow below is the warning shown to
   anyone who opens one on a phone, or at a browser zoom level that shrinks the
   viewport past the same threshold, which is the commoner way to meet it. */
.shell        { display:flex; height:100vh; height:100dvh; min-width:1360px; overflow:hidden; background:var(--bg); }
.shell-side   { width:244px; flex:0 0 244px; background:var(--surface); border-right:1px solid var(--line);
                display:flex; flex-direction:column; overflow:hidden; }
.shell-main   { flex:1; min-width:0; display:flex; flex-direction:column; overflow:hidden; }
.shell-topbar { height:64px; flex:0 0 64px; background:var(--surface); border-bottom:1px solid var(--line);
                display:flex; align-items:center; justify-content:space-between; gap:20px; padding:0 24px; }
.shell-body   { flex:1; min-height:0; overflow-y:auto; padding:20px 24px 28px; }
/* One content column for every shell page. Pages used to nest their own
   Tailwind max-width plus mx-auto wrapper in here, which capped them a second
   time at anything from 1024px down to 699px of usable width -- the console's
   pages were each a different width, several stranded mid-screen. This is the
   only cap now, and margin-inline keeps it centred once the viewport is wider
   than the cap. */
.shell-content{ max-width:1500px; margin-inline:auto; width:100%; display:flex; flex-direction:column; gap:16px; }

/* The narrow-screen warning the comment above has always promised. It did not
   exist: the selector was referenced and never written, so a head teacher who
   opened the console on a phone got a silently clipped layout and no hint that
   scrolling sideways was the intended behaviour.

   A notice, not a blocker. The pages do work below 1360px, they just need
   horizontal scrolling, and locking someone out of their own school because
   they are holding a phone is worse than letting them scroll.

   Two details that are not cosmetic. It starts at 244px, clear of the sidebar
   rail, and it is pointer-events:none. The first version spanned the full width
   and sat on top of the sidebar's logout button, so a warning about a cramped
   screen made it impossible to sign out on a cramped screen. Playwright runs at
   1280px wide, so the whole suite met this immediately -- three tests failed on
   "intercepts pointer events" before any user did. */
.shell-narrow { display:none; }
@media (max-width:1359px) {
  .shell-narrow {
    display:flex; align-items:center; gap:10px;
    position:fixed; left:244px; right:0; bottom:0; z-index:60;
    padding:10px 16px;
    background:var(--warn-50); border-top:1px solid var(--warn-200);
    font-size:12.5px; color:var(--text-2);
    pointer-events:none;
  }
}

/* Sidebar interior */
.shell-brand  { height:64px; flex:0 0 64px; border-bottom:1px solid var(--line); display:flex; align-items:center;
                gap:10px; padding:0 18px; }
.shell-nav    { flex:1; overflow-y:auto; padding:14px 12px; display:flex; flex-direction:column; gap:18px; }
.shell-group  { display:flex; flex-direction:column; gap:4px; }
.shell-grouplabel { font-size:10.5px; font-weight:700; letter-spacing:.12em; text-transform:uppercase;
                    color:var(--text-4); padding:0 10px 2px; }
.shell-user   { border-top:1px solid var(--line); padding:12px; display:flex; align-items:center; gap:10px; }

/* Page titles in the top bar */
.page-title { font-size:18px; font-weight:700; letter-spacing:-.015em; color:var(--text); }
.page-sub   { font-size:12.5px; font-weight:400; color:var(--text-3); }

/* ── Progress track ──────────────────────────────────────────────────────── */
.track     { height:8px; border-radius:999px; background:var(--track); overflow:hidden; }
.track--sm { height:6px; }
.track--xs { height:4px; }
.track > .fill { height:100%; border-radius:999px; }

/* ── Icon tile ───────────────────────────────────────────────────────────── */
.ico { border-radius:var(--r-xs); display:flex; align-items:center; justify-content:center; flex-shrink:0; font-weight:700; }
.ico--lg { width:38px; height:38px; font-size:17px; }
.ico--md { width:32px; height:32px; font-size:15px; }
.ico--sm { width:30px; height:30px; font-size:14px; }
.ico--brand   { background:var(--brand-50);   color:var(--brand); }
.ico--success { background:var(--success-50); color:var(--success); }
.ico--warn    { background:var(--warn-50);    color:var(--warn); }
.ico--danger  { background:var(--danger-50);  color:var(--danger); }
.ico--info    { background:var(--info-50);    color:var(--info); }
.ico--neutral { background:var(--track);      color:var(--text-2); }

/* ── Queue row ───────────────────────────────────────────────────────────────
   The verification pattern -- avatar, what happened, decide -- used identically
   on the teacher queue, the principal approvals, and the mobile co-sign card.
   One shape, so a teacher who learns it once has learned all three. */
.queue-row { display:grid; grid-template-columns:44px minmax(0,1fr) auto; gap:14px; align-items:center; padding:16px; }

/* ── Data table ──────────────────────────────────────────────────────────── */
.row { padding:12px 18px; border-bottom:1px solid var(--line); transition:background .12s; }
.row:last-child { border-bottom:0; }
.row:hover { background:var(--surface-2); }
.dense .row { padding:8px 18px; }
.dense .ico--sm { width:24px; height:24px; font-size:11px; }
.table-head { background:var(--surface-2); border-bottom:1px solid var(--line); padding:10px 18px;
              font-size:10.5px; font-weight:700; letter-spacing:.09em; text-transform:uppercase; color:var(--text-3); }

/* Density segmented control */
.segmented { display:inline-flex; gap:3px; padding:3px; background:var(--surface-2);
             border:1px solid var(--line-strong); border-radius:var(--r-sm); }
/* Buttons where the switch is client-side, links where each view is its own
   page -- both look and behave the same to the person using them. */
.segmented button, .segmented a { font-size:12.5px; font-weight:600; padding:7px 11px; border-radius:9px;
                    background:transparent; color:var(--text-3); border:0; cursor:pointer; transition:.15s;
                    display:inline-flex; align-items:center; }
.segmented button:hover, .segmented a:hover { color:var(--text); }
.segmented button.is-on, .segmented a.is-on { background:#fff; color:var(--text); box-shadow:0 1px 2px rgba(16,24,40,.08); }

/* ── Surfaces ────────────────────────────────────────────────────────────── */
.card { background:var(--surface); border:1px solid var(--line); border-radius:var(--r); box-shadow:var(--sh-1); }

/* A card's heading and the labels of the rows inside it were both .eyebrow, so
   "Care & Safety" and "Date of birth" rendered identically and the panel had no
   top. .card-title is the heading; .eyebrow stays the small label. */
.card-title { font-size:15px; font-weight:700; letter-spacing:-.01em; color:var(--text); }
.card-sub { font-size:13px; font-weight:400; color:var(--text-2); }
.eyebrow { font-size:11.5px; font-weight:600; letter-spacing:.06em; text-transform:uppercase; color:var(--text-3); }

/* ── Unified badge system — one shape, semantic colors ───────────────────── */
.badge { display:inline-flex; align-items:center; gap:5px; padding:3px 9px; border-radius:999px; font-size:11px; font-weight:600; line-height:1; border:1px solid transparent; }
.badge .dot { width:6px; height:6px; border-radius:50%; }
.badge--success { background:var(--success-50); color:var(--success); border-color:var(--success-200); }
.badge--info    { background:var(--info-50);    color:var(--info);    border-color:var(--info-200); }
.badge--neutral { background:var(--surface-2);  color:var(--text-2);  border-color:var(--line-strong); }
.badge--warn    { background:var(--warn-50);    color:var(--warn);    border-color:var(--warn-200); }
.badge--danger  { background:var(--danger-50);  color:var(--danger);  border-color:var(--danger-200); }
.badge--brand   { background:var(--brand-50);    color:var(--brand);   border-color:var(--brand-100); }
.badge--pink    { background:#FCE7F3;            color:#DB2777;        border-color:#FBCFE8; }

/* ── Buttons ─────────────────────────────────────────────────────────────── */
.btn { display:inline-flex; align-items:center; justify-content:center; gap:7px; font-weight:600; border-radius:var(--r-sm); transition:all .15s ease; cursor:pointer; border:1px solid transparent; }
.btn:focus-visible { outline:none; box-shadow:0 0 0 3px var(--brand-100); }
.btn-sm { padding:9px 15px; font-size:13.5px; }
.btn-xs { padding:7px 12px; font-size:12.5px; }
/* Solid buttons carry a shadow so they read as raised rather than as coloured
   rectangles, and so the primary action on a page is findable at a glance. */
.btn-primary { background:var(--brand); color:#fff; box-shadow:var(--sh-1); }
.btn-primary:hover { background:var(--brand-700); box-shadow:var(--sh-2); }
/* Was white on a white card with a pale border -- on the student profile the
   "Authorise someone" button was all but invisible against the panel behind
   it. A tint and a real border make it look like something you can press. */
.btn-secondary { background:var(--surface-2); color:var(--text); border-color:var(--line-strong); }
.btn-secondary:hover { background:var(--brand-50); color:var(--brand); border-color:var(--brand-100); }
.btn-success { background:var(--success); color:#fff; }
.btn-success:hover { background:#047857; }
/* Tinted brand action -- "Review" on a waiver row. Reads as the row's own next
   step without competing with the page's one primary button. */
.btn-brand-soft { background:var(--brand-50); color:var(--brand); border-color:var(--brand-100); }
.btn-brand-soft:hover { background:var(--brand); color:#fff; border-color:var(--brand); }
.btn-success-soft { background:var(--success-50); color:var(--success); border-color:var(--success-200); }
.btn-success-soft:hover { background:var(--success); color:#fff; }
.btn-danger { background:var(--danger); color:#fff; }
.btn-danger:hover { background:#B91C1C; }
.btn-ghost-danger { background:transparent; color:var(--text-3); border-color:transparent; }
.btn-ghost-danger:hover { background:var(--danger-50); color:var(--danger); }
.btn-reject { background:var(--surface); color:var(--text-2); border-color:var(--line-strong); }
.btn-reject:hover { background:var(--danger-50); color:var(--danger); border-color:var(--danger-200); }
.btn-security { background:var(--surface); color:var(--text); border-color:var(--line-strong); }
.btn-security:hover { border-color:var(--brand); color:var(--brand); background:var(--brand-50); }

/* ── Shape modifier: pill-radius buttons (gamified portal actions) ───────── */
.btn-pill { border-radius:999px; }

/* ── Portal action variants ──────────────────────────────────────────────────
   The parent/student portals colour-code actions (approve=emerald, reward=pink,
   message=indigo). These inherit the shared .btn base — one shape, focus-ring,
   and transition — while preserving that semantic colour system. Use with .btn
   (and usually .btn-pill .btn-xs). */
.btn-emerald { background:#059669; color:#fff; }
.btn-emerald:hover { background:#047857; }
.btn-pink { background:#DB2777; color:#fff; }
.btn-pink:hover { background:#BE185D; }
.btn-indigo { background:var(--brand); color:#fff; }
.btn-indigo:hover { background:var(--brand-700); }

/* ── Sidebar nav links ───────────────────────────────────────────────────── */
/* A transparent border on the inactive state, not "no border": without it the
   row shifts by a pixel the moment it becomes active, and a sidebar that twitches
   as you navigate reads as broken. */
.navlink { display:flex; align-items:center; gap:10px; padding:9px 10px; border-radius:var(--r-sm);
           font-size:14px; font-weight:500; color:var(--text-2); border:1px solid transparent;
           text-decoration:none; transition:.15s; }
.navlink:hover { background:var(--surface-2); color:var(--text); }
.navlink.active { background:var(--brand-50); color:var(--brand); font-weight:600; border-color:var(--brand-100); }

/* Leading dot carries the active accent. It replaces the 3px left border the
   parent portal used, which could not sit inside a rounded row without clipping. */
.navlink .dot { width:7px; height:7px; border-radius:50%; background:#C7CEDC; flex-shrink:0; transition:.15s; }
.navlink.active .dot { background:var(--brand); }

/* Trailing count. Absent when there is nothing waiting -- a zero badge trains
   people to ignore the badge. */
.navlink .count { margin-left:auto; font-size:11px; font-weight:700; padding:1px 7px; border-radius:999px;
                  background:var(--track); color:var(--text-3); }
.navlink.active .count { background:var(--brand); color:#fff; }

/* ── Stat strip ──────────────────────────────────────────────────────────── */
.stat-seg { padding:18px 20px; }
.stat-value { font-size:30px; font-weight:800; letter-spacing:-.02em; line-height:1; }

/* ── Form fields ─────────────────────────────────────────────────────────── */
.field { background:var(--surface-2); border:1px solid var(--line-strong); border-radius:var(--r-sm); color:var(--text); font-size:14.5px; padding:11px 14px; width:100%; outline:none; transition:.15s; }
.field:focus { border-color:var(--brand); box-shadow:0 0 0 3px var(--brand-100); background:#fff; }
.field::placeholder { color:var(--text-3); }

/* Search variant. The icon is decorative and must not eat the click that should
   focus the input, hence pointer-events:none. */
.field-search { position:relative; display:block; }
.field-search .field { padding-left:36px; }
.field-search svg { position:absolute; left:12px; top:50%; transform:translateY(-50%); width:16px; height:16px;
                    color:var(--text-3); pointer-events:none; }
.field-label { font-size:11.5px; font-weight:600; letter-spacing:.04em; text-transform:uppercase; color:var(--text-3); }

/* ── Panel masonry ───────────────────────────────────────────────────────────
   A CSS grid of cards with `items-start` leaves a void under every card that is
   shorter than the tallest one in its row -- on the student profile that was
   most of the right-hand side of the screen. Columns flow instead, so a short
   card is followed by the next card rather than by whitespace.

   Children must not be split across a column break, hence break-inside.

   Two columns, not three: at three the tallest card cannot share a column with
   any other, so one column dead-ends ~200px above the rest. Two wider columns
   pair up evenly and give the badge grids and field rows room to stop wrapping. */
.panel-columns { column-gap:20px; }
.panel-columns > * { break-inside:avoid; -webkit-column-break-inside:avoid; margin-bottom:20px; }
@media (min-width:1024px) { .panel-columns { column-count:2; } }

/* Empty states read as "nothing here", so they get one compact row rather than a
   centered icon blob whose padding inflates the card it sits in. */
.empty-inline { display:flex; align-items:flex-start; gap:10px; padding:10px 12px;
                background:var(--surface-2); border:1px solid var(--line); border-radius:var(--r-sm); }
.empty-inline__icon { flex:0 0 auto; font-size:16px; line-height:1.35; }

/* ── Scrollbar ───────────────────────────────────────────────────────────── */
::-webkit-scrollbar { width:9px; height:9px; }
::-webkit-scrollbar-track { background:transparent; }
::-webkit-scrollbar-thumb { background:#D3DAE6; border-radius:6px; }
::-webkit-scrollbar-thumb:hover { background:#B9C2D4; }

/* ── Screen-reader-only text ─────────────────────────────────────────────────
   Icon-only controls (the sidebar logout button) carry their label as a real
   text node hidden this way. Tailwind also defines .sr-only, but the shell
   should not depend on that being loaded on every page. */
.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;
}
