/* Prompt Flow, on the Aguken UI kit (`dashboard/ui_kit/`).

   kit.css is linked first and owns the tokens: greys on a near-black page, one
   blue accent, hairline borders, no gradients or shadows. This file is only the
   dashboard's own shapes — the two-stage split, the config editor, the run
   panel, the diff — written against those tokens so there is one palette and
   not two.

   Two deliberate departures from `ui_kit/README.md`, both about this page's job:

   - The page is 1360px, not 960px. The two stages are a pair of forms that are
     filled side by side, and at 960px they stack, which puts "Evaluate" below
     the fold on a laptop.
   - Status keeps a word as well as a dot. A run's state is the one thing an
     operator reads from across the room, and `running` / `waiting for human` /
     `failed` are not distinguishable as three coloured dots. The colour still
     appears only on the dot; the word beside it is plain text. */

/* The kit draws the primary button in `--k-text` (white on dark). That is the
   right weight for a form with one action. These two forms each have three. */
:root { --radius-box: var(--k-radius); --radius-field: 8px; --radius-btn: 7px; }

html { -webkit-text-size-adjust: 100%; }
body { min-height: 100vh; }

code, pre, textarea, .mono { font-family: var(--k-mono); }
code {
  background: var(--k-surface);
  border: 1px solid var(--k-line);
  padding: 1px 5px;
  border-radius: 5px;
  font-size: .875em;
  color: var(--k-text);
}

/* ── bar ──────────────────────────────────────────────────────────────────── */

.bar {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 16px;
  height: 56px;
  padding: 0 24px;
  background: var(--k-bg);
  border-bottom: 1px solid var(--k-line);
}

.brand { display: flex; align-items: center; gap: 10px; min-width: 0; }

/* A hairline square, not a gradient tile: the kit has no gradients, and the
   mark is an identifier rather than the brightest thing on the page. */
.logo {
  flex: none;
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border: 1px solid var(--k-line);
  border-radius: 7px;
  color: var(--k-muted);
}
.logo svg { width: 15px; height: 15px; }

.brand-text { display: flex; flex-direction: column; min-width: 0; }
.mark { font-size: 15px; font-weight: 600; letter-spacing: -.01em; line-height: 1.2; }

.bar-end { margin-left: auto; display: flex; align-items: center; gap: 8px; }
.push-end { margin-left: auto; }

@media (max-width: 900px) { .bar { padding: 0 16px; } }

/* ── shell ────────────────────────────────────────────────────────────────── */

main { max-width: 1360px; margin: 0 auto; padding: 32px 24px 96px; }

@media (max-width: 700px) { main { padding: 24px 16px 64px; } }

/* ── layout ───────────────────────────────────────────────────────────────── */

.split { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; }
.steps { display: contents; }

/* Both stages end on the same line: the shorter form takes up the slack above
   its action, so the two primary buttons land on the same row. */
.steps > .card { display: flex; flex-direction: column; }
.steps > .card > .cfg-host { flex: 1 1 auto; }
.eval-section { margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--k-line); }
.eval-section h3 { margin: 0 0 12px; color: var(--k-muted); }
.runbar, .panel { grid-column: 1 / -1; }

@media (max-width: 1040px) { .split { grid-template-columns: 1fr; } }

.card {
  padding: 20px 22px 22px;
  border: 1px solid var(--k-line);
  border-radius: var(--radius-box);
  background: none;
}

.runbar {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 14px 18px;
}
.runbar label { margin: 0; white-space: nowrap; }
.runbar input { max-width: 340px; }
.runbar .hint { margin: 0; flex: 1; min-width: 0; }

@media (max-width: 760px) {
  .runbar { display: block; }
  .runbar input { max-width: none; margin: 8px 0; }
}

.card-head { display: flex; gap: 12px; margin-bottom: 20px; }
.card-head h2 { margin: 0; font-size: 15px; font-weight: 600; letter-spacing: -.01em; }
.card-head .lede { margin: 4px 0 0; color: var(--k-muted); font-size: 13px; line-height: 1.5; }

.step {
  flex: none;
  display: grid;
  place-items: center;
  width: 22px; height: 22px;
  border: 1px solid var(--k-line);
  border-radius: 6px;
  color: var(--k-faint);
  font: 12px var(--k-mono);
  font-variant-numeric: tabular-nums;
}

/* ── fields ───────────────────────────────────────────────────────────────── */

