/* ============================================================
   MASTER VORTEX — platform prototype (design-fidelity shell)
   Brand: black base, electric green #1ee308, red #ff3b47
   Dashboard dock styling adapted from design/dashboard-prototype.html
   ============================================================ */
:root{
  --green:#1ee308;
  --red:#ff3b47;
  --bg:#010204;
  --panel:#070d18;
  --panel-2:#0a1322;
  --edge:#16283f;
  --ink:#e8f4ff;
  --dim:#8fa8c4;
  /* dashboard dock tokens (from dashboard-prototype.html) */
  --d-panel:#060b16; --d-edge:#1b3a5f; --d-row:#0a1322; --d-sep:#12233d;
  --d-label:#57b6ff; --d-green:#2ee66b; --d-red:#ff4d5e; --d-yellow:#ffd84d;
  /* LAYOUT COMPACTION 2026-10-28 (CEO: "make the chart bigger,
     bigger" — shrink every box around the chart, give the freed
     space to the canvas): rail 204px -> 178px. The wl column
     tracks are minmax() with mins re-derived for the narrower
     rail (see .wl-cols / .wl-item); all 20 rows stay usable. */
  --wl-width:178px;
}
*{box-sizing:border-box; margin:0; padding:0;}
b, strong{font-weight:400;}
html,body{height:100%;}
body{
  background:var(--bg); color:var(--ink);
  font-family:"Segoe UI", Arial, Helvetica, sans-serif;
  display:flex; flex-direction:column; overflow:hidden;
}

