/* Mobile-first single stylesheet for the TradingSystems panel (Block 6). */
:root {
  --bg: #0e1116;
  --card: #171b22;
  --card-2: #1f2530;
  --fg: #e6e9ef;
  --muted: #8b93a1;
  --line: #2a313c;
  --accent: #4c8bf5;
  --ok: #3fb950;
  --warn: #d29922;
  --err: #f85149;
  --crit: #ff5c8a;
}
* { box-sizing: border-box; }
body {
  margin: 0;
  font: 15px/1.45 -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  background: var(--bg);
  color: var(--fg);
}
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
.wrap { max-width: 900px; margin: 0 auto; padding: 12px; }
.banner-dev {
  background: var(--warn); color: #1b1b1b; text-align: center;
  padding: 6px 10px; font-weight: 600; font-size: 13px;
}
.nav {
  display: flex; flex-wrap: wrap; gap: 4px; align-items: center;
  background: var(--card); padding: 8px 12px; border-bottom: 1px solid var(--line);
  position: sticky; top: 0; z-index: 5;
}
.nav a { padding: 6px 10px; border-radius: 6px; color: var(--fg); }
.nav a:hover { background: var(--card-2); text-decoration: none; }
/* The version carries the auto margin now, so it and Log out travel together as
   the right-hand group: session chrome, not navigation. Quieter than the links
   it sits beside — it is a fact to check, never something to click. */
