/*
  app.css — the viewer's one stylesheet.

  Dark, one accent (UR blue), two semantic colours that must never be confused with each
  other or with the accent: GREEN = measured, AMBER = assumed, RED = a cap exceeded or a
  ticket refused. If a number is amber it has not been measured. That is the whole
  legend, and it is the reason the palette is this restrained.

  Layout: a 3D stage plus a fixed-width readout rail; the rail drops under the stage
  below 1180px so a laptop keeps both without either becoming useless.
*/

:root {
  --bg: #0b0e11;
  --panel: #12171b;
  --panel-2: #171d22;
  --line: #222b32;
  --ink: #e4e9ed;
  --ink-2: #9aa7b1;
  --ink-3: #66727c;
  --accent: #7dadcc;
  --measured: #6fbf8b;
  --assumed: #d9a441;
  --alert: #e0655a;
  --radius: 10px;
  --mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, system-ui, sans-serif;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  background: var(--bg);
  color: var(--ink);
  font: 14px/1.5 var(--sans);
  -webkit-font-smoothing: antialiased;
}

code { font-family: var(--mono); font-size: 0.92em; }
h2 { font-size: 13px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; margin: 0; }

/* --- header ------------------------------------------------------------------------ */

.top {
  display: flex; align-items: center; justify-content: space-between; gap: 24px;
  flex-wrap: wrap;
  padding: 14px 20px;
  border-bottom: 1px solid var(--line);
  background: linear-gradient(180deg, #10151a, var(--bg));
}
.brand { display: flex; align-items: baseline; gap: 14px; }
.mark { font-weight: 700; letter-spacing: 0.14em; font-size: 15px; }
.mark i { color: var(--accent); font-style: normal; }
.tagline { color: var(--ink-3); font-size: 12.5px; }

.runpicker { display: flex; gap: 22px; flex-wrap: wrap; }
.run-group { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.run-head {
  font-size: 10.5px; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--ink-3); margin-right: 2px;
}
.run {
  display: flex; flex-direction: column; align-items: flex-start; gap: 1px;
  padding: 6px 10px; cursor: pointer;
  background: var(--panel); color: var(--ink-2);
  border: 1px solid var(--line); border-radius: 7px;
  font: inherit; font-size: 12px; line-height: 1.25;
  transition: border-color .12s, color .12s, background .12s;
}
.run:hover { color: var(--ink); border-color: #33404a; }
.run-seed { font-family: var(--mono); font-size: 10px; color: var(--ink-3); }
.run.on { color: var(--ink); background: #182027; border-color: var(--accent); }
.run.refusal.on { border-color: var(--alert); }
.run.on .run-seed { color: var(--ink-2); }

/* --- layout ------------------------------------------------------------------------ */

main {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 390px;
  gap: 16px;
  padding: 16px 20px;
  align-items: start;
}
@media (max-width: 1180px) { main { grid-template-columns: minmax(0, 1fr); } }

.stage { display: flex; flex-direction: column; gap: 12px; min-width: 0; }

.canvas-wrap {
  position: relative;
  aspect-ratio: 16 / 10;
  min-height: 380px;
  border: 1px solid var(--line); border-radius: var(--radius);
  overflow: hidden; background: #0e1215;
}
@media (max-width: 720px) { .canvas-wrap { aspect-ratio: 4 / 3; min-height: 300px; } }
#view { display: block; width: 100%; height: 100%; }

.stamp, .meshnote {
  position: absolute; left: 12px; max-width: 380px;
  padding: 7px 10px; border-radius: 7px;
  background: rgba(10, 14, 17, 0.78); border: 1px solid var(--line);
  color: var(--ink-3); font-size: 11px; line-height: 1.45;
  backdrop-filter: blur(6px);
}
.stamp { top: 12px; }
.stamp b { color: var(--ink-2); }
.meshnote { bottom: 12px; }
.meshnote b { color: var(--ink-2); }

.views { position: absolute; top: 12px; right: 12px; display: flex; gap: 4px; }
.views button {
  padding: 5px 11px; cursor: pointer; font: inherit; font-size: 11.5px;
  color: var(--ink-2); background: rgba(10, 14, 17, 0.78);
  border: 1px solid var(--line); border-radius: 6px;
}
.views button.on { color: var(--ink); border-color: var(--accent); }

/* the refusal overlay — the safety demo's loudest signal */
.overlay { position: absolute; inset: 0; display: grid; place-items: center; pointer-events: none; }
.ov-card {
  display: none; flex-direction: column; align-items: center; gap: 6px; text-align: center;
  padding: 20px 30px; border-radius: 12px;
  background: rgba(24, 10, 10, 0.86); border: 1px solid var(--alert);
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(3px);
  max-width: 82%;
}
.is-refused .ov-card { display: flex; }
.is-refused .canvas-wrap { box-shadow: inset 0 0 0 2px rgba(224, 101, 90, 0.5); }
.ov-kind { font-size: 11px; letter-spacing: 0.2em; color: var(--alert); }
.ov-reason { font-size: 30px; font-weight: 650; letter-spacing: -0.01em; }
.ov-dq { font-family: var(--mono); font-size: 13px; color: var(--ink-2); }
.ov-note { font-size: 12px; color: var(--ink-3); max-width: 42ch; line-height: 1.5; }

/* --- station strip ----------------------------------------------------------------- */

.strip {
  position: relative;
  display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 8px;
}
@media (max-width: 720px) { .strip { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.st {
  padding: 9px 10px; border-radius: 8px;
  background: var(--panel); border: 1px solid var(--line);
  transition: border-color .15s, background .15s;
}
.st.working { border-color: var(--accent); background: #141c22; }
.st-top { display: flex; justify-content: space-between; align-items: baseline; gap: 6px; }
.st-name { font-size: 12px; font-weight: 600; }
.st-mode { font-size: 10px; color: var(--ink-3); text-transform: uppercase; letter-spacing: 0.06em; }
.st.working .st-mode { color: var(--accent); }
.st-ing {
  font-size: 11px; color: var(--ink-2); margin: 3px 0 6px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-height: 16px;
}
.st-bar { height: 3px; border-radius: 2px; background: #1e262c; overflow: hidden; }
.st-bar i { display: block; height: 100%; background: var(--accent); transition: width .1s linear; }
.st-util {
  display: flex; justify-content: space-between; margin-top: 6px;
  font-size: 10px; color: var(--ink-3); font-family: var(--mono);
}
.st-rail { grid-column: 1 / -1; position: relative; height: 20px; }
.st-tray {
  position: absolute; top: 2px; width: 52px; text-align: center;
  font-size: 10px; font-family: var(--mono); color: var(--bg);
  background: var(--accent); border-radius: 4px; padding: 2px 0;
  transition: left .35s cubic-bezier(.4, 0, .2, 1), opacity .3s;
}

/* --- transport ---------------------------------------------------------------------- */

.transport {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 10px 12px; border-radius: var(--radius);
  background: var(--panel); border: 1px solid var(--line);
}
.play, .speed {
  padding: 7px 16px; cursor: pointer; font: inherit; font-size: 12.5px;
  color: var(--ink); background: var(--panel-2);
  border: 1px solid var(--line); border-radius: 7px;
}
.play { min-width: 76px; font-weight: 600; }
.play.on { border-color: var(--accent); color: var(--accent); }
.speed { min-width: 52px; font-family: var(--mono); }
.clock { font-family: var(--mono); font-size: 12.5px; color: var(--ink-3); min-width: 96px; }
.clock b { color: var(--ink); }
.scrub { flex: 1 1 220px; min-width: 160px; accent-color: var(--accent); }
.now {
  flex: 1 1 100%; font-size: 11px; color: var(--ink-3); font-family: var(--mono);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* --- cards -------------------------------------------------------------------------- */

.rail { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.card {
  padding: 14px; border-radius: var(--radius);
  background: var(--panel); border: 1px solid var(--line);
}
.card-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  padding-bottom: 10px; margin-bottom: 11px; border-bottom: 1px solid var(--line);
}
.card-head .sub, .card-head .verdict { font-size: 11px; color: var(--ink-3); }
.fine { font-size: 11px; line-height: 1.55; color: var(--ink-3); margin: 10px 0 0; }
.fine b { color: var(--ink-2); font-weight: 600; }
.empty { font-size: 12px; color: var(--ink-3); margin: 0; }
.warn {
  font-size: 11px; line-height: 1.55; color: var(--assumed);
  margin: 10px 0 0; padding: 8px 10px;
  border-left: 2px solid var(--assumed); background: rgba(217, 164, 65, 0.06);
}

.tag {
  display: inline-block; padding: 1px 6px; border-radius: 4px;
  font-size: 10px; letter-spacing: 0.04em; text-transform: uppercase; font-weight: 600;
}
.tag-measured { color: var(--measured); background: rgba(111, 191, 139, 0.12); }
.tag-assumed { color: var(--assumed); background: rgba(217, 164, 65, 0.12); }
.tag-over { color: var(--alert); background: rgba(224, 101, 90, 0.14); }

/* --- safety card -------------------------------------------------------------------- */

.safety.admitted { border-color: #2b4a3a; }
.safety.refused { border-color: var(--alert); background: #17100f; }
.safety .verdict {
  font-size: 11px; font-weight: 700; letter-spacing: 0.14em;
  padding: 2px 8px; border-radius: 4px;
}
.safety.admitted .verdict { color: var(--measured); background: rgba(111, 191, 139, 0.12); }
.safety.refused .verdict { color: var(--alert); background: rgba(224, 101, 90, 0.16); }
.safety .reason { margin: 0; font-size: 12.5px; color: var(--ink-2); line-height: 1.5; }
.safety .reason code { color: var(--alert); }
.numbers { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 12px; }
.num {
  padding: 10px 12px; border-radius: 8px;
  background: var(--panel-2); border: 1px solid var(--line);
}
.num .n { font-size: 26px; font-weight: 650; font-family: var(--mono); letter-spacing: -0.02em; }
.num .u { font-size: 12px; color: var(--ink-3); margin-left: 4px; }
.num .k { display: block; font-size: 10.5px; color: var(--ink-3); margin-top: 3px; line-height: 1.35; }
.num.zero .n { color: var(--measured); }

/* --- force panel -------------------------------------------------------------------- */

.force { padding: 10px 0; border-bottom: 1px solid var(--line); }
.force:last-of-type { border-bottom: 0; }
.f-top { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.f-name { font-size: 12.5px; font-weight: 600; }
.f-val { font-family: var(--mono); font-size: 12.5px; }
.f-val em { color: var(--ink-3); font-style: normal; font-size: 11px; }
.force.over .f-val { color: var(--alert); }
.f-bar {
  position: relative; height: 6px; margin: 7px 0 6px;
  border-radius: 3px; background: #1e262c; overflow: hidden;
}
.f-bar i { display: block; height: 100%; background: var(--measured); }
.force.over .f-bar i { background: var(--alert); }
.f-bar u {
  position: absolute; top: -2px; bottom: -2px; width: 2px;
  background: var(--ink); opacity: 0.85;
}
.f-meta {
  display: flex; flex-wrap: wrap; gap: 6px 10px; align-items: center;
  font-size: 10.5px; color: var(--ink-3);
}
.f-meta .method { border-bottom: 1px dotted var(--ink-3); cursor: help; }
.skipped { margin-top: 12px; }
.skipped summary { cursor: pointer; font-size: 11.5px; color: var(--ink-2); }
.skipped ul { margin: 8px 0 0; padding-left: 16px; }
.skipped li { font-size: 11px; color: var(--ink-3); margin-bottom: 7px; line-height: 1.5; }
.skipped li b { color: var(--ink-2); display: block; }

/* --- provenance --------------------------------------------------------------------- */

.prov { width: 100%; border-collapse: collapse; font-size: 11.5px; }
.prov th {
  text-align: left; font-weight: 600; font-size: 10px; text-transform: uppercase;
  letter-spacing: 0.05em; color: var(--ink-3); padding: 0 6px 6px 0;
}
.prov td { padding: 5px 6px 5px 0; border-top: 1px solid var(--line); }
.prov .num-cell { font-family: var(--mono); }
.prov .num-cell em { color: var(--ink-3); font-style: normal; font-size: 10px; }
.prov tr.assumed td { color: var(--ink-2); }
.prov tr.assumed .num-cell:first-of-type { border-bottom: 1px dashed rgba(217, 164, 65, 0.5); }
.prov .nil { color: var(--ink-3); }

.tact { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line); }
.tact-head {
  display: flex; justify-content: space-between; align-items: center; gap: 8px;
  font-size: 11.5px; color: var(--ink-2); margin-bottom: 8px;
}
.tact-bar {
  position: relative; height: 8px; border-radius: 4px;
  background: #1e262c; overflow: visible; margin-bottom: 8px;
}
.tact-bar i { display: block; height: 100%; border-radius: 4px; background: var(--accent); }
.tact-bar u { position: absolute; top: -3px; bottom: -3px; width: 2px; background: var(--ink); }
.tact-nums { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.tact-nums b { font-family: var(--mono); font-size: 17px; }
.tact-nums span { font-size: 11px; color: var(--ink-3); }

/* --- divergence + log --------------------------------------------------------------- */

.dv-kinds { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 10px; }
.dv { list-style: none; margin: 0; padding: 0; max-height: 220px; overflow-y: auto; }
.dv li { padding: 7px 0; border-top: 1px solid var(--line); font-size: 11.5px; }
.dv li:first-child { border-top: 0; }
.dv b { font-weight: 600; }
.dv-line { display: block; color: var(--ink-3); font-size: 11px; margin-top: 2px; line-height: 1.5; }
.dv code { color: var(--ink-2); }

.logl { list-style: none; margin: 0; padding: 0; max-height: 200px; overflow-y: auto; }
.logl li {
  font-size: 11px; font-family: var(--mono); color: var(--ink-3);
  padding: 3px 0; opacity: 0.45; transition: opacity .2s;
}
.logl li.past { opacity: 1; color: var(--ink-2); }
.logl .t { display: inline-block; width: 52px; color: var(--ink-3); }

/* --- footer + boot ------------------------------------------------------------------ */

.foot { padding: 18px 20px 32px; border-top: 1px solid var(--line); }
.disclaimer {
  margin: 0 0 8px; font-size: 12px; color: var(--ink-2); max-width: 80ch; line-height: 1.6;
}
.credits { margin: 0; font-size: 11px; color: var(--ink-3); max-width: 90ch; line-height: 1.6; }

.boot {
  position: fixed; inset: 0; display: grid; place-items: center;
  background: var(--bg); color: var(--ink-3); font-size: 13px; z-index: 10;
}
.boot-fail { color: var(--alert); text-align: center; line-height: 1.7; }

/* --- mode switch and LIVE mode ------------------------------------------------------
   The page has two modes and they must never be mistaken for each other, so the switch
   is a full-width pair of cards with their own claim spelled out, and each mode hides
   everything belonging to the other. Live mode is tinted with the accent; playback is
   neutral. Nothing is shown in both unless it is true in both (the station strip is, and
   the 3D stage is, because in live mode it is parked and stamped as parked). */

.modes {
  display: grid; grid-template-columns: 1fr 1fr; gap: 10px;
  padding: 12px 20px 0;
}
.modes button {
  display: flex; flex-direction: column; gap: 4px; text-align: left;
  padding: 10px 14px; cursor: pointer;
  background: var(--panel); color: var(--ink-3);
  border: 1px solid var(--line); border-radius: var(--radius);
  font: inherit;
}
.modes button:hover { border-color: #33404a; color: var(--ink-2); }
.modes button b { font-size: 13px; letter-spacing: 0.04em; text-transform: uppercase; }
.modes button span { font-size: 12px; line-height: 1.45; }
.modes button i { font-style: italic; color: var(--ink-2); }
.modes button.on { color: var(--ink); background: #182027; border-color: var(--accent); }
.modes button.on b { color: var(--accent); }
@media (max-width: 720px) { .modes { grid-template-columns: 1fr; } }

.stamp.live { border-color: var(--accent); color: var(--ink-2); }
.stamp.live b { color: var(--accent); }

/* Mode visibility. One rule each way, so adding a panel means picking a side. */
#stamp-live, #console, #live-gate, #live-log { display: none; }
body.is-live #stamp-playback,
body.is-live #transport,
body.is-live .runpicker,
body.is-live #safety,
body.is-live #forces,
body.is-live #provenance,
body.is-live #divergence,
body.is-live #log { display: none; }
body.is-live #stamp-live,
body.is-live #console { display: block; }
body.is-live #live-gate,
body.is-live #live-log { display: block; }

/* --- the live console --------------------------------------------------------------- */

.console {
  display: flex; flex-direction: column; gap: 12px;
  padding: 12px 14px;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
}
.lv-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.lv-head {
  font-size: 11px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-3);
  min-width: 210px;
}
.lv-btns { display: flex; gap: 6px; flex-wrap: wrap; }
.lv-ticket, .lv-fault {
  padding: 6px 11px; cursor: pointer; font: inherit; font-size: 12px;
  background: var(--panel-2); color: var(--ink-2);
  border: 1px solid var(--line); border-radius: 7px;
}
.lv-ticket:hover, .lv-fault:hover { color: var(--ink); border-color: #33404a; }
.lv-ticket.ok { border-color: #2c4a38; color: var(--measured); }
/* A ticket that SHOULD be refused is red before it is clicked, because the point of the
   button is the refusal — not because the page knows the answer. The kernel does. */
.lv-ticket.bad { border-color: #4a2c2a; color: var(--alert); }
.lv-fine { margin: 0; font-size: 11.5px; line-height: 1.5; color: var(--ink-3); }
.console .clock { font-family: var(--mono); font-size: 12px; color: var(--ink-3); }
.console .clock b { color: var(--ink); }
#live-log .logl { max-height: 240px; }
#live-log .logl li { font-family: var(--mono); font-size: 11.5px; }
