:root {
  --bg:            #0B0B0F;
  --surface:       #131318;
  --surface-2:     #1A1A21;
  --surface-3:     #22222B;
  --border:        #26262E;
  --border-strong: #33333D;

  --fg:           #FAFAFA;
  --fg-secondary: #C4C4CC;
  --fg-muted:     #7A7A85;
  --fg-faint:     #4A4A55;

  --brand:        #8B5CF6;
  --brand-strong: #A78BFA;
  --brand-dim:    rgba(139, 92, 246, 0.12);
  --brand-ring:   rgba(139, 92, 246, 0.35);

  --ok:    #34D399;  --ok-bg:    rgba(52, 211, 153, 0.10);  --ok-bd:    rgba(52, 211, 153, 0.30);
  --warn:  #FBBF24;  --warn-bg:  rgba(251, 191, 36, 0.10);  --warn-bd:  rgba(251, 191, 36, 0.30);
  --err:   #F87171;  --err-bg:   rgba(248, 113, 113, 0.10); --err-bd:   rgba(248, 113, 113, 0.30);

  --shadow-sm: 0 1px 0 rgba(255,255,255,0.02) inset, 0 1px 2px rgba(0,0,0,0.4);
  --shadow:    0 1px 0 rgba(255,255,255,0.03) inset, 0 4px 12px rgba(0,0,0,0.45);

  --r-sm: 6px;
  --r:    8px;
  --r-lg: 12px;
}
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; height: 100%; }
body {
  font: 14px/1.55 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  background: var(--bg);
  color: var(--fg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
a { color: var(--brand-strong); text-decoration: none; }
a:hover { text-decoration: underline; }
::selection { background: var(--brand-dim); color: var(--fg); }

/* ----- Shell: sidebar + main ----- */
.app { display: grid; grid-template-columns: 240px 1fr; min-height: 100vh; }
.sidebar {
  position: sticky;
  top: 0;
  align-self: start;
  height: 100vh;
  background: var(--surface);
  border-right: 1px solid var(--border);
  padding: 24px 16px 20px;
  display: flex;
  flex-direction: column;
  gap: 24px;
}
.sidebar-brand { padding: 0 8px 16px; border-bottom: 1px solid var(--border); }
.sidebar-brand .name {
  font-size: 16px;
  font-weight: 600;
  color: var(--fg);
  letter-spacing: -0.015em;
  display: flex;
  align-items: center;
  gap: 10px;
}
.sidebar-brand .mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 7px;
  background: linear-gradient(135deg, rgba(139,92,246,0.16), rgba(139,92,246,0.06));
  border: 1px solid rgba(139, 92, 246, 0.25);
  flex-shrink: 0;
}
.sidebar-brand .sub {
  margin-top: 8px;
  font-size: 10.5px;
  color: var(--fg-muted);
  text-transform: uppercase;
  letter-spacing: 0.10em;
  font-weight: 500;
  padding-left: 38px;
}
.sidebar-brand .sub .tag {
  display: inline-block;
  padding: 1px 6px;
  border-radius: 4px;
  background: var(--surface-2);
  color: var(--fg-secondary);
  font-size: 9.5px;
  letter-spacing: 0.08em;
  margin-left: 4px;
}
.sidebar-nav { display: flex; flex-direction: column; gap: 2px; position: relative; }
.navitem {
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  height: 36px;
  padding: 0 12px;
  border-radius: var(--r-sm);
  color: var(--fg-secondary);
  font-size: 13px;
  font-weight: 500;
  text-decoration: none;
  transition: background 0.1s ease, color 0.1s ease;
}
.navitem:hover { background: var(--surface-2); color: var(--fg); text-decoration: none; }
.navitem.active {
  background: var(--brand-dim);
  color: var(--fg);
}
.navitem.active::before {
  content: "";
  position: absolute;
  left: 0;
  top: 6px;
  bottom: 6px;
  width: 2px;
  background: var(--brand);
  border-radius: 2px;
}
.navitem .dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--fg-faint);
  flex-shrink: 0;
}
.navitem.active .dot { background: var(--brand-strong); box-shadow: 0 0 0 3px rgba(139,92,246,0.18); }
.sidebar-foot { margin-top: auto; padding-top: 16px; border-top: 1px solid var(--border); }

/* Curation sub-nav strip (ABD-105): horizontal sub-tabs under the page header. */
.subnav {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin: 0 0 20px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--border);
}
.subtab {
  display: inline-flex;
  align-items: center;
  height: 30px;
  padding: 0 12px;
  border-radius: var(--r-sm);
  color: var(--fg-secondary);
  font-size: 13px;
  font-weight: 500;
  text-decoration: none;
  transition: background 0.1s ease, color 0.1s ease;
}
.subtab:hover { background: var(--surface-2); color: var(--fg); text-decoration: none; }
.subtab.active { background: var(--brand-dim); color: var(--brand-strong); }

/* Data Quality tab bars (ABD-111): label | filled track | value. Pure CSS, no JS. */
.qrow { display: flex; align-items: center; gap: 12px; padding: 4px 0; font-size: 13px; }
.qlabel { flex: 0 0 200px; color: var(--fg-secondary); overflow-wrap: anywhere; }
.qtrack { flex: 1 1 auto; height: 10px; background: var(--surface-2); border-radius: 5px; overflow: hidden; }
.qfill { height: 100%; border-radius: 5px; min-width: 2px; }
.qval { flex: 0 0 76px; text-align: right; color: var(--fg-muted); font-size: 12px; font-variant-numeric: tabular-nums; }