.field { margin-bottom: 16px; min-width: 0; }
.field:last-child { margin-bottom: 0; }
.pair { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.stack { display: flex; flex-direction: column; gap: 8px; }

@media (max-width: 560px) { .pair { grid-template-columns: 1fr; } }

label { display: block; font-size: 13px; font-weight: 500; color: var(--k-text); margin-bottom: 6px; }

.hint { margin: 6px 0 0; color: var(--k-muted); font-size: 12.5px; line-height: 1.45; }

/* The browser's blue is the one colour on the page the kit does not own, and it
   is close enough to the accent to read as "this is running". Links are text. */
a:not(.ghost) { color: var(--k-text); text-decoration-color: var(--k-faint); text-underline-offset: 2px; }
a:not(.ghost):hover { text-decoration-color: currentColor; }

input, select, textarea, button { font: inherit; color: inherit; }

input[type="text"], input[type="number"], input[type="email"],
input[type="password"], input:not([type]), select, textarea {
  width: 100%;
  padding: 9px 12px;
  border: 1px solid var(--k-line);
  border-radius: var(--radius-field);
  background: none;
  font-variant-numeric: tabular-nums;
  transition: border-color .15s;
}

select {
  appearance: none;
  padding-right: 30px;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 15px) 47%, calc(100% - 10px) 47%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  cursor: pointer;
}

textarea { resize: vertical; line-height: 1.55; font-size: 12.5px; }
input::placeholder, textarea::placeholder { color: var(--k-faint); }
input:hover, select:hover, textarea:hover { border-color: var(--k-muted); }

/* The accent marks what is live or focused, and nothing else. */
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--k-accent);
}

.sr-only {
  position: absolute; width: 1px; height: 1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
}

/* file input: the real control keeps click and keyboard, the label carries the
   look. Dashed while empty and solid once a file is in it, like `.k-drop`. */
.file {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 12px 6px 6px;
  border: 1px dashed var(--k-line);
  border-radius: var(--radius-field);
  cursor: pointer;
  min-height: 40px;
  transition: border-color .15s, background .15s;
}
.file:hover { border-color: var(--k-muted); }
.file:focus-within { border-color: var(--k-accent); }
.file:has(.file-name.set) { border-style: solid; }

