/* ============================================================================
   Dashboard layer — the operational UI on top of theme.css.
   ============================================================================

   theme.css carries the design system (tokens + primitives). This file adds the
   pieces a dashboard needs and a chat app does not: the app shell, KPI tiles,
   data tables, severity encoding, and the section rhythm.

   Load order matters:
       <link rel="stylesheet" href="theme.css">
       <link rel="stylesheet" href="dashboard.css">

   LIGHT BY DEFAULT, and that is a research call rather than a taste one. These
   pages are dense tables at 12-13px inside a document that gets printed and
   projected. Controlled studies (Ergonomics 2013, summarised by NN/g) find light
   mode ahead on visual-acuity tasks, and the gap widens as type gets smaller.
   Dark wins on glare comfort in dim rooms and on preference at night, neither of
   which governs a PDF. The dark theme is still fully supported by the toggle.

   ENCODING STATE WITHOUT THE ACCENT-RAIL CLICHE
   A coloured bar down the left edge of a rounded card is the house style of
   every generated dashboard on the internet, so state here is carried by an
   icon in a tinted chip, a semantic numeral, and a short rule under the value.
   ========================================================================== */

/* ------------------------------------------------------------------ shell */
body.dash {
  display: grid;
  grid-template-columns: 244px 1fr;
  grid-template-rows: 100vh;
  overflow: hidden;
}

.sidebar {
  background: var(--surface);
  border-right: 1px solid var(--border);
  display: flex; flex-direction: column;
  min-height: 0; overflow-y: auto;
}
.sidebar-brand {
  padding: var(--s-5) var(--s-5) var(--s-4);
  border-bottom: 1px solid var(--border);
  display: flex; gap: var(--s-3); align-items: flex-start;
}
/* The project number as a solid mark: an identity, not a decoration. */
.brand-mark {
  flex: none; width: 34px; height: 34px; border-radius: 9px;
  display: grid; place-items: center;
  font-family: var(--mono); font-size: 13px; font-weight: 700; letter-spacing: -.02em;
  color: var(--accent-ink);
  background: linear-gradient(150deg, var(--accent), var(--accent-deep));
  box-shadow: 0 2px 6px var(--accent-glow);
}
.sidebar-brand h1 {
  font-size: 14.5px; font-weight: 700; letter-spacing: -.012em; line-height: 1.25;
}
.sidebar-brand p { font-size: var(--fs-sm); color: var(--text-muted); margin: 5px 0 0; }

.sidebar-nav { padding: var(--s-3); display: flex; flex-direction: column; gap: 2px; }
.sidebar-nav a {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px; border-radius: 8px;
  color: var(--text-muted); text-decoration: none; font-size: 13.5px;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.sidebar-nav a svg { flex: none; opacity: .75; }
.sidebar-nav a:hover { background: var(--surface-2); color: var(--text); }
/* Filled, not rail-marked. */
.sidebar-nav a.active {
  background: var(--accent-soft); color: var(--accent-deep); font-weight: 600;
}
.sidebar-nav a.active svg { opacity: 1; }
.sidebar-nav .n {
  margin-left: auto; font-family: var(--mono); font-size: var(--fs-xs);
  color: var(--text-muted); font-variant-numeric: tabular-nums;   /* faint was 3.0:1; AA small text needs 4.5 */
}
.sidebar-foot {
  margin-top: auto; padding: var(--s-4) var(--s-5);
  border-top: 1px solid var(--border);
  font-size: var(--fs-xs); color: var(--text-faint); line-height: 1.7;
}
.sidebar-foot code {
  font-size: var(--fs-xs); color: var(--text-muted);
  overflow-wrap: anywhere; word-break: break-word; display: block;
}

.main { min-width: 0; overflow-y: auto; position: relative; }

/* A single soft wash behind the top of the page. The only ambient flourish in
   the interface, and it sits behind everything rather than on a component. */
.main::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 320px;
  background:
    radial-gradient(680px 260px at 12% -40%, var(--accent-glow), transparent 70%),
    radial-gradient(520px 220px at 88% -60%, var(--wash-2), transparent 70%);
  pointer-events: none; z-index: 0;
}

.topbar {
  position: sticky; top: 0; z-index: 10;
  display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-4) var(--s-6);
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: blur(10px) saturate(140%);
  -webkit-backdrop-filter: blur(10px) saturate(140%);
  border-bottom: 1px solid var(--border);
}
.topbar h2 { font-size: var(--fs-lg); font-weight: 700; letter-spacing: -.018em; }
.topbar .sub { font-size: var(--fs-sm); color: var(--text-muted); margin-top: 2px; }
.topbar .spacer { flex: 1; }

.content {
  padding: var(--s-6); display: flex; flex-direction: column; gap: var(--s-7);
  position: relative; z-index: 1;
}
/* The last section is at least a pane tall, so every section, including the
   short ones at the end, can be scrolled to the top of the pane. Without this
   the pane hits its bottom first, the click appears to do nothing, and the
   spy keeps the previous section highlighted. */