/* Trend sparklines (ABD-113): a labelled header row above each inline-SVG line. */
.trend-h { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 4px; font-size: 13px; color: var(--fg-secondary); }
.trend-v { color: var(--fg-muted); font-size: 12px; font-variant-numeric: tabular-nums; }

.main { padding: 40px 40px 64px; min-width: 0; }
.container { max-width: 880px; margin: 0 auto; }

/* ----- Auth shell (sign-in) ----- */
.auth-shell {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 24px;
  background:
    radial-gradient(900px 500px at 50% -10%, rgba(139,92,246,0.10), transparent 60%),
    var(--bg);
}
.auth-card {
  width: 100%;
  max-width: 400px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: 32px;
  box-shadow: var(--shadow);
}
.auth-brand { text-align: center; margin-bottom: 28px; }
.auth-brand .mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 11px;
  background: linear-gradient(135deg, rgba(139,92,246,0.20), rgba(139,92,246,0.06));
  border: 1px solid rgba(139, 92, 246, 0.30);
  margin-bottom: 14px;
}
.auth-brand .name { font-size: 20px; font-weight: 600; color: var(--fg); letter-spacing: -0.015em; }
.auth-brand .sub {
  margin-top: 4px;
  font-size: 11px;
  color: var(--fg-muted);
  text-transform: uppercase;
  letter-spacing: 0.10em;
  font-weight: 500;
}
.auth-brand .sub .tag {
  display: inline-block;
  padding: 1px 6px;
  border-radius: 4px;
  background: var(--surface-2);
  color: var(--fg-secondary);
  font-size: 9.5px;
  letter-spacing: 0.08em;
  margin-left: 4px;
}
.auth-card .field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 16px; }
.auth-card .field label { font-size: 12px; color: var(--fg-muted); font-weight: 500; }
.auth-card .btn { width: 100%; justify-content: center; }
.auth-foot { margin-top: 24px; text-align: center; font-size: 12px; color: var(--fg-muted); }

/* "Sign in with Google" - primary CTA, styled to the drugbase dark/purple theme
   (Google's dark button variant) rather than the stock white button: an elevated
   dark surface with a brand-purple border + hover glow. The colored G is kept per
   Google branding (recognisable + compliant on a dark surface). */
.btn-google {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  width: 100%;
  height: 44px;
  margin-bottom: 20px;
  background: var(--surface-2);
  color: var(--fg);
  border: 1px solid var(--brand-ring);
  border-radius: var(--r-md, 10px);
  font-family: inherit;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: .1px;
  transition: background .15s ease, border-color .15s ease, box-shadow .15s ease;
}
.btn-google:hover {
  background: var(--surface-3);
  border-color: var(--brand-strong);
  box-shadow: 0 0 0 3px var(--brand-dim);
  text-decoration: none;
}
.btn-google:active { background: var(--surface-2); }
.btn-google svg { flex: 0 0 18px; display: block; }
/* Divider between the Google button and the break-glass token form. */
.auth-or {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0 0 20px;
  color: var(--fg-muted);
  font-size: 12px;
}
.auth-or::before,
.auth-or::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--border);
}
/* Small "break-glass" tag beside the Access token label. */
.field label .hint {
  margin-left: 6px;
  padding: 1px 6px;
  border-radius: 999px;
  background: var(--surface-3);
  color: var(--fg-muted);
  font-size: 10px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: .4px;
  vertical-align: middle;
}

/* ----- Typography ----- */
h1 {
  margin: 0 0 6px;
  font-size: 24px;
  font-weight: 600;
  color: var(--fg);
  letter-spacing: -0.01em;
}
h1 code {
  font-size: 20px;
  background: var(--surface-2);
  color: var(--fg);
  border: 1px solid var(--border);
  padding: 1px 8px;
  border-radius: var(--r-sm);
}
.page-sub { color: var(--fg-muted); margin: 0 0 28px; font-size: 14px; }
.eyebrow {
  font-size: 11px;
  font-weight: 600;
  color: var(--fg-muted);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

/* ----- Card ----- */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: 20px 24px;
  margin-bottom: 20px;
  box-shadow: var(--shadow-sm);
}
.card-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin: -4px 0 16px;
}
.card-head h2 { margin: 0; font-size: 11px; font-weight: 600; color: var(--fg-muted); text-transform: uppercase; letter-spacing: 0.08em; }
/* Base .meta: small muted text. Used by the keys status line + pager indicator
   (injected by admin.js OUTSIDE .card-head), which were previously unstyled. */
.meta { font-size: 12px; color: var(--fg-muted); }
.card-head .meta { font-size: 12px; color: var(--fg-muted); }

/* ----- Table ----- */
table.tbl { width: 100%; border-collapse: collapse; }
table.tbl th, table.tbl td {
  text-align: left;
  padding: 10px 10px;
  font-size: 13px;
  vertical-align: middle;
}
/* Aggressive wrapping is OPT-IN per table (e.g. the Noise tab's long IPs/paths).
   It must NOT be global: on the Keys table it broke short tokens mid-word - the
   tier pill rendered "STANDAR/D", fingerprints + timestamps split across 2 lines. */
