/*
 * The Control Center shell.
 *
 * blueprint/12 § BLOCK 2 · 12 — MUST NOT be built yet: "The orb. Any
 * animation. A design system. Charts. Mobile." So this file is deliberately
 * flat: a handful of custom properties, no component library, no build step,
 * no motion. It is legible at 2am on a laptop and nothing more, because the
 * block that makes it beautiful is Block 17.
 */

:root {
  --bg: #0b0d10;
  --panel: #12161b;
  --line: #1e252d;
  --ink: #c8d0d8;
  --dim: #6b7885;
  --accent: #7dd3fc;
  --ok: #4ade80;
  --warn: #fbbf24;
  --bad: #f87171;
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

* { box-sizing: border-box; }

/*
 * [MEASURED] 2026-09-04, caught by test/ui/control-center.spec.ts on its first
 * run: the six-view navigation was VISIBLE on the login screen. `#nav` sets
 * `display: flex`, and an ID selector outranks the user-agent stylesheet's
 * `[hidden] { display: none }`, so setting the attribute did nothing.
 *
 * The shell hides things by attribute in a dozen places, so the rule is made
 * global and unconditional rather than patched at the one element that was
 * caught. Hiding must not depend on which selector happens to win.
 */
[hidden] { display: none !important; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 14px/1.55 var(--mono);
}

/* ── header status strip ─────────────────────────────────────────────── */
#strip {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  padding: 0.6rem 1rem;
  border-bottom: 1px solid var(--line);
  background: var(--panel);
  flex-wrap: wrap;
}
#strip .brand { font-weight: 700; letter-spacing: 0.1em; }
#strip .orb {
  display: inline-block; width: 9px; height: 9px; border-radius: 50%;
  background: var(--dim); vertical-align: middle; margin-right: 0.35rem;
}
#strip[data-state="RUNNING"]  .orb { background: var(--ok); }
#strip[data-state="PAUSED"]   .orb { background: var(--warn); }
#strip[data-state="FROZEN"]   .orb,
#strip[data-state="LOCKDOWN"] .orb { background: var(--bad); }

.clock { color: var(--dim); }
.dots { display: flex; gap: 0.85rem; margin-left: auto; }
.dot { color: var(--dim); }
.dot::before { content: "\25CF"; margin-right: 0.3rem; color: var(--dim); }
.dot[data-ok="true"]::before  { color: var(--ok); }
.dot[data-ok="false"]::before { color: var(--bad); }

.badge {
  padding: 0.15rem 0.6rem; border: 1px solid var(--line); border-radius: 3px;
  letter-spacing: 0.12em; font-weight: 700;
}
#strip[data-state="RUNNING"]  .badge { color: var(--ok);   border-color: var(--ok); }
#strip[data-state="PAUSED"]   .badge { color: var(--warn); border-color: var(--warn); }
#strip[data-state="FROZEN"]   .badge,
#strip[data-state="LOCKDOWN"] .badge { color: var(--bad);  border-color: var(--bad); }

.spend { color: var(--dim); }
.palette {
  background: none; border: 1px solid var(--line); color: var(--dim);
  border-radius: 3px; padding: 0.15rem 0.5rem; font: inherit; cursor: not-allowed;
}

/* ── navigation ──────────────────────────────────────────────────────── */
#nav { display: flex; gap: 0.25rem; padding: 0 0.5rem; border-bottom: 1px solid var(--line); flex-wrap: wrap; }
#nav a {
  color: var(--dim); text-decoration: none; padding: 0.55rem 0.8rem;
  border-bottom: 2px solid transparent;
}
#nav a:hover { color: var(--ink); }
#nav a[aria-current="page"] { color: var(--accent); border-bottom-color: var(--accent); }
#nav b { color: var(--line); font-weight: 400; margin-right: 0.3rem; }
#nav a[aria-current="page"] b { color: var(--accent); }

