/* tradinghub.cc — live trade tape + liquidations sidebar (Crypto terminal panel) */

/* ---------- Bloomberg/Aggr-style flat redesign ----------
   Retargets the shared color tokens for everything under .live-term only
   (custom properties cascade to every descendant that reads var(--line)
   etc.), and kills border-radius across the panel. Circular status dots
   are restored to round further down so they still read as indicator
   lights rather than tiny squares. No markup, IDs or classes changed. */
.live-term{
  --void: #000000;
  --panel: #090909;
  --panel-hover: #121212;
  --surface-header: #1A1A1A;
  --line: #1A1A1A;
  --line-soft: #141414;
  --ink: #CCCCCC;
  --mute: #8F8F8F;
  --mute-dim: #5A5A5A;
  --signal: #FFC857;
  --signal-soft: rgba(255,200,87,0.12);
  --pulse: #00FF88;
  --pulse-soft: rgba(0,255,136,0.12);
  --danger: #FF4D4D;
  --danger-soft: rgba(255,77,77,0.12);
  --exch-binance: #4CC2FF;
  --exch-bybit: #35D0A7;
  background:var(--void);
}
.live-term, .live-term *{ border-radius:0 !important; }
.live-term .term-identity-bar__dot,
.live-term .live-tape-idle__dot,
.live-term .dot{ border-radius:50% !important; }

.live-term{
  /* Balanced default: terminal (main) and Live Chart (side) split the
     available width roughly evenly and stay responsive across desktop
     resolutions. --live-side-w is only set (as a fixed px value) once a
     user drags the gutter or has a saved width in layout-persistence.js —
     until then the "1fr" fallback keeps both columns equal. */
  display:grid;
  grid-template-columns:minmax(0,1fr) 6px minmax(0,var(--live-side-w,1fr));
  gap:0;
  align-items:start;
  /* the ~160px accounts for the identity bar + asset/exchange selectors +
     toolbar + heatmap strip above the tape list, so the tape list itself
     (not just this outer container) clears 70% of the viewport height */
  min-height:calc(70vh + 160px);
}
@media (max-width:980px){
  .live-term{ grid-template-columns:1fr; min-height:0; }
  .live-term__gutter{ display:none; }
  /* Without a bounded height here, .live-tape (flex:1 with no height on
     this column) sizes to fit however many rows are currently rendered —
     easily 1000px+ — so the page has to be scrolled a very long way past
     the tape before reaching Live Chart and the rest of the sidebar below
     it. Capping .live-term__main lets the tape scroll internally instead,
     same as it already does on desktop. */
  .live-term__main{ height:55vh; }
}

/* ---------- resizable sidebar gutter (drag to resize, remembered) ---------- */
.live-term__gutter{
  align-self:stretch;
  width:6px;
  margin:0 -3px;
  cursor:col-resize;
  position:relative;
  z-index:3;
  background:transparent;
  touch-action:none;
}
.live-term__gutter::after{
  content:''; position:absolute; top:0; bottom:0; left:2px; width:1px;
  background:var(--line);
}
.live-term__gutter:hover::after,
.live-term__gutter--active::after{ left:1px; width:3px; background:var(--signal); }
.live-term--fullscreen .live-term__gutter{ align-self:stretch; }

/* ---------- sidebar panel drag-to-reorder ---------- */
.panel-drag-handle{
  flex:none; color:var(--mute-dim); font-size:14.5px; line-height:1;
  margin-right:2px; user-select:none;
  cursor:grab;
}
.panel-drag-handle:active{ cursor:grabbing; }
.live-term__side .widget-card--drag-ghost{ opacity:.35; }
.live-term__side .widget-card--drag-over{ box-shadow:inset 0 2px 0 var(--signal); }

.live-term__main{
  min-width:0;
  display:flex; flex-direction:column;
  position:relative;
  background:var(--void);
  border:1px solid var(--line);
  overflow:hidden;
  /* Fixed, not just inherited from the grid's min-height: the grid uses
     align-items:start (so the shorter sidebar column isn't stretched
     into a lot of empty space), which means this column was otherwise
     sized purely by its own content — as trade rows streamed in/out, or
     just changed height (large-trade rows get extra padding), the whole
     panel visibly grew and shrank. With an explicit height here, .live-tape
     below (flex:1) has something definite to size against and scrolls
     inside a constant box instead. Matches the same 70vh+160px the grid's
     min-height already targets, so nothing shifts on first load either. */
  height:calc(70vh + 160px);
}