table.tbl--wrap th, table.tbl--wrap td { overflow-wrap: anywhere; }
table.tbl th {
  color: var(--fg-muted);
  font-weight: 600;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  border-bottom: 1px solid var(--border);
  padding-bottom: 10px;
}
table.tbl td { border-bottom: 1px solid var(--border); }
table.tbl tbody tr:last-child td { border-bottom: 0; }
table.tbl tbody tr { transition: background 0.08s ease; }
table.tbl tbody tr:hover { background: var(--surface-2); }
table.tbl .num { text-align: right; font-variant-numeric: tabular-nums; }
table.tbl .actions { text-align: right; width: 1%; white-space: nowrap; }
/* Space the controls in an actions cell so a role <select>+Set form and a Delete form
   don't run together ("admin Set Delete" crammed). Each form's own controls get a small
   gap; adjacent forms get a larger one. */
table.tbl .actions form.inline { display: inline-flex; align-items: center; gap: 6px; vertical-align: middle; }
table.tbl .actions form.inline + form.inline { margin-left: 12px; }
table.tbl .actions form.inline select { min-width: 96px; }
/* Timestamp cell: muted + one line (was splitting "...18" / "GMT+0" across rows). */
table.tbl .cell-created { color: var(--fg-muted); white-space: nowrap; }

/* Reusable responsive-table utilities (ABD-258): rather than ever scroll a table
   horizontally, drop a low-priority column below a breakpoint. Put the class on BOTH
   the <th> and every matching <td>. `.nowrap` keeps compact cells (timestamps) on one
   line; `.wrap` lets a long free-text cell wrap instead of forcing width. */
table.tbl td.nowrap, table.tbl th.nowrap { white-space: nowrap; }
table.tbl td.wrap { white-space: normal; overflow-wrap: anywhere; }
table.tbl .follow-col { width: 30px; text-align: center; padding-left: 4px; padding-right: 0; }
table.tbl .follow-col .btn--sm { padding: 2px 5px; }
@media (max-width: 1150px) { table.tbl .col-hide-1150 { display: none; } }
@media (max-width: 1024px) { table.tbl .col-hide-1024 { display: none; } }

/* ----- Keys table (ABD-252): fit all columns with NO horizontal scroll -----
   The label column is the ONLY flexible one - it wraps so the table shrinks to the
   container instead of forcing a horizontal scroll; the fingerprint + timestamps stay
   on one line (compact fonts) and the owner input flexes. Auto layout so nothing clips.
   Columns: 1 Label, 2 Owner, 3 Tier, 4 Fingerprint, 5 Created, 6 Last seen, 7 actions. */
table.tbl--keys th, table.tbl--keys td { padding-left: 6px; padding-right: 6px; }
/* Label (1st col) is the flex column: wrap long labels rather than scroll. Break at
   hyphens (break-word) so a long "A-B-C-Pharmacy" splits cleanly instead of mid-token.
   The extra .tbl class outranks the `td code { white-space: nowrap }` rule below. */
table.tbl.tbl--keys td:nth-child(1) code { white-space: normal; overflow-wrap: break-word; }
table.tbl--keys .owner-cell { width: 15%; max-width: 12rem; }  /* cap owner so the label keeps room */
table.tbl--keys .owner-cell form { display: flex; gap: 4px; align-items: center; }
table.tbl--keys .owner-cell input { font-size: 12px; }
table.tbl--keys .cell-created, table.tbl--keys td:nth-child(6) { font-size: 11.5px; }  /* timestamps */
table.tbl--keys td:nth-child(4) code { font-size: 11px; }   /* fingerprint: compact, one line */
/* Below ~1150px the sidebar leaves too little room for all columns, so drop the
   lowest-priority one (Created) rather than ever scroll horizontally - "Last seen"
   (which drives the dormant surface) and the rest stay. Progressive disclosure > a
   hidden horizontal scrollbar. */
@media (max-width: 1150px) {
  table.tbl--keys th:nth-child(5), table.tbl--keys td:nth-child(5) { display: none; }  /* Created */
}
@media (max-width: 1024px) {
  table.tbl--keys th:nth-child(4), table.tbl--keys td:nth-child(4) { display: none; }  /* Fingerprint (label still IDs the key) */
}

/* ----- Inline code chips ----- */
code {
  background: var(--surface-2);
  color: var(--fg-secondary);
  padding: 2px 6px;
  border-radius: var(--r-sm);
  font-family: 'Inconsolata', ui-monospace, monospace;
  font-size: 12.5px;
  border: 1px solid var(--border);
}
td code { border-color: transparent; background: var(--surface-2); }
/* Code chips that are short identifiers (key label, fingerprint) stay on one line;
   the ellipsis in a fingerprint (9bef0a1f…1341c6ab) is otherwise a wrap point.
   The Noise tables (.tbl--wrap) are exempt - their IPs/paths SHOULD wrap. */
table.tbl:not(.tbl--wrap) td code { white-space: nowrap; }

