/* ---------------------------------------------------------------------------
   Palette. Every colour the dashboard uses is a role token declared here, so
   light/dark swap in one place. Values come from the validated reference
   palette: categorical slots 1 (blue), 2 (orange), 3 (aqua) and the blue<->red
   diverging pair with a neutral gray midpoint.
   --------------------------------------------------------------------------- */
:root,
:root[data-theme='dark'] {
  color-scheme: dark;

  --surface-1: #1a1a19;
  --page: #0d0d0d;
  --text-primary: #ffffff;
  --text-secondary: #c3c2b7;
  --text-muted: #898781;
  --gridline: #2c2c2a;
  --baseline: #383835;
  --border: rgba(255, 255, 255, 0.1);

  /* Entities keep the same hue everywhere on the page. */
  --series-up: #3987e5;    /* slot 1 - blue   */
  --series-down: #d95926;  /* slot 2 - orange */
  --series-btc: #199e70;   /* slot 3 - aqua   */
  /* The TWAP is a derived view of --series-btc, not a fourth entity: muted
     violet, drawn dashed, so it never competes with the price it averages. */
  --series-twap: #9c92e6;
  /* The locally rebuilt average: the same violet stepped back toward the
     background, drawn dotted. It sits on top of --series-twap whenever both
     are healthy, so it has to stay legible without ever winning that overlap. */
  --series-twap-local: #6f68a8;
  /* Binance BTC/USDT: another venue's price, not a view of --series-btc, so
     its own hue -- slot 5 magenta, clear of the amber that means 'held' and of
     the violet averages. */
  --series-binance: #e87ba4;
  /* Coinbase BTC-USD: a third venue beside Binance -- slot 4 yellow, the only
     free slot that stays apart from the aqua price and the magenta Binance
     line in both themes. Categorical yellow, not the status amber of 'held'. */
  --series-coinbase: #c98500;

  /* Diverging: bid-heavy <-> ask-heavy */
  --diverge-pos: #3987e5;
  --diverge-neg: #e66767;
  --diverge-mid: #383835;

  --status-good: #0ca30c;
  --status-warning: #fab219;
  --status-critical: #d03b3b;
  --success-text: #0ca30c;

  /* Wash behind the row whose window is on screen. */
  --row-selected: rgba(57, 135, 229, 0.2);

  --radius: 10px;
  --font: system-ui, -apple-system, 'Segoe UI', sans-serif;
}

:root[data-theme='light'] {
  color-scheme: light;
  --surface-1: #fcfcfb;
  --page: #f9f9f7;
  --text-primary: #0b0b0b;
  --text-secondary: #52514e;
  --text-muted: #898781;
  --gridline: #e1e0d9;
  --baseline: #c3c2b7;
  --border: rgba(11, 11, 11, 0.1);
  --series-up: #2a78d6;
  --series-down: #eb6834;
  --series-btc: #1baf7a;
  --series-twap: #7a6fd0;
  --series-twap-local: #a79fe0;
  --series-binance: #c94f86;
  --series-coinbase: #eda100;
  --diverge-pos: #2a78d6;
  --diverge-neg: #e34948;
  --diverge-mid: #f0efec;
  --success-text: #006300;
  --row-selected: rgba(42, 120, 214, 0.1);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--page);
  color: var(--text-primary);
  font-family: var(--font);
  font-size: 14px;
  line-height: 1.45;
}

.wrap {
  max-width: 1440px;
  margin: 0 auto;
  padding: 20px 20px 56px;
}

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

.topbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  margin-bottom: 18px;
}

.topbar h1 {
  font-size: 17px;
  font-weight: 600;
  margin: 0;
  letter-spacing: -0.01em;
}

.topbar .sub {
  color: var(--text-secondary);
  font-size: 13px;
  margin-right: auto;
}

.pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--surface-1);
  font-size: 12px;
  color: var(--text-secondary);
  white-space: nowrap;
}

.pill .dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--text-muted);
  flex: none;
}

.pill.ok .dot { background: var(--status-good); }
.pill.bad .dot { background: var(--status-critical); }
.pill.warn .dot { background: var(--status-warning); }

button.ghost {
  font: inherit;
  font-size: 12px;
  color: var(--text-secondary);
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 4px 12px;
  cursor: pointer;
}
button.ghost:hover { color: var(--text-primary); }
button.ghost[disabled] { opacity: 0.55; cursor: progress; }

