/*
 * Number API console — shared design system.
 *
 * Every console page loads this one stylesheet, so a change to a token or a component
 * lands everywhere at once. Pages contribute markup and their own behaviour; none of
 * them redefine a colour, a radius or a control.
 *
 * Tokens first, then layout, then components. Nothing below the token block hard-codes
 * a colour.
 */

:root {
  color-scheme: dark;

  /* Surfaces, darkest to lightest. The page sits on --bg; a card lifts to --surface;
     anything that sits on a card goes up again, so nesting stays legible. */
  --bg:        #080a0f;
  --bg-2:      #0c0f16;
  --surface:   #11151d;
  --surface-2: #161b25;
  --surface-3: #1d232f;
  --border:    #222a36;
  --border-2:  #2e3745;
  --border-3:  #3d4859;

  /* Text, strongest to faintest. */
  --text:   #eef2f8;
  --text-2: #98a3b6;
  --text-3: #667184;

  /* Accent and status. Each has a soft wash for fills and a light tint for text on
     that wash, so a badge never has to pick its own colours. */
  --accent:      #4f7cff;
  --accent-2:    #6b92ff;
  --accent-soft: #4f7cff1c;
  --accent-line: #4f7cff4d;
  --accent-text: #a8c0ff;

  --ok:        #2fd48f;
  --ok-soft:   #2fd48f1c;
  --warn:      #f5b544;
  --warn-soft: #f5b5441c;
  --err:       #fb6f6f;
  --err-soft:  #fb6f6f1c;

  /* Type scale. */
  --fs-xs:  11px;
  --fs-sm:  12.5px;
  --fs-md:  13.5px;
  --fs-lg:  15px;
  --fs-xl:  19px;
  --fs-2xl: 25px;

  /* Spacing scale — every gap and pad comes from here. */
  --s-1: 4px;
  --s-2: 8px;
  --s-3: 12px;
  --s-4: 16px;
  --s-5: 22px;
  --s-6: 30px;
  --s-7: 44px;

  --radius:      10px;
  --radius-sm:   7px;
  --radius-lg:   14px;
  --radius-pill: 999px;

  /* Two elevations: a resting card and something floating over the page. */
  --shadow-sm: 0 1px 2px #0006;
  --shadow:    0 18px 48px -12px #000000a6, 0 0 0 1px #ffffff08;
  --ring:      0 0 0 3px var(--accent-soft), 0 0 0 1px var(--accent);

  --sidebar-w: 244px;
  --control-h: 34px;

  --font: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}

/* ── Reset ──────────────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }

/* Components below set `display`, which would otherwise outrank the browser's own
   rule for the hidden attribute and leave `el.hidden = true` visible. */
[hidden] { display: none !important; }

html, body { height: 100%; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: var(--fs-md);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

a { color: var(--accent-text); text-decoration: none; }
a:hover { text-decoration: underline; }

button, input, select, textarea { font: inherit; color: inherit; }

:focus-visible { outline: none; box-shadow: var(--ring); border-radius: var(--radius-sm); }

code, .mono {
  font-family: var(--mono);
  font-size: 0.92em;
  font-variant-numeric: tabular-nums;
}

h1, h2, h3 { letter-spacing: -0.015em; }

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--border-2); border-radius: var(--radius-pill);
  border: 2px solid transparent; background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover { background: var(--border-3); background-clip: content-box; }

/* ── Shell ──────────────────────────────────────────────────────────────── */
/* Hidden until boot() has confirmed the session, so a page never flashes its chrome
   at somebody who is about to be redirected to the login screen. */
.shell { visibility: hidden; }
body.ready .shell { visibility: visible; }
.shell { display: grid; grid-template-columns: var(--sidebar-w) 1fr; min-height: 100vh; }

/* ── Sidebar ────────────────────────────────────────────────────────────── */
.sidebar {
  display: flex; flex-direction: column;
  background: var(--bg-2);
  border-right: 1px solid var(--border);
  padding: var(--s-5) var(--s-3) var(--s-3);
  position: sticky; top: 0; height: 100vh;
}

.brand {
  display: flex; align-items: center; gap: var(--s-2);
  padding: 0 var(--s-2) var(--s-5);
  font-size: var(--fs-lg); font-weight: 600; letter-spacing: -0.02em;
}
.brand .dot {
  width: 9px; height: 9px; border-radius: 50%; flex: none;
  background: var(--accent);
  box-shadow: 0 0 0 4px var(--accent-soft);
}
.brand em { font-style: normal; color: var(--text-3); font-weight: 500; }

