/* VNIndex static dashboard.
 *
 * Visual system is deliberately NOT an original design: it mirrors the
 * Streamlit app in ../vnindex-valuation so the two builds look like the same
 * product. Palette is copied from that app's :root token block; type sizes and
 * families were measured off the running app with getComputedStyle rather than
 * eyeballed (body 16px Source Sans, headings 28px/600 Fira Code, metric labels
 * 16px, scorecard values 22px). Sections sit flat on the page background with
 * hairline dividers -- no card chrome, matching the original's layout.
 *
 * If you change anything here, re-run the comparison against localhost:8501
 * instead of guessing.
 */
:root {
  /* Palette copied verbatim from the Streamlit app's :root token block so the
     two builds render the same colours, not merely similar ones. */
  --bg: #f2f5fb;
  --paper: #fcfeff;
  --paper-2: #fcfeff;
  --paper-3: #e2e8f1;
  --ink: #0a121d;
  --ink-2: #1b2532;
  --muted: #666f7c;
  --neutral: #47515e;
  --rule: #ced5df;
  --rule-strong: #afb8c4;

  /* accent + semantics */
  --primary: #00347b;
  --primary-light: #367ad1;
  --primary-soft: #d3e3f9;
  --primary-ring: rgba(0, 109, 221, 0.4);
  --gain: #15803d;
  --loss: #b91c1c;
  --warn: #b45309;

  /* Type. The original's *visible* body text renders in Source Sans (Streamlit's
     markdown default), with Fira Code on headings and numbers — measured off the
     running app, not assumed from its theme config. */
  --mono: "Fira Code", ui-monospace, "SF Mono", Consolas, monospace;
  --sans: "Source Sans 3", "Source Sans Pro", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;

  /* scale */
  --space-xs: 4px; --space-sm: 8px; --space-md: 14px; --space-lg: 20px; --space-xl: 28px;
  --radius: 8px; --radius-sm: 5px;
  --shadow-1: 0 1px 2px rgba(11, 20, 32, 0.04), 0 1px 3px rgba(11, 20, 32, 0.03);
  --shadow-2: 0 6px 20px rgba(11, 20, 32, 0.10);
  --ease-out: cubic-bezier(0.22, 0.61, 0.36, 1);
  --dur: 140ms;
}

* { box-sizing: border-box; }
html, body { overflow-x: clip; }
body {
  margin: 0; background: var(--bg); color: var(--ink);
  font-family: var(--sans); font-size: 16px; line-height: 1.5;
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
  display: grid; grid-template-columns: 300px 1fr; min-height: 100vh;
}
b, strong { font-weight: 600; }