/* The stop switch: red while the bot is armed, green once it is stopped --
   the colour is the action on offer, not the state. */
button.ghost.danger { color: var(--status-critical); border-color: var(--status-critical); }
button.ghost.danger:hover {
  color: var(--status-critical);
  background: color-mix(in srgb, var(--status-critical) 14%, transparent);
}
button.ghost.go { color: var(--success-text); border-color: var(--status-good); }
button.ghost.go:hover {
  color: var(--success-text);
  background: color-mix(in srgb, var(--status-good) 14%, transparent);
}

/* ------------------------------------------------------------ hero + tiles */

.hero-row {
  display: grid;
  /* Two heroes -- the price and the average it settles against -- then the
     four tiles that support them. */
  grid-template-columns: repeat(2, minmax(225px, 1.2fr)) repeat(4, minmax(115px, 0.72fr));
  gap: 12px;
  margin-bottom: 14px;
}

/* TWAP off: the second hero is not rendered at all, so the row goes back to
   the one-hero split rather than leaving a column of air behind it. */
.hero-row.no-twap {
  grid-template-columns: minmax(260px, 1.15fr) repeat(4, minmax(130px, 1fr));
}

.card {
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px 16px;
}

.card h2 {
  margin: 0 0 2px;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-secondary);
  letter-spacing: 0.01em;
}

.card .hint {
  margin: 0 0 10px;
  font-size: 11.5px;
  color: var(--text-muted);
}

/* Sized against its own card, so "$118,234.12" fits whichever share of the row
   the grid hands the hero -- full width on a narrow screen, half of it when the
   price and its TWAP sit side by side. */
.hero { container-type: inline-size; }

.hero .label {
  font-size: 12px;
  color: var(--text-secondary);
  display: flex;
  align-items: center;
  gap: 7px;
}

.hero .value {
  font-size: clamp(28px, 14cqw, 48px);
  font-weight: 600;
  line-height: 1.05;
  letter-spacing: -0.02em;
  margin-top: 2px;
}

/* Which way the average is heading, under the TWAP hero's delta. Tinted rather
   than filled: it sits right under the price, and a solid block of colour
   there reads as an alert. `flat` is deliberately the quiet one -- it is the
   resting state, and it should not compete with the two that mean something
   is happening. */
.dir-chip {
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 11.5px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  border: 1px solid transparent;
  color: var(--text-muted);
  margin-top:5px;
}

.dir-chip .rate { font-weight: 500; opacity: 0.85; }

.dir-chip.rising {
  color: var(--success-text);
  background: color-mix(in srgb, var(--success-text) 12%, transparent);
  border-color: color-mix(in srgb, var(--success-text) 30%, transparent);
}

.dir-chip.dropping {
  color: var(--status-critical);
  background: color-mix(in srgb, var(--status-critical) 12%, transparent);
  border-color: color-mix(in srgb, var(--status-critical) 30%, transparent);
}

.dir-chip.flat {
  color: var(--text-secondary);
  background: var(--surface-1);
  border-color: var(--border);
}

.hero .delta { font-size: 13px; color: var(--text-secondary); margin-top: 2px; }
.hero .foot { font-size: 11.5px; color: var(--text-muted); margin-top: 3px; }

.tile .label { font-size: 12px; color: var(--text-secondary); }
.tile .value {
  font-size: 26px;
  font-weight: 600;
  letter-spacing: -0.01em;
  margin-top: 4px;
}
.tile .foot { font-size: 11.5px; color: var(--text-muted); margin-top: 2px; }

.key-dot {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  flex: none;
}
.key-line {
  display: inline-block;
  width: 14px;
  height: 2px;
  border-radius: 1px;
  flex: none;
}

.up-ink { color: var(--success-text); }
.down-ink { color: var(--status-critical); }

/* --------------------------------------------------------------- filterbar */

.filterbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin-bottom: 14px;
}

.segmented {
  display: inline-flex;
  border: 1px solid var(--border);
  border-radius: 999px;
  overflow: hidden;
  background: var(--surface-1);
}

.segmented button {
  font: inherit;
  font-size: 12px;
  padding: 5px 12px;
  border: 0;
  background: transparent;
  color: var(--text-secondary);
  cursor: pointer;
}
.segmented button[aria-pressed='true'] {
  background: var(--text-primary);
  color: var(--surface-1);
}

