/* ===========================================================================
   Osoro — the staff console.
   ===========================================================================

   ONE stylesheet for all five staff pages, served from /console.css and
   cached, rather than the same two hundred lines pasted into each file and
   drifting apart. The public tracking page does NOT use this: it loads on a
   cheap Android over 2G on a bundle the recipient paid for, so it stays
   self-contained and small. Different surface, different rules.

   Colours and typefaces come from docs/brand.md and nowhere else. The console
   used to be crimson and Archivo, chosen before the identity existed — a
   dispatcher signed in to something that could have belonged to anyone.

   ---------------------------------------------------------------------------
   WHY THIS IS DENSE WHERE A DASHBOARD WOULD BE AIRY
   ---------------------------------------------------------------------------

   The board is an OPERATING surface, not a reading surface. A dispatcher
   assigns work over and over while riders wait on a corridor. Every row of
   whitespace between drops is a row they have to scroll past forty times an
   hour. So the shell around the work gets room to breathe and the work itself
   stays tight — the opposite of a reporting dashboard, on purpose.
   =========================================================================== */

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

:root {
  /* docs/brand.md §3. Pantone is the authority; these are the screen values. */
  --blue:       #005EB8;   /* Osoro Blue — Pantone 2945 C */
  --blue-deep:  #004A93;
  --blue-soft:  #E4EEF8;
  --night:      #0C2340;   /* Pantone 289 C */
  --paper:      #F7F5F1;
  --daybreak:   #B26B00;   /* 137 C, darkened only so it can be read on Paper */
  --daybreak-bg:#FFF4E0;

  --surface:    #FFFFFF;
  --surface-2:  #F1EEE8;
  --sel:        #E4EEF8;
  --ink:        #16283F;
  --soft:       #45566B;
  --faint:      #6E7C8C;   /* grey biased toward the blue, not a mid grey */
  --rule:       #DFDAD2;
  --rule-soft:  #ECE8E1;

  /* Semantic, and deliberately separate from the brand accent. A delivery
     succeeding is not "on brand", it is good — those are different ideas and
     conflating them makes a board harder to read at a glance. */
  --good:       #2C6E4B;
  --warn:       #9A6510;
  --bad:        #A63426;
  --info:       #2C5A82;

  --shadow:     0 1px 2px rgba(12,35,64,.05), 0 6px 20px -12px rgba(12,35,64,.16);
  --sidebar-w:  216px;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --blue:#6BB0F0; --blue-deep:#8CC3F5; --blue-soft:#14314C;
    --night:#0A1826; --paper:#0E1A28;
    --daybreak:#F0A83C; --daybreak-bg:#33240D;
    --surface:#152435; --surface-2:#1B2B3D; --sel:#14314C;
    --ink:#E7EEF6; --soft:#B4C2D0; --faint:#8FA2B6;
    --rule:#24384D; --rule-soft:#1B2B3D;
    --good:#6FBF8F; --warn:#D9A441; --bad:#E0705E; --info:#7FB0DA;
    --shadow:0 1px 2px rgba(0,0,0,.35), 0 6px 20px -12px rgba(0,0,0,.6);
  }
}
:root[data-theme="dark"] {
  --blue:#6BB0F0; --blue-deep:#8CC3F5; --blue-soft:#14314C;
  --night:#0A1826; --paper:#0E1A28;
  --daybreak:#F0A83C; --daybreak-bg:#33240D;
  --surface:#152435; --surface-2:#1B2B3D; --sel:#14314C;
  --ink:#E7EEF6; --soft:#B4C2D0; --faint:#8FA2B6;
  --rule:#24384D; --rule-soft:#1B2B3D;
  --good:#6FBF8F; --warn:#D9A441; --bad:#E0705E; --info:#7FB0DA;
  --shadow:0 1px 2px rgba(0,0,0,.35), 0 6px 20px -12px rgba(0,0,0,.6);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font: 14px/1.45 Inter, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
}

/* Numbers that change while you watch must not shift the columns under your
   eye. Tabular figures cost nothing and fix that entirely. */
.mono, .stat b, td.n, .kpi b {
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
}

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

.shell { display: grid; grid-template-columns: var(--sidebar-w) minmax(0,1fr); min-height: 100vh; }
@media (max-width: 900px) { .shell { grid-template-columns: minmax(0,1fr); } }

