/* qs-screener.css — design pass for the stock screener screen.
 *
 * Hand-authored source, not build output. Loads after visual-overhaul.css, so
 * rules here win without needing !important; reach for a higher-specificity
 * selector before reaching for the flag.
 *
 * Scope every rule to this screen. Shared token changes belong in
 * visual-overhaul.css and must be raised rather than duplicated here, so two
 * screens cannot drift apart on the same value.
 *
 * Bump the ?v=qs-screener-N key in scripts/build-static.js whenever this file changes,
 * or browsers keep serving the previous copy.
 *
 * ---------------------------------------------------------------------------
 * SPECIFICITY NOTE, read this before adding a rule.
 *
 * The screener's base styles live in a <style> block inside
 * scripts/fragments/stock-screener.html, which the component renders into the
 * BODY. This stylesheet is a <link> in the HEAD, so it loses every
 * same-specificity tie on document order. Every rule below therefore carries
 * the `.qs-scr-shell` ancestor (or `main.qs-scr-shell` for the shell itself)
 * to outrank the fragment by one selector. A bare `.qs-scr-card{...}` here
 * silently does nothing.
 * ---------------------------------------------------------------------------
 */

/* --- Tokens ---------------------------------------------------------------
 * Only the values this pass actually re-tuned, each with the measurement that
 * forced it. Everything else still comes from the fragment.
 */
main.qs-scr-shell {
  /* #66727d measured 3.88:1 on the panel and 3.76:1 on panel-2, and it carries
     9.5-11px text: the stat notes, the clearance readouts, the rank column,
     the sector tags, the axis and the whole footer. This is 5.21:1 / 5.05:1
     and still reads as the quietest ink on the screen. */
  --scr-dim: #7b8794;

  /* The sparkline is coloured by direction alone -- no glyph rides along with
     it the way one rides with the day-change label -- so the up/down pair has
     to survive colour-vision deficiency on its own. The old #23c88a against
     #ff5c68 separated by only ΔE 5.3 in deuteranopia (OKLab x100), under the
     ΔE 8 floor. Lifting the green and leaving the red alone takes the pair to
     ΔE 14.0 deutan / 35.3 normal, and raises the green's contrast on the panel
     from 8.81:1 to 12.23:1. The red is untouched on purpose: every loss
     figure on the screen is that exact red today. */
  --scr-green: #5fe6b4;

  /* The screened-out histogram bins are outline-only -- that is what the
     legend promises -- so the outline is the whole mark and has to clear the
     3:1 that WCAG asks of a meaningful graphic. #313f4b measured 1.81:1. */
  --scr-dist-line: #445769;
  --scr-dist-line-hi: #7a91a2;

  /* Hairlines, lifted just enough that a panel edge is visible without the
     page turning into a wireframe. */
  --scr-line: #1d2731;
  --scr-line-strong: #2f3d4a;
  --scr-line-quiet: #161f27;

  /* Depth. The shadow carries the page's own blue rather than neutral black,
     and the top highlight is what makes a panel read as lit from above. */
  --scr-lift: 0 1px 2px rgba(4, 9, 15, .55), 0 14px 34px -22px rgba(3, 12, 22, .95);
  --scr-lift-hi: 0 1px 2px rgba(4, 9, 15, .6), 0 20px 44px -20px rgba(3, 14, 26, 1);
  --scr-inner-top: inset 0 1px 0 rgba(190, 222, 240, .045);
  --scr-sheen: linear-gradient(180deg, rgba(174, 214, 236, .028), rgba(174, 214, 236, 0) 96px);

  --scr-dur: 150ms;
  --scr-dur-slow: 220ms;
  --scr-ease: cubic-bezier(.2, .6, .25, 1);

  /* The range input and the number input are native controls; without this
     they paint themselves from the OS light theme on some platforms. The whole
     shell is a fixed dark surface, so this is a statement of fact, not a
     preference -- if the screener ever gains a light theme this moves with it. */
  color-scheme: dark;
  /* 100vh is the iOS Safari trap: the bar collapses and the page jumps. */
  min-height: calc(100dvh - 150px);
}

/* --- Panels: give the stack one surface language ---------------------------
 * Every band on this screen was a flat fill with a near-invisible border, so
 * five stacked panels read as one undifferentiated sheet. A top sheen, an
 * inner highlight and a blue-tinted shadow are what separate them.
 */
.qs-scr-shell .qs-scr-head,
.qs-scr-shell .qs-scr-panel,
.qs-scr-shell .qs-scr-metrics,
.qs-scr-shell .qs-scr-ledger {
  background-image: var(--scr-sheen);
  box-shadow: var(--scr-inner-top), var(--scr-lift);
}

/* --- Header ---------------------------------------------------------------- */
.qs-scr-shell .qs-scr-head-lead { gap: 13px; padding: 24px 28px 26px; }

.qs-scr-shell .qs-scr-title {
  font-size: 32px;
  font-weight: 780;
  letter-spacing: -.028em;
  /* One-word last lines look like a mistake at this size. */
  text-wrap: balance;
}

/* The eyebrow and the "NONE YET" that replaces the chip row were the same
   class and so the same style, which ran them together into one string. The
   second one is a state, not a label: it stops shouting in mono caps. */