.filterbar label { font-size: 12px; color: var(--text-muted); }

select {
  font: inherit;
  font-size: 12px;
  padding: 5px 10px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--surface-1);
  color: var(--text-primary);
  /* Wide enough for a whole option -- stamp, market name and status -- so the
     closed select doesn't clip the name mid-word. Still shrinks on narrow
     viewports, where the filter bar wraps anyway. */
  max-width: min(100%, 560px);
}

/* ------------------------------------------------------------------ charts */

.grid-1 {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 12px;
  margin-bottom: 12px;
}

.grid-2 {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
  margin-bottom: 12px;
}

.grid-3 {
  display: grid;
  /* The history card carries the widest text on the page (a full market name
     per row), so it gets the extra width rather than the two ladders. */
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1.55fr);
  gap: 12px;
  margin-bottom: 12px;
}

.chart-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 2px;
}
.chart-head h2 { margin: 0; }

/* A control living in a card heading rather than the page filter bar (the
   history date picker). Pushed to the trailing edge so the heading still reads
   as the heading. */
.head-filter {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 6px;
}
.head-filter label { font-size: 11px; color: var(--text-muted); }

input[type='date'] {
  font: inherit;
  font-size: 12px;
  padding: 3px 10px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--surface-1);
  color: var(--text-primary);
  /* :root already declares color-scheme per theme, so the native calendar
     popup and the clear/spin affordances follow the page rather than staying
     light on a dark card. */
}
input[type='date']:focus-visible { outline: 2px solid var(--diverge-pos); outline-offset: 1px; }

.legend {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  margin-left: auto;
  font-size: 11.5px;
  color: var(--text-secondary);
}
.legend span { display: inline-flex; align-items: center; gap: 6px; }
/* An author `display` outranks the UA's `[hidden] { display: none }`, so the
   keys the page hides -- the TWAP ones, on a window recorded without it --
   have to be told a second time or they sit there naming a line that is not
   on the chart. */
.legend span[hidden] { display: none; }

.plot { width: 100%; display: block; touch-action: none; }
.plot text { font-family: var(--font); }

.tooltip {
  position: fixed;
  z-index: 40;
  pointer-events: none;
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 8px 10px;
  font-size: 12px;
  color: var(--text-primary);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.18);
  min-width: 148px;
  opacity: 0;
  transition: opacity 0.08s;
}
.tooltip.on { opacity: 1; }
.tooltip .tt-head {
  color: var(--text-muted);
  font-size: 11px;
  margin-bottom: 5px;
  font-variant-numeric: tabular-nums;
}
.tooltip .tt-row {
  display: flex;
  align-items: center;
  gap: 7px;
  justify-content: space-between;
}
.tooltip .tt-row b {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  margin-left: auto;
}
.tooltip .tt-name { display: inline-flex; align-items: center; gap: 6px; color: var(--text-secondary); }

/* -------------------------------------------------------------------- book */

.ladder { width: 100%; font-size: 12px; border-collapse: collapse; }
.ladder th {
  text-align: right;
  font-weight: 500;
  color: var(--text-muted);
  font-size: 11px;
  padding: 0 6px 5px;
}
.ladder th:first-child { text-align: left; }
.ladder td {
  padding: 2px 6px;
  font-variant-numeric: tabular-nums;
  text-align: right;
  color: var(--text-secondary);
  position: relative;
}
.ladder td:first-child { text-align: left; color: var(--text-primary); font-weight: 500; }
.ladder .bar {
  position: absolute;
  inset: 2px auto 2px 0;
  border-radius: 0 4px 4px 0;
  opacity: 0.16;
}
.ladder tr.bid .bar { background: var(--diverge-pos); }
.ladder tr.ask .bar { background: var(--diverge-neg); }
.ladder .mid td {
  border-top: 1px solid var(--baseline);
  border-bottom: 1px solid var(--baseline);
  color: var(--text-muted);
  font-size: 11px;
  padding: 4px 6px;
}

/* ---------------------------------------------------------------- history */

/* Unfiltered this holds 24 rows and never scrolls; a filtered day is up to 288
   (one per 5 minutes), which would otherwise stretch the card far past the two
   ladders beside it. The cap is about the height of a full ladder, so the row
   of three cards stays level. */