/* ── layout ──────────────────────────────────────────────────────────── */
#main { padding: 1.5rem 1rem 3rem; max-width: 72rem; margin: 0 auto; }
h1 { font-size: 1.05rem; letter-spacing: 0.08em; text-transform: uppercase; }
h2 { font-size: 0.85rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--dim); margin-top: 1.75rem; }
.muted { color: var(--dim); }
.small { font-size: 0.85em; }
.error { color: var(--bad); }
code { color: var(--accent); }
pre { background: var(--bg); border: 1px solid var(--line); padding: 0.75rem; overflow-x: auto; }

.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); gap: 0.75rem; }
.card { background: var(--panel); border: 1px solid var(--line); border-radius: 4px; padding: 0.9rem 1rem; }
.card h2 { margin-top: 0; }
.card.l5 { margin-top: 1rem; }
.lvl { color: var(--bad); }

dl { display: grid; grid-template-columns: auto 1fr; gap: 0.25rem 0.9rem; margin: 0; }
dt { color: var(--dim); }
dd { margin: 0; text-align: right; }
dd[data-ok="false"] { color: var(--bad); }
dd[data-ok="true"]  { color: var(--ok); }

table { border-collapse: collapse; width: 100%; }
th, td { text-align: left; padding: 0.35rem 0.6rem; border-bottom: 1px solid var(--line); }
th { color: var(--dim); font-weight: 400; }
.n { text-align: right; }
td.n[data-bad="true"] { color: var(--bad); }

/* ── kill switch ─────────────────────────────────────────────────────── */
.switches { display: grid; grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr)); gap: 0.75rem; }
.switch {
  background: var(--panel); border: 1px solid var(--line); border-radius: 4px;
  padding: 0.9rem 1rem; text-align: left; color: var(--ink); font: inherit; cursor: pointer;
}
.switch:hover { border-color: var(--accent); }
.switch h3 { margin: 0 0 0.35rem; font-size: 0.9rem; letter-spacing: 0.08em; text-transform: uppercase; }
.switch p { margin: 0; color: var(--dim); }
.switch[data-engaged="true"] { border-color: var(--bad); }
.switch[data-engaged="true"] h3 { color: var(--bad); }

#engaged .card { border-color: var(--bad); margin-bottom: 0.5rem; }

/* ── forms and dialog ────────────────────────────────────────────────── */
label { display: block; color: var(--dim); margin-top: 0.75rem; }
input {
  width: 100%; background: var(--bg); border: 1px solid var(--line);
  color: var(--ink); font: inherit; padding: 0.45rem 0.6rem; border-radius: 3px;
}
button { font: inherit; cursor: pointer; }
button.primary, button.danger, #btn-token, dialog menu button {
  background: var(--panel); border: 1px solid var(--line); color: var(--ink);
  padding: 0.45rem 0.9rem; border-radius: 3px; margin-top: 0.9rem;
}
button.primary { border-color: var(--accent); color: var(--accent); }
button.danger  { border-color: var(--bad);    color: var(--bad); }
dialog { background: var(--panel); color: var(--ink); border: 1px solid var(--line); border-radius: 5px; max-width: 34rem; }
dialog::backdrop { background: rgb(0 0 0 / 0.6); }
dialog menu { display: flex; gap: 0.6rem; justify-content: flex-end; padding: 0; margin: 0.5rem 0 0; }
details { margin-top: 1.5rem; }
summary { color: var(--dim); cursor: pointer; }

/* ── footer ──────────────────────────────────────────────────────────── */
footer {
  position: fixed; bottom: 0; left: 0; right: 0;
  display: flex; align-items: center; gap: 1rem;
  padding: 0.35rem 1rem; border-top: 1px solid var(--line);
  background: var(--panel); color: var(--dim); font-size: 0.85em;
}
footer button { background: none; border: 1px solid var(--line); color: var(--dim); border-radius: 3px; padding: 0.1rem 0.5rem; margin-left: auto; }
.conn[data-live="true"]  { color: var(--ok); }
.conn[data-live="false"] { color: var(--warn); }
.view.empty { color: var(--dim); }