/* ----- Form controls ----- */
input, select, textarea {
  font: inherit;
  height: 36px;
  padding: 0 12px;
  border-radius: var(--r-sm);
  border: 1px solid var(--border);
  background: var(--surface-2);
  color: var(--fg);
  transition: border-color 0.1s ease, box-shadow 0.1s ease, background 0.1s ease;
}
input::placeholder, textarea::placeholder { color: var(--fg-faint); }
input:hover, select:hover, textarea:hover { border-color: var(--border-strong); }
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--brand);
  box-shadow: 0 0 0 3px var(--brand-ring);
}
select {
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'><path fill='%237A7A85' d='M2.5 4.5 6 8l3.5-3.5z'/></svg>");
  background-repeat: no-repeat;
  background-position: right 10px center;
  padding-right: 30px;
}

/* ----- Buttons ----- */
.btn, button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: 36px;
  padding: 0 14px;
  border-radius: var(--r-sm);
  border: 1px solid transparent;
  background: var(--brand);
  color: #fff;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  text-decoration: none;
  transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease, box-shadow 0.12s ease, transform 0.06s ease;
}
.btn:hover, button:hover { background: var(--brand-strong); text-decoration: none; }
.btn:active, button:active { transform: translateY(1px); }
.btn:focus-visible, button:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--brand-ring);
}
.btn--ghost, button.ghost {
  background: transparent;
  color: var(--fg-secondary);
  border-color: var(--border);
  font-weight: 500;
}
.btn--ghost:hover, button.ghost:hover {
  background: var(--surface-2);
  border-color: var(--border-strong);
  color: var(--fg);
}
.btn--danger, button.danger {
  background: transparent;
  color: var(--err);
  border-color: var(--err-bd);
  font-weight: 500;
}
.btn--danger:hover, button.danger:hover {
  background: var(--err-bg);
  border-color: var(--err);
  color: var(--err);
}
.btn--sm { height: 30px; padding: 0 10px; font-size: 12px; }

/* ----- Forms layout ----- */
.row { display: flex; gap: 12px; align-items: flex-end; flex-wrap: wrap; }
/* Vertical form layout (Add-drug form): stack rows/fields with breathing room. */
.stack { display: flex; flex-direction: column; gap: 16px; align-items: stretch; }
.stack .field > input, .stack .field > select { width: 100%; }
.field { display: flex; flex-direction: column; gap: 6px; }
.field > label { font-size: 12px; color: var(--fg-muted); font-weight: 500; }
form.inline { display: inline; }

/* ----- Feedback form (ABD-270): a single narrow card, fields stacked full width ----- */
.page-head { margin-bottom: 10px; }
.fb-form { max-width: 640px; display: flex; flex-direction: column; gap: 18px; }
.fb-form .field { gap: 7px; }
.fb-form .field > input,
.fb-form .field > select,
.fb-form .field > textarea { width: 100%; }
.fb-form textarea { resize: vertical; min-height: 130px; line-height: 1.5; }
.fb-form input[type="file"] { padding: 8px 10px; font-size: 13px; cursor: pointer; }
.field-hint { margin: 2px 0 0; font-size: 12px; color: var(--fg-faint); }
.fb-actions { display: flex; gap: 10px; align-items: center; }
/* Sleek upload drop-zone: click / drag-drop / paste, with removable thumbnails. The
   native file input is visually hidden (kept keyboard-focusable), and the styled label
   is the drop target + click surface. */
.fb-file-input { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }
.fb-dropzone { display: block; border: 1.5px dashed var(--border-strong); border-radius: var(--r-sm);
  background: var(--surface-2); padding: 22px 16px; cursor: pointer; text-align: center;
  transition: border-color .12s ease, background .12s ease; }
.fb-dropzone:hover { border-color: var(--brand); }
.fb-dropzone:focus-within { border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-ring); }
.fb-dropzone.dragover { border-color: var(--brand); background: var(--brand-dim); }
.fb-dropzone-inner { display: flex; flex-direction: column; align-items: center; gap: 4px; pointer-events: none; }
.fb-dropzone-icon { color: var(--fg-muted); margin-bottom: 2px; }
.fb-dropzone-text { font-size: 13px; color: var(--fg); }
.fb-dropzone-text strong { color: var(--brand); font-weight: 600; }
.fb-dropzone-sub { font-size: 12px; color: var(--fg-faint); }
.fb-paste-preview { display: flex; flex-wrap: wrap; gap: 10px; }
.fb-paste-preview:not(:empty) { margin-top: 10px; }
.fb-thumb-wrap { position: relative; display: inline-flex; }
.fb-paste-thumb { max-height: 88px; max-width: 140px; border: 1px solid var(--border-strong);
  border-radius: var(--r-sm); display: block; }
.fb-thumb-x { position: absolute; top: -7px; right: -7px; width: 20px; height: 20px; border-radius: 999px;
  border: 1px solid var(--border-strong); background: var(--surface-2); color: var(--fg-muted);
  font-size: 14px; line-height: 1; cursor: pointer; display: flex; align-items: center;
  justify-content: center; padding: 0; }
.fb-thumb-x:hover { background: var(--err-bg); color: var(--err); border-color: var(--err-bd); }