#history { max-height: 420px; overflow-y: auto; }

.history { width: 100%; border-collapse: collapse; font-size: 12px; }
.history th {
  text-align: left;
  font-weight: 500;
  color: var(--text-muted);
  font-size: 11px;
  padding: 0 8px 6px;
  border-bottom: 1px solid var(--gridline);
  /* Stays put while a long day scrolls under it. */
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--surface-1);
}
.history td {
  padding: 5px 8px;
  border-bottom: 1px solid var(--gridline);
  font-variant-numeric: tabular-nums;
  color: var(--text-secondary);
}
.history tr:last-child td { border-bottom: 0; }
.history tr[data-window] { cursor: pointer; }
.history tr[data-window]:hover td { background: var(--page); }

/* The window currently on the charts. An inset rule marks it instead of a
   border so the row's text doesn't shift by 2px when the selection moves. */
.history tr.selected td { background: var(--row-selected); }
.history tr.selected:hover td { background: var(--row-selected); }
.history tr.selected td:first-child { box-shadow: inset 2px 0 0 var(--diverge-pos); }
.history tr.selected td.name { font-weight: 600; }

.history td.name { color: var(--text-primary); font-variant-numeric: normal; }
.history td.name .stamp { font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Polymarket's name for the window, under its start stamp. Every row repeats
   the same prefix, so it reads as the secondary line it is rather than
   competing with the numbers to its right. */
.history td.name .market {
  display: block;
  margin-top: 1px;
  font-size: 11px;
  font-weight: 400;
  color: var(--text-muted);
}
.history .tag {
  display: inline-block;
  padding: 1px 7px;
  border-radius: 999px;
  font-size: 10.5px;
  border: 1px solid var(--border);
  color: var(--text-secondary);
}
.history .tag.live { border-color: var(--status-good); color: var(--success-text); }

/* ------------------------------------------------------------ tracked wallet */

/* A quiet caption in a card head -- what the tracker is watching, beside the
   title rather than stealing a line from the table. */
.head-note {
  font-size: 11.5px;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

/* Two swatches, one label: a fill mark takes the colour and the direction of
   the outcome it bought, so its legend key has to show both rather than
   invent a third hue. They sit as a pair, which the legend's own 6px gap
   would break up. */
.legend span.key-wallet { gap: 2px; }
.key-wallet .key-tri + .key-tri { margin-right: 4px; }

/* A fill's key: the triangle its mark is drawn as, pointing the way the buy
   bet, in the colour set on `--key`. */
.key-tri {
  display: inline-block;
  width: 10px;
  height: 9px;
  flex: none;
  background: var(--key, var(--text-muted));
  clip-path: polygon(50% 0, 100% 100%, 0 100%);
}
.key-tri.down { clip-path: polygon(0 0, 100% 0, 50% 100%); }

/* The TWAP key is a dash, not a dot -- the line on the chart is dashed, and a
   round swatch would promise a solid stroke that isn't there. */
.key-dash {
  display: inline-block;
  width: 14px;
  height: 2px;
  flex: none;
}

/* About a dozen rows before it scrolls, so the card can't run away with the
   page when a busy wallet fills it. Seven columns is wider than a phone, so
   the overflow is both ways -- the page itself must never scroll sideways. */
#wallet { max-height: 340px; overflow: auto; }

.wallet { width: 100%; border-collapse: collapse; font-size: 12px; }
.wallet th {
  text-align: right;
  font-weight: 500;
  color: var(--text-muted);
  font-size: 11px;
  padding: 0 8px 6px;
  border-bottom: 1px solid var(--gridline);
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--surface-1);
  white-space: nowrap;
}
.wallet th:first-child, .wallet th:nth-child(2) { text-align: left; }
.wallet td {
  padding: 5px 8px;
  text-align: right;
  border-bottom: 1px solid var(--gridline);
  font-variant-numeric: tabular-nums;
  color: var(--text-secondary);
  white-space: nowrap;
}
.wallet tr:last-child td { border-bottom: 0; }
.wallet tr[data-wtx] { cursor: pointer; }
.wallet tr[data-wtx]:hover td { background: var(--page); }
/* A transaction whose window was never recorded is not a link. The row is
   complete either way, so it is not dimmed -- the context tag already says
   what is missing, and greying the row would claim more than that. */
.wallet tr.inert { cursor: default; }

/* The window this row would load is already on the charts. */
.wallet tr[aria-current='true'] td { background: var(--row-selected); }
.wallet tr[aria-current='true'] td:first-child { box-shadow: inset 2px 0 0 var(--diverge-pos); }

.wallet td.when, .wallet td.act { text-align: left; }
.wallet td.when { color: var(--text-primary); }
/* The full date + time is one unit; wrapping it mid-stamp would read as two
   different times stacked. */
.wallet td.when .stamp { font-variant-numeric: tabular-nums; white-space: nowrap; }
.wallet td.when .into {
  display: block;
  font-size: 11px;
  color: var(--text-muted);
}
.wallet td.act { color: var(--text-primary); font-variant-numeric: normal; }
.wallet td.act .usd { color: var(--text-muted); font-variant-numeric: tabular-nums; }

.wallet .tag {
  display: inline-block;
  padding: 1px 6px;
  margin-right: 4px;
  border-radius: 999px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.02em;
  border: 1px solid var(--border);
  color: var(--text-secondary);
}
/* Direction of the trade. Buying is the wallet taking a position, which is the
   event this whole card exists for, so it is the one that carries a hue. */
.wallet .tag.buy { border-color: var(--diverge-pos); color: var(--diverge-pos); }
.wallet .tag.sell { border-color: var(--diverge-neg); color: var(--diverge-neg); }

/* How the market context was obtained. `none` is a gap in the record and has
   to look like one; the rest are just provenance and stay recessive. */
.wallet .tag.src { font-weight: 500; letter-spacing: 0; text-transform: none; }
.wallet .tag.src.none { border-style: dashed; color: var(--text-muted); }

.empty {
  color: var(--text-muted);
  font-size: 12.5px;
  padding: 26px 0;
  text-align: center;
}

/* ========================================================================= */
/* The bot                                                                   */
/* ========================================================================= */

/* Five even tiles: the bot row has no hero, so nothing claims extra width. */
.bot-row {
  grid-template-columns: repeat(4, minmax(110px, 0.75fr)) repeat(2, minmax(185px, 1.25fr));
}

/* Signal and Position carry a sentence, not a figure, so they read at text
   size rather than at the 26px a single number gets. */
.tile.wide .value { font-size: 17px; line-height: 1.25; }

.tile .value.flat { color: var(--text-muted); }
.tile .value.armed { color: var(--success-text); }
/* The signal cleared, but something else refused the trade -- neither the
   green of an order going out nor the grey of nothing to do. */
.tile .value.held { color: var(--status-warning); }

/* --------------------------------------------------------- signal readout */

.sig {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  font-variant-numeric: tabular-nums;
}
.sig .sig-side {
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  font-size: 13px;
}
.sig .sig-side.up { color: var(--series-up); }
.sig .sig-side.down { color: var(--series-down); }
.sig .sig-gate {
  font-size: 12px;
  color: var(--text-muted);
  font-variant-numeric: normal;
}

/* A position is one leg per side held. When both do not fit on a line the
   break falls between the legs, never inside one. */
.sig.legs { flex-wrap: wrap; column-gap: 14px; row-gap: 0; }
.leg {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  white-space: nowrap;
}

/* ---------------------------------------------------------------- tables */

/* Every list on the page -- fills, traded windows, orders, skips, history,
   sharp moves -- is the same table, so it is styled once. */
#fills, #botwindows, #orders, #skips, #history, #moves-table { max-height: 240px; overflow: auto; }
#botwindows { max-height: 420px; }

table.rows {
  width: 100%;
  border-collapse: collapse;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}
table.rows th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--surface-1);
  text-align: right;
  font-size: 10.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
  padding: 0 8px 6px;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
