/* Global Reach API — load harness dashboard.
   Loaded only by /loadtest; app.css supplies everything shared (panels, forms, chips,
   the .res block the review panel reuses verbatim). */

:root {
    /* Outcome colours.

       These are a STATUS palette, not a series palette: they name states, and a state
       colour must never drift into meaning "series 3". The three were validated as an
       adjacent set against this app's own surfaces (#fff light, #171b21 dark) and clear
       every hard gate in both modes — worst adjacent pair ΔE 11.3 simulated / 27.6
       normal-vision, all three ≥3:1 on the dark surface.

       On the LIGHT surface --gr-err sits at 1.83:1, below the 3:1 mark. That is allowed
       here only because nothing leans on the fill alone: every legend entry and every
       table cell pairs the colour with an icon and a word, each identity bar carries its
       own count as a direct label, and the full table under the charts states every
       number in text. Remove those and the colour stops being legible — do not. */
    --gr-ok: #0ca30c;
    --gr-err: #fab219;
    --gr-block: #d03b3b;

    /* Chart chrome. Recessive by construction: the grid must never compete with a mark. */
    --gr-grid: #e1e0d9;
    --gr-axis: #898781;
    --gr-trend: #2a78d6;
}

@media (prefers-color-scheme: dark) {
    :root {
        --gr-grid: #2c2c2a;
        --gr-axis: #898781;
        --gr-trend: #3987e5;
    }
}

/* An explicit `display` beats the user agent's `[hidden] { display: none }`, and half the
   things on this page are flex containers toggled by the `hidden` attribute — the
   dashboard, the confirmation row, the restored-run note. Without this the dashboard is
   on screen before a run exists and the confirmation cannot be hidden again. */
[hidden] { display: none !important; }

/* ---- configuration column ---- */
.sec {
    margin: 0 0 12px; font-size: 12px; font-weight: 700;
    text-transform: uppercase; letter-spacing: .06em; color: var(--ink-3);
}

.preview { display: flex; flex-wrap: wrap; gap: 5px; margin: 10px 0 4px; }
.term {
    font-family: var(--mono); font-size: 11px; color: var(--ink-2);
    background: var(--surface-2); border-radius: 5px; padding: 2px 7px;
}
.term.more { color: var(--ink-3); background: transparent; }

.pacing, .estimate { line-height: 1.5; }
.estimate {
    margin: 14px 0 0; padding: 11px 13px; border-radius: 8px;
    background: var(--surface-2); font-size: 12.5px; color: var(--ink-2);
}
.estimate b { color: var(--ink); }
.warn-text { color: var(--warn); }

.check.confirm {
    margin-top: 10px; padding: 10px 12px; border-radius: 8px;
    background: var(--bad-bg); color: var(--bad); font-weight: 600;
}

.btn-stop {
    padding: 9px 16px; border: 1px solid var(--border); border-radius: 8px;
    background: var(--surface); color: var(--bad);
    font: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
}
.btn-stop:hover { background: var(--bad-bg); border-color: transparent; }

/* ---- dashboard ---- */
.dash { display: flex; flex-direction: column; gap: 16px; padding: 22px 0; position: relative; }

.restored-note {
    margin: 0; padding: 10px 13px; border-radius: 8px;
    background: var(--warn-bg); color: var(--warn); font-size: 12.5px;
}

/* ---- KPI tiles ----
   A stat tile rather than a one-bar chart: these are single current values, and the block
   rate leads because it is the question the page was opened to answer. */
.tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; }
.tile {
    background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
    padding: 14px 16px; display: flex; flex-direction: column; gap: 3px;
}
.tile-label { font-size: 11.5px; font-weight: 600; color: var(--ink-3); text-transform: uppercase; letter-spacing: .04em; }
.tile-value { font-size: 26px; font-weight: 650; letter-spacing: -.02em; color: var(--ink); line-height: 1.15; }
.tile-note { font-size: 11.5px; color: var(--ink-3); }
/* The hero is the block rate. It leads on size and colour rather than on width — spanning
   two columns left an orphan tile on the second row at most widths. */
