/*
 * Tenant console theme — the same dark palette dashboard.html defines, lifted
 * into a file so devices.html and database.html cannot drift from it.
 *
 * NO @import AND NO WEBFONT. database.html displays a live credential at
 * rotation time, and a page holding one should not also be making third-party
 * requests; since these two pages share a stylesheet, neither loads one. The
 * font stack falls through to Inter when the browser already has it and to the
 * system UI font otherwise. The map's basemap comes from tiles.postfinite.com,
 * which is ours (tiles/README.md), not a third party.
 *
 * Tables rather than cards for anything list-shaped, following the operator
 * console's preference — a device inventory is a table.
 */

:root {
  --bg-canvas: #090d16;
  --bg-surface: #111827;
  --bg-card: #1f293d;
  --bg-card-hover: #28354f;
  --border-subtle: #1e293b;
  --border-default: #334155;
  --primary: #6366f1;
  --primary-hover: #4f46e5;
  --primary-glow: rgba(99, 102, 241, 0.25);
  --accent-cyan: #06b6d4;
  --accent-emerald: #10b981;
  --accent-amber: #f59e0b;
  --accent-red: #ef4444;
  --text-main: #f8fafc;
  --text-muted: #94a3b8;
  --text-dim: #64748b;
  --font-sans: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --font-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
}