table.rows td {
  text-align: right;
  padding: 6px 8px;
  border-bottom: 1px solid var(--gridline);
  color: var(--text-secondary);
  white-space: nowrap;
}
table.rows th:first-child,
table.rows td:first-child,
table.rows th.l,
table.rows td.l { text-align: left; }
table.rows tr:last-child td { border-bottom: 0; }
table.rows tr[data-window] { cursor: pointer; }
table.rows tr[data-window]:hover td { background: var(--page); }
table.rows tr[aria-current='true'] td { background: var(--row-selected); }
table.rows tr[aria-current='true'] td:first-child {
  box-shadow: inset 2px 0 0 var(--diverge-pos);
}
table.rows td.when { color: var(--text-primary); }
table.rows td.when .stamp { white-space: nowrap; }
table.rows td.when .into {
  color: var(--text-muted);
  font-size: 11px;
  margin-left: 6px;
}
table.rows td.name {
  color: var(--text-primary);
  font-variant-numeric: normal;
  max-width: 320px;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ------------------------------------------------------------------- tags */

.tag {
  display: inline-block;
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  padding: 1px 6px;
  border-radius: 999px;
  border: 1px solid var(--border);
  color: var(--text-secondary);
  vertical-align: 1px;
}
.tag.up   { border-color: var(--series-up);   color: var(--series-up); }
.tag.down { border-color: var(--series-down); color: var(--series-down); }
.tag.win  { border-color: var(--status-good); color: var(--success-text); }
.tag.loss { border-color: var(--status-critical); color: var(--status-critical); }
.tag.live { border-color: var(--status-good); color: var(--success-text); }
.tag.open { border-style: dashed; color: var(--text-muted); }
.tag.maker { border-style: dashed; }
.tag.taker { border-color: var(--diverge-neg); color: var(--diverge-neg); }

/* Order-log actions. Placing and filling are things going right; cancelling
   and rejecting are the bot backing out, and they read differently. */
.tag.place  { border-color: var(--diverge-pos); color: var(--diverge-pos); }
.tag.amend  { color: var(--text-muted); }
.tag.cancel { border-color: var(--status-warning); color: var(--status-warning); }
.tag.fill   { border-color: var(--status-good); color: var(--success-text); }
.tag.reject { border-color: var(--status-critical); color: var(--status-critical); }
.tag.settle { border-color: var(--text-secondary); color: var(--text-secondary); }

/* A window that held both sides. Neither side's colour alone, and not a third
   hue either: the two outcome colours washed together behind neutral ink. */
.tag.both {
  border-color: var(--text-secondary);
  color: var(--text-primary);
  background: linear-gradient(
    90deg,
    color-mix(in srgb, var(--series-up) 18%, transparent),
    color-mix(in srgb, var(--series-down) 18%, transparent)
  );
}

/* An order on the wire that has not come back as a fill yet -- the live
   broker's first row for every order. Dashed like the other not-yet states. */
.tag.submit { border-style: dashed; color: var(--text-secondary); }

.head-note {
  font-size: 11px;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

/* A skip reason is a share of the time inside the entry band; the bar behind
   the row is that share, so the dominant reason is visible without reading. */
.skipbar {
  position: absolute;
  inset: 0 auto 0 0;
  background: var(--diverge-pos);
  opacity: 0.1;
  border-radius: 3px;
}
table.rows td.reason {
  position: relative;
  color: var(--text-primary);
  font-variant-numeric: normal;
}
table.rows td.reason span { position: relative; }

/* A stand-down is not a gate: the signal was good and something downstream
   refused it. Those rows sort to the top and carry the warning colour, so a
   window that was held back never reads like a window with nothing in it. */
table.rows tr.stood td.reason { color: var(--status-warning); }
table.rows tr.stood .skipbar { background: var(--status-warning); opacity: 0.16; }
.tag.stood { border-color: var(--status-warning); color: var(--status-warning); margin-left: 6px; }

/* --------------------------------------------------------------- backtest */

.nav {
  display: inline-flex;
  gap: 2px;
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 2px;
}
.nav a {
  font-size: 12px;
  font-weight: 500;
  padding: 3px 12px;
  border-radius: 999px;
  color: var(--text-secondary);
  text-decoration: none;
}
.nav a:hover { color: var(--text-primary); }
.nav a[aria-current='page'] {
  background: var(--diverge-pos);
  color: #fff;
  font-weight: 600;
}

.gates { margin-bottom: 12px; }
.gategrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 8px 12px;
}
.gategrid label {
  display: flex;
  flex-direction: column;
  gap: 3px;
  font-size: 11px;
  color: var(--text-muted);
}
.gategrid input,
.gategrid select {
  font: inherit;
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
  padding: 4px 7px;
  border-radius: 7px;
  border: 1px solid var(--border);
  background: var(--surface-1);
  color: var(--text-primary);
}
.gategrid input:focus-visible,
.gategrid select:focus-visible {
  outline: 2px solid var(--diverge-pos);
  outline-offset: 1px;
}
.gateactions {
  display: flex;
  gap: 8px;
  margin-top: 12px;
}

.compare-row { grid-template-columns: repeat(5, minmax(0, 1fr)); }

#rows { max-height: 560px; overflow: auto; }
#models, #reasons { overflow-x: auto; }

/* A run's parameters are prose, not figures: they wrap rather than scroll. */
#params table.rows td { white-space: normal; }
#params table.rows td:first-child {
  width: 100px;
  color: var(--text-muted);
  vertical-align: top;
}
#params code { font-size: 11.5px; word-break: break-all; }

