/* The dashboard shell — sidebar, page header, and the shared pieces the
   individual pages build on top of.
 *
 * Loaded alongside portal.css, not instead of it. That file styles the
 * contents of these pages (cards, stats, tables, charts) and is doing that job
 * well; what it had no concept of was a dashboard that is more than one page.
 * So this adds the frame and leaves the furniture alone.
 *
 * The colours here are the ones portal.css already uses — #0f1b33 for the dark
 * chrome, #f1f5f9 for the page, #e2e8f0 for borders — pulled into named tokens
 * so the two files can stop guessing at each other's hex codes. */

:root {
  --sh-ink: #0f1b33;          /* the dark chrome, from .topbar */
  --sh-ink-2: #1c2a47;
  --sh-page: #f1f5f9;
  --sh-line: #e2e8f0;
  --sh-text: #111827;
  --sh-muted: #64748b;
  --sh-accent: #2a78d6;       /* --series-1 in portal.css */
  --sh-accent-soft: #e8f0fb;
  --sh-warn: #b45309;
  --sh-warn-soft: #fef3c7;
  --sh-good: #1baf7a;
  --sh-bad: #dc2626;
  --sh-nav-w: 232px;
}

/* ---------- the frame ---------------------------------------------------- */

/* Applied to <body> on the staff pages, and to #dash-view on /portal/ — that
   page also holds a login card, which must not sit in a grid column beside a
   sidebar belonging to a session that does not exist yet. So the class carries
   only the layout, and body styling stays with portal.css. */
.has-shell {
  min-height: 100vh;
  /* The sidebar is a grid column, not a fixed overlay: the page keeps one
     scroll container, so the browser's own scroll restoration and the back
     button behave the way they do on any other page. */
  display: grid;
  grid-template-columns: var(--sh-nav-w) minmax(0, 1fr);
  align-items: start;
}

body.has-shell { margin: 0; background: var(--sh-page); }

.shell { position: sticky; top: 0; height: 100vh; }

.nv {
  height: 100vh;
  box-sizing: border-box;
  background: var(--sh-ink);
  color: #cbd5e1;
  display: flex;
  flex-direction: column;
  padding: 18px 12px 14px;
  gap: 18px;
}

.nv-brand {
  display: flex; align-items: center; gap: 10px;
  padding: 2px 8px 0; color: #fff; text-decoration: none;
  font-weight: 800; font-size: 1.05rem; letter-spacing: -.01em;
}
.nv-mark { width: 26px; height: 26px; color: var(--sh-accent); flex: 0 0 auto; }
.nv-mark svg { width: 100%; height: 100%; display: block; }

.nv-links { display: flex; flex-direction: column; gap: 2px; }