.nav { display: flex; flex-direction: column; gap: 2px; }
.nav a {
  display: flex; align-items: center; gap: var(--s-3);
  padding: 8px var(--s-3);
  border-radius: var(--radius-sm);
  color: var(--text-2); font-size: var(--fs-md); font-weight: 500;
  position: relative;
  transition: background .12s, color .12s;
}
.nav a:hover { background: var(--surface-2); color: var(--text); text-decoration: none; }
.nav a[aria-current="page"] { background: var(--accent-soft); color: var(--accent-text); }
.nav a[aria-current="page"]::before {
  content: ""; position: absolute; left: 0; top: 50%; transform: translateY(-50%);
  width: 3px; height: 17px; border-radius: 0 3px 3px 0; background: var(--accent);
}
.nav a svg { width: 17px; height: 17px; flex: none; opacity: .85; }
.nav a[aria-current="page"] svg { opacity: 1; }

.nav-label {
  padding: var(--s-4) var(--s-3) var(--s-1);
  font-size: var(--fs-xs); font-weight: 600;
  text-transform: uppercase; letter-spacing: .08em;
  color: var(--text-3);
}

.sidebar-foot { margin-top: auto; padding-top: var(--s-4); border-top: 1px solid var(--border); }

.identity { display: flex; align-items: center; gap: var(--s-3); padding: var(--s-2) var(--s-2) var(--s-3); }
.avatar {
  width: 32px; height: 32px; flex: none;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--accent-soft); color: var(--accent-text);
  border: 1px solid var(--accent-line);
  font-weight: 600; font-size: var(--fs-md);
}
.identity .who { min-width: 0; }
.identity .name {
  font-weight: 600; font-size: var(--fs-sm);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.identity .role { font-size: var(--fs-xs); color: var(--text-3); }

/* ── Content ────────────────────────────────────────────────────────────── */
.content { min-width: 0; }
.content-inner {
  max-width: 1360px; margin: 0 auto;
  padding: var(--s-6) var(--s-6) var(--s-7);
  display: flex; flex-direction: column; gap: var(--s-5);
}

.page-head {
  display: flex; align-items: flex-start; gap: var(--s-4);
  flex-wrap: wrap;
  padding-bottom: var(--s-1);
}
.page-head h1 { margin: 0; font-size: var(--fs-2xl); font-weight: 650; }
.page-head .sub { margin: var(--s-1) 0 0; color: var(--text-2); font-size: var(--fs-md); max-width: 62ch; }
.page-head .grow { flex: 1; }
.page-head .actions { display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap; padding-top: 2px; }

/* ── Buttons ────────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s-2);
  height: var(--control-h); padding: 0 var(--s-4);
  border: 1px solid transparent; border-radius: var(--radius-sm);
  background: var(--accent); color: #fff;
  font-size: var(--fs-md); font-weight: 550; white-space: nowrap;
  cursor: pointer;
  box-shadow: var(--shadow-sm);
  transition: background .12s, border-color .12s, color .12s, opacity .12s;
}
.btn:hover:not(:disabled) { background: var(--accent-2); }
.btn:disabled { opacity: .45; cursor: not-allowed; }
.btn:focus-visible { box-shadow: var(--ring); }

.btn.ghost {
  background: var(--surface-2); color: var(--text);
  border-color: var(--border-2); box-shadow: none;
}
.btn.ghost:hover:not(:disabled) { background: var(--surface-3); border-color: var(--border-3); }

.btn.danger { background: transparent; color: var(--err); border-color: #fb6f6f40; box-shadow: none; }
.btn.danger:hover:not(:disabled) { background: var(--err-soft); border-color: var(--err); }

.btn.sm { height: 27px; padding: 0 var(--s-3); font-size: var(--fs-sm); }

/* ── Form controls ──────────────────────────────────────────────────────── */
.select, .input {
  width: 100%; height: var(--control-h);
  padding: 0 var(--s-3);
  background: var(--bg-2); color: var(--text);
  border: 1px solid var(--border-2); border-radius: var(--radius-sm);
  font-size: var(--fs-md);
  transition: border-color .12s, box-shadow .12s;
}
.select {
  appearance: none; cursor: pointer;
  padding-right: var(--s-6);
  background-image: linear-gradient(45deg, transparent 50%, var(--text-3) 50%),
                    linear-gradient(135deg, var(--text-3) 50%, transparent 50%);
  background-position: calc(100% - 17px) 15px, calc(100% - 12px) 15px;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}
.input:focus, .select:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.input::placeholder { color: var(--text-3); }
.input:disabled, .select:disabled { opacity: .5; cursor: not-allowed; }

textarea.input { height: auto; resize: vertical; min-height: 68px; padding: var(--s-2) var(--s-3); line-height: 1.6; }

.field { display: flex; flex-direction: column; gap: 5px; margin-bottom: var(--s-4); }
.field > label { font-size: var(--fs-sm); font-weight: 550; color: var(--text-2); }
.field .hint { margin: 0; }
.field-row { display: flex; gap: var(--s-3); }
.field-row > * { flex: 1; }

.hint { font-size: var(--fs-sm); color: var(--text-3); }

.search { position: relative; display: inline-flex; }
.search .input { padding-left: 34px; min-width: 232px; width: auto; }
.search svg {
  position: absolute; left: 11px; top: 50%; transform: translateY(-50%);
  width: 15px; height: 15px; color: var(--text-3); pointer-events: none;
}

.toolbar { display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap; }
.toolbar .select { width: auto; min-width: 156px; }

/* ── Cards and tables ───────────────────────────────────────────────────── */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
}