/* ---------- terminal identity bar ---------- */
.term-identity-bar{
  display:flex; align-items:center; gap:10px;
  padding:4px 10px;
  background:var(--surface-header);
  border-bottom:1px solid var(--line);
  font-family:var(--font-mono);
  overflow-x:auto;
  white-space:nowrap;
}
.term-identity-bar__brand{
  font-size:12.5px; font-weight:700; letter-spacing:.06em;
  color:var(--signal);
  flex:none;
}
.term-identity-bar__brand span{ color:var(--ink); font-weight:600; }
.term-identity-bar__version{ color:var(--mute-dim) !important; font-weight:500 !important; }
.term-identity-bar__sep{
  flex:none; width:1px; align-self:stretch; background:var(--line-soft);
}
.term-identity-bar__item{
  display:flex; align-items:baseline; gap:5px;
  font-size:12px; letter-spacing:.04em;
  flex:none;
}
.term-identity-bar__label{ color:var(--mute-dim); text-transform:uppercase; }
.term-identity-bar__value{
  color:var(--ink); font-weight:600; font-variant-numeric:tabular-nums;
}
.term-identity-bar__value.term-identity--good{ color:var(--pulse); }
.term-identity-bar__value.term-identity--warn{ color:var(--ink); }
.term-identity-bar__value.term-identity--bad{ color:var(--danger); }
.term-identity-bar__dot{
  width:6px; height:6px; border-radius:50%; flex:none;
  background:var(--mute-dim);
}
.term-identity-bar__dot--live{ background:var(--pulse); box-shadow:0 0 6px rgba(0,255,136,.6); }
.term-identity-bar__dot--reconnecting{ background:var(--ink); }
.term-identity-bar__dot--offline{ background:var(--danger); }
@media (max-width:640px){
  .term-identity-bar__item:not(#term-identity-ws){ display:none; }
}

/* ---------- local + UTC clock (identity bar, upper-right) ---------- */
.term-clock-chip{
  display:flex; align-items:baseline; gap:8px;
  margin-left:auto; padding:2px 10px;
  border:1px solid var(--line);
  background:var(--panel);
  font-family:var(--font-mono); font-size:12px; letter-spacing:.04em;
  flex:none; white-space:nowrap;
}
.term-clock-chip__item{ display:flex; align-items:baseline; gap:5px; }
.term-clock-chip__label{ color:var(--mute-dim); text-transform:uppercase; }
.term-clock-chip__value{ color:var(--ink); font-weight:700; font-variant-numeric:tabular-nums; }
.term-clock-chip__sep{
  width:1px; align-self:stretch; background:var(--line-soft); flex:none;
}
@media (max-width:820px){ .term-clock-chip__label{ display:none; } }
@media (max-width:640px){ .term-clock-chip{ display:none; } }

/* ---------- asset selector ---------- */
.asset-select{
  display:flex; align-items:center; gap:0; flex-wrap:wrap;
  padding:6px 10px;
  border-bottom:1px solid var(--line);
  background:var(--panel);
}
.asset-pill{
  font-family:var(--font-mono);
  font-size:13px; font-weight:600;
  letter-spacing:.03em;
  color:var(--mute);
  background:transparent;
  border:1px solid var(--line);
  margin-right:-1px;
  padding:4px 12px;
  cursor:pointer;
  display:inline-flex; align-items:baseline; gap:7px;
  transition:color .15s ease, border-color .15s ease, background .15s ease;
}
.asset-pill:hover{ color:var(--ink); border-color:var(--mute-dim); }
.asset-pill--active{
  color:#000000;
  background:var(--signal);
  border-color:var(--signal);
}
.asset-pill__chg{
  font-size:12px; font-weight:600;
  font-variant-numeric:tabular-nums;
  color:var(--mute-dim);
}
.asset-pill__chg--up{ color:var(--pulse); }
.asset-pill__chg--down{ color:var(--danger); }
.asset-pill--active .asset-pill__chg--up{ color:#0a5c30; }
.asset-pill--active .asset-pill__chg--down{ color:#7a1518; }

/* Market Display Mode: "Both" stacks label above price+change on each pill */
.asset-select--stacked .asset-pill{
  flex-direction:column; align-items:flex-start; gap:2px;
  padding:5px 12px 6px;
}
.asset-select--stacked .asset-pill__chg{ font-size:12px; }

/* ---------- exchange toggles + tape toolbar, combined into one row ----------
   Was two full-width bars stacked on top of each other (exch-select, then
   tape-toolbar) — same content, just sharing a single border-bottom/background
   now so Settings/Cluster/Pause/Clear/Fullscreen sit inline with Binance/
   Bybit/OKX instead of costing an extra row. flex-wrap lets the toolbar drop
   to its own line on narrow phones if the two groups don't both fit. */
.exch-toolbar-row{
  display:flex; align-items:center; justify-content:space-between; flex-wrap:wrap; gap:4px 10px;
  border-bottom:1px solid var(--line);
  background:var(--panel);
}
.exch-toolbar-row .exch-select,
.exch-toolbar-row .tape-toolbar{
  border-bottom:none; background:transparent;
}
.exch-toolbar-row .exch-select{ padding-right:0; }
.exch-toolbar-row .tape-toolbar{ padding-left:0; }
/* ---------- exchange toggle chips ---------- */
.exch-select{
  display:flex; align-items:center; gap:14px; flex-wrap:wrap;
  padding:5px 10px;
  border-bottom:1px solid var(--line);
  background:var(--panel);
}
.exch-pill{
  display:flex; align-items:center; gap:6px;
  font-family:var(--font-mono); font-size:12px; font-weight:600;
  letter-spacing:.03em;
  color:var(--mute-dim);
  background:transparent;
  border:none;
  padding:2px 0;
  cursor:pointer;
  opacity:.55;
  transition:opacity .15s ease, color .15s ease;
}
.exch-pill:hover{ opacity:.8; }
.exch-pill--active{ opacity:1; color:var(--ink); }
.exch-pill__dot{ width:13px; height:13px; border-radius:4px !important; flex:none; display:inline-flex; overflow:hidden; }
.exch-pill__dot svg{ display:block; }

/* ---------- Fáza 2: tape toolbar (font size, stored rows, pause, clear, fullscreen) ---------- */
.tape-toolbar{
  display:flex; align-items:center; gap:10px; flex-wrap:wrap;
  padding:5px 10px;
  border-bottom:1px solid var(--line);
  background:var(--panel);
}
.tape-toolbar__group{ display:flex; align-items:center; gap:6px; }
.tape-toolbar__group--right{ margin-left:auto; gap:8px; }
.tape-toolbar__label{
  font-family:var(--font-mono); font-size:11px; text-transform:uppercase; letter-spacing:.06em;
  color:var(--mute-dim);
}
.tape-toolbar__select{
  font-family:var(--font-mono); font-size:12px;
  background:var(--void); color:var(--ink);
  border:1px solid var(--line);
  padding:2px 5px; cursor:pointer;
}
.toolbar-btn{
  display:inline-flex; align-items:center; gap:5px;
  font-family:var(--font-mono); font-size:12px; font-weight:600;
  letter-spacing:.02em;
  color:var(--mute);
  background:transparent;
  border:1px solid var(--line);
  padding:3px 8px;
  cursor:pointer;
  transition:color .15s ease, border-color .15s ease, background .15s ease;
}
.toolbar-btn:hover{ color:var(--ink); border-color:var(--mute-dim); }
.toolbar-btn:disabled{ opacity:.35; cursor:default; }
.toolbar-btn:disabled:hover{ color:var(--mute); border-color:var(--line); }
.toolbar-btn--sq{ padding:3px 7px; }
/* Subtle outline+tint instead of a solid, glowing gold fill — same
   language already used for .liq-filter--active/.whale-tab--active
   below, just applied consistently to toolbar buttons (Cluster, Pause,
   chart-type toggles, etc.) so "active" reads as a quiet state change
   rather than a bright illuminated control. */
.toolbar-btn--active{ color:var(--signal); background:var(--signal-soft); border-color:var(--signal); }
.toolbar-btn--active:hover{ color:var(--signal); background:rgba(255,200,87,.2); }
.toolbar-btn--active:active{ background:rgba(255,200,87,.28); }
.toolbar-btn:not(.toolbar-btn--active):active{ background:var(--panel-hover); }
.toolbar-btn__icon{ font-size:13.5px; line-height:1; }
@media (max-width:640px){
  .toolbar-btn__label{ display:none; }
  .toolbar-btn{ padding:5px 8px; min-width:36px; min-height:36px; justify-content:center; }
  .toolbar-btn--sq{ min-width:36px; }
  .exch-pill{ padding:8px 4px; min-height:32px; }
}

/* live-term--paused: subtle cue that the tape is frozen while connections stay live */
.live-term--paused .live-tape{ opacity:.6; }

/* fullscreen mode: fill the viewport and let the tape column claim the extra height.
   Both panels are given an explicit height + their own overflow so they scroll
   independently (Trade Tape on the left, sidebar cards on the right) instead of
   the browser's default :fullscreen overflow:auto turning the whole grid into a
   single page-level scroll surface, which is what made the sidebar uncrollable. */
.live-term--fullscreen{
  background:var(--panel);
  padding:12px;
  height:100vh;
  overflow:hidden;
}
.live-term--fullscreen .live-term__main{ min-height:0; height:100%; }
.live-term--fullscreen .live-term__side{
  height:100%; min-height:0;
  overflow-y:auto; -webkit-overflow-scrolling:touch;
}
:fullscreen.live-term{ min-height:100vh; overflow:hidden; }
@media (max-width:980px){
  /* below the breakpoint the tape/sidebar stack in a single column (same
     rule the base .live-term already applies) — let that stack scroll as
     one unit instead of fighting it for a fixed height, same tradeoff
     Immersive Mode makes at this breakpoint. */
  .live-term--fullscreen{ overflow-y:auto; }
  .live-term--fullscreen .live-term__main{ height:auto; }
  .live-term--fullscreen .live-term__side{ height:auto; overflow-y:visible; }
}

/* ---------- Fáza 3: sound alerts popover ---------- */
.sound-control{ position:relative; }
.sound-panel{
  position:absolute; top:calc(100% + 8px); right:0; z-index:20;
  width:240px;
  background:var(--panel); border:1px solid var(--line); border-radius:10px;
  
  padding:12px;
  font-family:var(--font-mono);
}
.sound-panel__head{
  display:flex; align-items:center; justify-content:space-between; gap:8px;
  margin-bottom:10px; padding-bottom:8px;
  border-bottom:1px solid var(--line-soft);
}
.sound-panel__head strong{ font-size:13.5px; color:var(--ink); }
.sound-panel__master{ display:flex; align-items:center; gap:5px; font-size:12px; color:var(--mute); cursor:pointer; }
.sound-panel__profile-row{
  display:flex; align-items:center; justify-content:space-between; gap:8px;
  padding:2px 0 10px; margin-bottom:6px;
  border-bottom:1px solid var(--line-soft);
}
.sound-panel__profile-row label{ font-size:12.5px; color:var(--mute); flex:none; }
.sound-panel__profile-row select{
  flex:1; font-family:var(--font-mono); font-size:12.5px;
  background:var(--void); color:var(--ink);
  border:1px solid var(--line); border-radius:5px;
  padding:3px 6px; cursor:pointer;
}
.sound-panel__volume-row{
  display:flex; align-items:center; gap:8px;
  padding:2px 0 10px;
  margin-bottom:6px;
  border-bottom:1px solid var(--line-soft);
}
.sound-panel__volume-row label{ font-size:12.5px; color:var(--mute); flex:none; }
.sound-panel__volume-row input[type="range"]{
  flex:1; accent-color:var(--signal); cursor:pointer;
}
.sound-panel__volume-value{
  font-size:12px; color:var(--mute-dim); flex:none; min-width:32px; text-align:right;
}
.sound-panel__row{
  display:flex; align-items:center; justify-content:space-between; gap:8px;
  padding:5px 0;
}
.sound-panel__profile{ display:flex; align-items:center; gap:6px; font-size:13px; color:var(--ink); cursor:pointer; }
.sound-panel__profile input{ accent-color:var(--signal); }
.sound-panel__row select{
  font-family:var(--font-mono); font-size:12px;
  background:var(--void); color:var(--ink);
  border:1px solid var(--line); border-radius:5px;
  padding:2px 5px; cursor:pointer;
}
.sound-panel__test{
  width:100%; margin-top:8px;
  font-family:var(--font-mono); font-size:12.5px; font-weight:600;
  color:var(--ink); background:var(--panel, #12151C);
  border:1px solid var(--line); border-radius:6px;
  padding:6px; cursor:pointer;
}
.sound-panel__test:hover{ border-color:var(--mute-dim); }
.sound-panel__hint{
  margin:8px 0 0; font-size:11.5px; line-height:1.4; color:var(--mute-dim);
}

/* ---------- Settings popover (Display + Filters + Sound, consolidated) ---------- */
.filter-control{ position:relative; }
.filter-panel{
  position:absolute; top:calc(100% + 8px); left:0; z-index:20;
  width:200px;
  background:var(--panel); border:1px solid var(--line); border-radius:10px;
  
  padding:12px;
  font-family:var(--font-mono);
}
/* Settings is always a fixed, centered modal dialog — on desktop AND
   mobile — rather than a popover anchored under the toolbar button.
   Being `position:fixed` means its position is purely viewport-relative:
   it can't drift, and it doesn't care where the button that opened it
   lives, whether that's a cramped mobile toolbar or a wide desktop one.
   Previously this centered treatment only kicked in above a min-width
   breakpoint, with a separate anchored-popover styling below it — that
   in-between anchored state (position:absolute, relative to the toolbar
   button) is what let the panel appear to drift/slide as the page
   reflowed from incoming trades. Making it unconditional removes that
   anchored state entirely.
   Centered with `inset:0` + `margin:auto` rather than the more common
   `top/left:50%` + `translate(-50%,-50%)` trick: auto-margins let the
   browser's own fixed-positioning layout center the box in the actual
   viewport directly, with no percentage-of-viewport / transform math for
   anything to go subtly wrong in. */
.filter-panel--settings{
  position:fixed;
  inset:0; margin:auto;
  display:flex; flex-direction:column;
  width:min(760px, calc(100vw - 32px));
  height:fit-content;
  max-width:none;
  max-height:calc(100vh - 64px);
  overflow-y:auto; overscroll-behavior:contain;
  padding:16px 18px 18px;
  box-sizing:border-box;
  box-shadow:0 24px 64px rgba(0,0,0,.5), 0 2px 8px rgba(0,0,0,.3);
  z-index:200;
}
/* position:fixed above has the same specificity as the browser's default
   [hidden]{display:none} rule, but author CSS always wins that tie — so
   without this, the panel would render open (dead center, backdrop and
   all) on page load, before the Settings button is ever clicked. */
.filter-panel--settings[hidden]{ display:none; }
/* Smooth open/close: the panel already toggles the [hidden] attribute in
   JS (trade-tape.js), which is instant with no transition surface — add
   a fade+scale driven by an "is-open" class that JS applies a frame after
   removing [hidden] (and removes a frame before restoring [hidden]), so
   the transition below actually has something to animate between.
   Centering here comes from inset:0+margin:auto above, so the animation
   only needs to scale — no translate offset to keep in sync with it. */
.filter-panel--settings{
  opacity:0;
  transform:scale(.97);
  transition:opacity .16s ease, transform .16s ease;
}
.filter-panel--settings.filter-panel--open{
  opacity:1;
  transform:scale(1);
}
.filter-panel__head{
  display:flex; align-items:center; justify-content:space-between;
  margin:-16px -18px 10px;
  padding:14px 18px 10px;
  background:var(--surface-header);
  border-bottom:1px solid var(--line);
}
.filter-panel__head strong{ font-size:13.5px; color:var(--ink); }
.filter-panel__close{
  display:inline-flex; /* Settings is always the modal treatment now */
  align-items:center; justify-content:center;
  width:24px; height:24px; padding:0;
  background:none; border:none; border-radius:6px;
  color:var(--mute-dim); font-size:13.5px; cursor:pointer;
  transition:color .15s ease, background .15s ease;
}
.filter-panel__close:hover{ color:var(--ink); background:rgba(255,255,255,0.06); }
.filter-panel__group{ padding:6px 0; border-bottom:1px solid var(--line-soft); }
.filter-panel__group:last-child{ border-bottom:none; padding-bottom:0; }
.filter-panel__group-label{
  display:block; font-size:11.5px; text-transform:uppercase; letter-spacing:.05em;
  color:var(--mute-dim); margin-bottom:5px;
}
.filter-panel__radio, .filter-panel__checkbox{
  display:flex; align-items:center; gap:6px;
  font-size:13px; color:var(--ink); cursor:pointer;
  padding:2px 0;
}
.filter-panel__radio input, .filter-panel__checkbox input{ accent-color:var(--signal); }
.settings-checkbox{ margin-top:2px; }
.settings-row{
  display:flex; align-items:center; justify-content:space-between; gap:8px;
  padding:4px 0;
}
.settings-row__label{ font-size:13px; color:var(--ink); }
.settings-row__control--buttons{ display:flex; gap:6px; }
.settings-row__select{
  font-family:var(--font-mono); font-size:12.5px;
  background:var(--void); color:var(--ink);
  border:1px solid var(--line); border-radius:5px;
  padding:3px 6px; cursor:pointer;
}
/* ---------- Settings categories: collapsible accordion ---------- */
.settings-categories{ display:flex; flex-direction:column; }
.settings-category{ border-bottom:1px solid var(--line-soft); }
.settings-category:last-child{ border-bottom:none; }
.settings-category__header{
  width:100%; display:flex; align-items:center; gap:8px;
  background:none; border:none; margin:0;
  font-family:var(--font-mono); text-align:left; cursor:pointer;
  padding:9px 2px;
  -webkit-tap-highlight-color:transparent;
}
.settings-category__title{
  flex:1; font-size:12px; text-transform:uppercase; letter-spacing:.05em;
  color:var(--mute-dim);
}
.settings-category__header--open .settings-category__title{ color:var(--ink); }
.settings-category__chevron{
  font-size:11.5px; line-height:1; color:var(--mute-dim);
  transition:transform .15s ease;
}
.settings-category__header--open .settings-category__chevron{ transform:rotate(180deg); color:var(--mute); }
.settings-category__body{ padding:0 2px 10px; }
.settings-category__body[hidden]{ display:none; }
.settings-category__hint{
  font-size:12px; line-height:1.4; color:var(--mute-dim);
  margin:0 0 6px;
}
.settings-subgroup{ padding:4px 0; }
.settings-subgroup .filter-panel__group-label{ margin-bottom:5px; }
.settings-reset-btn{
  width:100%; margin-top:2px;
  font-family:var(--font-mono); font-size:12.5px; font-weight:600;
  color:var(--danger); background:var(--panel, #12151C);
  border:1px solid var(--danger); border-radius:6px;
  padding:7px; cursor:pointer;
  transition:background .12s ease, color .12s ease;
}
.settings-reset-btn:hover{ background:var(--danger); color:var(--void, #0a0b0d); }
.settings-reset-btn:disabled{ opacity:.6; cursor:default; background:var(--panel, #12151C); color:var(--danger); }
.settings-category__header:hover .settings-category__title{ color:var(--ink); }

/* Settings dialog chrome: applies at every width now that the panel is
   always the fixed centered modal (previously gated to min-width:981px,
   with mobile relying on a different, anchored-popover layout). Categories
   lay out in an auto-fit grid — the number of columns grows with the
   panel's own width, not a fixed 2-per-row — so the more room a screen
   has, the shorter (not scrollier) the panel gets; on narrow phones the
   grid naturally collapses to one column. A generous max-height +
   overflow-y:auto is kept purely as a last-resort safety net for very
   short/zoomed-in viewports; in normal use it should never be needed. */
.filter-panel--settings .settings-categories{
  display:grid;
  grid-template-columns:repeat(auto-fit, minmax(220px, 1fr));
  gap:2px 20px;
  align-items:start;
}
.filter-panel--settings .settings-category{
  box-sizing:border-box;
  min-width:0;
}
/* Notifications (sound) has the most controls (profile, volume,
   per-type thresholds, test button) — give it the full width instead
   of squeezing it into one grid cell. */
.filter-panel--settings .settings-category--wide{
  grid-column:1 / -1;
}
/* A translucent backdrop behind the centered dialog: dims the terminal
   so the modal reads clearly as modal, and doubles as a big, obvious
   click target to dismiss it (clicks bubble to the existing document
   click-to-close listener in trade-tape.js — no extra JS needed). */
.filter-panel__backdrop{
  position:fixed; inset:0; z-index:199;
  background:rgba(4,6,10,.6);
  opacity:0; pointer-events:none;
  transition:opacity .16s ease;
}
.filter-panel__backdrop--open{ opacity:1; pointer-events:auto; }
/* Bigger tap targets on the category headers themselves at narrower
   widths, since these are the primary touch controls for showing/hiding
   a whole group. */
@media (max-width:980px){
  .settings-category__header{ padding:11px 2px; }
}
/* Sound now lives inline inside Settings instead of its own popover —
   same markup/ids as before, just without the floating position and
   its own trigger button (see sound.js: btn is optional there now). */
.sound-panel--inline{
  position:static; width:auto; border:none; border-radius:0; padding:0;
}
.sound-panel--inline .sound-panel__head{ border-bottom:none; padding-bottom:2px; margin-bottom:6px; justify-content:flex-start; }


/* ---------- Fáza 3: recent-trades heatmap strip ---------- */
.tape-heatmap{
  display:flex; align-items:stretch; gap:1px;
  height:20px;
  padding:0 12px;
  background:var(--void);
  border-bottom:1px solid var(--line-soft);
}
.tape-heatmap__cell{ flex:1 1 0; min-width:2px; border-radius:1px; margin:3px 0; }
.tape-heatmap__cell--buy{ background:var(--pulse); }
.tape-heatmap__cell--sell{ background:var(--danger); }
.tape-heatmap__cell--tier1{ opacity:.35; }
.tape-heatmap__cell--tier2{ opacity:.6; }
.tape-heatmap__cell--tier3{ opacity:.85; }
.tape-heatmap__cell--tier4{ opacity:1; }

/* ---------- Fáza 3: biggest-trade-in-5m highlight ---------- */
.tape-row--biggest{
  outline:1px solid var(--signal);
  outline-offset:-1px;
  box-shadow:inset 0 0 0 1px rgba(245,166,35,.25);
  /* the row element is newly created in the DOM whenever a trade becomes
     the biggest-in-5m (see tapeRowSignature/buildTapeRowEl in trade-tape.js),
     so a plain CSS entrance animation fires automatically the moment it's
     inserted — no JS timing hooks needed. Kept short and understated: a
     quick opacity/lift, not a flashy pop. */
  animation:tapeRowBiggestIn .35s ease-out;
}
@keyframes tapeRowBiggestIn{
  from{ opacity:0; transform:translateY(-3px); }
  to{ opacity:1; transform:translateY(0); }
}
@media (prefers-reduced-motion: reduce){
  .tape-row--biggest{ animation:none; }
}
.tape-row__crown{ flex:none; font-size:12.5px; line-height:1; margin-right:-4px; }

/* ---------- Prompt 8: chart+terminal sync — "just landed" row flash ----------
   A brief neutral flash (not tinted per side — buy/sell color already comes
   from the row's own background/text) applied only to a row's very first
   paint, both here on the trade tape and on the liquidations sidebar rows
   further down. Matches the terminal request literally: ~300ms. */
.tape-row--flash-in,
.liq-sidebar__row--flash-in{ animation:rowFlashIn .3s ease-out; }
@keyframes rowFlashIn{
  from{ box-shadow:inset 0 0 0 999px rgba(255,255,255,.18); }
  to{ box-shadow:inset 0 0 0 999px rgba(255,255,255,0); }
}
@media (prefers-reduced-motion: reduce){
  .tape-row--flash-in,
  .liq-sidebar__row--flash-in{ animation:none; }
}

/* ---------- Fáza 3: order flow (buy/sell ratio) card ----------
   Same overlay-bar pattern as .liq-multi-row__bar / .whale-stats__bar: the
   Buy/Sell % legend sits on top of the bar itself (pinned to its two ends)
   instead of on its own line underneath, so all three widgets share one
   visual language for red/green ratio bars. */
.orderflow-ratio-bar-wrap{ position:relative; }
.orderflow-ratio-bar{
  display:flex; height:16px; border-radius:5px; overflow:hidden;
  background:var(--line-soft);
}
.orderflow-ratio-bar__buy{ background:var(--pulse); transition:width .3s ease; }
.orderflow-ratio-bar__sell{ background:var(--danger); transition:width .3s ease; }
.orderflow-ratio-legend{
  position:absolute; inset:0;
  display:flex; justify-content:space-between; align-items:center;
  padding:0 7px;
  font-family:var(--font-mono); font-size:12px;
  pointer-events:none;
}
.orderflow-ratio-legend__buy,
.orderflow-ratio-legend__sell{
  color:#fff; font-weight:700; text-shadow:0 1px 2px rgba(0,0,0,.55);
  white-space:nowrap;
}
.orderflow-ratio-legend b{ font-weight:700; }
/* Compact "last 60 seconds" readout: one line instead of a 2x2 grid under
   its own "Last 60 seconds" heading — cuts the card's height by close to
   half versus the old layout. Sell vol is dropped here since it's already
   implied by the ratio bar/legend directly above. */
.orderflow-60s{
  margin-top:8px; padding-top:8px;
  border-top:1px solid var(--line-soft);
}
.orderflow-60s--compact{
  display:flex; align-items:baseline; flex-wrap:wrap; gap:5px;
  font-family:var(--font-mono); font-size:13px; color:var(--mute-dim);
}
.orderflow-60s-stat b{ font-size:14.5px; font-weight:700; color:var(--ink); }
.orderflow-60s-sep{ color:var(--line); }

/* ---------- Fáza 3: market stats card (volume / OI / funding / long-short) ---------- */
.mstat-row{
  display:flex; justify-content:space-between; align-items:center;
  padding:6px 0;
  font-family:var(--font-mono); font-size:13.5px;
  border-bottom:1px solid var(--line-soft);
}
.mstat-row:last-child{ border-bottom:none; }
.mstat-label{ color:var(--mute-dim); display:inline-flex; align-items:center; }
.mstat-value{ color:var(--ink); font-weight:600; }

/* Market Pulse column: keep the labels (1m/5m/15m Buy/Sell, Dominant side)
   visible next to the values so the numbers are self-explanatory. */
.marketpulse-card .mstat-value{ text-align:right; }

/* ---------- compact metric tooltips ----------
   Small ⓘ trigger next to a label or value that isn't self-explanatory
   (Order Flow scoring, the various "Volume" figures, funding/OI/long-short,
   cluster counts on the tape, etc). The actual bubble is one shared
   floating element (see metric-tooltips.js) so it's never clipped by a
   card's own layout — this just styles the small trigger itself and, on
   real hover-capable desktop pointers, reveals the bubble without needing
   a click; touch devices always use tap (handled in JS) so there's no
   double-tap-to-click quirk. */
.metric-tip{
  display:inline-flex; align-items:center; justify-content:center;
  width:13px; height:13px; margin-left:5px;
  border-radius:50%; border:1px solid var(--line); background:none;
  color:var(--mute-dim); font-family:var(--font-mono); font-size:10.5px; line-height:1;
  cursor:help; flex-shrink:0; padding:0; vertical-align:middle;
  transition:color .15s ease, border-color .15s ease;
}
.metric-tip:hover, .metric-tip:focus-visible, .metric-tip--open{
  color:var(--signal); border-color:var(--signal); outline:none;
}
/* Mobile: keep the glyph's small inline size (it sits mid-sentence next to
   labels like "Open interest") but give it a real ~32px tap target via an
   invisible expanded hit-area, instead of enlarging the visible dot. */
@media (max-width:760px){
  .metric-tip{ position:relative; }
  .metric-tip::after{
    content:''; position:absolute; top:50%; left:50%;
    transform:translate(-50%,-50%); width:32px; height:32px;
  }
}
.metric-tip-bubble{
  position:absolute; z-index:130; display:none;
  background:var(--panel); border:1px solid var(--line); border-radius:var(--radius-sm);
  padding:8px 10px; box-shadow:0 10px 30px rgba(0,0,0,.45);
  font-family:var(--font-mono); font-size:12.5px; line-height:1.5; color:var(--mute);
}
.metric-tip-bubble.open{ display:block; }

/* ---------- Prompt 9: Market Pulse card ---------- */
.tag--pos{ color:var(--pulse); border-color:rgba(0,255,136,.35); background:rgba(0,255,136,.08); }
.tag--neg{ color:var(--danger); border-color:rgba(255,77,77,.35); background:rgba(255,77,77,.08); }
/* Smoother "feel" when a tag flips direction (e.g. the live chart's price
   tag going from pos to neg on a tick) instead of an instant hard swap. */
.tag--pos, .tag--neg{ transition:background .2s ease, border-color .2s ease, color .2s ease; }

/* ---------- Prompt 10: Order Flow Score card ----------
   Redesigned for a faster read than the old -100..+100 gauge: a headline
   ("Buy Pressure" / "Sell Pressure"), the buy/sell split as two big
   numbers, a simple two-color bar for the same split, then the numeric
   score and its Bullish/Bearish/Neutral label — everything a trader needs
   in one glance, top to bottom, no gauge math required. */
.ofscore-pressure{ text-align:center; margin-bottom:2px; }
.ofscore-pressure__label{
  font-size:12.5px; font-weight:700; color:var(--mute-dim);
  text-transform:uppercase; letter-spacing:.05em;
  margin-bottom:4px;
}
.ofscore-pressure__label.pos{ color:var(--pulse); }
.ofscore-pressure__label.neg{ color:var(--danger); }
.ofscore-pressure__ratio{
  font-family:var(--font-mono); font-size:25px; font-weight:700;
  line-height:1.1; margin-bottom:7px;
}
.ofscore-pressure__buy{ color:var(--pulse); }
.ofscore-pressure__sell{ color:var(--danger); }
.ofscore-pressure__sep{ color:var(--mute-dim); font-weight:400; margin:0 2px; }
.ofscore-pressure__bar{
  display:flex; height:10px; border-radius:5px; overflow:hidden;
  background:var(--line-soft);
  margin-bottom:10px;
}
.ofscore-pressure__bar-buy{ background:var(--pulse); transition:width .3s ease; }
.ofscore-pressure__bar-sell{ background:var(--danger); transition:width .3s ease; }
.ofscore-value{
  font-family:var(--font-mono); font-size:28px; font-weight:700;
  text-align:center; color:var(--ink); line-height:1.1;
}
.ofscore-value.pos{ color:var(--pulse); }
.ofscore-value.neg{ color:var(--danger); }
.ofscore-label{
  text-align:center; font-size:12.5px; color:var(--mute-dim);
  text-transform:uppercase; letter-spacing:.04em;
  margin-top:2px; margin-bottom:10px;
}

/* Exchange marks: small rounded-square icon tiles (each SVG paints its own
   brand-accurate background + mark) instead of the old flat 3-letter text
   badges — so an exchange is tellable apart by its tile at a glance. */
.tape-row__exch, .liq-sidebar__exch, .whale-exch{
  flex:none;
  display:inline-flex; align-items:center; justify-content:center;
  border-radius:6px; overflow:hidden;
  box-shadow:0 0 0 1px rgba(255,255,255,0.06);
}
.tape-row__exch{ width:18px; height:18px; }
.liq-sidebar__exch{ width:17px; height:17px; }
.whale-exch{ width:17px; height:17px; }
.tape-row__exch svg, .liq-sidebar__exch svg, .whale-exch svg{ display:block; }

/* ---------- trade tape rows ---------- */
.live-tape{
  flex:1; min-height:0;
  overflow-y:auto;
  padding:4px 0;
  /* very low-contrast scanline texture so the space below the last trade
     (or under the "Waiting for new trades…" indicator on a quiet market)
     reads as intentional terminal surface rather than dead black space.
     Deliberately faint — it should not compete with trade row data. */
  background-image:repeating-linear-gradient(
    0deg,
    rgba(255,255,255,0.018) 0px,
    rgba(255,255,255,0.018) 1px,
    transparent 1px,
    transparent 3px
  );
}
.live-tape__empty{
  padding:40px 16px; text-align:center;
  color:var(--mute-dim); font-size:14.5px;
  display:flex; flex-direction:column; align-items:center; gap:10px;
}
.live-tape__empty-icon{
  font-size:26px; line-height:1; opacity:.35;
}
.live-tape__empty-title{
  font-family:var(--font-mono); font-size:14px; font-weight:700;
  color:var(--mute); letter-spacing:.02em;
}
.live-tape__empty-sub{
  font-size:12.5px; color:var(--mute-dim); max-width:280px;
}
/* Loading variant: a slow pulse on the icon signals "still working on it"
   without implying anything is broken. */
.live-tape__empty--loading .live-tape__empty-icon{
  animation:th-empty-pulse 1.6s ease-in-out infinite;
}
@keyframes th-empty-pulse{
  0%, 100%{ opacity:.25; }
  50%{ opacity:.55; }
}
/* Unavailable variant: static (no pulse) plus an amber accent on the title
   so it visibly reads as a different state from "still loading". */
.live-tape__empty--unavailable .live-tape__empty-title{ color:var(--signal); }
.live-tape__empty--unavailable .live-tape__empty-icon{ opacity:.3; }
/* ---------- idle-state indicator ----------
   Sits at the bottom of the tape panel (not inside the virtualized row
   list — it's a sibling of #live-tape-list, so it's never touched by that
   list's own render/spacer logic). Anchored to the panel rather than the
   scrolling list, so it always reads as "part of the empty space below
   the last trade" whether that gap is small or (during a quiet market)
   fills most of the ~70vh panel. Hidden by default; trade-tape.js adds
   .live-tape-idle--visible once a while has passed with no new prints,
   and removes it the moment the next trade arrives. */
.live-tape-idle{
  position:absolute; left:50%; bottom:16px; transform:translateX(-50%);
  display:flex; align-items:center; gap:7px;
  padding:6px 14px;
  font-family:var(--font-mono); font-size:12.5px; color:var(--mute-dim);
  background:rgba(11,11,11,0.7); border:1px solid var(--line);
  opacity:0; pointer-events:none;
  transition:opacity .4s ease;
  z-index:2;
}
.live-tape-idle--visible{ opacity:1; }
.live-tape-idle__dot{
  width:6px; height:6px; flex:none;
  background:var(--signal);
  animation:liveTapeIdlePulse 1.6s ease-in-out infinite;
}
@keyframes liveTapeIdlePulse{
  0%, 100%{ opacity:.35; transform:scale(.85); }
  50%{ opacity:1; transform:scale(1.15); }
}
@media (prefers-reduced-motion: reduce){
  .live-tape-idle__dot{ animation:none; }
}
.tape-row{
  display:flex; align-items:center; gap:8px;
  padding:1.5px 10px;
  font-family:var(--font-mono); font-size:var(--tape-fs, 11px);
  line-height:1.3;
  border-bottom:1px solid rgba(255,255,255,0.03);
  border-left:2px solid transparent;
}
.tape-row--buy{ background:rgba(0,255,136,.06); }
.tape-row--sell{ background:rgba(255,77,77,.06); }
.tape-row.tape-tier-2{ background-color:rgba(0,255,136,.12); }
.tape-row.tape-tier-2.tape-row--sell{ background-color:rgba(255,77,77,.12); }
.tape-row.tape-tier-3{ font-weight:700; padding-top:5px; padding-bottom:5px; background-color:rgba(0,255,136,.2); }
.tape-row.tape-tier-3.tape-row--sell{ background-color:rgba(255,77,77,.2); }
.tape-row.tape-tier-4{ font-weight:800; padding-top:6px; padding-bottom:6px; background-color:rgba(0,255,136,.32); }
.tape-row.tape-tier-4.tape-row--sell{ background-color:rgba(255,77,77,.32); }

/* ---------- outsized-print highlight hierarchy ($100K / $500K / $1M) ----------
   Layered on top of the buy/sell tint above via a left accent bar + faint
   wash, so direction stays legible while size still stands out. Escalates
   via border thickness + glow within the amber family, not by switching
   to --danger red on the top tier — a big *buy* print (green wash) getting
   a red border/value would read as a sell it isn't. Direction stays the
   tape's own job (background tint, ▲/▼ side glyph, price colour); this
   hierarchy is purely "how big", so it never touches red/green. */
.tape-row.tape-hl-1{ border-left-color:rgba(255,200,87,.55); box-shadow:inset 4px 0 10px -8px rgba(255,200,87,.6); }
.tape-row.tape-hl-2{ border-left-color:var(--signal); background-image:linear-gradient(90deg, rgba(255,200,87,.14), rgba(255,200,87,.05) 60%); }
.tape-row.tape-hl-3{
  border-left-width:4px;
  border-left-color:var(--signal);
  background-image:linear-gradient(90deg, rgba(255,200,87,.26), rgba(255,200,87,.07) 65%);
  box-shadow:inset 0 0 0 1px rgba(255,200,87,.3);
  font-weight:800;
}
.tape-row.tape-hl-3 .tape-row__value{ color:var(--signal); }

/* ---------- Settings: Terminal — Highlight whale trades toggles ----------
   trade-tape.js always computes tape-hl-1/2/3 for every row; these shell
   modifiers (flipped by settings-extras.js) neutralize a tier's accent
   without touching the size-based tape-tier-N bolding above, which is a
   separate always-on density cue. th-hl-off is the master "Highlight whale
   trades" switch; th-hl-N-off are the individual >100k/>500k/>1M toggles. */
.th-hl-off .tape-row.tape-hl-1,
.th-hl-off .tape-row.tape-hl-2,
.th-hl-off .tape-row.tape-hl-3,
.th-hl-1-off .tape-row.tape-hl-1,
.th-hl-2-off .tape-row.tape-hl-2,
.th-hl-3-off .tape-row.tape-hl-3{
  border-left-color:transparent; box-shadow:none; background-image:none;
}
.th-hl-off .tape-row.tape-hl-3 .tape-row__value,
.th-hl-3-off .tape-row.tape-hl-3 .tape-row__value{ color:inherit; }

/* ---------- Settings: Terminal — Show volumes toggle ---------- */
.th-hide-volumes .tape-row__value{ display:none; }

.tape-row__side{ flex:none; width:12px; text-align:center; font-size:11.5px; }
.tape-row--buy .tape-row__side{ color:var(--pulse); }
.tape-row--sell .tape-row__side{ color:var(--danger); }
.tape-row__price{ flex:none; width:90px; color:var(--ink); font-variant-numeric:tabular-nums; }
.tape-row--buy .tape-row__price{ color:var(--pulse); }
.tape-row--sell .tape-row__price{ color:var(--danger); }
.tape-row__qty{ flex:1; min-width:0; color:var(--mute); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.tape-row__value{ flex:none; width:72px; text-align:right; color:var(--ink); font-weight:600; }
.tape-row__time{ flex:none; width:66px; text-align:right; color:var(--mute-dim); font-size:12.5px; white-space:nowrap; }
.tape-row__cluster{
  flex:none; font-size:11.5px; font-weight:700;
  color:#000000; background:var(--pulse);
  border-radius:999px; padding:1px 6px; line-height:1.4;
  cursor:help;
}
.tape-row--sell .tape-row__cluster{ background:var(--danger); color:#fff; }

/* ---------- Tape modes: Compact / Normal / Large / Whales only ----------
   Normal = the base .tape-row rule above, no class needed. Compact/Large
   only change row density (padding/gap/font); the tier-based padding bumps
   above (tape-tier-3/4) still apply on top of whichever density is active.
   Whales-only doesn't change row layout — the filtering that keeps only
   $100k+ prints happens in trade-tape.js's render() — this just adds a
   small accent so it's visually obvious the mode is active even before any
   trade has arrived. */
.tape-mode--compact .tape-row{ padding-top:1px; padding-bottom:1px; gap:8px; font-size:var(--tape-fs, 10px); }
.tape-mode--compact .tape-row.tape-tier-3{ padding-top:3px; padding-bottom:3px; }
.tape-mode--compact .tape-row.tape-tier-4{ padding-top:4px; padding-bottom:4px; }

.tape-mode--large .tape-row{ padding-top:8px; padding-bottom:8px; gap:12px; font-size:var(--tape-fs, 14px); }
.tape-mode--large .tape-row.tape-tier-3{ padding-top:11px; padding-bottom:11px; }
.tape-mode--large .tape-row.tape-tier-4{ padding-top:14px; padding-bottom:14px; }
.tape-mode--large .tape-row__value{ width:88px; }

.tape-mode--whales .live-tape{ border-top:2px solid var(--signal); }
.tape-mode--whales .tape-row{ border-left:2px solid rgba(255,200,87,.4); }

/* ---------- terminal typography + density pass ----------
   IBM Plex Mono everywhere inside the sidebar (headers were inheriting the
   site's display font), and tighter card padding so the 2-column grid
   above reads as dense/information-rich rather than airy. */
.live-term__side .widget-card{
  background:transparent;
  border:none;
  border-bottom:1px solid var(--line);
  padding:8px 10px;
}
.live-term__side .widget-card:last-child{ border-bottom:none; }
.live-term__side .widget-card__head{ margin-bottom:6px; }
.live-term__side .widget-card__head h4{
  font-family:var(--font-mono); font-size:12.5px; font-weight:700;
  text-transform:uppercase; letter-spacing:.07em; color:var(--mute);
}
.live-term__side .mstat-row{ padding:2px 0; font-size:12.5px; }

/* ---------- sidebar: 2-column compact grid ----------
   Pairing (matches DOM order): Market Pulse | Order Flow Score,
   Whale Tracker | Market Overview, Statistics | Watchlist.
   List-heavy cards, plus Order Flow (whose "Biggest trade (5m)" row and
   60s stat grid read as cramped at half width), span both columns so
   their content stays readable instead of being squeezed narrow. The
   compact stat cards pair up automatically around them via
   grid-auto-flow:dense. */
.live-term__side{
  min-width:0;
  display:grid;
  grid-template-columns:1fr 1fr;
  grid-auto-flow:row dense;
  gap:0; align-content:start;
  border-left:1px solid var(--line);
  background:var(--void);
  position:relative;
  /* ---------- scroll-boundary fades ----------
     A soft inset shadow at the top/bottom edges hints that the card list
     continues beyond view. Lives on the container's own box (not a scrolled
     child), so it stays anchored at the edges whether the sidebar scrolls
     independently (fullscreen, via overflow-y:auto) or the whole page
     scrolls past it below the 980px breakpoint — and it never covers or
     intercepts clicks on the cards underneath. */
  box-shadow:
    inset 0 24px 16px -16px rgba(0,0,0,.55),
    inset 0 -24px 16px -16px rgba(0,0,0,.55);
}
.live-term__side .widget-card{ min-width:0; }
/* ---------- customizable dashboard: hidden widgets ----------
   display:none (not visibility/opacity) so the grid's dense auto-flow
   reclaims the freed cell immediately — no gap, no manual reflow needed.
   The card stays in the DOM and keeps receiving live updates underneath;
   only its box is pulled from the grid. */
.live-term__side .widget-card.widget-card--hidden,
.live-term__side .wc-split-col.widget-card--hidden{ display:none !important; }
/* list-heavy cards (multi-row tables) get the full width instead of being
   squeezed into a half-width column; the compact stat cards pair up
   automatically around them via grid-auto-flow:dense. */
.live-term__side .orderflow-card,
.live-term__side .liq-sidebar,
.live-term__side .whale-card,
.live-term__side .livechart-card,
.live-term__side .pulseflow-card,
.live-term__side .mktoverview-card{ grid-column:1 / -1; }
@media (max-width:980px){
  /* stacked single-column layout below the breakpoint (matches .live-term
     itself collapsing to one column there) — pairing two narrow cards
     side by side isn't worth it once the whole terminal is already stacked. */
  .live-term__side{ grid-template-columns:1fr; }
  .live-term__side .orderflow-card,
  .live-term__side .liq-sidebar,
  .live-term__side .whale-card,
  .live-term__side .livechart-card,
  .live-term__side .pulseflow-card,
  .live-term__side .mktoverview-card{ grid-column:auto; }
}
.liq-sidebar{ display:flex; flex-direction:column; }
.liq-sidebar .widget-card__body{ display:flex; flex-direction:column; min-height:0; flex:1; }
.liq-sidebar__src{
  font-family:var(--font-mono); font-size:11.5px; font-weight:500;
  color:var(--mute-dim); text-transform:uppercase; letter-spacing:.05em;
  margin-left:8px;
}

/* ---------- Liquidations: stats summary ---------- */
.liq-stats{ padding-bottom:10px; margin-bottom:8px; border-bottom:1px solid var(--line-soft); }

/* ---------- Liquidations: all timeframes at once (15m/30m/1h/4h) ----------
   Every window renders as its own block — window label on top, then
   Long/Short side by side as value-over-label pairs — separated from the
   next window by a dashed divider. No Total figure and no filter row;
   the feed below always shows everything. */
.liq-multi{ display:flex; flex-direction:column; }
.liq-multi-block{
  padding:7px 0;
  border-bottom:1px dashed var(--line-soft);
}
.liq-multi-block:first-child{ padding-top:0; }
.liq-multi-block:last-child{ padding-bottom:0; border-bottom:none; }
.liq-multi-block__win{
  display:block;
  font-family:var(--font-mono); font-size:11.5px; font-weight:700; letter-spacing:.03em;
  color:var(--mute-dim); text-transform:uppercase;
  margin-bottom:5px;
}
.liq-multi-block__sides{
  display:flex; align-items:stretch; gap:8px;
}
.liq-multi-block__side{
  flex:1 1 0; min-width:0;
  display:flex; flex-direction:column; align-items:center; gap:1px;
}
.liq-multi-block__value{
  font-family:var(--font-mono); font-size:19px; font-weight:800;
  color:var(--ink); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; max-width:100%;
  line-height:1.15;
}
.liq-multi-block__label{
  font-family:var(--font-mono); font-size:10px; font-weight:600; letter-spacing:.06em;
  color:var(--mute-dim);
}
.liq-multi-block__side--long .liq-multi-block__value{ color:var(--danger); }
.liq-multi-block__side--short .liq-multi-block__value{ color:var(--pulse); }
@media (max-width:640px){
  .liq-multi-block__value{ font-size:17px; }
}

.liq-sidebar__head-row{
  display:flex; align-items:center; gap:6px;
  padding:4px 6px 8px;
  font-family:var(--font-mono); font-size:11.5px; text-transform:uppercase; letter-spacing:.05em;
  color:var(--mute-dim);
  border-bottom:1px solid var(--line-soft);
}
.liq-sidebar__head-row span:nth-child(1){ flex:none; width:22px; }
.liq-sidebar__head-row span:nth-child(2){ flex:none; width:44px; }
.liq-sidebar__head-row span:nth-child(3){ flex:none; width:50px; }
.liq-sidebar__head-row span:nth-child(4){ flex:1; }
.liq-sidebar__head-row span:nth-child(5){ flex:none; width:64px; }
.liq-sidebar__head-row .ta-r{ text-align:right; }

.liq-sidebar__list{
  list-style:none; margin:0; padding:0;
  flex:1; min-height:0; overflow-y:auto;
  max-height:400px;
}
.liq-sidebar__empty{
  padding:20px 8px; text-align:center;
  color:var(--mute-dim); font-size:13.5px; list-style:none;
}
.liq-sidebar__row{
  display:flex; align-items:center; gap:6px;
  padding:6px;
  font-family:var(--font-mono); font-size:13px;
  border-bottom:1px solid rgba(255,255,255,0.03);
}
.liq-sidebar__row--long{ background:rgba(255,77,77,.10); }
.liq-sidebar__row--short{ background:rgba(0,255,136,.10); }
.liq-sidebar__sym{ flex:none; width:44px; font-weight:700; color:var(--ink); }
.liq-sidebar__side{ flex:none; width:50px; font-size:12px; white-space:nowrap; }
.liq-sidebar__row--long .liq-sidebar__side{ color:var(--danger); }
.liq-sidebar__row--short .liq-sidebar__side{ color:var(--pulse); }
.liq-sidebar__usd{ flex:1; text-align:right; font-weight:700; color:var(--ink); }
.liq-sidebar__time{ flex:none; width:64px; text-align:right; color:var(--mute-dim); font-size:12px; white-space:nowrap; }

/* ---------- unusually-large liquidation highlighting ----------
   Same three tiers as the trade tape's highlightTier() ($100k/$500k/$1M),
   layered as an inset ring on top of the long/short background tint so
   both signals stay visible at once. Escalates via ring thickness/
   brightness within the amber family, not by switching to red/green — a
   big *short* liquidation (green row) ringed in --danger would read as a
   sell signal it isn't, so size stays on its own amber channel. */
.liq-sidebar__row--tier1{ box-shadow:inset 0 0 0 1px rgba(255,200,87,.35); }
.liq-sidebar__row--tier2{ box-shadow:inset 0 0 0 1px rgba(255,159,10,.55); }
.liq-sidebar__row--tier3{ box-shadow:inset 0 0 0 2px rgba(255,159,10,.9); }
.liq-sidebar__row--tier2 .liq-sidebar__usd,
.liq-sidebar__row--tier3 .liq-sidebar__usd{ color:var(--signal); }

/* thin scrollbars to match the rest of the terminal */
.live-tape, .liq-sidebar__list{ scrollbar-width:thin; scrollbar-color:var(--line) transparent; }
.live-tape::-webkit-scrollbar, .liq-sidebar__list::-webkit-scrollbar{ width:6px; }
.live-tape::-webkit-scrollbar-thumb, .liq-sidebar__list::-webkit-scrollbar-thumb{ background:var(--line); border-radius:3px; }

/* ---------- Prompt 11: Whale Tracker card ---------- */

/* ---------- Whale Tracker: stats summary ---------- */
.whale-stats{ padding-bottom:8px; margin-bottom:8px; border-bottom:1px solid var(--line-soft); }
.whale-stats__row{ display:flex; gap:10px; }
.whale-stats__item{ flex:1; min-width:0; display:flex; flex-direction:column; gap:2px; font-family:var(--font-mono); }
.whale-stats__label{ font-size:11.5px; color:var(--mute-dim); text-transform:uppercase; letter-spacing:.04em; }
.whale-stats__value{ font-size:14.5px; font-weight:700; color:var(--ink); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }

/* Empty state: no whale trades recorded yet for this asset — collapse the
   whole card to one short line instead of showing an empty stats row,
   empty filter tabs and an empty list stacked on top of each other. */
.whale-card--empty .widget-card__head{ margin-bottom:2px; }
.whale-card--empty .widget-card__body{
  height:auto; padding-top:0; padding-bottom:0;
}
.whale-empty-msg{
  font-family:var(--font-mono); font-size:13.5px; color:var(--mute-dim);
  line-height:1.3;
}
.whale-empty-msg[hidden]{ display:none; }

.whale-tabs{ display:flex; flex-wrap:wrap; gap:5px; margin-bottom:8px; }
.whale-tab{
  flex:1 1 auto; padding:5px 6px;
  font-family:var(--font-mono); font-size:12px; font-weight:600;
  color:var(--mute-dim); background:var(--void);
  border:1px solid var(--line); border-radius:6px;
  cursor:pointer; transition:color .15s ease, border-color .15s ease, background .15s ease;
  white-space:nowrap;
}
.whale-tab:hover{ color:var(--ink); }
.whale-tab--active{ color:var(--ink); border-color:var(--signal); background:rgba(255,255,255,0.04); }
.whale-head-row{
  display:flex; align-items:center; gap:6px;
  padding:4px 6px 8px;
  font-family:var(--font-mono); font-size:11.5px; text-transform:uppercase; letter-spacing:.05em;
  color:var(--mute-dim);
  border-bottom:1px solid var(--line-soft);
}
.whale-head-row span:nth-child(1){ flex:none; width:26px; }
.whale-head-row span:nth-child(2){ flex:none; width:36px; }
.whale-head-row span:nth-child(3){ flex:none; width:54px; }
.whale-head-row span:nth-child(4){ flex:1; }
.whale-head-row span:nth-child(5){ flex:none; width:64px; }
.whale-head-row .ta-r{ text-align:right; }
.whale-list{
  list-style:none; margin:0; padding:0;
  max-height:340px; overflow-y:auto;
  scrollbar-width:thin; scrollbar-color:var(--line) transparent;
}
.whale-list::-webkit-scrollbar{ width:6px; }
.whale-list::-webkit-scrollbar-thumb{ background:var(--line); border-radius:3px; }
.whale-empty{
  padding:20px 8px; text-align:center;
  color:var(--mute-dim); font-size:13.5px; list-style:none;
}
.whale-row{
  display:flex; align-items:center; gap:6px;
  padding:6px;
  font-family:var(--font-mono); font-size:13px;
  border-bottom:1px solid rgba(255,255,255,0.03);
}
.whale-row--buy{ background:rgba(0,255,136,.10); }
.whale-row--sell{ background:rgba(255,77,77,.10); }
.whale-pair{ flex:none; width:36px; font-weight:700; color:var(--ink); }
.whale-side{ flex:none; width:54px; font-size:12px; white-space:nowrap; }
.whale-row--buy .whale-side{ color:var(--pulse); }
.whale-row--sell .whale-side{ color:var(--danger); }
.whale-value{ flex:1; text-align:right; font-weight:700; color:var(--ink); }
.whale-time{ flex:none; width:64px; text-align:right; color:var(--mute-dim); font-size:12px; white-space:nowrap; }

/* ---------- unusually-large whale trade highlighting ----------
   Same three tiers as the trade tape's highlightTier() ($100k/$500k/$1M).
   Escalates via ring thickness/brightness within the amber family, not by
   switching to red/green — direction is already shown by the row's own
   buy/sell tint (.whale-row--buy/--sell above), so a size-based ring in
   --danger would silently repaint a *buy* row red once it got big enough. */
.whale-row--tier1{ box-shadow:inset 0 0 0 1px rgba(255,200,87,.35); }
.whale-row--tier2{ box-shadow:inset 0 0 0 1px rgba(255,159,10,.55); }
.whale-row--tier3{ box-shadow:inset 0 0 0 2px rgba(255,159,10,.9); }
.whale-row--tier2 .whale-value,
.whale-row--tier3 .whale-value{ color:var(--signal); }

/* ---------- big-trade flash (flash-effects.js) ----------
   A brief pulse across the whole live-tape panel on $100k+/$500k+/$1M+
   prints, so a whale trade registers even if you're not staring at the
   tape row itself. Buy = green tint, sell = red tint; intensity and
   duration scale with size. Border-box only (box-shadow), so it never
   shifts layout. */
.live-term--flash-buy{ --flash-rgb: 0,255,136; }
.live-term--flash-sell{ --flash-rgb: 255,77,77; }
.live-term--flash-t1{ animation: liveTermFlash .5s ease-out; }
.live-term--flash-t2{ animation: liveTermFlash .7s ease-out; }
.live-term--flash-t3{ animation: liveTermFlashBig 1s ease-out; }
@keyframes liveTermFlash{
  0%{ box-shadow: inset 0 0 0 1px rgba(var(--flash-rgb,0,255,136),.5), 0 0 26px -4px rgba(var(--flash-rgb,0,255,136),.4); }
  100%{ box-shadow: inset 0 0 0 1px rgba(var(--flash-rgb,0,255,136),0), 0 0 26px -4px rgba(var(--flash-rgb,0,255,136),0); }
}
@keyframes liveTermFlashBig{
  0%{ box-shadow: inset 0 0 0 2px rgba(var(--flash-rgb,0,255,136),.85), 0 0 46px -2px rgba(var(--flash-rgb,0,255,136),.55); }
  55%{ box-shadow: inset 0 0 0 1px rgba(var(--flash-rgb,0,255,136),.4), 0 0 32px -4px rgba(var(--flash-rgb,0,255,136),.32); }
  100%{ box-shadow: inset 0 0 0 1px rgba(var(--flash-rgb,0,255,136),0), 0 0 26px -4px rgba(var(--flash-rgb,0,255,136),0); }
}
@media (prefers-reduced-motion: reduce){
  .live-term--flash-t1, .live-term--flash-t2, .live-term--flash-t3{ animation:none; }
  .livechart-price--flash-up, .livechart-price--flash-down{ animation:none; }
}

/* ---------- Live Chart widget ---------- */
.livechart-card .widget-card__body{ padding-top:2px; }
/* Brief wash of color on the header price tag for a live tick — the
   underlying .tag--pos/.tag--neg background shows again once the
   animation ends (animations don't persist past their keyframes unless
   given fill-mode:forwards, which this deliberately omits). */
@keyframes livechartPriceFlashUp{ 0%{ background:rgba(0,255,136,.38); } 100%{ background:transparent; } }
@keyframes livechartPriceFlashDown{ 0%{ background:rgba(255,77,77,.38); } 100%{ background:transparent; } }
.livechart-price--flash-up{ animation:livechartPriceFlashUp .5s ease-out; }
.livechart-price--flash-down{ animation:livechartPriceFlashDown .5s ease-out; }
.livechart-toolbar{
  display:flex; align-items:center; flex-wrap:wrap; gap:6px 8px;
  margin-bottom:8px;
}
.livechart-toolbar .tape-toolbar__group{ display:flex; align-items:center; gap:4px; }
.livechart-toolbar .tape-toolbar__select{ padding:3px 5px; }
#livechart-type-group{ gap:2px; }
#livechart-type-group .toolbar-btn{ padding:3px 8px; }
.livechart-indicator-control{ position:relative; }
.livechart-indicator-panel{
  width:190px;
  top:calc(100% + 6px); right:0; left:auto;
}
.livechart-indicator-panel .filter-panel__checkbox{ cursor:pointer; }
/* Replay mode is a UI state, not a market signal, so it uses the shared
   .toolbar-btn--active amber styling (see line ~293) instead of red —
   red is reserved for price/trade direction elsewhere in the terminal. */

/* ---------- Replay Mode: compact scrub/play bar ---------- */
.livechart-replay-bar{
  display:flex; align-items:center; gap:6px;
  margin-bottom:8px;
  padding:4px 8px;
  background:var(--signal-soft);
  border:1px solid rgba(255,200,87,.35);
  border-radius:6px;
}
.livechart-replay-bar[hidden]{ display:none; }
.livechart-replay-bar .toolbar-btn--sq{ padding:2px 7px; font-size:12.5px; flex:0 0 auto; }
.livechart-replay-slider{
  flex:1; min-width:0;
  accent-color:var(--signal);
  height:4px;
  cursor:pointer;
}
.livechart-replay-time{
  font-family:var(--font-mono); font-size:11.5px; color:var(--mute);
  white-space:nowrap;
}
.livechart-replay-speed{ padding:2px 4px; font-size:12.5px; flex:0 0 auto; }

.chart-share-modal{
  position:fixed; inset:0; z-index:970;
  display:none; align-items:center; justify-content:center;
  padding:20px;
}
.chart-share-modal.open{ display:flex; }
.chart-share-modal__backdrop{
  position:absolute; inset:0;
  background:rgba(3,3,3,0.78); backdrop-filter:blur(4px);
}
html.chart-share-lock{ overflow:hidden; }
.chart-share-modal__panel{
  position:relative; width:100%; max-width:480px; max-height:88vh;
  background:var(--panel); border:1px solid var(--line);
  box-shadow:0 24px 70px rgba(0,0,0,.55);
  display:flex; flex-direction:column; gap:10px;
  padding:16px; overflow-y:auto;
}
.chart-share-modal__close{
  position:absolute; top:8px; right:8px; width:28px; height:28px;
  display:flex; align-items:center; justify-content:center;
  background:transparent; border:1px solid var(--line); color:var(--mute);
  font-size:18px; line-height:1; cursor:pointer;
}
.chart-share-modal__close:hover{ color:var(--ink); border-color:var(--mute-dim); }
.chart-share-modal__preview{
  border:1px solid var(--line); background:var(--void);
  display:flex; align-items:center; justify-content:center; overflow:hidden;
}
.chart-share-modal__img{ display:block; width:100%; height:auto; }
.chart-share-modal__label{
  font:600 11px var(--font-mono); color:var(--mute); text-transform:uppercase; letter-spacing:.04em;
}
.chart-share-modal__input{
  width:100%; padding:9px 10px; font:14px var(--font-body); color:var(--ink);
  background:var(--panel-hover); border:1px solid var(--line); border-radius:var(--radius-sm);
}
.chart-share-modal__input:focus{ outline:none; border-color:var(--signal); }
.chart-share-modal__actions{ display:flex; gap:8px; margin-top:2px; }
.chart-share-modal__btn{
  flex:1; padding:10px 12px; font:600 13px var(--font-mono); cursor:pointer;
  background:var(--panel-hover); border:1px solid var(--line); color:var(--ink);
  transition:border-color .15s ease, color .15s ease;
}
.chart-share-modal__btn:hover{ border-color:var(--mute-dim); }
.chart-share-modal__btn--primary{
  background:var(--signal-soft); border-color:var(--signal); color:var(--signal);
}
.chart-share-modal__btn--primary:hover{ background:var(--signal); color:var(--void); }
.chart-share-modal__status{
  font:600 12px var(--font-mono); color:var(--pulse); margin:0; text-align:center;
}
.chart-share-modal__status--error{ color:var(--danger); }
.chart-share-modal__hint{
  font:12px var(--font-body); color:var(--mute-dim); margin:0; line-height:1.4;
}
@media (max-width:520px){
  .chart-share-modal{ padding:0; align-items:flex-end; }
  .chart-share-modal__panel{ max-width:none; max-height:92vh; border-left:0; border-right:0; border-bottom:0; }
}

/* Price + stats ticker — sits between the header and the toolbar so the
   headline number (current price + 24h %) and the five key reference
   stats (24h high, low, spread, volume, open interest) are readable at a
   glance, without needing to check the separate Market Overview card. */
.livechart-ticker{
  margin-bottom:8px;
  padding:8px 10px 7px;
  background:var(--void);
  border:1px solid var(--line-soft);
  border-radius:6px;
}
.livechart-ticker__headline{
  display:flex; align-items:baseline; gap:8px;
  margin-bottom:6px;
}
.livechart-ticker__price{
  font-family:var(--font-mono); font-size:22px; font-weight:700;
  line-height:1.1; color:var(--ink);
}
.livechart-ticker__price.pos{ color:var(--pulse); }
.livechart-ticker__price.neg{ color:var(--danger); }
.livechart-ticker__change{
  font-family:var(--font-mono); font-size:14.5px; font-weight:600;
  color:var(--mute-dim);
}
.livechart-ticker__change.pos{ color:var(--pulse); }
.livechart-ticker__change.neg{ color:var(--danger); }
.livechart-ticker__stats{
  display:flex; align-items:stretch;
  gap:1px;
  background:var(--line-soft);
  border:1px solid var(--line-soft);
  border-radius:5px;
  overflow:hidden;
}
.livechart-ticker__stat{
  flex:1; min-width:0;
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:2px;
  padding:5px 3px;
  background:var(--panel, #12151C);
}
.livechart-ticker__stat-label{
  font-size:11px; text-transform:uppercase; letter-spacing:.06em;
  color:var(--mute-dim);
  white-space:nowrap;
  display:inline-flex; align-items:center;
}
.livechart-ticker__stat-value{
  font-family:var(--font-mono); font-size:14px; font-weight:600;
  color:var(--ink);
  white-space:nowrap;
}
/* The 24H/Low cells double as a compact range read, same red/green
   convention the rest of the terminal uses for high/low reference points. */
.livechart-ticker__stat:nth-child(1) .livechart-ticker__stat-value{ color:var(--pulse); }
.livechart-ticker__stat:nth-child(2) .livechart-ticker__stat-value{ color:var(--danger); }

.livechart-canvas-wrap{
  position:relative;
  height:297px; /* was 220px, then 270px — chart is the primary widget on this screen; +10% again on top of the 270px pass */
  background:var(--void);
  border:1px solid var(--line-soft);
  overflow:hidden;
}
.livechart-canvas-wrap canvas{
  display:block; width:100%; height:100%;
  cursor:crosshair;
  /* The chart handles its own drag-to-pan and pinch-to-zoom (live-chart.js);
     without this the browser also tries to scroll/zoom the page for the
     same touch gestures, fighting the chart for them. */
  touch-action:none;
}
/* ---------- resizable chart height (drag to resize, remembered) ---------- */
.livechart-resize-handle{
  position:absolute; left:0; right:0; bottom:0; height:7px;
  cursor:row-resize;
  z-index:3;
  touch-action:none;
}
.livechart-resize-handle::after{
  content:''; position:absolute; left:0; right:0; bottom:2px; height:1px;
  background:var(--line-soft);
}
.livechart-resize-handle:hover::after,
.livechart-resize-handle--active::after{ bottom:1px; height:3px; background:var(--signal); }
.livechart-card:fullscreen .livechart-resize-handle,
.livechart-card--fullscreen .livechart-resize-handle{ display:none; }
.livechart-legend{
  position:absolute; top:6px; left:8px; z-index:2;
  display:flex; flex-wrap:wrap; gap:2px 10px;
  font-family:var(--font-mono); font-size:11.5px; color:var(--mute);
  pointer-events:none;
  text-shadow:0 1px 2px rgba(0,0,0,.8);
}
/* Mobile: the O/H/L/C strip is otherwise a single unwrapped-looking row
   that runs straight into the shaded price-axis panel on the right (it
   already wraps via flex-wrap, but with no right boundary it wraps far
   too late, right at the axis). Stopping it short of the axis makes it
   wrap onto a second line while there's still room, instead of visually
   colliding with the price labels. */
@media (max-width:480px){
  .livechart-legend{ right:64px; }
}
.livechart-legend b{ font-weight:700; }
.livechart-legend .pos{ color:var(--pulse); }
.livechart-legend .neg{ color:var(--danger); }
.livechart-marker-legend{
  position:absolute; bottom:14px; left:8px; z-index:2;
  display:flex; flex-wrap:wrap; gap:2px 9px;
  font-family:var(--font-mono); font-size:10.5px; font-weight:700; letter-spacing:.02em;
  pointer-events:none;
  text-shadow:0 1px 2px rgba(0,0,0,.85);
}
.livechart-marker-legend .lcml-item--buy{ color:var(--pulse); }
.livechart-marker-legend .lcml-item--sell{ color:var(--danger); }
.livechart-marker-legend .lcml-item--whale{ color:var(--signal); }
.livechart-marker-legend .lcml-item--liq{ color:var(--ink); }
.livechart-loading{
  position:absolute; inset:0; z-index:3;
  display:flex; align-items:center; justify-content:center;
  font-family:var(--font-mono); font-size:12.5px; color:var(--mute-dim);
  background:rgba(5,5,5,.5);
  transition:opacity .2s ease;
}
.livechart-loading[hidden]{ display:none; }
.livechart-subpane{
  position:relative;
  height:64px;
  margin-top:4px;
  background:var(--void);
  border:1px solid var(--line-soft);
  overflow:hidden;
}
.livechart-subpane canvas{ display:block; width:100%; height:100%; }
.livechart-subpane__label{
  position:absolute; top:3px; left:6px; z-index:2;
  font-family:var(--font-mono); font-size:10.5px; text-transform:uppercase; letter-spacing:.05em;
  color:var(--mute-dim);
  pointer-events:none;
}

/* fullscreen: the card itself becomes the fullscreen element and grows to
   fill the viewport, same convention as .live-term--fullscreen for the tape */
.livechart-card:fullscreen,
.livechart-card.livechart-card--fullscreen{
  background:var(--panel); padding:12px; height:100vh;
  display:flex; flex-direction:column;
}
.livechart-card:fullscreen .livechart-canvas-wrap,
.livechart-card--fullscreen .livechart-canvas-wrap{ flex:1; height:auto; min-height:0; }
.livechart-card:fullscreen .widget-card__body,
.livechart-card--fullscreen .widget-card__body{ flex:1; min-height:0; display:flex; flex-direction:column; }

@media (max-width:640px){
  .livechart-toolbar .tape-toolbar__label{ display:none; }
}

/* ============================================================
   Mobile default layout
   Placed at the end of the stylesheet on purpose: several of these
   rules share a selector with an earlier, unconditional rule (e.g.
   .live-term__side's display:grid, .live-tape's flex:1), and at equal
   specificity the later declaration in the file wins whenever both
   apply — so this block needs to come last to reliably override them
   below the breakpoint, without touching the desktop rules themselves.
   ============================================================ */
@media (max-width:980px){
  .live-term{ overflow-x:hidden; }

  /* ---------- reorder: Live Chart first, trade tape second,
     Liquidations third, everything else after ----------
     .live-term__side is only ever a wrapper for the sidebar cards —
     giving it display:contents unwraps it so those cards become direct
     items of the .live-term grid alongside .live-term__main, which lets
     `order` interleave them instead of the whole sidebar always trailing
     the tape as one block. Every descendant selector still matches
     (e.g. ".live-term__side .widget-card"): display:contents only drops
     the wrapper's own box — its border-left/background/scroll-fade
     shadow no longer render — it stays in the DOM. Drag-to-reorder
     (layout-persistence.js) still works exactly as before; it reorders
     the underlying DOM/localStorage, it just no longer changes what's
     drawn here, since this fixed order is the point of a "default"
     mobile layout. */
  .live-term__side{ display:contents; }
  .livechart-card{ order:1; }
  .live-term__main{ order:2; }
  .liq-sidebar{ order:3; }
  .orderflow-card{ order:4; }
  .pulseflow-card{ order:5; }
  .whale-card{ order:6; }
  .mktoverview-card{ order:7; }

  /* ---------- 30 trade rows by default ----------
     The tape used to stretch (flex:1) to fit however many rows were
     currently rendered — easily 1000px+ tall — forcing a long scroll
     before reaching Live Chart/Liquidations below it. A default .tape-row
     (12px text, 1.3 line-height, 1.5px top/bottom padding, 1px border)
     is ~20px tall, so 30 rows is ~600px: fixing .live-tape's height there
     shows 30 rows by default, with the rest reachable by scrolling inside
     the tape itself — same as it already works on desktop, just bounded
     by row count instead of viewport height. The 80vh ceiling only kicks
     in on short/landscape phones — tall enough on ordinary portrait
     phones that it doesn't clip the 30-row target. Live updates,
     clustering, filters, pause/clear, etc. are untouched — this only
     changes how tall the scroll area is. */
  .live-term__main{ height:auto; }
  .live-tape{ flex:none; height:600px; max-height:80vh; }

  /* ---------- readability on small screens ---------- */
  .live-term__side .widget-card{ padding:10px 12px; }
  .live-term__side .widget-card__head{ margin-bottom:8px; }
  .live-term__side .widget-card__head h4{ font-size:13px; }
  .live-term__side .mstat-row{ padding:4px 0; font-size:13px; }
  .liq-sidebar__row, .whale-row{ padding:7px 6px; }

  /* ---------- chart: full-bleed on mobile ----------
     Breaks the canvas out of the card's own left/right padding (a
     negative margin equal to --card-pad-x, widened to compensate) so the
     candles use the phone's entire screen width instead of sitting in a
     smaller inset box with visible side margins. Border moves to the
     wrap's top/bottom only so it still reads as a distinct panel without
     drawing a vertical edge partway across the screen. The toolbar/ticker
     above stay within the card's normal padding — only the plot itself
     bleeds. live-chart.js's chartPadL()/chartPadR() already shrink the
     internal candle-area gutter to match on screens this narrow, so the
     extra width actually goes to visible candles, not empty space. */
  .livechart-canvas-wrap{
    margin-left:calc(var(--card-pad-x, 12px) * -1);
    margin-right:calc(var(--card-pad-x, 12px) * -1);
    width:auto;
    border-left:none;
    border-right:none;
  }
}

/* ============================================================
   VISUAL PRIORITY — 3-tier hierarchy
   ------------------------------------------------------------
   Everything under .live-term used to read at the same visual
   weight (same background, same border, same header treatment)
   regardless of how important the panel actually is. That forces
   the eye to scan the whole terminal instead of landing on the
   thing that matters most.

   Three tiers, same content/layout — only background depth,
   border weight and header opacity move:

     HIGH   — Terminal (trade tape) + Live Chart
              the two panels the terminal is actually "for"
     MEDIUM — Buy/Sell, Liquidations
              secondary, glanceable order-flow signals
     LOW    — Market Pulse, Whales, Market Overview/Statistics
              supporting context, read on demand not at a glance
   ============================================================ */

/* ---- HIGH: Terminal (trade tape) ---- */
.live-term__main{
  background:var(--panel-hover);
  border-top:2px solid var(--signal);
}
.term-identity-bar{ opacity:1; }

/* ---- HIGH: Live Chart ---- */
.live-term__side .livechart-card{
  background:var(--panel-hover);
  border:1px solid var(--line);
  border-top:2px solid var(--signal);
  padding:10px 12px 8px;
}
.live-term__side .livechart-card:fullscreen,
.live-term__side .livechart-card.livechart-card--fullscreen{
  border-top:2px solid var(--signal);
}
.live-term__side .livechart-card .widget-card__head{ opacity:1; }
.live-term__side .livechart-card .widget-card__head h4{ color:var(--ink); }

/* ---- MEDIUM: Buy/Sell + Liquidations ---- */
.live-term__side .orderflow-card,
.live-term__side .liq-sidebar{
  background:var(--panel);
  border-bottom:1px solid var(--line);
}
.live-term__side .orderflow-card .widget-card__head,
.live-term__side .liq-sidebar .widget-card__head{ opacity:.85; }

/* ---- LOW: Market Pulse, Whales, Market Overview/Statistics ---- */
.live-term__side .pulseflow-card,
.live-term__side .whale-card,
.live-term__side .mktoverview-card{
  background:transparent;
  border-bottom:1px solid var(--line-soft);
}
.live-term__side .pulseflow-card .widget-card__head,
.live-term__side .whale-card .widget-card__head,
.live-term__side .mktoverview-card .widget-card__head{ opacity:.65; }

/* Drag-reordering swaps a card's position in the DOM, not which panel
   it represents — keep the tier rules keyed to the panel classes above
   (unaffected by order) rather than nth-child, so re-ordering a widget
   never silently changes its priority tier. */