/* ── ⌘2 Knowledge (Block 3) ─────────────────────────────────────────────
   A nested list and a plain SVG. blueprint/12 § BLOCK 3 · 12 forbids a graph
   visualisation library outright: "a force-directed graph is a demo, not a
   tool." Nothing here is a library and nothing moves. */
.kg-controls {
  display: grid; grid-template-columns: auto 1fr auto auto auto auto auto auto;
  gap: 0.4rem 0.6rem; align-items: center; margin: 1rem 0;
}
.kg-controls label { margin: 0; white-space: nowrap; }
.kg-controls input, .kg-controls select {
  width: auto; background: var(--bg); border: 1px solid var(--line);
  color: var(--ink); font: inherit; padding: 0.3rem 0.5rem; border-radius: 3px;
}
.kg-split { display: grid; grid-template-columns: minmax(18rem, 1fr) minmax(20rem, 1.3fr); gap: 1rem; align-items: start; }
#kg-list tr { cursor: pointer; }
#kg-list tr:hover td { color: var(--accent); }
#kg-list tr[aria-selected="true"] td { color: var(--accent); }
.kg-imp { color: var(--dim); text-align: right; width: 3rem; }
.kg-badge { color: var(--dim); font-size: 0.85em; }
.kg-badge[data-scope^="restricted"] { color: var(--warn); }
#kg-detail h2 { margin-top: 1.1rem; }
#kg-detail h2:first-child { margin-top: 0; }
.kg-edge { display: flex; gap: 0.5rem; padding: 0.2rem 0; border-bottom: 1px solid var(--line); }
.kg-edge .t { color: var(--accent); }
.kg-edge .w { color: var(--dim); margin-left: auto; white-space: nowrap; }
.kg-edge[data-closed="true"] { color: var(--dim); }
.kg-edge[data-closed="true"] .t { color: var(--dim); }
svg.kg-graph { width: 100%; height: 260px; border: 1px solid var(--line); border-radius: 4px; background: var(--bg); }
svg.kg-graph line { stroke: var(--line); stroke-width: 1; }
svg.kg-graph circle { fill: var(--panel); stroke: var(--dim); }
svg.kg-graph circle.root { stroke: var(--accent); }
svg.kg-graph text { fill: var(--ink); font-size: 9px; }

/* ── ⌘3 Memory (Block 4) ────────────────────────────────────────────────
   A belief is shown with its receipts or not at all: the excerpt block is
   deliberately the most legible thing on the panel, because "confidence 0.94"
   is unfalsifiable and the literal words are checkable in two seconds. */
#mem-list tr, #mem-inferences tr { cursor: pointer; }
#mem-list tr:hover td { color: var(--accent); }
#mem-list tr[aria-selected="true"] td { color: var(--accent); }
.kg-badge[data-state="retracted"],
.kg-badge[data-state="quarantined"] { color: var(--bad); }
.kg-badge[data-state="superseded"],
.kg-badge[data-state="expired"] { color: var(--warn); }

.mem-formula {
  white-space: pre-wrap; word-break: break-word;
  font-size: 0.85em; color: var(--ink);
}
.mem-excerpt {
  margin: 0.4rem 0; padding: 0.4rem 0.8rem;
  border-left: 2px solid var(--accent); color: var(--ink);
}
.mem-excerpt[data-kind="contradicts"] { border-left-color: var(--bad); }
.mem-excerpt[data-kind="qualifies"]   { border-left-color: var(--warn); }
.mem-excerpt .kg-badge { display: block; margin-top: 0.2rem; }

.mem-ctr {
  background: var(--panel); border: 1px solid var(--warn);
  border-radius: 4px; padding: 0.6rem 0.8rem; margin-bottom: 0.5rem;
}
.mem-ctr-head { color: var(--warn); font-size: 0.85em; letter-spacing: 0.06em; }
.mem-ctr-acts { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.5rem; }
.mem-ctr-acts button {
  background: none; border: 1px solid var(--line); color: var(--dim);
  border-radius: 3px; padding: 0.2rem 0.6rem; font: inherit; font-size: 0.85em;
}
.mem-ctr-acts button:hover { color: var(--accent); border-color: var(--accent); }
button.linkish {
  background: none; border: none; color: var(--accent);
  padding: 0; font: inherit; text-align: left;
}

