/*
 * Solver console.
 *
 * The one design rule, and everything else follows from it: COLOUR IS RESERVED
 * FOR RISK. `exposed` is amber, `failed` is brick, and `open`/`done` get no
 * colour at all — they are plain text.
 *
 * That is not minimalism for its own sake. The four corridors disagree about
 * what their state words mean (`claimed` is terminal success on the two send
 * legs and money-still-out on the two receive legs), so the word alone is
 * misleading and the PHASE has to carry the signal. If "fine" were green and
 * "done" were blue, amber would be one of five competing colours instead of
 * the only saturated thing on the screen.
 *
 * Monospace is the primary face, not an accent: every column here is a txid, a
 * payment hash, a pubkey or a sat amount. System stack only — no webfont,
 * because there is no build step and an ops box should not need a CDN.
 */

:root {
  /* Cool near-black, deliberately off the framework ramps. Dark because this
     is read in dim rooms during long sessions, not for fashion. */
  --ground: #0d0f12;
  --raised: #14171c;
  --line: #232830;
  --line-strong: #333a45;

  --text: #d5d9df;
  --text-dim: #8a929e;
  --text-faint: #5b636e;

  /* The only two saturated colours in the interface. */
  --exposed: #e0a33e;
  --exposed-bg: #2a2113;
  --failed: #c05a4d;
  --failed-bg: #2a1917;

  --focus: #6d8ba6;

  --mono: ui-monospace, 'SF Mono', 'Cascadia Mono', 'Segoe UI Mono', 'Roboto Mono', Menlo, Consolas, monospace;
  --sans: ui-sans-serif, system-ui, 'Segoe UI', Roboto, sans-serif;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  background: var(--ground);
  color: var(--text);
  font: 13px/1.5 var(--mono);
  -webkit-font-smoothing: antialiased;
}

a {
  color: inherit;
}

/* ---- status bar -------------------------------------------------------- */
/* Always visible, always first. The question at 3am is "is money at risk right
   now", so the answer is pinned to the top of every view rather than living on
   a dashboard the operator has to navigate to. */

.status {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  flex-wrap: wrap;
  gap: 0 1.5rem;
  align-items: baseline;
  padding: 0.5rem 1rem;
  background: var(--raised);
  border-bottom: 1px solid var(--line);
}

.status b {
  font-weight: 600;
}

.status .sep {
  color: var(--text-faint);
}

.status .at-risk {
  color: var(--exposed);
  font-weight: 600;
}

/* ---- navigation -------------------------------------------------------- */

nav {
  display: flex;
  gap: 0;
  padding: 0 1rem;
  border-bottom: 1px solid var(--line);
  overflow-x: auto;
}

nav button {
  appearance: none;
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  color: var(--text-dim);
  font: inherit;
  padding: 0.6rem 0.9rem;
  cursor: pointer;
  white-space: nowrap;
}

nav button:hover {
  color: var(--text);
}

nav button[aria-current='true'] {
  color: var(--text);
  border-bottom-color: var(--text);
}

main {
  padding: 1rem;
  max-width: 1400px;
}

/* ---- tables ------------------------------------------------------------ */
/* Dense on purpose. An operator scanning for the one bad row wants as many
   rows on screen as will fit, not generous padding. */

table {
  width: 100%;
  border-collapse: collapse;
  font-variant-numeric: tabular-nums;
}

th {
  text-align: left;
  font-weight: 600;
  color: var(--text-dim);
  border-bottom: 1px solid var(--line-strong);
  padding: 0.35rem 0.6rem;
  white-space: nowrap;
}

td {
  border-bottom: 1px solid var(--line);
  padding: 0.35rem 0.6rem;
  white-space: nowrap;
}

tbody tr:hover {
  background: var(--raised);
}

tbody tr.clickable {
  cursor: pointer;
}

td.num {
  text-align: right;
}