/* The per-window table pairs two actors over the same window, so the header is
   two rows: who, then what. The group rule is what keeps a strategy column from
   being read as a wallet one. */
table.rows th.group {
  text-align: center;
  font-size: 10px;
  letter-spacing: 0.08em;
  padding-bottom: 2px;
}
table.rows th.group.strategy { color: var(--series-btc); }
table.rows th.group.wallet   { color: var(--series-up); }
table.rows td.sep, table.rows th.sep { border-left: 1px solid var(--gridline); }
table.rows td.dim, table.rows .dim { color: var(--text-muted); }
/* The wallet is not a fourth model -- it is what happened. Its own rule. */
table.rows tr.sep-top td { border-top: 1px solid var(--baseline); }

.tag.agree { border-color: var(--status-good); color: var(--success-text); }
.tag.opposed { border-color: var(--status-critical); color: var(--status-critical); }
.tag.solo { border-style: dashed; color: var(--text-muted); }

/* The headline model is the one driving the tiles, the chart and the table;
   the other two stay legible but recede. */
table.rows tr.model-on td { background: var(--row-selected); font-weight: 600; }

.runbanner {
  font-size: 12.5px;
  color: var(--text-secondary);
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface-1);
  margin-bottom: 12px;
}
.runbanner.bad { border-color: var(--status-critical); color: var(--status-critical); }