/* ----- Feedback inbox (ABD-271): owner-only triage, card list (no wide table) ----- */
.fb-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; flex-wrap: wrap; }
.fb-chips { display: flex; flex-wrap: wrap; gap: 8px; margin: 2px 0 14px; }
.fb-chip { display: inline-flex; align-items: center; gap: 6px; padding: 5px 12px; border-radius: 999px;
  border: 1px solid var(--border-strong); background: var(--surface-2); color: var(--fg-muted);
  font-size: 13px; text-decoration: none; }
.fb-chip:hover { border-color: var(--brand); color: var(--fg); }
.fb-chip.active { background: var(--brand-dim); color: var(--brand); border-color: var(--brand-ring); }
.fb-chip-n { font-size: 11px; opacity: 0.75; }
.fb-filters { display: flex; gap: 10px; align-items: center; margin-bottom: 18px; flex-wrap: wrap; }
.fb-filters input[type="search"] { min-width: 240px; }
.fb-list { display: flex; flex-direction: column; gap: 14px; }
.fb-card { padding: 16px 18px; display: flex; flex-direction: column; gap: 12px; }
.fb-card-head { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.fb-card-meta { font-size: 12px; color: var(--fg-muted); }
.fb-card-msg { white-space: pre-wrap; overflow-wrap: anywhere; line-height: 1.55; }
.fb-thumbs { display: flex; flex-wrap: wrap; gap: 10px; }
.fb-thumb { display: block; border: 1px solid var(--border-strong); border-radius: var(--r-sm); overflow: hidden; }
.fb-thumb img { display: block; max-height: 160px; max-width: 240px; }
.fb-card-actions { display: flex; flex-wrap: wrap; gap: 16px; align-items: flex-start;
  border-top: 1px solid var(--border-strong); padding-top: 12px; }
.fb-status-form { display: inline-flex; gap: 8px; align-items: center; }
.fb-note-form { display: flex; flex-direction: column; gap: 6px; flex: 1; min-width: 260px; }
.fb-note-form textarea { width: 100%; resize: vertical; min-height: 46px; }
.fb-note-form button { align-self: flex-start; }
.fb-dup { color: var(--warn); }
.fb-sub, .fb-frompage { color: var(--fg-muted); }
.pill.fb-kind-bug { background: var(--warn-bg); color: var(--warn); border-color: var(--warn-bd); }
.pill.fb-kind-request { background: var(--brand-dim); color: var(--brand); border-color: var(--brand-ring); }
.pill.fb-st-new { background: var(--brand-dim); color: var(--brand); border-color: var(--brand-ring); }
.pill.fb-st-triaged { background: var(--warn-bg); color: var(--warn); border-color: var(--warn-bd); }
.pill.fb-st-promoted { background: var(--ok-bg); color: var(--ok); border-color: var(--ok-bd); }
.pill.fb-st-dismissed { background: var(--surface-2); color: var(--fg-faint); border-color: var(--border-strong); }
.fb-promote-cell { display: inline-flex; align-items: center; }
.fb-inlinear { color: var(--ok); border-color: var(--ok-bd); }
.fb-delete { color: var(--err); }
.fb-delete:hover { border-color: var(--err); }
/* Busy/disabled submit buttons (admin.js data-busy-label): read as inactive while the
   request is in flight, so a double-click can't fire a second POST. */
.btn:disabled, .btn[disabled] { opacity: 0.6; cursor: default; }
/* Higher specificity than .btn:disabled so the busy cursor actually wins; no
   pointer-events:none - a native disabled button already can't be activated. */
.btn[aria-busy="true"] { cursor: progress; }

/* ----- Pills ----- */
.pill {
  display: inline-flex;
  align-items: center;
  height: 22px;
  padding: 0 10px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  border: 1px solid transparent;
  white-space: nowrap;   /* a pill label must never wrap (e.g. "STANDARD") */
}
.pill.standard {
  background: var(--brand-dim);
  color: var(--brand-strong);
  border-color: rgba(139, 92, 246, 0.25);
}
.pill.unlimited {
  background: var(--brand);
  color: #fff;
}
/* Writer = a different capability (write-only) from standard/unlimited reads, so
   give it its own colour (amber) - it was indistinguishable from standard before. */
.pill.writer {
  background: var(--warn-bg);
  color: var(--warn);
  border-color: var(--warn-bd);
}
/* Account roles (ENC2-6): admin = solid brand, reviewer = dim/outlined. */
.pill.admin {
  background: var(--brand);
  color: #fff;
}
.pill.reviewer {
  background: var(--brand-dim);
  color: var(--brand-strong);
  border-color: rgba(139, 92, 246, 0.25);
}
.pill.owner {
  background: rgba(234, 179, 8, 0.14);
  color: #eab308;
  border-color: rgba(234, 179, 8, 0.35);
}
.pill.member {
  background: var(--surface-2, rgba(148, 163, 184, 0.12));
  color: var(--fg-secondary);
  border-color: rgba(148, 163, 184, 0.28);
}

/* ----- Flash / inline notices ----- */
.flash {
  padding: 12px 14px;
  border-radius: var(--r);
  margin-bottom: 20px;
  font-size: 13px;
  border: 1px solid;
  line-height: 1.5;
}
.flash.ok { background: var(--ok-bg); border-color: var(--ok-bd); color: var(--ok); }
.flash.err { background: var(--err-bg); border-color: var(--err-bd); color: var(--err); }
.flash.warn { background: var(--warn-bg); border-color: var(--warn-bd); color: var(--warn); }
.flash strong { color: inherit; }

/* ----- KPI strip (Usage page headline) ----- */
.kpi-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
}
.kpi {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: 16px 18px;
}
.kpi .label {
  font-size: 11px;
  color: var(--fg-muted);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 600;
}
.kpi .value {
  margin-top: 8px;
  font-size: 26px;
  font-weight: 600;
  color: var(--fg);
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}
.kpi .delta { margin-top: 4px; font-size: 12px; color: var(--fg-muted); }
.kpi.ok   .value { color: var(--ok); }
.kpi.warn .value { color: var(--warn); }
.kpi.err  .value { color: var(--err); }

