/* OpenRouter market terminal — design system.
   Terminal density and colour discipline, contemporary typography and spacing. */

@font-face {
  font-family: 'JetBrains Mono Variable';
  src: url('/fonts/jetbrains-mono-var.woff2') format('woff2');
  font-weight: 100 800;
  font-style: normal;
  font-display: swap;
}

:root {
  color-scheme: dark;

  --bg:          #08090b;
  --bg-raised:   #0d0f13;
  --bg-panel:    #101319;
  --bg-hover:    #161a22;
  --bg-active:   #1b212b;
  --line:        #1c2129;
  --line-strong: #2a313d;

  --text:        #e8ebf0;
  --text-dim:    #98a1b0;
  --text-faint:  #626c7c;

  --amber:       #ffb020;
  --amber-dim:   #7a5410;
  --cyan:        #45c8e0;
  --up:          #3fd48a;
  --down:        #ff5f56;
  --violet:      #9b8cff;
  --magenta:     #e86fc4;

  --mono: 'JetBrains Mono Variable', 'JetBrains Mono', ui-monospace,
          "SFMono-Regular", "Cascadia Mono", "Roboto Mono", Menlo, Consolas,
          monospace;

  --topbar: 46px;
  --navbar: 34px;
  --tape: 26px;

  /* The content column: main is capped and centred, so past the cap it stops
     widening and grows gutters instead. */
  --content-max: 2100px;
  --content-pad: 10px;
  /* Inset that lands a full-bleed bar's content on the same column as main's.
     Goes negative below the cap, so each bar wraps it in max() with whatever
     gutter it already had — nothing changes until the gutters open up. */
  --align: calc((100% - var(--content-max)) / 2 + var(--content-pad));

  /* Frosted chrome: the three sticky bars share one translucent tint. */
  --chrome: rgb(13 15 19 / .72);
  --frost: blur(14px) saturate(1.25);
  /* Table headers frost over their own rows, not over the aurora. The backdrop
     is high-contrast text and coloured sparklines rather than a smooth
     gradient, so the tint is heavier and the saturation pulled down instead of
     boosted -- otherwise the rows underneath ghost through the labels. */
  --chrome-head: rgb(13 15 19 / .93);
  --frost-head: blur(18px) saturate(.85);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--mono);
  font-size: 13px;
  -webkit-font-smoothing: antialiased;
  scrollbar-color: var(--line-strong) transparent;
}

body { min-width: 360px; }

/* A slow aurora behind the sticky chrome only; the page body stays flat.
   Painted beneath all content, fading out below the three bars. */
