:root {
  --bg: #0d1013;
  --panel: #12161a;
  --line: #222a31;
  --line2: #2f3941;
  --ink: #c3cbd2;
  --ink-dim: #7d8992;
  --ink-hi: #eaf0f4;
  --good: #4a8fc7;
  --defect: #d1803b;
  --alarm: #c1493f;
  --ok: #4f9d69;
  --mark: #d8dee3;
  --mono: ui-monospace, "Cascadia Mono", Consolas, "DejaVu Sans Mono", monospace;
  --sans: "Segoe UI", Roboto, system-ui, sans-serif;
}

* { box-sizing: border-box; }

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

/* status bar */
.bar {
  position: sticky;
  top: 0;
  z-index: 5;
  display: flex;
  align-items: stretch;
  justify-content: space-between;
  gap: 16px;
  background: #0a0d10;
  border-bottom: 1px solid var(--line2);
  padding: 0 12px;
}
.bar-id { display: flex; align-items: center; gap: 12px; padding: 8px 0; }
.mark {
  font: 600 13px/1 var(--mono);
  letter-spacing: 0.22em;
  color: var(--mark);
  border: 1px solid var(--line2);
  padding: 6px 8px;
}
.sub { color: var(--ink-dim); font-size: 12px; }

.bar-stats { display: flex; flex-wrap: wrap; }
.bar-cell {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 2px;
  padding: 6px 12px;
  border-left: 1px solid var(--line);
  min-width: 78px;
}
.bar-cell b { font: 400 13px/1.2 var(--mono); color: var(--ink-hi); }
.bar-cell span { font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-dim); }

main { padding: 12px; display: flex; flex-direction: column; gap: 12px; max-width: 1400px; margin: 0 auto; }

/* plain language intro.
   Every other block on this page is an instrument and is dense on purpose. This one is read
   start to finish by someone who has not decided yet whether to care, so it gets no panel
   chrome, a bigger body size than the panels below, a measure that stops around 66
   characters, and room between the parts. */
.intro {
  padding: 34px 14px 18px;
  max-width: 74ch;
  /* the measure has to be centred. left aligned in a 1400px shell it leaves two
     thirds of the screen empty and the reader thinks the page is broken. */
  margin: 0 auto;
}
.intro h1 {
  margin: 0 0 20px;
  font: 400 30px/1.25 var(--sans);
  letter-spacing: -0.01em;
  color: var(--ink-hi);
  /* 22ch broke the headline across three lines. let it use the measure. */
  max-width: 40ch;
}
.intro h2 {
  margin: 32px 0 10px;
  font: 600 15px/1.4 var(--sans);
  color: var(--ink-hi);
}
.intro p { margin: 0 0 15px; font-size: 16px; line-height: 1.72; }
.intro .qa { border-left: 1px solid var(--line2); padding-left: 14px; margin: 0 0 18px; }
.intro .qa .q { margin-bottom: 6px; color: var(--ink-hi); }
.intro .qa .a { margin-bottom: 0; }
.intro .bits { margin: 0; padding: 0; list-style: none; }
.intro .bits li {
  position: relative;
  margin-bottom: 14px;
  padding-left: 16px;
  font-size: 16px;
  line-height: 1.72;
}
.intro .bits li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 11px;
  width: 6px;
  height: 1px;
  background: var(--ink-dim);
}
.intro .credit { margin-top: 26px; font-size: 13px; color: var(--ink-dim); }
.intro .src { margin-top: 16px; }

/* panels */
.panel {
  background: var(--panel);
  border: 1px solid var(--line);
  padding: 12px 14px 10px;
}
.panel.warn { border-color: #4a3a2c; }
.panel-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  border-bottom: 1px solid var(--line);
  padding-bottom: 6px;
  margin-bottom: 10px;
}
.panel-head h2 {
  margin: 0;
  font: 600 12px/1 var(--sans);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-hi);
}
.panel-controls { display: flex; align-items: center; gap: 12px; }
.stat { font: 12px/1 var(--mono); color: var(--ink-dim); }

h3 {
  margin: 12px 0 6px;
  font: 600 11px/1 var(--sans);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-dim);
}

.lede { margin: 0 0 10px; color: var(--ink); max-width: 78ch; }
.hint { margin: 4px 0 12px; font-size: 11px; color: var(--ink-dim); }
.note { margin: 8px 0 0; font-size: 12px; color: var(--ink-dim); max-width: 82ch; }

.callout {
  margin: 12px 0 0;
  padding: 8px 10px;
  border-left: 2px solid var(--defect);
  background: #16191d;
  color: var(--ink-hi);
  max-width: 90ch;
}
.callout.strong { border-left-color: var(--alarm); }

.src {
  margin: 10px 0 0;
  padding-top: 6px;
  border-top: 1px solid var(--line);
  font: 11px/1.5 var(--mono);
  color: var(--ink-dim);
  overflow-wrap: anywhere;
}