/* ----- Card row: side-by-side when there's room for two readable tables,
   otherwise each stacks full-width (no horizontal scroll). auto-fit +
   minmax(min(560px,100%),1fr): >=~1140px -> 2 columns; narrower -> 1 full-width
   column; the min() guard means a column is never wider than the container, so
   phones don't scroll the page either. ----- */
.grid-2 { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(560px, 100%), 1fr)); gap: 20px; }

/* ----- Key display (issue-success page) ----- */
.key-display {
  background: #08080A;
  color: var(--fg);
  padding: 16px 18px;
  border-radius: var(--r);
  font-family: 'Inconsolata', ui-monospace, monospace;
  font-size: 13.5px;
  word-break: break-all;
  user-select: all;
  cursor: copy;
  border: 1px solid var(--border);
}

/* ----- Foot / helper text ----- */
.foot { color: var(--fg-muted); font-size: 12.5px; margin-top: 28px; line-height: 1.65; }
.foot a { color: var(--brand-strong); }

/* ----- Empty state ----- */
.empty {
  text-align: center;
  padding: 36px 20px;
  color: var(--fg-muted);
  font-size: 13px;
}

/* ----- Help tooltip ([data-tip], positioned via JS) (ABD-227) ----- */
.help-tip {
  position: fixed;
  z-index: 60;
  pointer-events: none;
  max-width: 320px;
  background: var(--surface-2);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-sm);
  padding: 9px 12px;
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--fg);
  box-shadow: var(--shadow);
  opacity: 0;
  transition: opacity 0.08s ease;
  /* Pills/labels are uppercase + tracked; the help text must read as normal prose. */
  text-transform: none;
  letter-spacing: normal;
  font-weight: 400;
  white-space: normal;
}
/* Affordance: a non-interactive element that carries help gets the help cursor and a
   faint dotted underline so users know it explains itself. Interactive controls
   (links, buttons, inputs) keep their own cursor. */
[data-tip]:not(a):not(button):not(input):not(select):not(textarea) { cursor: help; }
/* A jargon pill (gcn, ndc, abstained, ...) is the thing a non-expert most needs
   flagged as explainable, so give those a faint dotted underline. KPI tiles already
   have descriptive labels, so they get the help cursor only, no extra chrome. */
.pill[data-tip] { text-decoration: underline dotted currentColor; text-underline-offset: 2px; }