/* ---------------- Top bar ---------------- */
.topbar{
  /* LAYOUT COMPACTION 2026-10-28: 48px floor -> 42px and tighter
     gaps/padding across every top-bar control family (see the
     .topbar-scoped overrides below). Measured anatomy of the old
     99px bar: the brand line held only ~334px of content while
     .top-right wrapped AS A UNIT to a second line and wrapped
     again inside itself. flex-wrap:nowrap keeps brand + title +
     controls on ONE line; the controls wrap inside .top-right's
     own box (flex:1 1 auto, min-width:0) in two slim sub-rows.
     The <=900px media query below restores wrap for phones. */
  min-height:42px; flex:0 0 auto; display:flex; align-items:center; gap:4px;
  flex-wrap:nowrap;
  padding:0 8px; background:linear-gradient(180deg,#07130a 0%, #020604 78%);
  border-bottom:1px solid rgba(30,227,8,.28);
  box-shadow:0 6px 24px rgba(30,227,8,.07);
}
.brand{display:flex; align-items:center; gap:6px; flex:0 0 auto;}
.brand img{width:20px; height:20px; object-fit:cover; border-radius:8px;
  border:1px solid rgba(30,227,8,.45); background:#0a1a0c;}
.brand .wordmark{line-height:.95; font-weight:400; font-style:italic; white-space:nowrap;}
.brand .wordmark .pos{color:#ffffff; font-size:10px; letter-spacing:.4px;}
.brand .wordmark .pos .dollar{color:var(--green);}
.brand .wordmark .en{display:block; color:var(--green); font-size:7px; letter-spacing:1.8px;}
.vr{width:1px; height:22px; background:rgba(30,227,8,.35); flex:0 0 auto;}
.title{display:flex; align-items:center; gap:5px; white-space:nowrap;
  flex:0 0 auto; margin-left:2px;}
.title svg{width:16px; height:16px;}
.title svg{flex:0 0 auto; filter:drop-shadow(0 0 9px rgba(30,227,8,.55));}
.title h1{
  color:var(--green); font-size:14px; font-weight:400; letter-spacing:.5px;
  text-shadow:0 0 22px rgba(30,227,8,.35);
}
.top-right{margin-left:auto; display:flex; align-items:center; gap:2px 4px;
  flex:1 1 auto; min-width:0; flex-wrap:wrap;}
.tf-group{display:flex; gap:3px;}
.tf{
  background:#101823; color:#dfe9f5; border:1px solid #1d2c42; border-radius:8px;
  font-size:11.5px; font-weight:400; padding:2px 4px; cursor:pointer; font-family:inherit;
}
.tf:hover{border-color:rgba(30,227,8,.5); color:#fff;}
.tf.active{background:var(--green); color:#03140a; border-color:var(--green);
  box-shadow:0 0 14px rgba(30,227,8,.45);}
.proto-tag{
  font-size:9.5px; font-weight:400; letter-spacing:.8px; color:var(--d-yellow);
  border:1px solid rgba(255,216,77,.55); border-radius:20px; padding:2px 5px; white-space:nowrap;
}
.icon-btn{
  width:24px; height:24px; border-radius:50%; border:1px solid transparent;
  background:transparent; color:var(--green); font-size:14px; cursor:pointer; line-height:1;
}
/* Pass 4 compaction: view tabs share the slimmer top-bar scale.
   Padding/size only — the .active color pairing lives in
   screener.css / news.css and is untouched.
   LAYOUT COMPACTION 2026-10-28: one notch tighter again. */
.topbar .view-tab{padding:3px 5px; font-size:11px;}
/* Top-line fit pass (2026-10-23, CEO: the RSI/MACD/VOLUME pane
   buttons join the top line and it ALL has to be seen): the line
   is compacted across every control family, and the bar wraps
   INSIDE the header when a window is narrower than the full line
   instead of clipping the tail controls off-screen (the wrap
   already existed at <=900px; the fixed 48px height is now a
   minimum, so wide windows keep the exact one-row 48px bar).
   Module files keep their own rules; these .topbar-scoped
   overrides only trim padding/size in the header. */
.topbar .mc-switch{gap:3px;}
.topbar .mc-layout-btn{padding:3px 6px; font-size:12px;}
.topbar .ct-btn{height:24px; padding:0 6px;}
.topbar .tf-menu-btn{padding:3px 6px; font-size:11.5px;}
.topbar .replay-btn{padding:3px 6px; font-size:11px;}
.topbar .sp-top-btn{padding:3px 5px;}
.topbar .mv-session-chip{padding:3px 8px; font-size:10.5px;}
.topbar .mv-fp-btn{padding:3px 6px; font-size:11px;}
.icon-btn:hover{border-color:rgba(30,227,8,.4);}

/* ---------------- Main grid ---------------- */
.main{flex:1 1 auto; display:flex; min-height:0;}

/* Watchlist */
.watchlist{
  flex:0 0 var(--wl-width); background:var(--panel); position:relative; border-right:1px solid var(--edge);
  margin:2px 0 2px 2px; border:1px solid var(--edge); border-radius:10px;
  display:flex; flex-direction:column; overflow-x:hidden; overflow-y:auto;
  /* Rail scroll (2026-10-26 CEO live-session fix): the rail stacks
     watchlist + LISTS + runners in one fixed-height column. With
     overflow:hidden the panels that could not shrink ate the whole
     column and the watchlist was crushed to 0px with NO way to
     scroll anything — "stuck up there, can't bring it down". The
     rail itself now scrolls vertically as the final guarantee that
     every panel stays reachable at any viewport height; in the
     common case the flex floors below keep everything on screen
     and no rail scrollbar appears. */
}
.wl-head{
  padding:4px 7px; color:var(--green); font-weight:400; letter-spacing:1.2px; font-size:11px;
  border-bottom:1px solid var(--edge); display:flex; align-items:center; gap:6px;
}
.wl-head .star{color:var(--green); font-size:12px;}
/* FOUR-COLUMN header (CEO 2026-11-04 ~5:48pm CT): SYM | LAST |
   $ CHG | % CHG — the sort spans keep their order (children
   0/1/2/3 = sym/last/$chg/%chg for initWlSort; BOTH change
   spans carry the 'chg' sort key, which reads the % column). */
.wl-cols{
  display:grid; grid-template-columns:minmax(0,.8fr) minmax(0,.72fr) minmax(0,.8fr) minmax(0,.68fr); column-gap:6px; align-items:baseline;
  padding:2px 7px 1px; border-bottom:1px solid var(--edge);
  font-size:9px; font-weight:400; letter-spacing:.4px; color:#5f7699; text-transform:uppercase;
}
.wl-cols span{text-align:center;}
.wl-cols span:first-child{text-align:left;}
/* min-height floor (2026-10-26 CEO live-session fix): the list is
   the rail's only flexible element, so every fixed panel below it
   (LISTS chrome, the fixed-height runners box) used to take its
   space first and crush the list — 149px at 900px viewport height,
   0px (invisible, ungrabbable) at 768px. The floor is the full
   8-row content height (162px), so the whole watchlist is always
   on screen; anything the rail cannot fit goes to the rail's own
   scroll instead. overflow-x hidden plus the 6px row padding kills
   the spurious horizontal scrollbar (columns 190px + padding used
   to total 204px in a 202px box) that stole another ~15px. The
   row/column tracks are minmax() so they also compress to fit
   when the rail narrows (a rail scrollbar or a user-dragged
   narrower rail leaves ~187px — fixed tracks overflowed that). */
.wl-list{flex:1 1 auto; min-height:162px; overflow-y:auto; overflow-x:hidden; position:relative;}
/* Full-height column dividers (CEO 2026-11-04): one overlay on the
   scroll container — lines at the SYM|LAST and LAST|CHG track
   boundaries, continuous over the whole scroll height. */
/* The old column-divider overlay pseudo-element that rode this list is
   DELETED (CEO shading fix 2026-11-04 ~5:36pm CT): its gradient ran
   transparent -> line color across each whole segment, painting a soft
   blue wash instead of crisp lines, and the overlay was only as tall as
   the visible box, so the wash covered just the first screenful of rows.
   Dividers now ride on the row cells — see the tail block of this file. */
/* CENTERED EVERYWHERE (CEO alignment order 2026-11-04 ~4:03pm CT): every character in every watchlist cell/box sits CENTERED (middle plane) — symbol, name, last, $chg, %chg — all lists, all bands. Do not re-right-align. */
/* TV ROWS (CEO 2026-11-04 ~2:17am CT, supersedes the 5-column
   grid + the centered column-line passes of earlier tonight):
   every row is the TradingView two-block shape — LEFT: symbol
   bold over the muted company name; RIGHT (right-aligned): LAST
   over "$chg %chg" on one line, sign-colored, exactly ONE change
   group per row. The VOL and EXT columns and their "—"
   placeholders are gone; a genuine extended-hours print adds a
   third muted line under the change (paintWlItem only). The
   dashboard-strength row divider stays; there are no vertical
   column lines — the two blocks align by the flex edges, like
   the dashboard boxes align by their grid. */
/* REORGANIZED GRID (CEO 2026-11-04 ~5:06pm CT — supersedes the
   TV-rows two-block for the row body): the two content-sized
   flex blocks read as disorganized — the values block took a
   different width on every row, so LAST and CHG never lined
   up, and once the company-name line was removed the lone
   ticker floated against a two-line stack. Every row is now
   ONE grid on shared tracks — SYM | LAST | $CHG %CHG on a
   single line, every value centered in its column (the
   middle-plane law), the divider under every row, and the
   header (.wl-cols) runs the identical template so the
   labels sit exactly over their columns. A genuine extended
   print adds the moon line on a full-width second row of
   the grid; no print, no line, no dash.
   FOUR COLUMNS (CEO 2026-11-04 ~5:48pm CT — supersedes the
   shared CHG cell of the reorganization above): $ CHG and
   % CHG are SEPARATE columns on the row grid — SYM | LAST |
   $CHG | %CHG, each value in its own track on every row and
   a divider between every pair of columns (cell borders,
   tail block), so each column reads as one straight line
   of numbers down the whole list. The painters write the
   .usd / .pct cells directly; the header sort reads .pct. */
.wl-item{
  position:relative;
  display:grid; grid-template-columns:minmax(0,.8fr) minmax(0,.72fr) minmax(0,.8fr) minmax(0,.68fr); column-gap:6px; align-items:center;
  padding:3px 7px; border-bottom:1px solid rgba(85,135,210,.6); cursor:pointer; line-height:1.25;
  font-variant-numeric:tabular-nums;
}
.wl-item:hover{background:#0a1524;}
.wl-item.active{background:#0b1a10; box-shadow:inset 3px 0 0 var(--green);}
/* (the row cells are flat grid children now — no identity or
   values wrapper blocks; the .nm rule below survives only as
   a rule — the name node itself is gone by the tickers-only
   order and is never painted) */
.wl-item .sym{font-size:10.5px; font-weight:600; letter-spacing:0; text-align:left; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
.wl-item .nm{font-size:9.5px; font-weight:400; text-align:center; color:#8fa8c4; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
.wl-item .px{font-size:11.5px; font-weight:400; text-align:center;}
.wl-item .px.up{color:var(--green);}
/* FOUR COLUMNS (CEO 2026-11-04 ~5:48pm CT): the $ change and
   the % change are flat cells of the row grid now — each in
   its own track, centered in its column like LAST. (The old
   shared .chg cell put both values in one sub-grid; the
   header sort reads the .pct cell directly — wlRowData.) */
.wl-item .usd{font-size:10.5px; font-weight:400; text-align:right;}
.wl-item .pct{font-size:10px; font-weight:400; text-align:right;}
.wl-item .ext .ex-chg.up{color:var(--green);}
.wl-item .ext .ex-chg.dn{color:var(--red);}
.wl-item .usd.up, .wl-item .pct.up{color:var(--green);}
.wl-item .usd.dn, .wl-item .pct.dn{color:var(--red);}
/* Watchlist remove control (audit 11b): a small × pinned to the
   row's right edge, revealed on hover so the resting row keeps its
   exact grid. It overlays the Ext cell while shown — the row's
   click target everywhere else still loads the symbol. */
.wl-rm{
  position:absolute; right:2px; top:50%; transform:translateY(-50%);
  display:none; width:16px; height:16px; padding:0; line-height:1;
  font-size:12px; text-align:center; cursor:pointer; z-index:2;
  color:#9fb6d8; background:#16283f; border:1px solid var(--edge); border-radius:3px;
}
.wl-item:hover .wl-rm{display:block;}
.wl-rm:hover{color:#ff7a7a; border-color:#ff7a7a;}
/* Drag-to-reorder (CEO 2026-11-02): press-hold a rail row and drag
   it to a new position. The dragged row lifts as a floating clone;
   the source row dims in place so the list never reflows mid-drag,
   and the teal inset line marks the drop slot. Price paints keep
   landing in the real rows by symbol — a paint never moves a row. */
.wl-item.mv-drag-src{opacity:.45;}
.wl-item.mv-drag-float{position:fixed; z-index:999; pointer-events:none; margin:0;
  box-shadow:0 10px 28px rgba(0,0,0,.55); background:#0b1a10;}
.wl-item.mv-drop-before{box-shadow:inset 0 2px 0 #2bd9c7;}
.wl-item.mv-drop-after{box-shadow:inset 0 -2px 0 #2bd9c7;}
/* The selected-symbol detail card that used to live under the
   watchlist moved onto the chart pane header (.chart-symbar, see
   the chart column section) in the 2026-10-22 layout pass. */
.up{color:var(--green);} .dn{color:var(--red);}
.wl-add{padding:4px 5px; display:flex; flex-wrap:wrap; gap:5px;}
.wl-add input{
  flex:1 1 70px; min-width:0; padding:4px 6px; background:#0a1524; color:#e8f2ff;
  border:1.5px solid #1c3350; border-radius:8px; font-size:11px;
  font-weight:400; letter-spacing:.8px; font-family:inherit; text-transform:uppercase;
}
.wl-add input:focus{outline:none; border-color:rgba(30,227,8,.65);}
.wl-add button{
  flex:0 0 auto; padding:4px 7px; background:transparent; color:var(--green);
  border:1.5px solid rgba(30,227,8,.65); border-radius:8px; font-size:11px;
  font-weight:400; letter-spacing:.8px; cursor:pointer; font-family:inherit;
}
.wl-add button:hover{background:rgba(30,227,8,.12);}
.wl-add button:disabled{opacity:.5; cursor:wait;}
.wl-add-msg{flex:1 1 100%; font-size:11px; font-weight:400; color:#9fb6d8; min-height:0;}
.wl-add-msg.err{color:var(--red);}

/* Watchlist: no red — down moves render neutral gray; errors amber */
.watchlist .dn{color:#c9d6e8;}
.watchlist .wl-add-msg.err{color:#ffd84d;}
/* Watchlist resize handle (wl-resize.js) */
.wl-resize-handle{position:absolute; top:0; right:0; width:6px; height:100%; cursor:ew-resize; z-index:20; touch-action:none;}
.wl-resize-handle:hover, .wl-resize-handle.dragging{background:rgba(30,227,8,.35);}
@media (max-width: 900px){ .wl-resize-handle{display:none;} }


/* Chart column */
.chart-col{
  flex:1 1 auto; min-width:0; display:flex; flex-direction:column;
  background:var(--panel); border:1px solid var(--edge); border-radius:10px;
  margin:2px; overflow:hidden;
}

.tool.alerts .dot{color:var(--red);}
/* Chart stack: main price pane ~68% of the column height, then three slim
   sub-panes (VOLUME / MACD / RSI) spanning the chart column width only. */
.chart-stack{flex:1 1 auto; min-height:0; display:flex; flex-direction:column;}
/* Selected-symbol price line: the chart pane's header strip (the
   price block removed from the watchlist rail in the 2026-10-22
   layout pass lives here now, above the price pane). */
.chart-symbar{
  flex:0 0 auto; display:flex; align-items:baseline; gap:7px;
  padding:2px 8px; border-bottom:1px solid var(--edge);
  font-variant-numeric:tabular-nums; white-space:nowrap; overflow:hidden;
}
.csb-sym{font-size:12px; font-weight:400; letter-spacing:.4px;}
.csb-name{font-size:10px; font-weight:400; color:#9fb6d8; overflow:hidden; text-overflow:ellipsis;}
.csb-px{font-size:12.5px; font-weight:400;}
.csb-chg{font-size:11px; font-weight:400;}
.csb-ext{font-size:10px; font-weight:400; color:#9fb6d8;}
.csb-ext[hidden]{display:none;}
.pane{position:relative; min-height:0;}
/* Price pane is a ROW: the docked drawing toolbar (drawings.js,
   .mv-tools, 37px) sits in flow on the left and the chart area
   takes the rest — the chart starts at the toolbar's right edge. */
/* LAYOUT COMPACTION 2026-10-28: price pane share of the stack
   65/(65+30) = 68% -> 84/(84+18) = 82%; the three built-in
   sub-panes stay readable at ~6/102 of the stack each
   (~33px at a 773px-tall window, ~46px at 1080px). Because the
   stack itself grew ~73px in the same pass, the sub-panes end
   up within ~3px of their old absolute height — the price pane
   takes essentially all of the growth. */
.pane-price{flex:84 1 0; display:flex; flex-direction:row;}
.mv-chart-area{position:relative; flex:1 1 auto; min-width:0; min-height:0;}
.pane-sub{flex:6 1 0; border-top:1px solid var(--edge);}
.pane-chart{position:absolute; inset:0;}
.pane-label{
  position:absolute; top:3px; left:8px; z-index:5; pointer-events:none;
  font-size:10px; font-weight:400; letter-spacing:1.4px; color:var(--dim);
}

/* ---------------- Dashboard dock (adapted from dashboard-prototype.html) ---------------- */
.dock{
  /* CEO layout pass 2026-10-22: dock halved 312px -> 156px with
     compact contents; the freed width goes to the chart.
     CEO correction 2026-10-22 ~11:59pm CT: at 156px the dash rows
     had to stack each metric pair on two lines; he ordered the
     pairs back side by side (three columns, one line level) while
     staying space-cognizant. 210px was the computed legibility
     floor for that pairing (labels 9px / values 10px, no token
     clipped; a zero-wrap layout measures ~283px).
     MISSING-ROWS FIX 2026-10-23 (CEO live report ~12:21am CT:
     dock "only stops at ADX and EST FLOW"): at 210px the pair-B
     cell was ~71px wide, so nearly every row wrapped to two
     lines and the 29-row table measured ~786px tall — taller
     than the dock at any window under ~1010px, so the last three
     rows (MKT OPEN / MACD+ATR / MKT BULL+SWEEP LVL) sat below an
     effectively invisible 8px scrollbar and read as missing.
     The engine/API always sent all 31 rows; this was purely a
     fit problem. Dock 210px -> 248px with rebalanced columns
     (48/66/1fr) gives pair B ~116px of text room: the table now
     measures ~550px and ALL rows fit with no scrolling at
     window heights >= ~768px (verified in headless Chromium at
     1080/900/864/768). Still 64px slimmer than the original
     312px dock; below ~768px the dock scrolls with a visible
     scrollbar + scroll shadows (see .dash-scroll.has-overflow).
     FILL + CENTER + SLIM PASS 2026-10-23 (CEO ~1:28am CT: "fit
     all the columns in the box so there's not empty spaces on
     the bottom... align the words and the numbers in the middle
     of every box... squeeze the width skinnier"; doctrine: use
     every space, no blank space anywhere, the chart is
     important): at 248px the ~550px table sat at the top of an
     ~878px scroll area at 1080p — a 328px dead void at the
     bottom of the box — and two worst-case strings actually
     CLIPPED (CUP/HANDLE by 6px in its 66px column, SUPPORT by
     3px in its 48px column, both measured in headless Chromium
     against a worst-case payload built by the real engine).
     Now: the table is a flex column that fills the dock height
     with rows distributing evenly (no bottom void at any
     height; short windows still scroll with the shadows), all
     cell content is centered horizontally and vertically, and
     the columns were re-derived from layout-measured worst
     cases — col 1 49px (longest label word SUPPORT 43.3px),
     col 2 70px (longest unbreakable value CUP/HANDLE 64.5px),
     col 3 the rest (binding single-line pair RSI STATE +
     OVERBOUGHT = 118.3px incl. the trimmed 2px pair-label
     margin). 244px is the measured floor for that contract:
     at 242px the RSI pair itself wraps (verified), and 244px
     is also exactly where .dash-sub stays on one row. The
     only worst-case pair-B wraps left are inside multi-token
     values at their own spaces (SELL CONTROL, WAIT C100/P100,
     RANGE+VWAP) — nothing clips anywhere. Panel gutters in
     .main trimmed 6px -> 3px in the same pass; total chart
     gain vs the 248px layout: +16px width, +6px height.
     One-line reverts: dock width in this rule; row template,
     td padding/alignment in the .dash rules below. */
  /* Width stays 244px — the measured legibility floor for the
     31-row paired table (see the long note above; 242px wraps
     the RSI pair). LAYOUT COMPACTION 2026-10-28 trims only the
     dock's vertical chrome below. */
  /* ALIGNMENT PASS 2026-11-02 (CEO spot ~11:03pm CT, from his
     iPad screenshot: the dock "doesn't look organized... The
     spaces and data and columns need to be aligned and clean
     looking organized looking"): the dock goes back to the
     design spec's strict FOUR-column table (label | value |
     label | value — DASHBOARD-SPEC.md: "table 4 columns x 31
     rows"). The 2026-10-22 three-column pairing had merged
     pair B into one inline cell (label span + value span), so
     pair-B values started at a different x on every row and
     wrapped under their labels — the ragged look he circled.
     Columns are now fixed px sized from the engine's full
     string inventory, measured in Chromium (Arial/Liberation
     metrics): col 1 70px (longest label SESSION HIGH, 60px at
     9px), col 2 94px (longest value A, 84px at 10px — VWAP
     price + ABOVE at BTC scale, WAIT C100/P100, macro
     price + pct), col 3 65px (SESSION LOW, 55px), col 4
     minmax(101px,1fr) (sized for the widest pair-B value of
     all - a crypto-scale GAP ZONE line, two 8-digit prices
     joined by a dash, 102px; the 1fr absorbs the 10px
     scrollbar on short windows so no value ever clips). Cells are white-space:nowrap and left-aligned:
     every label starts on the same x and every value aligns on
     the same x down the whole panel. The engine's designed
     two-line values (patterns, FVG zone, gap type, impact —
     literal newlines in the model) keep exactly their two
     lines via <br>. Dock 244px -> 342px is the honest cost of
     one-line, never-wrapped values at the locked 9px/10px
     fonts.
     CENTER + TRIM PASS 2026-11-04 (CEO voice order ~1:35am CT,
     from his iPad screenshot of the owner view: "everything is
     moved to the left... they need to be center plain in every
     single box... get rid of the empty spots to make room for
     the chart to become bigger"): every dash cell is
     CENTER-aligned (supersedes the 2026-11-02 left-align
     choice; the four real columns stay, so each column still
     shares one x down the panel), and the dock trims
     342px -> 334px by folding cell padding into the column
     widths (70/94/65 -> 68/92/63, td padding 3px -> 2px a
     side): every column's measured content room is IDENTICAL
     to the 2026-11-02 contract (62px / 86px / 57px), col 4
     keeps its minmax(101px,1fr) floor, nothing can newly
     clip, and the freed 8px goes to the chart. */
  /* DEPTH REMOVAL + DOCK SLIM 2026-11-04 (CEO voice orders
     ~3:43pm CT): Depth stays out (removed from this tree
     earlier tonight; production followed in the same pass),
     and the dock is slimmed to the WATCHLIST RAIL's width: it
     flexes to var(--wl-width), the rail's own variable — 256px
     at 901-1150, 280px at 1151-1400, the rail's drag-resize
     width (180-380px, default ~204px) on desktop — so the two
     side panels are always the same size and every reclaimed
     pixel goes to the chart (flex:1). The dash adapts inside
     its own panel only, in the tail section at the end of this
     file: COMPRESSION ONLY in every band — the four-column
     grid (label | value | label | value), field set and field
     order are FROZEN (CEO refinement 2026-11-04 ~4:02pm CT);
     an earlier labels-over-values two-line flow at 901-1150
     and on desktop was reverted the same evening. Cells stay
     CENTER-aligned in every band (CEO 2026-11-04 center pass).
     The 334px four-column layout below remains the base
     contract for the full-width stack band (<=900px). */
  flex:0 0 var(--wl-width); margin:2px 2px 2px 0; display:flex; flex-direction:column; min-height:0;
}
.dash{
  flex:1 1 auto; min-height:0; display:flex; flex-direction:column;
  background:var(--d-panel); border:1px solid var(--d-edge); border-radius:6px;
  overflow:hidden; box-shadow:0 0 34px rgba(30,120,255,.12);
}
.dash-head{display:flex; align-items:center; justify-content:space-between;
  padding:2px 6px; background:#0a1626; border-bottom:1px solid var(--d-edge); flex:0 0 auto;}
.dash-head .t{font-size:10px; font-weight:400; letter-spacing:.8px; white-space:nowrap;}
.dash-head .t .swirl{color:var(--d-green);}
.dash-head .ctl{color:var(--dim); font-size:9px; letter-spacing:1px;}
.dash-banner{
  flex:0 0 auto; text-align:center; padding:2px 4px;
  background:var(--d-green); color:#03140a;
  font-size:10px; font-weight:400; letter-spacing:1px;
}
.dash-sub{display:flex; flex-direction:row; flex-wrap:wrap; column-gap:8px; row-gap:1px;
  align-items:baseline; padding:1px 6px;
  background:rgba(46,230,107,.10); border-bottom:1px solid var(--d-edge);
  font-size:10px; font-weight:400; letter-spacing:.4px; flex:0 0 auto;}
.dash-sub .state{color:var(--d-green);}
.dash-scroll{flex:1 1 auto; overflow-y:auto; min-height:0;
  display:flex; flex-direction:column;
  scrollbar-width:thin; scrollbar-color:#2a5aa8 rgba(85,135,210,.14);}
/* Overflow must never read as "rows are missing" again: when the
   table genuinely exceeds the dock (short windows), renderDashboard
   tags .has-overflow and these scroll shadows fade in at the edge
   that has more content; the scrollbar is wide/bright enough to
   see. When everything fits, no shadows and no scrollbar. */
.dash-scroll.has-overflow{
  background:
    linear-gradient(var(--d-panel) 30%, rgba(6,11,22,0)) center top / 100% 14px,
    linear-gradient(rgba(6,11,22,0), var(--d-panel) 70%) center bottom / 100% 14px,
    radial-gradient(farthest-side at 50% 0, rgba(0,0,0,.5), rgba(0,0,0,0)) center top / 100% 10px,
    radial-gradient(farthest-side at 50% 100%, rgba(0,0,0,.5), rgba(0,0,0,0)) center bottom / 100% 10px;
  background-repeat:no-repeat;
  background-attachment:local, local, scroll, scroll;
}
.dash-scroll::-webkit-scrollbar{width:10px;}
.dash-scroll::-webkit-scrollbar-track{background:rgba(85,135,210,.10);}
.dash-scroll::-webkit-scrollbar-thumb{background:#2a5aa8; border-radius:5px;}
/* The state model is a strict 4-cell row (label / value / label /
   value — two natural pairs, 31 rows, unchanged). CEO three-column
   pairing (2026-10-22 ~11:59pm CT): each row renders as THREE
   columns on ONE line level — label A | value A | pair B (label +
   value in a single cell) — so CALL sits beside PUT, RSI beside
   RSI STATE, BUY PRESS beside SELL PRESS. Column widths are sized
   from the model's real worst-case strings: col 1 fits the
   longest label word, col 2 the longest unbreakable value token,
   col 3 the longest pair-B value token; on the longest rows text
   wraps only at token boundaries (never mid-number, never
   clipped). Pure presentation; the row model is untouched.
   2026-10-23 missing-rows fix: columns rebalanced 51/76 -> 48/66
   and the dock widened to 248px (see .dock note) so pair B fits
   on one line for all but the designed-multiline rows; row
   padding/line-height tightened so the whole table fits the
   dock at window heights >= ~768px.
   2026-10-23 fill/center/slim pass (see .dock note): the table
   is a flex column stretched to the scroller's full height and
   each row flexes (1 0 auto — grows to distribute the height,
   never shrinks below its content, so short windows scroll
   instead of squashing rows); columns re-derived 49/70/1fr at
   the 244px dock; cell padding symmetric (centering freed the
   old 4px left pad) and every cell's content is centered
   horizontally (text-align) and vertically (align-content).
   2026-11-02 alignment pass: superseded in part — the grid is
   now FOUR fixed columns (70/94/65/minmax(101px,1fr)), cells
   are left-aligned and nowrap; see the .dock note. */
.dash table{width:100%; border-collapse:collapse; table-layout:fixed; font-size:10px;
  flex:1 1 auto; display:flex; flex-direction:column;}
.dash tbody{flex:1 1 auto; display:flex; flex-direction:column; min-height:0;}
.dash tr{display:grid; grid-template-columns:68px 92px 63px minmax(101px,1fr); flex:1 0 auto;}
.dash td{
  width:auto; padding:0 2px 1px; text-align:center; vertical-align:middle; align-content:center;
  border:1px solid rgba(85,135,210,.30); white-space:nowrap; overflow:hidden;
  line-height:1.12; font-variant-numeric:tabular-nums;
}
.dash td.lc{font-size:9px;}
.dash td.lc{color:var(--d-label); font-weight:400;}
.dash td.vc{font-weight:400;}
/* Pair-B composite spans (.pbl/.pbv) retired 2026-11-02: pair B renders as real cells. */
.dash .g{color:var(--d-green);} .dash .r{color:var(--d-red);}
.dash .y{color:var(--d-yellow);} .dash .w{color:var(--ink);}
.dash .foot{padding:2px 6px; color:var(--dim); font-size:9px;
  border-top:1px solid var(--d-edge); text-align:center; flex:0 0 auto;}

/* ---------------- Ticker tape ---------------- */
.tape{
  flex:0 0 22px; border-top:1px solid rgba(30,227,8,.3); background:#020604;
  overflow:hidden; display:flex; align-items:center;
}
.tape-track{display:flex; white-space:nowrap; animation:tape 92s linear infinite; will-change:transform;}
.tape:hover .tape-track{animation-play-state:paused;}
@keyframes tape{from{transform:translateX(0);} to{transform:translateX(-50%);}}
.tape .q{font-size:12px; padding:0 5px;}
.tape .q b{color:#fff; font-weight:400;}
.tape .sep{color:#33506e; padding:0 4px;}

/* ---------------- Mobile (phones / narrow screens) ----------------
   Desktop is a fixed row: watchlist 232px + chart + dock 412px, which
   crushes the chart to zero width on a phone. Below 900px the layout
   stacks vertically and the page scrolls: compact top bar, watchlist
   as a horizontal strip, chart at a fixed tall height, dock below. */
@media (max-width: 900px){
  body{overflow-y:auto;}
  .topbar{height:auto; flex:0 0 auto; flex-wrap:wrap; gap:8px; padding:10px 12px;}
  .brand img{width:34px; height:34px;}
  .brand .wordmark .pos{font-size:15px;}
  .brand .wordmark .en{font-size:10px; letter-spacing:3px;}
  .vr{display:none;}
  .title svg{width:19px; height:19px;}
  .title h1{font-size:15px; letter-spacing:.5px;}
  .top-right{margin-left:0; flex-wrap:wrap; gap:8px;}
  .tf{padding:7px 11px; font-size:13px;}
  .proto-tag{display:none;}
  .main{flex:0 0 auto; flex-direction:column; min-height:auto;}
  .watchlist{flex:0 0 auto; margin:8px 8px 0;}
  .wl-cols{display:none;}
  .wl-list{display:flex; overflow-x:auto; overflow-y:hidden; min-height:0;}
  .wl-item{flex:0 0 auto; min-width:216px; padding:5px 8px; border-bottom:none; border-right:1px solid rgba(85,135,210,.6); line-height:1.25;}
  .wl-item .sym{font-size:12px;}
  .wl-item .nm{font-size:10px;}
  .wl-item .px{font-size:12px;}
  .wl-item .pct{font-size:10.5px;} .wl-item .usd{font-size:11px;}
  .wl-add{display:none;}
  .chart-col{flex:0 0 auto; margin:8px; height:76vh; min-height:470px;}
  .dock{flex:0 0 auto; margin:0 8px 8px;}
  .dash{flex:0 0 auto;}
  .dash-scroll{overflow:visible;}
  .dash td{white-space:nowrap;}
  .tape{flex:0 0 24px;}
}

/* ---------------- Indicators tab ----------------
   Top-bar ƒx button + library panel (indicators.js builds the
   panel DOM) + dynamic oscillator/volume sub-panes. */
.ind-btn{
  background:#101823; color:#dfe9f5; border:1px solid #1d2c42; border-radius:8px;
  font-size:11px; font-weight:400; letter-spacing:.6px; padding:3px 6px;
  cursor:pointer; font-family:inherit; white-space:nowrap;
}
.ind-btn:hover{border-color:rgba(30,227,8,.5); color:#fff;}
.ind-btn.active{background:var(--green); color:#03140a; border-color:var(--green);
  box-shadow:0 0 14px rgba(30,227,8,.45);}
.ind-remove-all{font-size:11px; padding:4px 6px; line-height:1.1;}
.ind-remove-all:disabled{opacity:.38; cursor:default;}
.ind-remove-all:not(:disabled):hover{border-color:rgba(255,59,71,.65); color:#ff8a94;}
.ind-panel{
  position:fixed; top:64px; right:12px; width:348px; max-height:calc(100vh - 120px);
  overflow-y:auto; z-index:60; background:var(--panel-2);
  border:1px solid rgba(30,227,8,.35); border-radius:10px;
  box-shadow:0 18px 50px rgba(0,0,0,.65), 0 0 24px rgba(30,227,8,.08);
  padding:10px 12px 12px;
}
.ind-panel::-webkit-scrollbar{width:8px;}
.ind-panel::-webkit-scrollbar-thumb{background:#1b3a5f; border-radius:4px;}
.ind-panel-head{
  display:flex; align-items:center; justify-content:space-between;
  color:var(--green); font-weight:400; letter-spacing:1.6px; font-size:13px;
  padding:2px 0 8px;
}
.ind-x{
  background:transparent; border:none; color:var(--dim); font-size:13px;
  cursor:pointer; padding:2px 6px; font-family:inherit;
}
.ind-x:hover{color:#fff;}
#indSearch{
  width:100%; padding:8px 10px; background:#0a1524; color:#e8f2ff;
  border:1.5px solid #1c3350; border-radius:8px; font-size:12.5px;
  font-family:inherit; margin-bottom:6px;
}
#indSearch:focus{outline:none; border-color:rgba(30,227,8,.65);}
.ind-group{
  color:var(--green); font-size:10.5px; font-weight:400; letter-spacing:1.4px;
  padding:12px 0 5px; border-bottom:1px solid var(--edge); margin-bottom:4px;
}
.ind-none{color:var(--dim); font-size:12px; padding:5px 0 2px;}
.ind-active-row{
  display:flex; align-items:center; gap:8px; flex-wrap:wrap;
  padding:6px 0; border-bottom:1px solid #101c2e;
}
.ind-active-name{font-size:12.5px; font-weight:400; color:#fff; margin-right:auto;}
.ind-param{font-size:10.5px; font-weight:400; color:var(--dim); letter-spacing:.4px;
  display:flex; align-items:center; gap:4px;}
.ind-param input{
  width:52px; padding:4px 5px; background:#0a1524; color:#e8f2ff;
  border:1px solid #1c3350; border-radius:6px; font-size:12px; font-family:inherit;
}
.ind-param input:focus{outline:none; border-color:rgba(30,227,8,.65);}
.ind-remove{
  background:transparent; border:1px solid #1d2c42; color:var(--dim);
  border-radius:6px; font-size:11px; padding:3px 7px; cursor:pointer; font-family:inherit;
}
.ind-remove:hover{color:var(--red); border-color:rgba(255,59,71,.6);}
.ind-row{
  display:flex; align-items:baseline; justify-content:space-between; gap:10px;
  width:100%; text-align:left; background:transparent; border:none;
  border-bottom:1px solid #101c2e; padding:7px 4px; cursor:pointer; font-family:inherit;
}
.ind-row:hover{background:rgba(30,227,8,.07);}
.ind-row.disabled{cursor:default; opacity:.45;}
.ind-row.disabled:hover{background:transparent;}
.ind-row-name{font-size:13px; font-weight:400; color:var(--ink);}
.ind-row-sub{font-size:10.5px; color:var(--dim); text-align:right;}
.ind-foot{color:var(--dim); font-size:11px; line-height:1.45; padding-top:10px;}
/* dynamic indicator panes reuse .pane-sub; the label carries a
   working remove button, so it needs pointer events back */
.ind-pane .pane-label{pointer-events:auto; display:flex; align-items:center; gap:6px;}
.ind-pane-x{
  background:transparent; border:none; color:var(--dim); font-size:10.5px;
  cursor:pointer; padding:0 2px; font-family:inherit; line-height:1;
}
.ind-pane-x:hover{color:var(--red);}

/* Chart-library attribution logo guard: the on-chart vendor logo is
   disabled via the attributionLogo:false chart option at every
   createChart call; this rule guarantees no chart container can ever
   render the vendor attribution anchor, present or future. The
   license-required text credit lives on the Account > About section
   (see IP-AND-LICENSES.md). */
.tv-lightweight-charts a[href*="tradingview.com"] { display: none !important; }

/* ============================================================
   TABLET BAND — watchlist readability (CEO iPad spot 2026-11-02).
   Between the phone stack (<=900px) and wide desktop (>1400px,
   untouched), the desktop row layout squeezed the rail to 178px:
   8.5-10.5px type, GOOGL/BTCUSD/ETHUSD ellipsized, and CHG/VOL/
   EXT cells overflowing into each other. In this band the rail
   takes a fair width and each row becomes a two-line card:
     line 1: SYMBOL (13.5px) ............ LAST (13.5px)
     line 2: CHG $ +% .... VOL n .... EXT $ +%
   Same DOM, same painters, same drag engine — presentation only.
   The drag-resize handle is retired in the band (the rail width
   is designed here, as on phones); it returns at desktop widths.
   ============================================================ */
@media (min-width: 901px) and (max-width: 1400px){
  :root{ --wl-width:256px; }
  .watchlist{ flex-basis:256px; }
  .wl-resize-handle{ display:none; }
  .wl-head{ font-size:12.5px; padding:7px 9px; }
  .wl-cols{ display:none; }
  .wl-list{ min-height:200px; }
  /* TV ROWS in the tablet band: same two-block row as desktop,
     at the band's readable sizes — no card areas, no in-cell
     VOL/EXT labels (those columns are gone). */
  .wl-item{ padding:5px 8px; line-height:1.3; }
  .wl-item .sym{ font-size:13.5px; }
  .wl-item .nm{ font-size:11px; }
  .wl-item .px{ font-size:13.5px; }
  .wl-item .pct{ font-size:11.5px; }
  .wl-item .usd{ font-size:12px; }
    .wl-add{ padding:6px 7px; gap:6px; }
  .wl-add input{ font-size:12.5px; padding:7px 8px; }
  .wl-add button{ font-size:12.5px; padding:7px 10px; }
}
@media (min-width: 1151px) and (max-width: 1400px){
  :root{ --wl-width:280px; }
  .watchlist{ flex-basis:280px; }
}
/* ============================================================
   STACK BAND — portrait / narrow watchlist readability
   (CEO follow-on 2026-11-02: the approved tablet treatment,
   extended to the last untreated layout). At <=900px the rail
   becomes a full-width panel over the chart and the Default
   list renders as a horizontal strip whose items kept the
   desktop 5-track capped grid — CHG/VOL/EXT collided into
   each other and type sat at 8.5-11px. Each strip item now
   carries the same two-line card the CEO approved for the
   tablet band, at a fixed card width (the strip scrolls
   horizontally, so width costs nothing):
     line 1: SYMBOL (13.5px) ............ LAST (13.5px)
     line 2: CHG $ +% .... VOL n .... EXT $ +%
   Same DOM, same painters, same drag engine — presentation
   only. The 901-1400px tablet band and wide desktop are
   outside this media query and stay byte-identical.
   ============================================================ */
@media (max-width: 900px){
  .wl-head{ font-size:12.5px; padding:7px 9px; }
  /* TV ROWS in the stack band: one stock per strip card, the
     same two-block row at the band's readable sizes. */
  .wl-item{
    width:252px;
    padding:5px 8px; line-height:1.3;
  }
  .wl-item .sym{ font-size:13.5px; }
  .wl-item .nm{ font-size:11px; }
  .wl-item .px{ font-size:13.5px; }
  .wl-item .pct{ font-size:11.5px; }
  .wl-item .usd{ font-size:12px; }
  }


/* ============================================================
   VISIBILITY FIX — real full-height watchlist column lines +
   top-bar REFRESH button (CEO 2026-11-04 ~2:03am CT: "I don't
   see a refresh button. I don't see the watchlist columns
   splitting the stocks like I drew either").
   Root cause of the invisible columns: the refinement pass put
   the vertical dividers on the row CELLS as border-right, but
   the row grids run align-items:center, so each cell box
   shrinks to its text height and its "line" is a short stub
   floating around the words — the stubs never join into a
   column line, in any band (desktop grid included). Fix: the
   row grids stretch their cells to the full row height and
   each cell centers its content with flex, so border-right
   runs the row's full height; in the two-line iPad cards the
   row gap folds into the second line's top padding so the
   first-line and second-line segments meet into one continuous
   line. Divider alpha also steps .45 -> .6 (same dashboard
   hue) so the lines read at iPad brightness.
   ============================================================ */
/* TV ROWS (CEO 2026-11-04 ~2:17am CT) supersede the visibility
   fix's stretch cells and JOB 4's one-line column grid above in
   spirit: since the CEO reorganization order (2026-11-04
   ~5:06pm CT) the row is the one-line column grid (see the
   .wl-item base rules) in EVERY band — no grid areas, no stretched cells, no
   column lines, no VOL/EXT cells exist to label. The two media
   blocks below only restate the band sizes so this tail of the
   file — the last word in the cascade — agrees with the design:
   identical structure top to bottom, values aligned on the two
   block edges, dashboard-strength divider under every row. */
.wl-item{align-items:center;}
@media (min-width: 901px) and (max-width: 1400px){
  .wl-item{ padding:5px 8px; }
  .wl-item .sym{font-size:13.5px;}
  .wl-item .nm{font-size:11px;}
  .wl-item .px{font-size:13.5px;}
  .wl-item .pct{font-size:11.5px;}
  .wl-item .usd{font-size:12px;}
  }
@media (max-width: 900px){
  .wl-item{ width:252px; padding:5px 8px; }
  .wl-item .sym{font-size:13.5px;}
  .wl-item .nm{font-size:11px;}
  .wl-item .px{font-size:13.5px;}
  .wl-item .pct{font-size:11.5px;}
  .wl-item .usd{font-size:12px;}
  }
/* ---------------- Provider transition fine print (2026-11-03) ---------------- */
.provider-note{
  flex:0 0 auto; font-size:10px; line-height:1.45; text-align:center;
  color:#7d8ea3; background:var(--bg); padding:2px 12px 3px;
}

/* Refresh button (CEO 2026-11-04 ~1:47am CT): far right of the
   top bar; one tap reloads the page fresh (handler in
   index.html). .ind-btn family styling with the brand-green
   edge so it is unmissable on the iPad. */
.mv-refresh-btn{
  background:#101823; color:#1ee308; border:1px solid rgba(30,227,8,.55); border-radius:8px;
  font-size:12px; font-weight:400; letter-spacing:.8px; padding:5px 12px;
  cursor:pointer; font-family:inherit; white-space:nowrap;
  /* Far-right pin (CEO 2026-11-04: "I don't see a refresh button
     on the desktop version"): .top-right is a wrapping flex row,
     so without this the button just trails the settings icon
     mid-bar; margin-left:auto pins it to the far right of its
     line at every width, desktop and iPad alike. */
  flex:0 0 auto; margin-left:auto;
}
.mv-refresh-btn:hover{background:rgba(30,227,8,.14); color:#eaffea;}
.mv-refresh-btn:active{background:var(--green); color:#03140a;}

/* ============================================================
   DOCK SLIM — dash band adaptation (CEO 2026-11-04 ~3:43pm CT;
   see the .dock note). The dock rides at the watchlist rail's
   width (var(--wl-width)); the dashboard adapts inside its own
   panel only — the chart and the rail never shrink, and every
   cell stays center-aligned (2026-11-04 center pass).
   LAYOUT FROZEN (CEO refinement 2026-11-04 ~4:02pm CT,
   binding): the four-column grid (label | value | label |
   value), the field set and the field order NEVER change, in
   any band — the slim is COMPRESSION ONLY (tracks, padding,
   fonts). The first pass's two-line flow at 901-1150 and on
   desktop is REVERTED here. Fit contract, from the 2026-11-02
   Chromium-measured string inventory (labels 60/55px at 9px;
   values 84/102px at 10px), scaled linearly:
     - 1151-1400 (dock 280px): tracks 55/76/51/minmax(91px,1fr)
       at 1px cell padding give rooms 51/72/47/87+px vs needs
       50/71.4/45.8/86.7 at labels 7.5px / values 8.5px — fits.
     - 901-1150 (dock 256px): tracks 49/65/45/minmax(89px,1fr)
       at 1px cell padding give rooms 47/63/43/87+px vs needs
       46.7/63/42.8/76.5 at labels 7px / values 7.5px — fits.
     - Desktop (dock = the rail's 180-380px): the four tracks
       ride at the base proportions (68/92/63/101 as fr shares)
       so the grid scales with the rail; at the narrowest rail
       widths the longest strings reach the base design's own
       overflow:hidden edge — the frozen layout takes
       precedence over the last pixels (layout first, tighten
       the fit only).
   ============================================================ */
@media (min-width: 1151px) and (max-width: 1400px){
  .dash tr{grid-template-columns:55px 76px 51px minmax(91px,1fr);}
  .dash table{font-size:8.5px;}
  .dash td{padding:0 1px 1px;}
  .dash td.lc{font-size:7.5px;}
}
@media (min-width: 901px) and (max-width: 1150px){
  .dash tr{grid-template-columns:49px 65px 45px minmax(89px,1fr);}
  .dash table{font-size:7.5px;}
  .dash td{padding:0 1px 1px;}
  .dash td.lc{font-size:7px;}
}
@media (min-width: 1401px){
  .dash tr{grid-template-columns:minmax(0,68fr) minmax(0,92fr) minmax(0,63fr) minmax(0,101fr);}
  .dash table{font-size:8.5px;}
  .dash td{padding:0 1px 1px;}
  .dash td.lc{font-size:7.5px;}
  .dash-head .t{font-size:9px; letter-spacing:.4px;}
  .dash-head .ctl{font-size:8px; letter-spacing:.5px;}
}

/* ============================================================
   SHADING + COLUMN LINES FIX (CEO 2026-11-04 ~5:36pm CT: "Why
   does it have faded highlight all over it? ... there's no
   line in between it").
   Root cause of BOTH complaints was the column-divider
   overlay deleted above (and the same gradient painted on
   the header): its linear-gradient interpolated transparent
   -> line color across each whole segment, so instead of
   crisp 1px lines it painted a soft blue WASH peaking at
   every column boundary; and the absolutely-positioned
   overlay was only as tall as the list's visible box, so
   the wash (and the "lines") existed over the first
   screenful of rows and vanished on scroll. Dividers now
   ride on the row cells themselves: every row stretches its
   SYM and LAST cells to the full row height with a
   border-right, so the two column lines run unbroken
   through the ENTIRE scroll height, and every row keeps the
   one uniform panel background — no overlay, no wash.
   ============================================================ */
/* FOUR-COLUMN DIVIDERS (CEO 2026-11-04 ~5:48pm CT): the row is
   four columns now, so the $ CHG cell carries the third
   divider — the line between the $ column and the % column
   he pointed at — and the header's third span matches.
   PAIR ALIGNMENT (CEO refinement, same order): the $ and %
   cells are RIGHT-aligned as a pair — one treatment for
   both, tabular figures — so the two values end on
   consistent edges and read as one aligned block row to
   row. This carves the two change columns out of the
   center law, the same way SYM was carved out flush-left;
   LAST stays centered. Do not re-center the pair. */
.wl-item{align-items:stretch;}
.wl-item .sym{display:flex; align-items:center; justify-content:flex-start; border-right:1px solid rgba(85,135,210,.6);}
.wl-item .px{display:flex; align-items:center; justify-content:center; border-right:1px solid rgba(85,135,210,.6);}
.wl-item .usd{display:flex; align-items:center; justify-content:flex-end; padding-right:4px; border-right:1px solid rgba(85,135,210,.6);}
.wl-item .pct{display:flex; align-items:center; justify-content:flex-end; padding-right:4px;}
.wl-cols{align-items:stretch;}
.wl-cols span{display:flex; align-items:center; justify-content:center;}
.wl-cols span:first-child{justify-content:flex-start; border-right:1px solid rgba(85,135,210,.6);}
.wl-cols span:nth-child(2){border-right:1px solid rgba(85,135,210,.6);}
.wl-cols span:nth-child(3){border-right:1px solid rgba(85,135,210,.6);}
.wl-cols span:nth-child(3), .wl-cols span:nth-child(4){justify-content:flex-end; padding-right:4px;}
@media (max-width: 900px){
  /* phone strip: one stock per card — the card's own right
     border is the separator there; no in-card column lines. */
  .wl-item{align-items:center;}
  .wl-item .sym, .wl-item .px, .wl-item .usd{border-right:none;}
}