* { box-sizing: border-box; margin: 0; padding: 0; }
body {
  background-color: var(--bg-canvas);
  color: var(--text-main);
  font-family: var(--font-sans);
  line-height: 1.6;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

header {
  background: rgba(17, 24, 39, 0.85);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--border-subtle);
  position: sticky; top: 0; z-index: 100;
  padding: 0.85rem 2rem;
  display: flex; justify-content: space-between; align-items: center; gap: 1rem;
}
.brand-logo { display: flex; align-items: center; gap: 0.75rem; text-decoration: none; color: var(--text-main); }
.brand-icon { width: 36px; height: 36px; flex: none; filter: drop-shadow(0 0 10px var(--primary-glow)); }
/* An org's own logo: same footprint as the mark, never stretched. */
img.brand-icon { object-fit: contain; border-radius: 8px; }
.brand-icon .mark-tile { fill: rgba(99, 102, 241, 0.12); stroke: rgba(99, 102, 241, 0.45); stroke-width: 1.5; }
.brand-icon .mark-loop { fill: none; stroke: url(#pf-mark-grad); stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
.brand-name {
  font-size: 1.25rem; font-weight: 700; letter-spacing: -0.02em;
  background: linear-gradient(90deg, #ffffff, #cbd5e1);
  -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
}
.nav-links { display: flex; gap: 0.35rem; align-items: center; flex-wrap: wrap; }
.nav-btn {
  background: transparent; border: 1px solid transparent; color: var(--text-muted);
  padding: 0.45rem 0.9rem; border-radius: 6px; font-size: 0.88rem; font-weight: 500;
  cursor: pointer; transition: all 0.2s ease; text-decoration: none;
  display: inline-block; font-family: var(--font-sans);
}
.nav-btn:hover { color: var(--text-main); background: var(--bg-card); }
.nav-btn.current { color: var(--text-main); background: var(--bg-card); border-color: var(--border-default); }

main { flex: 1; max-width: 1040px; width: 100%; margin: 0 auto; padding: 2rem 1.5rem; }

.crumb { font-size: 0.85rem; color: var(--text-dim); margin-bottom: 0.75rem; }
.crumb a { color: var(--text-muted); text-decoration: none; }
.crumb a:hover { color: var(--text-main); text-decoration: underline; }

.page-head {
  display: flex; justify-content: space-between; align-items: flex-start;
  gap: 1rem; flex-wrap: wrap; margin-bottom: 1.5rem;
}
.page-head h1 { font-size: 1.8rem; font-weight: 800; letter-spacing: -0.02em; margin-bottom: 0.25rem; }
.page-head .subtle { font-family: var(--font-mono); font-size: 0.85rem; color: var(--text-muted); }
.head-actions { display: flex; gap: 0.6rem; flex-wrap: wrap; }

.btn {
  background: var(--primary); color: #fff; border: none;
  padding: 0.55rem 1.1rem; border-radius: 6px; font-weight: 600; font-size: 0.88rem;
  cursor: pointer; transition: background 0.2s ease; font-family: var(--font-sans);
}
.btn:hover { background: var(--primary-hover); }
.btn:disabled { opacity: 0.55; cursor: not-allowed; }
.btn.secondary { background: transparent; border: 1px solid var(--border-default); color: var(--text-main); }
.btn.secondary:hover { background: var(--bg-card-hover); }
.btn.danger { background: var(--accent-red); }
.btn.danger:hover { background: #dc2626; }
.btn.small { padding: 0.3rem 0.65rem; font-size: 0.8rem; }
a.btn { text-decoration: none; display: inline-block; }

.panel {
  background: var(--bg-surface); border: 1px solid var(--border-subtle);
  border-radius: 12px; padding: 1.5rem; margin-bottom: 1.5rem;
}
.panel-header {
  display: flex; justify-content: space-between; align-items: center;
  margin-bottom: 1.25rem; gap: 1rem; flex-wrap: wrap;
}
.panel-title { font-size: 1.15rem; font-weight: 700; }
.panel-note { font-size: 0.85rem; color: var(--text-muted); margin-top: -0.5rem; margin-bottom: 1rem; }
/* A note that qualifies the number above it: carries the same amber as the
   badge that warned about it, so the two read as one statement. */
/* A reading of a number, not the number: subject, what was measured, and
   what it usually means — stacked so the fact stays the loud part. */
.findings { display: grid; gap: 0.75rem; }
.finding {
  padding: 0.7rem 0.9rem; border-radius: 8px;
  background: rgba(148, 163, 184, 0.06); border-left: 2px solid rgba(148, 163, 184, 0.35);
}
.finding-subject { font-size: 0.78rem; color: var(--text-dim); margin-bottom: 0.15rem; }
.finding-fact { font-size: 0.95rem; font-weight: 600; }
.finding-means { font-size: 0.85rem; margin-top: 0.2rem; }
/* A section inside a panel, for a page that has to say several different
   kinds of thing without becoming several panels. */
.sub-head {
  font-size: 0.75rem; color: var(--text-muted); text-transform: uppercase;
  letter-spacing: 0.05em; margin: 1.3rem 0 0.5rem;
}
.plain-list { margin: 0 0 0.4rem; padding-left: 1.1rem; color: var(--text-muted); font-size: 0.88rem; }
.plain-list li { margin-bottom: 0.35rem; }
.plain-list a { color: var(--text-main); text-decoration: none; }
.plain-list a:hover { color: var(--primary); text-decoration: underline; }
/* An absence, not a feature: same shape as a finding, amber edge, so the
   eye does not read the list as more things we have. */
/* A dataset you do not hold is shown, not hidden — dimmed enough to read
   as an offer rather than as something broken. */
.ds-card.ds-locked { opacity: 0.72; }
.ds-card.ds-locked:hover { opacity: 1; }
/* Source, licence and terms read as words, links in the palette: a licence
   name is a sentence, not an identifier to break letter by letter. */
.ds-card .kv .kv-value { word-break: normal; overflow-wrap: anywhere; }
.ds-card .kv-value a, .ds-card .panel-note a {
  color: inherit; text-decoration: none; border-bottom: 1px dotted var(--text-muted);
}
.ds-card .kv-value a:hover, .ds-card .panel-note a:hover { color: var(--primary); border-bottom-color: var(--primary); }
/* Published data: a row of type chips per dataset, each a way into browsing it. */
.ds-browse { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; margin: 0.2rem 0 0.8rem; }
.ds-browse > .dim { font-size: 0.8rem; margin-right: 0.2rem; }
.ds-browse .metric-chip { text-decoration: none; }
/* Published data, a folded section per theme: its name, how many sets, and
   their names on one line, so a closed section still says what is in it. */
.ds-theme { border: 1px solid var(--border-subtle); border-radius: 10px; background: var(--bg-surface); margin-bottom: 0.6rem; }
.ds-theme > summary {
  list-style: none; cursor: pointer; display: flex; align-items: baseline; gap: 0.75rem;
  padding: 0.8rem 1rem; border-radius: 10px;
}
.ds-theme > summary::-webkit-details-marker { display: none; }
.ds-theme > summary::before { content: '▸'; color: var(--text-dim); transition: transform 0.15s; }
.ds-theme[open] > summary::before { transform: rotate(90deg); }
.ds-theme > summary:hover { background: var(--bg-card); }
.ds-theme > summary:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
.ds-theme-name { font-weight: 600; white-space: nowrap; }
.ds-theme-count { color: var(--text-muted); font-size: 0.85rem; white-space: nowrap; font-variant-numeric: tabular-nums; }
.ds-theme-names { font-size: 0.82rem; min-width: 0; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ds-theme[open] .ds-theme-names { visibility: hidden; }
.ds-theme-body { padding: 0 1rem 0.4rem; }
.ds-theme-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0.1rem 0 0.8rem; }
.ds-card-state { display: inline-flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; justify-content: flex-end; }
@media (prefers-reduced-motion: reduce) { .ds-theme > summary::before { transition: none; } }

.finding.caveat-finding { border-left-color: rgba(245, 158, 11, 0.45); }
tr.row-warn td { background: rgba(245, 158, 11, 0.05); }

pre.snippet.stmt { max-width: 46ch; white-space: pre-wrap; word-break: break-word; font-size: 0.78rem; }

.panel-note.caveat {
  margin-top: 0.9rem; padding-left: 0.7rem;
  border-left: 2px solid rgba(245, 158, 11, 0.45); color: var(--text-muted);
}

.banner {
  display: flex; flex-direction: column; gap: 0.2rem;
  border-radius: 10px; padding: 0.9rem 1.1rem; margin-bottom: 1rem;
  border: 1px solid; font-size: 0.9rem;
  overflow-wrap: anywhere; /* API error strings arrive verbatim */
}
.banner strong { font-size: 0.95rem; }
.banner a { color: inherit; font-weight: 600; }
.banner code {
  font-family: var(--font-mono); font-size: 0.82em;
  background: rgba(0,0,0,0.3); padding: 0.05rem 0.3rem; border-radius: 4px;
}
.banner .banner-note { display: block; margin-top: 0.4rem; opacity: 0.85; font-size: 0.85rem; }
.banner.red { color: #fecaca; background: rgba(239, 68, 68, 0.1); border-color: rgba(239,68,68,0.4); }
.banner.amber { color: #fde68a; background: rgba(245, 158, 11, 0.1); border-color: rgba(245,158,11,0.4); }
.banner.green { color: #a7f3d0; background: rgba(16, 185, 129, 0.1); border-color: rgba(16,185,129,0.4); }

table { width: 100%; border-collapse: collapse; font-size: 0.9rem; }
thead th {
  text-align: left; font-size: 0.75rem; font-weight: 700; color: var(--text-muted);
  text-transform: uppercase; letter-spacing: 0.05em;
  padding: 0.5rem 0.75rem; border-bottom: 1px solid var(--border-default); white-space: nowrap;
}
tbody td { padding: 0.7rem 0.75rem; border-bottom: 1px solid var(--border-subtle); vertical-align: middle; }
tbody tr:hover { background: rgba(255,255,255,0.02); }
td.mono, .mono { font-family: var(--font-mono); }
td.right, th.right { text-align: right; }
td.actions { white-space: nowrap; text-align: right; }
td.actions .btn { margin-left: 0.35rem; }
.table-scroll { overflow-x: auto; }
.dim { color: var(--text-dim); }
.empty { text-align: center; color: var(--text-muted); padding: 2.5rem 1rem; }

.kv-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 1.1rem; }
.kv .kv-label {
  font-size: 0.75rem; color: var(--text-muted);
  text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 0.2rem;
}
.kv .kv-value { font-size: 1rem; font-weight: 600; font-family: var(--font-mono); word-break: break-all; }

.badge {
  display: inline-flex; align-items: center; gap: 0.4rem;
  font-size: 0.75rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em;
  padding: 0.15rem 0.55rem; border-radius: 9999px;
}
.badge::before { content: ''; width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
.badge.green { color: #6ee7b7; background: rgba(16, 185, 129, 0.12); border: 1px solid rgba(16,185,129,0.3); }
.badge.amber { color: #fcd34d; background: rgba(245, 158, 11, 0.12); border: 1px solid rgba(245,158,11,0.3); }
.badge.red   { color: #fca5a5; background: rgba(239, 68, 68, 0.12); border: 1px solid rgba(239,68,68,0.3); }
.badge.grey  { color: var(--text-muted); background: var(--bg-card); border: 1px solid var(--border-default); }

label { display: block; font-size: 0.8rem; color: var(--text-muted); margin-bottom: 0.3rem; font-weight: 600; }
input[type="text"], input[type="search"], select {
  width: 100%; background: var(--bg-canvas); color: var(--text-main);
  border: 1px solid var(--border-default); border-radius: 6px;
  padding: 0.5rem 0.7rem; font-size: 0.9rem; font-family: var(--font-sans);
}
input:focus, select:focus { outline: 2px solid var(--primary); outline-offset: 0; border-color: var(--primary); }
input.mono { font-family: var(--font-mono); }
.field { margin-bottom: 0.9rem; }
.field-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 0.9rem; }
.hint { font-size: 0.78rem; color: var(--text-dim); margin-top: 0.3rem; }

pre.snippet {
  background: var(--bg-canvas); border: 1px solid var(--border-subtle); border-radius: 8px;
  padding: 0.75rem 0.9rem; font-family: var(--font-mono); font-size: 0.82rem;
  overflow-x: auto; white-space: pre; color: #cbd5e1;
}
.snippet-row { display: flex; align-items: flex-start; gap: 0.6rem; margin-bottom: 0.9rem; }
.snippet-row pre { flex: 1; min-width: 0; }

/* Modals. Every destructive action goes through one, and each asks the user to
   type the thing being destroyed rather than to click "yes". */
.modal-backdrop {
  position: fixed; inset: 0; z-index: 500; background: rgba(2, 6, 16, 0.75);
  display: flex; justify-content: center; padding: 1rem;
  /* Every modal here auto-focuses a typed-confirmation field, so on a phone
     the keyboard opens with the dialog. `safe center` centres when the box
     fits and top-anchors when it does not; plain flex-start is the fallback
     for engines without the keyword. The backdrop scrolls so the action row
     can never be clipped out of reach. */
  align-items: flex-start;
  align-items: safe center;
  overflow-y: auto; overscroll-behavior: contain;
}
.modal {
  background: var(--bg-surface); border: 1px solid var(--border-default);
  border-radius: 12px; padding: 1.5rem; max-width: 560px; width: 100%;
  max-height: 90vh; overflow-y: auto;
}
.modal h3 { font-size: 1.15rem; font-weight: 700; margin-bottom: 0.6rem; }
.modal p { font-size: 0.9rem; color: var(--text-muted); margin-bottom: 0.9rem; }
.modal .modal-actions { display: flex; justify-content: flex-end; gap: 0.6rem; margin-top: 1.2rem; flex-wrap: wrap; }
.modal-error { color: #fca5a5; font-size: 0.85rem; margin-top: 0.6rem; min-height: 1.2em; overflow-wrap: anywhere; }
.modal.wiz { max-width: 620px; }

/* New-type wizard. A step rail, selectable enforcement cards, and repeatable
   metric/relationship rows, all built on the existing modal shell. */
.wiz-steps { display: flex; gap: 0.35rem; margin: 0 0 1.2rem; flex-wrap: wrap; }
.wiz-steps li {
  display: flex; align-items: center; gap: 0.4rem; flex: 1 1 auto; min-width: 0;
  font-size: 0.72rem; color: var(--text-dim); list-style: none;
}
.wiz-steps .n {
  width: 1.4rem; height: 1.4rem; border-radius: 50%; flex: none;
  display: grid; place-items: center; font-family: var(--font-mono); font-size: 0.72rem;
  border: 1px solid var(--border-default); background: var(--bg-card); color: var(--text-dim);
}
.wiz-steps .lbl { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wiz-steps li.at { color: var(--text-main); }
.wiz-steps li.at .n { border-color: var(--primary); color: var(--primary); }
.wiz-steps li.done .n { background: var(--primary); border-color: var(--primary); color: #fff; }
@media (max-width: 560px) { .wiz-steps .lbl { display: none; } }

.wiz-cards { display: grid; gap: 0.6rem; }
.wiz-card {
  text-align: left; width: 100%; cursor: pointer;
  border: 1px solid var(--border-default); background: var(--bg-card);
  border-radius: 10px; padding: 0.8rem 0.9rem; color: inherit; font: inherit;
}
.wiz-card:hover { border-color: var(--text-dim); }
.wiz-card.on { border-color: var(--primary); box-shadow: 0 0 0 1px var(--primary); }
.wiz-card .t { font-weight: 600; display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.2rem; }
.wiz-card .dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.wiz-card .dot.strict { background: var(--accent-amber); }
.wiz-card .dot.open { background: var(--border-default); }
.wiz-card .d { font-size: 0.82rem; color: var(--text-muted); line-height: 1.45; }
.wiz-card[disabled] { opacity: 0.5; cursor: not-allowed; }

.wiz-row { display: grid; grid-template-columns: 1fr 1fr auto; gap: 0.5rem; align-items: start; margin-bottom: 0.5rem; }
.wiz-row.metric { grid-template-columns: 1.3fr 0.9fr 0.7fr 0.7fr auto; }
.wiz-row.rel { grid-template-columns: 1fr 1fr 1fr auto; }
.wiz-row input, .wiz-row select { margin: 0; }
.wiz-row .wiz-rm {
  border: 1px solid var(--border-default); background: var(--bg-card); color: var(--text-dim);
  border-radius: 8px; cursor: pointer; padding: 0 0.6rem; height: 2.1rem; align-self: center;
}
.wiz-row .wiz-rm:hover { color: #fca5a5; border-color: #fca5a5; }
.wiz-empty { font-size: 0.85rem; color: var(--text-dim); margin: 0.2rem 0 0.7rem; }
.wiz-review { font-size: 0.88rem; }
.wiz-review .kv { display: flex; gap: 0.6rem; padding: 0.3rem 0; border-bottom: 1px solid var(--border-subtle); }
.wiz-review .kv .k { color: var(--text-dim); min-width: 8.5rem; flex: none; }
.wiz-review .kv .v { color: var(--text-main); overflow-wrap: anywhere; }
@media (max-width: 560px) {
  .wiz-row, .wiz-row.rel { grid-template-columns: 1fr 1fr; }
  .wiz-row .wiz-rm { grid-column: 1 / -1; height: 1.9rem; }
}

.spinner {
  width: 28px; height: 28px; border: 3px solid var(--border-default);
  border-top-color: var(--primary); border-radius: 50%;
  animation: spin 0.8s linear infinite; margin: 0 auto 1rem auto;
}
@keyframes spin { to { transform: rotate(360deg); } }
.loading { text-align: center; padding: 3rem 1rem; color: var(--text-muted); }

footer {
  border-top: 1px solid var(--border-subtle); padding: 1.5rem 2rem; text-align: center;
  font-size: 0.85rem; color: var(--text-dim); background: var(--bg-surface);
}

#impersonation-bar {
  position: fixed; top: 0; left: 0; right: 0; z-index: 9999;
  display: flex; align-items: center; justify-content: center; flex-wrap: wrap; gap: .4rem 1rem;
  padding: .6rem 1rem; font-size: .85rem;
  background: #7a4b00; color: #fff; border-bottom: 2px solid #ffb020;
}

@media (max-width: 640px) {
  header { padding: 0.75rem 1rem; flex-wrap: wrap; }
  main { padding: 1.25rem 1rem; }
  .panel { padding: 1.1rem; }
  footer { padding: 1.25rem 1rem; }

  /* Tables become cards, the same shape the operator console uses: the header
     row hides and each cell carries its column name in data-label. Rows are
     written with the attribute in the page scripts. */
  .table-scroll:not(.no-stack) thead { display: none; }
  .table-scroll:not(.no-stack) table,
  .table-scroll:not(.no-stack) tbody,
  .table-scroll:not(.no-stack) tr { display: block; width: 100%; }
  /* A row kept for later (a published table's chart, say) stays hidden: the
     rule above would otherwise outrank the attribute. */
  .table-scroll:not(.no-stack) tr[hidden] { display: none; }
  /* And when it opens, it is a chart, not a card of labelled cells. */
  .table-scroll:not(.no-stack) tbody td.fc-exp-cell { display: block; text-align: left; }
  .table-scroll:not(.no-stack) tbody td.fc-exp-cell::before { content: none; }

  .table-scroll:not(.no-stack) tbody tr {
    border: 1px solid var(--border-default);
    border-radius: 10px;
    margin-bottom: 0.6rem;
    padding: 0.2rem 0.75rem;
    background: var(--bg-card);
  }
  .table-scroll:not(.no-stack) tbody tr:hover { background: var(--bg-card); }

  .table-scroll:not(.no-stack) tbody td {
    display: flex; justify-content: space-between; align-items: baseline;
    gap: 1rem;
    border-bottom: 1px dotted var(--border-subtle);
    padding: 0.45rem 0;
    text-align: right;
    overflow-wrap: anywhere;
  }
  .table-scroll:not(.no-stack) tbody tr td:last-child { border-bottom: none; }

  .table-scroll:not(.no-stack) tbody td::before {
    content: attr(data-label);
    flex: none; text-align: left;
    color: var(--text-muted);
    font-size: 0.75rem; font-weight: 700;
    text-transform: uppercase; letter-spacing: 0.05em;
  }
  .table-scroll:not(.no-stack) tbody td:not([data-label])::before { content: none; }

  /* The trend sparkline is decoration; the latest value is the information.
     Same call the operator console makes about its quota gauge. */
  .spark-cell { display: none; }

  /* The action buttons read better as a full-width row than a label/value pair. */
  .table-scroll:not(.no-stack) tbody td.actions {
    display: flex; justify-content: flex-end; white-space: normal; text-align: right;
  }
}

/* Hit targets and input sizing follow the pointer, not the width: a tablet
   needs 44px buttons at any width, a narrow desktop window does not. */
@media (pointer: coarse) {
  .btn { padding: 0.7rem 1.1rem; min-height: 44px; }
  .btn.small { padding: 0.55rem 0.8rem; min-height: 44px; }
  .nav-btn { padding: 0.65rem 0.9rem; min-height: 44px; }
  td.actions .btn { margin-top: 0.15rem; margin-bottom: 0.15rem; }
  /* 16px is the iOS no-zoom floor. */
  input[type="text"], input[type="search"], select, textarea { font-size: 16px; }
}

/* ------------------------------------------------------------- workbench
   pgAdmin's shape in the console's own hand: an object tree on the left, an
   edge to drag, and the workspace, where what you have open sits as tabs and
   the active one's page below. Below 900px the tree is a drawer that the
   Objects button in the tab strip opens. */
.wb-shell { display: flex; flex: 1; align-items: stretch; width: 100%; --rail-w: 272px; }
.wb-rail {
  width: var(--rail-w); flex: none; align-self: flex-start;
  position: sticky; top: 0; height: 100vh; overflow-y: auto; overscroll-behavior: contain;
  border-right: 1px solid var(--border-subtle);
  padding: 0.7rem 0.35rem 2.5rem;
  background: var(--bg-surface);
  scrollbar-width: thin;
}
.wb-resize {
  width: 6px; margin-left: -3px; flex: none; align-self: flex-start;
  position: sticky; top: 0; height: 100vh; z-index: 2; cursor: col-resize;
}
.wb-resize:hover, .wb-resize:focus-visible { background: var(--primary-glow); outline: none; }

.ico {
  width: 16px; height: 16px; flex: none; vertical-align: -3px;
  fill: none; stroke: currentColor; stroke-width: 1.35; stroke-linecap: round; stroke-linejoin: round;
}

.tree-search { padding: 0 0.35rem 0.55rem; }
.tree-search input { width: 100%; padding: 0.42rem 0.65rem; font-size: 0.85rem; }
.tree { font-size: 0.86rem; }
.tree-row {
  display: flex; align-items: center; gap: 0.35rem; min-height: 1.8rem;
  padding: 0.2rem 0.45rem 0.2rem calc(0.25rem + var(--d, 0) * 0.95rem);
  border-radius: 6px; color: var(--text-muted); cursor: pointer; white-space: nowrap;
}
.tree-row:hover { background: var(--bg-card); color: var(--text-main); }
.tree-row.active { background: var(--bg-card); color: var(--text-main); box-shadow: inset 2px 0 0 var(--primary); }
.tree-row:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }
.tree-row .tw { width: 14px; height: 14px; flex: none; display: inline-flex; align-items: center; justify-content: center; color: var(--text-dim); }
.tree-row .tw .ico { width: 12px; height: 12px; transition: transform 0.12s; }
.tree-row .tw.open .ico { transform: rotate(90deg); }
.tree-row .tw[data-toggle]:hover { color: var(--text-main); }
.tree-row > .ico { width: 15px; height: 15px; color: var(--text-dim); }
.tree-row.active > .ico, .tree-row:hover > .ico { color: var(--text-muted); }
.tree-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; color: inherit; text-decoration: none; }
.tree-meta, .tree-row .count { flex: none; font-family: var(--font-mono); font-size: 0.72rem; color: var(--text-dim); }
.tree-meta { max-width: 45%; overflow: hidden; text-overflow: ellipsis; }
.tree-row .dot { width: 7px; height: 7px; border-radius: 50%; flex: none; margin: 0 4px; }
.tree-row .dot.strict, #help-pop .dot.strict { background: var(--accent-amber); }
.tree-row .dot.open, #help-pop .dot.open { background: var(--border-default); }
/* A published type: the platform's, read-only, hollow beside your own types' filled dots. */
.tree-row .dot.published { background: transparent; box-shadow: inset 0 0 0 1px var(--text-muted); }
.tree-row .help-tip { flex: none; }
.tree-section {
  margin-top: 0.75rem; font-size: 0.7rem; font-weight: 700; letter-spacing: 0.07em; text-transform: uppercase;
  color: var(--text-dim);
}
.tree-section:hover, .tree-section.active { background: none; box-shadow: none; }
.tree-section:hover .tree-name, .tree-section.active .tree-name { color: var(--text-main); }
.tree-db { color: var(--text-main); font-weight: 600; }
.tree-db .tree-meta { font-weight: 400; }
.tree-row.dim, .tree-row.dim .tree-name { color: var(--text-dim); }
.tree-empty { padding: 0.75rem; font-size: 0.85rem; }

/* The tab strip. A preview tab (opened, not yet kept) has its name in italics. */
.wb-tabs {
  display: flex; align-items: flex-end; gap: 0.3rem; min-height: 2.3rem;
  margin: -0.5rem 0 1rem; border-bottom: 1px solid var(--border-subtle);
}
.wb-tabs-list { display: flex; gap: 0.15rem; flex: 1; min-width: 0; overflow-x: auto; scrollbar-width: thin; }
.wb-tab {
  display: flex; align-items: center; gap: 0.4rem; flex: none; max-width: 15rem;
  padding: 0.32rem 0.25rem 0.32rem 0.6rem; border: 1px solid transparent; border-bottom: none;
  border-radius: 7px 7px 0 0; color: var(--text-dim); font-size: 0.82rem; cursor: pointer;
}
.wb-tab:hover { color: var(--text-main); background: var(--bg-surface); }
.wb-tab.active {
  color: var(--text-main); background: var(--bg-surface); border-color: var(--border-subtle);
  position: relative; top: 1px; box-shadow: inset 0 2px 0 var(--primary);
}
.wb-tab.preview .wb-tab-name { font-style: italic; }
.wb-tab .ico { width: 14px; height: 14px; }
.wb-tab-name { color: inherit; text-decoration: none; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wb-tab-x {
  border: 0; background: none; color: var(--text-dim); cursor: pointer;
  font-size: 1rem; line-height: 1; padding: 0.05rem 0.3rem; border-radius: 4px;
}
.wb-tab-x:hover { color: var(--text-main); background: var(--bg-card); }
.tabs-tree {
  display: none; align-items: center; gap: 0.35rem; flex: none; margin-bottom: 0.3rem;
  padding: 0.3rem 0.6rem; border: 1px solid var(--border-default); border-radius: 6px;
  background: var(--bg-card); color: var(--text-muted); font: inherit; font-size: 0.82rem; cursor: pointer;
}

/* Object pages: facts, a strip of the object's aspects, then the aspect. */
.obj-title .badge { vertical-align: 3px; margin-left: 0.2rem; }
.obj-comment { color: var(--text-muted); margin: -0.4rem 0 0.9rem; max-width: 75ch; }
.obj-tabs { display: flex; gap: 1.15rem; margin-bottom: 1rem; border-bottom: 1px solid var(--border-subtle); overflow-x: auto; scrollbar-width: thin; }
.obj-tab {
  padding: 0 0 0.55rem; margin-bottom: -1px; border-bottom: 2px solid transparent;
  color: var(--text-dim); text-decoration: none; font-size: 0.88rem; white-space: nowrap;
}
.obj-tab:hover { color: var(--text-main); }
.obj-tab.active { color: var(--text-main); border-bottom-color: var(--primary); font-weight: 600; }
.obj-panel { margin-bottom: 1rem; }
.obj-link { color: var(--text-main); text-decoration: none; }
.obj-link:hover { text-decoration: underline; }
.obj-sub { font-size: 0.85rem; font-weight: 600; margin: 0.9rem 0 0.4rem; color: var(--text-muted); }
.obj-select { width: auto; padding: 0.3rem 0.5rem; font-size: 0.85rem; }
.obj-ddl {
  margin: 0; padding: 0.85rem 1rem; max-height: 70vh; overflow: auto;
  font-family: var(--font-mono); font-size: 0.82rem; line-height: 1.55; white-space: pre-wrap; overflow-wrap: anywhere;
  background: var(--bg-canvas); border: 1px solid var(--border-subtle); border-radius: 8px;
}
.grid-scroll { max-height: 70vh; overflow: auto; }
table.grid { font-family: var(--font-mono); font-size: 0.8rem; }
table.grid th { position: sticky; top: 0; z-index: 1; background: var(--bg-surface); vertical-align: bottom; white-space: nowrap; }
table.grid td { white-space: nowrap; max-width: 28rem; overflow: hidden; text-overflow: ellipsis; }
table.grid td.num { text-align: right; }
table.grid td.grid-null { color: var(--text-dim); font-style: italic; }
.grid-sort { padding: 0; border: 0; background: none; color: var(--text-main); font: inherit; font-weight: 600; cursor: pointer; }
.grid-type { display: block; font-size: 0.68rem; font-weight: 400; color: var(--text-dim); }

/* Editing rows. A changed cell is tinted until it is saved, a new row is
   marked at its edge, a row to be deleted is struck through, and the row a
   save was refused over is outlined in red. */
table.grid th.grid-sel, table.grid td.grid-sel { width: 2.2rem; padding-left: 0.55rem; padding-right: 0.2rem; text-align: center; }
.grid-sel input { width: auto; margin: 0; vertical-align: middle; }
.grid-sel .ddl-x { font-size: 1rem; padding: 0 0.2rem; }
table.grid-edit td[data-c] { cursor: cell; }
table.grid td[data-c]:focus { outline: 2px solid var(--primary); outline-offset: -2px; }
table.grid td.cell-changed { background: rgba(245, 158, 11, 0.14); color: #fde68a; }
table.grid td.grid-default { color: var(--text-dim); font-style: italic; }
table.grid tr.row-new td { background: rgba(16, 185, 129, 0.07); }
table.grid tr.row-new td:first-child { box-shadow: inset 3px 0 0 var(--accent-emerald); }
table.grid tr.row-deleted td:not(.grid-sel) { text-decoration: line-through; color: var(--text-dim); background: rgba(239, 68, 68, 0.08); }
table.grid tr.row-error td { background: rgba(239, 68, 68, 0.16); }
table.grid tr.row-error td:first-child { box-shadow: inset 3px 0 0 var(--accent-red); }
.od-error { margin: 0 0 0.8rem; }
.wb-tab-dirty { color: var(--accent-amber); font-size: 1.05rem; line-height: 1; margin: 0 -0.1rem 0 -0.15rem; }
.cell-ed {
  position: fixed; z-index: 600; padding: 0.65rem; display: flex; flex-direction: column; gap: 0.5rem;
  background: var(--bg-surface); border: 1px solid var(--border-default); border-radius: 8px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.45);
}
.cell-ed-head { display: flex; justify-content: space-between; gap: 0.6rem; font-size: 0.8rem; }
.cell-ed-text {
  width: 100%; padding: 0.45rem 0.6rem; resize: vertical;
  background: var(--bg-canvas); color: var(--text-main); border: 1px solid var(--border-default); border-radius: 6px;
  font-family: var(--font-mono); font-size: 0.82rem; line-height: 1.45;
}
.cell-ed-text:focus { outline: 2px solid var(--primary); outline-offset: 0; border-color: var(--primary); }
.cell-ed-text:disabled { opacity: 0.4; }
.cell-ed-row { display: flex; align-items: center; gap: 0.9rem; flex-wrap: wrap; font-size: 0.82rem; }
.cell-ed-acts { margin-left: auto; display: flex; gap: 0.4rem; }
.cell-ed .hint { font-size: 0.72rem; color: var(--text-dim); }
.role-chip { font-family: var(--font-mono); font-size: 0.72rem; padding: 0.05rem 0.45rem; border-radius: 9999px; border: 1px solid var(--border-default); }
.role-time { color: #fcd34d; border-color: rgba(245, 158, 11, 0.4); }
.role-key { color: #67e8f9; border-color: rgba(6, 182, 212, 0.4); }
.role-value { color: #a5b4fc; border-color: rgba(99, 102, 241, 0.45); }

/* Create and alter: a dialog with the SQL it will run beneath it, and the
   object menu that opens dialogs from the tree or an object page. */
.modal.ddl-wide { max-width: 780px; }
.ddl-form textarea, .ddl-query { width: 100%; font-family: var(--font-mono); font-size: 0.85rem; }
.ddl-sql-head {
  display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; margin: 0.3rem 0 0.35rem;
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.07em; text-transform: uppercase; color: var(--text-dim);
}
.ddl-sql-head .dim { text-transform: none; letter-spacing: 0; font-weight: 400; text-align: right; }
.obj-ddl.ddl-sql { min-height: 2.6rem; max-height: 14rem; font-size: 0.78rem; }
.ddl-notes {
  margin: 0.5rem 0 0; padding: 0.55rem 0.8rem; list-style: none; border-radius: 8px; font-size: 0.82rem;
  background: rgba(245, 158, 11, 0.1); border: 1px solid rgba(245, 158, 11, 0.35); color: #fcd34d;
}
.ddl-sub { padding: 0.8rem 0.9rem 0.1rem; margin-bottom: 0.9rem; border: 1px solid var(--border-subtle); border-radius: 8px; }
.ddl-cols { display: flex; flex-direction: column; gap: 0.35rem; margin-bottom: 0.5rem; }
.ddl-col {
  display: grid; align-items: center; gap: 0.4rem;
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 1.1fr) 4rem minmax(0, 1fr) 2.6rem 2rem;
}
.ddl-col-head span { font-size: 0.72rem; font-weight: 600; color: var(--text-dim); }
.ddl-col-head span:nth-child(3), .ddl-col-head span:nth-child(5) { text-align: center; }
.ddl-col input[type="text"] { padding: 0.35rem 0.5rem; font-size: 0.85rem; font-family: var(--font-mono); }
.ddl-col input[type="checkbox"] { justify-self: center; width: auto; margin: 0; }
.ddl-x { border: 0; background: none; color: var(--text-dim); font-size: 1.1rem; line-height: 1; cursor: pointer; border-radius: 4px; padding: 0.2rem; }
.ddl-x:hover { color: var(--text-main); background: var(--bg-card); }
.ddl-pick, .ddl-checks { display: flex; flex-wrap: wrap; gap: 0.45rem 1.1rem; }
.ddl-methods { display: flex; flex-direction: column; gap: 0.4rem; }
.row-acts { white-space: nowrap; text-align: right; }
.row-acts .btn + .btn { margin-left: 0.35rem; }

.ctx-menu {
  position: fixed; z-index: 600; min-width: 13.5rem; padding: 0.3rem;
  display: flex; flex-direction: column;
  background: var(--bg-surface); border: 1px solid var(--border-default); border-radius: 8px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.45);
}
.ctx-item {
  padding: 0.45rem 0.7rem; border: 0; border-radius: 5px; background: none; text-align: left;
  color: var(--text-muted); font: inherit; font-size: 0.86rem; cursor: pointer;
}
.ctx-item:hover, .ctx-item:focus { background: var(--bg-card); color: var(--text-main); outline: none; }
.ctx-item.danger { color: #fca5a5; }
.ctx-sep { height: 1px; margin: 0.25rem 0.3rem; background: var(--border-subtle); }
@media (max-width: 640px) {
  .ddl-col { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) 1.6rem minmax(0, 1fr) 1.6rem 1.6rem; gap: 0.3rem; }
  .ddl-col-head span { font-size: 0.65rem; }
}

/* The horizon, drawn: tiers from the oldest kept data to now, then the future. */
.hz-bar, .hz-axis { display: flex; gap: 3px; }
.hz-bar { height: 3.2rem; margin: 0.4rem 0 0.3rem; }
.hz-seg {
  flex: 1; min-width: 0; display: flex; flex-direction: column; justify-content: center;
  padding: 0.3rem 0.55rem; border-radius: 6px; font-size: 0.75rem; white-space: nowrap; overflow: hidden;
}
.hz-seg b { font-size: 0.8rem; font-weight: 600; }
.hz-seg span { color: var(--text-dim); overflow: hidden; text-overflow: ellipsis; }
.tier-3 { background: rgba(100, 116, 139, 0.2); color: #cbd5e1; }
.tier-2 { background: rgba(99, 102, 241, 0.17); color: #c7d2fe; }
.tier-1 { background: rgba(6, 182, 212, 0.16); color: #a5f3fc; }
.tier-raw { background: rgba(16, 185, 129, 0.16); color: #a7f3d0; }
.hz-seg.hz-now { flex: 0 0 2px; padding: 0; border-radius: 1px; background: var(--accent-amber); }
.hz-seg.hz-future { flex: 0.8; border: 1px dashed var(--border-default); color: var(--text-muted); }
.hz-axis { margin-bottom: 1rem; font-family: var(--font-mono); font-size: 0.7rem; color: var(--text-dim); }
.hz-axis > span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hz-axis > .hz-axis-gap { flex: 0 0 2px; }
.hz-axis > .hz-axis-future { flex: 0.8; display: flex; justify-content: space-between; }
.hz-axis b { font-weight: 400; }

/* The workspace fills what the tree leaves: tables and charts want the width. */
.wb-main { flex: 1; min-width: 0; max-width: none; margin: 0; padding: 1.2rem 1.4rem 3rem; }
.wb-toolbar {
  display: flex; justify-content: space-between; align-items: center;
  gap: 1rem; flex-wrap: wrap; margin-bottom: 1rem;
}
.wb-toolbar h1 { font-size: 1.35rem; font-weight: 800; letter-spacing: -0.02em; }
.wb-toolbar .sub { font-family: var(--font-mono); font-size: 0.8rem; color: var(--text-dim); }
.wb-actions { display: flex; gap: 0.5rem; flex-wrap: wrap; align-items: center; }

.metric-chip {
  display: inline-block; padding: 0.3rem 0.7rem; border-radius: 9999px;
  border: 1px solid var(--border-default); background: transparent;
  color: var(--text-muted); font-family: var(--font-mono); font-size: 0.8rem;
  cursor: pointer;
}
.metric-chip:hover { color: var(--text-main); background: var(--bg-card); }
.metric-chip.active { color: var(--text-main); border-color: var(--primary); background: var(--bg-card); }

.wb-back { color: var(--text-muted); text-decoration: none; font-size: 0.85rem; }
.wb-back:hover { color: var(--text-main); }

@media (max-width: 900px) {
  .wb-shell { flex-direction: column; }
  /* The tree is a drawer above the work, opened from the tab strip. */
  .wb-rail {
    display: none; position: static; width: 100%; height: auto; max-height: 70vh;
    border-right: none; border-bottom: 1px solid var(--border-subtle);
  }
  .wb-shell.rail-open .wb-rail { display: block; }
  .wb-resize { display: none; }
  .tabs-tree { display: inline-flex; }
  .wb-main { padding: 1rem 1rem 2.5rem; }
  .hz-seg span { display: none; }
}
@media (pointer: coarse) {
  .tree-row { min-height: 44px; }
  .wb-tab { min-height: 40px; }
  .metric-chip { min-height: 44px; padding: 0.6rem 0.9rem; }
}

/* Overview usage meters (console shell). */
.meter { height: 8px; border-radius: 9999px; background: var(--bg-canvas); border: 1px solid var(--border-subtle); overflow: hidden; margin-top: 0.45rem; }
.meter > span { display: block; height: 100%; background: var(--primary); }
.meter.warn > span { background: var(--accent-amber); }
.meter.full > span { background: var(--accent-red); }

/* Sparklines (console entity view). */
.spark-cell { width: 130px; }

/* Identity chip + toasts. */
.id-chip {
  display: inline-flex; align-items: center;
  padding: 0.35rem 0.7rem; border-radius: 9999px;
  border: 1px solid var(--border-default); background: var(--bg-card);
  color: var(--text-muted); font-family: var(--font-mono); font-size: 0.78rem;
  max-width: 16rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#toast-stack {
  position: fixed; right: 1rem; bottom: 1rem; z-index: 9000;
  display: flex; flex-direction: column; gap: 0.5rem; max-width: min(24rem, 90vw);
}
.toast {
  padding: 0.7rem 1rem; border-radius: 8px; font-size: 0.88rem;
  border: 1px solid; overflow-wrap: anywhere;
}
.toast.err { color: #fca5a5; background: rgba(239,68,68,0.14); border-color: rgba(239,68,68,0.5); }
.toast.ok  { color: #6ee7b7; background: rgba(16,185,129,0.14); border-color: rgba(16,185,129,0.5); }


/* Entity graph (console #graph view). */
/* Graph navigation. Cytoscape draws on a canvas and styles its nodes and
   edges from JS (console.html, drawGraph), pans, drags and pinch-zooms; a
   busy graph names only its best-connected nodes and hides its verbs until
   a node is lit, selected or the view is zoomed in. Selecting a node opens
   the inspector over the top-right of the stage; on a phone it sits below. */
.graph-stage { position: relative; }
.graph-stage:focus { outline: none; }
.graph-cy {
  width: 100%; height: 520px; margin-top: 0.4rem; touch-action: none;
  border: 1px solid var(--border-subtle); border-radius: 10px; background: var(--bg-surface);
}
.graph-zoom { position: absolute; top: 0.85rem; left: 0.45rem; display: flex; gap: 0.25rem; z-index: 3; }
.graph-zoom .btn { min-width: 2rem; background: var(--bg-surface); }
.graph-inspect {
  z-index: 3;
  position: absolute; top: 0.4rem; right: 0.4rem; width: 17rem; max-height: calc(100% - 0.8rem); overflow: auto;
  background: var(--bg-surface); border: 1px solid var(--border-default); border-radius: 8px;
  padding: 0.75rem 0.8rem; font-size: 0.85rem; box-shadow: 0 6px 24px rgba(0, 0, 0, 0.25);
}
.graph-inspect .gi-head { display: flex; gap: 0.6rem; align-items: flex-start; }
.graph-inspect .gi-head i { width: 12px; height: 12px; border-radius: 50%; flex: none; margin-top: 0.3rem; }
.graph-inspect .gi-head > div { flex: 1; min-width: 0; }
.graph-inspect .gi-name { font-weight: 700; overflow-wrap: anywhere; }
.graph-inspect .gi-sub { font-size: 0.78rem; color: var(--text-dim); overflow-wrap: anywhere; }
.graph-inspect .gi-close { background: none; border: 0; color: var(--text-muted); font-size: 1.25rem; line-height: 1; cursor: pointer; padding: 0 0.2rem; }
.graph-inspect .gi-close:hover { color: var(--text-main); }
.graph-inspect .gi-edges { list-style: none; margin: 0.65rem 0 0; padding: 0; display: grid; gap: 0.3rem; }
.graph-inspect .gi-edges li { overflow-wrap: anywhere; }
.graph-inspect .gi-edges a { color: var(--text-main); text-decoration: none; border-bottom: 1px dotted var(--border-default); }
.graph-inspect .gi-edges a:hover { color: var(--primary); border-bottom-color: var(--primary); }
.graph-inspect .gi-dir { color: var(--text-dim); }
.graph-inspect .gi-verb { color: var(--text-muted); font-family: var(--font-mono); font-size: 0.78rem; }
.graph-inspect .gi-none { color: var(--text-dim); margin: 0.65rem 0 0; }
.graph-inspect .gi-actions { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.75rem; }
@media (max-width: 700px) {
  .graph-inspect { position: static; width: auto; max-height: none; margin-top: 0.6rem; box-shadow: none; }
}

/* The graph explorer (#graph): a facet panel beside one view, graph or
   tables, sharing filters and selection. The facet whose values colour the
   graph shows swatches, so the panel is also the legend. */
.gx-grid { display: grid; grid-template-columns: 14.5rem minmax(0, 1fr); gap: 1.1rem; align-items: start; }
.gx-grid:has(> .gx-facets:not([open])) { grid-template-columns: auto minmax(0, 1fr); }
.gx-main { min-width: 0; }
.gx-facets { position: sticky; top: 0.5rem; max-height: calc(100vh - 6rem); overflow: auto; font-size: 0.84rem; }
.gx-facets > summary {
  cursor: pointer; color: var(--text-muted); font-size: 0.74rem; text-transform: uppercase; letter-spacing: 0.06em;
  padding: 0.3rem 0; list-style: none; display: flex; align-items: center; gap: 0.4rem;
}
.gx-facets > summary::-webkit-details-marker { display: none; }
.gx-facets > summary::before { content: '▸'; transition: transform 0.15s; }
.gx-facets[open] > summary::before { transform: rotate(90deg); }
.gx-facets .badge { font-size: 0.7rem; padding: 0 0.4rem; }
.gx-facets .badge::before { display: none; }
.gx-facet { margin-top: 0.75rem; }
.gx-facet-head { display: flex; justify-content: space-between; align-items: baseline; color: var(--text-dim);
  font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.06em; margin-bottom: 0.2rem; }
.gx-facet ul { list-style: none; margin: 0; padding: 0; }
.gx-fv {
  display: flex; align-items: center; gap: 0.45rem; width: 100%; text-align: left; background: none; border: 0;
  padding: 0.22rem 0.4rem; border-radius: 5px; color: var(--text-muted); cursor: pointer; font: inherit;
}
.gx-fv:hover, .gx-fv:focus-visible { background: var(--bg-card); color: var(--text-main); outline: none; }
.gx-fv.on { background: var(--primary-glow); color: var(--text-main); }
.gx-fv.zero { opacity: 0.45; }
.gx-fv i { width: 9px; height: 9px; border-radius: 50%; flex: none; }
.gx-fv-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gx-fv-name.mono { font-size: 0.8rem; }
.gx-n { color: var(--text-dim); font-size: 0.76rem; font-variant-numeric: tabular-nums; }
.gx-link { background: none; border: 0; padding: 0; color: var(--primary); cursor: pointer; font: inherit; font-size: 0.78rem; text-transform: none; letter-spacing: 0; }
.gx-link:hover { text-decoration: underline; }
.gx-more { margin: 0.15rem 0 0 0.4rem; }

.gx-bar { display: flex; flex-wrap: wrap; gap: 0.5rem 0.9rem; align-items: center; margin-bottom: 0.6rem; }
.gx-switch { display: inline-flex; border: 1px solid var(--border-default); border-radius: 7px; overflow: hidden; }
.gx-switch button { background: none; border: 0; padding: 0.35rem 0.9rem; color: var(--text-muted); cursor: pointer; font: inherit; font-size: 0.85rem; font-weight: 600; }
.gx-switch button + button { border-left: 1px solid var(--border-default); }
.gx-switch button[aria-selected="true"] { background: var(--primary); color: #fff; }
.gx-search { display: inline-flex; gap: 0.3rem; align-items: center; }
.gx-search input { width: 15rem; max-width: 52vw; margin: 0; }
.gx-search select, .gx-ctl select { margin: 0; width: auto; padding: 0.3rem 0.45rem; font-size: 0.82rem; }
.gx-ctl { display: inline-flex; align-items: center; gap: 0.35rem; font-size: 0.82rem; color: var(--text-muted); }
.gx-ctl input { margin: 0; }
.gx-export { position: relative; margin-left: auto; }
.gx-export > summary { list-style: none; }
.gx-export > summary::-webkit-details-marker { display: none; }
.gx-menu {
  position: absolute; right: 0; top: calc(100% + 0.3rem); z-index: 5; min-width: 15rem; display: grid;
  background: var(--bg-surface); border: 1px solid var(--border-default); border-radius: 8px; padding: 0.3rem;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.3);
}
.gx-menu button { background: none; border: 0; text-align: left; padding: 0.45rem 0.6rem; border-radius: 5px; color: var(--text-main); cursor: pointer; font: inherit; font-size: 0.85rem; }
.gx-menu button:hover { background: var(--bg-card); }

.gx-chips { display: flex; flex-wrap: wrap; gap: 0.35rem 0.5rem; align-items: center; margin-bottom: 0.6rem; }
.gx-chip {
  display: inline-flex; align-items: center; gap: 0.3rem; font-size: 0.8rem; padding: 0.15rem 0.2rem 0.15rem 0.6rem;
  background: var(--bg-card); border: 1px solid var(--border-default); border-radius: 999px; color: var(--text-main);
}
.gx-chip button { background: none; border: 0; color: var(--text-muted); cursor: pointer; font-size: 1rem; line-height: 1; padding: 0 0.3rem; }
.gx-chip button:hover { color: var(--text-main); }

.gx-actions {
  margin-bottom: 0.6rem; padding: 0.55rem 0.7rem; border: 1px solid var(--primary); border-radius: 8px;
  background: rgba(99, 102, 241, 0.08); font-size: 0.85rem;
}
.gx-actions-row { display: flex; flex-wrap: wrap; gap: 0.4rem 0.5rem; align-items: center; }
.gx-what { margin-right: 0.4rem; overflow-wrap: anywhere; }
.gx-path { margin-top: 0.45rem; color: var(--text-muted); overflow-wrap: anywhere; }
.gx-pick { background: none; border: 0; padding: 0; color: var(--text-main); cursor: pointer; font: inherit; border-bottom: 1px dotted var(--border-default); }
.gx-pick:hover { color: var(--primary); border-bottom-color: var(--primary); }

.gx-tabs { display: flex; gap: 0.2rem; border-bottom: 1px solid var(--border-subtle); margin-bottom: 0.5rem; }
.gx-tabs button { background: none; border: 0; border-bottom: 2px solid transparent; padding: 0.4rem 0.8rem; color: var(--text-muted); cursor: pointer; font: inherit; font-size: 0.88rem; }
.gx-tabs button[aria-selected="true"] { color: var(--text-main); border-bottom-color: var(--primary); }
.gx-table { max-height: 70vh; overflow: auto; }
.gx-table thead th { position: sticky; top: 0; background: var(--bg-surface); z-index: 1; }
.gx-table th.num, .gx-table td.num { text-align: right; font-variant-numeric: tabular-nums; }
.gx-table .gx-check { width: 2rem; }
.gx-table .gx-check input { margin: 0; }
.gx-sort { background: none; border: 0; padding: 0; color: inherit; cursor: pointer; font: inherit; text-transform: inherit; letter-spacing: inherit; white-space: nowrap; }
.gx-sort:hover { color: var(--text-main); }
.gx-table tbody tr[data-row] { cursor: pointer; }
.gx-table tbody tr[data-row]:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }
.gx-table tbody tr.sel td { background: var(--primary-glow); }
.gx-table tbody tr.dim-row { opacity: 0.4; }
.gx-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 0.4rem; vertical-align: 1px; }
.gx-open { color: var(--text-dim); text-decoration: none; margin-left: 0.2rem; }
.gx-open:hover { color: var(--primary); }
.gx-table-note { font-size: 0.78rem; margin-top: 0.5rem; }

.gx-underlay[hidden] { display: none; }
.gx-underlay { position: absolute; left: 0; width: 100%; pointer-events: none; border-radius: 10px; background: var(--bg-surface); }
.gx-underlay path { fill: rgba(148, 163, 184, 0.07); stroke: rgba(148, 163, 184, 0.28); stroke-width: 0.8; vector-effect: non-scaling-stroke; }
.gx-underlay .gx-mask rect { fill: var(--bg-surface); stroke: none; }
.graph-cy.over-map { background: transparent; position: relative; z-index: 1; }
.gx-minimap {
  position: absolute; right: 0.5rem; bottom: 0.5rem; z-index: 2; width: 200px; height: 130px; cursor: crosshair;
  background: rgba(17, 24, 39, 0.88); border: 1px solid var(--border-default); border-radius: 6px; touch-action: none;
}
.gx-legend { display: flex; flex-wrap: wrap; gap: 0.35rem 0.9rem; align-items: center; margin-top: 0.6rem; font-size: 0.8rem; color: var(--text-muted); }
.gx-legend .gf-k { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-dim); }
.gx-legend .gf-k + .lg { margin-left: -0.3rem; }
.gx-legend .lg { display: inline-flex; align-items: center; gap: 0.35rem; }
.gx-legend .lg i { width: 9px; height: 9px; border-radius: 50%; display: inline-block; }
.gx-legend .lg i.ring { background: none; border: 2px solid; width: 10px; height: 10px; }
.gx-legend .lg i.ring.red { border-color: var(--accent-red); }
.gx-legend .lg i.ring.cyan { border-color: var(--accent-cyan); border-style: dashed; }
.gx-legend .lg i.ring.amber { border-color: var(--accent-amber); border-style: double; border-width: 3px; }
.graph-inspect .gi-facts { display: flex; flex-wrap: wrap; gap: 0.25rem 0.8rem; margin-top: 0.55rem; font-size: 0.8rem; color: var(--text-muted); }
.graph-inspect .gi-alert { color: #fca5a5; }

@media (max-width: 900px) {
  .gx-grid, .gx-grid:has(> .gx-facets:not([open])) { grid-template-columns: minmax(0, 1fr); }
  .gx-facets { position: static; max-height: none; border: 1px solid var(--border-subtle); border-radius: 8px; padding: 0.3rem 0.7rem 0.6rem; }
  .gx-facets[open] .gx-facets-body { display: grid; grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr)); gap: 0 1rem; }
  .gx-export { margin-left: 0; }
  .gx-minimap { width: 140px; height: 91px; }
}

/* Connect form (entity Connections panel). */
.edge-form { display: flex; gap: 0.5rem; flex-wrap: wrap; align-items: center; margin-top: 0.9rem; }
.edge-form select, .edge-form input { width: auto; max-width: 100%; }
.edge-form input { flex: 1 1 9rem; min-width: 8rem; }
@media (max-width: 640px) {
  .edge-form { flex-direction: column; align-items: stretch; }
  .edge-form select, .edge-form input { width: 100%; }
}

/* Help tips: the circled ? that explains a concept in place. */
.help-tip {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.05rem; height: 1.05rem; padding: 0; margin-left: 0.45rem;
  appearance: none; border-radius: 50%;
  border: 1px solid var(--border-default); background: transparent;
  color: var(--text-dim); font-family: var(--font-sans);
  font-size: 0.7rem; font-weight: 600; line-height: 1;
  cursor: help; vertical-align: middle; flex: 0 0 auto;
}
.help-tip:hover, .help-tip:focus-visible, .help-tip[aria-expanded="true"] {
  color: var(--primary); border-color: var(--primary); background: var(--primary-glow);
}
.help-tip:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }
#help-pop {
  position: fixed; z-index: 8500; max-width: 300px;
  background: var(--bg-card); border: 1px solid var(--border-default);
  border-radius: 8px; padding: 0.7rem 0.85rem;
  font-size: 0.82rem; line-height: 1.55; color: var(--text-muted);
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.5);
  display: none; overflow-wrap: anywhere;
}
#help-pop .mono, #help-pop code {
  font-family: var(--font-mono); font-size: 0.78rem; color: var(--text-main);
}
#help-pop strong { color: var(--text-main); }
#help-pop p { margin: 0 0 0.5rem; }
#help-pop p:last-child { margin-bottom: 0; }
#help-pop .dot {
  display: inline-block; width: 7px; height: 7px; border-radius: 50%;
  margin-right: 0.2rem; vertical-align: baseline;
}
#help-pop .dot.strict { background: var(--accent-amber); }
#help-pop .dot.open { background: var(--border-default); }

/* Forecast chart (console #forecasts view). */
.fc-tabs { display: flex; flex-wrap: wrap; gap: 0.4rem; margin: 0.2rem 0 0.5rem; }
.fc-tab {
  padding: 0.25rem 0.6rem; border: 1px solid var(--border-default); border-radius: 6px;
  font-family: var(--font-mono); font-size: 0.78rem; color: var(--text-muted);
  background: transparent; cursor: pointer;
}
.fc-tab.active { color: var(--primary); border-color: var(--primary); background: var(--primary-glow); }
.fc-legend { display: flex; flex-wrap: wrap; gap: 0.35rem 1rem; margin: 0.6rem 0 0.9rem; }
.fc-legend .lg, td .lg {
  display: inline-flex; align-items: center; gap: 0.4rem;
  font-size: 0.8rem; color: var(--text-muted); font-family: var(--font-mono);
}
.fc-legend .lg i, td .lg i { width: 10px; height: 10px; border-radius: 50%; display: inline-block; flex: none; }
.fc-legend .lg.toggle { background: none; border: 0; padding: 0; cursor: pointer; }
.fc-legend .lg.toggle.off { opacity: 0.4; text-decoration: line-through; }

/* Tour: spotlight walkthrough. The hole's box-shadow does the dimming. */
#tour-overlay { position: fixed; inset: 0; z-index: 9500; }
#tour-hole {
  position: fixed; border-radius: 8px;
  box-shadow: 0 0 0 9999px rgba(2, 6, 16, 0.72);
  border: 1.5px solid var(--primary);
  transition: all 0.25s ease;
  pointer-events: none;
}
#tour-card {
  position: fixed; z-index: 9501; max-width: 340px;
  background: var(--bg-card); border: 1px solid var(--border-default);
  border-radius: 10px; padding: 0.9rem 1rem;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.55);
}
#tour-card h3 { margin: 0.1rem 0 0.4rem; font-size: 0.98rem; color: var(--text-main); }
#tour-card p { margin: 0 0 0.7rem; font-size: 0.85rem; line-height: 1.55; color: var(--text-muted); }
#tour-card .tour-n { font-size: 0.72rem; color: var(--text-dim); font-family: var(--font-mono); }
#tour-card .tour-kicker {
  font-size: 0.68rem; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--primary); margin-bottom: 0.15rem;
}
#tour-card .tour-actions { display: flex; gap: 0.5rem; align-items: center; }
#tour-card .tour-skip {
  margin-left: auto; background: none; border: 0; padding: 0;
  color: var(--text-dim); font-size: 0.78rem; cursor: pointer; text-decoration: underline;
}
@media (max-width: 640px) {
  #tour-card { left: 0.5rem !important; right: 0.5rem; bottom: 0.5rem; top: auto !important; max-width: none; }
}

/* Overview home: stat strip + getting-started checklist. */
.stat-strip {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr));
  gap: 0.6rem; margin-bottom: 1rem;
}
.stat-chip {
  display: block; padding: 0.7rem 0.85rem; border-radius: 10px;
  border: 1px solid var(--border-subtle); background: var(--bg-surface);
  text-decoration: none; color: inherit;
}
.stat-chip:hover { border-color: var(--primary); }
.stat-chip .n { font-size: 1.35rem; font-weight: 650; color: var(--text-main); font-family: var(--font-mono); }
.stat-chip .l { font-size: 0.76rem; color: var(--text-dim); margin-top: 0.1rem; }
.gs-step { display: flex; align-items: baseline; gap: 0.6rem; padding: 0.42rem 0; }
.gs-step + .gs-step { border-top: 1px solid var(--border-subtle); }
.gs-step .tick {
  flex: none; width: 1.15rem; height: 1.15rem; border-radius: 50%;
  border: 1.5px solid var(--border-default); color: transparent;
  font-size: 0.72rem; line-height: 1.05rem; text-align: center; align-self: center;
}
.gs-step.done .tick { background: var(--accent-emerald); border-color: var(--accent-emerald); color: #06281c; }
.gs-step.done .gs-text { color: var(--text-dim); text-decoration: line-through; }
.gs-step .gs-text { flex: 1; font-size: 0.88rem; }
.gs-step .gs-go { font-size: 0.82rem; white-space: nowrap; }

/* Alerts: the enable toggle in the rules table. */
.al-tog { display: inline-flex; align-items: center; gap: 0.35rem; font-size: 0.82rem; color: var(--text-muted); cursor: pointer; }
.al-tog input { margin: 0; }

/* ------------------------------------------------------------ passkeys */
/* An enrollment code is read aloud or copied, so it is large, spaced and
   selectable as one run. */
.enroll-code-box {
  font-family: ui-monospace, 'SFMono-Regular', Menlo, Consolas, monospace;
  font-size: 1.55rem; letter-spacing: 0.14em; text-align: center;
  padding: 0.85rem 1rem; margin: 0.6rem 0 0.9rem;
  border: 1px dashed var(--border-default, #2a2f3b); border-radius: 10px;
  background: var(--bg-canvas, #0b0d12); color: var(--text-main, #e8eaed);
  user-select: all; -webkit-user-select: all;
}
.pk-kind { font-size: 0.78rem; color: var(--text-dim, #6b7280); }
.pk-name { font-weight: 600; }

/* ---------------------------------------------------------- the SQL editor */
/* Editor left, sidebar right; the sidebar drops under the editor on a phone,
   where a side rail would leave neither usable. */
.sql-grid { display: grid; grid-template-columns: minmax(0, 1fr) 16rem; gap: 0.9rem; }
@media (max-width: 860px) { .sql-grid { grid-template-columns: minmax(0, 1fr); } }
.sql-main { position: relative; min-width: 0; }

/* Tabs: one per query, like a browser's. */
.sql-tabs { display: flex; flex-wrap: wrap; gap: 0.3rem; margin: -0.3rem 0 0.6rem; align-items: center; }
.sql-tab {
  display: inline-flex; align-items: center; max-width: 14rem;
  border: 1px solid var(--border-subtle); border-radius: 7px; background: var(--bg-canvas);
}
.sql-tab.active { border-color: var(--primary); background: var(--primary-glow); }
.sql-tab-name {
  background: none; border: 0; color: var(--text-muted); cursor: pointer;
  padding: 0.28rem 0.2rem 0.28rem 0.65rem; font: 500 0.8rem var(--font-sans);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}
.sql-tab.active .sql-tab-name { color: var(--text-main); }
.sql-tab-x, .sql-tab-new, .sql-mini {
  background: none; border: 0; color: var(--text-dim); cursor: pointer;
  font: 600 0.95rem/1 var(--font-sans); padding: 0.3rem 0.45rem; border-radius: 5px;
}
.sql-tab-x:hover, .sql-tab-new:hover, .sql-mini:hover { color: var(--text-main); background: var(--bg-card); }
.sql-tab-new { border: 1px dashed var(--border-default); padding: 0.25rem 0.6rem; }
.sql-tab-rename { width: 9rem !important; padding: 0.2rem 0.45rem !important; font-size: 0.8rem !important; }

/* The editor: a transparent textarea over a highlighted copy of its own
   text. Both are unwrapped, same font, same padding, scrolled together, so
   every character sits exactly over its coloured twin. */
.sql-ed {
  position: relative; display: flex; height: 15rem; min-height: 8rem; max-height: 70vh;
  resize: vertical; overflow: hidden;
  background: var(--bg-canvas); border: 1px solid var(--border-default); border-radius: 10px;
}
.sql-ed:focus-within { border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-glow); }
/* Write mode is a different posture; the editor says so at a glance. */
.sql-ed.writing { border-color: rgba(245, 158, 11, 0.7); }
.sql-ed.writing:focus-within { box-shadow: 0 0 0 3px rgba(245, 158, 11, 0.2); }
.sql-gutter {
  flex: none; min-width: 2.6rem; overflow: hidden; white-space: pre; text-align: right;
  padding: 0.8rem 0.55rem calc(0.8rem + 24px) 0.5rem; color: var(--text-dim);
  font: 0.9rem/1.6 var(--font-mono); user-select: none; border-right: 1px solid var(--border-subtle);
}
.sql-code { position: relative; flex: 1; min-width: 0; }
.sql-hl, .sql-text, .sql-measure {
  font-family: var(--font-mono); font-size: 0.9rem; line-height: 1.6; tab-size: 2;
  letter-spacing: 0; font-variant-ligatures: none;
}
.sql-hl, .sql-text {
  position: absolute; inset: 0; margin: 0; white-space: pre; padding: 0.8rem 0.9rem;
  border: 0; border-radius: 0;
}
/* Extra room at the far edges so the copy can always scroll as far as the
   textarea, whose scrollbars take space the copy does not have. */
.sql-hl {
  overflow: hidden; pointer-events: none; color: var(--text-main);
  padding-bottom: calc(0.8rem + 24px); padding-right: calc(0.9rem + 24px);
}
.sql-text {
  width: 100%; height: 100%; resize: none; overflow: auto; background: transparent;
  color: transparent; caret-color: var(--text-main); outline: none;
}
.sql-text::placeholder { color: var(--text-dim); }
.sql-text::selection { background: rgba(99, 102, 241, 0.4); color: transparent; }
.sql-measure { position: absolute; visibility: hidden; white-space: pre; left: 0; top: 0; }
@media (pointer: coarse) {
  /* 16px is the iOS no-zoom floor; the gutter follows so the lines stay level. */
  .sql-hl, .sql-text, .sql-measure, .sql-gutter { font-size: 16px; }
}
.tk-keyword { color: #a5b4fc; }
.tk-string { color: #86efac; }
.tk-number { color: #fcd34d; }
.tk-comment { color: var(--text-dim); font-style: italic; }
.tk-qident { color: #67e8f9; }
.tk-param { color: #f9a8d4; }
.tk-op { color: #cbd5e1; }
.tk-mark { text-decoration: underline wavy var(--accent-red); text-underline-offset: 3px; background: rgba(239, 68, 68, 0.18); }

/* Completion, under the caret. */
.sql-ac {
  position: absolute; z-index: 30; min-width: 16rem; max-width: 28rem; max-height: 15rem; overflow-y: auto;
  background: var(--bg-surface); border: 1px solid var(--border-default); border-radius: 8px;
  box-shadow: 0 12px 28px rgba(0, 0, 0, 0.45); padding: 0.25rem;
}
.sql-ac-item {
  display: flex; align-items: baseline; gap: 0.5rem; padding: 0.25rem 0.5rem; border-radius: 5px;
  font-size: 0.84rem; cursor: pointer; white-space: nowrap;
}
.sql-ac-item.on { background: var(--primary-glow); }
.sql-ac-item > .mono { overflow: hidden; text-overflow: ellipsis; }
.sql-ac-kind {
  flex: none; width: 1.9rem; font: 700 0.62rem var(--font-mono); text-transform: uppercase;
  color: var(--text-dim); letter-spacing: 0.04em;
}
.sql-ac-kind.k-column { color: #67e8f9; }
.sql-ac-kind.k-table { color: #a5b4fc; }
.sql-ac-kind.k-function { color: #fcd34d; }
.sql-ac-detail { margin-left: auto; padding-left: 0.8rem; font-size: 0.74rem; overflow: hidden; text-overflow: ellipsis; }

.sql-bar { display: flex; align-items: center; gap: 0.6rem; margin-top: 0.6rem; flex-wrap: wrap; }
.sql-bar #sql-run { min-width: 7.5rem; }
.sql-status { margin-left: auto; font-size: 0.8rem; }

/* The sidebar: tables, saved queries, history. */
.sql-side {
  border: 1px solid var(--border-subtle); border-radius: 10px; background: var(--bg-canvas);
  display: flex; flex-direction: column; max-height: 24rem; min-height: 0;
}
.sql-side-tabs { display: flex; border-bottom: 1px solid var(--border-subtle); flex: none; }
.sql-side-tabs button {
  flex: 1; background: none; border: 0; border-bottom: 2px solid transparent; cursor: pointer;
  color: var(--text-dim); font: 600 0.74rem var(--font-sans); letter-spacing: 0.06em; text-transform: uppercase;
  padding: 0.5rem 0.3rem 0.4rem;
}
.sql-side-tabs button:hover { color: var(--text-main); }
.sql-side-tabs button.active { color: var(--text-main); border-bottom-color: var(--primary); }
/* Vertical only: a long table name should end in an ellipsis, not push a
   horizontal scrollbar under a list you are trying to read down. */
.sql-side-body { overflow-y: auto; overflow-x: hidden; min-height: 0; flex: 1; }
.sql-schema-head {
  padding: 0.45rem 0.5rem; border-bottom: 1px solid var(--border-subtle);
  position: sticky; top: 0; background: var(--bg-canvas); z-index: 2;
}
.sql-filter {
  width: 100%; background: var(--bg-surface) !important; color: var(--text-main);
  border: 1px solid var(--border-subtle) !important; border-radius: 6px; padding: 0.25rem 0.45rem !important;
  font-family: var(--font-sans); font-size: 0.8rem !important;
}
.sql-filter:focus { outline: none; border-color: var(--primary) !important; }
/* A schema heading, so the engine's own schemas read as a section rather
   than as tables someone forgot to name well. */
.sql-group {
  padding: 0.45rem 0.7rem 0.2rem; font-family: var(--font-mono);
  font-size: 0.74rem; color: var(--text-muted);
  background: var(--bg-canvas); border-bottom: 1px solid var(--border-subtle);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sql-group-row { display: flex; justify-content: space-between; align-items: center; }
.sql-side-empty { padding: 0.6rem 0.7rem; font-size: 0.8rem; }
.sql-table { display: flex; align-items: center; border-bottom: 1px solid var(--border-subtle); }
.sql-table:hover { background: var(--bg-card); }
.sql-table-name {
  flex: 1; min-width: 0; display: flex; align-items: baseline; gap: 0.35rem;
  background: none; border: 0; cursor: pointer; text-align: left; color: var(--text-muted);
  padding: 0.38rem 0.2rem 0.38rem 0.55rem; font-size: 0.82rem;
}
.sql-table-name:hover { color: var(--text-main); }
.sql-table-name > .mono { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.sql-caret { flex: none; width: 0.7rem; color: var(--text-dim); font-size: 0.7rem; }
.sql-count { margin-left: auto; flex: none; font-size: 0.75rem; }
.sql-table .sql-mini { font-size: 0.78rem; padding: 0.3rem 0.35rem; }
.sql-cols { border-bottom: 1px solid var(--border-subtle); padding: 0.15rem 0 0.3rem; }
.sql-col {
  display: flex; width: 100%; justify-content: space-between; gap: 0.6rem; align-items: baseline;
  background: none; border: 0; cursor: pointer; text-align: left; color: var(--text-muted);
  padding: 0.15rem 0.7rem 0.15rem 1.7rem; font-size: 0.78rem;
}
.sql-col:hover { color: var(--text-main); background: var(--bg-card); }
.sql-col > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.sql-col > .dim { flex: none; max-width: 45%; font-size: 0.72rem; }
.sql-item { display: flex; align-items: center; border-bottom: 1px solid var(--border-subtle); }
.sql-item:hover { background: var(--bg-card); }
.sql-item-open {
  flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0.1rem;
  background: none; border: 0; cursor: pointer; text-align: left; color: var(--text-muted);
  padding: 0.42rem 0.7rem; font-size: 0.82rem;
}
.sql-item-open:hover { color: var(--text-main); }
.sql-item-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sql-item-name.mono { font-size: 0.78rem; }
.sql-item-meta { font-size: 0.72rem; }
.sql-bad { color: #fca5a5; }
.sql-mini.text { font-size: 0.72rem; font-weight: 600; text-transform: none; letter-spacing: 0; }

/* Results stay a grid, never stacked cards: a query result is columns. */
.sql-set-actions { gap: 0.4rem; }
.sql-row-filter { width: 9.5rem !important; padding: 0.3rem 0.5rem !important; font-size: 0.8rem !important; }
.sql-seg { display: inline-flex; border: 1px solid var(--border-default); border-radius: 6px; overflow: hidden; }
.sql-seg button {
  background: none; border: 0; color: var(--text-muted); cursor: pointer;
  padding: 0.3rem 0.65rem; font: 600 0.8rem var(--font-sans);
}
.sql-seg button + button { border-left: 1px solid var(--border-default); }
.sql-seg button[aria-pressed="true"] { background: var(--primary-glow); color: var(--text-main); }
.sql-out-wrap { max-height: 32rem; overflow: auto; border: 1px solid var(--border-subtle); border-radius: 8px; }
table.sql-out { font-size: 0.84rem; }
table.sql-out thead th {
  position: sticky; top: 0; z-index: 1; background: var(--bg-surface); padding: 0;
  text-transform: none; letter-spacing: 0;
}
table.sql-out th.sql-rn, table.sql-out td.sql-rn {
  width: 1%; text-align: right; font-size: 0.72rem; padding: 0.45rem 0.6rem; font-family: var(--font-mono);
}
table.sql-out td { white-space: nowrap; max-width: 26rem; overflow: hidden; text-overflow: ellipsis; padding: 0.45rem 0.75rem; cursor: pointer; }
table.sql-out td.sql-rn { cursor: default; }
table.sql-out td:not(.sql-rn):hover { background: rgba(99, 102, 241, 0.1); }
.sql-sort {
  display: flex; align-items: baseline; gap: 0.35rem; width: 100%;
  background: none; border: 0; cursor: pointer; color: var(--text-muted);
  font: 700 0.78rem var(--font-mono); padding: 0.5rem 0.75rem; white-space: nowrap; text-align: left;
}
th.right .sql-sort { justify-content: flex-end; }
.sql-sort:hover { color: var(--text-main); }
.sql-type { font-weight: 400; font-size: 0.66rem; color: var(--text-dim); }
.sql-arrow { font-size: 0.6rem; color: var(--primary); min-width: 0.6rem; }
.sql-cell-full { white-space: pre-wrap; overflow-wrap: anywhere; max-height: 50vh; overflow-y: auto; }
.sql-plan { white-space: pre; max-height: 32rem; overflow: auto; }
.sql-plan .plan-node { color: #a5b4fc; font-weight: 700; }
.sql-plan .plan-node.seq { color: #fcd34d; }

/* Bars stay HTML: a label, a bar and its value read better as a row than
   as a canvas. */
.sql-bars { display: flex; flex-direction: column; gap: 0.3rem; }
.sql-bar-row { display: grid; grid-template-columns: minmax(6rem, 14rem) minmax(0, 1fr) auto; gap: 0.7rem; align-items: center; font-size: 0.82rem; }
.sql-bar-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-muted); }
.sql-bar-track { height: 0.85rem; }
.sql-bar-track i { display: block; height: 100%; background: #3987e5; border-radius: 0 4px 4px 0; }
.sql-bar-val { color: var(--text-main); }
@media (max-width: 640px) {
  .sql-bar-row { grid-template-columns: minmax(4rem, 8rem) minmax(0, 1fr) auto; }
  .sql-row-filter { width: 100% !important; }
  .sql-status { margin-left: 0; width: 100%; }
}

/* ------------------------------------------------------ metric explorer */
/* Stacked charts, one per metric, sharing a time axis and a cursor. The
   toolbar wraps rather than scrolls; on a phone each group takes a row. */
.mx { margin-top: 1.1rem; border-top: 1px solid var(--border-subtle); padding-top: 1rem; }
.mx-bar { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; }
.mx-actions { margin-left: auto; display: inline-flex; gap: 0.5rem; align-items: center; }
.mx-custom { position: relative; }
.mx-custom > summary { list-style: none; cursor: pointer; }
.mx-custom > summary::-webkit-details-marker { display: none; }
.mx-custom-box {
  position: absolute; z-index: 20; top: calc(100% + 0.35rem); left: 0;
  display: flex; flex-wrap: wrap; gap: 0.6rem; align-items: flex-end;
  background: var(--bg-surface); border: 1px solid var(--border-default); border-radius: 8px;
  padding: 0.75rem; box-shadow: 0 12px 28px rgba(0, 0, 0, 0.45); width: max-content; max-width: 90vw;
}
.mx-custom-box label { margin: 0; display: flex; flex-direction: column; gap: 0.2rem; font-size: 0.75rem; }
.mx-custom-box input {
  background: var(--bg-canvas); color: var(--text-main); border: 1px solid var(--border-default);
  border-radius: 6px; padding: 0.35rem 0.5rem; font: 0.85rem var(--font-mono); color-scheme: dark;
}
.mx-range { margin: 0.7rem 0 0.2rem; font-size: 0.85rem; font-family: var(--font-mono); }
.mx-note { font-family: var(--font-sans); font-size: 0.78rem; margin-top: 0.15rem; }
.mx-chart { margin-top: 0.8rem; }
.mx-head { display: flex; align-items: baseline; gap: 0.5rem; min-width: 0; margin-bottom: 0.25rem; }
.mx-swatch { width: 10px; height: 10px; border-radius: 50%; flex: none; align-self: center; }
.mx-name { font-weight: 700; font-size: 0.88rem; }
.mx-head > .dim { font-size: 0.8rem; }
.mx-read { margin-left: auto; font-size: 0.8rem; text-align: right; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.mx-read strong { color: var(--text-main); }
.mx-plot { width: 100%; position: relative; }
/* uPlot's own stylesheet sets a light background on the drag selection. */
.mx-plot .u-select { background: rgba(99, 102, 241, 0.18); }
.mx-plot .u-over { cursor: crosshair; }
.mx-table { max-height: 22rem; overflow: auto; border: 1px solid var(--border-subtle); border-radius: 8px; }
.mx-table thead th { position: sticky; top: 0; background: var(--bg-surface); }
.mx-table tbody td { padding: 0.4rem 0.75rem; }
@media (max-width: 640px) {
  .mx-actions { margin-left: 0; }
  .mx-head { flex-wrap: wrap; }
  .mx-read { flex-basis: 100%; margin-left: 0; text-align: left; white-space: normal; }
}

/* ------------------------------------------------------------ house charts */
/* The readout sits above a chart and says what is under the cursor, so no
   tooltip ever covers the line being read. Fixed height: the chart must not
   jump as the text changes. */
.pc-read {
  min-height: 1.5rem; display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.25rem 0.9rem;
  font-size: 0.78rem; margin-bottom: 0.25rem;
}
.pc-item { display: inline-flex; align-items: baseline; gap: 0.35rem; color: var(--text-muted); white-space: nowrap; }
.pc-item i { width: 9px; height: 9px; border-radius: 50%; display: inline-block; align-self: center; }
.pc-item strong { color: var(--text-main); }
.pc-plot { width: 100%; }
.pc-plot .u-select, .mx-plot .u-select { background: rgba(99, 102, 241, 0.18); }
.pc-plot .u-over { cursor: crosshair; }
.spark-host { width: 120px; height: 26px; }

/* ----------------------------------------------------------------- grafana */
.gf-dash { display: grid; grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr)); gap: 0.9rem; }
.gf-card {
  border: 1px solid var(--border-subtle); border-radius: 10px; background: var(--bg-canvas);
  padding: 0.9rem 1rem; display: flex; flex-direction: column; gap: 0.5rem; align-items: flex-start;
}
.gf-card-title { font-weight: 700; }
.gf-card p { font-size: 0.85rem; color: var(--text-muted); flex: 1; }
.gf-tips { margin: 0.9rem 0 0 1.1rem; font-size: 0.86rem; color: var(--text-muted); display: grid; gap: 0.35rem; }

/* --------------------------------------------------------------------- map */
.map-panel { padding: 1rem; }
.map-bar { display: flex; flex-wrap: wrap; gap: 0.6rem; align-items: center; margin-bottom: 0.7rem; }
.map-q { width: 14rem !important; }
.map-types { display: flex; flex-wrap: wrap; gap: 0.35rem; }
.map-place-bar {
  display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; margin-bottom: 0.7rem;
  padding: 0.55rem 0.8rem; border: 1px solid var(--primary); border-radius: 8px; background: var(--primary-glow);
  font-size: 0.88rem;
}
.map-place-bar select { width: auto !important; max-width: 100%; }
.map-wrap { position: relative; border: 1px solid var(--border-subtle); border-radius: 10px; overflow: hidden; }
.map { width: 100%; height: min(68vh, 620px); min-height: 320px; }
.map-foot { display: flex; flex-wrap: wrap; gap: 0.5rem 1rem; align-items: center; justify-content: space-between; margin-top: 0.7rem; }
.map-legend { margin: 0; }
.map-legend .lg i.ring { background: transparent; border: 2.5px solid; width: 12px; height: 12px; }
.map-legend .lg i.cluster { background: rgba(148, 163, 184, 0.35); border: 1.5px solid #cbd5e1; width: 13px; height: 13px; }
.map-count { font-size: 0.82rem; }
.map-attr { font-size: 0.72rem; margin-top: 0.4rem; }
.map-row { background: none; border: 0; padding: 0; color: var(--text-main); cursor: pointer; text-align: left; font: inherit; }
.map-row:hover strong { text-decoration: underline; }
.kv-link { font-family: var(--font-sans); font-size: 0.78rem; font-weight: 500; color: var(--text-muted); }
/* The popup, in the console's dress rather than MapLibre's white. */
.pf-popup .maplibregl-popup-content {
  background: var(--bg-surface); color: var(--text-main); border: 1px solid var(--border-default);
  border-radius: 10px; padding: 0.75rem 0.85rem; box-shadow: 0 12px 28px rgba(0, 0, 0, 0.5); font-family: var(--font-sans);
}
.pf-popup .maplibregl-popup-close-button { color: var(--text-muted); font-size: 1.1rem; padding: 0 0.4rem; }
.pf-popup.maplibregl-popup-anchor-bottom .maplibregl-popup-tip { border-top-color: var(--border-default); }
.pf-popup.maplibregl-popup-anchor-top .maplibregl-popup-tip { border-bottom-color: var(--border-default); }
.pf-popup.maplibregl-popup-anchor-left .maplibregl-popup-tip { border-right-color: var(--border-default); }
.pf-popup.maplibregl-popup-anchor-right .maplibregl-popup-tip { border-left-color: var(--border-default); }
.map-pop-name { font-weight: 700; padding-right: 1.2rem; }
.map-pop .mono.dim { font-size: 0.75rem; }
.map-pop-meta { font-size: 0.8rem; color: var(--text-muted); margin-top: 0.2rem; }
.map-pop-alert { color: #fca5a5; font-weight: 600; }
.map-pop-latest { margin-top: 0.5rem; font-size: 0.8rem; width: 100%; }
.map-pop-latest td { padding: 0.1rem 0.4rem 0.1rem 0; border: 0; }
.map-pop-actions { display: flex; gap: 0.4rem; flex-wrap: wrap; margin-top: 0.65rem; }
.maplibregl-ctrl-attrib { background: rgba(9, 13, 22, 0.7) !important; color: var(--text-dim); }
.maplibregl-ctrl-attrib a { color: var(--text-muted); }
@media (max-width: 640px) {
  .map-q { width: 100% !important; }
  .map { height: 58vh; }
}