.nv-item {
  display: flex; align-items: center; gap: 11px;
  padding: 9px 10px; border-radius: 9px;
  color: #cbd5e1; text-decoration: none;
  font-size: .895rem; font-weight: 500;
  transition: background .12s ease, color .12s ease;
}
.nv-item:hover { background: var(--sh-ink-2); color: #fff; }

/* The current page is marked with a filled block and a brighter label rather
   than only a colour change: on a dark sidebar, colour alone is a weak signal
   and disappears entirely for anyone who cannot separate these two hues. */
.nv-item.on { background: var(--sh-accent); color: #fff; font-weight: 600; }
.nv-item.on .nv-ic { opacity: 1; }
.nv-ic { width: 17px; height: 17px; flex: 0 0 auto; opacity: .72; }

.nv-foot { margin-top: auto; display: flex; flex-direction: column; gap: 10px; }

.nv-acct {
  display: flex; align-items: center; gap: 10px;
  padding: 10px; border-radius: 10px; background: var(--sh-ink-2);
}
.nv-av {
  width: 30px; height: 30px; flex: 0 0 auto; border-radius: 8px;
  background: var(--sh-accent); color: #fff;
  display: grid; place-items: center;
  font-size: .74rem; font-weight: 700; letter-spacing: .02em;
}
.nv-acct-t { min-width: 0; display: flex; flex-direction: column; line-height: 1.25; }
.nv-acct-t b {
  color: #fff; font-size: .82rem; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.nv-acct-t i { color: #94a3b8; font-size: .7rem; font-style: normal; }

.nv-out {
  background: transparent; border: 1px solid #33415a; color: #cbd5e1;
  border-radius: 8px; padding: 8px 10px; font: inherit; font-size: .8rem;
  cursor: pointer;
}
.nv-out:hover { background: var(--sh-ink-2); color: #fff; }

/* ---------- the page beside it ------------------------------------------- */

.page {
  min-width: 0;           /* without this a wide table stretches the grid
                             column and pushes the sidebar off-screen */
  padding: 26px 30px 60px;
  max-width: 1400px;
}

.page-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 18px; flex-wrap: wrap; margin-bottom: 22px;
}
.ph-text h1 {
  margin: 0; font-size: 1.55rem; font-weight: 700;
  letter-spacing: -.02em; color: var(--sh-text);
}
.ph-text p { margin: 5px 0 0; color: var(--sh-muted); font-size: .9rem; max-width: 62ch; }
.ph-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

/* ---------- metric tiles -------------------------------------------------- */

.tiles {
  display: grid; gap: 12px; margin-bottom: 22px;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
}
.tile {
  background: #fff; border: 1px solid var(--sh-line); border-radius: 12px;
  padding: 15px 16px; min-width: 0;
}
.tile-l {
  display: block; font-size: .755rem; font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; color: var(--sh-muted); margin-bottom: 7px;
}
.tile-v {
  display: block; font-size: 1.75rem; font-weight: 700;
  letter-spacing: -.02em; line-height: 1.1; color: var(--sh-text);
}
.tile-f { display: block; margin-top: 6px; font-size: .78rem; color: var(--sh-muted); }

/* Direction is carried by an arrow as well as a colour, so the reading does
   not depend on telling green from red. */
.trend { font-weight: 600; }
.trend.up { color: var(--sh-good); }
.trend.down { color: var(--sh-bad); }
.trend.flat { color: var(--sh-muted); }

/* ---------- panels -------------------------------------------------------- */

.panel {
  background: #fff; border: 1px solid var(--sh-line);
  border-radius: 12px; margin-bottom: 18px; overflow: hidden;
}
.panel-h {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap;
  padding: 13px 16px; border-bottom: 1px solid var(--sh-line);
}
.panel-h h2 { margin: 0; font-size: .98rem; font-weight: 650; letter-spacing: -.01em; }
.panel-h p { margin: 3px 0 0; font-size: .8rem; color: var(--sh-muted); }
.panel-b { padding: 16px; }
.panel-b.flush { padding: 0; }

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

.tbl-wrap { overflow-x: auto; }
table.dt { width: 100%; border-collapse: collapse; background: #fff; font-size: .875rem; }
table.dt th {
  position: sticky; top: 0; z-index: 1;
  background: #f8fafc; text-align: left; white-space: nowrap;
  padding: 10px 14px; border-bottom: 1px solid var(--sh-line);
  font-size: .755rem; font-weight: 650; letter-spacing: .04em;
  text-transform: uppercase; color: var(--sh-muted);
}
table.dt td { padding: 11px 14px; border-bottom: 1px solid #f1f5f9; vertical-align: middle; }
table.dt tbody tr:last-child td { border-bottom: 0; }
table.dt tbody tr:hover { background: #f8fafc; }
table.dt .num { text-align: right; font-variant-numeric: tabular-nums; }

/* A sortable header is a button so it can be reached and fired from the
   keyboard; the caret is drawn only on the column actually in use. */
th.sortable { cursor: pointer; user-select: none; }
th.sortable:hover { color: var(--sh-text); }
th.sortable::after { content: ''; display: inline-block; width: 0; margin-left: 6px; }
th.sortable[aria-sort="ascending"]::after { content: '▲'; font-size: .6em; }
th.sortable[aria-sort="descending"]::after { content: '▼'; font-size: .6em; }

/* ---------- small parts --------------------------------------------------- */

.pill {
  display: inline-block; padding: 2px 8px; border-radius: 999px;
  font-size: .72rem; font-weight: 600; white-space: nowrap;
}
.pill-good { background: #dcfce7; color: #15803d; }
.pill-warn { background: var(--sh-warn-soft); color: var(--sh-warn); }
.pill-mute { background: #f1f5f9; color: var(--sh-muted); }
.pill-info { background: var(--sh-accent-soft); color: #1d4ed8; }

.btn {
  font: inherit; font-size: .84rem; font-weight: 550;
  padding: 8px 13px; border-radius: 8px; cursor: pointer;
  border: 1px solid var(--sh-line); background: #fff; color: var(--sh-text);
}
.btn:hover { background: #f8fafc; }
.btn-primary { background: var(--sh-accent); border-color: var(--sh-accent); color: #fff; }
.btn-primary:hover { background: #1f63b8; }
.btn:disabled { opacity: .55; cursor: not-allowed; }

.seg { display: inline-flex; border: 1px solid var(--sh-line); border-radius: 8px; overflow: hidden; background: #fff; }
.seg button {
  font: inherit; font-size: .82rem; padding: 7px 12px; border: 0;
  background: transparent; cursor: pointer; color: var(--sh-muted);
  border-right: 1px solid var(--sh-line);
}
.seg button:last-child { border-right: 0; }
.seg button.on { background: var(--sh-accent); color: #fff; font-weight: 600; }

.attn { display: flex; flex-direction: column; gap: 0; }
.attn-row {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 13px 16px; border-bottom: 1px solid #f1f5f9;
}
.attn-row:last-child { border-bottom: 0; }
.attn-dot { width: 8px; height: 8px; border-radius: 50%; margin-top: 6px; flex: 0 0 auto; }
.attn-dot.warn { background: #f59e0b; }
.attn-dot.info { background: var(--sh-accent); }
.attn-t { min-width: 0; }
.attn-t b { display: block; font-size: .885rem; font-weight: 600; }
.attn-t span { display: block; font-size: .8rem; color: var(--sh-muted); margin-top: 2px; }

.empty { padding: 34px 16px; text-align: center; color: var(--sh-muted); font-size: .88rem; }

.field-row { display: grid; gap: 14px; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.fld { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.fld label { font-size: .79rem; font-weight: 600; color: var(--sh-text); }
.fld .hint { font-size: .74rem; color: var(--sh-muted); }
.fld input, .fld select {
  font: inherit; font-size: .875rem; padding: 9px 11px;
  border: 1px solid #cbd5e1; border-radius: 8px; background: #fff; color: var(--sh-text);
  min-width: 0;
}
.fld input:focus, .fld select:focus { outline: 2px solid var(--sh-accent); outline-offset: -1px; border-color: var(--sh-accent); }
.fld input[aria-invalid="true"] { border-color: var(--sh-bad); }

.note { border-radius: 9px; padding: 11px 13px; font-size: .84rem; }
.note-bad { background: #fef2f2; color: #991b1b; border: 1px solid #fecaca; }
.note-good { background: #f0fdf4; color: #166534; border: 1px solid #bbf7d0; }
.note-info { background: var(--sh-accent-soft); color: #1e40af; border: 1px solid #bfdbfe; }

.mono { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: .82rem; }

/* ---------- section jump bar ---------------------------------------------- */

/* The site page is fifteen charts of scroll. This is how you get to one of
   them without reading past the other fourteen. */
.secnav {
  position: sticky; top: 0; z-index: 4;
  display: flex; gap: 4px; flex-wrap: wrap;
  margin: 0 0 18px; padding: 8px;
  background: rgba(241, 245, 249, .92);
  backdrop-filter: blur(6px);
  border: 1px solid var(--sh-line); border-radius: 10px;
}
.secnav a {
  padding: 6px 11px; border-radius: 7px; text-decoration: none;
  font-size: .82rem; font-weight: 550; color: var(--sh-muted);
  white-space: nowrap;
}
.secnav a:hover { background: #fff; color: var(--sh-text); }

/* Without this the sticky bar lands on top of whatever heading was just
   jumped to, so the section you asked for is the one thing hidden. */
[id^='sec-'] { scroll-margin-top: 66px; }

/* Somebody who prefers less motion gets the jump without the slide; everyone
   else gets enough movement to see which way the page went. */
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

/* ---------- narrow screens ------------------------------------------------ */

/* Below this the sidebar stops being a column and becomes a strip along the
   top: a 232px rail on a phone leaves nothing for the table it exists to help
   you read. The labels stay — icon-only navigation is a guessing game. */
@media (max-width: 860px) {
  .has-shell { grid-template-columns: 1fr; }
  .shell { position: static; height: auto; }
  .nv { height: auto; flex-direction: row; align-items: center; flex-wrap: wrap; padding: 10px 12px; gap: 10px; }
  .nv-links { flex-direction: row; flex-wrap: wrap; flex: 1 1 100%; order: 3; gap: 4px; }
  .nv-item { padding: 7px 9px; font-size: .82rem; }
  .nv-foot { margin: 0 0 0 auto; flex-direction: row; align-items: center; gap: 8px; }
  .nv-acct { padding: 5px 8px; background: transparent; }
  .nv-acct-t { display: none; }
  .page { padding: 18px 14px 48px; }
  /* The sidebar is a top strip at this width, so a second sticky bar under it
     would eat most of a phone screen. It scrolls away with the page instead. */
  .secnav { position: static; overflow-x: auto; flex-wrap: nowrap; }
  [id^='sec-'] { scroll-margin-top: 12px; }
  .ph-text h1 { font-size: 1.3rem; }
}

/* Staff looking at somebody else's dashboard.
   portal.css turned the old .topbar this colour, and removing that bar took
   the warning with it — leaving a staff account able to read another client's
   calls with nothing on screen saying so. The sidebar is the bar's replacement,
   so it inherits the job. The orange rule above the content and the tinted
   admin bar are still portal.css's, and all three now agree again. */
body.viewing-other .nv { background: #7c2d12; }
body.viewing-other .nv-item.on { background: #c2410c; }
body.viewing-other .nv-acct { background: #9a3412; }

@media print {
  .shell, .ph-actions, .secnav { display: none !important; }
  .has-shell { display: block; }
  .page { padding: 0; max-width: none; }

  /* The call dashboard prints through .print-head, which carries the company
     AND the date range the report covers. Its .page-head says the company a
     second time and the range not at all, so on paper it is a duplicate
     heading — hidden here rather than globally, because on the pages that
     have no .print-head it is the only heading there is. */
  #dash-view .page-head { display: none !important; }
}