/* ── THE INGESTION MONITOR ────────────────────────────────────────────────
   The card headings inside ⌘6 System's ingestion block. `h3` rather than
   `h2` so the Monitor reads as part of System rather than as a seventh
   view — blueprint/11 § 3 fixes the Control Center at six views and a
   block does not get to add one. */
#view-system .card h3 {
  margin: 0 0 0.5rem;
  font-size: 0.9rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}
#ing-items tr { cursor: pointer; }
#ing-items tr:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
#ing-items tr[aria-current="true"] { background: var(--sel, rgba(255,255,255,0.06)); }
/* An untrusted source is marked wherever it appears: it is the one property
   that decides whether the row's output can ever be retrieved. */
#ing-sources tr[data-bad="true"] td:nth-child(2) { color: var(--bad); font-weight: 600; }
/* Label above, key beneath: the key is what every command and error message
   uses, so the Monitor shows both rather than making the reader translate. */
#ing-sources td.src { white-space: pre-line; line-height: 1.3; }
#ing-sources td.src::first-line { font-weight: 600; }

/* ── THE MODEL BOUNDARY ───────────────────────────────────────────────────
   A model that is not zero-retention is marked wherever it appears: it is
   the one property that decides whether restricted content may reach it. */
#gw-models td.src { white-space: pre-line; line-height: 1.3; }
#gw-models td.src::first-line { font-weight: 600; }
#gw-models tr[data-bad="true"] td:nth-child(3) { color: var(--warn); font-weight: 600; }
#gw-assemblies tr { cursor: pointer; }
#gw-assemblies tr:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
#gw-assemblies tr[aria-current="true"] { background: var(--sel, rgba(255,255,255,0.06)); }
#gw-evals tr[data-bad="true"] td:nth-child(2) { color: var(--bad); font-weight: 600; }

/* ── BLOCK 7 · the audit log and the capability tree ──────────────────────
   Refusals and permanently-unassigned capabilities get their own colours.
   That is not decoration: the whole point of rendering money.move is that a
   person can SEE the difference between "not granted yet" and "can never be
   granted", and two rows in the same grey would lose exactly the distinction
   the row was created to carry. */