.file-btn {
  flex: none;
  padding: 5px 11px;
  border: 1px solid var(--k-line);
  border-radius: var(--radius-btn);
  font-size: 12.5px;
  font-weight: 500;
}
.file-name {
  color: var(--k-faint);
  font-size: 13px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.file-name.set { color: var(--k-text); font-family: var(--k-mono); font-size: 12px; }
.file .agent {
  flex: none;
  min-width: 64px;
  font-family: var(--k-mono);
  font-size: 11.5px;
  color: var(--k-faint);
}

.choice { display: flex; gap: 8px; flex-wrap: wrap; }

.pick {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  padding: 7px 12px;
  border: 1px solid var(--k-line);
  border-radius: var(--radius-field);
  color: var(--k-muted);
  font-size: 13px;
  cursor: pointer;
  transition: border-color .15s, color .15s;
}
.pick input { width: auto; margin: 0; accent-color: var(--k-accent); }
.pick:has(input:checked) { border-color: var(--k-muted); color: var(--k-text); }
.pick:has(input:disabled) { opacity: .35; cursor: not-allowed; }

.check { display: flex; align-items: center; gap: 8px; margin: 12px 0 0; color: var(--k-muted); }
.check input { width: auto; margin: 0; accent-color: var(--k-accent); }
.check:has(input:checked) { color: var(--k-text); }

/* ── folds ────────────────────────────────────────────────────────────────── */

.fold { margin-top: 16px; border-top: 1px solid var(--k-line); }
.fold > summary {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 0 4px;
  font-size: 13px;
  font-weight: 500;
  color: var(--k-muted);
  cursor: pointer;
  list-style: none;
}
.fold > summary::-webkit-details-marker { display: none; }
.fold > summary::before {
  content: "";
  width: 5px; height: 5px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(-45deg);
  transition: transform .15s;
}
.fold[open] > summary::before { transform: rotate(45deg); }
.fold > summary:hover { color: var(--k-text); }
.fold-body { padding: 12px 0 8px; }

/* ── buttons ──────────────────────────────────────────────────────────────── */

/* `.run` is the kit's `.is-primary`: the text colour as a fill, so the one
   action that costs money is the one solid thing in the form. */
.run {
  width: 100%;
  margin-top: 20px;
  min-height: 40px;
  padding: 9px 16px;
  border: 1px solid var(--k-text);
  border-radius: var(--radius-btn);
  background: var(--k-text);
  color: var(--k-bg);
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: opacity .15s;
}
.run:hover { opacity: .85; }
.run:focus-visible { outline: 2px solid var(--k-accent); outline-offset: 2px; }
.run[disabled] { opacity: .35; cursor: not-allowed; }

/* One row, three buttons, one height. The primary takes the room that is left;
   Pause and Stop are the same width as each other so the row does not shift
   when a label grows (Pause -> Resume, Stop -> Stopping...). `min-width: 0`
   matters: flex items default to min-width:auto, so "Stopping…" would push Stop
   wider than Pause and the row would be uneven. */
.submit-row { display: flex; align-items: stretch; gap: 8px; margin-top: 20px; }
.submit-row .run { flex: 1 1 auto; width: auto; margin-top: 0; }
.submit-row .side-stop {
  flex: 0 0 100px;
  min-width: 0;
  padding: 0 8px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 40px;
  border-radius: var(--radius-btn);
  font-size: 13px;
  overflow: hidden;
}

@media (max-width: 560px) {
  /* Narrow: the primary takes its own line and the two controls share the next,
     rather than three buttons squeezing under 40px each. */
  .submit-row { flex-wrap: wrap; }
  .submit-row .run { flex: 1 0 100%; }
  .submit-row .side-stop { flex: 1 1 0; }
}

.ghost {
  padding: 6px 12px;
  border: 1px solid var(--k-line);
  border-radius: var(--radius-btn);
  background: none;
  color: var(--k-muted);
  font-size: 12.5px;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  transition: background .15s, color .15s, border-color .15s;
}
.ghost:hover { background: var(--k-hover); color: var(--k-text); }
.ghost[disabled] { opacity: .35; cursor: not-allowed; }

/* Pause and Stop are filled, against the kit's "colour on a dot, not a fill"
   rule, because they are the two controls reached for in a hurry and a word on
   a hairline is not. Both carry white text in either colour scheme, so the
   fills are fixed rather than taken from the light/dark tokens:

     Stop  #c81e1e  white text 5.74:1, block 3.45:1 on the dark page, 5.74:1 on the light one
     Pause #63636d  white text 5.94:1, block 3.33:1 on the dark page, 5.94:1 on the light one

   Both clear 4.5:1 for the label and 3:1 for the control's own edge. */
.side-stop { background: #63636d; border-color: #63636d; color: #fff; }
.side-stop:hover:not([disabled]) { background: #71717a; border-color: #71717a; color: #fff; }
.side-stop.danger, .side-stop.danger:hover { color: #fff; }
.side-stop.danger { background: #c81e1e; border-color: #c81e1e; }
.side-stop.danger:hover:not([disabled]) { background: #dc2626; border-color: #dc2626; }
/* Disabled is most of their life, and .35 put the label under 3:1. */
.side-stop[disabled] { opacity: .55; }

#runs { width: auto; max-width: 300px; padding: 6px 28px 6px 12px; font-size: 12.5px; border-radius: var(--radius-btn); }

/* ── configuration editor ─────────────────────────────────────────────────── */

.req { margin-left: 8px; color: var(--k-faint); font-size: 10.5px; text-transform: uppercase; letter-spacing: .06em; }

.cfg-group {
  margin: 12px 0;
  /* The legend sits on the border, so without top padding the first label
     collides with it. */
  padding: 8px 12px 12px;
  border: 1px solid var(--k-line);
  border-radius: var(--radius-field);
}
.cfg-group > legend {
  padding: 0 4px;
  color: var(--k-faint);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.cfg .field { margin-bottom: 12px; }
.cfg textarea { min-height: 88px; }
.cfg > .fold:first-child { margin-top: 0; border-top: 0; }

/* ── the run panel ────────────────────────────────────────────────────────── */

.panel { padding: 20px 22px 22px; }

.placeholder { padding: 48px 16px; text-align: center; }
.placeholder-title { margin: 0 0 6px; color: var(--k-text); font-size: 14px; font-weight: 500; }
.placeholder .hint { max-width: 42ch; margin: 0 auto; }

.row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.row b { font-size: 13.5px; font-weight: 500; }

/* The kit's row dot, with the state spelled out beside it. */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 0;
  background: none;
  color: var(--k-muted);
  font-size: 12px;
  letter-spacing: .02em;
}
.badge::before {
  content: "";
  flex: none;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--k-faint);
}
.badge.running::before, .badge.queued::before { background: var(--k-accent); }
.badge.running::before { animation: k-pulse 1.6s infinite; }
.badge.waiting_for_human::before, .badge.paused::before, .badge.stopping::before { background: var(--k-warn); }
.badge.complete::before { background: var(--k-ok); }
.badge.failed::before, .badge.stopped::before { background: var(--k-bad); }
.badge.running, .badge.queued { color: var(--k-text); }

/* ── numbers ──────────────────────────────────────────────────────────────── */

.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(148px, 1fr));
  margin: 20px 0 0;
  border: 1px solid var(--k-line);
  border-radius: var(--radius-box);
  overflow: hidden;
}
.stat {
  display: flex;
  flex-direction: column-reverse;
  gap: 6px;
  padding: 14px 16px;
  min-width: 0;
  border-left: 1px solid var(--k-line);
}
/* No left rule on a column that starts a row, whatever auto-fit decided. */
.stat:first-child { border-left: 0; }
.stat b {
  font-size: 22px;
  font-weight: 500;
  line-height: 1.1;
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
  overflow: hidden;
  text-overflow: ellipsis;
}
.stat span {
  color: var(--k-faint);
  font-size: 11px;
  letter-spacing: .08em;
  text-transform: uppercase;
}

/* ── notices ──────────────────────────────────────────────────────────────── */

.warn, .err {
  margin: 12px 0;
  padding: 10px 14px;
  border: 1px solid var(--k-line);
  border-left: 2px solid currentColor;
  border-radius: var(--radius-field);
  font-size: 13px;
  line-height: 1.5;
}
.warn { color: var(--k-warn); }
.err { color: var(--k-bad); }
.warn, .err { background: none; }
#warnings:not(:empty) { margin-bottom: 24px; }

pre.log, pre.preview {
  margin: 20px 0 0;
  padding: 12px 14px;
  max-height: 380px;
  overflow: auto;
  border: 1px solid var(--k-line);
  border-radius: var(--radius-field);
  background: var(--k-surface);
  color: var(--k-muted);
  font-size: 12px;
  line-height: 1.6;
  white-space: pre-wrap;
  word-break: break-word;
  scrollbar-width: thin;
}
pre.preview { max-height: 460px; color: var(--k-text); }

/* ── the prompt before and after ──────────────────────────────────────────── */

.diff-scroll {
  margin-top: 12px;
  max-height: 460px;
  overflow: auto;
  border: 1px solid var(--k-line);
  border-radius: var(--radius-field);
  background: var(--k-surface);
  scrollbar-width: thin;
}

table.diff {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--k-mono);
  font-size: 12px;
  line-height: 1.55;
}
table.diff th {
  position: sticky;
  top: 0;
  z-index: 1;
  padding: 7px 12px;
  background: var(--k-surface);
  color: var(--k-muted);
  font-size: 11px;
  font-weight: 500;
  text-align: left;
  box-shadow: inset 0 -1px 0 var(--k-line);
}
/* The two halves read as two documents, not one table. */
table.diff th:nth-child(2), table.diff td:nth-child(2) { border-right: 1px solid var(--k-line); }

td.diff-no {
  width: 1%;
  padding: 0 8px;
  color: var(--k-faint);
  text-align: right;
  /* The +/-/~ mark is appended to this cell, and at width:1% it wrapped onto a
     second line and pushed the row to double height. */
  white-space: nowrap;
  user-select: none;         /* copying a side should give the text, not the gutter */
}
td.diff-line {
  padding: 0 12px 0 8px;
  color: var(--k-text);
  white-space: pre-wrap;
  word-break: break-word;
  vertical-align: top;
}

/* A wash, not a fill: the line stays readable, and the gutter mark says which
   kind it is, because colour alone is not a signal everyone receives. */
td.diff-line.change { background: color-mix(in srgb, var(--k-warn) 12%, transparent); }
td.diff-line.add    { background: color-mix(in srgb, var(--k-ok) 12%, transparent); }
td.diff-line.remove { background: color-mix(in srgb, var(--k-bad) 12%, transparent); }
td.diff-line.empty  { background: var(--k-surface); }

tr.diff-add    td.diff-no::after { content: " +"; color: var(--k-ok); }
tr.diff-remove td.diff-no::after { content: " −"; color: var(--k-bad); }
tr.diff-change td.diff-no::after { content: " ~"; color: var(--k-warn); }

@media (max-width: 700px) {
  table.diff { font-size: 11px; }
  td.diff-line { padding: 0 8px; }
}

/* ── tables ───────────────────────────────────────────────────────────────── */

h3 {
  margin: 28px 0 12px;
  color: var(--k-faint);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .08em;
  text-transform: uppercase;
}

table { width: 100%; border-collapse: collapse; font-size: 12.5px; font-variant-numeric: tabular-nums; }
th, td { text-align: left; padding: 7px 12px; border-bottom: 1px solid var(--k-line); }
th { color: var(--k-muted); font-size: 11px; font-weight: 500; letter-spacing: .06em; text-transform: uppercase; }
tbody tr { transition: background .15s; }
tbody tr:hover { background: var(--k-hover); }
tr:last-child td { border-bottom: 0; }
td:first-child { color: var(--k-text); }
td.right { text-align: right; white-space: nowrap; }
td.right .ghost { margin-left: 4px; padding: 4px 10px; }
td code { background: none; border: 0; padding: 0; color: var(--k-text); font-size: 12px; }

/* delta: direction is colour + sign, never colour alone */
td.delta { font-family: var(--k-mono); font-size: 12px; }
td.delta.up { color: var(--k-ok); }
td.delta.down { color: var(--k-bad); }
td.delta.flat { color: var(--k-muted); }

/* ── human review ─────────────────────────────────────────────────────────── */

/* The run is stopped and waiting on a person, so this box is the one thing on
   the page with a coloured edge. */
.review {
  margin: 20px 0 0;
  padding: 18px 20px;
  border: 1px solid var(--k-line);
  border-left: 2px solid var(--k-warn);
  border-radius: var(--radius-box);
}
.review h3 { margin-top: 0; color: var(--k-warn); }
.review .question {
  margin: 0 0 16px;
  color: var(--k-text);
  font-size: 15px;
  font-weight: 500;
  line-height: 1.45;
}
.review .issue {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--k-line);
  font-size: 13px;
}
.review .issue b { font-family: var(--k-mono); font-size: 11.5px; color: var(--k-muted); }
.review .issue p { margin: 4px 0; color: var(--k-muted); }
.review pre {
  margin: 8px 0 0;
  padding: 10px 12px;
  max-height: 150px;
  overflow: auto;
  border: 1px solid var(--k-line);
  border-radius: 6px;
  background: var(--k-surface);
  color: var(--k-muted);
  font-size: 11.5px;
}
.review label { margin-top: 16px; }
.review .run { width: auto; padding: 9px 20px; }

/* ── live feedback ─────────────────────────────────────────────────────────── */

/* The review block's shape without the warning edge: this is routine, and
   nothing is blocked on it. */
.feedback {
  margin: 20px 0 0;
  padding: 18px 20px;
  border: 1px solid var(--k-line);
  border-radius: var(--radius-box);
}
.feedback h3 { margin-top: 0; }
.feedback label { margin-top: 12px; }
.feedback .ghost { margin-top: 12px; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; animation: none !important; }
}