/* ------------------------------------------------------------------ sidebar */

.side {
  background: var(--night);
  color: #cfe0f2;
  padding: 18px 0 28px;
  display: flex; flex-direction: column; gap: 4px;
  position: sticky; top: 0; height: 100vh; overflow-y: auto;
}
@media (max-width: 900px) {
  .side { position: static; height: auto; flex-direction: row; flex-wrap: wrap;
          align-items: center; padding: 10px 14px; gap: 6px 14px; }
  .side .grp { display: none; }
}

.brand { display: flex; align-items: center; gap: 11px; padding: 0 18px 20px; }
.brand svg { width: 26px; height: 26px; flex: none; }
.brand .word {
  font-family: Poppins, 'Trebuchet MS', Arial, sans-serif;
  font-weight: 600; font-size: 17px; letter-spacing: .12em; color: #fff;
}
@media (max-width: 900px) { .brand { padding: 0 8px 0 0; } }

.grp {
  font-size: 9.5px; letter-spacing: .14em; text-transform: uppercase;
  color: #6d8db2; padding: 16px 18px 6px; font-weight: 600;
}
.side a.nav {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 18px; color: #cfe0f2; text-decoration: none;
  font-size: 13.5px; font-weight: 500; border-left: 3px solid transparent;
}
.side a.nav:hover { background: rgba(255,255,255,.06); color: #fff; }
.side a.nav.on { background: rgba(107,176,240,.14); border-left-color: var(--blue); color: #fff; }
.side a.nav .dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; opacity: .55; flex: none; }
@media (max-width: 900px) { .side a.nav { border-left: 0; padding: 6px 10px; border-radius: 4px; } }

.side .foot { margin-top: auto; padding: 14px 18px 0; font-size: 11px; color: #6d8db2; }
@media (max-width: 900px) { .side .foot { display: none; } }

/* ------------------------------------------------------------------- topbar */

.top {
  background: var(--surface); border-bottom: 1px solid var(--rule);
  padding: 14px 22px; display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
  position: sticky; top: 0; z-index: 20;
}
.top h1 { font-family: Poppins, sans-serif; font-size: 17px; font-weight: 600; margin: 0; letter-spacing: -.01em; }
.top .sub { color: var(--faint); font-size: 12.5px; }
.top .spacer { margin-left: auto; }

#pulse { width: 8px; height: 8px; border-radius: 50%; background: var(--good); flex: none; }
#pulse.stale { background: var(--bad); }

/* ---------------------------------------------------------------- KPI cards */
/* The markup is what the existing JS already emits — .stat > b + i — so this
   is a restyle, not a rewrite. Nothing in the board's logic changes. */

.stats, .day { display: flex; gap: 10px; flex-wrap: wrap; }
.stat {
  background: var(--surface); border: 1px solid var(--rule);
  border-left: 3px solid var(--blue); border-radius: 5px;
  padding: 8px 14px; min-width: 84px; box-shadow: var(--shadow);
}
.stat b { display: block; font-size: 21px; font-weight: 600; line-height: 1.12; }
/* Two pages render the label as <span>, two as <i>. Style both rather than
   rewriting four files' worth of working JavaScript to agree with the CSS. */
.stat i, .stat span {
  display: block; font-style: normal; font-size: 9.5px; letter-spacing: .11em;
  text-transform: uppercase; color: var(--faint); font-weight: 600;
}

/* ------------------------------------------------------------------- alerts */

.banner { padding: 14px 22px 0; }
.banner h2 {
  margin: 0 0 8px; font-size: 10.5px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--faint); font-weight: 600;
}
.alert-row, .cf {
  display: flex; gap: 12px; align-items: center; flex-wrap: wrap;
  background: var(--surface); border: 1px solid var(--rule);
  border-left: 3px solid var(--daybreak); border-radius: 5px;
  padding: 10px 14px; margin-bottom: 8px; font-size: 13px; color: var(--soft);
  box-shadow: var(--shadow);
}
.cf { border-left-color: var(--bad); }
.cf b, .alert-title { color: var(--ink); font-weight: 600; }
.alert-sev {
  font-size: 9.5px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase;
  padding: 2px 7px; border-radius: 3px; border: 1px solid currentColor;
}
.sev-error, .sev-critical { color: var(--bad); }
.sev-warn, .sev-warning { color: var(--warn); }
.sev-info { color: var(--info); }
.alert-age { color: var(--faint); font-size: 12px; }
/* The action is the point of an alert. brand.md's rule for messages applies
   here too: say what happened and what happens next. */
.alert-action {
  flex-basis: 100%; color: var(--soft); font-size: 12.5px;
  border-top: 1px dashed var(--rule-soft); padding-top: 7px; margin-top: 2px;
}

/* --------------------------------------------------------------------- main */

main { display: grid; grid-template-columns: minmax(0,1fr); }
@media (min-width: 1100px) { main { grid-template-columns: minmax(0,1fr) 340px; } }

/* A page with one section gets the whole width. Without this, auto-placement
   drops a lone table into whichever track is free — on the riders page that
   was the 340px side column, and a five-column table rendered 4270px wide,
   starting off the right edge of the screen. */
main > section:only-child { grid-column: 1 / -1; }

/* A grid item's default min-width is `auto`, which is min-content, so a table
   pushes its own column wider rather than fitting inside it. That is what
   clipped the REQUIRED column on the proof page. */
section { padding: 16px 22px 40px; min-width: 0; overflow-x: auto; }
section table { width: 100%; }

/* An actions cell holds one button per paired phone, and a rider who has
   replaced a handset several times has several. `white-space: nowrap` ran the
   row off the right of the screen; let them wrap and stack instead. */
td.acts { text-align: right; }
td.acts button { margin: 0 0 4px 6px; }
section + section { border-left: 1px solid var(--rule); }

h3 {
  font-size: 10.5px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--faint); margin: 0 0 10px; font-weight: 600;
  display: flex; justify-content: space-between; align-items: center; gap: 12px;
}
.hint { font-size: 12px; color: var(--faint); font-weight: 500; text-transform: none; letter-spacing: 0; }