.tile.hero .tile-value { font-size: 40px; color: var(--gr-block); }

/* ---- chart cards ---- */
.chart-card {
    background: var(--surface); border: 1px solid var(--border);
    border-radius: var(--radius); padding: 16px 18px 18px;
}
.chart-head { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.chart-head h3 { margin: 0; font-size: 14px; font-weight: 650; letter-spacing: -.01em; }
.chart-sub { margin: 3px 0 12px; font-size: 12px; color: var(--ink-3); }
.chart-empty { margin: 0; padding: 28px 0; text-align: center; color: var(--ink-3); font-size: 12.5px; }

.chart-legend { display: flex; gap: 14px; flex-wrap: wrap; }
.lg { font-size: 11.5px; color: var(--ink-2); display: inline-flex; align-items: center; gap: 5px; }
.lg i { font-style: normal; font-size: 10px; }

/* SVG chrome. Text wears ink tokens, never a series colour. */
.chart-card .grid { stroke: var(--gr-grid); stroke-width: 1; }
.chart-card .axis { fill: var(--gr-axis); font-size: 10.5px; font-family: var(--mono); font-variant-numeric: tabular-nums; }
.chart-card .band { fill: var(--gr-trend); opacity: .18; }
.chart-card .trend { fill: none; stroke: var(--gr-trend); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.chart-card .trend-dot { fill: var(--gr-trend); stroke: var(--surface); stroke-width: 2; }
.chart-card .hit { cursor: crosshair; }

.chart-tip {
    position: absolute; z-index: 10; pointer-events: none;
    background: var(--code-bg); color: var(--code-ink);
    font-size: 11.5px; font-family: var(--mono); line-height: 1.45;
    padding: 6px 9px; border-radius: 6px; max-width: 320px;
    box-shadow: 0 4px 14px rgb(0 0 0 / .18);
}

/* ---- tables ---- */
.tbl { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.tbl th {
    text-align: left; font-size: 11px; font-weight: 600; color: var(--ink-3);
    text-transform: uppercase; letter-spacing: .04em;
    padding: 6px 8px; border-bottom: 1px solid var(--border);
}
.tbl td { padding: 7px 8px; border-bottom: 1px solid var(--border); color: var(--ink-2); vertical-align: top; }
.tbl .num { text-align: right; font-variant-numeric: tabular-nums; }
.tbl code { font-family: var(--mono); font-size: 11px; }
.klass { font-size: 10px; }
.mini { font-family: var(--mono); font-size: 11px; color: var(--ink-3); }

.tbl.jobs { table-layout: auto; }
.tbl.jobs .job { cursor: pointer; }
.tbl.jobs .job:hover td { background: var(--surface-2); }
.tbl.jobs .job.is-open td { background: var(--surface-2); font-weight: 600; color: var(--ink); }
.tbl.jobs .term-cell { color: var(--ink); }
/* The review panel reuses app.css's .res block. It needs its own ceiling — a depth-5 job is
   fifty results and would push every other row off screen — and that ceiling has to live on
   a div, because a table cell ignores max-height. */
.tbl.jobs .detail td { background: var(--bg); padding: 0; }
.detail-body { max-height: 460px; overflow-y: auto; padding: 16px 18px; }
.detail-body > .res:first-of-type { border-top: 0; }

/* ---- toolbar ---- */
.toolbar { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.toolbar select, .toolbar input[type=text] { width: auto; font-size: 12px; padding: 5px 8px; }
.toolbar input[type=text] { width: 140px; }
.toolbar .btn-ghost.wide { width: auto; padding: 5px 10px; }

/* Wide content scrolls inside its own box; the page body never scrolls sideways. */
.chart-card > div { overflow-x: auto; }