.nav-version { margin-left: auto; color: var(--muted); font-size: 12px; }
.nav-logout { margin-left: 2px; }
button, .btn {
  /* inline-block matters on the anchor form: vertical padding on an INLINE
     element does not grow the line box, so an a.btn in flowing text paints over
     the lines above and below it. Invisible while every .btn sat alone in a
     table cell; the Block 15 remedy steps put one in a paragraph and it showed. */
  display: inline-block; text-decoration: none;
  font: inherit; cursor: pointer; border: 1px solid var(--line);
  background: var(--card-2); color: var(--fg); padding: 8px 14px; border-radius: 6px;
}
button:hover, .btn:hover { border-color: var(--accent); }
button.link { background: none; border: none; color: var(--accent); padding: 6px 10px; }
button.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
button.danger { background: var(--err); border-color: var(--err); color: #fff; }
.card {
  background: var(--card); border: 1px solid var(--line); border-radius: 10px;
  padding: 14px; margin: 10px 0;
}
.card h2, .card h3 { margin: 0 0 8px; font-size: 16px; }
.grid { display: grid; gap: 10px; grid-template-columns: 1fr; }
@media (min-width: 640px) { .grid.two { grid-template-columns: 1fr 1fr; } }
.row { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.spacer { flex: 1; }
.muted { color: var(--muted); }
/* The clock marker beside a date/time label. Quiet on purpose: it is there to
   be found when the number looks wrong, not to compete with the number. */
.tz { color: var(--muted); font-weight: 400; font-size: 11px; white-space: nowrap; }
.mono { font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; font-size: 13px; }
table { width: 100%; border-collapse: collapse; font-size: 13px; }
th, td { text-align: left; padding: 6px 8px; border-bottom: 1px solid var(--line); }
th { color: var(--muted); font-weight: 600; }
.table-scroll { overflow-x: auto; }
.chip {
  display: inline-block; padding: 2px 8px; border-radius: 999px; font-size: 12px;
  font-weight: 600; background: var(--card-2); border: 1px solid var(--line);
}
.chip.ok { color: var(--ok); border-color: var(--ok); }
.chip.warn { color: var(--warn); border-color: var(--warn); }
.chip.err, .chip.failed { color: var(--err); border-color: var(--err); }
.chip.crit { color: var(--crit); border-color: var(--crit); }
.chip.queued { color: var(--accent); border-color: var(--accent); }
.chip.running { color: var(--warn); border-color: var(--warn); }
.chip.done, .chip.passed { color: var(--ok); border-color: var(--ok); }
.lock { color: var(--warn); }
.metrics { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; }
@media (min-width: 640px) { .metrics { grid-template-columns: repeat(4, 1fr); } }
.metric { background: var(--card-2); border-radius: 8px; padding: 10px; }
.metric .v { font-size: 18px; font-weight: 700; }
.metric .k { color: var(--muted); font-size: 12px; }
/* Budget gauges (Block 10): a number, its cap, and how alarming the ratio is.
   The bar exists so "40% spent" and "95% spent" differ at a glance on a phone,
   which is where the operator actually reads this. */
.gauges { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
@media (max-width: 480px) { .gauges { grid-template-columns: 1fr; } }
.gauge { background: var(--card-2); border-radius: 8px; padding: 10px; }
.gauge .k { color: var(--muted); font-size: 12px; }
.gauge .v { font-size: 18px; font-weight: 700; }
.gauge .bar {
  /* `display: block` is load-bearing. This is a <span>, and an inline element
     ignores height and vertical margins, so the bar painted itself at
     line-height on the text baseline and sat on top of the value above it. */
  display: block;
  height: 6px; margin-top: 8px; border-radius: 3px;
  background: var(--bg); overflow: hidden;
}
.gauge .fill { display: block; height: 100%; background: var(--ok); }
.gauge.warn .fill { background: var(--warn); }
.gauge.err .fill { background: var(--err); }

/* Markdown reports are stored as markdown and shown as markdown: no renderer,
   no new dependency, and the text an operator reads is byte-for-byte the text
   that was written into research.hypotheses.report_md. */
pre.report {
  white-space: pre-wrap; word-break: break-word; margin: 0;
  background: var(--card-2); border-radius: 8px; padding: 12px;
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; font-size: 13px;
}

textarea {
  width: 100%; min-height: 240px; background: var(--bg); color: var(--fg);
  border: 1px solid var(--line); border-radius: 8px; padding: 10px;
  font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 13px;
}
input[type=text], input[type=password], input[type=date], select {
  font: inherit; background: var(--bg); color: var(--fg);
  border: 1px solid var(--line); border-radius: 6px; padding: 8px 10px;
}
label { display: block; margin: 8px 0 4px; color: var(--muted); font-size: 13px; }
.login { max-width: 340px; margin: 12vh auto; }
.error { color: var(--err); margin: 8px 0; }
form.inline { display: inline; }

/* Version footer: unobtrusive, but always answers "which build is this?" —
   the panel is a long-running process and its Python is only re-read on
   restart, so a stale process is otherwise invisible. */
.footer {
  display: flex;
  gap: 8px;
  align-items: baseline;
  justify-content: flex-end;
  padding: 12px 0 24px;
  border-top: 1px solid var(--line);
  margin-top: 24px;
}
.footer .version { color: var(--muted); }

/* ═══ Panel redesign (Block 14) ═══
   The seven components PANEL_UX_BRIEF §4 lists as missing, plus the chrome the
   five-section IA needs. Same tokens, same density, no new dependency: nothing
   above this line changed. */

/* A refused action must look refused. The panel disables a button wherever the
   server would refuse the request anyway and says why underneath; without this
   rule an accent-blue, pointer-cursor button still reads as clickable. */
button:disabled, .btn:disabled, button.primary:disabled, button.danger:disabled {
  background: var(--card-2); border-color: var(--line); color: var(--muted);
  cursor: not-allowed;
}
button:disabled:hover, .btn:disabled:hover { border-color: var(--line); }

/* Chrome: current top-level page, and a section sub-nav beneath the header. */
.nav a.on { background: var(--card-2); box-shadow: inset 0 -2px 0 var(--accent); }
.subnav { display: flex; flex-wrap: wrap; gap: 4px; margin: 0 0 10px; }
.subnav a {
  padding: 4px 10px; border-radius: 999px; font-size: 13px;
  color: var(--muted); border: 1px solid transparent;
}
.subnav a:hover { color: var(--fg); text-decoration: none; }
.subnav a.on { color: var(--fg); background: var(--card); border-color: var(--line); }

/* The trail back to the listing a record came from. Quieter than the sub-nav on
   purpose: it reports where you are, it is not the primary control. */
.crumbs { margin: 0 0 8px; font-size: 13px; }
.crumbs ol { display: flex; flex-wrap: wrap; gap: 6px; list-style: none; margin: 0; padding: 0; }
.crumbs li { display: flex; gap: 6px; align-items: center; }
.crumbs li + li::before { content: "/"; color: var(--line); }
.crumbs a { color: var(--muted); }
.crumbs a:hover { color: var(--fg); }
.crumbs [aria-current="page"] { color: var(--fg); }

/* 1. Empty state — what is missing, why, and the control that changes it.
   "No signals yet." is honest and inert; it says what is absent and never what
   to do about it, which is most of what makes a fresh install a wall. */
.empty {
  display: grid; gap: 8px; justify-items: start; padding: 16px;
  border: 1px dashed var(--line); border-radius: 8px; background: var(--card-2);
}
.empty .what { font-weight: 600; }
.empty .why { color: var(--muted); font-size: 13px; max-width: 62ch; }
td .empty { margin: 4px 0; }

/* 2. Stepper — position in a fixed sequence that spans several pages. Getting a
   bot live is six steps enforced in code and documented nowhere in the UI. */
.steps { display: flex; gap: 8px; overflow-x: auto; list-style: none; margin: 0; padding: 0 0 2px; }
.step { flex: 1 0 132px; border-top: 3px solid var(--line); padding-top: 8px; }
.step .n {
  display: block; color: var(--muted); font-size: 11px;
  letter-spacing: .06em; text-transform: uppercase;
}
.step .t { display: block; font-size: 13px; font-weight: 600; }
.step .s { font-size: 12px; color: var(--muted); }
.step.todo .t, .step.todo .t a { color: var(--muted); }
.step.done { border-top-color: var(--ok); }
.step.done .s { color: var(--ok); }
.step.now { border-top-color: var(--accent); }
.step.now .s { color: var(--accent); }
.step.blocked { border-top-color: var(--err); }
.step.blocked .s { color: var(--err); }
/* A step this bot cannot reach. Shown rather than dropped — the chain is the
   same six for every bot and renumbering it per strategy would make two bots'
   steppers incomparable — but struck through, and not counted. */
.step.na { border-top-style: dashed; opacity: 0.5; }
.step.na .t, .step.na .t a { text-decoration: line-through; }

/* 3. Inline definition — one sentence, where the term is used. tabindex="0"
   makes it work on a phone tap and on a keyboard, so it needs no JS. */
.def { position: relative; border-bottom: 1px dotted var(--muted); cursor: help; }
.def > span {
  display: none; position: absolute; left: 0; top: calc(100% + 6px); z-index: 20;
  width: min(320px, 78vw); padding: 8px 10px; cursor: auto;
  background: var(--card-2); border: 1px solid var(--line); border-radius: 6px;
  font-size: 13px; line-height: 1.4; font-weight: 400; color: var(--fg);
  box-shadow: 0 6px 18px rgba(0, 0, 0, .5);
}
.def:hover > span, .def:focus > span, .def:focus-within > span { display: block; }

/* 4. Command pending — exec-node work is asynchronous. Requested is not done,
   and a UI that reports success on the POST is lying about the single writer. */
.cmd {
  display: grid; gap: 6px; padding: 8px 10px; background: var(--card-2);
  border: 1px solid var(--line); border-left: 3px solid var(--accent); border-radius: 8px;
}
.cmd.acked { border-left-color: var(--ok); }
.cmd.failed { border-left-color: var(--err); }
.cmd .phases {
  display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
  font-size: 12px; color: var(--muted);
}
.cmd .phase { display: inline-flex; gap: 5px; align-items: center; }
.cmd .phase.on { color: var(--fg); font-weight: 600; }
.cmd .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--line); }
.cmd .phase.on .dot { background: var(--accent); }
.cmd.acked .phase.on .dot { background: var(--ok); }
.cmd.failed .phase.on .dot { background: var(--err); }
@keyframes cmd-wait { 0%, 100% { opacity: 1 } 50% { opacity: .2 } }
.cmd.pending .phase.on:last-of-type .dot { animation: cmd-wait 1.4s ease-in-out infinite; }

/* 5. Severity escalation — a card looks like what it can do, before the
   confirmation step. Routine .card, then .caution, then .irreversible. The
   typed confirmation stays the deliberation step; this is the run-up to it. */
.card.caution { border-color: var(--warn); }
.card.caution > h2, .card.caution > h3 { color: var(--warn); }
.card.irreversible { border-color: var(--err); }
.card.irreversible > h2, .card.irreversible > h3 { color: var(--err); }
.sev { font-size: 11px; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); }
.consequence { margin: 8px 0 0; padding-left: 18px; font-size: 13px; color: var(--muted); }
.consequence li { margin: 2px 0; }
.card.irreversible .consequence { color: var(--fg); }
.confirm {
  display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
  margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line);
}
.confirm .note { flex-basis: 100%; margin: 0; font-size: 12px; color: var(--muted); }

