/* A dark room with one hot light on the ring. The prose panel stays a reading
   surface: serif, generous measure, no neon. */
:root {
  --bg: #0d0f12;
  --panel: #14171c;
  --panel-2: #1b1f26;
  --line: #272c35;
  --ink: #e8e6e1;
  --dim: #8b93a1;
  --hot: #ff6a3d;
  --good: #4ade80;
  --gold: #f5c451;
  --mono: ui-monospace, "SF Mono", Menlo, monospace;
  --serif: "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif;
  --sans: system-ui, -apple-system, "Segoe UI", sans-serif;
}

* { box-sizing: border-box; }

html, body {
  margin: 0; height: 100%;
  background: var(--bg); color: var(--ink);
  font-family: var(--sans);
  overflow: hidden;
}

/* ---------------------------------------------------------------- header */
#bar {
  display: flex; align-items: center; gap: 14px;
  padding: 0 16px; height: 52px;
  background: linear-gradient(#171a20, #101317);
  border-bottom: 1px solid var(--line);
}
#bar h1 {
  font: 600 15px/1 var(--mono);
  letter-spacing: .04em; margin: 0; color: var(--ink);
}
.spacer { flex: 1; }

.phase {
  font: 600 11px/1 var(--mono); letter-spacing: .18em; text-transform: uppercase;
  padding: 6px 12px; border-radius: 999px;
  border: 1px solid var(--line); color: var(--dim);
  transition: color .3s, border-color .3s, background .3s;
}
.phase.unlock  { color: #c4b5fd; border-color: #423a6b; background: #1a1630; }
.phase.draft   { color: #7dd3fc; border-color: #1e4d6b; background: #0d2634; }
.phase.roast   { color: var(--hot); border-color: #5c2513; background: #2a1209; }
.phase.revise  { color: var(--good); border-color: #1f5133; background: #0c2418; }
.phase.verdict { color: var(--gold); border-color: #5c4611; background: #2a2109; }
.phase.done    { color: var(--gold); border-color: #5c4611; }

.readout { display: flex; flex-direction: column; align-items: flex-end; font-family: var(--mono); }
.readout span { font-size: 13px; color: var(--gold); }
.readout small { font-size: 10px; color: var(--dim); }

.speeds {
  display: flex; align-items: center; gap: 8px;
  border: 1px solid var(--line); border-radius: 8px; padding: 5px 10px;
}
.speeds label  { font: 500 10px var(--mono); color: var(--dim); text-transform: uppercase; letter-spacing: .06em; }
/* Fixed width on the readout so the controls beside it do not shuffle
   sideways every time the number changes width while you drag. */
.speeds output { font: 500 11px var(--mono); color: var(--gold); width: 34px; text-align: right; }

.speeds input[type=range] {
  -webkit-appearance: none; appearance: none;
  width: 92px; height: 14px; background: none; cursor: pointer;
}
.speeds input[type=range]::-webkit-slider-runnable-track {
  height: 3px; border-radius: 2px; background: var(--line);
}
.speeds input[type=range]::-moz-range-track {
  height: 3px; border-radius: 2px; background: var(--line);
}
.speeds input[type=range]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 12px; height: 12px; border-radius: 50%; background: var(--hot);
  border: 0; margin-top: -4.5px;
}
.speeds input[type=range]::-moz-range-thumb {
  width: 12px; height: 12px; border-radius: 50%; background: var(--hot); border: 0;
}
.speeds input[type=range]:focus-visible { outline: 2px solid var(--hot); outline-offset: 3px; }

button.ghost, button.primary {
  font: 500 12px var(--sans); padding: 7px 14px; border-radius: 8px; cursor: pointer;
  border: 1px solid var(--line); background: var(--panel-2); color: var(--ink);
}
button.ghost:hover { border-color: #3b424e; }
button.primary { background: var(--hot); border-color: var(--hot); color: #170a04; font-weight: 700; }
button:disabled { opacity: .4; cursor: not-allowed; }

/* ----------------------------------------------------------------- layout */
main { display: flex; height: calc(100% - 52px); }
#stage { position: relative; flex: 1; min-width: 0; }
#arena { display: block; width: 100%; height: 100%; }

#ticker {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 10px 18px; font: 400 13px/1.5 var(--serif);
  color: var(--ink); background: linear-gradient(transparent, #0d0f12 55%);
  min-height: 46px; pointer-events: none;
}
#ticker b { color: var(--hot); font-family: var(--mono); font-size: 11px; letter-spacing: .08em; }

/* ------------------------------------------------------------------- side */
#side {
  width: 400px; flex: none; display: flex; flex-direction: column;
  border-left: 1px solid var(--line); background: var(--panel);
}
.tabs { display: flex; border-bottom: 1px solid var(--line); }
.tabs button {
  flex: 1; background: none; border: 0; border-bottom: 2px solid transparent;
  color: var(--dim); font: 500 11px/1 var(--mono); letter-spacing: .1em;
  text-transform: uppercase; padding: 12px 0; cursor: pointer;
}
.tabs button.on { color: var(--ink); border-bottom-color: var(--hot); }

.pane { display: none; overflow-y: auto; padding: 14px; flex: 1; }
.pane.on { display: block; }

.card {
  border: 1px solid var(--line); border-left: 3px solid var(--c, var(--dim));
  border-radius: 8px; padding: 11px 13px; margin-bottom: 10px; background: var(--panel-2);
  animation: rise .3s ease-out;
}
@keyframes rise { from { opacity: 0; transform: translateY(8px); } }
.card h4 {
  margin: 0 0 6px; font: 600 11px var(--mono); letter-spacing: .06em;
  color: var(--dim); display: flex; gap: 6px; align-items: baseline;
}
.card h4 .who { color: var(--c, var(--ink)); }
.card h4 .dmg { margin-left: auto; color: var(--hot); }
.card .md { font: 400 13.5px/1.55 var(--serif); color: #d6d3cc; }
.card .tic { margin-top: 7px; font: 400 11px var(--mono); color: var(--dim); }
.card.self { border-left-color: var(--gold); background: #1f1a10; }
.card.self h4::after { content: "self-roast"; color: var(--gold); font-size: 10px; }
.card.talk .md { font-style: italic; color: var(--gold); }
.card.sys .md { font-family: var(--mono); font-size: 11.5px; color: var(--dim); }
.card.warn { border-left-color: var(--gold); background: #1f1a10; }
.card.warn .md { color: #d8c79a; }

/* Rendered markdown. The models write it, so the feed and the drafts pane both
   parse it now, and the two share one set of rules. Headings are set in the
   mono face rather than scaled up, because a verdict that opens on "## Verdict"
   should read as a label in a side panel, not as a banner. */
.md > :first-child { margin-top: 0; }
.md > :last-child  { margin-bottom: 0; }
.md p { margin: 0 0 8px; }
.md h1, .md h2, .md h3, .md h4, .md h5, .md h6 {
  margin: 12px 0 6px; font: 600 11px var(--mono); color: var(--ink);
  text-transform: uppercase; letter-spacing: .06em;
}
.md ul, .md ol { margin: 0 0 8px; padding-left: 18px; }
.md li { margin: 3px 0; }
.md blockquote {
  margin: 0 0 8px; padding-left: 10px;
  border-left: 2px solid var(--line); color: var(--dim);
}
.md code {
  font: 400 .88em var(--mono); background: #0f1216;
  padding: 1px 4px; border-radius: 3px;
}
.md pre {
  margin: 0 0 8px; padding: 8px 10px; background: #0f1216;
  border-radius: 6px; overflow-x: auto;
}
.md pre code { background: none; padding: 0; }
.md hr { border: 0; border-top: 1px solid var(--line); margin: 12px 0; }
.md a { color: var(--gold); }
.md strong { color: var(--ink); font-weight: 600; }

table.board { width: 100%; border-collapse: collapse; font: 400 12px var(--mono); }
table.board td, table.board th { padding: 7px 6px; border-bottom: 1px solid var(--line); text-align: left; }
table.board th { color: var(--dim); font-weight: 500; font-size: 10px; letter-spacing: .1em; text-transform: uppercase; }
table.board td.n { text-align: right; }
table.board tr.win td { color: var(--gold); }

.textblock { margin-bottom: 18px; }
.textblock h3 { margin: 0 0 6px; font: 600 12px var(--mono); color: var(--c, var(--ink)); }
/* No pre-wrap any more: the markdown pass owns the block structure now, and
   leaving it on would keep every source line break as a hard one. */
.textblock .body { font: 400 14px/1.6 var(--serif); color: #cfccc5; }
.textblock .meta { font: 400 10px var(--mono); color: var(--dim); margin-bottom: 6px; }

/* ------------------------------------------------------------------ setup */
/* 62vh clipped the footer under its own default content on a 13" laptop:
 * a maximized browser there runs well under the display's own height once
 * tabs and the address bar are subtracted, and the panel's rows plus a
 * freshly-picked room's brief already run close to 80vh at that size. */
#setup {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 20;
  background: #10141a; border-top: 1px solid var(--line);
  transform: translateY(100%); transition: transform .25s ease;
  max-height: 80vh; overflow-y: auto;
  box-shadow: 0 -18px 40px rgba(0,0,0,.5);
}
#setup.open { transform: none; }
.setup-inner { padding: 16px 18px 20px; display: flex; flex-direction: column; gap: 12px; }
.row { display: flex; gap: 14px; align-items: flex-start; flex-wrap: wrap; }
.row.actions { align-items: center; }
label { font: 500 10px var(--mono); letter-spacing: .1em; text-transform: uppercase; color: var(--dim);
        display: flex; flex-direction: column; gap: 5px; }
label.grow { flex: 1; min-width: 320px; }
label.check { flex-direction: row; align-items: center; gap: 6px; text-transform: none; letter-spacing: 0; font-size: 12px; }
label.replay { flex-direction: row; align-items: center; gap: 6px; }
.hint { color: #5c6473; text-transform: none; letter-spacing: 0; font-size: 10px; }
input, select, textarea {
  background: var(--panel-2); border: 1px solid var(--line); color: var(--ink);
  border-radius: 7px; padding: 8px 10px; font: 400 13px var(--sans); min-width: 90px;
}
textarea { font: 400 13px/1.5 var(--serif); resize: vertical; width: 100%; }

/* The setup panel is pinned to the bottom of the viewport, so a taller brief
 * grows upward. A native resize corner sits at the bottom and grows downward
 * on drag, which fights that: the pointer goes one way and the box goes the
 * other. Hence a grip on the top edge instead, dragged in the direction the
 * box actually moves. */
.brief-box { display: flex; flex-direction: column; width: 100%; }
.grip {
  height: 13px; cursor: ns-resize; flex: none;
  border: 1px solid var(--line); border-bottom: 0; border-radius: 7px 7px 0 0;
  background: var(--panel-2); display: flex; align-items: center; justify-content: center;
}
.grip::before { content: ""; width: 46px; height: 2px; border-radius: 2px; background: #3b424e; }
.grip:hover::before { background: var(--hot); }
#brief { border-radius: 0 0 7px 7px; resize: none; min-height: 72px; }
input[type=checkbox] { min-width: 0; accent-color: var(--hot); }

#roster { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 6px; }
.chip {
  display: flex; align-items: center; gap: 7px; padding: 5px 8px 5px 10px;
  border-radius: 999px; font: 500 11px var(--mono);
  background: var(--panel-2); border: 1px solid var(--line); color: var(--ink);
  text-transform: none; letter-spacing: 0;
}
.chip .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--c); }
.chip button { background: none; border: 0; color: var(--dim); cursor: pointer; font-size: 14px; line-height: 1; padding: 0 2px; }
.chip button:hover { color: var(--hot); }
.adder { display: flex; gap: 6px; }
.adder input { flex: 1; font-family: var(--mono); font-size: 12px; }
#status { font: 400 11px var(--mono); color: var(--dim); }
#status.err { color: var(--hot); }

/* ----------------------------------------------------------------- drawer */
#drawer { position: fixed; inset: 0; z-index: 40; background: rgba(6,8,10,.72); backdrop-filter: blur(3px); }
.drawer-inner {
  position: absolute; top: 0; right: 0; bottom: 0; width: min(680px, 92vw);
  background: var(--panel); border-left: 1px solid var(--line);
  padding: 20px 26px; overflow-y: auto;
}
#drawer-close { position: sticky; top: 0; float: right; }

@media (max-width: 900px) {
  main { flex-direction: column; }
  #side { width: auto; height: 44%; border-left: 0; border-top: 1px solid var(--line); }
}

/* Model picker. A filtered list under the input rather than a bare datalist,
   so a row can carry the provider mark, the id and both prices at once. */
.adder { position: relative; }
/* Both comboboxes drop upward, because the setup panel is pinned to the bottom
 * of the viewport and there is nothing below it. The judge sits in a narrow
 * column at the right, so its menu is widened and right aligned rather than
 * inheriting a column width that would crush the rows. */
.picker { position: relative; }
.mmenu {
  text-transform: none; letter-spacing: 0;
  position: absolute; left: 0; right: 0; bottom: calc(100% + 6px);
  max-height: 320px; overflow-y: auto; z-index: 40;
  background: var(--panel); border: 1px solid var(--line); border-radius: 9px;
  box-shadow: 0 -10px 34px rgba(0, 0, 0, .55);
}
#judge-menu { left: auto; right: 0; width: 560px; max-width: 78vw; }
.judge-col { min-width: 230px; }
.mrow.mnoneopt .mname { color: var(--dim); white-space: normal; }
.mrow.mnoneopt .mname em { color: #5c6473; white-space: normal; }
.mrow {
  display: grid; grid-template-columns: 22px minmax(0, 1.1fr) minmax(0, 1.4fr) 74px;
  align-items: center; gap: 10px; padding: 6px 10px; cursor: pointer;
  border-bottom: 1px solid rgba(255, 255, 255, .04);
}
.mrow:last-child { border-bottom: 0; }
.mrow:hover, .mrow.on { background: var(--panel-2); }
.mrow .mk { width: 22px; height: 22px; display: block; }
.mrow .mname {
  font: 500 12px var(--sans); color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mrow .mname em { font: 400 10px var(--mono); color: var(--dim); font-style: normal; display: block; }
.mrow .mid {
  font: 400 11px var(--mono); color: #5c6473;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mrow .mpx { font: 400 10px/1.35 var(--mono); color: var(--dim); text-align: right; }
.mnone { padding: 9px 12px; font: 400 11px var(--mono); color: var(--dim); }

/* --------------------------------------------------------------- key row
   The credential input sits above everything else in setup, because with no
   server between the page and OpenRouter it is the first thing a visitor has
   to make a decision about. */
.key-row { align-items: flex-end; }
.key-row input[type=password] { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.key-note { font-size: 12px; opacity: .75; align-self: center; }
.key-note.err { color: #ff6a3d; opacity: 1; }
.replay input[type=file] { font-size: 12px; max-width: 190px; }

/* ------------------------------------------------------------ download
   Appears in the header when a run ends, beside the phase badge, because a
   run that is not downloaded is a run that is gone on reload. */
.dl { position: relative; }
.dlmenu {
  position: absolute; left: 0; top: calc(100% + 6px); z-index: 40; min-width: 260px;
  background: var(--panel); border: 1px solid var(--line); border-radius: 9px;
  box-shadow: 0 10px 34px rgba(0, 0, 0, .55); padding: 4px;
}
.dlmenu button {
  display: block; width: 100%; text-align: left; background: none; border: 0;
  color: var(--ink); font: 500 12px var(--mono); padding: 8px 10px; border-radius: 6px; cursor: pointer;
}
.dlmenu button:hover, .dlmenu button:focus-visible { background: rgba(255, 255, 255, .06); outline: none; }
.dlmenu small { display: block; color: var(--dim); font-size: 10px; margin-top: 2px; }

/* --------------------------------------------------------------- about */
#about {
  background: var(--panel); color: var(--ink); border: 1px solid var(--line);
  border-radius: 12px; padding: 0; max-width: 620px; width: calc(100vw - 40px);
  box-shadow: 0 20px 60px rgba(0, 0, 0, .6);
}
#about::backdrop { background: rgba(0, 0, 0, .6); }
.about-inner { padding: 22px 26px; font: 400 13px/1.55 var(--sans, system-ui, sans-serif); }
.about-inner h2 { margin: 0 0 12px; font: 600 15px var(--mono); letter-spacing: .04em; }
.about-inner h3 { margin: 18px 0 6px; font: 600 11px var(--mono); letter-spacing: .14em; text-transform: uppercase; color: var(--gold); }
.about-inner p { margin: 0 0 10px; }
.about-inner a { color: #7dd3fc; }
.about-inner code { font: 500 12px var(--mono); }
.about-inner form { margin-top: 18px; text-align: right; }
.fine { font: 400 10px var(--mono); color: #5c6473; margin-top: 2px; }
.fine a { color: var(--dim); }