/* layout */
.split { display: flex; gap: 14px; flex-wrap: wrap; }
.col-main { flex: 1 1 520px; min-width: 0; }
.col-side { flex: 0 1 280px; min-width: 240px; }
.col-half { flex: 1 1 340px; min-width: 0; }

/* the live panel reuses .split, but these two columns never got rules, so they
   kept the flex default of min-width auto and would not shrink below their own
   content. on a phone the side column sat at 450px inside a 336px row. */
.live-stage { flex: 1 1 520px; min-width: 0; }
.live-side { flex: 0 1 420px; min-width: 0; }

/* explicit heights: a canvas with only a css width would scale by intrinsic ratio */
.chart { width: 100%; display: block; touch-action: none; }
#histCanvas { height: 260px; cursor: ew-resize; }
#costCanvas { height: 180px; }
#curveCanvas { height: 280px; }
#compCanvas { height: 300px; }

/* readouts */
.readouts { display: flex; flex-wrap: wrap; gap: 1px; background: var(--line); border: 1px solid var(--line); margin-bottom: 12px; }
.ro { background: var(--panel); padding: 7px 10px; flex: 1 1 120px; }
.ro b { display: block; font: 400 17px/1.25 var(--mono); color: var(--ink-hi); }
.ro span { font-size: 10px; letter-spacing: 0.07em; text-transform: uppercase; color: var(--ink-dim); }
.ro small { display: block; font: 11px/1.3 var(--mono); color: var(--ink-dim); }
.ro.alarm b { color: var(--alarm); }
.ro.hot b { color: var(--defect); }

/* controls */
.controls { display: flex; flex-direction: column; gap: 10px; }
.ctl { display: grid; grid-template-columns: 1fr auto; align-items: center; gap: 4px 8px; }
.ctl > span { font-size: 11px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-dim); }
.ctl > span em { font-style: normal; color: var(--line2); }
.ctl output { font: 13px/1 var(--mono); color: var(--ink-hi); text-align: right; }
.ctl input[type=range] { grid-column: 1 / -1; width: 100%; accent-color: var(--defect); }
.ctl input[type=number] {
  width: 80px; background: #0a0d10; color: var(--ink-hi);
  border: 1px solid var(--line2); padding: 4px 6px; font: 13px/1 var(--mono);
}
.seg { display: flex; align-items: center; gap: 6px; font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--ink-dim); }
select, button {
  background: #0a0d10; color: var(--ink); border: 1px solid var(--line2);
  padding: 4px 8px; font: 12px/1.4 var(--mono);
}
button { cursor: pointer; }
button:hover { border-color: var(--ink-dim); color: var(--ink-hi); }

/* tables */
/* the cells are nowrap, so a table narrower than its content has to scroll somewhere. it
   scrolls here rather than taking the whole page sideways with it. */