.content > .section:last-child { min-height: calc(100vh - 140px); }

/* ---------------------------------------------------------------- section */
.section > header {
  display: flex; align-items: baseline; gap: var(--s-3);
  margin-bottom: var(--s-4);
}
/* An uppercase mono eyebrow carries the hierarchy instead of a coloured bar. */
.section h3 {
  font-size: var(--fs-md); font-weight: 700; letter-spacing: -.015em;
}
.section .hint { font-size: var(--fs-sm); color: var(--text-muted); }
.section .spacer { flex: 1; }

/* -------------------------------------------------------------- kpi tiles */
.kpis {
  display: grid; gap: var(--s-3);
  grid-template-columns: repeat(auto-fit, minmax(196px, 1fr));
}
.kpi {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 12px; padding: var(--s-4);
  display: flex; flex-direction: column; gap: 10px;
  position: relative; overflow: hidden;
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.kpi:hover { border-color: var(--border-strong); box-shadow: var(--shadow-2); }
.kpi-head { display: flex; align-items: center; gap: 9px; }
/* The icon chip is where the state colour lives now. */
.kpi-icon {
  flex: none; width: 28px; height: 28px; border-radius: 8px;
  display: grid; place-items: center;
  background: var(--accent-soft); color: var(--accent-deep);
}
.kpi.ok    .kpi-icon { background: var(--ok-soft);     color: var(--ok); }
.kpi.warn  .kpi-icon { background: var(--warn-soft);   color: var(--warn); }
.kpi.danger .kpi-icon { background: var(--danger-soft); color: var(--danger); }
.kpi.muted .kpi-icon { background: var(--surface-3);   color: var(--text-faint); }
.kpi .label {
  font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: .1em;
  color: var(--text-muted); font-family: var(--mono); font-weight: 600;
}
.kpi .value {
  font-size: 30px; font-weight: 700; letter-spacing: -.03em; line-height: 1;
  font-variant-numeric: tabular-nums;
}
.kpi .value small { font-size: 14px; font-weight: 600; color: var(--text-muted); }
/* A short rule under the number, sized to the value, replaces the full-height
   rail: the same semantic signal without the borrowed silhouette. */
.kpi .value::after {
  content: ""; display: block; width: 28px; height: 3px; border-radius: 2px;
  margin-top: 10px; background: var(--accent); opacity: .85;
}
.kpi.ok .value::after { background: var(--ok); }
.kpi.warn .value::after { background: var(--warn); }
.kpi.danger .value::after { background: var(--danger); }
.kpi.muted .value::after { background: var(--border-strong); }
.kpi .note { font-size: var(--fs-sm); color: var(--text-muted); line-height: 1.45; }
/* The headline tile. One per row at most: if everything is emphasised, nothing is. */
.kpi.lead {
  background: linear-gradient(168deg, var(--surface), var(--lead-tint));
  border-color: var(--border-strong);
}
.kpi.lead .value { font-size: 36px; }

/* ------------------------------------------------------------------ table */
.table-wrap {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 12px; overflow-x: auto;
}
table.data { width: 100%; border-collapse: collapse; font-size: 13.5px; }
table.data th {
  text-align: left; font-size: var(--fs-xs); text-transform: uppercase;
  letter-spacing: .09em; color: var(--text-muted); font-weight: 700;
  padding: 11px var(--s-4); border-bottom: 1px solid var(--border);
  white-space: nowrap; background: var(--surface-2);
  position: sticky; top: 0;
}
table.data td {
  padding: 11px var(--s-4); border-bottom: 1px solid var(--border);
  vertical-align: top;
}
table.data tr:last-child td { border-bottom: 0; }
table.data tbody tr { transition: background var(--dur) var(--ease); }
table.data tbody tr:hover { background: var(--surface-2); }
table.data td.num, table.data th.num { text-align: right; font-variant-numeric: tabular-nums; }
table.data td.mono, .mono-cell {
  font-family: var(--mono); font-size: 12px; color: var(--text-muted);
}
table.data td:first-child { font-weight: 600; }
table.data td.wrap { white-space: normal; min-width: 260px; }
table.data .sub { color: var(--text-muted); font-size: var(--fs-sm); }

/* ------------------------------------------------------------------- list */
.rows { display: flex; flex-direction: column; gap: var(--s-2); }
.row-card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 10px; padding: var(--s-3) var(--s-4);
  display: flex; align-items: flex-start; gap: var(--s-3);
}
.row-card .grow { flex: 1; min-width: 0; }
.row-card .t { font-weight: 600; }
.row-card .d { color: var(--text-muted); font-size: var(--fs-sm); margin-top: 2px; }

/* --------------------------------------------------------------- keyvalue */
.kv { display: grid; grid-template-columns: max-content 1fr; gap: 9px var(--s-5); }
.kv dt { color: var(--text-muted); font-size: var(--fs-sm); }
.kv dd { margin: 0; font-variant-numeric: tabular-nums; }