/* -------------------------------------------------------------------- table */
/* Deliberately tight. See the note at the top of this file. */

table { border-collapse: collapse; width: 100%; }
th {
  font-size: 9.5px; letter-spacing: .11em; text-transform: uppercase; color: var(--faint);
  text-align: left; padding: 7px 9px; border-bottom: 1px solid var(--rule);
  font-weight: 600; white-space: nowrap;
}
td { padding: 8px 9px; border-bottom: 1px solid var(--rule-soft); vertical-align: middle; }
tbody tr { cursor: pointer; }
tbody tr:hover { background: var(--surface); }
tbody tr.sel { background: var(--sel); outline: 1px solid var(--blue); outline-offset: -1px; }
td.n { text-align: right; white-space: nowrap; }
.stripe { width: 3px; padding: 0; border-bottom: 1px solid var(--rule-soft); }
.place { font-weight: 600; }
/* The landmark description IS the address here, so it gets real weight rather
   than being demoted to a caption. Same argument as the parcel sticker. */
.place small { display: block; font-weight: 400; color: var(--faint); font-size: 11.5px; margin-top: 2px; }
.empty { color: var(--faint); text-align: center; padding: 26px 0; }

.tag {
  display: inline-block; font-size: 9.5px; font-weight: 600; letter-spacing: .07em;
  text-transform: uppercase; padding: 2px 6px; border-radius: 3px;
  border: 1px solid currentColor; white-space: nowrap;
}
.t-good{color:var(--good)} .t-warn{color:var(--warn)} .t-bad{color:var(--bad)}
.t-info{color:var(--info)} .t-faint{color:var(--faint)} .t-acc{color:var(--blue)}

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