.qs-scr-shell .qs-scr-saved { gap: 7px; min-height: 26px; }
.qs-scr-shell .qs-scr-saved-label {
  color: var(--scr-dim);
  font: 600 9.5px var(--scr-mono);
  letter-spacing: .15em;
}
.qs-scr-shell .qs-scr-saved-label:not(:first-child) {
  color: var(--scr-dim);
  font: italic 400 10.5px "IBM Plex Sans", Arial, sans-serif;
  letter-spacing: 0;
  opacity: .85;
}

/* The subtitle is the query in prose, and it is the one line that says what
   the eight rows underneath actually are. It was 11px dim italic. */
.qs-scr-shell .qs-scr-head-lead .qs-scr-sentence {
  max-width: 62ch;
  color: var(--scr-soft);
  font-size: 12.5px;
  font-style: normal;
  line-height: 1.5;
  text-wrap: pretty;
}

/* The stat rail: hairline-separated cells rather than three floating blocks. */
.qs-scr-shell .qs-scr-stat { gap: 8px; padding: 22px 26px; }
.qs-scr-shell .qs-scr-stat-label {
  color: var(--scr-dim);
  font: 650 9.5px var(--scr-mono);
  letter-spacing: .15em;
}
.qs-scr-shell .qs-scr-stat-value {
  font-size: 29px;
  font-weight: 780;
  letter-spacing: -.022em;
  font-variant-numeric: tabular-nums;
}
.qs-scr-shell .qs-scr-stat-note {
  color: var(--scr-dim);
  font-size: 10.5px;
  letter-spacing: .005em;
}

/* --- Shared interactive behaviour ------------------------------------------
 * Explicit property lists, never `transition: all` -- `all` animates layout
 * properties nobody asked it to and costs a frame on every hover.
 */
.qs-scr-shell .qs-scr-chip,
.qs-scr-shell .qs-scr-chip-drop,
.qs-scr-shell .qs-scr-tab,
.qs-scr-shell .qs-scr-seg-btn,
.qs-scr-shell .qs-scr-action,
.qs-scr-shell .qs-scr-add-opt,
.qs-scr-shell .qs-scr-clear,
.qs-scr-shell .qs-scr-x,
.qs-scr-shell .qs-scr-op,
.qs-scr-shell .qs-scr-search,
.qs-scr-shell .qs-scr-num,
.qs-scr-shell .qs-scr-row,
.qs-scr-shell .qs-scr-gcard,
.qs-scr-shell .qs-scr-dist-bar {
  transition:
    color var(--scr-dur) var(--scr-ease),
    background-color var(--scr-dur) var(--scr-ease),
    border-color var(--scr-dur) var(--scr-ease),
    box-shadow var(--scr-dur) var(--scr-ease),
    transform var(--scr-dur) var(--scr-ease);
}

/* A pressed control should feel like it took the press. */
.qs-scr-shell .qs-scr-chip:active,
.qs-scr-shell .qs-scr-tab:active,
.qs-scr-shell .qs-scr-seg-btn:active,
.qs-scr-shell .qs-scr-action:active,
.qs-scr-shell .qs-scr-add-opt:active,
.qs-scr-shell .qs-scr-gcard:active { transform: translateY(1px); }

/* The fragment's focus rule missed the add-criterion chips, CLEAR QUERY, the
   threshold number field, the grid cards, the saved-screen delete and the
   ledger's scroll region -- all reachable by Tab, none of them showing it. */
.qs-scr-shell .qs-scr-add-opt:focus-visible,
.qs-scr-shell .qs-scr-clear:focus-visible,
.qs-scr-shell .qs-scr-num:focus-visible,
.qs-scr-shell .qs-scr-gcard:focus-visible,
.qs-scr-shell .qs-scr-chip-drop:focus-visible,
.qs-scr-shell .qs-scr-ledgerwrap:focus-visible,
.qs-scr-shell .qs-scr-dist-bar:focus-visible {
  outline: 2px solid var(--scr-focus);
  outline-offset: 2px;
}

/* --- Saved-screen chips ----------------------------------------------------
 * Now a name button and a delete button side by side (see the fragment). The
 * pair is drawn as one chip so the split is invisible until you reach for it.
 */