/* ---- phase, the only coloured thing ------------------------------------ */

.phase {
  display: inline-block;
  padding: 0 0.4rem;
  border: 1px solid var(--line-strong);
  border-radius: 2px;
  color: var(--text-dim);
}

.phase-exposed {
  color: var(--exposed);
  border-color: var(--exposed);
  background: var(--exposed-bg);
  font-weight: 600;
}

.phase-failed {
  color: var(--failed);
  border-color: var(--failed);
  background: var(--failed-bg);
}

/* The corridor's own word, secondary to the phase beside it. */
.state {
  color: var(--text-dim);
}

/* `stuck` is spelled the same on all four corridors and always needs a human. */
.state-stuck {
  color: var(--failed);
  font-weight: 600;
}

/* ---- panels ------------------------------------------------------------ */

.panels {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 0.75rem;
}

.panel {
  border: 1px solid var(--line);
  background: var(--raised);
  padding: 0.75rem;
}

.panel h2 {
  margin: 0 0 0.5rem;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-dim);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.kv {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.15rem 0.75rem;
}

.kv dt {
  color: var(--text-dim);
}

.kv dd {
  margin: 0;
  overflow-wrap: anywhere;
}

/* ---- backend status ---------------------------------------------------- */
/* A dot, not a traffic light: only "down" is coloured, for the same reason
   only "exposed" is. */

.dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--text-faint);
  margin-right: 0.4rem;
}

.dot.down {
  background: var(--failed);
}

/* ---- forms and buttons ------------------------------------------------- */

button.act,
input,
select {
  font: inherit;
  background: var(--ground);
  color: var(--text);
  border: 1px solid var(--line-strong);
  border-radius: 2px;
  padding: 0.3rem 0.6rem;
}

button.act {
  cursor: pointer;
}

button.act:hover {
  border-color: var(--text-dim);
}

button.act.armed {
  border-color: var(--exposed);
  color: var(--exposed);
}

button.act:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 1px;
}

/* ---- dialog ------------------------------------------------------------ */

.scrim {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.65);
  display: grid;
  place-items: center;
  padding: 1rem;
  z-index: 50;
}

.dialog {
  background: var(--raised);
  border: 1px solid var(--line-strong);
  max-width: 620px;
  width: 100%;
  padding: 1rem;
}

.dialog h2 {
  margin: 0 0 0.5rem;
  font-size: 14px;
}

.dialog .warning {
  border-left: 3px solid var(--exposed);
  background: var(--exposed-bg);
  color: var(--text);
  padding: 0.6rem 0.75rem;
  margin: 0 0 0.75rem;
  font-family: var(--sans);
  line-height: 1.45;
}

.dialog .row {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  margin-top: 0.75rem;
}

.dialog input {
  flex: 1;
}

/* ---- banners ----------------------------------------------------------- */
/* Errors are shown, never swallowed into the console: an operator who cannot
   see that a request failed will assume it succeeded. */

.banner {
  border: 1px solid var(--failed);
  background: var(--failed-bg);
  color: var(--text);
  padding: 0.5rem 0.75rem;
  margin-bottom: 0.75rem;
  font-family: var(--sans);
}

.notice {
  border: 1px solid var(--line-strong);
  background: var(--raised);
  color: var(--text-dim);
  padding: 0.5rem 0.75rem;
  margin-bottom: 0.75rem;
  font-family: var(--sans);
}

.muted {
  color: var(--text-dim);
}

.faint {
  color: var(--text-faint);
}

.sans {
  font-family: var(--sans);
}

.right {
  text-align: right;
}

.bar {
  height: 6px;
  background: var(--line);
  overflow: hidden;
}

.bar > span {
  display: block;
  height: 100%;
  background: var(--text-faint);
}

.bar.at-risk > span {
  background: var(--exposed);
}

.toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: center;
  margin-bottom: 0.75rem;
}

.spacer {
  flex: 1;
}