.card-head {
  display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-4) var(--s-5);
  border-bottom: 1px solid var(--border);
}
.card-head h2 { margin: 0; font-size: var(--fs-lg); font-weight: 600; }
.card-head .note { margin-left: auto; font-size: var(--fs-sm); color: var(--text-3); }
/* A filter that belongs to one table sits in that table's header. The note keeps the
   margin that pushes both to the right; the search only needs to stop growing. */
.card-head .search .input { min-width: 15rem; height: 30px; font-size: var(--fs-sm); }
.card-head .note + .search { margin-left: var(--s-3); }

.card-body { padding: var(--s-5); }
.card-body.tight { padding: 0; }

.table-wrap { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; font-size: var(--fs-md); }
th, td { padding: 11px var(--s-5); text-align: left; white-space: nowrap; }

thead th {
  position: sticky; top: 0; z-index: 1;
  background: var(--surface-2);
  font-size: var(--fs-xs); font-weight: 600;
  text-transform: uppercase; letter-spacing: .06em;
  color: var(--text-3);
  border-bottom: 1px solid var(--border);
}

tbody tr { border-bottom: 1px solid var(--border); }
tbody tr:last-child { border-bottom: none; }
tbody tr:hover { background: var(--surface-2); }

td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }
td.wrap { white-space: normal; }
/* A grant cell can hold many badges; cap it so the columns after it stay on screen. */
td.grants { max-width: 30rem; }

/* The row you are currently looking at, in a table you pick rows from. */
tbody tr.pick { cursor: pointer; }
tbody tr.picked { background: var(--accent-soft); }
tbody tr.picked td:first-child { box-shadow: inset 3px 0 0 var(--accent); }

/* An expandable row and the panel it folds out. The drawer is a table row so it stays
   in the same column grid, but its content is free to be its own table. */
td.caret { color: var(--text-3); width: 1%; padding-right: 0; user-select: none; }
tbody tr.picked td.caret { color: var(--accent-text); }
tbody tr.drawer { background: var(--bg-2); }
tbody tr.drawer:hover { background: var(--bg-2); }
tbody tr.drawer > td { padding: var(--s-3) var(--s-5) var(--s-4); }

.subtable { width: auto; min-width: 32rem; border-collapse: collapse; }
.subtable th {
  position: static; background: transparent;
  padding: 4px var(--s-4) 4px 0;
  font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: .06em;
  color: var(--text-3); border-bottom: 1px solid var(--border);
}
.subtable td { padding: 5px var(--s-4) 5px 0; border-bottom: none; }
.subtable tbody tr:hover { background: transparent; }
.subtable tbody tr.pick { cursor: pointer; }
.subtable tbody tr.pick:hover { background: var(--surface-2); }
.subtable tbody tr.picked { background: var(--accent-soft); }
.subtable tbody tr.picked td:first-child { box-shadow: none; }
/* A country under its application. The rule is the indent doing the work, not a colour:
   the depth should be readable without relying on one. */
.subtable td.indent { padding-left: var(--s-4); border-left: 1px solid var(--border-2); }
.subtable tr.leaf td { color: var(--text-2); }

.muted { color: var(--text-2); }
.faint { color: var(--text-3); }
.strong { font-weight: 600; }

.table-note { margin: 0; padding: var(--s-3) var(--s-5) var(--s-4); border-top: 1px solid var(--border); }
.table-note strong { color: var(--text-2); font-weight: 600; }

.empty { padding: var(--s-7) var(--s-4); text-align: center; color: var(--text-3); white-space: normal; }
.empty .title { font-size: var(--fs-lg); font-weight: 600; color: var(--text-2); margin-bottom: var(--s-1); }

.skeleton {
  display: block; height: 10px; border-radius: var(--radius-pill);
  background: linear-gradient(90deg, var(--surface-2) 25%, var(--surface-3) 50%, var(--surface-2) 75%);
  background-size: 200% 100%;
  animation: shimmer 1.3s infinite linear;
}
@keyframes shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }

/* ── Badges ─────────────────────────────────────────────────────────────── */
.badge {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 9px;
  border-radius: var(--radius-pill);
  background: var(--surface-3); color: var(--text-2);
  font-size: var(--fs-xs); font-weight: 600;
  letter-spacing: .02em; white-space: nowrap;
}
.badge.ok   { background: var(--ok-soft);     color: var(--ok); }
.badge.warn { background: var(--warn-soft);   color: var(--warn); }
.badge.err  { background: var(--err-soft);    color: var(--err); }
.badge.info { background: var(--accent-soft); color: var(--accent-text); }
.badge-group { display: inline-flex; flex-wrap: wrap; gap: var(--s-1); }
/* A ceiling shown on a grant badge. Warn-coloured: it is a restriction, and reading it
   as just more scope would be the wrong way round. */
.badge .cap { color: var(--warn); font-variant-numeric: tabular-nums; }
/* The two rate boxes inside a grant row, which is a tighter space than a modal field. */
.grant .rates { margin-bottom: var(--s-2); }
.grant .rates .field { margin-bottom: 0; }
.grant .rates .input { height: 30px; font-size: var(--fs-sm); }

/* ── Stat tiles ─────────────────────────────────────────────────────────── */
.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(178px, 1fr)); gap: var(--s-3); }
.stat {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--s-4) var(--s-5);
  display: flex; flex-direction: column; gap: 2px;
}
.stat .k {
  font-size: var(--fs-xs); font-weight: 600;
  text-transform: uppercase; letter-spacing: .07em; color: var(--text-3);
}
.stat .v {
  font-size: var(--fs-2xl); font-weight: 650; line-height: 1.2;
  letter-spacing: -0.02em; font-variant-numeric: tabular-nums;
}
.stat .s { font-size: var(--fs-sm); color: var(--text-2); }

.meter { height: 6px; min-width: 60px; border-radius: var(--radius-pill); background: var(--surface-3); overflow: hidden; }
.meter i { display: block; height: 100%; background: var(--accent); border-radius: inherit; transition: width .3s; }
.meter.ok i { background: var(--ok); }

/* ── Chart ──────────────────────────────────────────────────────────────── */
.chart { display: flex; align-items: flex-end; gap: 2px; height: 140px; padding: var(--s-5) var(--s-5) var(--s-4); }
.chart .col { flex: 1; min-width: 3px; display: flex; flex-direction: column; justify-content: flex-end; gap: 1px; }
.chart .a { background: var(--accent); border-radius: 2px 2px 0 0; }
.chart .b { background: var(--ok); border-radius: 2px 2px 0 0; }
.legend { display: flex; gap: var(--s-4); padding: 0 var(--s-5) var(--s-4); font-size: var(--fs-sm); color: var(--text-2); }
.legend i { display: inline-block; width: 9px; height: 9px; border-radius: 3px; margin-right: 6px; vertical-align: middle; }

/* ── Pager ──────────────────────────────────────────────────────────────── */
.pager {
  display: flex; align-items: center; gap: var(--s-2);
  padding: var(--s-3) var(--s-5);
  border-top: 1px solid var(--border);
  font-size: var(--fs-sm); color: var(--text-3);
}
.pager .grow { flex: 1; }
.pager button {
  height: 27px; padding: 0 var(--s-3);
  background: transparent; color: var(--text-2);
  border: 1px solid var(--border-2); border-radius: var(--radius-sm);
  font-size: var(--fs-sm); cursor: pointer;
  transition: color .12s, border-color .12s;
}
.pager button:hover:not(:disabled) { color: var(--text); border-color: var(--border-3); }
.pager button:disabled { opacity: .35; cursor: not-allowed; }

/* ── Modal ──────────────────────────────────────────────────────────────── */
.modal {
  position: fixed; inset: 0; z-index: 60;
  background: #04060bd9; backdrop-filter: blur(3px);
  display: none; align-items: center; justify-content: center; padding: var(--s-4);
}
.modal.open { display: flex; }
.modal-card {
  width: 100%; max-width: 560px; max-height: 88vh; overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border-2); border-radius: var(--radius-lg);
  padding: var(--s-5);
  box-shadow: var(--shadow);
  animation: rise .16s ease-out;
}
@keyframes rise { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
.modal-card h2 { margin: 0 0 var(--s-2); font-size: var(--fs-xl); font-weight: 620; }
.modal-card > p { margin: 0 0 var(--s-5); color: var(--text-2); font-size: var(--fs-sm); }
.modal-foot {
  display: flex; justify-content: flex-end; gap: var(--s-2);
  margin-top: var(--s-5); padding-top: var(--s-4);
  border-top: 1px solid var(--border);
}

/* ── Chips and pickers ──────────────────────────────────────────────────── */
.chips { display: flex; flex-wrap: wrap; gap: var(--s-1); }
.chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 10px;
  background: var(--surface-2); border: 1px solid var(--border-2);
  border-radius: var(--radius-pill);
  font-size: var(--fs-sm); cursor: pointer;
  transition: background .12s, border-color .12s;
}
.chip:hover { background: var(--surface-3); }
.chip:has(input:checked) { background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent-text); }
.chip input { accent-color: var(--accent); margin: 0; }