.qs-scr-shell .qs-scr-chipset {
  display: inline-flex;
  align-items: stretch;
  border: 1px solid var(--scr-line-strong);
  border-radius: 5px;
  background: transparent;
  transition: border-color var(--scr-dur) var(--scr-ease), background-color var(--scr-dur) var(--scr-ease);
}
.qs-scr-shell .qs-scr-chipset:hover { border-color: #46596a; background: #111a22; }
.qs-scr-shell .qs-scr-chipset:has(.qs-scr-chip[data-active="true"]) {
  border-color: var(--scr-cyan);
  background: var(--scr-cyan-fill);
}
.qs-scr-shell .qs-scr-chipset .qs-scr-chip {
  border: 0;
  border-radius: 4px 0 0 4px;
  background: transparent;
  padding: 4px 4px 4px 11px;
}
.qs-scr-shell .qs-scr-chipset .qs-scr-chip:hover { background: transparent; }
.qs-scr-shell .qs-scr-chip[data-active="true"] { color: var(--scr-text); }
.qs-scr-shell .qs-scr-chip-drop {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 24px;
  margin: 0;
  padding: 0 7px 0 5px;
  color: var(--scr-dim);
  background: transparent;
  border: 0;
  border-radius: 0 4px 4px 0;
  cursor: pointer;
  font-size: 10px;
  line-height: 1;
}
.qs-scr-shell .qs-scr-chip-drop:hover { color: var(--scr-red); background: rgba(255, 92, 104, .12); }

/* --- Query bar ------------------------------------------------------------- */
.qs-scr-shell .qs-scr-query { gap: 11px; padding: 15px 24px; }
.qs-scr-shell .qs-scr-query-label,
.qs-scr-shell .qs-scr-add-count,
.qs-scr-shell .qs-scr-card-label { letter-spacing: .14em; }

.qs-scr-shell .qs-scr-tabs {
  gap: 1px;
  padding: 2px;
  border: 1px solid var(--scr-line-quiet);
  border-radius: 6px;
  background: rgba(0, 0, 0, .22);
}
.qs-scr-shell .qs-scr-tab { border-radius: 4px; letter-spacing: .09em; }
.qs-scr-shell .qs-scr-tab-count {
  margin-left: 7px;
  font-variant-numeric: tabular-nums;
}

/* An empty bucket was dimmed to opacity .45, which took a live, clickable
   control down to 2.15:1 against the panel. The count already says the bucket
   is empty; the label does not also have to be unreadable to say it. */
.qs-scr-shell .qs-scr-tab[data-zero="true"] { opacity: 1; color: var(--scr-dim); }
.qs-scr-shell .qs-scr-tab[data-zero="true"] .qs-scr-tab-count { color: var(--scr-dim); }
.qs-scr-shell .qs-scr-tab[data-zero="true"]:hover,
.qs-scr-shell .qs-scr-tab[data-zero="true"]:focus-visible { color: var(--scr-text); }

.qs-scr-shell .qs-scr-search {
  width: 216px;
  height: 32px;
  border-radius: 5px;
  background: rgba(0, 0, 0, .22);
}
.qs-scr-shell .qs-scr-search:hover { border-color: #46596a; }
.qs-scr-shell .qs-scr-search:focus { border-color: var(--scr-cyan); background: #0a1219; }

/* The layout toggle and SAVE SCREEN were both a solid cyan fill, so a view
   preference and the screen's one committing action carried identical weight.
   The selected segment now reads as raised rather than primary, which leaves
   exactly one filled button on the screen. */
.qs-scr-shell .qs-scr-seg {
  gap: 1px;
  padding: 2px;
  border-color: var(--scr-line-quiet);
  border-radius: 6px;
  background: rgba(0, 0, 0, .22);
}
.qs-scr-shell .qs-scr-seg-btn { border-radius: 4px; }
.qs-scr-shell .qs-scr-seg-btn:hover { color: var(--scr-soft); }
.qs-scr-shell .qs-scr-seg-btn[data-active="true"] {
  color: var(--scr-text);
  background: #1a2732;
  box-shadow: inset 0 1px 0 rgba(190, 222, 240, .08), 0 1px 2px rgba(0, 0, 0, .45);
}
.qs-scr-shell .qs-scr-seg-btn[data-active="true"]:hover { color: var(--scr-text); }

.qs-scr-shell .qs-scr-actions { gap: 7px; }
.qs-scr-shell .qs-scr-action { border-radius: 5px; }
.qs-scr-shell .qs-scr-action-primary { box-shadow: 0 1px 0 rgba(190, 222, 240, .18) inset, 0 6px 16px -8px rgba(98, 195, 217, .55); }
.qs-scr-shell .qs-scr-action-primary:hover { box-shadow: 0 1px 0 rgba(255, 255, 255, .22) inset, 0 8px 20px -8px rgba(98, 195, 217, .7); }

/* --- Criteria cells: the signature of this screen --------------------------
 * Four ruled cells, each one a threshold you can drag and a statement of how
 * much of the universe that threshold lets through. Everything here is in
 * service of keeping those two things -- the control and its consequence --
 * from looking like the same object.
 */
.qs-scr-shell .qs-scr-card {
  position: relative;
  padding: 16px 20px 18px;
  transition: background-color var(--scr-dur) var(--scr-ease);
}
.qs-scr-shell .qs-scr-card:hover { background: rgba(147, 197, 224, .022); }
/* The cell you are editing, marked on its leading edge. */
.qs-scr-shell .qs-scr-card:focus-within { background: rgba(98, 195, 217, .045); }
.qs-scr-shell .qs-scr-card::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 2px;
  background: var(--scr-cyan);
  opacity: 0;
  transition: opacity var(--scr-dur) var(--scr-ease);
}
.qs-scr-shell .qs-scr-card:focus-within::before { opacity: 1; }

.qs-scr-shell .qs-scr-card-label { color: var(--scr-muted); font-weight: 650; }

/* 16x16 is under every touch-target minimum going. The hit area grows to 26px
   without moving anything, because the growth is padding cancelled by margin. */
.qs-scr-shell .qs-scr-x {
  width: 26px;
  height: 26px;
  margin: -5px -6px -5px 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 4px;
  font-size: 11px;
}
.qs-scr-shell .qs-scr-x:hover { color: var(--scr-red); background: rgba(255, 92, 104, .12); }

.qs-scr-shell .qs-scr-card-row { gap: 8px; margin-top: 12px; }

/* The operator flips between >= and <= on click and gave no sign it could be
   clicked at all. It is now a real target with a resting outline. */
.qs-scr-shell .qs-scr-op {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 26px;
  height: 26px;
  padding: 0 5px;
  align-self: center;
  border: 1px solid transparent;
  border-radius: 5px;
  font-size: 14px;
  line-height: 1;
}
.qs-scr-shell .qs-scr-op:hover { color: var(--scr-cyan-hi); border-color: var(--scr-line-strong); background: rgba(98, 195, 217, .1); }

.qs-scr-shell .qs-scr-num {
  padding: 1px 0 3px;
  border-bottom: 1px solid transparent;
  font: 780 22px "IBM Plex Sans", Arial, sans-serif;
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
}
.qs-scr-shell .qs-scr-num:hover { border-bottom-color: var(--scr-line-strong); }
.qs-scr-shell .qs-scr-num:focus { border-bottom-color: var(--scr-cyan); outline: none; }
.qs-scr-shell .qs-scr-num:focus-visible { outline: 2px solid var(--scr-focus); outline-offset: 3px; }
/* The slider is the coarse control and the field is the exact one; spinners
   are a third way to do the same job, one pixel wide. */
.qs-scr-shell .qs-scr-num::-webkit-outer-spin-button,
.qs-scr-shell .qs-scr-num::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.qs-scr-shell .qs-scr-num { -moz-appearance: textfield; appearance: textfield; }

.qs-scr-shell .qs-scr-unit { color: var(--scr-muted); font-size: 12.5px; font-weight: 650; }

/* The slider: a 2px track with a 9px dot was a hairline sitting 11px above
   another hairline, and the other one is not draggable. This one is thicker,
   rounded, and its thumb carries a ring on hover and focus. */
.qs-scr-shell .qs-scr-slider { height: 18px; margin-top: 10px; }
.qs-scr-shell .qs-scr-slider::-webkit-slider-runnable-track {
  height: 4px;
  border-radius: 3px;
  background: linear-gradient(180deg, #0a1017, #26323d);
  box-shadow: inset 0 1px 1px rgba(0, 0, 0, .55);
}
.qs-scr-shell .qs-scr-slider::-moz-range-track {
  height: 4px;
  border-radius: 3px;
  background: linear-gradient(180deg, #0a1017, #26323d);
  box-shadow: inset 0 1px 1px rgba(0, 0, 0, .55);
}
.qs-scr-shell .qs-scr-slider::-webkit-slider-thumb {
  width: 13px;
  height: 13px;
  margin-top: -4.5px;
  background: var(--scr-text);
  border-radius: 50%;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .7), 0 0 0 0 rgba(98, 195, 217, .35);
  transition: box-shadow var(--scr-dur) var(--scr-ease), background-color var(--scr-dur) var(--scr-ease);
}
.qs-scr-shell .qs-scr-slider::-moz-range-thumb {
  width: 13px;
  height: 13px;
  background: var(--scr-text);
  border: 0;
  border-radius: 50%;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .7), 0 0 0 0 rgba(98, 195, 217, .35);
  transition: box-shadow var(--scr-dur) var(--scr-ease), background-color var(--scr-dur) var(--scr-ease);
}
.qs-scr-shell .qs-scr-slider:hover::-webkit-slider-thumb { box-shadow: 0 1px 3px rgba(0, 0, 0, .7), 0 0 0 5px rgba(98, 195, 217, .2); }
.qs-scr-shell .qs-scr-slider:hover::-moz-range-thumb { box-shadow: 0 1px 3px rgba(0, 0, 0, .7), 0 0 0 5px rgba(98, 195, 217, .2); }
.qs-scr-shell .qs-scr-slider:focus-visible::-webkit-slider-thumb { background: var(--scr-cyan-hi); box-shadow: 0 1px 3px rgba(0, 0, 0, .7), 0 0 0 5px rgba(98, 195, 217, .3); }
.qs-scr-shell .qs-scr-slider:focus-visible::-moz-range-thumb { background: var(--scr-cyan-hi); box-shadow: 0 1px 3px rgba(0, 0, 0, .7), 0 0 0 5px rgba(98, 195, 217, .3); }
.qs-scr-shell .qs-scr-slider:focus-visible { outline: none; }
.qs-scr-shell .qs-scr-slider:focus-visible ~ .qs-scr-clears .qs-scr-clears-note { color: var(--scr-soft); }

/* The clearance readout. It was a second thin rounded track parked directly
   under the slider's thin rounded track, in the same colour, and the eye read
   the pair as two sliders. Segmenting it into ten cells is what tells them
   apart: a gauge is stepped, a control is continuous. */
.qs-scr-shell .qs-scr-clears { gap: 10px; margin-top: 14px; }
.qs-scr-shell .qs-scr-clears-track {
  height: 6px;
  border-radius: 1px;
  background: var(--scr-line-quiet);
  box-shadow: inset 0 0 0 1px rgba(120, 150, 172, .1);
  /* Ten cells with a surface gap between them, so the meter is countable. */
  -webkit-mask-image: repeating-linear-gradient(90deg, #000 0 calc(10% - 2px), transparent calc(10% - 2px) 10%);
  mask-image: repeating-linear-gradient(90deg, #000 0 calc(10% - 2px), transparent calc(10% - 2px) 10%);
}
.qs-scr-shell .qs-scr-clears-fill {
  border-radius: 1px;
  background: var(--scr-dist-fill);
  transition: width var(--scr-dur-slow) var(--scr-ease);
}
.qs-scr-shell .qs-scr-clears-note {
  min-width: 74px;
  color: var(--scr-dim);
  font: 500 10px var(--scr-mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: .02em;
  text-align: right;
}

/* --- Add criterion --------------------------------------------------------- */
.qs-scr-shell .qs-scr-add { gap: 12px; padding: 16px 20px 18px; }
.qs-scr-shell .qs-scr-add-count { color: var(--scr-dim); font-weight: 650; }
.qs-scr-shell .qs-scr-add-menu { gap: 5px; }
.qs-scr-shell .qs-scr-add-opt {
  padding: 5px 8px;
  color: var(--scr-muted);
  border-style: dashed;
  border-color: #2a3742;
  border-radius: 5px;
  letter-spacing: .07em;
}
.qs-scr-shell .qs-scr-add-opt:hover { color: var(--scr-text); border-style: solid; border-color: var(--scr-cyan); background: var(--scr-cyan-fill); }

/* --- Query summary --------------------------------------------------------- */
.qs-scr-shell .qs-scr-summary { padding: 13px 24px; border-top: 1px solid var(--scr-line-quiet); }
/* The header already carries this sentence as the screen's subtitle. Here it
   is a confirmation of the edit just made, so it stays a footnote. */
.qs-scr-shell .qs-scr-summary .qs-scr-sentence { color: var(--scr-dim); font-size: 10.5px; }
.qs-scr-shell .qs-scr-clear { padding: 4px 2px; border-radius: 3px; }
.qs-scr-shell .qs-scr-clear:hover { color: var(--scr-cyan-hi); }

/* --- Metrics panel ---------------------------------------------------------
 * It arrived with a 6px radius, a brighter border and tighter padding than
 * every other band, so it read as a control panel bolted onto the page rather
 * than a section of it.
 */
.qs-scr-shell .qs-scr-metrics {
  padding: 18px 24px 20px;
  border-color: var(--scr-line);
  border-radius: 10px;
}
.qs-scr-shell .qs-scr-metrics-head { margin-bottom: 16px; padding-bottom: 14px; border-bottom: 1px solid var(--scr-line); }
.qs-scr-shell .qs-scr-metrics-title { font-size: 11px; letter-spacing: .12em; font-family: var(--scr-mono); font-weight: 650; }
/* Ruled like the criteria row above it, so the five readings are one strip. */
.qs-scr-shell .qs-scr-metrics-grid { gap: 0; }
.qs-scr-shell .qs-scr-metrics-grid > * { padding: 2px 20px; border-right: 1px solid var(--scr-line); }
.qs-scr-shell .qs-scr-metrics-grid > :first-child { padding-left: 0; }
.qs-scr-shell .qs-scr-metrics-grid > :last-child { border-right: 0; }
.qs-scr-shell .qs-scr-metric-label { color: var(--scr-dim); font-size: 9px; letter-spacing: .13em; }
.qs-scr-shell .qs-scr-metric-value { margin-top: 8px; font-size: 20px; font-weight: 780; letter-spacing: -.02em; }
.qs-scr-shell .qs-scr-metrics-note { margin-top: 16px; padding-top: 13px; max-width: 96ch; color: var(--scr-dim); font-size: 10.5px; }

/* --- Distribution ----------------------------------------------------------
 * The only band on the page with no housing, so the stack went panel, panel,
 * bare chart, panel. It is a section like the others now.
 */
.qs-scr-shell .qs-scr-dist {
  margin-top: 20px;
  padding: 16px 24px 18px;
  background: var(--scr-panel);
  background-image: var(--scr-sheen);
  border: 1px solid var(--scr-line);
  border-radius: 10px;
  box-shadow: var(--scr-inner-top), var(--scr-lift);
}
.qs-scr-shell .qs-scr-dist-head { padding-bottom: 13px; border-bottom: 1px solid var(--scr-line); }
.qs-scr-shell .qs-scr-dist-label { color: var(--scr-dim); font-family: var(--scr-mono); font-size: 9.5px; font-weight: 650; letter-spacing: .13em; }
.qs-scr-shell .qs-scr-dist-head .qs-scr-dist-label:last-child { color: var(--scr-dim); font-weight: 500; letter-spacing: .08em; }

/* Bars had no line to stand on, so 24 of them floated at 24 different heights
   and the empty bins read as damage rather than as zero. */
.qs-scr-shell .qs-scr-dist-plot {
  height: 76px;
  margin-top: 16px;
  gap: 3px;
  padding-bottom: 1px;
  border-bottom: 1px solid var(--scr-line-strong);
}
.qs-scr-shell .qs-scr-dist-bar {
  border-radius: 3px 3px 0 0;
  /* Screened-out bins stay genuinely hollow: the legend promises outline for
     screened out and fill for matched, and a wash inside the outline would
     make the legend false. The outline itself was 1.81:1 against the page,
     which is what made them look empty rather than unmatched. */
  border-color: var(--scr-dist-line);
}
.qs-scr-shell .qs-scr-dist-bar:hover { border-color: var(--scr-dist-line-hi); }
.qs-scr-shell .qs-scr-dist-bar[data-matched="true"]:hover { background: var(--scr-cyan); border-color: var(--scr-cyan); }

/* The axis row is a min / median / max readout, not three positioned
   annotations -- flexbox parks the middle cell dead centre regardless of where
   the median actually falls, and an unlabelled figure sitting at the centre of
   an axis claims a position it does not have. Naming all three ends that
   claim. The words are generated content, so innerText and the assertions in
   screener-browser-smoke.py still see exactly the bound values. */
.qs-scr-shell .qs-scr-dist-axis { margin-top: 9px; font-size: 9.5px; letter-spacing: .04em; }
.qs-scr-shell .qs-scr-dist-axis > span:first-child::before { content: "MIN "; color: var(--scr-dim); }
.qs-scr-shell .qs-scr-dist-axis > span:last-child::before { content: "MAX "; color: var(--scr-dim); }
.qs-scr-shell .qs-scr-dist-median { color: var(--scr-soft); font-weight: 650; }

/* --- Loading --------------------------------------------------------------
 * Four identical grey bars told you nothing about what was coming. These are
 * shaped like the ledger that replaces them.
 */
.qs-scr-shell .qs-scr-skeleton {
  height: 52px;
  margin: 0 34px;
  background: linear-gradient(90deg, #0d1620 0%, #16222d 42%, #0d1620 84%);
  background-size: 220% 100%;
  border: 1px solid var(--scr-line);
  border-radius: 0;
  animation: qsScrSweep 1.5s var(--scr-ease) infinite;
}
.qs-scr-shell .qs-scr-skeleton:first-child { margin-top: 22px; border-radius: 10px 10px 0 0; }
.qs-scr-shell .qs-scr-skeleton:last-child { border-radius: 0 0 10px 10px; }
.qs-scr-shell .qs-scr-skeleton + .qs-scr-skeleton { border-top: 0; }
.qs-scr-shell .qs-scr-skeleton:nth-child(2) { animation-delay: .1s; }
.qs-scr-shell .qs-scr-skeleton:nth-child(3) { animation-delay: .2s; }
.qs-scr-shell .qs-scr-skeleton:nth-child(4) { animation-delay: .3s; }
@keyframes qsScrSweep {
  0% { background-position: 130% 0; }
  100% { background-position: -30% 0; }
}

/* --- Notices --------------------------------------------------------------- */
.qs-scr-shell .qs-scr-alert,
.qs-scr-shell .qs-scr-stale {
  display: flex;
  gap: 9px;
  align-items: flex-start;
  padding: 11px 14px;
  border-radius: 7px;
  box-shadow: var(--scr-lift);
}
.qs-scr-shell .qs-scr-alert::before { content: "!"; }
.qs-scr-shell .qs-scr-stale::before { content: "*"; }
.qs-scr-shell .qs-scr-alert::before,
.qs-scr-shell .qs-scr-stale::before {
  flex: none;
  width: 15px;
  height: 15px;
  margin-top: .5px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid currentColor;
  border-radius: 50%;
  font: 700 9px var(--scr-mono);
  opacity: .8;
}

/* --- Results ledger -------------------------------------------------------- */
.qs-scr-shell .qs-scr-ledgerwrap {
  margin-top: 20px;
  border-radius: 10px;
  /* A horizontal swipe on the ledger must not trigger the browser's back
     gesture on the page behind it. */
  overscroll-behavior-x: contain;
}
.qs-scr-shell .qs-scr-ledger { border-radius: 10px; }

.qs-scr-shell .qs-scr-lhead {
  padding: 13px 26px 12px;
  background: linear-gradient(180deg, #121a23, #0d141c);
  color: var(--scr-dim);
  letter-spacing: .13em;
}
/* The threshold under a column head is the live query, not a caption. Drawn as
   a chip so the filtered columns are countable at a glance. */
.qs-scr-shell .qs-scr-th-note {
  display: block;
  width: fit-content;
  margin-top: 6px;
  margin-left: auto;
  padding: 2px 6px;
  color: var(--scr-cyan);
  background: var(--scr-cyan-fill);
  border-radius: 3px;
  font-family: var(--scr-mono);
  font-size: 9px;
  letter-spacing: .05em;
  font-variant-numeric: tabular-nums;
}

.qs-scr-shell .qs-scr-row {
  position: relative;
  padding: 12px 26px;
  border-bottom-color: var(--scr-line-quiet);
}
/* The hover and selected marker. transform-driven, so it composites. */
.qs-scr-shell .qs-scr-row::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 2px;
  background: var(--scr-cyan);
  transform: scaleY(0);
  transform-origin: center;
  transition: transform var(--scr-dur) var(--scr-ease);
}
.qs-scr-shell .qs-scr-row:hover { background: rgba(147, 197, 224, .035); }
.qs-scr-shell .qs-scr-row:hover::before { transform: scaleY(.55); }
/* An open row and its detail are one object. The cyan was a rule BETWEEN them,
   which is the one place a divider says they are two. */
.qs-scr-shell .qs-scr-row[data-open="true"] {
  background: #111c26;
  border-bottom-color: transparent;
}
.qs-scr-shell .qs-scr-row[data-open="true"]::before { transform: scaleY(1); }
.qs-scr-shell .qs-scr-row[data-open="true"] .qs-scr-sym { color: var(--scr-cyan-hi); }

.qs-scr-shell .qs-scr-rank { color: var(--scr-dim); font-size: 10.5px; letter-spacing: .06em; }
.qs-scr-shell .qs-scr-sym { font-size: 14.5px; font-weight: 720; letter-spacing: .015em; }
.qs-scr-shell .qs-scr-sector { color: var(--scr-dim); font-size: 9px; letter-spacing: .1em; }
.qs-scr-shell .qs-scr-name { color: var(--scr-muted); font-size: 10.5px; }
.qs-scr-shell .qs-scr-price { font-size: 13.5px; font-weight: 550; letter-spacing: -.005em; }
.qs-scr-shell .qs-scr-chg { font-size: 10.5px; letter-spacing: .01em; }

.qs-scr-shell .qs-scr-spark polyline { stroke-linecap: round; }

/* The magnitude bar under a right-aligned figure was filling from the LEFT
   edge of the column, so on a wide column the number sat at one end and its
   own bar started at the other. It now grows out from underneath the figure it
   belongs to. */
.qs-scr-shell .qs-scr-bar {
  display: flex;
  justify-content: flex-end;
  height: 3px;
  margin-top: 5px;
  background: var(--scr-line-quiet);
  box-shadow: inset 0 0 0 1px rgba(120, 150, 172, .08);
}
.qs-scr-shell .qs-scr-bar-fill { transition: width var(--scr-dur-slow) var(--scr-ease); }

.qs-scr-shell .qs-scr-more { color: var(--scr-dim); font-size: 10.5px; }

/* --- Row detail ------------------------------------------------------------ */
.qs-scr-shell .qs-scr-detail {
  position: relative;
  padding: 0 26px 24px;
  background: #0b141d;
  border-bottom-color: var(--scr-line);
  box-shadow: inset 0 10px 14px -12px rgba(0, 0, 0, .8);
}
/* Same leading edge as the row above, unbroken, so the two read as one card. */
.qs-scr-shell .qs-scr-detail::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 2px;
  background: var(--scr-cyan);
}
.qs-scr-shell .qs-scr-detail-grid { padding-top: 20px; }
.qs-scr-shell .qs-scr-detail-head { font-family: var(--scr-mono); font-size: 9px; letter-spacing: .14em; }
.qs-scr-shell .qs-scr-detail-line { margin-top: 12px; }
.qs-scr-shell .qs-scr-detail-key { color: var(--scr-muted); font-size: 11px; }
.qs-scr-shell .qs-scr-detail-val { font-size: 11.5px; }
.qs-scr-shell .qs-scr-detail-foot { gap: 9px; margin-top: 22px; padding-top: 16px; border-top: 1px solid var(--scr-line); }
.qs-scr-shell .qs-scr-detail-clears { color: var(--scr-dim); font-size: 10.5px; }
.qs-scr-shell .qs-scr-detail-foot .qs-scr-action[aria-pressed="true"] {
  color: var(--scr-cyan);
  border-color: var(--scr-cyan);
  background: var(--scr-cyan-fill);
}

/* --- Grid layout -----------------------------------------------------------
 * gap:1px between cards that each carried their own 1px border drew every
 * interior division as a 3px double rule, and three metrics in a two-column
 * grid left the third alone beside a hole.
 */
.qs-scr-shell .qs-scr-grid { gap: 12px; margin-top: 20px; }
.qs-scr-shell .qs-scr-gcard {
  padding: 16px 17px 17px;
  border-radius: 8px;
  background-image: var(--scr-sheen);
  box-shadow: var(--scr-inner-top), var(--scr-lift);
}
.qs-scr-shell .qs-scr-gcard:hover {
  border-color: var(--scr-line-strong);
  background-color: #101a24;
  box-shadow: var(--scr-inner-top), var(--scr-lift-hi);
  transform: translateY(-1px);
}
.qs-scr-shell .qs-scr-gcard .qs-scr-name { margin-top: 4px; }
.qs-scr-shell .qs-scr-gcard .qs-scr-chg { margin-top: 6px; }
.qs-scr-shell .qs-scr-gcard-metrics {
  gap: 12px 14px;
  margin-top: 15px;
  padding-top: 13px;
  border-top: 1px solid var(--scr-line);
}
/* An odd last metric takes the full row instead of orphaning. */
.qs-scr-shell .qs-scr-gcard-metrics > :last-child:nth-child(odd) { grid-column: 1 / -1; }
.qs-scr-shell .qs-scr-gcard .qs-scr-cell-val { margin-top: 5px; font-size: 13px; }

/* --- Empty state -----------------------------------------------------------
 * Two lines of centred text on the page background. It is a section of the
 * page like every other one now, and it says what state it is in before it
 * says what to do about it.
 */
.qs-scr-shell .qs-scr-empty {
  margin: 22px 34px 0;
  padding: 54px 28px 56px;
  background: rgba(11, 16, 23, .55);
  border: 1px dashed #253340;
  border-radius: 10px;
}
.qs-scr-shell .qs-scr-empty::before {
  content: "NO MATCHES IN VIEW";
  display: block;
  margin-bottom: 16px;
  color: var(--scr-dim);
  font: 650 9.5px var(--scr-mono);
  letter-spacing: .19em;
}
.qs-scr-shell .qs-scr-empty-title {
  font-size: 17px;
  font-weight: 720;
  letter-spacing: -.015em;
  text-wrap: balance;
}
.qs-scr-shell .qs-scr-empty-copy {
  max-width: 46ch;
  margin: 10px auto 0;
  color: var(--scr-muted);
  font-size: 12.5px;
  line-height: 1.55;
  text-wrap: pretty;
}

/* --- Footer ---------------------------------------------------------------- */
.qs-scr-shell .qs-scr-foot { margin-top: 26px; padding-top: 17px; color: var(--scr-dim); font-size: 10.5px; }
.qs-scr-shell .qs-scr-keys { gap: 18px; }
.qs-scr-shell .qs-scr-kbd {
  min-width: 19px;
  height: 19px;
  color: var(--scr-soft);
  background: linear-gradient(180deg, #131c25, #0c141b);
  border-color: var(--scr-line-strong);
  border-radius: 4px;
  box-shadow: 0 1px 0 rgba(0, 0, 0, .6), inset 0 1px 0 rgba(190, 222, 240, .07);
  font: 600 9.5px var(--scr-mono);
}

/* --- Narrow ---------------------------------------------------------------- */
@media (max-width: 900px) {
  .qs-scr-shell .qs-scr-title { font-size: 27px; }
  .qs-scr-shell .qs-scr-head-lead { padding: 20px 20px 18px; }
  .qs-scr-shell .qs-scr-stat { padding: 16px 20px; }
  .qs-scr-shell .qs-scr-stat-value { font-size: 23px; }
  .qs-scr-shell .qs-scr-head,
  .qs-scr-shell .qs-scr-panel,
  .qs-scr-shell .qs-scr-dist,
  .qs-scr-shell .qs-scr-foot,
  .qs-scr-shell .qs-scr-metrics,
  .qs-scr-shell .qs-scr-empty,
  .qs-scr-shell .qs-scr-skeleton { margin-left: 18px; margin-right: 18px; }
  .qs-scr-shell .qs-scr-query,
  .qs-scr-shell .qs-scr-summary { padding-left: 18px; padding-right: 18px; }
  .qs-scr-shell .qs-scr-dist { padding-left: 18px; padding-right: 18px; }

  /* The search is the only way to find a name in a long match list, and it was
     a 216px island in a full-width row. */
  .qs-scr-shell .qs-scr-search { width: 100%; flex: 1 1 100%; }
  .qs-scr-shell .qs-scr-seg,
  .qs-scr-shell .qs-scr-actions { flex: 1 1 auto; }
  .qs-scr-shell .qs-scr-seg-btn { flex: 1; }
  .qs-scr-shell .qs-scr-actions .qs-scr-action { flex: 1 1 auto; }

  /* Nine stacked chips in a half-width cell towered over the criterion cell
     beside it and left a column of dead space under it. Across the full width
     they flow. */
  .qs-scr-shell .qs-scr-add { grid-column: 1 / -1; border-right: 0; }
  .qs-scr-shell .qs-scr-criteria > :nth-last-child(2):nth-child(odd) { border-right: 0; }

  .qs-scr-shell .qs-scr-dist-head { flex-direction: column; align-items: flex-start; gap: 5px; }
  .qs-scr-shell .qs-scr-dist-plot { height: 62px; gap: 2px; }

  .qs-scr-shell .qs-scr-metrics-grid > * { padding: 2px 0; border-right: 0; }

  /* Two criterion cells across a phone leave the meter about 40px, and ten
     cells in 40px is a dotted line rather than something countable. Five
     wider cells still read as a gauge. */
  .qs-scr-shell .qs-scr-clears { gap: 8px; }
  .qs-scr-shell .qs-scr-clears-track {
    -webkit-mask-image: repeating-linear-gradient(90deg, #000 0 calc(20% - 2px), transparent calc(20% - 2px) 20%);
    mask-image: repeating-linear-gradient(90deg, #000 0 calc(20% - 2px), transparent calc(20% - 2px) 20%);
  }
  .qs-scr-shell .qs-scr-clears-note { min-width: 0; }

  .qs-scr-shell .qs-scr-detail-col { padding: 0 0 16px; border-right: 0; border-bottom: 1px solid var(--scr-line); }
  .qs-scr-shell .qs-scr-detail-col:last-child { border-bottom: 0; padding-bottom: 0; }
  .qs-scr-shell .qs-scr-detail-grid { gap: 16px; }
}

/* The ledger's own min-width is 920px, so below roughly this it always
   overflows its container. The fade is gated to exactly that range: at full
   width there is nothing to scroll and a permanent fade would just clip the
   last column. */
@media (max-width: 987px) {
  .qs-scr-shell .qs-scr-ledgerwrap {
    margin-left: 18px;
    margin-right: 18px;
    -webkit-mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 26px), transparent 100%);
    mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 26px), transparent 100%);
  }
  /* A mask clips the focus ring, so the region shows focus with a shadow. */
  .qs-scr-shell .qs-scr-ledgerwrap:focus-visible {
    outline: none;
    box-shadow: inset 0 0 0 2px var(--scr-focus);
    border-radius: 10px;
  }
}

/* --- Motion ---------------------------------------------------------------
 * Everything above animates colour, shadow, opacity, transform or a bar's
 * width. Under a reduced-motion preference all of it resolves instantly; the
 * states themselves stay, because they are how the screen says what is
 * selected.
 */
@media (prefers-reduced-motion: reduce) {
  .qs-scr-shell .qs-scr-skeleton { animation: none; background: #16222d; }
  .qs-scr-shell *,
  .qs-scr-shell *::before,
  .qs-scr-shell *::after {
    transition-duration: 1ms;
    animation-duration: 1ms;
    animation-iteration-count: 1;
  }
  .qs-scr-shell .qs-scr-gcard:hover { transform: none; }
}