/* ------------------------------------------------------------------- bars */
.bar-row { display: flex; align-items: center; gap: var(--s-3); }
.bar-row .bar-label { width: 190px; font-size: 13px; }
.bar-track {
  flex: 1; height: 8px; background: var(--surface-3);
  border-radius: var(--r-full); overflow: hidden;
}
.bar-fill { height: 100%; background: var(--accent); border-radius: var(--r-full); }
.bar-fill.ok { background: var(--ok); }
.bar-fill.warn { background: var(--warn); }
.bar-fill.danger { background: var(--danger); }
.bar-row .bar-val {
  width: 62px; text-align: right; font-family: var(--mono);
  font-size: 12.5px; color: var(--text-muted); font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------------ notes */
/* An icon and a tint, no left rail. */
.note-card {
  background: var(--accent-soft);
  border: 1px solid var(--accent-line);
  border-radius: 10px;
  padding: var(--s-3) var(--s-4);
  font-size: 13px; line-height: 1.6; color: var(--text);   /* muted on the tinted card was 4.4:1; AA needs 4.5 */
  display: flex; gap: 11px; align-items: flex-start; max-width: 108ch;
}
.note-card svg { flex: none; margin-top: 1px; color: var(--accent-deep); opacity: .9; }
.note-card strong, .note-card b { color: var(--text); font-weight: 700; }
.note-card.warn { background: var(--warn-soft); border-color: var(--warn-line); }
.note-card.warn svg { color: var(--warn); }
.note-card.danger { background: var(--danger-soft); border-color: var(--danger-line); }
.note-card.danger svg { color: var(--danger); }

/* --------------------------------------------------------------- segments */
.segbar {
  display: flex; height: 15px; border-radius: var(--r-full);
  overflow: hidden; background: var(--surface-3); border: 1px solid var(--border);
}
.segbar span { display: block; height: 100%; }
.seg-ok { background: linear-gradient(180deg, var(--ok), var(--ok-deep)); }
.seg-warn { background: linear-gradient(180deg, var(--warn), var(--warn-deep)); }
.seg-danger { background: linear-gradient(180deg, var(--danger), var(--danger-deep)); }
.seg-info { background: linear-gradient(180deg, var(--info), var(--info-deep)); }
.seg-muted { background: var(--border-strong); }
.seg-accent { background: linear-gradient(180deg, var(--accent), var(--accent-deep)); }
.seg-legend {
  display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-5); margin-top: var(--s-3);
}
.seg-legend .item { display: flex; align-items: center; gap: 7px; font-size: 13px; }
.seg-legend .dot { width: 9px; height: 9px; border-radius: 3px; flex: none; }
.seg-legend .n {
  font-family: var(--mono); font-variant-numeric: tabular-nums; color: var(--text-muted);
}

/* ----------------------------------------------------------------- utility */
.stack { display: flex; flex-direction: column; gap: var(--s-3); }
.cluster { display: flex; flex-wrap: wrap; gap: var(--s-2); align-items: center; }
.grid-2 { display: grid; gap: var(--s-4); grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); }
.muted { color: var(--text-muted); }
.faint { color: var(--text-faint); }
.mono { font-family: var(--mono); }
.tnum { font-variant-numeric: tabular-nums; }
.right { text-align: right; }

@media (max-width: 900px) {
  /* Two rows on a phone: the brand, then the section links as a strip that
     scrolls sideways. The first layout put everything on one row and let the
     tagline push the links off the right edge, so on a phone the navigation
     did not exist until you scrolled the header sideways. Found by the audit. */
  body.dash { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto 1fr; }
  .sidebar { flex-direction: row; flex-wrap: wrap; align-items: center; overflow: hidden; min-width: 0; }
  .sidebar-brand {
    flex: 0 0 100%; width: 100%; min-width: 0; align-items: center;
    padding: 10px 14px; border-bottom: 1px solid var(--border);
  }
  .sidebar-brand p { display: none; }
  .sidebar-nav {
    flex: 0 0 100%; width: 100%; min-width: 0; box-sizing: border-box;
    flex-direction: row; gap: 4px; padding: 6px 8px;
    overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none;
  }
  .sidebar-nav::-webkit-scrollbar { display: none; }
  .sidebar-nav a { flex: none; padding: 6px 10px; white-space: nowrap; }
  .sidebar-nav .n { margin-left: 6px; }
  .sidebar-foot { display: none; }
}


/* --------------------------------------------------------- capture mode */
/* One section, no shell. Used to photograph a single feature for the deck. */
body.capture {
  display: block; overflow: auto; background: var(--bg);
  padding: 26px 30px;
}
body.capture .capture-wrap { max-width: 1180px; margin: 0 auto; }
body.capture .section > header { margin-bottom: var(--s-4); }