@media (max-width: 1100px) {
  /* .no-twap is the more specific selector, so it has to be named here too or
     the five-column desktop split would survive the breakpoint. */
  .hero-row,
  .hero-row.no-twap { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .hero-row .hero { grid-column: 1 / -1; }
  .bot-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .compare-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid-2, .grid-3 { grid-template-columns: minmax(0, 1fr); }
}

/* ------------------------------------------------------------------ replay */

/* The transport for playing a closed window back. It sits between the window
   picker and the charts it drives, because that is the order the two are used
   in: pick the window, then play it. */
.replay { margin-bottom: 14px; }

.replay-transport {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}

/* The scrubber takes whatever the buttons leave, down to a width where the
   handle is still worth dragging; below that the row wraps instead. */
.replay-transport input[type='range'] {
  flex: 1 1 220px;
  min-width: 160px;
  accent-color: var(--diverge-pos);
  cursor: pointer;
}
.replay-transport input[type='range'][disabled] { opacity: 0.4; cursor: default; }

.replay-clock {
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  color: var(--text-secondary);
  white-space: nowrap;
}
.replay-clock b { color: var(--text-primary); font-weight: 600; }

/* One row of small readouts under the transport: the whole decision at the
   instant on the clock, so the window can be read without looking away from
   the thing being scrubbed. */
.replay-hud {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 10px;
  border-top: 1px solid var(--border);
  padding-top: 12px;
}
/* `display` here beats the UA rule behind the `hidden` attribute, so the panel
   needs telling twice or it survives its own hiding. */
.replay-hud[hidden] { display: none; }

.rcell { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.rlabel { font-size: 11px; color: var(--text-secondary); }
.rvalue {
  font-size: 15px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}
.rvalue.rmuted, .rvalue .rmuted {
  color: var(--text-muted);
  font-weight: 400;
  font-size: 13px;
}
.rfoot { font-size: 11px; color: var(--text-muted); }

/* The breakdown beside a figure in the tooltip: muted, since the figure is
   what is read and this only explains the corner under the cursor. */
.tooltip .tt-step {
  margin-left: 6px;
  font-weight: 400;
  color: var(--text-muted);
}
