/* ------------------------------------------------------------------ *
 * Premarket Scanner - dark terminal styling.
 * No external fonts or assets: everything here ships inside the Worker.
 * ------------------------------------------------------------------ */

:root {
  --bg: #101220;
  --panel: #141625;
  --surface: #161828;
  --raised: #191b2c;
  --row-hover: #1a1d2e;
  --border: #262a3d;
  --border-soft: #1d2031;
  --line: #23263a;
  --field: #1b1e2f;
  --field-border: #303449;

  --text: #e9e9ed;
  --n100: #f3f5fe;
  --n200: #e4e7f5;
  --n300: #cfd3e5;
  --n400: #b2b6ca;
  --n500: #9397ab;
  --n600: #75798c;
  --n700: #595d6c;
  --n800: #3f424d;

  --bull: #3ddc97;
  --bull-dim: #1e5238;
  --bull-bg: #12291f;
  --bear: #f2555a;
  --bear-dim: #5c2429;
  --bear-bg: #2b1518;
  --warn: #d8a13c;
  --warn-dim: #5a4820;
  --warn-bg: #2a2314;
  --info: #7fb6d8;
  --info-dim: #22465c;
  --accent: #9184d9;
  --accent-400: #b5abfc;
  --accent-700: #5d5294;
  --accent-bg: #232043;

  --mono: ui-monospace, SFMono-Regular, "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;
  --sans: system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

*, *::before, *::after { box-sizing: border-box; }

html, body { height: 100%; }

/*
 * The `hidden` attribute is styled `display: none` by the UA stylesheet ONLY,
 * so any author rule that sets `display` beats it. Three panels here set
 * `display: grid` / `display: flex` on their own class, which made
 * `element.hidden = true` a no-op: they stayed on screen permanently once
 * rendered, and every toggle in the app looked broken. `!important` is the
 * correct tool for exactly this - `hidden` is meant to be non-negotiable.
 */
[hidden] { display: none !important; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--sans);
  font-size: 13px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

/*
 * ONE scrollport: the page. This used to be a locked 100vh flex column with
 * `overflow: hidden`, which forced .summary and .tablewrap to grow their own
 * scrollbars - so the wheel did something different depending on which strip of
 * the window the pointer happened to be over. The only nested scroll left is
 * the table's HORIZONTAL one, which is unavoidable at 1634px of columns.
 */
#app { display: flex; flex-direction: column; min-height: 100vh; }

button, input, select { font: inherit; color: inherit; }
button { cursor: pointer; }
a { color: var(--accent); text-underline-offset: 3px; }
a:hover { color: var(--accent-400); }

::-webkit-scrollbar { height: 10px; width: 10px; }
::-webkit-scrollbar-thumb { background: var(--n800); border-radius: 6px; }
::-webkit-scrollbar-thumb:hover { background: var(--n700); }
::-webkit-scrollbar-track { background: var(--raised); }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

.mono { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.pos { color: var(--bull); }
.neg { color: var(--bear); }
.muted { color: var(--n600); }
.nowrap { white-space: nowrap; }
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

@keyframes flashcell { from { opacity: .55; } to { opacity: 0; } }
@keyframes pulsedot { 0%, 100% { opacity: 1; } 50% { opacity: .3; } }
@keyframes skel { 0%, 100% { opacity: .3; } 50% { opacity: .7; } }
@keyframes spin { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; }
}

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

header.top {
  flex: 0 0 auto;
  display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between;
  gap: 12px; padding: 11px 16px 9px;
  background: linear-gradient(to bottom, var(--panel), var(--bg));
  border-bottom: 1px solid var(--border);
}
.brand { display: flex; align-items: baseline; gap: 13px; flex-wrap: wrap; }
.brand h1 { margin: 0; font-size: 19px; font-weight: 600; letter-spacing: -.015em; }
.brand .sub { font-size: 10px; letter-spacing: .14em; text-transform: uppercase; color: var(--n600); }

.head-right { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }

.context { display: flex; gap: 13px; font-family: var(--mono); font-size: 11px; color: var(--n500); font-variant-numeric: tabular-nums; }
.context .sym { color: var(--n600); letter-spacing: .06em; margin-right: 3px; }

.session-badge {
  display: flex; align-items: center; gap: 6px;
  padding: 4px 9px; border-radius: 4px; border: 1px solid var(--border);
}
.session-badge .dot { width: 6px; height: 6px; border-radius: 50%; animation: pulsedot 2.4s ease-in-out infinite; }
.session-badge .label { font-size: 10px; letter-spacing: .14em; font-weight: 600; }
.session-badge[data-phase="premarket"] { background: var(--bull-bg); border-color: var(--bull-dim); }
.session-badge[data-phase="premarket"] .dot, .session-badge[data-phase="premarket"] .label { background: var(--bull); color: var(--bull); }
.session-badge[data-phase="regular"] { background: #152431; border-color: var(--info-dim); }
.session-badge[data-phase="regular"] .dot { background: var(--info); }
.session-badge[data-phase="regular"] .label { color: var(--info); }
.session-badge[data-phase="afterhours"] { background: var(--warn-bg); border-color: var(--warn-dim); }
.session-badge[data-phase="afterhours"] .dot { background: var(--warn); }
.session-badge[data-phase="afterhours"] .label { color: var(--warn); }
.session-badge[data-phase="closed"] { background: #1c1e2c; border-color: var(--field-border); }
.session-badge[data-phase="closed"] .dot { background: var(--n700); animation: none; }
.session-badge[data-phase="closed"] .label { color: var(--n400); }
.session-badge .dot { background: currentColor; }

.clock { text-align: right; font-family: var(--mono); font-variant-numeric: tabular-nums; line-height: 1.35; }
.clock .t { font-size: 13px; color: var(--n200); }
.clock .u { font-size: 10px; color: var(--n600); }
.clock .u b { font-weight: 500; color: var(--n500); }

/* ---------------------------------------------------------- banner */

.banner {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 8px 16px; font-size: 12px; border-bottom: 1px solid var(--border);
}
.banner .mark { font-size: 13px; }
.banner .title { font-weight: 600; letter-spacing: .05em; }
.banner .body { color: var(--n400); }
.banner .act {
  margin-left: auto; background: none; border: 1px solid currentColor;
  border-radius: 4px; padding: 2px 9px; font-size: 11px; opacity: .85;
}
.banner .act:hover { opacity: 1; }
.banner[data-kind="stale"] { background: #241d10; border-bottom-color: var(--warn-dim); color: var(--warn); }
.banner[data-kind="error"] { background: #251316; border-bottom-color: var(--bear-dim); color: var(--bear); }
.banner[data-kind="closed"] { background: #1b1d2b; border-bottom-color: var(--field-border); color: var(--n300); }
.banner[data-kind="info"] { background: #16192c; border-bottom-color: var(--accent-700); color: var(--accent-400); }

/* --------------------------------------------------------- filters */

/* The only pinned element. It stays at the top of the viewport once the brand
   header has scrolled away, so thresholds and the pool switch stay reachable
   without scrolling back up - and top:0 means no hardcoded header height to go
   stale when the header wraps. */
.filters {
  position: sticky; top: 0; z-index: 25;
  flex: 0 0 auto;
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  padding: 8px 16px; background: var(--panel); border-bottom: 1px solid var(--border);
}
.filters label { display: flex; align-items: center; gap: 5px; font-size: 11px; color: var(--n500); }

.input, select.input {
  min-height: 30px; padding: 4px 8px; font-size: 12px;
  background: var(--field); border: 1px solid var(--field-border);
  border-radius: 4px; color: var(--text);
}
.input:hover { border-color: var(--n600); }
select.input { min-height: 28px; font-size: 11px; padding: 3px 6px; cursor: pointer; }

.search-wrap { position: relative; }
.search-wrap .icon { position: absolute; left: 8px; top: 50%; transform: translateY(-50%); font-size: 12px; color: var(--n600); pointer-events: none; }
.search-wrap .input { width: 210px; padding-left: 26px; }

.seg { display: flex; border: 1px solid var(--field-border); border-radius: 4px; overflow: hidden; }
.seg button {
  border: 0; background: transparent; color: var(--n500);
  font-size: 11px; padding: 5px 9px;
}
.seg button + button { border-left: 1px solid var(--field-border); }
.seg button:hover { background: #232740; }
.seg button[aria-pressed="true"] { background: var(--accent-bg); color: var(--accent); }
.seg.tiny button { font-size: 10px; letter-spacing: .08em; padding: 4px 6px; }

.chip {
  border: 1px solid var(--field-border); background: transparent; color: var(--n500);
  font-size: 11px; padding: 5px 9px; border-radius: 4px;
  display: inline-flex; align-items: center; gap: 5px;
}
.chip:hover { border-color: var(--accent); color: var(--accent); }
.chip[aria-pressed="true"] { background: var(--accent-bg); color: var(--accent); border-color: var(--accent-700); }
.chip.mono { font-size: 10px; padding: 4px 6px; }

/* A cluster of controls that belong together inside the filter bar. */

.vsep { width: 1px; height: 20px; background: var(--border); }
.spacer { margin-left: auto; }

.advanced {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 8px 14px; padding: 10px 16px 12px;
  background: #12142280; border-bottom: 1px solid var(--border);
}
.advanced label { display: flex; flex-direction: column; gap: 3px; }
.advanced .lab { font-size: 10px; letter-spacing: .08em; text-transform: uppercase; color: var(--n600); }
.advanced .input { font-family: var(--mono); min-height: 28px; }
.advanced .hint { font-size: 9.5px; color: var(--n700); }

/* Both panels hang off the pinned bar the way .pop does, so opening one can
   never land off-screen and never displaces .tablewrap. .filters is sticky and
   therefore already the containing block, and its z-index:25 stacking context
   puts this subtree above the table's own sticky header (z-index 3). */
.advanced, .wlpanel {
  position: absolute; top: 100%; left: 0; right: 0;
  max-height: 70vh; overflow-y: auto;
  /* Opaque. The old #12142280 is ~50% alpha and would show table rows through. */
  background: var(--panel);
  box-shadow: 0 10px 28px #0009;
}

/* --------------------------------------------------------- popover */

.popwrap { position: relative; display: inline-flex; }
.pop {
  position: absolute; top: calc(100% + 4px); left: 0; z-index: 40;
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  width: max-content; max-width: 280px; padding: 10px;
  background: var(--raised); border: 1px solid var(--field-border);
  border-radius: 6px; box-shadow: 0 10px 28px #0009;
}
.pop .poptitle { flex: 0 0 100%; font-size: 10px; color: var(--n600); letter-spacing: .04em; }
.chip[aria-expanded="true"] { border-color: var(--accent); color: var(--accent); }

/* A filter that is on must look on even when its popover is shut, or it becomes
   an invisible reason the table is empty. */
.chip[data-active="1"] { border-color: var(--accent); color: var(--accent); }

/* ------------------------------------------------------- watchlist */

.wlpanel {
  padding: 12px 16px 14px; background: #12142280;
  border-bottom: 1px solid var(--border);
  display: flex; flex-direction: column; gap: 10px;
}
.wlpanel .wlrow { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.wlpanel .lab {
  font-size: 10px; letter-spacing: .08em; text-transform: uppercase; color: var(--n600);
  flex: 0 0 auto;
}
.wlpanel .grow { flex: 1 1 260px; min-width: 200px; }

/* The search box and its suggestion list share a positioning context so the
   list can hang below the input without pushing the panel around. */
.wlsearch { position: relative; flex: 1 1 280px; min-width: 200px; }
.wlsearch .input { width: 100%; }
.wlsug {
  position: absolute; left: 0; right: 0; top: calc(100% + 3px); z-index: 40;
  background: var(--raised); border: 1px solid var(--field-border); border-radius: 5px;
  box-shadow: 0 10px 28px #0009; max-height: 300px; overflow-y: auto; padding: 3px;
}
.wlsug .opt {
  display: flex; align-items: baseline; gap: 8px; width: 100%;
  padding: 6px 8px; border: 0; background: none; text-align: left;
  border-radius: 4px; cursor: pointer; color: inherit;
}
.wlsug .opt:hover, .wlsug .opt[aria-selected="true"] { background: var(--row-hover); }
.wlsug .opt .tic { font-family: var(--mono); font-size: 12px; font-weight: 600; min-width: 58px; }
.wlsug .opt .nm { font-size: 11px; color: var(--n500); flex: 1 1 auto;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wlsug .opt .xch { font-size: 9.5px; color: var(--n700); letter-spacing: .06em; }
.wlsug .opt .have { font-size: 9.5px; color: var(--accent); }
.wlsug .msg { padding: 7px 9px; font-size: 11px; color: var(--n600); }

.wlchips { display: flex; flex-wrap: wrap; gap: 6px; }
.wlchip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 4px 3px 9px; border: 1px solid var(--field-border); border-radius: 999px;
  background: var(--panel); font-family: var(--mono); font-size: 11.5px;
}
.wlchip.missing { border-style: dashed; color: var(--n600); }
.wlchip .x {
  border: 0; background: none; color: var(--n600); cursor: pointer;
  font-size: 13px; line-height: 1; padding: 2px 5px; border-radius: 999px;
}
.wlchip .x:hover { background: var(--bear); color: #fff; }
.wlempty { font-size: 11.5px; color: var(--n600); }
.wlnote { font-size: 10px; color: var(--n700); }

/* --------------------------------------------------------- summary */

.summary {
  /* Now BELOW the table, so its rule sits on top of it rather than under. */
  flex: 0 0 auto;
  padding: 12px 16px 28px; border-top: 1px solid var(--border);
}
.summary-head { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 16px; margin-bottom: 8px; }
.summary-head h2 { margin: 0; font-size: 10px; letter-spacing: .16em; text-transform: uppercase; color: var(--n400); font-weight: 600; }
.scope { font-family: var(--mono); font-size: 10.5px; color: var(--n600); }

.breadth { display: flex; align-items: center; gap: 8px; }
.breadth .bar { width: 132px; height: 5px; border-radius: 3px; overflow: hidden; display: flex; background: var(--line); }
.breadth .bar i { display: block; height: 100%; }
.breadth .txt { font-family: var(--mono); font-size: 10.5px; color: var(--n500); }

.stats { display: flex; flex-wrap: wrap; gap: 4px 14px; }
.stats .st { font-size: 10.5px; color: var(--n600); }
.stats .st b { font-family: var(--mono); font-size: 11.5px; font-weight: 500; margin-left: 3px; }

.hist { display: flex; align-items: flex-end; gap: 3px; height: 18px; }
.hist i { width: 12px; border-radius: 1px 1px 0 0; display: block; }

.narrative { font-size: 12px; line-height: 1.55; color: var(--n300); max-width: 100ch; text-wrap: pretty; margin-bottom: 6px; }
.caveat { font-size: 11px; line-height: 1.5; color: var(--n600); max-width: 100ch; margin-bottom: 10px;
          border-left: 2px solid var(--warn-dim); padding-left: 8px; }

.top3 { display: grid; grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); gap: 10px; }
.setup-card {
  border: 1px solid #282c40; border-left-width: 2px; border-radius: 4px;
  background: #16182880; padding: 9px 11px 10px;
  display: flex; flex-direction: column; gap: 8px;
}
.setup-card .hd { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.setup-card .rank { font-size: 10px; color: var(--n700); font-family: var(--mono); }
.setup-card .tic { font-family: var(--mono); font-size: 15px; font-weight: 600; letter-spacing: .02em; }
.setup-card .nm { font-size: 10px; color: var(--n600); }
.setup-card .dir { font-size: 9px; letter-spacing: .1em; font-weight: 700; }
.setup-card .sc { margin-left: auto; font-family: var(--mono); font-size: 17px; font-variant-numeric: tabular-nums; }
.setup-card .of { font-size: 10px; color: var(--n700); }
.setup-card .chips { font-family: var(--mono); font-size: 10.5px; display: flex; flex-wrap: wrap; gap: 3px 8px; }
.setup-card .thesis { font-size: 11.5px; line-height: 1.55; color: var(--n300); text-wrap: pretty; }

.block-label { font-size: 9px; letter-spacing: .12em; color: var(--n600); margin-bottom: 3px; }

.compbars { display: flex; flex-direction: column; gap: 2px; }
.compbar { display: flex; align-items: center; gap: 7px; font-size: 11px; }
.compbar .l { width: 104px; color: var(--n500); flex: 0 0 auto; }
.compbar .t { flex: 1; height: 3px; background: var(--line); border-radius: 2px; overflow: hidden; }
.compbar .t i { display: block; height: 100%; }
.compbar .v { width: 52px; text-align: right; font-family: var(--mono); font-size: 10.5px; color: var(--n400); flex: 0 0 auto; }

.levelmap { display: flex; align-items: center; gap: 7px; font-family: var(--mono); font-size: 10px; color: var(--n600); }
.levelmap .track { flex: 1; position: relative; height: 8px; background: var(--line); border-radius: 3px; }
.levelmap .mk { position: absolute; top: -2px; width: 2px; height: 12px; }
.levelmap .cur { position: absolute; top: -4px; width: 3px; height: 16px; background: var(--n100); border-radius: 1px; }

.cols2 { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.bullets { display: flex; flex-direction: column; gap: 2px; }
.bullets div { font-size: 11px; line-height: 1.45; color: var(--n300); }
.bullets .mk { margin-right: 5px; }

.ai-note { border-left: 2px solid var(--accent-700); padding-left: 8px; }
.ai-note .hd { font-size: 9px; letter-spacing: .12em; color: var(--accent-400); margin-bottom: 2px; }
.ai-note .bd { font-size: 11px; line-height: 1.5; color: var(--n400); text-wrap: pretty; }

/* ----------------------------------------------------------- table */

/*
 * overflow-x only. The used value of overflow-y becomes `auto` alongside it, but
 * the wrapper's height is its content's, so there is nothing to scroll
 * vertically and no second scrollbar appears.
 */
.tablewrap { flex: 0 0 auto; overflow-x: auto; }

table.scan { width: 100%; border-collapse: separate; border-spacing: 0; min-width: 1340px; }
table.scan th, table.scan td { white-space: nowrap; }

table.scan thead th.grp {
  position: sticky; top: 0; z-index: 3; background: var(--raised);
  padding: 4px 8px; font-size: 9px; letter-spacing: .16em; font-weight: 600;
  border-bottom: 1px solid var(--border);
}
table.scan thead th.col {
  position: sticky; top: 21px; z-index: 3; background: var(--panel);
  padding: 5px 8px; font-family: var(--mono); font-size: 10px; letter-spacing: .06em;
  font-weight: 500; color: var(--n500); border-bottom: 1px solid var(--border);
}
table.scan thead th.col.sortable { cursor: pointer; }
table.scan thead th.col.sortable:hover { color: var(--accent); }
table.scan thead th.col[aria-sort] { color: var(--accent); }
table.scan th.sep, table.scan td.sep { border-left: 1px solid var(--line); }

table.scan tbody tr.row { height: 38px; cursor: pointer; }
table.scan tbody tr.row:hover td { background: var(--row-hover); }
table.scan tbody tr.row.open td { background: #191c2c; }
table.scan tbody td { padding: 0 8px; border-bottom: 1px solid var(--border-soft); background: var(--bg); }
table.scan tbody td.stick { position: sticky; z-index: 2; }
table.scan tbody td.stick-star { left: 0; padding: 0 4px 0 10px; }
table.scan tbody td.stick-tic { left: 30px; }
table.scan tbody tr.row:hover td.stick { background: var(--row-hover); }
table.scan tbody tr.row.open td.stick { background: #191c2c; }

td.num { text-align: right; font-family: var(--mono); font-size: 12.5px; font-variant-numeric: tabular-nums; }
td.mid { text-align: center; }

.star { font-size: 13px; color: #33374a; background: none; border: 0; padding: 2px; line-height: 1; }
.star[aria-pressed="true"] { color: var(--accent); }
.star:hover { color: var(--accent-400); }

.tickcell { display: flex; align-items: baseline; gap: 6px; }
.tickcell .t { font-family: var(--mono); font-size: 13.5px; font-weight: 600; letter-spacing: .02em; color: var(--n100); }
.tickcell .x { font-size: 9px; letter-spacing: .06em; color: var(--n700); }

.rvolcell { display: flex; align-items: center; justify-content: flex-end; gap: 6px; }
.rvolcell .t { width: 26px; height: 3px; background: var(--line); border-radius: 2px; overflow: hidden; }
.rvolcell .t i { display: block; height: 100%; }

.lvl { position: relative; text-align: center; padding: 0 5px; white-space: nowrap; }
.lvl .flash { position: absolute; inset: 1px; animation: flashcell 1.6s ease-out forwards; pointer-events: none; }
.lvl .brk { font-family: var(--mono); font-size: 10px; font-weight: 600; letter-spacing: .02em; }
.lvl .meter { font-family: var(--mono); font-size: 9px; letter-spacing: -.6px; }
/* The raw ATR multiple sits beside every meter: the meter is a glance aid,
   this number is the fact it is approximating. */
.lvl .lvlatr { font-family: var(--mono); font-size: 9px; color: var(--n700); margin-left: 4px; }

.flagmark { font-size: 9px; margin-left: 3px; cursor: help; }

.pdrange { display: flex; align-items: center; justify-content: flex-end; gap: 5px; }
.pdrange .meter { font-family: var(--mono); font-size: 9.5px; letter-spacing: -.5px; }
.pdrange .p { font-family: var(--mono); font-size: 10.5px; color: var(--n500); }

.scorecell { display: flex; align-items: center; justify-content: flex-end; gap: 6px; }
.scorecell .d { font-size: 9px; letter-spacing: .06em; font-weight: 600; }
.scorecell .v { font-family: var(--mono); font-size: 13.5px; font-variant-numeric: tabular-nums; min-width: 30px; text-align: right; }

/* --------------------------------------------------- expanded row */

tr.detail > td { padding: 0; background: #13152280 !important; border-bottom: 1px solid var(--border); }
.detail-grid {
  display: grid; grid-template-columns: minmax(320px, 1.15fr) minmax(230px, 1fr) minmax(250px, 1fr);
  gap: 18px; padding: 12px 16px 14px;
}
.detail-grid h4 { margin: 0 0 8px; font-size: 10px; letter-spacing: .12em; color: var(--n600); font-weight: 600; }
.kv { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1px 18px; }
.kv .r { display: flex; justify-content: space-between; gap: 10px; padding: 2px 0; border-bottom: 1px solid #1d203190; font-size: 11.5px; }
.kv .r .k { color: var(--n600); }
.kv .r .v { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.detail-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 8px; flex-wrap: wrap; }
.detail-head .t { font-family: var(--mono); font-size: 14px; }
.detail-head .lbl { font-size: 10px; letter-spacing: .12em; color: var(--n600); }
.detail-head .lnk { margin-left: auto; font-size: 10.5px; text-decoration: none; }

/* -------------------------------------------------- skeleton/empty */

.skel { display: block; height: 8px; border-radius: 2px; background: var(--border); animation: skel 1.4s ease-in-out infinite; }
.empty { padding: 40px 16px; text-align: center; color: var(--n600); font-size: 12px; }
.empty button { background: none; border: 0; color: var(--accent); text-decoration: underline; padding: 0; }

.legend {
  display: flex; flex-wrap: wrap; gap: 8px 16px; align-items: center;
  padding: 8px 16px 22px; font-size: 10.5px; color: var(--n700);
}
.legend .sepdot { color: var(--n800); }

/* -------------------------------------------------------- mobile */

.cards { display: none; }

@media (max-width: 900px) {
  /* Natural scrolling is now the default; the filter bar is too tall to pin on
     a phone, where it wraps to several rows. `relative` rather than `static` so
     it still anchors the two absolutely-positioned panels. */
  .filters { position: relative; }
  .advanced, .wlpanel { max-height: 60vh; }
  .tablewrap { overflow: visible; }
  table.scan { display: none; }
  .cards { display: flex; flex-direction: column; gap: 8px; padding: 10px 12px 24px; }

  .mcard { border: 1px solid var(--border); border-left-width: 2px; border-radius: 5px; background: var(--surface); padding: 9px 11px; }
  .mcard .hd { display: flex; align-items: center; gap: 8px; }
  .mcard .tic { font-family: var(--mono); font-size: 15px; font-weight: 600; }
  .mcard .nm { font-size: 10px; color: var(--n600); overflow: hidden; text-overflow: ellipsis; }
  .mcard .sc { margin-left: auto; font-family: var(--mono); font-size: 16px; }
  .mcard .nums { display: flex; flex-wrap: wrap; gap: 3px 12px; margin-top: 5px; font-family: var(--mono); font-size: 11.5px; }
  .mcard .nums span i { font-style: normal; color: var(--n600); margin-right: 3px; }
  .mcard .lvls { display: flex; flex-wrap: wrap; gap: 4px 10px; margin-top: 6px; font-family: var(--mono); font-size: 10px; }
  .mcard .lvls b { font-weight: 500; color: var(--n600); margin-right: 3px; }
  .mcard .mas { display: flex; gap: 10px; margin-top: 6px; font-size: 10px; color: var(--n600); }

  header.top { align-items: flex-start; }
  .head-right { width: 100%; justify-content: space-between; }
  .search-wrap .input { width: 100%; }
  .search-wrap { flex: 1 1 180px; }
  .cols2 { grid-template-columns: 1fr; }
  .detail-grid { grid-template-columns: 1fr; }
  .kv { grid-template-columns: 1fr; }
}