.rider {
  border: 1px solid var(--rule); background: var(--surface); border-radius: 6px;
  padding: 12px 14px; margin-bottom: 10px; cursor: pointer;
  box-shadow: var(--shadow); transition: border-color .12s ease;
}
.rider:hover { border-color: var(--blue); }
.rider.blocked { opacity: .6; cursor: not-allowed; }
.rider.blocked:hover { border-color: var(--rule); }
.rider .top { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.rider .nm { font-weight: 600; font-size: 14px; }
.rider .meta { font-size: 11.5px; color: var(--faint); margin-top: 3px; }
.rider .bar { height: 5px; background: var(--rule-soft); border-radius: 3px; margin-top: 9px; overflow: hidden; }
.rider .bar i { display: block; height: 100%; background: var(--good); }
.rider .bar i.over { background: var(--bad); }
.rider .cash { display: flex; justify-content: space-between; font-size: 11px; color: var(--faint); margin-top: 5px; }

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

button, .btn {
  font: 500 13px Inter, sans-serif; padding: 8px 14px; border-radius: 5px;
  border: 1px solid var(--blue); background: var(--blue); color: #fff; cursor: pointer;
}
button:hover, .btn:hover { background: var(--blue-deep); border-color: var(--blue-deep); }
button.ghost, a.ghost {
  background: transparent; color: var(--blue); border-color: var(--rule);
  text-decoration: none; display: inline-block;
}
button.ghost:hover, a.ghost:hover { border-color: var(--blue); background: var(--blue-soft); }
button:disabled { opacity: .5; cursor: not-allowed; }
:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; border-radius: 3px; }

/* ------------------------------------------------------- overlays and toast */

#login, #intake {
  position: fixed; inset: 0; background: rgba(12,35,64,.55);
  display: flex; align-items: center; justify-content: center; z-index: 50; padding: 20px;
}
#login[hidden], #intake[hidden] { display: none; }
#login form, .sheet {
  background: var(--surface); border: 1px solid var(--rule); border-radius: 8px;
  padding: 26px 28px; width: 100%; max-width: 420px; box-shadow: 0 20px 60px -20px rgba(12,35,64,.5);
}
.sheet { max-width: 680px; }
#login h2, .sheet h2 { font-family: Poppins, sans-serif; font-size: 19px; margin: 0 0 16px; font-weight: 600; }
#login label, .sheet label { display: block; margin-bottom: 14px; font-size: 10.5px;
  letter-spacing: .11em; text-transform: uppercase; color: var(--faint); font-weight: 600; }
#login input, .sheet input, .sheet textarea {
  display: block; width: 100%; margin-top: 6px; padding: 10px 12px; font: 14px Inter, sans-serif;
  border: 1px solid var(--rule); border-radius: 5px; background: var(--surface-2); color: var(--ink);
  text-transform: none; letter-spacing: 0;
}
.sheet textarea { min-height: 190px; font-family: ui-monospace, Menlo, monospace; font-size: 12.5px; }
#login button { width: 100%; padding: 11px; font-size: 14px; font-weight: 600; }
#loginErr { color: var(--bad); font-size: 13px; margin: 12px 0 0; }
.hint2 { font-size: 12.5px; color: var(--faint); margin: 0 0 14px; }
.row { display: flex; gap: 10px; margin-top: 14px; }
code { font-family: ui-monospace, Menlo, monospace; font-size: 12px;
       background: var(--blue-soft); padding: 1px 5px; border-radius: 3px; }

#toast {
  position: fixed; left: 50%; transform: translateX(-50%); bottom: 26px; z-index: 60;
  background: var(--night); color: #fff; padding: 11px 18px; border-radius: 6px;
  font-size: 13.5px; box-shadow: 0 10px 30px -10px rgba(0,0,0,.5);
}
#toast[hidden] { display: none; }
#toast.err { background: var(--bad); }

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

/* ===========================================================================
   Page-specific rules.
   ===========================================================================
   These lived in five separate <style> blocks and were lost when the pages
   moved to this shared sheet. Recovered from git rather than reinvented, and
   translated to brand tokens on the way: --accent became --blue, Archivo
   became Poppins, JetBrains Mono became the system monospace stack.
   =========================================================================== */

/* The grid child that holds everything right of the sidebar. min-width:0 or a
   wide table refuses to shrink and pushes the whole page sideways. */
.pane { min-width: 0; }

/* Name over relationship — riders and cash desk. Without the block display
   the two run together as "Kwame Mensahcontracted". */
.nm { font-weight: 600; }
.nm small {
  display: block; font-weight: 400; color: var(--faint);
  font-size: 11.5px; margin-top: 2px;
}

#csvOut .ok  { color: var(--good); font-weight: 600; }
#csvOut .bad { color: var(--bad); }