/* ----- Chart tooltip (positioned via JS) ----- */
.chart-tip {
  position: fixed;
  z-index: 50;
  pointer-events: none;
  background: var(--surface-2);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-sm);
  padding: 8px 10px;
  font-size: 12px;
  box-shadow: var(--shadow);
  opacity: 0;
  transition: opacity 0.08s ease;
  min-width: 130px;
}
.chart-tip .t-label {
  color: var(--fg-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-size: 10px;
  font-weight: 600;
}
.chart-tip .t-value {
  color: var(--fg);
  font-weight: 600;
  font-size: 14px;
  margin-top: 2px;
  font-variant-numeric: tabular-nums;
}

/* ----- Chart bar hover affordance ----- */
svg[data-chart="bar"] rect[data-label] {
  transition: opacity 0.08s ease;
  cursor: pointer;
}

/* ----- Sortable tables ----- */
table.tbl th.sortable {
  cursor: pointer;
  user-select: none;
  position: relative;
  padding-right: 18px;
  transition: color 0.08s ease;
}
table.tbl th.sortable:hover { color: var(--fg-secondary); }
table.tbl th.sortable:focus-visible {
  outline: none;
  color: var(--fg);
  box-shadow: inset 0 0 0 2px var(--brand-ring);
  border-radius: var(--r-sm);
}
table.tbl th.sortable::after {
  content: "";
  position: absolute;
  right: 6px;
  top: 50%;
  transform: translateY(-50%);
  width: 0;
  height: 0;
  border-left: 3px solid transparent;
  border-right: 3px solid transparent;
  border-top: 3px solid var(--fg-faint);
  opacity: 0.5;
}
table.tbl th.sortable:hover::after { opacity: 1; border-top-color: var(--fg-muted); }
table.tbl th.sort-asc::after  { border-top: 0; border-bottom: 3px solid var(--brand-strong); opacity: 1; }
table.tbl th.sort-desc::after { border-top-color: var(--brand-strong); opacity: 1; }

/* ----- Responsive: collapse sidebar below 768px ----- */
/* ----- Responsive / data tables (ENC2-7 UI pass) ----- */
/* Wrap data tables so a table wider than its card scrolls horizontally inside
   the card instead of shoving the whole page sideways on narrow screens. */
.tbl-wrap { overflow-x: auto; }
.tbl-wrap > table.tbl { min-width: 560px; }

/* Wider content column for the review queue (it has the most columns). */
.container.wide { max-width: 1180px; }

/* Submissions review table: short columns stay on one line so the Drug name -
   the field that actually matters - keeps the remaining width and wraps to a
   line or two instead of one word per line. */
table.tbl--review { min-width: 760px; }
/* Tighter padding + top alignment for the dense, multi-line review table.
   `table.tbl--review` matches the original `table.tbl td` specificity, and
   comes later in the file, so these win. */
table.tbl--review th, table.tbl--review td { white-space: nowrap; padding-left: 8px; padding-right: 8px; vertical-align: top; }
.tbl--review th.col-drug, .tbl--review td.col-drug { white-space: normal; min-width: 220px; }
/* Compact, vertically-stacked review control so the Approve/Reject buttons (the
   primary action) always stay visible instead of being pushed off the right. */
.tbl--review .review-form { display: flex; flex-direction: column; gap: 6px; align-items: stretch; width: 150px; }
.tbl--review .review-actions { display: flex; gap: 6px; }
.tbl--review .review-actions .btn--sm { flex: 1; }
.tbl--review .note-input { width: 100%; }

@media (max-width: 768px) {
  /* minmax(0, 1fr) lets the single column shrink below its content's min-width,
     so a wide table (which scrolls inside its own .tbl-wrap) can't force the
     whole page to scroll sideways. */
  .app { grid-template-columns: minmax(0, 1fr); }
  .sidebar {
    position: static;
    height: auto;
    flex-direction: row;
    align-items: center;
    gap: 16px;
    padding: 14px 20px;
    flex-wrap: wrap;
  }
  /* Wrap the nav chips to a second row instead of overflowing the viewport. */
  .sidebar-nav { flex-direction: row; flex-wrap: wrap; gap: 4px; flex: 1; min-width: 0; }
  .navitem { height: 32px; }
  .navitem.active::before { display: none; }
  .sidebar-foot { margin: 0; padding: 0; border: 0; }
  .main { padding: 24px 20px 48px; }
  .kpi-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid-2 { grid-template-columns: minmax(0, 1fr); }
}

/* ----- API Explorer (ABD-262) ----- */
.ex-header { margin-bottom: 14px; }
.explorer {
  display: grid;
  grid-template-columns: 300px minmax(0, 1fr);
  gap: 16px;
  align-items: start;
  /* The PAGE is the single scroll container - the panel grows to fit its content (the
     full response, no inner scroll) and the page scrolls if it exceeds the viewport.
     Nested/inner scroll areas are a known anti-pattern (control + a11y problems); the
     only concession is the sticky sidebar below, which scrolls internally ONLY when the
     endpoint list itself is taller than the viewport. */
}

/* Left column: a sticky sidebar (search box over the endpoint list) that stays in view as
   the page scrolls the panel; it scrolls internally only if the list exceeds the viewport. */
.explorer-list {
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r);
  overflow: hidden;
  position: sticky;
  top: 20px;
  max-height: calc(100vh - 40px);
}
.explorer-list-search { padding: 10px; border-bottom: 1px solid var(--border); }
.explorer-list-search input {
  width: 100%; background: var(--bg); border: 1px solid var(--border-strong);
  border-radius: var(--r-sm); color: var(--fg); padding: 8px 10px; font-size: 13px;
}
.explorer-list-search input:focus { outline: none; border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-ring); }
.explorer-list-scroll { flex: 1; overflow-y: auto; padding: 8px; display: flex; flex-direction: column; gap: 4px; }

.ex-item {
  display: flex; align-items: flex-start; gap: 10px; width: 100%; text-align: left;
  padding: 9px 11px; background: transparent; border: 1px solid transparent;
  border-radius: var(--r-sm); color: var(--fg-secondary); cursor: pointer; line-height: 1.35;
  /* Override the global button height:36px reset - the list item is a <button> and that
     fixed height locked it to one line, so the second line (the path) overflowed below
     the box (obvious on the active item's highlight). Let it grow to both lines. */
  height: auto; flex: 0 0 auto;
}
.ex-item:hover { background: var(--surface-2); color: var(--fg); }
.ex-item.active { background: var(--brand-dim); border-color: var(--brand-ring); color: var(--fg); }
.ex-item:focus-visible { outline: 2px solid var(--brand-strong); outline-offset: -1px; }
.ex-item-txt { display: flex; flex-direction: column; gap: 3px; min-width: 0; flex: 1; }
.ex-item-sum { font-size: 13px; font-weight: 600; line-height: 1.35; }
/* Reset the global `code {}` chip (bg/border/padding): on an inline <code> the vertical
   padding bleeds into adjacent rows and collides them (only visible with the real
   Inconsolata metrics). Plain block text instead - own line, ellipsis, no bleed. */