/* ── sidebar ──────────────────────────────────────────────── */
.sidebar {
  background: var(--paper); border-right: 1px solid var(--rule);
  padding: var(--space-lg) var(--space-md); position: sticky; top: 0; height: 100vh;
  display: flex; flex-direction: column; gap: var(--space-lg);
  /* The screener's filter panel makes the sidebar taller than the viewport;
     without this its lower controls are unreachable. */
  overflow-y: auto; overscroll-behavior: contain;
}
.brand { font-family: var(--mono); font-weight: 700; font-size: 19px; letter-spacing: 1.5px; color: var(--primary); }
.brand span { color: var(--ink); }
.picker-wrap { position: relative; }
#picker {
  width: 100%; padding: 9px 11px; border: 1px solid var(--rule); border-radius: var(--radius-sm);
  font-family: var(--mono); font-size: 13px; background: var(--paper-2); color: var(--ink);
  transition: border-color var(--dur) var(--ease-out), box-shadow var(--dur) var(--ease-out);
}
#picker:focus-visible { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-ring); }
#picker-list {
  position: absolute; z-index: 20; top: 42px; left: 0; right: 0; max-height: 340px; overflow-y: auto;
  background: var(--paper); border: 1px solid var(--rule-strong); border-radius: var(--radius-sm);
  box-shadow: var(--shadow-2);
}
.pick { padding: 8px 11px; cursor: pointer; display: flex; flex-direction: column; transition: background var(--dur) var(--ease-out); }
.pick:hover { background: var(--paper-3); }
.pick b { font-family: var(--mono); font-size: 13px; }
.pick span { font-size: 11px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#nav { display: flex; flex-direction: column; gap: 2px; }
.nav-item {
  position: relative; text-align: left; padding: 9px 12px; border: none; border-radius: var(--radius-sm);
  background: none; color: var(--muted); font-family: var(--sans); font-size: 13px; cursor: pointer;
  transition: background var(--dur) var(--ease-out), color var(--dur) var(--ease-out);
}
.nav-item:hover { background: var(--paper-3); color: var(--ink); }
.nav-item:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--primary-ring); }
.nav-item.active { background: var(--primary); color: #fff; font-weight: 600; }
.meta { margin-top: auto; font-family: var(--mono); font-size: 10px; color: var(--muted); line-height: 1.6; }

/* ── main ─────────────────────────────────────────────────── */
/* The original's block-container has NO max-width -- it fills the window with
   80px side padding. Capping it at 1500px left a wide empty gutter on large
   monitors, which is what made the port look unfinished next to the original. */
.main { padding: 40px 56px; width: 100%; min-width: 0; }
.view.hidden, .hidden { display: none !important; }
.loading { color: var(--muted); padding: 48px; font-family: var(--mono); font-size: 13px; }
/* Sections sit flat on the page background and are separated by a hairline
   rule, matching the Streamlit original (st.markdown("---") dividers) -- no
   card chrome, no elevation. */
.card {
  background: transparent; border: none; box-shadow: none; padding: 0;
  margin-bottom: var(--space-xl); padding-bottom: var(--space-xl);
  border-bottom: 1px solid var(--rule);
}
.card:last-child { border-bottom: none; }
.sec-h {
  font-family: var(--mono); font-size: 28px; font-weight: 600;
  margin: 0 0 var(--space-md); color: var(--ink);
}

/* ── stock header ─────────────────────────────────────────── */
.stock-head { display: flex; justify-content: flex-start; align-items: flex-start; gap: var(--space-xl); flex-wrap: wrap; }
/* One row: identity, price, then the metric grid, as the original lays it out. */
.head-row { display: flex; align-items: flex-start; gap: var(--space-xl); margin-bottom: var(--space-lg); flex-wrap: wrap; }
.head-row > .stock-head { flex: 0 0 auto; margin-bottom: 0; }
.head-row > .metrics { flex: 1 1 460px; min-width: 0; }
.sh-tick { font-family: var(--mono); font-size: 30px; font-weight: 700; letter-spacing: -0.5px; display: flex; align-items: center; gap: 10px; }
.badge { font-family: var(--sans); font-size: 10.5px; font-weight: 600; letter-spacing: .5px; background: var(--primary-soft); color: var(--primary); padding: 3px 8px; border-radius: 4px; }
.sh-name { color: var(--ink-2); margin-top: 5px; font-size: 14px; }
.sh-sector { color: var(--muted); font-size: 12px; margin-top: 1px; }
.sh-right { text-align: left; min-width: 300px; padding-right: 28px; }
.sh-price { font-family: var(--mono); font-size: 36px; font-weight: 700; line-height: 1; letter-spacing: -1px; }
.sh-chg { font-family: var(--mono); font-size: 13px; margin-top: 5px; }
.sh-range { display: flex; align-items: center; gap: 8px; margin-top: 10px; font-family: var(--mono); font-size: 10px; color: var(--muted); }
.sh-range .bar { position: relative; flex: 1; height: 4px; background: var(--rule-strong); border-radius: 2px; }
.sh-range .fill { position: absolute; left: 0; top: 0; bottom: 0; border-radius: 2px; }
.sh-range .dot { position: absolute; top: -3px; width: 10px; height: 10px; border-radius: 50%; transform: translateX(-50%); background: var(--ink); box-shadow: 0 0 0 2px var(--paper); }
.gain { color: var(--gain); } .loss { color: var(--loss); } .flat { color: var(--muted); }
.fill.gain { background: var(--gain); } .fill.loss { background: var(--loss); } .fill.flat { background: var(--muted); }

/* ── metrics grid ─────────────────────────────────────────── */
/* Plain 3-across grid on the page background — the original's layout; no
   boxes, no separators. */
.metrics { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px 18px; margin-bottom: var(--space-xl); }
.metric { min-width: 0; }
.mk { font-size: 16px; color: var(--muted); line-height: 1.3; overflow-wrap: anywhere; }
.mv { font-size: 20px; font-weight: 600; color: #1e3a8a; white-space: nowrap; }
.mv.accent { color: #3b82f6; }

/* ── range buttons ────────────────────────────────────────── */
.range-row { display: flex; gap: 6px; margin-bottom: var(--space-md); }
.range-btn {
  padding: 5px 13px; border: 1px solid var(--rule-strong); background: var(--paper-2); border-radius: var(--radius-sm);
  font-family: var(--mono); font-size: 11px; cursor: pointer; color: var(--muted);
  transition: background var(--dur) var(--ease-out), color var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out);
}
.range-btn:hover { color: var(--ink); border-color: var(--primary); }
.range-btn:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--primary-ring); }
.range-btn.active { background: var(--primary); color: #fff; border-color: var(--primary); }

/* ── scorecard ────────────────────────────────────────────── */
/* No overflow:hidden here -- it was clipping the hover tooltip (which sits
   above the cell) by ~130px. The original rounds the title bar itself instead
   of clipping the block. */
.sc-block { border: 1px solid var(--rule); border-radius: var(--radius-sm); margin-bottom: 10px; }
.sc-title { background: rgba(148, 163, 184, 0.08); padding: 6px 14px; font-size: 10px; font-weight: 700; letter-spacing: 1.4px; color: var(--muted); border-radius: var(--radius-sm) var(--radius-sm) 0 0; }
.sc-cells { display: flex; }
.sc-cell { flex: 1; text-align: center; padding: 15px 10px; min-width: 0; transition: background var(--dur) var(--ease-out); }
.sc-cell:hover { background: var(--paper-2); }
.sc-k { font-size: 11px; color: var(--muted); margin-bottom: 7px; line-height: 1.35; overflow-wrap: anywhere; }
.sc-v { font-family: var(--mono); font-size: 22px; font-weight: 700; letter-spacing: -0.5px; }
.legend { display: flex; gap: 16px; justify-content: flex-end; padding: 6px 2px 0; font-size: 11px; color: var(--muted); }
.legend i { display: inline-block; width: 9px; height: 9px; border-radius: 50%; margin-right: 5px; vertical-align: middle; }

/* ── evaluation cards ─────────────────────────────────────── */
.ev-cards { display: flex; gap: var(--space-md); flex-wrap: wrap; }
.ev-card { flex: 1; min-width: 210px; background: var(--paper-2); border: 1px solid var(--rule); border-radius: var(--radius-sm); padding: 15px 17px; }
.ev-t { font-size: 10.5px; color: var(--muted); text-transform: uppercase; letter-spacing: .6px; margin-bottom: 7px; }
.ev-m { font-family: var(--mono); font-size: 24px; font-weight: 800; line-height: 1.1; letter-spacing: -0.5px; }
.ev-u { font-size: 14px; color: var(--muted); font-weight: 500; }
.ev-s { font-size: 12px; color: var(--ink-2); margin-top: 6px; }
.ev-note { font-size: 11px; color: var(--muted); margin-top: var(--space-md); line-height: 1.55; }
.ev-src { font-size: 10px; color: var(--muted); margin-top: 4px; font-style: italic; }

/* ── two-column split: chart left, valuation panel right ──── */
.split { display: grid; grid-template-columns: 5fr 2fr; gap: 32px; align-items: start; }
.split-l, .split-r { min-width: 0; }
.split-r { display: flex; flex-direction: column; gap: var(--space-xl); }

/* valuation panel */
.vp-h { font-size: 21px; margin-bottom: 6px; }
.vp-mkt { font-size: 12.5px; color: var(--muted); margin-bottom: 10px; }
.vp-mkt b { color: var(--ink); }
.vp-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
/* Measured off the original, not styled by eye: the crisp dark slate outline
   (#334155) is what gives these cards their look -- a light-grey rule reads as
   a different component entirely. The value is Source Sans here, not the mono
   used elsewhere, and the ▲/▼ percentage uses the bright pair. */
.vp-card { background: var(--paper-2); border: 1px solid #334155; border-radius: 4px; padding: 12px 14px; min-width: 0; }
/* Method names run long ("FCFE / Dòng tiền vốn chủ") and the right column
   narrows with the viewport; wrap instead of truncating with an ellipsis,
   which hid which method a card was showing. */
.vp-k { font-size: 12px; font-weight: 400; color: var(--muted); margin-bottom: 6px;
        line-height: 1.35; overflow-wrap: anywhere; }
.vp-v { font-family: var(--sans); font-size: 21px; font-weight: 800; color: var(--ink); letter-spacing: .3px; }
.vp-cur { font-size: 13px; font-weight: 600; color: var(--muted); }
.vp-u { font-size: 12px; font-weight: 700; margin-top: 4px; }
.vp-u.gain { color: #4ade80; }
.vp-u.loss { color: #f87171; }
.vp-vs { color: var(--neutral); font-weight: 400; }
.vp-avg { margin-top: 12px; background: linear-gradient(135deg, #dbeafe, #eff6ff); border: 1px solid #3b82f6; border-radius: 4px; padding: 13px 15px; }
/* Wraps rather than overflowing: the right column narrows as the sidebar
   widens, and this row holds a long label beside a long number. */
.vp-avg-row { display: flex; justify-content: space-between; align-items: center;
              gap: 10px; flex-wrap: wrap; min-width: 0; }
.vp-avg-row > * { min-width: 0; }
.vp-avg-k { font-size: 10.5px; color: #002057; font-weight: 700; letter-spacing: .4px; }
.vp-avg-v { font-family: var(--mono); font-size: 25px; font-weight: 800; color: var(--ink); margin-top: 2px; }
.vp-avg-right { text-align: right; font-family: var(--mono); font-size: 14px; font-weight: 700; white-space: nowrap; }
.vp-avg-med { font-size: 10.5px; color: var(--neutral); font-weight: 400; margin-top: 3px; }
.vp-avg-note { font-size: 10.5px; color: var(--neutral); margin-top: 7px; }
.vp-params { margin-top: 14px; border: 1px solid var(--rule); border-radius: 4px; padding: 10px 13px; }
.vp-params-h { font-size: 10.5px; font-weight: 700; letter-spacing: 1px; color: var(--muted); text-transform: uppercase; margin-bottom: 7px; }
.vp-prow { display: flex; justify-content: space-between; font-size: 12.5px; padding: 3px 0; color: var(--neutral); }
.vp-prow b { font-family: var(--mono); color: var(--ink); font-weight: 600; }

/* technical analysis — structure copied from the original: verdict line, a
   Mua/Bán tally beside the gauge, pivot table, indicator table, MA table. */
.ta-sub { color: var(--muted); font-size: 13px; font-weight: 400; }
.ta-head { font-family: var(--mono); font-size: 17px; font-weight: 800; letter-spacing: .3px; margin-bottom: 8px; }
/* minmax(0, 1fr), not 1fr: a bare fr track floors at the content min-width,
   so the tally table (181px min-content) plus the 150px gauge and the gap
   overflowed a 330px column instead of the table shrinking. */
.ta-top { display: grid; grid-template-columns: minmax(0, 1fr) 150px; gap: 8px; align-items: center; }
.ta-top > * { min-width: 0; overflow: hidden; }
.ta-h2 { font-size: 13px; font-weight: 700; color: var(--ink); margin: 14px 0 6px; }
.ta-note { font-size: 11px; color: var(--muted); margin-top: 6px; line-height: 1.5; }
.ta-scroll { overflow-x: auto; }
.ta-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.ta-table th { font-size: 10.5px; color: var(--muted); font-weight: 600; text-align: right; padding: 4px 6px; border-bottom: 1px solid var(--rule); }
.ta-table th:first-child { text-align: left; }
.ta-table td { padding: 5px 6px; border-bottom: 1px solid var(--rule); }
.ta-table td.num { font-family: var(--mono); text-align: right; white-space: nowrap; }
.ta-table td.sig { text-align: right; font-weight: 600; white-space: nowrap; }
.ta-count td:first-child { color: var(--neutral); }
.ta-pivot { min-width: 460px; font-size: 11.5px; }
.ta-pivot td.sup { color: #4ade80; }
.ta-pivot td.res { color: #f87171; }
.ta-pivot td.piv { color: #ca8a04; font-weight: 700; }
/* Negative side margins let the gauge poke 6px past the card; only the
   vertical tightening is wanted. */
#ta-gauge { margin: -8px 0 -14px; min-width: 0; }

/* ── DuPont ───────────────────────────────────────────────── */
.dp-row { display: flex; align-items: stretch; gap: 3px; }
.dp-card { flex: 1; min-width: 0; text-align: center; background: var(--paper); border: 1px solid #e2e8f0; box-shadow: 0 1px 4px rgba(0,0,0,0.07); border-radius: 4px; padding: 14px 10px 12px; }
.dp-k { font-size: 11px; color: var(--muted); margin-bottom: 6px; line-height: 1.35; overflow-wrap: anywhere; }
.dp-v { font-family: var(--mono); font-size: 22px; font-weight: 700; letter-spacing: -0.5px; }
.dp-h { font-size: 10px; color: var(--neutral); margin-top: 4px; }
.dp-op { font-size: 18px; color: var(--neutral); align-self: center; padding: 0 2px; }
.dp-badges { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.dp-badge { padding: 2px 9px; border-radius: 5px; border: 1px solid; font-weight: 600; font-size: 12px; white-space: nowrap; }
.dp-comment { font-size: 13px; color: var(--neutral); margin-top: 10px; line-height: 1.6; }

/* ── ROIC vs WACC ─────────────────────────────────────────── */
.rw-row { display: flex; gap: 12px; flex-wrap: wrap; }
.rw-card { flex: 1; min-width: 150px; border: 1px solid var(--rule); border-radius: 4px; padding: 13px 15px; background: var(--paper); }
.rw-k { font-size: 11px; color: var(--muted); margin-bottom: 5px; }
.rw-v { font-family: var(--mono); font-size: 22px; font-weight: 700; letter-spacing: -0.5px; }
.rw-years { display: flex; gap: 16px; flex-wrap: wrap; margin-top: 12px; font-size: 12px; color: var(--muted); }
.rw-yr { display: flex; gap: 6px; align-items: baseline; }
.rw-yr b { font-family: var(--mono); font-size: 13px; }

/* ── peer comparison ──────────────────────────────────────── */
.pr-row { display: flex; gap: 12px; flex-wrap: wrap; }
.pr-card { flex: 1; min-width: 140px; border: 1px solid var(--rule); border-radius: 4px; padding: 12px 14px; background: var(--paper); }
.pr-k { font-size: 11px; color: var(--muted); }
.pr-v { font-family: var(--mono); font-size: 21px; font-weight: 700; margin-top: 3px; }
.pr-d { font-size: 11.5px; font-weight: 600; margin-top: 3px; }

/* ── chart grid ───────────────────────────────────────────── */
/* The original lays the report out as st.columns(3) on every row, so nine
   charts fill three rows exactly instead of leaving an orphan. */
.qgrid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-md); }
.qchart { border: 1px solid var(--rule); border-radius: var(--radius-sm); padding: 10px 12px 6px; min-width: 0; background: var(--paper); }
.qtitle { font-size: 10.5px; font-weight: 700; letter-spacing: .7px; color: var(--muted); text-transform: uppercase; margin-bottom: 4px; }

/* ── foreign-flow stat row ────────────────────────────────── */
/* The original stacks the six figures as two st.columns(3) rows above the
   chart, not one row of six under it. */
.ff-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; padding: 10px 14px; }
.ff-stats + .ff-stats { padding-top: 0; }
.ff-tabs { margin-bottom: var(--space-sm); }
.ff-body { display: block; }
.ff-plot { margin-top: 4px; }
.ff-k { font-size: 11px; color: var(--muted); line-height: 1.35; overflow-wrap: anywhere; }
.ff-v { font-family: var(--mono); font-size: 16px; font-weight: 600; margin-top: 3px; white-space: nowrap; }

/* ── portfolio ────────────────────────────────────────────── */
.pf-add { display: flex; flex-wrap: wrap; gap: var(--space-sm); align-items: center; }
.pf-add input { font-family: var(--mono); font-size: 13px; padding: 8px 10px; border: 1px solid var(--rule-strong); border-radius: var(--radius-sm); background: var(--paper-2); color: var(--ink); }
.pf-add input:focus-visible { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-ring); }
.pf-del { border: none; background: none; color: var(--muted); cursor: pointer; font-size: 13px; padding: 2px 6px; border-radius: 4px; transition: color var(--dur) var(--ease-out); }
.pf-del:hover { color: var(--loss); }

/* ── screener filters ─────────────────────────────────────── */
.filters { display: flex; flex-wrap: wrap; gap: var(--space-md); align-items: center; margin-bottom: var(--space-md); padding-bottom: var(--space-md); border-bottom: 1px solid var(--rule); }
.filters label { font-size: 12px; color: var(--muted); display: flex; align-items: center; gap: 5px; }
.filters select, .filters input { font-family: var(--mono); font-size: 12px; padding: 6px 9px; border: 1px solid var(--rule-strong); border-radius: var(--radius-sm); background: var(--paper-2); color: var(--ink); }
.filters input { width: 64px; }
.filters select:focus-visible, .filters input:focus-visible { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-ring); }
.fcount { margin-left: auto; font-family: var(--mono); font-size: 11px; color: var(--muted); }

/* ── tables ───────────────────────────────────────────────── */
table.screen { width: 100%; border-collapse: collapse; font-size: 13px; }
table.screen th {
  text-align: right; padding: 9px 10px; font-size: 11px; color: var(--muted); border-bottom: 1px solid var(--rule-strong);
  font-weight: 600; position: sticky; top: 0; background: var(--bg);
}
table.screen th:first-child, table.screen th:nth-child(2) { text-align: left; }
table.screen td { text-align: right; padding: 8px 10px; border-bottom: 1px solid var(--rule); font-family: var(--mono); letter-spacing: -0.2px; }
table.screen td:first-child, table.screen td.dim { text-align: left; }
table.screen td:first-child b { color: var(--primary); }
table.screen td.dim { font-family: var(--sans); color: var(--muted); font-size: 12px; }
table.screen tbody tr { cursor: pointer; transition: background var(--dur) var(--ease-out); }
table.screen tbody tr:hover { background: var(--paper-3); }
table.screen tbody tr:hover td:first-child { box-shadow: inset 3px 0 0 var(--primary); }

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

@media (max-width: 820px) {
  body { grid-template-columns: 1fr; }
  .sidebar { position: static; height: auto; flex-direction: row; flex-wrap: wrap; align-items: center; gap: var(--space-md); }
  #nav { flex-direction: row; flex-wrap: wrap; }
  .meta { margin: 0; }
  .main { padding: var(--space-md); }
  .metrics { grid-template-columns: repeat(2, 1fr); }
  .sc-cells { flex-wrap: wrap; }
  .sc-cell { flex: 1 1 45%; }
  .qgrid { grid-template-columns: 1fr; }
  .stock-head { gap: var(--space-md); }
  .sh-right { text-align: left; min-width: 0; padding-right: 0; }
  .head-row { flex-direction: column; gap: var(--space-md); }
  .split { grid-template-columns: 1fr; gap: var(--space-xl); }
}
@media (max-width: 1200px) and (min-width: 821px) {
  .split { grid-template-columns: 3fr 2fr; }
  .vp-grid { grid-template-columns: 1fr; }
  /* Three plots side by side stop being readable below ~1200px: axis labels
     and legends start colliding. Step down to two rather than straight to one. */
  .qgrid { grid-template-columns: repeat(2, 1fr); }
}

/* self-relative valuation band */
.vb-row { margin-bottom: 8px; }
.vb-note { font-size: 12.5px; color: var(--neutral); margin-top: 8px; line-height: 1.6; }

/* screener signal-count row */
.sig-counts { display: grid; grid-template-columns: repeat(7, 1fr); gap: 16px; margin-bottom: var(--space-md); }
/* Two-tier chip: tonal when unselected, solid when selected. Colours are
   set inline per signal (see QC_COLORS); a white card with a coloured top
   rule is the design the original tried and rejected as washed out. */
/* Measured against the original: one uniform 16px/600 sans face on both
   lines, 20px line-height, 4px 12px padding, 56px tall. A big mono number
   over a small label made the chip top-heavy and mismatched. */
.sig-c { border-radius: 4px; padding: 4px 12px; height: 56px; cursor: pointer;
         text-align: center; font-family: var(--sans); font-size: 16px; font-weight: 600;
         line-height: 20px; display: flex; flex-direction: column; justify-content: center;
         transition: filter var(--dur) var(--ease-out); }
.sig-c:hover { filter: brightness(0.96); }
.sig-c:hover { background: var(--paper-3); }
.sig-n { font: inherit; color: inherit; }
.sig-l { font: inherit; color: inherit; }
@media (max-width: 900px) { .sig-counts { grid-template-columns: repeat(4, 1fr); } }
@media (max-width: 560px) { .ff-stats { grid-template-columns: repeat(2, 1fr); } }

/* market overview */
.split-31 { display: grid; grid-template-columns: 3fr 1fr; gap: 32px; align-items: start; }
.ad-ratio { font-family: var(--mono); font-size: 34px; font-weight: 800; line-height: 1.1; }
.ad-ratio-l { font-family: var(--sans); font-size: 13px; font-weight: 600; color: var(--muted); }
.ad-bar { display: flex; height: 26px; width: 100%; border-radius: 4px; overflow: hidden; margin: 14px 0 10px; background: var(--paper-3); }
.ad-legend { display: flex; justify-content: space-between; font-size: 12.5px; font-family: var(--mono); }
.ad-legend .dimtxt { color: var(--muted); font-family: var(--sans); }
.ad-total { font-size: 12px; color: var(--muted); margin-top: 8px; }
.mv-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 22px; }
.mv-card { min-width: 0; }
.mv-card .sec-h { font-size: 17px; }
@media (max-width: 1100px) { .mv-row { grid-template-columns: 1fr; } .split-31 { grid-template-columns: 1fr; } }

/* The foreign-trading card holds one chart plus a stat row, not a 2-up grid --
   inheriting .qgrid's two columns left the chart at half width with dead space
   beside it. */
.ff-grid { grid-template-columns: 1fr; }

/* Price change badge — the original wraps the change in a tinted pill whose
   hue encodes ceiling / up / flat / floor / down. */
.sh-chgbadge { display: inline-block; padding: 3px 9px; border-radius: 4px; font-weight: 600; }

/* compare view */
.cmp-pick { position: relative; }
.cmp-pick input { width: 260px; font-family: var(--mono); font-size: 13px; padding: 8px 10px; border: 1px solid var(--rule-strong); border-radius: var(--radius-sm); background: var(--paper-2); color: var(--ink); }
.cmp-pick input:focus-visible { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-ring); }
#cmp-sugg { position: absolute; z-index: 20; top: 40px; left: 0; width: 300px; max-height: 300px; overflow-y: auto; background: var(--paper); border: 1px solid var(--rule-strong); border-radius: var(--radius-sm); box-shadow: var(--shadow-2); }
.cmp-chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.cmp-chip { display: inline-flex; align-items: center; gap: 6px; font-family: var(--mono); font-size: 13px; font-weight: 600; background: var(--primary-soft); color: var(--primary); padding: 4px 8px; border-radius: 4px; }
.cmp-chip button { border: none; background: none; color: var(--primary); cursor: pointer; font-size: 12px; padding: 0 2px; }
.cmp-chip button:hover { color: var(--loss); }
.macro-tabs, .mo-tabs { flex-wrap: wrap; }

/* ── mobile fixes ─────────────────────────────────────────── */
@media (max-width: 820px) {
  /* Wide tables (screener, comparison, sector summary) scroll inside their own
     card instead of pushing the page sideways. */
  .card:has(table.screen) { overflow-x: auto; }
  table.screen { min-width: 560px; }
  /* The "Ngành" cell holds a long sector name; nowrap alone made it overflow
     its grid column. */
  .mv { overflow: hidden; text-overflow: ellipsis; }
  .cmp-pick input, #cmp-sugg { width: 100%; }
}

/* sector: top-5 per sector grid */
.top5-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 12px; }
.t5-box { border: 1px solid var(--rule); border-radius: 4px; padding: 10px 12px; background: var(--paper); min-width: 0; }
.t5-h { font-size: 11px; font-weight: 700; letter-spacing: .4px; color: var(--muted); text-transform: uppercase; margin-bottom: 6px; line-height: 1.3; overflow-wrap: anywhere; }
.t5-row { display: flex; justify-content: space-between; font-family: var(--mono); font-size: 12.5px; padding: 3px 0; cursor: pointer; border-radius: 3px; }
.t5-row:hover { background: var(--paper-3); }

/* financial-report tab strip inside the quarterly card */
.fin-tabs { flex-wrap: wrap; margin-bottom: var(--space-md); }

/* technical-analysis gauge sits above the verdict box */


/* ── scorecard hover tooltip (ported from the original) ───── */
.ttm-cell { position: relative; cursor: default; }
.ttm-tooltip {
  display: none; position: absolute; bottom: calc(100% + 10px); left: 50%;
  transform: translateX(-50%); background: var(--paper); border: 1px solid var(--rule-strong);
  border-radius: 4px; padding: 12px 14px; width: 240px; z-index: 40;
  box-shadow: 0 6px 24px rgba(10, 18, 29, 0.18); pointer-events: none; text-align: left;
}
.ttm-cell:hover .ttm-tooltip, .ttm-cell.tip-open .ttm-tooltip { display: block; }
/* Desktop keeps the original's bare tile: hover is discoverable there. A touch
   device has no hover at all, so it gets a mark saying the tile can be opened
   -- guarded by (hover: none) so the mouse layout is untouched. */
@media (hover: none) {
  .ttm-cell { cursor: pointer; }
  .ttm-cell .sc-k::after { content: " ⓘ"; color: var(--rule-strong); font-size: 10px; }
  .ttm-cell.tip-open { background: var(--paper-2); }
  .ttm-cell.tip-open .sc-k::after { color: var(--primary); }
}
.tt-f { font-size: 11px; color: var(--neutral); margin-bottom: 4px; font-style: italic; }
.tt-d { font-size: 12px; color: var(--neutral); margin-bottom: 10px; line-height: 1.45; }
.tt-bands { display: flex; flex-direction: column; gap: 4px; font-size: 11px; color: var(--neutral); }
.tt-bands i { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 6px; }
.ttm-tt-arrow {
  position: absolute; top: 100%; left: 50%; transform: translateX(-50%);
  border: 7px solid transparent; border-top-color: var(--rule-strong);
}

/* wide screener table scrolls inside its card rather than stretching the page */
table.screen-wide { min-width: 1100px; }

/* view title and chart context line */
.view-title { font-family: var(--mono); font-size: 28px; font-weight: 600; margin: 0 0 var(--space-lg); color: var(--ink); }
.chart-sub { font-size: 12.5px; color: var(--neutral); margin-bottom: 8px; font-family: var(--mono); }

/* On a phone the cell is ~172px wide but the tooltip is 240px, so centring it
   on the cell pushed it off both edges. Anchor it to the whole scorecard block
   instead — it stays readable at full width rather than being squeezed. */
@media (max-width: 820px) {
  .sc-block { position: relative; }
  .ttm-cell { position: static; }
  .ttm-tooltip { left: 8px; right: 8px; width: auto; transform: none; }
  .ttm-tt-arrow { display: none; }
}

/* news & events list */
.ne-tabs { margin-bottom: var(--space-md); }
/* Left border encodes recency (red today, orange this week, then the category
   hue), matching the original. */
.ne-item { padding: 9px 12px; margin-bottom: 6px; background: var(--paper);
  border: 1px solid var(--rule); border-left: 4px solid var(--rule-strong); border-radius: 4px; }
.ne-badge { display: inline-block; font-size: 10.5px; font-weight: 700; letter-spacing: .3px;
  padding: 2px 8px; border-radius: 4px; margin-right: 8px; vertical-align: 2px; white-space: nowrap; }
.ne-t { font-size: 13.5px; color: var(--ink); line-height: 1.55; }
.ne-t a { color: var(--primary); text-decoration: none; }
.ne-t a:hover { text-decoration: underline; }
.ne-d { font-size: 11.5px; color: var(--muted); margin-top: 3px; font-family: var(--mono); }


/* ── screener sidebar filters (the original keeps them in the sidebar) ── */
.side-filters { border-top: 1px solid var(--rule); margin-top: var(--space-md); padding-top: var(--space-md); display: flex; flex-direction: column; gap: 10px; }
.sf-h { font-family: var(--mono); font-size: 13px; font-weight: 700; color: var(--ink); letter-spacing: .02em; }
.sf-l { display: block; font-size: 12px; color: var(--muted); line-height: 1.5; }
.sf-l select, .sf-l input[type="range"] { width: 100%; margin-top: 4px; }
.sf-l select { font-family: var(--sans); font-size: 12px; border: 1px solid var(--rule); border-radius: 4px; background: var(--paper); color: var(--ink); padding: 3px; }
.sf-v { font-family: var(--mono); font-size: 12px; color: var(--accent); font-weight: 600; flex: 0 0 auto; }
.sf-c { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--muted); }
.sf-reset { align-self: flex-start; }
.sc-tabs { margin-bottom: var(--space-sm); }
.sc-bar { display: flex; justify-content: flex-end; margin-bottom: 8px; }
.wl-cell { text-align: center; width: 28px; }
.wl-star { border: 0; background: none; cursor: pointer; font-size: 14px; color: var(--rule); line-height: 1; padding: 0; }
.wl-star.on { color: #f59e0b; }

.cmp-ind { display: flex; align-items: center; gap: 8px; margin-top: 10px; font-size: 13px; color: var(--ink); cursor: pointer; }
.cmp-ind .dim { color: var(--muted); font-size: 12px; }

/* P/E and P/B sit side by side, as two st.columns in the original. */
.mkt-pair { display: grid; grid-template-columns: repeat(2, 1fr); gap: 22px; }
@media (max-width: 1100px) { .mkt-pair { grid-template-columns: 1fr; } }


/* ── phone layout ─────────────────────────────────────────────────
   Audited at 390px: the DuPont chain, the metric-selector rows and the
   header metric labels were the three things still overflowing. */
@media (max-width: 560px) {
  /* The DuPont chain is five boxes in a row; on a phone it has to wrap. */
  .dp-row { flex-wrap: wrap; gap: 8px; }
  .dp-row > * { flex: 1 1 46%; min-width: 0; }
  .dp-v { font-size: 17px; letter-spacing: 0; }
  .dp-k { white-space: normal; overflow: visible; text-overflow: clip; line-height: 1.35; }

  /* Selector rows (ranges, tabs, sector metrics) scroll sideways rather than
     spilling out of the card. */
  .range-row { flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch;
               padding-bottom: 4px; scrollbar-width: thin; }
  .range-btn { flex: 0 0 auto; }

  /* Header metric labels wrap instead of being cut mid-word. */
  .mk { white-space: normal; overflow: visible; text-overflow: clip; font-size: 13px; line-height: 1.3; }
  .mv { font-size: 18px; }

  .metrics { grid-template-columns: repeat(2, 1fr); gap: 10px; }
  .card { padding: 12px; }
  .sec-h { font-size: 20px; }
  .view-title { font-size: 22px; }
  /* Wide tables keep their own scroller; make sure nothing forces the page wide. */
  .screen-wide { min-width: 720px; }
  .ta-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .sig-counts { grid-template-columns: repeat(2, 1fr); }
  .top5-grid { grid-template-columns: 1fr; }
  .pr-row { grid-template-columns: repeat(2, 1fr); }
  .side-filters .sf-l select { max-width: 100%; }
}

/* Nothing may push the page itself sideways on a phone. */
@media (max-width: 820px) {
  html, body { max-width: 100%; overflow-x: hidden; }
  .main { min-width: 0; }
}

/* Measured: the right column is ~230px at a 1250px viewport and ~420px at
   1100px, so the tally table and the 150px gauge stop fitting side by side
   well before the old 1200px cut-off. Stack them up to 1360px. */
@media (max-width: 1360px) and (min-width: 821px) {
  .ta-top { grid-template-columns: 1fr; }
  .ta-top > * { justify-self: center; }
  .ta-count { width: 100%; }
}

/* Belt and braces for the gauge: never wider than the column that holds it. */
#ta-gauge { max-width: 100%; overflow: hidden; }

/* Filter panel: always open on desktop, collapsed behind a button on a phone. */
.sf-toggle { display: none; margin-bottom: var(--space-sm); }
@media (max-width: 820px) {
  .sf-toggle { display: inline-block; }
  .side-filters { display: none; }
  .side-filters.sf-open { display: flex; }
}

/* Comparison table: group headers and rank-shaded cells. */
/* Comparison table, styled after the original: zebra rows, hairline row
   rules, a divider between ticker columns, and a colour bar per header.
   These carry table.screen for the shared chrome, so a few of the screener's
   own alignment rules (which left-align its Mã and Tín hiệu columns) have to
   be undone here -- only the metric name column is left-aligned. */
table.screen.cmp-heat th:nth-child(2),
table.screen.cmp-heat td:nth-child(2) { text-align: right; }
table.screen.cmp-heat tbody tr { cursor: default; }
.cmp-heat { width: 100%; border-collapse: collapse; background: rgba(255,255,255,0.97); }
.cmp-heat th { text-align: right; padding: 12px 16px; font-size: 15px; font-weight: 700;
               border-bottom: 2px solid #cbd5e1; min-width: 130px; }
.cmp-heat th:first-child, .cmp-heat td:first-child {
  text-align: left; white-space: nowrap; min-width: 190px;
  font-size: 13px; font-weight: 400; color: var(--muted); border-top: 0; }
.cmp-heat tbody tr { border-bottom: 1px solid #e2e8f0; }
.cmp-heat tbody tr:nth-child(even):not(.cmp-grp) { background: rgba(0,0,0,0.025); }
/* One rule between columns so a wide table still reads as columns. */
.cmp-heat th + th, .cmp-heat td + td { border-left: 1px solid #eef2f7; }
/* Rank shows through weight, not through fading the text out. The original
   greys ranks 2+ to #64748b, but most cells are rank 2+, so the whole table
   read washed out. Everything stays at full ink; only the leader takes its
   column's colour. */
.cmp-heat .cmp-r0 { font-weight: 700; font-size: 14px; }
.cmp-heat .cmp-r1 { font-weight: 600; color: var(--ink); }
.cmp-heat .cmp-r2 { font-weight: 400; color: var(--ink); }
/* The sector mean is a reference, not a rival: its own hue, never ranked,
   never starred, and set apart by a rule so the eye reads it as the margin
   of the table rather than one more column of contenders. */
.cmp-heat .cmp-avg { font-weight: 600; color: #b45309; }
.cmp-heat th:last-child, .cmp-heat td:last-child { border-left: 2px solid #fed7aa; }
.cmp-heat .cmp-grp td { border-left: 0; background: var(--accent-tint, #eef4ff); color: #1e3a5f; font-size: 11.5px;
              font-weight: 700; letter-spacing: .10em; text-transform: uppercase;
              padding: 8px 16px; border-top: 2px solid #bfdbfe; }
.cmp-heat td.num { text-align: right; font-family: var(--mono); white-space: nowrap;
                   padding: 10px 24px; font-size: 13px; }

/* Cổ đông lớn & Ban lãnh đạo — collapsed by default, as in the original. */
.holders > summary, .hd-sum { cursor: pointer; list-style: none; font-size: 17px; }
.holders > summary::-webkit-details-marker { display: none; }
.holders > summary::before { content: "▸ "; color: var(--muted); }
.holders[open] > summary::before { content: "▾ "; }
.hd-body { margin-top: var(--space-md); }
.hd-split { display: grid; grid-template-columns: 3fr 2fr; gap: var(--space-xl); align-items: start; }
@media (max-width: 900px) { .hd-split { grid-template-columns: 1fr; } }

/* Comparison summary cards */
.cmp-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: var(--space-md); }
.cmp-card { border: 1px solid var(--rule); border-top: 3px solid; border-radius: 4px; background: var(--paper); padding: 12px 14px; }
.cmp-t { font-family: var(--mono); font-size: 16px; font-weight: 700; }
.cmp-w { font-family: var(--mono); font-size: 26px; font-weight: 700; color: var(--ink); margin: 4px 0 8px; }
.cmp-wl { font-family: var(--sans); font-size: 12px; font-weight: 400; color: var(--muted); margin-left: 6px; }
.cmp-l { font-size: 12px; color: var(--muted); line-height: 1.55; }
.cmp-l b { color: var(--ink); font-weight: 600; margin-right: 4px; }
/* Star inherits the cell colour, so it always matches its ticker. */
.cmp-star { color: currentColor; font-size: 10px; }

/* Holder names are long and the officer table is three wide columns; on a
   phone both need their own scroller rather than pushing the page sideways. */
@media (max-width: 700px) {
  .hd-body { overflow-x: hidden; }
  .hd-split > div { min-width: 0; }
}

/* Ticker search + sector quick-select, directly above the table. */
.sc-quick { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.sc-quick input, .sc-quick select { font-family: var(--sans); font-size: 13px; padding: 6px 10px;
  border: 1px solid var(--rule); border-radius: 4px; background: var(--paper); color: var(--ink); }
.sc-quick input { flex: 0 1 260px; }
.sc-quick .fcount { margin-left: auto; }
@media (max-width: 560px) { .sc-quick { flex-wrap: wrap; } .sc-quick input { flex: 1 1 100%; } }

/* ── screener sidebar: two slider columns and compact tag pickers ── */
.sf-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 14px; }
.sf-cols > div { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.sf-exp > summary { cursor: pointer; font-size: 12px; color: var(--muted); list-style: none; }
.sf-exp > summary::-webkit-details-marker { display: none; }
.sf-exp > summary::before { content: "▸ "; }
.sf-exp[open] > summary::before { content: "▾ "; }
.sf-exp > * { margin-top: 8px; }

/* Tag picker: chips plus a filter input, with an overlay list. Replaces a
   six-row list box that was taller than every slider put together. */
.sf-tags { position: relative; margin-top: 4px; }
.tp-box { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; min-height: 30px;
          border: 1px solid var(--rule); border-radius: 4px; background: var(--paper); padding: 3px 6px; }
.tp-chips { display: contents; }
.tp-chip { display: inline-flex; align-items: center; gap: 4px; background: var(--primary);
           color: #fff; border-radius: 3px; padding: 1px 4px 1px 6px; font-size: 11px; }
.tp-chip button { border: 0; background: none; color: #fff; cursor: pointer; font-size: 10px; padding: 0; line-height: 1; }
.tp-in { flex: 1 1 60px; min-width: 60px; border: 0; outline: none; background: none;
         font-family: var(--sans); font-size: 12px; color: var(--ink); padding: 2px; }
.tp-list { position: absolute; z-index: 30; left: 0; right: 0; top: 100%; max-height: 220px;
           overflow-y: auto; background: var(--paper); border: 1px solid var(--rule);
           border-radius: 4px; box-shadow: 0 6px 18px rgba(15,23,42,0.12); }
.tp-opt { padding: 5px 8px; font-size: 12px; cursor: pointer; }
.tp-opt:hover { background: var(--paper-3, #eef2f7); }
@media (max-width: 820px) { .sf-cols { grid-template-columns: 1fr 1fr; } }

/* Slider label and its value share a line and wrap together; the range input
   always takes a full row beneath them. At two columns the label alone is
   wider than the column, so it must be allowed to break. */
.sf-cols .sf-l { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 6px; }
.sf-k { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
.sf-cols .sf-l input[type="range"] { flex: 1 1 100%; margin-top: 2px; }

/* Switch, matching the original's st.toggle. The checkbox stays in the DOM
   for keyboard and screen-reader behaviour; only its rendering is replaced. */
.sw-in { position: absolute; opacity: 0; width: 0; height: 0; }
.sw { position: relative; flex: 0 0 auto; width: 34px; height: 20px; border-radius: 10px;
      background: var(--rule-strong, #ced5df); transition: background var(--dur) var(--ease-out); }
.sw::after { content: ""; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px;
             border-radius: 50%; background: #fff; box-shadow: 0 1px 2px rgba(15,23,42,0.25);
             transition: transform var(--dur) var(--ease-out); }
.sw-in:checked + .sw { background: var(--primary); }
.sw-in:checked + .sw::after { transform: translateX(14px); }
.sw-in:focus-visible + .sw { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Leader cell: a soft tint of its column's colour, one per row. */
.cmp-heat .cmp-r0 { border-radius: 3px; }

/* Label above a row of selector chips, as the original captions its radios. */
.sel-lab { font-size: 12px; color: var(--muted); margin-bottom: 6px; }

/* Four charts read better two-up than three-plus-one. */
.qgrid.grid-2 { grid-template-columns: repeat(2, 1fr); }
@media (max-width: 900px) { .qgrid.grid-2 { grid-template-columns: 1fr; } }

/* The four headline macro readings belong on one row; .metrics is three wide
   for the ticker header, which wrapped them 3 + 1. */
.metrics.metrics-4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 1100px) { .metrics.metrics-4 { grid-template-columns: repeat(2, 1fr); } }

/* Macro groups: a full-width lead chart, then rows sized so none is orphaned. */
.mc-row { display: grid; gap: var(--space-md); margin-bottom: var(--space-md); }
.mc-1 { grid-template-columns: 1fr; }
.mc-2 { grid-template-columns: repeat(2, 1fr); }
.mc-3 { grid-template-columns: repeat(3, 1fr); }
.mc-row > .qchart { min-width: 0; }
@media (max-width: 1200px) { .mc-3 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 820px) { .mc-2, .mc-3 { grid-template-columns: 1fr; } }

/* Compare picker: chips and the clear-all sit on one row. */
/* Sits in the chip row as its last item, so it is found where the chips are
   rather than at the far edge of the card. Muted until hover so it never
   competes with the mã themselves. */
.cmp-clear { display: inline-flex; align-items: center; gap: 5px; font-family: var(--sans);
  font-size: 12px; font-weight: 600; line-height: 1; color: var(--muted); cursor: pointer;
  background: none; border: 1px dashed var(--rule-strong); border-radius: 4px;
  padding: 5px 9px; margin-left: 2px; transition: color var(--dur) var(--ease-out),
  border-color var(--dur) var(--ease-out), background var(--dur) var(--ease-out); }
.cmp-clear:hover { color: var(--loss); border-color: var(--loss); border-style: solid;
  background: rgba(185, 28, 28, 0.06); }
.cmp-clear:focus-visible { outline: 2px solid var(--primary-ring); outline-offset: 1px; }
.cmp-empty { text-align: left; }
.cmp-empty-t { font-family: var(--mono); font-size: 15px; font-weight: 700; color: var(--ink); margin-bottom: 6px; }