/* 6. Form validation — the error sits on the field and the input survives. */
.field { margin: 0 0 10px; }
.field .hint { color: var(--muted); font-size: 12px; margin-top: 4px; }
.field .msg { display: none; color: var(--err); font-size: 12px; margin-top: 4px; }
.field.bad input, .field.bad select, .field.bad textarea { border-color: var(--err); }
.field.bad .msg { display: block; }
.form-error {
  margin: 0 0 10px; padding: 10px; background: var(--card-2);
  border: 1px solid var(--err); border-left-width: 3px; border-radius: 8px;
}
.form-error p { margin: 0; }

/* 7. Disclosure — common settings visible, advanced one click away. */
details.more { border-top: 1px solid var(--line); margin-top: 10px; padding-top: 8px; }
details.more > summary {
  list-style: none; cursor: pointer; color: var(--accent); font-size: 13px; padding: 2px 0;
}
details.more > summary::-webkit-details-marker { display: none; }
details.more > summary::before { content: "\25B8"; display: inline-block; width: 14px; }
details.more[open] > summary::before { content: "\25BE"; }
details.more > summary:hover { text-decoration: underline; }
details.more > .body { padding-top: 8px; }

/* Read-only status readout — the inventory's §5 operations, the ones the panel
   may show and must not change. */