.ex-item-path { display: block; background: transparent; border: 0; padding: 0; border-radius: 0;
  font-family: Inconsolata, monospace; font-size: 11px; color: var(--fg-muted);
  line-height: 1.35; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ex-method {
  flex: 0 0 auto; margin-top: 1px; font-family: Inconsolata, monospace; font-size: 10px;
  font-weight: 600; letter-spacing: 0.04em; padding: 2px 6px; border-radius: 4px;
  background: var(--surface-3); color: var(--fg-secondary);
}
.ex-method--get { background: rgba(52, 211, 153, 0.14); color: var(--ok); }
.ex-method--post { background: rgba(251, 191, 36, 0.14); color: var(--warn); }
.ex-group { font-size: 10px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--fg-faint); padding: 12px 8px 4px; }
.ex-group:first-child { padding-top: 2px; }

/* Right column: a full-height panel with a header bar over a scrolling body. */
.explorer-panel {
  display: flex; flex-direction: column; min-width: 0;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r); overflow: hidden;
}
.ex-panel-head {
  display: flex; align-items: center; gap: 10px; padding: 14px 18px;
  border-bottom: 1px solid var(--border);
  background: linear-gradient(180deg, var(--surface-2), var(--surface));
}
.ex-panel-head .ex-path { background: transparent; border: 0; padding: 0;
  font-family: Inconsolata, monospace; font-size: 14px; color: var(--fg);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ex-panel-head .ex-status { margin-left: auto; font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; }
.ex-status.ok { color: var(--ok); }
.ex-status.warn { color: var(--warn); }
.ex-status.err { color: var(--err); }

/* Natural page flow: the panel-body and all its sections grow to their content - no inner
   scroll. The whole response is laid out; if the panel is taller than the viewport the
   PAGE scrolls (single scroll container), which is the standard, accessible pattern. */
.ex-panel-body { display: flex; flex-direction: column; gap: 14px; padding: 18px; }
.ex-meta { display: flex; flex-direction: column; gap: 14px; }
.ex-summary { font-size: 16px; font-weight: 600; color: var(--fg); }
.ex-desc { color: var(--fg-secondary); font-size: 13px; line-height: 1.55; margin: -6px 0 0; }

.ex-params-title, .ex-code-title {
  font-size: 11px; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: var(--fg-muted);
}
.ex-params-title { margin-bottom: 10px; }
.ex-form { display: flex; flex-direction: column; gap: 12px; }
.ex-field { display: flex; flex-direction: column; gap: 5px; }
.ex-field label { font-size: 12px; color: var(--fg-secondary); font-weight: 500; }
.ex-input {
  width: 100%; background: var(--bg); border: 1px solid var(--border-strong); border-radius: var(--r-sm);
  color: var(--fg); padding: 9px 11px; font-family: Inconsolata, monospace; font-size: 13px;
}
.ex-input:focus { outline: none; border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-ring); }
.ex-hint { font-size: 11px; color: var(--fg-muted); }
.ex-run-row { display: flex; align-items: center; gap: 12px; }
.ex-run { min-width: 92px; }
.ex-run-hint { font-size: 12px; }

/* Code viewer blocks (Response + cURL): header bar over a scrollable body. */
.ex-code {
  display: flex; flex-direction: column; background: var(--bg);
  border: 1px solid var(--border); border-radius: var(--r-sm); overflow: hidden;
}
.ex-code--grow .ex-code-body { min-height: 96px; }   /* the empty "Run to see..." state has a body */
.ex-code-head {
  display: flex; align-items: center; gap: 10px; padding: 7px 12px;
  background: var(--surface-2); border-bottom: 1px solid var(--border);
}
.ex-code-meta { margin-left: auto; font-size: 11px; color: var(--fg-muted); font-variant-numeric: tabular-nums; }
.ex-copy {
  background: transparent; border: 1px solid var(--border-strong); border-radius: 4px;
  color: var(--fg-secondary); font-size: 11px; padding: 2px 9px; cursor: pointer;
}
.ex-copy:hover { background: var(--surface-3); color: var(--fg); }
.ex-code-body {
  margin: 0; padding: 12px; font-family: Inconsolata, monospace; font-size: 12.5px;
  line-height: 1.55; color: var(--fg-secondary);
  /* Expand fully (no inner scroll) and WRAP long lines - the page scrolls, and wrapping
     keeps a wide response from forcing a horizontal scroll. */
  white-space: pre-wrap; overflow-wrap: anywhere;
}
.ex-code-body[data-empty] {
  display: flex; align-items: center; justify-content: center; white-space: normal;
  color: var(--fg-faint); font-family: Inter, system-ui, sans-serif; font-size: 13px;
}
.ex-curl { color: #a5b4fc; }

@media (max-width: 900px) {
  .explorer { grid-template-columns: minmax(0, 1fr); }
  /* Stacked: the list sits above the panel, so it is a normal block (not sticky),
     capped so it doesn't fill the screen before the panel. */
  .explorer-list { position: static; max-height: 320px; }
}

/* ----- Keys: pinned Favourites card (ABD-273) ----- */
.card--fav { border-color: var(--brand-ring); background:
  linear-gradient(180deg, var(--brand-dim), transparent 120px), var(--surface); }
.card--fav .card-head h2 { display: inline-flex; align-items: center; gap: 6px; }
.fav-star { color: #eab308; font-size: 14px; line-height: 1; }