.grant { border: 1px solid var(--border); border-radius: var(--radius); margin-bottom: var(--s-2); overflow: hidden; }
.grant > summary {
  display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  cursor: pointer; list-style: none;
  background: var(--surface-2);
}
.grant > summary::-webkit-details-marker { display: none; }
.grant > summary .name { font-weight: 550; }
.grant > summary .scope { margin-left: auto; font-size: var(--fs-sm); color: var(--text-3); }
.grant[open] > summary { border-bottom: 1px solid var(--border); }
.grant .body { padding: var(--s-4); background: var(--bg-2); }
.grant .row { display: flex; gap: var(--s-2); margin-bottom: var(--s-3); }
.grant input[type=checkbox] { accent-color: var(--accent); margin: 0; }

.country-search { display: flex; align-items: center; gap: var(--s-2); margin-bottom: var(--s-2); }
.country-search .input { height: 30px; font-size: var(--fs-sm); }
.country-search .shown { font-size: var(--fs-xs); color: var(--text-3); white-space: nowrap; }

.country-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(78px, 1fr));
  gap: 3px; max-height: 196px; overflow-y: auto;
}
.country-grid label {
  display: flex; align-items: center; gap: 5px;
  padding: 3px 6px; border-radius: var(--radius-sm);
  font-size: var(--fs-sm); cursor: pointer;
}
.country-grid label:hover { background: var(--surface-2); }
.country-grid label:has(input:checked) { background: var(--accent-soft); color: var(--accent-text); }

/* A read-only sample of what a setting will produce. Neutral border: unlike .reveal
   it is not showing a secret, it is showing arithmetic. */
.preview {
  padding: var(--s-3); background: var(--bg-2);
  border: 1px solid var(--border-2); border-radius: var(--radius-sm);
  font-family: var(--mono); font-size: var(--fs-sm); line-height: 1.7;
  max-height: 180px; overflow-y: auto;
}
.preview .bad { color: var(--err); }

/* Shown once and never again, so the warning border is the point. */
.reveal {
  padding: var(--s-4); background: var(--bg-2);
  border: 1px solid var(--warn); border-radius: var(--radius-sm);
  word-break: break-all; font-family: var(--mono); font-size: var(--fs-sm);
}

/* ── Code blocks and the Try it runner ──────────────────────────────────── */
/* The copy button sits over the block rather than beside it, so a wide snippet keeps
   the full column width and the control is in the same place on every one. */
.code { position: relative; }
.code .copy {
  position: absolute; top: var(--s-2); right: var(--s-2); z-index: 1;
  height: 25px; padding: 0 10px;
  background: var(--surface-3); color: var(--text-2);
  border: 1px solid var(--border-2); border-radius: var(--radius-sm);
  font-size: var(--fs-xs); font-weight: 600; cursor: pointer;
  opacity: 0; transition: opacity .12s, color .12s, border-color .12s;
}
.code:hover .copy, .code .copy:focus-visible { opacity: 1; }
.code .copy:hover { color: var(--text); border-color: var(--border-3); }
.code-label {
  position: absolute; top: var(--s-2); left: var(--s-4);
  font-family: var(--mono); font-size: var(--fs-xs); color: var(--text-3);
}
.code-label ~ pre { padding-top: var(--s-6); }

/* The key is the widest thing in its column and the thing people came for, so it gets
   the room and a permanently visible copy control rather than a hover-only one. */
.key-row { display: flex; align-items: center; gap: var(--s-2); }
code.key {
  padding: 2px 7px;
  background: var(--surface-3); border: 1px solid var(--border-2);
  border-radius: var(--radius-sm);
  color: var(--accent-text); white-space: nowrap;
}
.copy.inline { position: static; opacity: 1; flex: none; }

.runner { max-width: 620px; }
.run-row { display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap; margin-top: var(--s-2); }
.run-row .grow { flex: 1; }