.kv { display: grid; grid-template-columns: auto 1fr; gap: 4px 14px; margin: 0; font-size: 13px; }
.kv dt { color: var(--muted); }
.kv dd { margin: 0; }

/* Remedy steps (BLOCK15_SPEC §2) — a Needs-you row states the requirement, the
   verdict and what to do about it. A shell step is text for the operator to
   copy; the panel never executes it (brief §3c), so it is styled as a quotable
   block rather than as a control. */
.steps-remedy { display: grid; gap: 8px; margin-top: 8px; justify-items: start; }
.steps-remedy > .btn { padding: 6px 12px; font-size: 13px; }
.shell-step {
  display: grid; gap: 6px; width: 100%; padding: 8px 10px;
  background: var(--card-2); border: 1px solid var(--line);
  border-left: 3px solid var(--muted); border-radius: 8px;
}
.shell-step .cmd-line { display: flex; gap: 8px; align-items: flex-start; }
.shell-step code {
  /* min-width:0 lets a flex child shrink below its content width, which is what
     allows a long schtasks line to wrap instead of widening the whole table. */
  flex: 1; min-width: 0; overflow-wrap: anywhere; white-space: pre-wrap;
}
.shell-step button.copy { flex: none; padding: 4px 10px; font-size: 12px; }
button.copy.ok { border-color: var(--ok); color: var(--ok); }

/* Ignoring a row on purpose: a reason is required, so the control is a small
   form rather than a single button. */
details.dismiss > summary {
  cursor: pointer; color: var(--muted); font-size: 12px; list-style: none;
}
details.dismiss > summary::-webkit-details-marker { display: none; }
details.dismiss > summary::before { content: "\25B8 "; }
details.dismiss[open] > summary::before { content: "\25BE "; }
details.dismiss form { display: grid; gap: 6px; margin-top: 6px; min-width: 160px; }
details.dismiss input {
  font: inherit; padding: 5px 8px; border-radius: 6px;
  border: 1px solid var(--line); background: var(--card); color: var(--fg);
}

/* A row arrived at from a go-live checklist remedy. Without it the link scrolls
   to the right place and the operator still has to work out which of the rows
   in view was the one they clicked. */
tr[id^="op-"]:target > td { background: var(--card-2); }
tr[id^="op-"]:target > td:first-child { box-shadow: inset 3px 0 var(--accent); }

/* The by-hand procedure under an operation that only records its outcome. */
.procedure ol { margin: 4px 0 0; padding-left: 20px; }
.procedure li { margin: 0 0 10px; max-width: 62em; }
.procedure pre {
  margin: 6px 0 0; padding: 8px 10px; overflow-x: auto;
  background: var(--bg); border: 1px solid var(--line); border-radius: 6px;
  font-size: 12px; white-space: pre; color: var(--fg);
}

/* A go-live line that is evaluated and shown but does not gate this target
   (DECISIONS.md P2.11). Dimmed, never hidden: the operator reads the whole of
   §10 whatever they are deploying to. */
tr.not-gating > td { opacity: 0.55; }

