/* ==========================================================================
   Season One — institution portal.
   A signed-in application, not a marketing page: sidebar, dense tables, status
   colour. It deliberately does NOT import s1.css. That sheet is built for a
   marketing site (hard offset shadows, 3px black rules, full-bleed type), and a
   roster of 60 students rendered in it would be unreadable. What carries over is
   the palette, lifted value-for-value from PANCEPrep/Theme.swift so the portal,
   the site and the app cannot drift.

   Re-themed 2026-09-06 for Annexity. Theme.swift is four blues and white now, so
   the teal this was built on had drifted from the very file it claims to follow.
   Amber and violet became steps of the one ramp, exactly as they did in the app.
   Green and red stayed: this is a roster, and "overdue" and "done" are the two
   things a programme director scans for — the app makes the same exception for
   right and wrong answers.

   PROTOTYPE. Every number on these pages is mock data held in portal.js. No
   backend is wired; see the institution platform plan in Notion.
   ========================================================================== */

:root{
  --brand:#375A9C; --brand-deep:#11235A; --brand-lite:#E6EFFA;
  --amber:#6189D8; --amber-lite:#E6EFFA;
  --leaf:#2E7861; --leaf-lite:#E8F2EE;
  --siren:#B04F4A; --siren-lite:#F8EBEA;
  --violet:#69A0E2; --violet-lite:#EEF3FA;
  --ink:#0E1726; --ink-dim:#5A6D8B; --ink-faint:#8496AD;
  --paper:#FFFFFF; --paper-2:#F7FAFD; --paper-3:#EEF3FA;
  --rule:#E3E9F3; --rule-soft:#EDF1F8;
  --display:Poppins,system-ui,-apple-system,"Segoe UI",sans-serif;
  --sans:Karla,system-ui,-apple-system,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  --mono:ui-monospace,"SF Mono",SFMono-Regular,Menlo,Consolas,monospace;
  --shadow:0 1px 2px rgba(17,35,90,.05),0 4px 14px rgba(17,35,90,.07);
  --sidebar:248px;
}

*{box-sizing:border-box}
html,body{margin:0;padding:0}
body{
  font-family:var(--sans);background:var(--paper-2);color:var(--ink);
  font-size:15px;line-height:1.5;-webkit-font-smoothing:antialiased;
}
a{color:var(--brand);text-decoration:none}
a:hover{text-decoration:underline}
button{font-family:inherit;font-size:inherit;cursor:pointer}
:focus-visible{outline:2px solid var(--brand);outline-offset:2px}

/* -- shell ---------------------------------------------------------------- */
.shell{display:grid;grid-template-columns:var(--sidebar) 1fr;min-height:100vh}