.out {
  margin: var(--s-4) 0 0;
  padding: var(--s-4);
  max-height: 340px; overflow: auto;
  background: var(--bg-2);
  border: 1px solid var(--border); border-radius: var(--radius);
  font-family: var(--mono); font-size: var(--fs-sm); line-height: 1.6;
  white-space: pre-wrap; word-break: break-word;
}
.out.bad { border-color: #fb6f6f59; }

/* ── Toast ──────────────────────────────────────────────────────────────── */
.toast {
  position: fixed; bottom: var(--s-6); left: 50%;
  transform: translate(-50%, 18px);
  padding: 10px var(--s-5);
  background: var(--surface-3); color: var(--text);
  border: 1px solid var(--border-2); border-radius: var(--radius-pill);
  box-shadow: var(--shadow);
  font-size: var(--fs-md); font-weight: 500;
  opacity: 0; pointer-events: none; z-index: 80;
  transition: opacity .18s, transform .18s;
}
.toast.show { opacity: 1; transform: translate(-50%, 0); }
.toast.err { border-color: var(--err); color: var(--err); }

/* ── Inline messages ────────────────────────────────────────────────────── */
.msg { padding: var(--s-3) var(--s-4); border-radius: var(--radius-sm); font-size: var(--fs-sm); }
.msg.err { background: var(--err-soft); color: var(--err); }
.msg.ok  { background: var(--ok-soft);  color: var(--ok); }

.notice {
  padding: var(--s-3) var(--s-4);
  background: var(--accent-soft);
  border: 1px solid var(--accent-line);
  border-radius: var(--radius);
  font-size: var(--fs-sm); color: var(--text-2);
}
.notice.warn { background: var(--warn-soft); border-color: #f5b54440; }

/* ── Sign-in ────────────────────────────────────────────────────────────── */
.auth { min-height: 100vh; display: grid; place-items: center; padding: var(--s-4); }
.auth-card {
  width: 100%; max-width: 372px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--s-6);
  box-shadow: var(--shadow);
}
.auth-card .brand { justify-content: center; padding-bottom: var(--s-2); }
.auth-card .lede { text-align: center; color: var(--text-2); font-size: var(--fs-sm); margin: 0 0 var(--s-5); }

/* ── Documentation page ─────────────────────────────────────────────────── */
.doc { max-width: 78ch; }
.doc h2 { margin: var(--s-6) 0 var(--s-3); font-size: var(--fs-lg); font-weight: 620; }
.doc h2:first-child { margin-top: 0; }
.doc h3 { margin: var(--s-5) 0 var(--s-2); font-size: var(--fs-md); font-weight: 620; color: var(--text-2); }
.doc p { color: var(--text-2); }
.doc pre {
  margin: 0 0 var(--s-4);
  padding: var(--s-4);
  background: var(--bg-2);
  border: 1px solid var(--border); border-radius: var(--radius);
  overflow-x: auto;
}
.doc pre code { font-size: var(--fs-sm); line-height: 1.65; }
.doc :not(pre) > code {
  padding: 1px 6px;
  background: var(--surface-3); border-radius: var(--radius-sm);
  color: var(--accent-text);
}
.doc table { margin-bottom: var(--s-4); }
.doc td, .doc th { padding: var(--s-2) var(--s-3); }
.doc .card { padding: var(--s-5); }

/* ── Narrow screens ─────────────────────────────────────────────────────── */
/* The sidebar stops being a column and becomes a scrolling strip along the top, so a
   phone gets the whole width for the table it came to read. */
@media (max-width: 900px) {
  .shell { grid-template-columns: 1fr; }
  .sidebar {
    position: static; height: auto;
    flex-direction: row; align-items: center; gap: var(--s-3);
    border-right: none; border-bottom: 1px solid var(--border);
    padding: var(--s-3) var(--s-4);
    overflow-x: auto;
  }
  .brand { padding: 0; flex: none; }
  .nav { flex-direction: row; gap: var(--s-1); }
  .nav a { padding: 6px var(--s-3); white-space: nowrap; }
  .nav a[aria-current="page"]::before { display: none; }
  .nav-label { display: none; }
  .sidebar-foot { margin: 0 0 0 auto; padding: 0; border: none; }
  .identity { padding: 0; }
  .identity .who { display: none; }
  .content-inner { padding: var(--s-4) var(--s-4) var(--s-6); gap: var(--s-4); }
  .page-head h1 { font-size: var(--fs-xl); }
  th, td { padding: 10px var(--s-4); }
  .card-head, .table-note, .pager { padding-left: var(--s-4); padding-right: var(--s-4); }
  .card-body { padding: var(--s-4); }
}

/* ── One board entry: the thread ─────────────────────────────────────────── */
/* A conversation reads down one column with the facts pinned beside it, the way an
   issue tracker does. Below tablet width the facts move above the conversation --
   on a phone the state of the entry is what you want first. */
.thread {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 272px;
  gap: var(--s-5);
  align-items: start;
}
.thread > .side { display: flex; flex-direction: column; gap: var(--s-4); }

.entry-title { display: flex; align-items: center; gap: var(--s-3); flex-wrap: wrap; }
.entry-title h1 { margin: 0; font-size: var(--fs-2xl); font-weight: 650; }
.entry-title .num { color: var(--text-3); font-weight: 400; }

/* The sidebar facts. A definition list rather than a table: each is one label and one
   value, and a table would put borders around four rows of nothing. */
.facts { display: flex; flex-direction: column; gap: var(--s-4); }
.facts .k {
  font-size: var(--fs-xs); font-weight: 600; color: var(--text-3);
  text-transform: uppercase; letter-spacing: .06em; margin-bottom: 5px;
}
.facts .v { font-size: var(--fs-md); color: var(--text); word-break: break-word; }

/* ── Comments ───────────────────────────────────────────────────────────── */
.timeline { display: flex; flex-direction: column; gap: var(--s-4); }
.comment { display: flex; gap: var(--s-3); align-items: flex-start; }
.comment .bubble {
  flex: 1; min-width: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
.comment .bubble > .head {
  display: flex; align-items: center; gap: var(--s-2);
  padding: 9px var(--s-4);
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
  font-size: var(--fs-sm);
}
.comment .bubble > .head .who { font-weight: 600; }
.comment .bubble > .head .when { color: var(--text-3); }
.comment .bubble > .head .btn { margin-left: auto; }
/* Somebody else's words: shown as written, never as markup. The page escapes them and
   this keeps the line breaks they typed. */
.comment .bubble > .body {
  padding: var(--s-4);
  font-size: var(--fs-md); line-height: 1.6;
  white-space: pre-wrap; overflow-wrap: anywhere;
}

/* ── Attachments ────────────────────────────────────────────────────────── */
/* auto-fill rather than a fixed count: two screenshots should not each stretch to half
   the width, and eight should wrap instead of shrinking to thumbnails. */
.attachments {
  display: grid; gap: var(--s-3);
  grid-template-columns: repeat(auto-fill, minmax(168px, 1fr));
}
.attach {
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface-2); overflow: hidden;
  display: flex; flex-direction: column;
}
.attach .shot {
  display: block; width: 100%; height: 118px;
  object-fit: cover; background: var(--bg-2);
  border: none; padding: 0; cursor: zoom-in;
}
.attach .file {
  display: grid; place-items: center; height: 118px;
  background: var(--bg-2); color: var(--text-3);
  font-size: var(--fs-xs); font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase;
}
.attach .foot {
  display: flex; align-items: center; gap: var(--s-2);
  padding: var(--s-2) var(--s-3);
  border-top: 1px solid var(--border);
  font-size: var(--fs-sm); min-width: 0;
}
.attach .foot a {
  color: var(--text); text-decoration: none;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.attach .foot a:hover { color: var(--accent-text); text-decoration: underline; }
.attach .foot .size { color: var(--text-3); font-size: var(--fs-xs); white-space: nowrap; }
.attach .foot .btn { margin-left: auto; }

/* Full size, over the page. Same backdrop as a modal so it reads as the same idea. */
.lightbox {
  position: fixed; inset: 0; z-index: 90;
  display: grid; place-items: center;
  padding: var(--s-5);
  background: #05070ce6; backdrop-filter: blur(3px);
  cursor: zoom-out;
}
.lightbox img {
  max-width: 100%; max-height: 100%;
  border-radius: var(--radius); box-shadow: var(--shadow);
}

@media (max-width: 980px) {
  .thread { grid-template-columns: minmax(0, 1fr); }
  .thread > .side { order: -1; }
}

/* The way back to the board, above the title rather than beside it: it is where you
   came from, not something you do to this entry. */
.page-head .back {
  display: inline-block; margin-bottom: 5px;
  color: var(--text-3); font-size: var(--fs-sm); text-decoration: none;
}
.page-head .back:hover { color: var(--accent-text); }

.thread > .main { display: flex; flex-direction: column; gap: var(--s-4); min-width: 0; }

/* Free text somebody typed: their line breaks kept, long identifiers wrapped rather
   than stretching the card. */
.prose { font-size: var(--fs-md); line-height: 1.65; white-space: pre-wrap; overflow-wrap: anywhere; }

.composer { margin-top: var(--s-4); }
.composer textarea { resize: vertical; min-height: 78px; line-height: 1.55; }
.composer .row { display: flex; align-items: center; gap: var(--s-3); margin-top: var(--s-3); }
.composer .row .btn { margin-left: auto; }
/* The conversation already has a divider above it when there is one; without comments
   the composer is the whole card and needs no line. */
.timeline + .composer { border-top: 1px solid var(--border); padding-top: var(--s-4); }

.dropzone {
  display: flex; align-items: center; gap: var(--s-3); flex-wrap: wrap;
  margin-top: var(--s-3); padding: var(--s-3) var(--s-4);
  border: 1px dashed var(--border-2); border-radius: var(--radius);
  background: var(--bg-2);
}
.attachments + .dropzone { margin-top: var(--s-4); }
#drop.over .dropzone { border-color: var(--accent); background: var(--accent-soft); }
#drop.over .dropzone .hint { color: var(--accent-text); }

/* A row that opens something. Underlined only on hover, so a column of them does not
   read as a wall of links. */
td a.open { color: var(--text); text-decoration: none; }
td a.open:hover { color: var(--accent-text); text-decoration: underline; }

/* ── Segmented control ───────────────────────────────────────────────────── */
/* For a handful of periods looked at constantly: one click apart, and which one is
   showing is readable without opening anything. A select hides both. */
.segmented {
  display: inline-flex;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 2px;
  gap: 2px;
}
.segmented button {
  appearance: none; cursor: pointer;
  border: none; background: none;
  padding: 0 var(--s-3);
  height: calc(var(--control-h) - 8px);
  border-radius: calc(var(--radius) - 3px);
  color: var(--text-2);
  font: inherit; font-size: var(--fs-sm); font-weight: 550;
  white-space: nowrap;
}
.segmented button:hover { color: var(--text); background: var(--surface-3); }
.segmented button[aria-pressed="true"] {
  background: var(--accent-soft);
  color: var(--accent-text);
  box-shadow: inset 0 0 0 1px var(--accent-line);
}
.segmented button:focus-visible { outline: none; box-shadow: var(--ring); }

@media (max-width: 720px) {
  /* Four periods will not sit on one phone line; let the row wrap rather than
     scrolling the whole header sideways. */
  .segmented { flex-wrap: wrap; }
}

/* ── Filter row ──────────────────────────────────────────────────────────── */
/* A filter that belongs to one column sits under that column's heading, where the
   reader is already looking, rather than in the page corner where it has to be hunted
   for and gives no clue which column it acts on. */
thead tr.filters th {
  padding-top: 6px; padding-bottom: 8px;
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
  text-transform: none; letter-spacing: 0;
  position: sticky; top: 33px; z-index: 1;
}
.input.sm {
  height: 27px; padding: 0 var(--s-3);
  font-size: var(--fs-sm); font-weight: 400;
  min-width: 8rem; width: 100%;
}
@media (max-width: 720px) {
  /* The heading row is taller when it wraps, so the filters would stick over it. */
  thead tr.filters th { position: static; }
}

/* ── Edit history ────────────────────────────────────────────────────────── */
/* The mark on an edited comment. A button rather than text because it opens something,
   and quiet because it is a footnote, not a headline. */
.linky {
  appearance: none; border: none; background: none; padding: 0;
  color: var(--text-3); font: inherit; font-size: var(--fs-sm);
  cursor: pointer; text-decoration: underline dotted; text-underline-offset: 3px;
}
.linky:hover { color: var(--accent-text); }
.comment .bubble > .head .grow { flex: 1; }

.history { list-style: none; margin: 0; padding: 0; }
.history li { padding: 0 0 var(--s-4) var(--s-4); border-left: 2px solid var(--border); position: relative; }
.history li:last-child { padding-bottom: 0; }
.history li::before {
  content: ""; position: absolute; left: -5px; top: 6px;
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--border-3);
}
.history li.current::before { background: var(--accent); }
.history .when { font-size: var(--fs-sm); color: var(--text-3); margin-bottom: 5px; }
.history .was {
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: var(--s-3);
  font-size: var(--fs-md); line-height: 1.55;
  white-space: pre-wrap; overflow-wrap: anywhere;
}
.history li.current .was { border-color: var(--accent-line); }
.history .note { font-size: var(--fs-xs); color: var(--text-3); margin-top: 5px; }

/* A row with an open question against it. Marked, not hidden: the point of holding the
   removal is that the entry stays readable while somebody decides. */
tbody tr.flagged > td:first-child { box-shadow: inset 3px 0 0 var(--warn); }
tbody tr.flagged .badge.warn { margin-top: 4px; }

/* ── Unread ──────────────────────────────────────────────────────────────── */
/* The count sits on the menu item it concerns rather than in a bell: what is unread is
   unread about something, and the something is already on screen. */
.nav a .count {
  margin-left: auto;
  min-width: 18px; padding: 0 5px;
  border-radius: var(--radius-pill);
  background: var(--accent); color: #fff;
  font-size: var(--fs-xs); font-weight: 700; font-style: normal;
  text-align: center; line-height: 17px;
}
.nav a[aria-current="page"] .count { background: var(--accent-2); }

.note-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 2px var(--s-3);
  padding: var(--s-3) var(--s-5);
  border-bottom: 1px solid var(--border);
  color: var(--text-2); text-decoration: none;
  font-size: var(--fs-md);
}
.note-row:last-child { border-bottom: none; }
.note-row:hover { background: var(--surface-2); }
.note-row .who { font-weight: 600; color: var(--text); }
.note-row .when { grid-column: 2; grid-row: 1; color: var(--text-3); font-size: var(--fs-sm); }
.note-row .preview {
  grid-column: 1 / -1;
  color: var(--text-3); font-size: var(--fs-sm);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ── Server-load tiles ───────────────────────────────────────────────────── */
/* The same tiles as the traffic stats, with a load bar between the number and its
   caption. The bar's own colour already carries the warning; the tile stays calm. */
.stats.srv .stat { position: relative; }
.stats.srv .meter { margin: 6px 0 8px; }
.meter.warn i { background: var(--warn); }
.meter.err  i { background: var(--err); }