/* ── data prep: the ETL agent, opened as a third column beside the two stages ── */
.split.has-dataprep { grid-template-columns: 1fr 1fr 1.25fr; }
main:has(.split.has-dataprep) { max-width: 1840px; }
@media (max-width: 1500px) {
  .split.has-dataprep { grid-template-columns: 1fr 1fr; }
  .split.has-dataprep .dataprep { grid-column: 1 / -1; }
}
@media (max-width: 1040px) { .split.has-dataprep { grid-template-columns: 1fr; } }
.dataprep { min-width: 0; }
.dataprep .card-head { align-items: flex-start; }
.dp-close { margin-left: auto; padding: 4px 10px; }
.dp-msg:empty { display: none; }
.dp-msg.err { color: var(--k-bad); }

/* the client preview strip, between the uploads and Start */
.dp-demo { display: flex; align-items: center; gap: 10px; margin-top: 12px; padding: 10px 14px;
           border: 1px solid var(--k-line); border-radius: 8px; font-size: 13px; }
.dp-demo-dot { flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--k-faint); }
.dp-demo[data-state="generating"] .dp-demo-dot { background: var(--k-accent); animation: k-pulse 1.6s infinite; }
.dp-demo[data-state="ready"] .dp-demo-dot { background: var(--k-ok); }
.dp-demo[data-state="failed"] .dp-demo-dot { background: var(--k-bad); }
.dp-demo-text { flex: 1; min-width: 0; color: var(--k-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dp-demo-text b { color: var(--k-text); font-weight: 500; }
.dp-proposed { color: var(--k-warn); }

/* the pipe runs from the controls into the runs list, inside the card */
.dataprep .k-pipe { height: 28px; margin: 16px auto -1px; }
.dataprep .k-row-side { grid-template-columns: 68px 56px minmax(150px, auto); gap: 10px; }
.dataprep .k-acts { gap: 12px; }
.dp-req { margin: 0 0 12px; font-size: 13px; color: var(--k-muted); }
.dp-req b { color: var(--k-text); font-weight: 500; }