.side{
  background:var(--brand-deep);color:#fff;padding:22px 0;
  display:flex;flex-direction:column;gap:6px;position:sticky;top:0;height:100vh;
}
.side-brand{
  padding:0 22px 20px;font-family:var(--mono);font-size:13px;font-weight:700;
  letter-spacing:.13em;text-transform:uppercase;line-height:1.35;
}
.side-brand small{display:block;font-size:10.5px;font-weight:400;opacity:.7;letter-spacing:.1em;margin-top:5px}
.side-group{
  padding:16px 22px 6px;font-family:var(--mono);font-size:10px;letter-spacing:.14em;
  text-transform:uppercase;color:rgba(255,255,255,.45);
}
.side a{
  display:flex;align-items:center;gap:11px;padding:10px 22px;color:rgba(255,255,255,.82);
  font-size:14.5px;text-decoration:none;border-left:3px solid transparent;
}
.side a:hover{background:rgba(255,255,255,.07);color:#fff;text-decoration:none}
.side a.on{background:rgba(255,255,255,.12);color:#fff;border-left-color:var(--amber);font-weight:600}
.side a .ic{width:18px;text-align:center;opacity:.9}
.side-foot{margin-top:auto;padding:16px 22px 0;border-top:1px solid rgba(255,255,255,.14);font-size:12.5px;color:rgba(255,255,255,.6)}

.main{min-width:0;display:flex;flex-direction:column}
.top{
  background:var(--paper);border-bottom:1px solid var(--rule);
  padding:16px 28px;display:flex;align-items:center;gap:18px;position:sticky;top:0;z-index:5;
}
.top h1{margin:0;font-size:20px;font-weight:700;letter-spacing:-.01em}
.top .sub{color:var(--ink-dim);font-size:13px;margin-top:2px}
.top-right{margin-left:auto;display:flex;align-items:center;gap:12px}
.who{display:flex;align-items:center;gap:9px;font-size:13.5px;color:var(--ink-dim)}
.avatar{
  width:34px;height:34px;border-radius:50%;background:var(--brand);color:#fff;
  display:grid;place-items:center;font-weight:700;font-size:13.5px;
}
.content{padding:24px 28px 56px;max-width:1500px;width:100%}

/* -- primitives ----------------------------------------------------------- */
.card{background:var(--paper);border:1px solid var(--rule);border-radius:12px;box-shadow:var(--shadow)}
.card-head{
  padding:15px 18px;border-bottom:1px solid var(--rule-soft);
  display:flex;align-items:center;gap:12px;
}
.card-head h2{margin:0;font-size:15.5px;font-weight:700}
.card-head .hint{color:var(--ink-faint);font-size:12.5px}
.card-head .spacer{margin-left:auto}
.card-body{padding:18px}
.card-body.flush{padding:0}

.btn{
  border:1px solid var(--brand);background:var(--brand);color:#fff;
  padding:9px 15px;border-radius:9px;font-weight:600;font-size:13.5px;
}
.btn:hover{background:var(--brand-deep);border-color:var(--brand-deep)}
.btn.ghost{background:var(--paper);color:var(--ink);border-color:var(--rule)}
.btn.ghost:hover{background:var(--paper-3)}
.btn.danger{background:var(--siren);border-color:var(--siren)}
.btn.sm{padding:6px 11px;font-size:12.5px;border-radius:7px}
.btn[disabled]{opacity:.5;cursor:not-allowed}

.grid{display:grid;gap:16px}
.g-4{grid-template-columns:repeat(4,minmax(0,1fr))}
.g-3{grid-template-columns:repeat(3,minmax(0,1fr))}
.g-2{grid-template-columns:repeat(2,minmax(0,1fr))}
.g-2-1{grid-template-columns:minmax(0,2fr) minmax(0,1fr)}

/* -- stat tiles ----------------------------------------------------------- */
.stat{padding:16px 18px}
.stat .lbl{font-family:var(--mono);font-size:10.5px;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-faint)}
.stat .val{font-size:30px;font-weight:700;letter-spacing:-.02em;margin-top:6px;line-height:1}
.stat .delta{font-size:12.5px;color:var(--ink-dim);margin-top:6px}
.stat .delta.up{color:var(--leaf)}
.stat .delta.down{color:var(--siren)}

/* -- alerts bar ----------------------------------------------------------- */
.alerts{border-left:4px solid var(--siren)}
.alert-row{
  display:flex;align-items:flex-start;gap:12px;padding:13px 18px;
  border-bottom:1px solid var(--rule-soft);
}
.alert-row:last-child{border-bottom:0}
.alert-row .dot{width:9px;height:9px;border-radius:50%;background:var(--siren);margin-top:6px;flex:none}
.alert-row.warn .dot{background:var(--amber)}
.alert-row .txt{min-width:0}
.alert-row .txt b{display:block;font-size:14px}
.alert-row .txt span{color:var(--ink-dim);font-size:13px}
.alert-row .act{margin-left:auto;flex:none}

/* -- tables --------------------------------------------------------------- */
.tbl-wrap{overflow-x:auto}
table{width:100%;border-collapse:collapse;font-size:13.5px}
thead th{
  text-align:left;padding:11px 14px;background:var(--paper-3);color:var(--ink-dim);
  font-family:var(--mono);font-size:10.5px;letter-spacing:.1em;text-transform:uppercase;
  font-weight:600;white-space:nowrap;border-bottom:1px solid var(--rule);
}
tbody td{padding:12px 14px;border-bottom:1px solid var(--rule-soft);vertical-align:middle}
tbody tr:last-child td{border-bottom:0}
tbody tr:hover{background:var(--paper-2)}
td.num{text-align:right;font-variant-numeric:tabular-nums}
.who-cell{display:flex;align-items:center;gap:10px}
.who-cell .avatar{width:30px;height:30px;font-size:12px}
.who-cell b{font-weight:600}
.who-cell small{display:block;color:var(--ink-faint);font-size:11.5px}

/* -- pills ---------------------------------------------------------------- */
.pill{
  display:inline-block;padding:3px 9px;border-radius:999px;font-size:11.5px;font-weight:600;
  white-space:nowrap;
}
.pill.ok{background:var(--leaf-lite);color:var(--leaf)}
.pill.warn{background:var(--amber-lite);color:#8A5B08}
.pill.bad{background:var(--siren-lite);color:var(--siren)}
.pill.neutral{background:var(--paper-3);color:var(--ink-dim)}
.pill.ai{background:var(--violet-lite);color:var(--violet)}

/* -- bars ----------------------------------------------------------------- */
.bar{height:7px;border-radius:999px;background:var(--paper-3);overflow:hidden;min-width:70px}
.bar i{display:block;height:100%;background:var(--brand);border-radius:999px}
.bar i.warn{background:var(--amber)}
.bar i.bad{background:var(--siren)}
.bar-row{display:flex;align-items:center;gap:10px}
.bar-row span{font-variant-numeric:tabular-nums;font-size:12.5px;color:var(--ink-dim);min-width:34px;text-align:right}

/* Column chart, pure CSS — no chart library on a prototype. */
/* `align-items:stretch` and an explicit `height:100%` on the column, not `flex-end`:
   a percentage height on the bar needs a *definite* parent height to resolve against,
   and a flex-end column is only as tall as its content, so every bar computed to zero. */
.cols{display:flex;align-items:stretch;gap:10px;height:168px;padding-top:8px}
.cols .col{flex:1;height:100%;display:flex;flex-direction:column;justify-content:flex-end;gap:6px;min-width:0}
.cols .col i{display:block;background:var(--brand);border-radius:5px 5px 0 0;min-height:3px}
.cols .col i.low{background:var(--siren)}
.cols .col i.mid{background:var(--amber)}
.cols .col b{font-size:11px;font-weight:600;text-align:center;color:var(--ink-dim);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cols .col em{font-style:normal;font-size:11px;text-align:center;color:var(--ink-faint)}

/* -- forms ---------------------------------------------------------------- */
.field{display:flex;flex-direction:column;gap:6px;margin-bottom:14px}
.field label{font-family:var(--mono);font-size:10.5px;letter-spacing:.11em;text-transform:uppercase;color:var(--ink-dim)}
.field input,.field select,.field textarea{
  font-family:var(--sans);font-size:14.5px;padding:10px 12px;border:1px solid var(--rule);
  border-radius:9px;background:var(--paper);color:var(--ink);width:100%;
}
.field input:focus,.field select:focus,.field textarea:focus{border-color:var(--brand);outline:none}
.field textarea{min-height:96px;resize:vertical}
.row-2{display:grid;grid-template-columns:1fr 1fr;gap:14px}

.drop{
  border:2px dashed var(--rule);border-radius:12px;padding:26px;text-align:center;
  color:var(--ink-dim);background:var(--paper-2);
}
.drop b{display:block;color:var(--ink);margin-bottom:4px}

.check{display:flex;gap:10px;align-items:flex-start;padding:9px 0;font-size:14px}
.check input{margin-top:3px;width:16px;height:16px;accent-color:var(--brand);flex:none}

.empty{padding:44px 20px;text-align:center;color:var(--ink-dim)}
.empty b{display:block;font-size:16px;color:var(--ink);margin-bottom:6px}

.note{
  background:var(--brand-lite);border:1px solid #CFE4E0;border-radius:10px;
  padding:12px 14px;font-size:13px;color:var(--brand-deep);
}
.note.proto{background:var(--amber-lite);border-color:#F2DFBE;color:#7A4F06}

.sect-title{font-size:13px;font-family:var(--mono);letter-spacing:.11em;text-transform:uppercase;
  color:var(--ink-faint);margin:26px 0 12px}
.sect-title:first-child{margin-top:0}

/* -- sign in -------------------------------------------------------------- */
/* -- sign in --------------------------------------------------------------

   White, not a colour field. This was a full-bleed brand gradient with a card
   floating on it — the look every SaaS login had in 2019, and nothing to do with
   a palette whose ground is white. The card now sits on white and is held by a
   hairline instead of a drop shadow.
   ----------------------------------------------------------------------- */

.auth-page{background:var(--paper)}
.auth-wrap{min-height:100vh;display:grid;place-items:center;padding:24px;
  background:var(--paper)}
.auth{width:100%;max-width:414px;background:var(--paper);
  border:1px solid var(--rule);border-radius:16px;padding:30px 30px 26px}

.auth-mark{display:flex;align-items:center;gap:9px;text-decoration:none;
  margin-bottom:22px}
.auth-mark svg{width:28px;height:auto;display:block}
.auth-mark span{font-family:var(--display);font-weight:700;font-size:1.3rem;
  letter-spacing:-.022em;color:var(--brand-deep)}
.auth-mark:hover{text-decoration:none}

/* The tabs sit on a rail rather than in a pill group: the underline says which
   panel is showing without adding a second filled shape beside the button. */
.tabs{display:flex;gap:4px;border-bottom:1px solid var(--rule);margin-bottom:20px}
.tab{font-family:var(--display);font-size:14.5px;font-weight:500;
  background:none;border:0;color:var(--ink-dim);padding:9px 12px;
  border-bottom:2px solid transparent;margin-bottom:-1px}
.tab:hover{color:var(--brand-deep)}
.tab[aria-selected="true"]{color:var(--brand-deep);font-weight:600;
  border-bottom-color:var(--brand)}

.auth p.lede{margin:0 0 18px;color:var(--ink-dim);font-size:14px}
.auth .note.proto{margin-bottom:18px}
.auth .btn{width:100%;padding:12px;font-size:15px}
.auth-alt{text-align:center;margin-top:16px;font-size:13.5px;color:var(--ink-dim)}
.panel[hidden]{display:none}

@media(max-width:1100px){
  .g-4{grid-template-columns:repeat(2,minmax(0,1fr))}
  .g-3,.g-2-1{grid-template-columns:1fr}
}
@media(max-width:820px){
  .shell{grid-template-columns:1fr}
  .side{position:static;height:auto;flex-direction:row;overflow-x:auto;padding:10px;gap:2px;align-items:center}
  .side-brand,.side-group,.side-foot{display:none}
  .side a{border-left:0;border-bottom:3px solid transparent;padding:9px 13px;white-space:nowrap;border-radius:8px}
  .side a.on{border-left:0;border-bottom-color:var(--amber)}
  .content{padding:18px 16px 44px}
  .top{padding:14px 16px}
  .g-2,.g-4{grid-template-columns:1fr}
}

/* -- states and controls added with the real data layer -------------------- */

.alert{background:var(--siren-lite);border:1px solid var(--siren);color:#7A302B;
  border-radius:10px;padding:11px 13px;font-size:13.5px;margin-bottom:16px}
.alert[hidden]{display:none}

.empty{padding:26px 18px;text-align:center;color:var(--ink-dim);font-size:14px;line-height:1.6}
.empty b{color:var(--ink)}

.muted{color:var(--ink-faint)}
td.mono{font-family:var(--mono);font-size:12.5px;color:var(--ink-dim);
  font-variant-numeric:tabular-nums}

.search,.card-head select{
  font:inherit;font-size:13.5px;background:var(--paper);color:var(--ink);
  border:1px solid var(--rule);border-radius:9px;padding:7px 10px}
.search{min-width:190px}
.search:focus,.card-head select:focus{outline:2px solid var(--brand);outline-offset:1px}

.who-head{display:flex;align-items:center;gap:14px}
.name-line{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap;margin:0}
/* A note a colleague left, not a verdict the software reached. Same weight as the meta
   line under it, set apart by a rule rather than by a colour. */
.status-word{font-family:var(--sans);font-size:13.5px;font-weight:500;color:var(--ink-dim);
  padding-left:12px;border-left:1px solid var(--rule)}
.status-word:empty{display:none}

/* The roster and dashboard columns. Same reasoning as .status-word: it is a note, not a
   verdict, so it is set in the table's own voice rather than given a colour of its own. */
.status-cell{font-size:13.5px;color:var(--ink)}
.avatar.lg{width:52px;height:52px;font-size:17px}
.who-meta{color:var(--ink-dim);font-size:13.5px;margin-top:3px}
.ok{background:var(--leaf-lite);border:1px solid var(--leaf);color:#1E5C46;
  border-radius:10px;padding:11px 13px;font-size:13.5px;margin-bottom:16px}
.ok[hidden]{display:none}
hr.rule{border:0;border-top:1px solid var(--rule);margin:18px 0}

dl.facts{display:grid;grid-template-columns:170px 1fr;gap:9px 16px;margin:0}
dl.facts dt{color:var(--ink-dim);font-size:13.5px}
dl.facts dd{margin:0}
.joincode{font-family:var(--mono);font-size:26px;letter-spacing:.08em;
  color:var(--brand-deep);background:var(--brand-lite);border-radius:10px;
  padding:14px 18px;display:inline-block;margin:6px 0 14px}
textarea{font:inherit;font-size:14px;width:100%;background:var(--sunk,#F7FAFD);
  border:1px solid var(--rule);border-radius:9px;padding:9px 11px;resize:vertical}
textarea:focus{outline:2px solid var(--brand);outline-offset:1px}

/* -- the lesson-plan builder ---------------------------------------------- */

.sub-head{font-family:var(--display);font-size:14px;font-weight:600;color:var(--navy,var(--brand-deep));
  margin:0 0 8px;display:flex;align-items:baseline;gap:8px}
.sub-head .hint{font-family:var(--sans);font-weight:400;font-size:12.5px;color:var(--ink-faint)}

.split-2{display:grid;gap:20px;margin:18px 0}
@media(min-width:900px){.split-2{grid-template-columns:1fr 1fr}}

/* A scrolling list of checkboxes, capped in height so the form stays navigable with 200
   conditions in it. */
.picker{border:1px solid var(--rule);border-radius:10px;max-height:280px;overflow-y:auto;
  background:var(--paper)}
.pick{display:flex;gap:10px;align-items:flex-start;padding:8px 10px;cursor:pointer;
  border-bottom:1px solid var(--rule-soft)}
.pick:last-child{border-bottom:0}
.pick:hover{background:var(--brand-lite)}
.pick input{margin-top:3px;flex:none}
.pick span{display:block;font-size:13.5px;line-height:1.35}
.pick small{display:block;color:var(--ink-faint);font-size:12px}

.picker-actions{display:flex;gap:8px;margin-bottom:8px}
.picker-actions select{flex:1}

.filter-row{display:flex;gap:8px;margin-bottom:8px}
.filter-row select{flex:1;min-width:0}
.filter-row select:disabled{opacity:.55}

fieldset.pace{border:1px solid var(--rule);border-radius:12px;padding:14px 16px;margin:4px 0 0}
fieldset.pace legend{font-family:var(--display);font-size:13px;font-weight:600;
  color:var(--ink-dim);padding:0 6px}
.radio{display:flex;gap:10px;align-items:flex-start;padding:6px 0;cursor:pointer}
.radio input{margin-top:4px;flex:none}
.radio b{font-family:var(--display);font-weight:600;font-size:14px;display:block}
.radio small{color:var(--ink-dim);font-size:12.5px;display:block;line-height:1.4}

.pace-n{display:flex;align-items:center;gap:8px;margin:10px 0 0 26px}
.pace-n[hidden]{display:none}
.pace-n input{width:64px;text-align:center;font:inherit;font-size:15px;
  background:var(--sunk,#F7FAFD);border:1px solid var(--rule);border-radius:9px;padding:6px}
.step{width:32px;height:32px;border-radius:9px;border:1px solid var(--rule);
  background:var(--paper);color:var(--ink);font-size:17px;line-height:1;padding:0}
.step:hover{background:var(--brand-lite);color:var(--brand-deep)}

.builder-foot{display:flex;align-items:center;gap:14px;margin-top:6px;flex-wrap:wrap}

/* -- material upload ------------------------------------------------------ */

.drop{border:1.5px dashed var(--rule-firm,var(--rule));border-radius:14px;padding:26px 20px;
  text-align:center;background:var(--sunk,#F7FAFD)}
.drop.over{border-color:var(--brand);background:var(--brand-lite)}
.drop p{margin:0 0 6px}
.drop .btn{margin-top:8px}

ul.terms{margin:0 0 4px;padding-left:18px}
ul.terms li{margin-bottom:8px;font-size:13.5px;line-height:1.55;color:var(--ink-dim)}
ul.terms li b{color:var(--ink)}

/* The mark in the sidebar. Its navy facet is lightened here: navy on the deep sidebar is
   the invisible-on-its-own-colour problem the brand's dark ramp exists to solve. */
.side-brand{display:flex;align-items:center;gap:9px}
.side-mark{width:22px;height:auto;flex:none}
.side-brand span{display:block;min-width:0}

/* -- sign-up --------------------------------------------------------------- */
.auth.wide{max-width:620px}
.signup-title{font-family:var(--display);font-size:24px;font-weight:700;
  color:var(--brand-deep);margin:0 0 6px;letter-spacing:-.02em}
.auth .lede{margin-bottom:20px}
.auth .row-2{display:grid;gap:0 14px}
@media(min-width:520px){.auth .row-2{grid-template-columns:1fr 1fr}}
.auth .sub-head{margin-top:4px}

/* -- Bubby ---------------------------------------------------------------- */
.chat{border:1px solid var(--rule);border-radius:12px;background:var(--paper);
  padding:14px;max-height:320px;overflow-y:auto;display:flex;flex-direction:column;gap:10px}
.msg{max-width:80%;padding:10px 13px;border-radius:13px;font-size:14px;line-height:1.5;
  white-space:pre-wrap}
.msg.bot{background:var(--brand-lite);color:var(--ink);align-self:flex-start;
  border-bottom-left-radius:4px}
.msg.me{background:var(--brand);color:#fff;align-self:flex-end;border-bottom-right-radius:4px}
.chat-row{display:flex;gap:8px;margin-top:12px}
.chat-row input{flex:1;font:inherit;font-size:14px;background:var(--sunk,#F7FAFD);
  border:1px solid var(--rule);border-radius:10px;padding:9px 12px}
.chat-row input:focus{outline:2px solid var(--brand);outline-offset:1px}