body::before {
  content: ""; position: fixed; top: 0; left: -15%; right: -15%; height: 200px;
  z-index: 0; pointer-events: none;
  background:
    radial-gradient(560px 160px at 18% 0%, rgb(255 176 32 / .30), transparent 70%),
    radial-gradient(720px 180px at 52% 0%, rgb(69 200 224 / .24), transparent 70%),
    radial-gradient(620px 170px at 84% 0%, rgb(155 140 255 / .26), transparent 70%);
  mask-image: linear-gradient(180deg, #000 70%, transparent);
  animation: chrome-aurora 20s ease-in-out infinite alternate;
}
@keyframes chrome-aurora {
  from { transform: translateX(-3.5%); }
  to { transform: translateX(3.5%); }
}

a { color: inherit; text-decoration: none; }
button, input, select, textarea { font: inherit; color: inherit; }
:focus-visible { outline: 1px solid var(--amber); outline-offset: 1px; }

::-webkit-scrollbar { width: 9px; height: 9px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--line-strong); border-radius: 0; }
::-webkit-scrollbar-thumb:hover { background: #3b434f; }

.mono, .num { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.hidden { display: none !important; }
.up { color: var(--up); }
.down { color: var(--down); }
.dim { color: var(--text-dim); }
.faint { color: var(--text-faint); }
.amber { color: var(--amber); }
.nowrap { white-space: nowrap; }
.right { text-align: right; }
.center { text-align: center; }

/* ---------------------------------------------------------------- chrome -- */

.topbar {
  position: sticky; top: var(--tape); z-index: 60;
  height: var(--topbar);
  display: flex; align-items: center; gap: 18px;
  /* Full-bleed bar, content on the same column as main. */
  padding-block: 0; padding-inline: max(18px, var(--align));
  background: var(--chrome);
  -webkit-backdrop-filter: var(--frost); backdrop-filter: var(--frost);
  border-bottom: 1px solid var(--line);
}

.brand { display: flex; align-items: baseline; gap: 9px; flex: none; }
.brand-name { font-family: var(--mono); font-size: 13px; letter-spacing: .08em;
  color: var(--text); }

.topbar-spacer { flex: 1; }

.cmd-trigger {
  display: flex; align-items: center; gap: 10px;
  height: 28px; min-width: 260px; padding: 0 10px;
  background: var(--bg-panel); border: 1px solid var(--line);
  color: var(--text-faint); cursor: pointer;
  font-family: var(--mono); font-size: 11px; letter-spacing: .04em;
}
.cmd-trigger:hover { border-color: var(--line-strong); color: var(--text-dim); }
.cmd-trigger kbd {
  margin-left: auto; font-family: var(--mono); font-size: 10px;
  border: 1px solid var(--line-strong); padding: 1px 4px; color: var(--text-faint);
}

.clock { font-family: var(--mono); font-size: 11px; color: var(--text-dim);
  letter-spacing: .05em; flex: none; }
.clock b { color: var(--amber); font-weight: 500; }

/* Section nav as its own bar, links centred. `safe` keeps the first items
   reachable when the row overflows and has to scroll sideways. */
.navbar {
  position: sticky; top: calc(var(--tape) + var(--topbar)); z-index: 55;
  height: var(--navbar);
  display: flex; align-items: stretch; justify-content: safe center;
  background: var(--chrome);
  -webkit-backdrop-filter: var(--frost); backdrop-filter: var(--frost);
  border-bottom: 1px solid var(--line);
  overflow-x: auto; scrollbar-width: none;
}
.navbar::-webkit-scrollbar { display: none; }
.nav-item {
  display: flex; align-items: center; gap: 7px;
  padding: 0 14px; border: 0; background: transparent; cursor: pointer;
  font-family: var(--mono); font-size: 11px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--text-faint);
  border-bottom: 2px solid transparent; white-space: nowrap;
}
.nav-item:hover { color: var(--text); background: var(--bg-raised); }
.nav-item.active { color: var(--amber); border-bottom-color: var(--amber); }

/* ------------------------------------------------------------------ tape -- */

.tape {
  position: sticky; top: 0; z-index: 65;
  height: var(--tape); overflow: hidden;
  background: var(--chrome);
  -webkit-backdrop-filter: var(--frost); backdrop-filter: var(--frost);
  border-bottom: 1px solid var(--line);
}
/* The marquee is the one element allowed to run wider than the content
   column: past --content-max it scrolls across the full viewport while the
   bars below stay aligned. The clipping lives on an inner box rather than on
   .tape itself -- overflow clips at the padding box, so padding on .tape
   would let items ride into the fade at the edge. */
.tape-clip {
  position: relative; height: 100%; overflow: hidden;
}
/* Edge fade as overlays: the items dissolve into the chrome tint. */
.tape-clip::before, .tape-clip::after {
  content: ""; position: absolute; top: 0; bottom: 0; width: 40px;
  z-index: 1; pointer-events: none;
}
.tape-clip::before { left: 0; background: linear-gradient(90deg, var(--chrome), transparent); }
.tape-clip::after { right: 0; background: linear-gradient(-90deg, var(--chrome), transparent); }
.tape-track {
  display: flex; align-items: center; height: 100%; width: max-content;
  white-space: nowrap; will-change: transform;
  animation: tape-scroll 120s linear infinite;
}
.tape-half { display: flex; align-items: center; gap: 26px; padding-right: 26px; }
.tape:hover .tape-track { animation-play-state: paused; }
@keyframes tape-scroll { from { transform: translateX(0); } to { transform: translateX(-50%); } }
@media (prefers-reduced-motion: reduce) {
  .tape-track { animation: none; }
  body::before { animation: none; }
}
.tape-item { display: flex; align-items: baseline; gap: 7px;
  font-family: var(--mono); font-size: 11px; }
.tape-item .sym { color: var(--text-dim); letter-spacing: .05em; }
.tape-item .val { color: var(--text); }

/* ----------------------------------------------------------------- shell -- */

/* The frame matches the 10px rhythm between the panels. */
main { padding: var(--content-pad); max-width: var(--content-max); margin: 0 auto; }

/* Vertical rhythm: 10px between a view's top-level sections and inside
   stacking containers. The margin collapses with any margin a section
   already carries (kpis, detail-head, page-head, tabs), so those keep
   exactly 10px instead of doubling. */
#view > div > * + *, .stack > * + * { margin-top: 10px; }

/* Controls strip that sits where the page title used to be. */
.page-head {
  display: flex; align-items: center; gap: 14px;
  margin-bottom: 10px; flex-wrap: wrap;
}
.page-head:empty { display: none; }

.grid { display: grid; gap: 10px; }
.g2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.g3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.g4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.g-2-1 { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); }
.g-1-2 { grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); }
.g-3-2 { grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); }
@media (max-width: 1180px) {
  .g3, .g4, .g-2-1, .g-1-2, .g-3-2 { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 820px) { .g2 { grid-template-columns: minmax(0, 1fr); } }

/* ----------------------------------------------------------------- panel -- */

/* The frosted chrome implies a light source at the top of the viewport, so the
   surfaces below it are lit the same way: a brighter top edge where the light
   catches, and a soft cast shadow so a panel sits above the page rather than
   being drawn onto it. The top edge is a border rather than an inset shadow
   because .panel-head is opaque and would paint straight over an inset. */
.panel {
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-top-color: var(--line-strong);
  box-shadow: 0 12px 28px -18px rgb(0 0 0 / .9);
  display: flex; flex-direction: column; min-width: 0;
}
.panel-head {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 8px 11px; border-bottom: 1px solid var(--line);
  background: var(--bg-raised); min-height: 34px;
}
.panel-title {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .05em;
  text-transform: uppercase; color: var(--amber); white-space: nowrap;
}
.panel-note { font-family: var(--mono); font-size: 10px; color: var(--text-faint);
  letter-spacing: .05em; }
/* A head can carry more than one note (share filter, then provenance); without
   a separator they read as one run-on sentence. */
.panel-note + .panel-note::before { content: '·'; margin: 0 6px; opacity: .6; }
/* Wraps because a panel head can carry several control groups at once — layer
   toggles, a scale switch and a metric select — which overflow a phone width. */
.panel-tools { margin-left: auto; display: flex; align-items: center; gap: 6px;
  flex-wrap: wrap; min-width: 0; }
.panel-tools .term { max-width: 100%; }
.panel-body { padding: 11px; min-width: 0; }
.panel-body.flush { padding: 0; }
/* Inside a flush body the last row's underline sits on top of the panel's own
   bottom border and reads as a 2px line. */
.panel-body.flush .table-wrap table.data tbody tr:last-child td { border-bottom: 0; }
.panel-body.flush .wire-row:last-child { border-bottom: 0; }
.panel-foot {
  padding: 7px 11px; border-top: 1px solid var(--line);
  font-family: var(--mono); font-size: 10px; color: var(--text-faint);
  letter-spacing: .04em;
}

/* ------------------------------------------------------------- kpi cells -- */

.kpis { display: grid; gap: 1px; background: var(--line);
  border: 1px solid var(--line); border-top-color: var(--line-strong);
  box-shadow: 0 12px 28px -18px rgb(0 0 0 / .9); margin-bottom: 10px;
  grid-template-columns: repeat(auto-fit, minmax(158px, 1fr)); }
/* Each cell is lit from above too, so a wrapped second row does not read as an
   unlit slab hanging off the first. */
.kpi { background: var(--bg-panel); padding: 10px 12px; min-width: 0;
  box-shadow: inset 0 1px 0 rgb(255 255 255 / .035); }
.kpi-label { font-family: var(--mono); font-size: 9.5px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--text-faint); margin-bottom: 5px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kpi-value { font-family: var(--mono); font-size: 21px; line-height: 1.1;
  font-variant-numeric: tabular-nums; letter-spacing: -.02em; }
.kpi-value small { font-size: 12px; color: var(--text-dim); margin-left: 3px; }
/* The live spend counter carries every digit so the movement is visible, which
   makes it the widest value on the row; it must not break mid-number. */
.kpi-value .ticker { white-space: nowrap; }
/* Value and its change on one baseline: the arrow belongs beside the number it
   qualifies, not stacked under it where it reads as a second statistic. The
   change is allowed to wrap away on a narrow cell rather than squeeze the
   number, which is the figure being read. */
.kpi-value.with-change { display: flex; align-items: baseline; gap: 7px;
  flex-wrap: wrap; }
.kpi-change { font-family: var(--mono); font-size: 11px; font-weight: 600;
  letter-spacing: 0; white-space: nowrap; }
.kpi-delta { font-family: var(--mono); font-size: 10.5px; margin-top: 5px;
  display: flex; align-items: center; gap: 5px; color: var(--text-faint); }
/* The comparison figure a live counter is measured against reads in full
   white; only its basis ("last month") stays dim. */
.kpi-was { color: var(--text); }

/* ----------------------------------------------------------------- table -- */

.table-wrap { overflow: auto; max-height: 100%; }
/* A wrap inside a growing panel body fills the depth the grid row sets; the
   table stretches to at least that depth so a short log still fills it, and
   scrolls when it has more rows than fit. */
.table-wrap.fill { flex: 1 1 0; min-height: 0; max-height: none; }
.table-wrap.fill table.data { height: 100%; }
table.data { width: 100%; border-collapse: collapse; font-family: var(--mono);
  font-size: 11.5px; font-variant-numeric: tabular-nums; }
/* The same frosted tint as the three sticky bars, for the same reason: rows
   pass under the header rather than behind an opaque slab, which is both the
   page's visual language and better scroll feedback on the long tables. */
table.data thead th {
  position: sticky; top: 0; z-index: 2;
  background: var(--chrome-head); color: var(--text-faint);
  -webkit-backdrop-filter: var(--frost-head); backdrop-filter: var(--frost-head);
  font-weight: 500; font-size: 9.5px; letter-spacing: .1em; text-transform: uppercase;
  text-align: left; padding: 7px 9px; border-bottom: 1px solid var(--line-strong);
  white-space: nowrap; user-select: none;
}
table.data thead th.sortable { cursor: pointer; }
table.data thead th.sortable:hover { color: var(--text); }
table.data thead th.sorted { color: var(--amber); }
table.data thead th.sorted[data-sort-dir="asc"]::after { content: ' \25B2'; }
table.data thead th.sorted[data-sort-dir="desc"]::after { content: ' \25BC'; }
table.data thead th.num, table.data td.num { text-align: right; }
table.data tbody td { padding: 6px 9px; border-bottom: 1px solid var(--line);
  white-space: nowrap; }
table.data tbody tr:hover { background: var(--bg-hover); }
table.data tbody tr.clickable { cursor: pointer; }
table.data tbody tr.rank-row td:first-child { color: var(--text-faint); }
table.data td.name { font-family: var(--mono); font-size: 12px;
  max-width: 280px; overflow: hidden; text-overflow: ellipsis; }
table.data td.wide { white-space: normal; max-width: 420px; }
table.data .sub { color: var(--text-faint); font-size: 10px; }
table.data tbody tr.total-row { background: var(--bg-raised); font-weight: 600; }

.linklike { color: var(--cyan); }
tr:hover .linklike { text-decoration: underline; }

/* --------------------------------------------------------------- controls -- */

.controls { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.seg { display: inline-flex; border: 1px solid var(--line); background: var(--bg-raised); }
.seg button {
  border: 0; background: transparent; cursor: pointer; padding: 4px 9px;
  font-family: var(--mono); font-size: 10px; letter-spacing: .08em;
  text-transform: uppercase; color: var(--text-faint);
  border-right: 1px solid var(--line);
}
.seg button:last-child { border-right: 0; }
.seg button:hover { color: var(--text); background: var(--bg-hover); }
.seg button.active { color: var(--bg); background: var(--amber); }

select.term, input.term {
  background: var(--bg-raised); border: 1px solid var(--line); color: var(--text);
  padding: 4px 8px; font-family: var(--mono); font-size: 11px; min-width: 0;
}
select.term:hover, input.term:hover { border-color: var(--line-strong); }
input.term::placeholder { color: var(--text-faint); }
label.field { display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--text-faint); }

.chip {
  display: inline-flex; align-items: center; gap: 5px;
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .07em;
  text-transform: uppercase; padding: 2px 6px;
  border: 1px solid var(--line-strong); color: var(--text-dim);
}
.chip.on { border-color: var(--amber-dim); color: var(--amber); }
.chip.warn { border-color: #6b3a1a; color: #ff9d4d; }
.chip.bad { border-color: #6b2222; color: var(--down); }
.chip.good { border-color: #1e5a3c; color: var(--up); }
.chips { display: flex; flex-wrap: wrap; gap: 5px; }

/* ---------------------------------------------------------------- charts -- */

.chart { position: relative; width: 100%; }
/* flex-basis must be 0, not auto: with `auto` the box sizes to the SVG it
   already contains, so every redraw measures the last render and the chart
   grows a little each time a scale toggle is clicked. */
.chart.chart-fill { flex: 1 1 0; min-height: 0; }
.chart svg { display: block; width: 100%; height: 100%; overflow: visible; }

/* A filling chart needs an unbroken flex column from the panel down. */
.panel-body.grow { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0; }
.chart-host-fill { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0; }
.chart .axis-line { stroke: var(--line); stroke-width: 1; }
.chart .grid-line { stroke: var(--line); stroke-width: 1; stroke-dasharray: 2 4; opacity: .55; }
.chart .appealing-quadrant {
  fill: var(--text);
  fill-opacity: .022;
  stroke: none;
}
.chart .appealing-quadrant-label {
  fill: var(--text-faint);
  fill-opacity: .72;
  font-family: var(--mono);
  font-size: 8.5px;
  font-weight: 600;
  letter-spacing: .06em;
}
.chart .axis-text { fill: var(--text-faint); font-family: var(--mono); font-size: 9.5px; }
.chart .series-line { fill: none; stroke-width: 1.4; stroke-linejoin: round;
  stroke-linecap: round; }
.chart .series-area { stroke: none; }
.chart .crosshair { stroke: var(--text-faint); stroke-width: 1; stroke-dasharray: 3 3; }
.chart .hover-dot { stroke: var(--bg); stroke-width: 1.5; }
.chart-legend {
  display: flex; flex-wrap: wrap; gap: 4px 14px; padding: 8px 2px 0;
  font-family: var(--mono); font-size: 10.5px;
}
.legend-item { display: flex; align-items: center; gap: 6px; cursor: pointer;
  color: var(--text-dim); }
.legend-item.off { opacity: .35; }
/* Picked out of the field — matches the white the series takes on the plot. */
.legend-item.lit { color: #eef2f7; }
.legend-swatch { width: 9px; height: 9px; flex: none; }
.legend-value { color: var(--text); margin-left: auto; font-variant-numeric: tabular-nums; }
.chart-readout {
  position: absolute; top: 0; right: 0; pointer-events: none;
  font-family: var(--mono); font-size: 10px; color: var(--text-dim);
  background: rgba(8, 9, 11, .9); border: 1px solid var(--line);
  padding: 5px 8px; max-width: 300px; display: none; z-index: 5;
}
.chart-readout.show { display: block; }
.chart-readout .row { display: flex; gap: 10px; justify-content: space-between; }
.chart-readout .row b { color: var(--text); font-weight: 500; }
/* Secondary reading (cache-hit rate) sits between label and price, and must not
   push the price out of alignment when only some rows carry one. */
.chart-readout .row span:nth-of-type(2) { flex: 1; }
.chart-readout .row i { color: var(--muted); font-style: normal; white-space: nowrap; }
.chart-readout .head { color: var(--amber); margin-bottom: 4px; letter-spacing: .06em; }
.chart-empty { display: grid; place-items: center; height: 100%;
  font-family: var(--mono); font-size: 11px; color: var(--text-faint);
  letter-spacing: .06em; text-transform: uppercase; }

.spark { display: inline-block; vertical-align: middle; }

/* --------------------------------------------------------------- bar cell -- */

.bar-cell { position: relative; display: block; height: 100%; }
.bar-fill { position: absolute; inset: 0 auto 0 0; background: var(--amber);
  opacity: .18; }
.bar-fill.cyan { background: var(--cyan); }
.bar-fill.up { background: var(--up); }
.bar-fill.down { background: var(--down); }
.bar-cell span { position: relative; }

/* p50 -> p99 spread. The bar starts at the median rather than at zero, so a
   provider that is usually quick but occasionally stalls reads as a long bar
   sitting far to the left -- the shape says what a single number cannot. */
.spread {
  position: relative; display: block; height: 6px; min-width: 96px;
  background: var(--bg-active);
}
.spread i {
  position: absolute; top: 0; bottom: 0;
  background: var(--amber); opacity: .5;
}

.meter { height: 4px; background: var(--bg-active); position: relative; min-width: 40px; }
.meter i { position: absolute; inset: 0 auto 0 0; background: var(--amber); }

/* ------------------------------------------------------------------ wire -- */

.wire { display: flex; flex-direction: column; }
.wire-row {
  display: grid; grid-template-columns: 74px 96px minmax(0, 1fr) auto;
  gap: 10px; align-items: baseline;
  padding: 6px 11px; border-bottom: 1px solid var(--line);
  font-family: var(--mono); font-size: 11px; cursor: pointer;
}
.wire-row:hover { background: var(--bg-hover); }
.wire-time { color: var(--text-faint); font-size: 10px; }
.wire-kind { font-size: 9px; letter-spacing: .09em; text-transform: uppercase;
  color: var(--text-faint); }
.wire-kind.price_change { color: var(--amber); }
.wire-kind.promotion { color: var(--cyan); }
.wire-kind.model_launch { color: var(--up); }
.wire-kind.model_removed { color: var(--down); }
.wire-kind.provider_policy { color: var(--violet); }
.wire-title { color: var(--text); overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }
.wire-value { color: var(--text-dim); font-size: 10.5px; }

/* --------------------------------------------------------------- palette -- */

.overlay {
  position: fixed; inset: 0; z-index: 200; background: rgba(4, 5, 7, .72);
  display: flex; align-items: flex-start; justify-content: center; padding-top: 12vh;
  backdrop-filter: blur(2px);
}
.palette { width: min(620px, 92vw); background: var(--bg-panel);
  border: 1px solid var(--line-strong); }
.palette input {
  width: 100%; border: 0; border-bottom: 1px solid var(--line);
  background: transparent; padding: 13px 15px; font-family: var(--mono);
  font-size: 14px; letter-spacing: .02em;
}
.palette-results { max-height: 52vh; overflow: auto; }
.palette-row {
  display: flex; align-items: center; gap: 11px; padding: 8px 15px;
  cursor: pointer; border-bottom: 1px solid var(--line); font-family: var(--mono);
  font-size: 12px;
}
.palette-row.active { background: var(--bg-active); }
.palette-type { font-size: 9px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--bg); background: var(--text-faint); padding: 1px 5px; flex: none; }
.palette-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.palette-detail { margin-left: auto; color: var(--text-faint); font-size: 10px;
  white-space: nowrap; }
.palette-hint { padding: 8px 15px; font-family: var(--mono); font-size: 10px;
  color: var(--text-faint); letter-spacing: .06em; }

/* ---------------------------------------------------------------- detail -- */

.detail-head {
  display: flex; align-items: flex-start; gap: 20px; flex-wrap: wrap;
  padding: 13px 14px; background: var(--bg-panel); border: 1px solid var(--line);
  margin-bottom: 10px;
}
.detail-id { min-width: 260px; flex: 1 1 420px; }
.detail-name { margin: 0; font-size: 20px; font-weight: 600; letter-spacing: -.01em; }
.detail-slug { font-family: var(--mono); font-size: 11px; color: var(--text-dim);
  margin-top: 3px; }
.detail-desc { margin: 8px 0 0; color: var(--text-dim); font-size: 12px;
  max-width: 110ch; line-height: 1.5; text-align: justify; text-align-last: left;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 8;
  overflow: hidden; }
.detail-desc a { color: var(--cyan); text-decoration: underline; text-underline-offset: 2px; }
.detail-desc code { color: var(--amber); font-size: .95em; }
.detail-stats { margin-left: auto; display: flex; gap: 1px; background: var(--line);
  border: 1px solid var(--line); flex-wrap: wrap; }
.detail-stat { background: var(--bg-panel); padding: 7px 12px; min-width: 104px; }
.detail-stat .k { font-family: var(--mono); font-size: 9px; letter-spacing: .11em;
  text-transform: uppercase; color: var(--text-faint); }
.detail-stat .v { font-family: var(--mono); font-size: 15px; margin-top: 3px;
  font-variant-numeric: tabular-nums; }

.tabs { display: flex; gap: 0; border-bottom: 1px solid var(--line);
  margin-bottom: 10px; overflow-x: auto; scrollbar-width: none; }
.tabs::-webkit-scrollbar { display: none; }
.tab {
  border: 0; background: transparent; cursor: pointer; padding: 8px 15px;
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .11em;
  text-transform: uppercase; color: var(--text-faint);
  border-bottom: 2px solid transparent; white-space: nowrap;
}
.tab:hover { color: var(--text); }
.tab.active { color: var(--amber); border-bottom-color: var(--amber); }

/* ----------------------------------------------------------------- misc --- */

.loading { display: grid; place-items: center; min-height: 46vh;
  font-family: var(--mono); font-size: 11px; letter-spacing: .16em;
  text-transform: uppercase; color: var(--text-faint); }
.loading::after { content: ""; animation: dots 1.4s steps(4, end) infinite; }
@keyframes dots { 0% { content: ""; } 25% { content: "."; } 50% { content: ".."; }
  75% { content: "..."; } }

.error-box { border: 1px solid #5a2020; background: #14090a; padding: 14px;
  font-family: var(--mono); font-size: 12px; color: #ff9a94; }

.note { font-size: 11.5px; color: var(--text-faint); line-height: 1.55;
  max-width: 92ch; }
.note strong { color: var(--text-dim); font-weight: 600; }
.note code { font-family: var(--mono); font-size: 11px; color: var(--cyan); }

.prose { font-size: 12.5px; line-height: 1.65; color: var(--text-dim); max-width: 88ch; }
.prose h4 { color: var(--text); font-size: 12px; letter-spacing: .09em;
  text-transform: uppercase; font-family: var(--mono); margin: 18px 0 7px; }
.prose p { margin: 0 0 9px; }
.prose ul { margin: 0 0 11px; padding-left: 18px; }
.prose li { margin-bottom: 4px; }
.prose a { color: var(--cyan); text-decoration: underline; text-underline-offset: 2px; }
/* Prose in a full-width panel: keep the line length readable by flowing into
   columns rather than stretching, and fall back to one column when narrow. */
.prose.columns { max-width: none; column-width: 62ch; column-gap: 30px; }
.prose.columns p { break-inside: avoid; }

/* ------------------------------------------------------------ responsive -- */

@media (max-width: 1000px) {
  .cmd-trigger { min-width: 0; }
  .cmd-trigger span { display: none; }
  .cmd-trigger::before { content: "SEARCH"; letter-spacing: .1em; }
  .detail-stats { margin-left: 0; width: 100%; }
}

@media (max-width: 700px) {
  main { padding: 10px; }
  .topbar { gap: 10px; padding: 0 10px; }
  .brand-name { font-size: 11px; }
  .clock { display: none; }
  .cmd-trigger kbd { display: none; }
  .kpis { grid-template-columns: repeat(auto-fit, minmax(132px, 1fr)); }
  .kpi-value { font-size: 17px; }
  .detail-name { font-size: 17px; }
  .wire-row { grid-template-columns: 52px minmax(0, 1fr) auto; }
  .wire-kind { display: none; }
  .panel-note { display: none; }
  .panel-tools { margin-left: 0; }
  .scroll-fill { max-height: 70vh; min-height: 300px; }
}

/* Fills the models page to the 10px frame: chrome 106 + main padding 10 +
   controls row 36 + panel head 34 + panel border 1 + bottom frame 10. */
.scroll-fill { max-height: calc(100vh - 197px); min-height: 420px; }
.scroll-240 { max-height: 240px; }
.scroll-320 { max-height: 320px; }
.scroll-420 { max-height: 420px; }
.scroll-560 { max-height: 560px; }

/* Benchmark table and scatter views are deliberately paired at the same
   depth. The table scrolls inside its panel while the chart uses the padded
   680px canvas, yielding equal outer panel heights. */
.benchmark-display-panel { height: 738px; }
.benchmark-display-panel > .panel-body { flex: 1 1 0; min-height: 0; }
.benchmark-display-panel .benchmark-table-scroll {
  height: 100%;
  max-height: none;
}
/* Gainers, decliners and the wire share one height so the three columns line up.
   Sized to show 20 mover rows without scrolling; the longer wire scrolls. */
.scroll-movers { max-height: 648px; overflow: auto; }