table { width: 100%; border-collapse: collapse; font-size: .86rem; }
th { text-align: left; font-weight: 600; opacity: .65; padding: .35rem .5rem;
     border-bottom: 1px solid var(--line, #2a2a2a); white-space: nowrap; }
td { padding: .35rem .5rem; border-bottom: 1px solid rgba(128,128,128,.14);
     vertical-align: top; }
td.authority { white-space: nowrap; opacity: .8; }
.big { font-size: 1.6rem; margin: .2rem 0 0; }

.outcome-executed  { color: #6bd08a; }
.outcome-refused   { color: #f0a35e; font-weight: 600; }
.outcome-awaiting_approval { color: #e6cf67; }
.outcome-abandoned { color: #9aa0a6; }
.outcome-reversed  { color: #7fb2f0; }

.status-ok        { color: #6bd08a; }
.status-denied    { color: #f0a35e; font-weight: 600; }
.status-error,
.status-timeout   { color: #ef6f6f; }
.status-running   { color: #7fb2f0; }
.status-cancelled { color: #9aa0a6; }

.verdict-allow             { color: #6bd08a; }
.verdict-deny              { color: #f0a35e; font-weight: 600; }
.verdict-halted            { color: #ef6f6f; font-weight: 600; }
.verdict-approval_required,
.verdict-dry_run_first     { color: #e6cf67; }

.risk-read { opacity: .7; }
.risk-medium { color: #e6cf67; }
.risk-high { color: #f0a35e; }
.risk-critical { color: #ef6f6f; font-weight: 600; }

/* The one that matters. */
.posture-permanently_unassigned {
  color: #ef6f6f; font-weight: 700; letter-spacing: .02em;
}
.posture-granted   { color: #6bd08a; }
.posture-ungranted { opacity: .65; }
.posture-disabled  { opacity: .45; }
.posture-declared_no_tool { opacity: .55; font-style: italic; }

/* ═══ ⌘1 Ask (Block 8) ════════════════════════════════════════════════════ */
.visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; }
.ask-bar { display: flex; gap: .5rem; margin: .75rem 0 .25rem; }
.ask-bar input { flex: 1; }
.ask-split { display: grid; grid-template-columns: minmax(20rem, 1.4fr) minmax(18rem, 1fr);
  gap: 1rem; align-items: start; }
.ask-answer { min-height: 4rem; white-space: pre-wrap; line-height: 1.55; }
/* A citation is an identifier, not a footnote number: the id IS the thing the
   verifier resolved, so it is rendered as itself rather than prettified. */
.ask-answer .cite { font-family: var(--mono, monospace); font-size: .82em;
  padding: 0 .25rem; border-radius: 3px; background: var(--chip, #1e2530); }
.ask-answer .cite.bad { background: #4a1f1f; }
.ask-stream { list-style: none; margin: .25rem 0; padding: 0; max-height: 22rem;
  overflow-y: auto; font-size: .88rem; }
.ask-stream li { display: flex; gap: .6rem; padding: .2rem 0;
  border-bottom: 1px solid var(--line, #222); }
.ask-stream .t { font-family: var(--mono, monospace); color: var(--dim, #7b8794);
  min-width: 9.5rem; }
.why-block { margin-bottom: .9rem; }
.why-block h3 { font-size: .78rem; letter-spacing: .06em; text-transform: uppercase;
  color: var(--dim, #7b8794); margin: 0 0 .3rem; }
.why-row { display: flex; gap: .5rem; font-size: .85rem; padding: .1rem 0; }
.why-row .k { color: var(--dim, #7b8794); min-width: 7rem; }

/* ═══ BLOCK 9 · tasks, approvals, failures ════════════════════════════════ */

/* The preview is the whole point of the approval screen, so it gets room and a
   monospace face: it is the action's own account of what it would do, and a
   person reading it is checking a payload, not skimming prose. */
.preview { font-family: var(--mono); font-size: .82rem; line-height: 1.5;
  background: var(--bg); border: 1px solid var(--line); border-radius: 4px;
  padding: .7rem .8rem; margin: .5rem 0 .9rem; max-height: 18rem; overflow: auto;
  white-space: pre-wrap; word-break: break-word; color: var(--ink); }

.appr { border: 1px solid var(--line); border-left: 3px solid var(--warn);
  border-radius: 4px; padding: .8rem .9rem; margin-bottom: .8rem;
  background: var(--panel); }
.appr.lapsed { border-left-color: var(--bad); opacity: .7; }
.appr h3 { margin: 0 0 .2rem; font-size: .95rem; }
.appr .meta { color: var(--dim); font-size: .8rem; font-family: var(--mono); }
.appr .why { margin: .45rem 0 .1rem; }
.appr .impact { color: var(--dim); margin: .1rem 0 .3rem; }
.appr menu { display: flex; gap: .5rem; margin: .6rem 0 0; padding: 0; }

/* A task's state is the first thing read, so it is a chip rather than a word in
   a sentence. `unknown_state` is the only one that is red AND bordered: it is
   not a failure, it is an absence of knowledge, and it needs a person. */
.tstate { font-family: var(--mono); font-size: .74rem; letter-spacing: .04em;
  padding: .12rem .45rem; border-radius: 3px; border: 1px solid transparent;
  text-transform: uppercase; }
.tstate.succeeded { color: var(--ok); }
.tstate.running, .tstate.pending { color: var(--accent); }
.tstate.blocked { color: var(--warn); }
.tstate.failed, .tstate.cancelled { color: var(--bad); }
.tstate.unknown_state { color: var(--bad); border-color: var(--bad); }

.task { border: 1px solid var(--line); border-radius: 4px; padding: .6rem .8rem;
  margin-bottom: .55rem; background: var(--panel); }
.task .title { font-weight: 600; }
.task .sub { color: var(--dim); font-size: .8rem; font-family: var(--mono); }
.task .flag { font-size: .82rem; margin-top: .3rem; }
.task .flag.warn { color: var(--warn); }
.task .flag.bad { color: var(--bad); }

/* ── ⌘7 Traces & Cost (Block 10) ─────────────────────────────────────────
   Four tabs on one screen rather than four screens, because a person reading
   this is holding one question — "what happened, and what did it cost" — and
   four nav entries would make them navigate their own investigation. */
.tabs { display: flex; gap: 0.35rem; margin: 0.75rem 0; border-bottom: 1px solid var(--line); }
.tab {
  background: none; border: none; border-bottom: 2px solid transparent;
  color: var(--dim); font: inherit; padding: 0.45rem 0.8rem; cursor: pointer;
}
.tab:hover { color: var(--fg); }
.tab.on { color: var(--fg); border-bottom-color: var(--accent); }
.split { display: grid; grid-template-columns: minmax(18rem, 22rem) 1fr; gap: 0.9rem; align-items: start; }
@media (max-width: 60rem) { .split { grid-template-columns: 1fr; } }
.rows { font-size: 0.9em; }
.rows td { padding: 0.28rem 0.5rem; vertical-align: top; }
.rows tr[data-selected="true"] td { background: var(--panel); }
.rows tr.clickable { cursor: pointer; }
.rows tr.clickable:hover td { background: var(--panel); }
.rows .bad { color: var(--bad); }
.rows .none { color: var(--dim); font-style: italic; }

/* The waterfall. One row per span, indented by depth, with a bar whose left
   edge is the offset and whose width is the duration — both as percentages of
   the trace's wall clock, so the picture is the timing rather than a decoration
   beside it. */
.waterfall { margin: 0.5rem 0 0.9rem; }
.wf-row { display: grid; grid-template-columns: 1fr 55%; gap: 0.6rem; align-items: center; padding: 0.12rem 0; }
.wf-name { font-size: 0.85em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wf-track { position: relative; height: 0.7rem; background: var(--panel); border-radius: 2px; }
.wf-bar { position: absolute; top: 0; bottom: 0; background: var(--accent); border-radius: 2px; min-width: 2px; }
.wf-bar[data-error="true"] { background: var(--bad); }
.wf-ms { font-size: 0.78em; color: var(--dim); }

/* BLOCK 11 · D4 — the freshness stamp.
   Four verdicts, four appearances, and `no_evidence` is deliberately the
   loudest of them rather than the quietest: the failure this stamp exists to
   catch is a screen that shows a value with nothing behind it, and a grey
   whisper in the corner is how that failure stays invisible. */
.freshness {
  display: block; margin: 0.35rem 0 0.6rem; font-size: 0.85em;
  padding: 0.25rem 0.5rem; border-left: 3px solid var(--dim); color: var(--dim);
}
.freshness[data-verdict="fresh"]       { border-left-color: var(--accent); color: var(--fg); }
.freshness[data-verdict="unbounded"]   { border-left-color: var(--dim); }
.freshness[data-verdict="stale"]       { border-left-color: var(--warn); color: var(--warn); }
.freshness[data-verdict="no_evidence"] { border-left-color: var(--bad);  color: var(--bad); }

/* BLOCK 11 · D11 — Connected systems, inside ⌘6.
   A FORBIDDEN system is painted in the bad colour wherever it appears, for the
   same reason an untrusted ingest source is: it is the one property that
   decides whether anything may ever reach that system, and a row that renders
   it as ordinary text buries the only thing about the row that matters.
   `ext-tools` marks an unusable tool on its health cell rather than on the
   whole row, so the 24h counts beside it stay readable — during an incident
   those counts are what tells you whether it ever worked. */
#ext-systems tr[data-forbidden="true"] td:nth-child(2) { color: var(--bad); font-weight: 600; }
#ext-tools   tr[data-ok="false"]       td:nth-child(2) { color: var(--warn); font-weight: 600; }