/* --- riders: pairing a handset ------------------------------------------ */
button.primary { background: var(--blue); border-color: var(--blue); color: #fff; }
button.primary:hover { background: var(--blue-deep); border-color: var(--blue-deep); }
button.danger {
  background: none; border: 1px solid var(--bad); color: var(--bad);
  padding: 6px 10px; font-size: 11.5px;
}
button.danger:hover { background: var(--bad); color: #fff; }

.modal {
  position: fixed; inset: 0; z-index: 70; background: rgba(12,35,64,.55);
  display: flex; align-items: flex-start; justify-content: center;
  padding: 40px 20px; overflow-y: auto;
}
.modal[hidden] { display: none; }
.modal > * {
  background: var(--surface); border: 1px solid var(--rule); border-radius: 8px;
  padding: 24px 26px; width: 100%; max-width: 520px;
  box-shadow: 0 20px 60px -20px rgba(12,35,64,.5);
}
.grid { display: grid; gap: 12px; }
.grid.two { grid-template-columns: 1fr 1fr; }
@media (max-width: 560px) { .grid.two { grid-template-columns: 1fr; } }

.pair { text-align: center; padding: 8px 0 0; }
/* The QR ground stays white in dark mode too. A scanner needs the contrast
   the code was generated for, and a rider pairing a handset in a dim yard is
   exactly when that matters. */
.pair .qr { background: #fff; padding: 14px; border-radius: 6px; display: inline-block; line-height: 0; }
.pair .qr svg { width: 230px; height: 230px; display: block; }
.token {
  font-family: ui-monospace, Menlo, monospace; font-size: 13px; word-break: break-all;
  background: var(--surface-2); border: 1px solid var(--rule); border-radius: 5px;
  padding: 10px 12px; margin-top: 12px;
}
/* Shown once and never again — so it should look like it. */
.once {
  background: var(--daybreak-bg); border-left: 3px solid var(--daybreak);
  padding: 13px 16px; margin: 18px 0; border-radius: 0 5px 5px 0; font-size: 13px;
}
.once b { font-weight: 700; color: var(--daybreak); }

/* --- cash desk ---------------------------------------------------------- */
.panel {
  border: 1px solid var(--rule); background: var(--surface);
  border-radius: 6px; padding: 18px 20px; box-shadow: var(--shadow);
}
.panel h4 { margin: 0 0 4px; font-size: 15px; font-weight: 600; font-family: Poppins, sans-serif; }
.panel .sub { color: var(--faint); font-size: 12.5px; margin: 0 0 16px; }
.big {
  font: 600 30px/1 Inter, sans-serif; font-variant-numeric: tabular-nums;
  letter-spacing: -.02em; color: var(--ink);
}
.lbl {
  font-size: 10px; letter-spacing: .11em; text-transform: uppercase;
  color: var(--faint); margin: 14px 0 4px; font-weight: 600;
}
button.go { width: 100%; margin-top: 14px; }

/* --- end of day and proof ----------------------------------------------- */
.lede { color: var(--soft); font-size: 13px; margin: 0 0 14px; max-width: 76ch; }
.lede b { color: var(--ink); }
.card {
  border: 1px solid var(--rule); border-radius: 6px; background: var(--surface);
  overflow-x: auto; box-shadow: var(--shadow);
}
.pill {
  display: inline-block; font: 600 10px/1 Inter, sans-serif; letter-spacing: .06em;
  text-transform: uppercase; padding: 4px 7px; border-radius: 3px;
  border: 1px solid currentColor; white-space: nowrap;
}
.actions { display: flex; gap: 6px; flex-wrap: wrap; }
.note { font-size: 12px; color: var(--soft); line-height: 1.5; max-width: 52ch; margin-top: 5px; }
td.num { font-family: ui-monospace, Menlo, monospace; font-variant-numeric: tabular-nums; white-space: nowrap; }

.proofs { display: flex; gap: 14px; flex-wrap: wrap; margin-top: 14px; }
.nomedia {
  height: 170px; display: flex; align-items: center; justify-content: center;
  border-radius: 4px; background: var(--surface-2); color: var(--faint);
  font-size: 12px; padding: 0 18px; text-align: center;
}
/* A reused photograph is the classic proof-of-delivery fraud. It should not
   look like a note. */
.warnbox {
  border-left: 3px solid var(--bad); background: var(--surface-2);
  padding: 11px 14px; border-radius: 0 5px 5px 0; margin: 12px 0; font-size: 13px;
}
.warnbox b { color: var(--bad); }