.tbl-wrap { overflow-x: auto; overflow-y: hidden; }
.tbl { width: 100%; border-collapse: collapse; font: 12px/1.4 var(--mono); }
.tbl th, .tbl td { text-align: right; padding: 4px 8px; border-bottom: 1px solid var(--line); white-space: nowrap; }
.tbl th {
  font: 600 10px/1.4 var(--sans); letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--ink-dim); border-bottom-color: var(--line2);
}
.tbl th:first-child, .tbl td:first-child { text-align: left; }
.tbl.wide { font-size: 11px; }
#panel-runs { overflow-x: auto; }
.tbl tbody tr:hover { background: #171c21; }
.tbl td.hi { color: var(--ink-hi); }
.tbl td.alarm { color: var(--alarm); }
.tbl td.warn { color: var(--defect); }

/* The switcher buttons stack their three facts. Inline they printed as one run
   of text: cablewide_resnet50_210.9 MB. */
.set-btns { display: flex; flex-wrap: wrap; gap: 6px; }
.set-btns button { display: inline-flex; flex-direction: column; align-items: flex-start; gap: 2px; line-height: 1.3; }
.set-btns button b { font-weight: 600; }
.set-btns button small { display: block; opacity: 0.62; font-size: 10px; }
/* markSet toggles this. without it nothing on screen says which one is loaded. */
.set-btns button.on { border-color: var(--ink-hi); background: #1a2027; }
.set-btns button.on b { color: var(--ink-hi); }
.set-btns button:disabled { opacity: 0.45; cursor: default; }
/* utility. without this every state of the live panel paints at once: the
   loader, the deferred strip and the loaded body are all in the markup. */
.hidden { display: none !important; }

.error {
  margin: 0;
  padding: 8px 12px;
  background: #2a1614;
  border-bottom: 1px solid var(--alarm);
  color: var(--ink-hi);
  font: 12px/1.5 var(--mono);
}

/* the live panel is the one people came for, so it gets a little more room
   than the instrument panels under it */
.panel.hero { padding-bottom: 14px; }
.hero .lede { margin-top: 0; }

.live-pick { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

/* loading */
.live-load { margin: 10px 0 4px; }
.load-row {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  font: 11px/1.4 var(--mono);
  color: var(--ink-dim);
  margin-bottom: 5px;
}
.load-track { height: 2px; background: var(--line); overflow: hidden; }
.load-track i { display: block; height: 100%; width: 0; background: var(--good); transition: width 0.15s linear; }

.live-defer { display: flex; flex-direction: column; align-items: flex-start; gap: 10px; margin: 10px 0; }

/* the picker strip. the img tags carry width=224 height=224, so with no rule
   here every thumbnail rendered at full size and the strip filled the screen. */
.live-strip {
  display: flex;
  gap: 6px;
  overflow-x: auto;
  padding-bottom: 8px;
  margin-bottom: 12px;
  scrollbar-width: thin;
}
.live-strip.busy { pointer-events: none; opacity: 0.5; }
.thumb {
  flex: 0 0 auto;
  padding: 0;
  border: 1px solid var(--line);
  background: var(--panel);
  cursor: pointer;
  line-height: 0;
}
.thumb img { display: block; width: 74px; height: 74px; object-fit: cover; }
.thumb span {
  display: block;
  max-width: 74px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  padding: 3px 4px;
  font: 9px/1.3 var(--mono);
  color: var(--ink-dim);
}
.thumb .bad { color: var(--defect); }
.thumb .ok { color: var(--ink-dim); }
.thumb.on { border-color: var(--ink-hi); }
.thumb.on span { color: var(--ink-hi); }

/* stage */
.stage-wrap { position: relative; width: 100%; max-width: 520px; background: #000; border: 1px solid var(--line); }
.stage-wrap canvas { display: block; width: 100%; height: auto; }
.stage-tag {
  position: absolute;
  left: 0;
  bottom: 0;
  padding: 3px 7px;
  background: rgba(10, 13, 16, 0.82);
  font: 10px/1.4 var(--mono);
  color: var(--ink-hi);
}
/* the scan line only says the gpu is busy. it is decoration and nothing reads it. */
.stage-scan {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 2px;
  background: var(--good);
  animation: scan 0.9s linear infinite;
}
@keyframes scan { from { top: 0; } to { top: 100%; } }

.stage-ctl { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 8px; flex-wrap: wrap; }
.seg-btns { display: flex; flex-wrap: wrap; gap: 4px; }
.seg-btns button.on { border-color: var(--ink-dim); color: var(--ink-hi); background: var(--panel); }

/* verdict pill */
.pill {
  padding: 2px 8px;
  border: 1px solid var(--line2);
  font: 10px/1.6 var(--mono);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-dim);
  white-space: nowrap;
}
.pill.off { opacity: 0.6; }
.pill.run { border-color: var(--good); color: var(--good); }
.pill.ok { border-color: var(--ok); color: var(--ok); }
.pill.bad { border-color: var(--alarm); color: var(--alarm); }

/* the offline heatmap strip. these are wide panels, so they get a grid rather
   than the flex row the picker uses. */
/* each png is three 224 panels side by side, original, overlay and truth, so a
   narrow column renders them at 70px each and nothing in them is readable. */
.strip { display: grid; grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); gap: 12px; }
.strip figure { margin: 0; }
.strip img { display: block; width: 100%; height: auto; border: 1px solid var(--line); background: #000; }
.strip figcaption { margin-top: 4px; font: 10px/1.45 var(--mono); color: var(--ink-dim); }
.strip figcaption b { color: var(--ink-hi); font-weight: 400; }

/* empty states */
.empty {
  padding: 12px;
  border: 1px dashed var(--line2);
  font: 11px/1.5 var(--mono);
  color: var(--ink-dim);
}
.empty-row td { text-align: left; color: var(--ink-dim); font-style: italic; }

.warn-note { border-left: 2px solid var(--defect); padding-left: 10px; }

.grid4 { display: grid; grid-template-columns: repeat(auto-fit, minmax(215px, 1fr)); gap: 10px; }
.card { background: var(--panel); border: 1px solid var(--line); padding: 10px 12px; }
.card h3 { margin: 0 0 6px; }
.card p { margin: 0; font-size: 13px; color: var(--ink-dim); }

.legend { display: flex; flex-wrap: wrap; gap: 6px 14px; font-size: 11px; color: var(--ink-dim); }
.legend span { display: inline-flex; align-items: center; gap: 5px; }
.legend i { width: 9px; height: 9px; display: inline-block; }

.foot {
  max-width: 74ch;
  margin: 0 auto;
  padding: 26px 14px 40px;
  border-top: 1px solid var(--line);
  font-size: 13px;
  color: var(--ink-dim);
}
.foot a { color: var(--ink); }
.foot b { color: var(--ink-hi); font-weight: 600; }
.foot p { margin: 0 0 10px; }


.about-links { display: flex; flex-wrap: wrap; gap: 8px 10px; margin: 14px 0 0; }
.about-links a {
  padding: 5px 10px;
  border: 1px solid var(--line2);
  color: var(--ink);
  text-decoration: none;
  font: 11px/1.5 var(--mono);
}
.about-links a:hover { border-color: var(--ink-dim); color: var(--ink-hi); }
