* { box-sizing: border-box; }

/* Scrollbars, drawn by us on every platform.
   `color-scheme: dark` (tokens.css) already stops them being white, but the
   width and the chrome around them still differ per OS, so the bar itself is
   spelled out: a thin thumb on no track at all. The standard properties cover
   Firefox and current Chromium; the ::-webkit- rules cover everything older,
   and both say the same thing. */
* { scrollbar-width: thin; scrollbar-color: var(--scroll-thumb) transparent; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track, ::-webkit-scrollbar-corner { background: transparent; }
::-webkit-scrollbar-thumb {
  /* The transparent border is the padding: it keeps the visible thumb narrow
     while the grab area stays the full ten pixels. */
  background: var(--scroll-thumb); background-clip: padding-box;
  border: 2px solid transparent; border-radius: 6px;
}
::-webkit-scrollbar-thumb:hover { background: var(--scroll-thumb-hover); background-clip: padding-box; }

html { background: var(--ground); }
body {
  margin: 0; background: var(--ground); color: var(--ink);
  font-family: var(--mono); font-size: 12px; font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased; padding: 0 18px 28px;
}
a { color: var(--info); text-decoration: none; }
:focus-visible { outline: 2px solid var(--info); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { * { transition: none !important; } }
[hidden] { display: none !important; }

.lbl { font-size: 10px; letter-spacing: 1.2px; color: var(--ink-3); text-transform: uppercase; }
.num { text-align: right; }
.pos { color: var(--pos); } .neg { color: var(--neg); } .warn { color: var(--warn); } .info { color: var(--info); }
.muted { color: var(--ink-2); } .faint { color: var(--ink-3); }
.ell { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.panel {
  position: relative;
  background: var(--panel); border: 1px solid var(--rule); border-radius: 4px;
  box-shadow: 0 1px 0 rgba(255,255,255,.02); min-width: 0;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.panel:hover { border-color: var(--rule-strong); }
.btn {
  padding: 6px 12px; border: 1px solid var(--rule-strong); border-radius: 2px; background: none;
  color: var(--ink-2); font: inherit; letter-spacing: .8px; cursor: pointer; white-space: nowrap;
}
.btn:hover { color: var(--ink); border-color: var(--ink-3); }
.btn-sm { padding: 3px 9px; font-size: 11px; }
.btn-pos { border-color: var(--pos); color: var(--pos); }
.btn-pos:hover { background: var(--pos-dim); border-color: var(--pos); color: var(--ink); }
.chip {
  padding: 4px 10px; border: 1px solid var(--rule); border-radius: 2px; color: var(--ink-3);
  letter-spacing: .6px; background: none; font: inherit; cursor: pointer;
}
.chip:hover { border-color: var(--rule-strong); color: var(--ink); }
.chip[aria-pressed="true"] { border-color: var(--rule-strong); color: var(--ink); background: var(--raised); }
.dot { width: 6px; height: 6px; border-radius: 50%; display: inline-block; }
input, select {
  background: var(--ground); border: 1px solid var(--rule); border-radius: 2px; color: var(--ink);
  font: inherit; padding: 3px 7px;
}
input:focus, select:focus { outline: none; border-color: var(--rule-strong); }

/* ───── sticky header + tabs ───── */
.sticky-top { position: sticky; top: 0; z-index: 40; background: var(--ground); padding-top: 8px; }
.strip { display: flex; align-items: stretch; border: 1px solid var(--rule); background: var(--panel); border-radius: 3px; }
.strip-brand { display: flex; align-items: center; gap: 8px; padding: 6px 14px; border-right: 1px solid var(--rule); }
.strip-brand a { display: contents; color: inherit; text-decoration: none; }
.brand-name { font-weight: 700; letter-spacing: 1.6px; }
.strip-ops { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 14px; padding: 6px 14px; flex: 1; min-width: 0; }
.strip-ops .state { display: flex; align-items: center; gap: 6px; }
.tabs { display: flex; align-items: center; border-bottom: 1px solid var(--rule); margin-top: var(--gap); overflow-x: auto; }
main { padding-top: var(--gap); }
.empty { padding: 16px; color: var(--ink-3); }

/* ───── paid tier ───── */
/* A locked block keeps its place in every list and says what it is; the data
   itself is gated server-side, so none of this is the lock. */
.pro-gate { padding: 16px; display: flex; flex-direction: column; gap: 8px; }
.pro-gate-title { font-size: 12px; }
.pro-gate-about, .pro-gate-how { font-size: 11px; line-height: 1.45; max-width: 46em; }
.block-menu-item.is-locked > span:first-child { color: var(--ink-2); }

/* ───── toasts ───── */
.toasts { position: fixed; right: 16px; bottom: 16px; z-index: 90; display: flex; flex-direction: column; gap: 8px; align-items: flex-end; }
.toast { background: var(--panel); border: 1px solid var(--rule-strong); border-left: 2px solid var(--info); border-radius: 2px; padding: 9px 14px; font-size: 11px; max-width: 380px; }
.toast.t-pos { border-left-color: var(--pos); } .toast.t-neg { border-left-color: var(--neg); } .toast.t-warn { border-left-color: var(--warn); }
.toast.t-alert { border-left-color: var(--warn); white-space: pre-line; }

/* ───── alert banner ───── */
.alert-banner {
  position: fixed; top: 14px; left: 50%; transform: translateX(-50%); z-index: 100;
  display: flex; align-items: center; gap: 14px; background: var(--panel);
  border: 1px solid var(--rule-strong); border-left: 3px solid var(--pos);
  border-radius: 3px; padding: 8px 14px; font-size: 11px;
  box-shadow: 0 4px 20px rgba(0, 0, 0, .6); max-width: calc(100vw - 32px);
  animation: banner-drop .15s ease-out;
}
@keyframes banner-drop {
  from { opacity: 0; transform: translate(-50%, -8px); }
  to { opacity: 1; transform: translate(-50%, 0); }
}
.al-banner-head { display: flex; align-items: center; gap: 6px; }
.al-banner-icon { font-size: 13px; line-height: 1; }
.al-banner-content { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.al-banner-desc { color: var(--ink); font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 480px; }
.al-banner-hint { font-size: 10px; }
.al-banner-actions { display: flex; align-items: center; gap: 8px; margin-left: auto; flex-shrink: 0; }

/* ───── the desk ───── */
/* The desk is exactly as tall as the window leaves room for. `min-height`
   alone was a floor, not a ceiling: a block with more rows than fit stretched
   its panel — and with it the whole desk — down the page, instead of scrolling
   inside its own body. A block may fill the desk; it may not grow past it. */
.workspace { display: flex; align-items: stretch; width: 100%; height: var(--deck-viewport-h); overflow: auto; }
/* One per desk. The inactive ones stay in the DOM, mounted and live, so that
   switching back is a rebuild of boxes rather than of every data source. */
.ws-desk { display: flex; align-items: stretch; flex: 1 1 0; min-width: 0; }
.ws-split { display: flex; min-width: 0; }
.ws-row { flex-direction: row; align-items: stretch; }
.ws-col { flex-direction: column; align-items: stretch; min-width: 0; }
.ws-row > [data-panel], .ws-row > .ws-split { min-width: 0; }
[data-panel] {
  position: relative; display: flex; flex-direction: column; min-height: 120px;
  overflow: hidden;
}
[data-panel].context-hover { outline: 1px solid var(--info-dim); outline-offset: -1px; }
.panel-head {
  position: relative; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; min-height: 34px;
  padding: 6px 42px 6px 10px; border-bottom: 1px solid var(--rule); background: var(--raised);
}
.block-sym-host { display: inline-flex; align-items: center; }
.block-sym { border: 0; background: none; color: var(--ink); font: inherit; font-size: 10px; letter-spacing: .8px; padding: 2px 4px; border-radius: 2px; cursor: text; }
.block-sym:hover:not(:disabled) { background: var(--raised); }
.block-sym:disabled { color: var(--ink-2); cursor: default; }
.block-sym-input { background: var(--raised); border: 1px solid var(--info); border-radius: 2px; color: var(--ink); font: inherit; font-size: 10px; letter-spacing: .8px; padding: 1px 4px; }
/* The channel link sits where the focus box used to: same size as the ⌘K
   button beside it, so the strip keeps one rhythm. */
.tg-link { text-decoration: none; letter-spacing: .3px; white-space: nowrap; }
.tg-link:hover { border-color: var(--info); color: var(--info); }

.block-title.has-about { cursor: help; text-decoration: underline dotted color-mix(in srgb, var(--ink-3) 60%, transparent); text-underline-offset: 3px; }
/* What the block is, drawn by us: the native tooltip waits a second, vanishes
   on its own and loses the line break. */
.block-about {
  position: fixed; z-index: 90; max-width: min(380px, calc(100vw - 16px));
  padding: 7px 9px; border: 1px solid var(--rule-strong); border-radius: 3px;
  background: var(--panel); box-shadow: 0 12px 32px rgba(0,0,0,.55);
  color: var(--ink-2); font-size: 10.5px; line-height: 1.45; pointer-events: none;
}
.block-about div + div { margin-top: 4px; }
/* Any `data-tip`, drawn the same way (core/tip.js). */
.tip-card {
  position: fixed; z-index: 95; max-width: min(460px, calc(100vw - 16px));
  padding: 6px 9px; border: 1px solid var(--rule-strong); border-radius: 3px;
  background: var(--panel); box-shadow: 0 12px 32px rgba(0,0,0,.55);
  color: var(--ink); font-size: 10.5px; line-height: 1.45; white-space: pre-wrap; pointer-events: none;
}
.block-about-name { color: var(--ink); font-size: 10px; letter-spacing: 1px; text-transform: uppercase; }
.panel-head .grip { cursor: grab; color: var(--rule-strong); letter-spacing: -1px; padding: 0 2px; user-select: none; order: -1; }
.panel-head .grip:hover { color: var(--ink-2); }
.panel-head .grip:active { cursor: grabbing; }
.block-params { display: flex; gap: 6px; align-items: center; }
.block-params input, .block-params select { padding: 2px 6px; font-size: 11px; }
.block-params .follow { padding: 1px 6px; font-size: 11px; }
.block-context-links { display: inline-flex; align-items: center; gap: 3px; }
/* A token link carries the coin and nothing else, so pointing it elsewhere
   leaves every block on its own exchange — a market link moves the exchange
   too. The two were one chip with one number; the dotted underline is the
   shortest honest difference in a header this narrow. */
.context-link-trigger.is-token { text-decoration: underline dotted; text-underline-offset: 2px; }
.context-link-trigger.is-local { min-width: 0; color: var(--ink-3); }
.context-link-trigger.is-local:hover { color: var(--info); }
.context-link-trigger {
  min-width: 43px; padding: 2px 5px; border: 1px solid var(--rule); border-radius: 2px;
  background: none; color: var(--info); font: inherit; font-size: 9px; letter-spacing: .4px;
  cursor: pointer; white-space: nowrap;
}
.context-link-trigger:hover, .context-link-trigger[aria-expanded="true"], .context-link-trigger.context-hover { border-color: var(--info); color: var(--ink); background: var(--raised); }
.context-link-swap { min-width: 28px; padding: 2px 4px; border: 1px solid var(--rule); border-radius: 2px; background: none; color: var(--warn); font: inherit; font-size: 12px; cursor: pointer; }
.context-link-swap:hover, .context-link-swap:focus-visible { border-color: var(--warn); color: var(--ink); background: var(--raised); outline: none; }
.context-menu {
  position: fixed; z-index: 78; width: min(280px, calc(100vw - 16px)); max-height: min(520px, calc(100vh - 24px));
  overflow-y: auto; padding: 7px; border: 1px solid var(--rule-strong); border-radius: 3px;
  background: var(--panel); box-shadow: 0 16px 48px rgba(0,0,0,.58); color: var(--ink-2); font-size: 11px;
}
.context-menu-title { padding: 3px 5px 7px; color: var(--ink); font-size: 10px; letter-spacing: 1px; text-transform: uppercase; }
.context-menu-channels { display: flex; flex-direction: column; gap: 2px; }
.context-menu-option {
  display: flex; width: 100%; padding: 6px 7px; border: 1px solid transparent; border-radius: 2px;
  background: none; color: var(--ink-2); font: inherit; text-align: left; cursor: pointer;
}
.context-menu-option:hover, .context-menu-option:focus-visible, .context-menu-option.active { border-color: var(--info-dim); background: var(--raised); color: var(--ink); outline: none; }
.context-menu-new { margin-top: 3px; border-top: 1px solid var(--rule); border-radius: 0; color: var(--pos); }
.context-menu-manual { display: flex; gap: 5px; margin: 7px 0; padding-top: 7px; border-top: 1px solid var(--rule); }
.context-menu-channel-input, .context-menu-scope, .context-menu-token, .context-menu-mode { width: 100%; min-width: 0; padding: 4px 5px; font: inherit; font-size: 10px; }
.context-menu-channel-input { flex: 1; }
.context-menu-manual .chip { white-space: nowrap; }
.context-menu-hint { padding: 8px 5px 3px; color: var(--ink-3); font-size: 10px; }
.context-menu-scope, .context-menu-token { display: block; margin: 6px 0; }
.context-menu-scope-label { margin: 7px 0; padding: 5px 6px; border: 1px solid var(--rule); color: var(--ink-2); font-size: 10px; }
.context-menu-advanced { margin: 7px 0; border-top: 1px solid var(--rule); padding-top: 5px; }
.context-menu-advanced-label { color: var(--ink-3); font-size: 10px; }
.context-menu-mode-hint { margin-top: 4px; color: var(--ink-3); font-size: 10px; line-height: 1.35; }
.context-menu-mode { margin-top: 6px; }
.context-menu-apply { width: 100%; color: var(--info); }
.block-status { margin-left: auto; font-size: 10px; }
.block-tools { display: inline-flex; align-items: center; gap: 6px; }
.block-tools .chip { white-space: nowrap; }
.block-tools:empty { display: none; }
.block-close { order: 99; position: absolute; top: 5px; right: 8px; z-index: 1; padding: 2px 8px; }
.panel-body { flex: 1 1 auto; min-height: 0; overflow: auto; padding: 8px 10px; }
.notes-text { width: 100%; height: 100%; min-height: 90px; resize: none; border: 0; background: transparent; color: var(--ink); font: inherit; line-height: 1.5; }
.notes-text:focus { outline: none; }
[data-panel].dragging { opacity: .4; }
/* Where the dragged block will land. A fixed overlay above every panel: an
   inset border on the target is hidden by the panel head and by the root-drop
   strips, which is precisely where a drop hint has to be readable. */
.ws-drop-preview {
  position: fixed; z-index: 72; pointer-events: none;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--pos); border-radius: 3px;
  background: color-mix(in srgb, var(--pos) 13%, transparent);
  font-size: 10px; letter-spacing: 1.4px; text-transform: uppercase; color: var(--pos);
  transition: left .07s ease, top .07s ease, width .07s ease, height .07s ease;
}
.ws-drop-preview.drop-above { border-top-width: 3px; }
.ws-drop-preview.drop-below { border-bottom-width: 3px; }
.ws-drop-preview.drop-left { border-left-width: 3px; }
.ws-drop-preview.drop-right { border-right-width: 3px; }
.ws-drop-preview.drop-root { border-width: 2px; border-style: dashed; }
.ws-gap { flex: 0 0 var(--gap); align-self: stretch; position: relative; touch-action: none; z-index: 2; }
.ws-gap-row { min-width: var(--gap); cursor: col-resize; }
.ws-gap-col { min-height: var(--gap); cursor: row-resize; }
.ws-gap::before { content: ''; position: absolute; background: var(--rule); }
.ws-gap-row::before { top: 0; bottom: 0; left: 50%; width: 1px; transform: translateX(-50%); }
.ws-gap-col::before { left: 0; right: 0; top: 50%; height: 1px; transform: translateY(-50%); }
.ws-gap:hover::before { background: var(--pos); width: 3px; }
.ws-gap-col:hover::before { width: auto; height: 3px; }
body.resizing { user-select: none; cursor: col-resize; }
body.resizing-row { user-select: none; cursor: row-resize; }
.ws-edges { position: fixed; inset: 0; z-index: 70; pointer-events: none; }
/* Root-drop strips live in the page margins, not over the desk: at 54px tall
   and inset 12px the bottom one sat on top of the bottom row's own drop zone,
   so a block could never be attached below the panel it covered. */
.ws-edge {
  position: absolute; left: 0; right: 0; height: 26px; pointer-events: auto;
  display: flex; align-items: center; justify-content: center;
  border: 1px dashed var(--rule-strong); border-radius: 3px; background: rgba(13,15,19,.96);
  font-size: 10px; letter-spacing: 1.2px; text-transform: uppercase; color: var(--ink-3);
}
.ws-edge[data-edge="top"] { top: 0; } .ws-edge[data-edge="bottom"] { bottom: 1px; }
.ws-edge.edge-armed { border-color: var(--pos); border-style: solid; color: var(--pos); background: color-mix(in srgb, var(--pos) 16%, rgba(13,15,19,.96)); }
.desk-tabs { display: flex; align-items: stretch; gap: 4px; padding: 0 6px 0 14px; }
.desk-menu-sym { width: 100%; margin: 2px 0 6px; font-size: 11px; }
/* A saved template sits on one row with its rename/delete buttons, so the
   name stays clickable and the two small actions never eat the click. */
.desk-menu-row { display: flex; align-items: stretch; gap: 2px; }
.desk-menu-row .desk-menu-item { flex: 1 1 auto; min-width: 0; }
.desk-menu-act {
  flex: 0 0 auto; width: 22px; border: 0; border-radius: 2px; background: none;
  color: var(--ink-3); font: inherit; font-size: 11px; cursor: pointer;
}
.desk-menu-act:hover { background: var(--raised); color: var(--ink); }
.desk-menu-mine:empty { display: none; }
.desk-tab { display: flex; align-items: center; border-bottom: 2px solid transparent; margin-bottom: -1px; }
.desk-tab.active { border-bottom-color: var(--pos); }
.desk-name { background: none; border: 0; font: inherit; letter-spacing: 1.1px; color: var(--ink-3); cursor: pointer; padding: 9px 9px 9px 2px; text-transform: uppercase; white-space: nowrap; }
.desk-tab.active .desk-name { color: var(--ink); font-weight: 700; }
.desk-close { flex: 0 0 auto; width: 20px; background: none; border: 0; font: inherit; font-size: 10px; color: var(--rule-strong); cursor: pointer; padding: 9px 0; text-align: center; }
.desk-close:hover { color: var(--neg); }
.desk-add { background: none; border: 1px solid var(--rule); border-radius: 2px; color: var(--ink-3); font: inherit; cursor: pointer; padding: 2px 9px; align-self: center; margin-left: 4px; }
.desk-add:hover { border-color: var(--pos); color: var(--pos); }
.palette-blocks { position: relative; display: flex; align-items: center; gap: 5px; margin-left: auto; padding: 0 10px; }
/* Quick add: the blocks this browser uses most, left of the group menus and
   separated from them so the two kinds of button do not read as one row. */
.block-menu-trigger {
  display: inline-flex; align-items: center; gap: 5px; flex: 0 0 auto; padding: 4px 8px; border: 1px solid var(--rule);
  border-radius: 2px; background: none; color: var(--ink-2); font: inherit; font-size: 10px;
  letter-spacing: .8px; cursor: pointer; white-space: nowrap;
}
.block-menu-trigger:hover, .block-menu-trigger[aria-expanded="true"] { border-color: var(--pos); color: var(--ink); background: var(--raised); }
.block-menu-caret { margin-left: 2px; color: var(--ink-3); font-size: 11px; transition: transform .15s ease; }
.block-menu-trigger[aria-expanded="true"] .block-menu-caret { transform: rotate(180deg); }
.block-menu {
  position: fixed; z-index: 75; width: min(284px, calc(100vw - 16px)); max-height: min(520px, calc(100vh - 80px));
  overflow-y: auto; padding: 5px; border: 1px solid var(--rule-strong); border-radius: 3px;
  background: var(--panel); box-shadow: 0 16px 48px rgba(0,0,0,.58);
}
.block-menu-group + .block-menu-group { border-top: 1px solid var(--rule); margin-top: 5px; padding-top: 5px; }
.block-menu-label { padding: 5px 9px 4px; color: var(--ink-3); font-size: 9px; font-weight: 700; letter-spacing: 1.2px; text-transform: uppercase; }
/* Is this block still being fed? Green while data arrives at the block's own
   rhythm, amber when it has gone quiet for three of its own beats. Hidden
   entirely for blocks with no feed — Notes, the catalogue — because a dot
   there would report health nobody measured. */
.block-pulse {
  width: 6px; height: 6px; border-radius: 50%; flex: 0 0 auto;
  background: var(--pos); margin: 0 2px;
  transition: background .3s ease;
}
.block-pulse.is-stale { background: var(--warn); }
@media (prefers-reduced-motion: reduce) { .block-pulse { transition: none; } }

.block-menu-item {
  display: flex; align-items: center; gap: 10px; width: 100%; padding: 7px 9px; border: 0;
  border-left: 2px solid transparent; border-radius: 1px; background: none; color: var(--ink-2);
  font: inherit; text-align: left; cursor: pointer;
}
.block-menu-item:hover, .block-menu-item:focus-visible { background: var(--raised); border-left-color: var(--pos); color: var(--ink); outline: 0; }
.block-menu-hint { margin-left: auto; color: var(--ink-3); font-size: 9px; }
/* Between the phone breakpoint and a full desk the header row is the tight
   one: the tabs wrap and the workspace stacks. */
@media (max-width: 760px) {
  .tabs { flex-wrap: wrap; overflow-x: visible; }
  .workspace, .ws-split { flex-direction: column; }
  /* Stacked on a phone the blocks are meant to run past the fold. */
  .workspace { height: auto; min-height: var(--deck-viewport-h); overflow: visible; }
  .ws-split { gap: var(--gap); min-width: 0 !important; min-height: 0 !important; }
  .ws-split > [data-panel], .ws-split > .ws-split, .workspace > [data-panel], .workspace > .ws-split {
    flex: 0 0 auto !important; width: 100%; min-width: 0 !important;
  }
  [data-panel] { min-width: 0 !important; }
  .ws-gap { display: none; }
  .palette-blocks { flex-basis: 100%; justify-content: flex-end; margin-left: 0; padding: 4px 6px; border-top: 1px solid var(--rule); }
}

/* A funding rate the hub did not collect, filled from the aggregator. Small
   and quiet, but never absent: second-hand must not look first-hand. */
.fx-src { margin-left: 5px; padding: 0 3px; border: 1px solid var(--rule-strong); border-radius: 2px; color: var(--ink-3); font-size: 9px; cursor: help; }
/* A row priced in something other than what was asked for. */
.fx-src.warn { border-color: var(--warn); color: var(--warn); }

/* A venue row that can be carried into the Watchlist, and the Watchlist while
   something is being carried over it. */
/* Token watch: one token across every venue we can price. */
.tw-head { display: flex; align-items: baseline; gap: 10px; padding: 0 0 6px; }

.tbl tr.is-focus td { background: color-mix(in srgb, var(--info) 14%, transparent); }
.wl-drop-cell { width: 18px; padding-left: 0 !important; padding-right: 4px !important; text-align: right; }
.wl-x { border: 0; background: none; color: var(--ink-3); font: inherit; font-size: 10px; line-height: 1; padding: 2px; cursor: pointer; opacity: 0; transition: opacity .12s ease; }
.tbl tr:hover .wl-x, .wl-x:focus-visible { opacity: 1; }
/* The exchange's own page for a row's market, left of the name. Faint until
   the row is under the pointer rather than hidden: it holds its place either
   way, and an empty gap before every name reads as a misaligned column. */
.venue-go { margin-right: 5px; color: var(--ink-3); text-decoration: none; font-size: 11px; opacity: .35; transition: opacity .12s ease; }
.venue-go:hover { color: var(--info); }
.tbl tr:hover .venue-go, .venue-go:focus-visible { opacity: 1; }
@media (hover: none) { .venue-go { opacity: 1; } }
.wl-x:hover { color: var(--neg); }
/* `user-select: none` is not cosmetic here. The chip is a <button>, and on
   Linux Chromium a press-and-move over its label starts a TEXT SELECTION
   instead of a drag, so the group cannot be carried at all — reported from
   Vivaldi on Linux while the same build dragged fine on macOS, where buttons
   are not selectable to begin with. `.drag-venue` has had the rule since it
   was written, which is why rows drag on both. */
/* `-webkit-user-drag: none`: the chip is carried by pointer on every platform,
   and WebKit would otherwise still start a native drag of its own on macOS —
   two gestures racing for the same press. */
.drag-link { cursor: grab; user-select: none; -webkit-user-select: none; -webkit-user-drag: none; }
.drag-link * { user-select: none; -webkit-user-select: none; }

/* The chip while it is being carried by pointer, where the browser refuses to
   start a real drag and so draws no image of its own. */
.link-carry-ghost {
  position: fixed; z-index: 90; transform: translate(10px, 10px); pointer-events: none;
  padding: 2px 6px; border: 1px solid var(--info); border-radius: 2px;
  background: var(--panel); color: var(--ink);
  font: inherit; font-size: 9px; letter-spacing: .4px; white-space: nowrap;
  box-shadow: 0 4px 14px rgba(0,0,0,.5);
}
.drag-link:active { cursor: grabbing; }
/* Which port a carried group would land on, drawn over the target panel. */
.link-drop-zone {
  position: absolute; top: 0; bottom: 0; z-index: 6; pointer-events: none;
  display: flex; align-items: center; justify-content: center;
  border: 1px dashed var(--info); border-radius: 3px;
  background: color-mix(in srgb, var(--info) 14%, transparent);
}
.link-drop-zone span {
  padding: 4px 9px; border: 1px solid var(--info); border-radius: 3px;
  background: var(--panel); box-shadow: 0 4px 14px rgba(0,0,0,.5);
  color: var(--ink); font-size: 11px; letter-spacing: .8px; text-transform: uppercase; white-space: nowrap;
}

.drag-venue { cursor: grab; user-select: none; -webkit-user-drag: element; }
.drag-venue * { user-select: none; }
.drag-venue:active { cursor: grabbing; }
.panel-body.drop-market { position: relative; outline: 1px dashed var(--pos); outline-offset: -3px; background: color-mix(in srgb, var(--pos) 6%, transparent); }
/* The Spread chart has two places to put a market, so it shows both and lights
   the one the pointer is over. */
.sc-drop { position: absolute; inset: 0; z-index: 5; display: flex; pointer-events: none; }
.sc-drop-half { flex: 1 1 50%; display: flex; align-items: center; justify-content: center; border: 1px dashed var(--rule-strong); color: var(--ink-3); font-size: 11px; letter-spacing: .08em; text-transform: uppercase; }
.sc-drop-half.is-active { border-color: var(--pos); color: var(--ink); background: color-mix(in srgb, var(--pos) 12%, transparent); }

/* ───── ⌘K palette ───── */
.overlay { position: fixed; inset: 0; z-index: 80; background: rgba(0,0,0,.55); display: flex; align-items: flex-start; justify-content: center; padding-top: 12vh; }
.palette-box { width: 100%; max-width: 620px; background: var(--panel); border: 1px solid var(--rule-strong); border-radius: 3px; box-shadow: 0 18px 60px rgba(0,0,0,.6); display: flex; flex-direction: column; max-height: 76vh; }
.palette-box > input { background: none; border: 0; border-bottom: 1px solid var(--rule); color: var(--ink); font: inherit; font-size: 14px; padding: 13px 16px; }
.palette-box > input:focus { outline: none; }
.palette-list { overflow-y: auto; }
.pal-item { display: flex; align-items: center; gap: 10px; width: 100%; padding: 8px 16px; border: 0; border-left: 2px solid transparent; background: none; color: var(--ink-2); font: inherit; text-align: left; cursor: pointer; }
.pal-item .pal-kind { font-size: 10px; color: var(--ink-3); letter-spacing: 1px; width: 62px; flex: 0 0 auto; }
.pal-item .pal-hint { margin-left: auto; font-size: 10px; color: var(--ink-3); }
.pal-item[aria-selected="true"] { background: var(--raised); color: var(--ink); border-left-color: var(--pos); }
.pal-empty { padding: 16px; color: var(--ink-3); }

/* ───── screener table ───── */
.tbl-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 4px; }
/* The screener's own search box: it filters in place, so it sits in the table
   head rather than among the block params, which remount on change. */
.tbl-q { width: 88px; padding: 1px 5px; font-size: 10.5px; background: var(--raised); border: 1px solid var(--rule); border-radius: 2px; color: var(--ink); }
.tbl-q::placeholder { color: var(--ink-3); }
/* The column everything is read by — sorted on, filtered by, grouped on. */
.tbl th.is-window { color: var(--ink); }
.tbl td.is-window { font-weight: 600; }
.tbl-chips { display: flex; gap: 5px; flex-wrap: wrap; margin-bottom: 6px; }
.tbl-chips .chip { font-size: 10px; padding: 2px 7px; cursor: default; }
.tbl-wrap { overflow: auto; }
.tbl { border-collapse: collapse; width: 100%; font-size: 11.5px; }
.tbl th { text-align: left; font-size: 9.5px; letter-spacing: 1px; text-transform: uppercase; color: var(--ink-3); font-weight: 500; padding: 4px 8px; border-bottom: 1px solid var(--rule-strong); white-space: nowrap; position: sticky; top: 0; background: var(--panel); }
.tbl th.num { text-align: right; }
.tbl td { padding: 3px 8px; border-bottom: 1px solid var(--rule-soft); white-space: nowrap; }
.tbl tr:hover td { background: var(--raised); }
.tbl tr.is-focus td { background: var(--raised); box-shadow: inset 2px 0 0 var(--pos); }

/* Open interest: the change columns, and the movers table. */
.oi-note { padding: 4px 10px; font-size: 10.5px; }
.oi-note:empty { display: none; }
.oi-tbl td, .oi-movers td { font-variant-numeric: tabular-nums; }
/* The column the table is ranked by, so the order is never a mystery. */
.tbl th.is-sorted { color: var(--ink); border-bottom-color: var(--info); }
/* A header that sorts is a control, and has to look like one — but a table
   head is not a place for a button's chrome. */
.tbl th > .th-sort { background: none; border: 0; padding: 0; margin: 0; font: inherit; color: inherit; letter-spacing: inherit; text-transform: inherit; cursor: pointer; }
.tbl th > .th-sort:hover { color: var(--ink); }
.tbl th.num > .th-sort { width: 100%; text-align: right; }
.oi-movers td.is-sorted { box-shadow: inset 0 -1px 0 color-mix(in srgb, var(--info) 45%, transparent); }
.oi-mover-row { cursor: pointer; }
.oi-mover-row.is-picked td { background: color-mix(in srgb, var(--info) 12%, transparent); }
.oi-coin { font-weight: 600; letter-spacing: .3px; }

/* The dividend calendar. Its whole point is that a date two days out reads
   differently from one next month, so the countdown is the coloured column —
   not the size, which every other ranking already colours. */
.dividends td { font-variant-numeric: tabular-nums; }
.div-coin { font-weight: 600; letter-spacing: .3px; }
.div-row { cursor: pointer; }
.div-venues { font-size: 10.5px; letter-spacing: .2px; }
.div-soon { color: var(--warn); font-weight: 600; }
.div-near { color: var(--ink-2); }
.div-far, .div-past { color: var(--ink-3); }
.div-note { padding: 4px 10px; font-size: 10.5px; }
.div-note:empty { display: none; }
.div-row.is-picked td { background: color-mix(in srgb, var(--info) 12%, transparent); }

/* carry: curve against funding */
.carry-hint { padding: 4px 10px 6px; font-size: 10.5px; }
.carry-coin { font-weight: 600; letter-spacing: .3px; }
.carry-contract { font-size: 10px; }

/* delistings */
.delist-hint { padding: 4px 10px 6px; font-size: 10.5px; }
.delist-note { padding: 3px 10px 6px; font-size: 10.5px; }
.delist-tools { display: flex; align-items: center; gap: 10px; padding: 4px 10px 2px; font-size: 10.5px; }
.delist-min-label { display: inline-flex; align-items: center; gap: 4px; }
.delist-min { width: 46px; }
.delist-coin { font-weight: 600; letter-spacing: .3px; }
.delist-row.is-title { opacity: .7; }
.delist-row.is-done { opacity: .55; }
.delist-row.is-window { background: rgba(255, 170, 60, .07); }
.delist-cd { font-size: 10.5px; }
.delist-state { display: inline-block; padding: 0 6px; border-radius: 9px; font-size: 10px; letter-spacing: .3px; border: 1px solid rgba(128, 128, 128, .35); }
.delist-state.is-window { border-color: rgba(255, 170, 60, .8); color: #ffb347; }
.delist-state.is-closeOnly { border-color: rgba(255, 220, 120, .6); }
.delist-state.is-done, .delist-state.is-unknown { opacity: .6; }
.delist-dev.warm { color: #ffb347; font-weight: 600; }
.delist-dev.strong { color: #ff6b6b; font-weight: 700; }
.delist-devs { white-space: nowrap; }
.delist-spread.warm, .delist-hist td.warm { color: #ffb347; }
.delist-spread.strong, .delist-hist td.strong { color: #ff6b6b; font-weight: 600; }
.delist-hist .delist-row.is-live .delist-coin::after { content: ' •'; color: #ffb347; }
.delist-link a { text-decoration: none; opacity: .7; }
.delist-link a:hover { opacity: 1; }
.carry-row { cursor: pointer; }
.carry-row.is-picked td { background: color-mix(in srgb, var(--info) 12%, transparent); }
.carry-soon { color: var(--warn); font-weight: 600; }
.carry-near { color: var(--ink); }
/* The table shrinks with its panel: no column pins a width beyond its own
   content, so a second block beside this one takes room rather than
   pushing the table into a sideways scroll. */
.tbl.carry { table-layout: auto; }
.tbl.carry td, .tbl.carry th { padding-left: 6px; padding-right: 6px; white-space: normal; }
.tbl.carry td.num { white-space: nowrap; }
.tbl.carry th { white-space: normal; line-height: 1.25; }
.carry-venue.is-unknown { color: var(--ink-3); }
.carry-venue.is-stale b { opacity: .55; }
.carry-legs { font-size: 10.5px; letter-spacing: .2px; }
.carry-dev { font-size: 10px; }
/* A roll under way is a different kind of row: tinted, striped, with a
   progress bar for how much of the volume has moved. */
.carry-row.is-rolling td { background: color-mix(in srgb, var(--warn) 6%, transparent); }
.carry-row.is-rolling td:first-child { box-shadow: inset 2px 0 0 var(--warn); }
.carry-row.is-rolling:hover td { background: color-mix(in srgb, var(--warn) 11%, transparent); }
.carry-live { color: var(--warn); font-weight: 600; }
.carry-rollnow { display: block; font-size: 9.5px; letter-spacing: .3px; text-transform: uppercase; color: var(--warn); font-weight: 500; }
.carry-bar { height: 3px; min-width: 72px; margin: 3px 0 2px auto; background: var(--rule); border-radius: 2px; overflow: hidden; }
.carry-bar i { display: block; height: 100%; background: var(--warn); }
.carry-progress { display: block; font-size: 10px; font-weight: 500; white-space: nowrap; }
/* The roll at the venues: a head line and one line per venue with a bar of
   how far its index has moved into the next contract. */
.tbl td.carry-vroll { white-space: normal; min-width: 150px; vertical-align: top; }
.carry-vroll-head { display: block; font-size: 9.5px; letter-spacing: .3px; text-transform: uppercase; font-weight: 500; margin-bottom: 2px; white-space: normal; }
.carry-vlist { display: flex; flex-direction: column; gap: 1px; }
.carry-vline { display: flex; align-items: center; flex-wrap: wrap; gap: 2px 5px; font-size: 10px; line-height: 1.35; white-space: normal; }
.carry-vline.is-unknown { color: var(--ink-3); }
.carry-vline.is-step .carry-vname { color: var(--warn); font-weight: 600; }
.carry-vname { min-width: 58px; }
.carry-vbar { display: inline-block; width: 44px; height: 4px; background: var(--rule); border-radius: 2px; overflow: hidden; }
.carry-vbar i { display: block; height: 100%; background: var(--warn); }
.carry-vstep { color: var(--ink-2); }
.carry-vmark { font-size: 10px; }
.carry-igap span { display: block; }
/* The «минулий рол» view: a cell a day. */
.tbl.carry-prev td.carry-days { white-space: normal; }
.carry-day { display: inline-block; margin: 0 8px 1px 0; font-size: 10.5px; white-space: nowrap; }
.carry-contracts { font-weight: 600; letter-spacing: .3px; }
.tbl.carry-prev td.carry-fund { white-space: normal; max-width: 520px; line-height: 1.5; }
.carry-fchip { display: inline-block; vertical-align: top; margin: 0 10px 3px 0; font-size: 10.5px; white-space: nowrap; }
.carry-fchip .carry-vname { min-width: 0; }
.carry-fline { display: block; line-height: 1.3; }
.carry-fverdict { font-size: 9.5px; letter-spacing: .2px; }
.carry-fchip.is-over { border-left: 2px solid var(--pos); padding-left: 5px; }
.carry-fchip.is-under { border-left: 2px solid var(--neg); padding-left: 5px; }
.carry-fchip.is-even { border-left: 2px solid var(--rule-strong); padding-left: 5px; }
.carry-row.is-norule td { color: var(--ink-3); }
.carry-measured { font-size: 10px; }
.carry-roll { display: block; font-size: 9.5px; letter-spacing: .3px; text-transform: uppercase; white-space: nowrap; }
.carry-months { font-size: 10px; }
.carry-note { padding: 4px 10px; font-size: 10.5px; }
.carry-note:empty { display: none; }

/* Токени на біржах. Колонка з адресами — не довідка, а міра довіри до рядка,
   тож вона підсвічується, коли рядок тримається на одній-двох адресах. */
.holders td { font-variant-numeric: tabular-nums; }
.hold-cex { font-weight: 600; letter-spacing: .3px; }
.hold-input { padding: 6px 10px 2px; }
.hold-addr { width: 100%; font-size: 11px; font-family: var(--mono); }
.hold-thin { color: var(--neg); }
.hold-partial { color: var(--warn); }
/* Рядок, що спирається на нашу власну адресу, а не на джерело — щоб хибну
   мітку можна було простежити до того, хто її додав. */
.hold-ours .hold-cex { text-decoration: underline dotted; text-underline-offset: 3px; }
.hold-note { padding: 6px 10px 8px; font-size: 10.5px; line-height: 1.4; }
.hold-note:empty { display: none; }

/* DEX vs spot. A row that carries no price is dimmed rather than hidden: the
   reason it has none is the most useful thing on the table when a coin has
   quietly stopped being reachable. */
.dexgap-note { padding: 6px 10px 8px; font-size: 10.5px; line-height: 1.4; }
.dexgap-bar { padding: 4px 6px 2px; }
.dexgap-bar .tbl-q { width: 150px; }
.dexgap-note:empty { display: none; }
.dexgap-coin { font-weight: 600; }
.dexgap-unpriced { opacity: 0.62; }
.dexgap-unpriced td { font-style: italic; }
.tbl.dexgap tr.row-pick { cursor: pointer; }
.tbl.dexgap tr.row-pick:hover { background: var(--hover, rgba(127,127,127,0.12)); }
.dexgap-sub { font-size: 9.5px; line-height: 1.15; }
.dexgap-addr { font-size: 9.5px; letter-spacing: -0.2px; }
/* The shared copy button: a control that reads as text until it is hovered,
   because a table full of buttons reads as a form. */
.copy-btn { border: 0; background: none; padding: 0; font: inherit; color: var(--ink-3); cursor: pointer; }
.copy-btn:hover { color: var(--ink-1); text-decoration: underline dotted; }
.copy-btn.is-copied { color: var(--pos, #7fd1a8); }
.dexgap-contract { font-size: 9.5px; letter-spacing: -0.2px; }
a.dexgap-coin { color: inherit; text-decoration: none; border-bottom: 1px dotted currentColor; }
a.dexgap-coin:hover { color: var(--accent, #7fd1a8); }
/* Which of the two exchange columns the net figure speaks for. */
.dexgap-best { box-shadow: inset 2px 0 0 var(--accent, #7fd1a8); }
/* An open-interest cell on a spot row is the perpetual's, borrowed. Marking
   it keeps the column from reading as "this spot market has one". */
.tbl td.is-borrowed { text-decoration: underline dotted; text-underline-offset: 3px; }

/* The catalogue: the block palette, left open on the desk. */
.cat-search { width: calc(100% - 20px); margin: 8px 10px 4px; font-size: 11px; }
.cat-list { padding-bottom: 6px; }
/* Auto layout, not fixed: a fixed share gave "Ratio" the same width as
   "Ліквідність" and took it out of the summary, which is the column doing the
   explaining. The outer two hug their content instead and the summary keeps
   whatever the panel has left. */
.cat-tbl { width: 100%; }
.cat-tbl th:nth-child(1), .cat-tbl td:nth-child(1) { width: 1%; white-space: nowrap; }
.cat-tbl th:nth-child(3), .cat-tbl td:nth-child(3) { width: 1%; white-space: nowrap; text-align: right; }
.cat-tbl td:nth-child(2) { max-width: 0; }
/* A group heading is a row, not a table of its own: the columns have to keep
   lining up across the whole catalogue. */
.cat-group td {
  padding-top: 10px; color: var(--ink-3); font-size: 9px; letter-spacing: .8px;
  text-transform: uppercase; border-bottom: 1px solid var(--rule);
}
.cat-row { cursor: pointer; border-left: 2px solid transparent; }
.cat-row:hover, .cat-row:focus-visible { background: var(--raised); border-left-color: var(--info); outline: none; }
.cat-name { font-size: 11.5px; }
/* The summary is the wide column and the one that can outgrow it; clipping it
   is better than a row that grows to three lines, and the title carries the
   whole text. */
.cat-about { font-size: 10px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cat-here { color: var(--ink-3); font-size: 9px; letter-spacing: .6px; text-transform: uppercase; }
.cat-row.is-here .cat-name { color: var(--ink-2); }

/* Ліквідність: a book whose rows are distances, not prices. */
/* The ladder keeps one width and sits in the middle of whatever panel it is
   given, the way the Order book does: past a point a wider panel only pushes
   the numbers apart, and a price ladder is read as a column, not a row. */
/* The two sides split the height and the mid sits between them, so the spread
   line holds the middle of the panel at any height — the Order book rule. */
[data-panel][data-type="liquidity"] .panel-body { display: flex; flex-direction: column; overflow: hidden; min-height: 0; }
[data-panel][data-type="liquidity"] .lq-side { flex: 1 1 0; min-height: 0; overflow-y: auto; }
[data-panel][data-type="liquidity"] .lq-asks { justify-content: flex-end; }
[data-panel][data-type="liquidity"] .lq-bids { justify-content: flex-start; }
[data-panel][data-type="liquidity"] .lq-head,
[data-panel][data-type="liquidity"] .lq-mid,
[data-panel][data-type="liquidity"] .mp { flex: 0 0 auto; }
.lq-side { display: flex; flex-direction: column; }
.lq-row { flex: 0 0 auto; }
.lq-head, .lq-side, .lq-mid { width: 100%; max-width: 660px; margin-inline: auto; }
.lq-head, .lq-row {
  /* Fractional, so the columns scale together instead of the bar eating every
     spare pixel. The last column is the order marker — a fixed sliver, so the
     ladder does not shift when it appears. */
  display: grid; grid-template-columns: 58px 1fr 1.15fr 1.5fr 12px;
  gap: 8px; align-items: center; padding: 2px 10px;
}
.lq-head { padding-top: 6px; padding-bottom: 4px; border-bottom: 1px solid var(--rule-strong); cursor: help; }
.lq-row { position: relative; font-size: 11.5px; font-variant-numeric: tabular-nums; }
.lq-row:hover { background: var(--raised); }
.lq-ask .lq-pct { color: var(--neg); }
.lq-bid .lq-pct { color: var(--pos); }
.lq-bar-cell { display: block; height: 7px; border-radius: 1px; background: var(--rule-soft); overflow: hidden; }
.lq-bar { display: block; height: 100%; background: var(--rule-strong); }
.lq-ask .lq-bar { background: color-mix(in srgb, var(--neg) 55%, transparent); }
.lq-bid .lq-bar { background: color-mix(in srgb, var(--pos) 55%, transparent); }
/* The row for the size being considered: it is the answer, so it reads louder
   than the ladder it sits in. */
.lq-row.is-order { background: color-mix(in srgb, var(--info) 13%, transparent); box-shadow: inset 2px 0 0 var(--info); }
.lq-row.is-order .lq-pct { color: var(--info); font-weight: 600; }
.lq-order-tag { color: var(--info); font-size: 9.5px; line-height: 1; }
.lq-mid {
  /* `auto` on the sides, not 0: this rule sits after the one that centres the
     ladder, and a shorthand margin would quietly undo it. */
  display: flex; justify-content: space-between; gap: 8px; margin: 3px auto;
  padding: 3px 10px; border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule);
  background: var(--raised); font-size: 12px; font-variant-numeric: tabular-nums;
}
.sym-btn { background: none; border: 0; color: var(--ink); font: inherit; cursor: pointer; padding: 0; }
.sym-btn:hover { color: var(--info); }
.sym-btn.is-picked { color: var(--info); font-weight: 600; }
.badge { font-size: 10px; padding: 1px 6px; border-radius: 2px; border: 1px solid var(--rule-strong); }
.badge.info { border-color: var(--info-dim); } .badge.warn { border-color: var(--warn-dim); } .badge.pos { border-color: var(--pos-dim); } .badge.neg { border-color: var(--neg-dim); }

/* ───── order book ───── */
[data-panel][data-type="orderbook"] .panel-body { display: flex; flex-direction: column; overflow: hidden; min-height: 0; }
[data-panel][data-type="orderbook"] .ob-cols { flex: 0 0 auto; }
[data-panel][data-type="orderbook"] .ob-side { flex: 1 1 0; min-height: 0; overflow: hidden; }
[data-panel][data-type="orderbook"] .ob-asks { justify-content: flex-end; }
[data-panel][data-type="orderbook"] .ob-bids { justify-content: flex-start; }
.ob-cols { display: grid; grid-template-columns: 1.2fr 1fr 1fr; gap: 6px; padding: 0 4px 4px; }
.ob-side { display: flex; flex-direction: column; }
.ob-row { display: grid; grid-template-columns: 1.2fr 1fr 1fr; gap: 6px; padding: 1px 4px; font-size: 11.5px; position: relative; flex: 0 0 auto; }
.ob-row::before { content: ''; position: absolute; inset: 0; left: auto; right: 0; width: var(--fill, 0); opacity: .12; }
.ob-row.neg::before { background: var(--neg); }
.ob-row.pos::before { background: var(--pos); }
.ob-price { display: flex; align-items: baseline; gap: 4px; min-width: 0; white-space: nowrap; }
.ob-price-value { overflow: hidden; text-overflow: ellipsis; }
.ob-offset { color: var(--ink-3); font-size: 9px; letter-spacing: 0; }
.ob-mid { display: flex; justify-content: space-between; align-items: baseline; flex: 0 0 auto; padding: 4px 4px; border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule); margin: 3px 0; font-size: 13px; }

/* ───── pair book ───── */
.pb-grid { display: grid; grid-template-columns: 1fr 90px 1fr; gap: 8px; align-items: start; }
.pb-col .ob-row { grid-template-columns: 1.4fr 1fr; }
.pb-mid { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; padding-top: 40px; font-size: 13px; font-weight: 700; }

/* ───── candles ───── */
.chart-host { width: 100%; height: 100%; min-width: 0; min-height: 220px; overflow: hidden; }
[data-panel][data-type="candles"] .panel-body { display: flex; flex-direction: column; padding: 0; overflow: hidden; min-height: 0; }
[data-panel][data-type="candles"] .chart-host { flex: 1 1 0; height: auto; min-height: 0; }
[data-panel][data-type="candles"] { min-height: 280px; }
.mkt-picker { position: relative; z-index: 3; padding: 6px 8px 0; }
.mkt-picker-bar { display: flex; align-items: center; gap: 7px; min-width: 0; padding: 4px 7px; border: 1px solid var(--rule); border-radius: 3px; background: var(--ground); }
.mkt-picker-icon { color: var(--ink-3); font-size: 16px; line-height: 1; }
.mkt-picker-input { min-width: 90px; flex: 1 1 140px; padding: 2px 0; border: 0; background: transparent; font: inherit; font-size: 12px; color: var(--ink); }
.mkt-picker-input:focus { outline: none; }
.mkt-picker-selected { margin-left: auto; overflow: hidden; color: var(--ink-3); font-size: 10px; text-overflow: ellipsis; white-space: nowrap; }
.mkt-picker-results { position: absolute; top: calc(100% - 1px); left: 8px; right: 8px; max-height: 250px; overflow-y: auto; border: 1px solid var(--rule-strong); border-radius: 0 0 3px 3px; background: var(--panel); box-shadow: 0 12px 28px rgba(0,0,0,.42); }
.mkt-row { display: grid; grid-template-columns: 1.1fr 1fr .9fr 1.2fr; gap: 8px; width: 100%; padding: 7px 9px; border: 0; border-bottom: 1px solid var(--rule-soft); background: transparent; color: var(--ink-2); font: inherit; font-size: 11px; text-align: left; cursor: pointer; }
.mkt-row:last-child { border-bottom: 0; }
.mkt-row:hover, .mkt-row:focus-visible { background: var(--raised); color: var(--ink); outline: none; }
.mkt-row.is-unavailable { opacity: .42; cursor: not-allowed; }
.mkt-row.is-unavailable:hover { background: transparent; }
.mkt-row-symbol { color: var(--ink); font-weight: 600; }
.mkt-row-name { color: var(--info); }
.mkt-row-type { color: var(--pos); font-size: 10px; }
.mkt-row-native { overflow: hidden; color: var(--ink-3); text-overflow: ellipsis; white-space: nowrap; }
.mkt-picker-empty { padding: 10px; color: var(--ink-3); font-size: 11px; }
.mkt-picker-bar { flex-wrap: wrap; }
.mkt-picker-chips { display: contents; }
.mkt-chip { display: inline-flex; align-items: center; gap: 4px; padding: 1px 3px 1px 6px; border: 1px solid var(--rule-strong); border-radius: 2px; background: var(--raised); color: var(--ink); font-size: 10px; letter-spacing: .03em; }
.mkt-chip-x { padding: 0 3px; border: 0; background: transparent; color: var(--ink-3); font: inherit; font-size: 12px; line-height: 1; cursor: pointer; }
.mkt-chip-x:hover, .mkt-chip-x:focus-visible { color: var(--neg); outline: none; }

/* ───── spread chart ───── */
.sc-legend { display: flex; gap: 5px; flex-wrap: wrap; padding: 4px 6px; }
.sc-legend .chip { font-size: 10px; padding: 1px 6px; }
.sc-meta { display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 14px; padding: 6px 10px; border-bottom: 1px solid var(--rule); font-size: 11px; }
.sc-pairname { color: var(--ink); font-weight: 500; }
.sc-in, .sc-out { font-size: 13px; font-weight: 500; }
.sc-fund { white-space: nowrap; font-variant-numeric: tabular-nums; }
.sc-context-side.context-hover { background: var(--raised); border-radius: 2px; outline: 1px solid var(--info); outline-offset: 2px; }
.sc-status:empty { display: none; }
/* The two ways out of this block, kept tight against the re-pick chip they
   sit next to — the meta row's own gap is 14px between groups. */
.sc-links { display: inline-flex; gap: 4px; }
.sc-link { text-decoration: none; padding: 2px 7px; font-size: 10px; }
.sc-ranges { display: flex; gap: 2px; margin-left: auto; }
.sc-ranges .chip { padding: 2px 6px; }
[data-panel][data-type="spread-chart"] .panel-body { padding: 0; display: flex; flex-direction: column; }

/* ───── trades ───── */
[data-panel][data-type="trades"] .panel-body { display: flex; flex-direction: column; overflow: hidden; min-height: 0; height: 0; }
.tr-flow { display: flex; gap: 12px; padding: 0 4px 6px; text-transform: none; letter-spacing: 0; font-size: 11px; }
.tr-table-wrap { flex: 1 1 0; min-height: 0; overflow: auto; overflow-anchor: none; }
.tr-tbl { width: 100%; }
.tr-tbl td { padding: 1px 6px; font-size: 11px; }
.tr-big td { font-weight: 700; }

/* ───── alerts ───── */
[data-panel][data-type="alerts"] .panel-body { display: flex; flex-direction: column; overflow: hidden; min-height: 0; }
[data-panel][data-type="alerts"] .tbl-head { flex-shrink: 0; }
.al-list { display: flex; flex-direction: column; gap: 6px; flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding-right: 4px; }
.al-item { border-left: 2px solid var(--rule-strong); padding: 4px 8px; }
.al-meta { display: flex; gap: 8px; align-items: center; font-size: 10.5px; margin-bottom: 2px; }
.al-meta .chip { font-size: 9.5px; padding: 0 6px; cursor: default; }
.al-text { white-space: pre-wrap; font-size: 11.5px; line-height: 1.45; overflow-wrap: anywhere; }
.al-text a { overflow-wrap: anywhere; }
.al-meta .chip.neg { color: var(--neg); border-color: var(--neg-dim); }

/* The «+ alert» control: a native popover enters the top layer so panel
   overflow and stacking contexts cannot clip or cover its choices. */
.al-menu-wrap { position: relative; display: inline-flex; }
.al-menu {
  position: fixed; inset: auto; margin: 0; min-width: 246px; max-width: calc(100vw - 16px);
  max-height: calc(100vh - 16px); overflow-y: auto;
  display: flex; flex-direction: column; gap: 1px; padding: 5px;
  background: var(--panel); border: 1px solid var(--rule-strong); border-radius: 3px;
  box-shadow: 0 8px 22px rgba(0, 0, 0, .55);
}
/* Author display:flex overrides the browser's hidden popover state. */
.al-menu:not(:popover-open) { display: none; }
.al-menu.is-asking { width: 320px; max-width: calc(100vw - 16px); }
.al-menu button {
  display: block; width: 100%; text-align: left; padding: 6px 8px;
  background: none; border: 0; border-radius: 2px; color: var(--ink); font: inherit; cursor: pointer;
}
.al-menu button:hover { background: var(--raised); }
.al-menu .hint { display: block; margin-top: 2px; color: var(--ink-3); font-size: 10px; }
.al-menu button.back { color: var(--ink-3); border-bottom: 1px solid var(--rule); border-radius: 0; margin-bottom: 3px; }
.al-menu button:disabled { color: var(--ink-3); cursor: default; }
.al-menu .already { float: right; color: var(--pos); font-size: 10px; letter-spacing: .4px; }
.al-menu .note { padding: 6px 8px; font-size: 11px; line-height: 1.4; }
.al-menu .note.warn { color: var(--warn); }
.al-menu .note.neg { color: var(--neg); }
.al-menu .note.ok { color: var(--pos); }
/* The one question a menu asks: which coin. It sits in the menu, so the field
   has to look like the rows above it rather than like a form. */
.al-menu .al-ask { display: flex; align-items: center; gap: 6px; padding: 6px 8px; }
.al-menu .al-ask span { color: var(--ink-3); font-size: 10px; letter-spacing: .4px; text-transform: uppercase; }
.al-menu .al-ask input { flex: 1 1 auto; min-width: 0; }
.al-menu .al-ask input::placeholder { color: var(--ink-3); opacity: 1; }
.al-menu .al-ask button {
  width: auto; flex: 0 0 auto; padding: 4px 10px;
  background: var(--raised); border: 1px solid var(--rule-strong); border-radius: 3px;
}
.al-menu > .hint { padding: 0 8px 4px; color: var(--ink-3); font-size: 10px; }

/* A button that is only an icon: square, and the glyph centred rather than
   sitting on a text baseline that does not exist. */
.icon-btn { display: inline-flex; align-items: center; justify-content: center; padding: 2px 8px; }
.icon-btn svg { display: block; }

/* Settings: one panel for what is true of the whole deck. */
.set-box {
  width: min(560px, 94vw); max-height: 86vh; overflow: auto;
  background: var(--panel); border: 1px solid var(--rule-strong); border-radius: 4px;
  padding: 14px 16px 16px; display: flex; flex-direction: column; gap: 14px;
}
.set-head { display: flex; align-items: baseline; gap: 10px; }
.set-head .btn { margin-left: auto; }
.set-section { display: flex; flex-direction: column; gap: 6px; }
.set-section .lbl { margin-bottom: 2px; }
.set-row {
  display: grid; grid-template-columns: 1fr auto; gap: 12px; align-items: center;
  padding: 4px 0; border-bottom: 1px solid var(--rule-soft);
}
.set-row:last-child { border-bottom: 0; }
.set-label { display: flex; flex-direction: column; }
.set-hint { color: var(--ink-3); font-size: 10px; margin-top: 2px; }
.set-row input[type="text"] { width: 240px; }
.set-row input.set-time { width: 64px; text-align: center; }
.set-row input.set-num { width: 80px; text-align: right; }
.set-pair { display: inline-flex; align-items: center; gap: 6px; color: var(--ink-3); }
.set-actions { display: flex; align-items: center; gap: 10px; margin-top: 4px; }
.set-status { font-size: 11px; }
.set-foot { display: flex; align-items: center; gap: 12px; }
.set-legal { display: flex; flex-wrap: wrap; gap: 4px 14px; padding-top: 10px; border-top: 1px solid var(--rule); font-size: 11px; }
.set-legal a { color: var(--ink-3); text-decoration: none; }
.set-legal a:hover { color: var(--ink); text-decoration: underline; }

/* Compact density: the same deck with less air, for a screen that has to hold
   four more rows. Only paddings and leading — never the font size, which is
   what makes a table unreadable rather than dense. */
:root[data-density="compact"] .tbl th, :root[data-density="compact"] .tbl td { padding-top: 1px; padding-bottom: 1px; }
:root[data-density="compact"] .panel-body { padding: 5px 7px; }
:root[data-density="compact"] .al-item { padding-top: 2px; padding-bottom: 2px; }
:root[data-density="compact"] .nw-row, :root[data-density="compact"] .ix-row { line-height: 1.25; }

/* Networks: deposit/withdrawal status per chain, grouped by exchange */
.nw-head { display: flex; align-items: baseline; gap: 10px; padding: 7px 9px; border-bottom: 1px solid var(--rule); }
.nw-title { color: var(--ink); font-weight: 600; }
.nw-counts { margin-left: auto; color: var(--ink-2); font-size: 11px; white-space: nowrap; }
.nw-age { margin-left: auto; font-size: 10px; }
.nw-venue-head .nw-note + .nw-counts, .nw-venue-head .nw-counts { margin-left: auto; }
.nw-body { overflow-y: auto; }
.nw-venue { margin-bottom: 6px; }
.nw-venue:last-child { margin-bottom: 0; }
.nw-venue-head { display: flex; align-items: baseline; gap: 8px; padding: 5px 9px 5px 7px; border-left: 2px solid var(--info); background: var(--raised); font-size: 11px; }
.nw-venue-head b { letter-spacing: .04em; text-transform: uppercase; }
.nw-cols, .nw-row { display: grid; grid-template-columns: minmax(64px, 1.3fr) 40px 40px minmax(56px, 1fr) 46px minmax(74px, 1.2fr); gap: 6px; align-items: center; padding: 4px 9px; }
.nw-cols { position: sticky; top: 0; z-index: 1; padding-left: 21px; border-bottom: 1px solid var(--rule); background: var(--panel); font-size: 10px; }
.nw-row { position: relative; font-size: 11px; border-bottom: 1px solid var(--rule-soft); padding-left: 21px; }
.nw-row::before { content: ''; position: absolute; left: 10px; top: 0; bottom: 0; border-left: 1px solid var(--rule); }
.nw-venue .nw-row:last-child::before { bottom: 50%; }
.nw-row:last-child { border-bottom: 0; }
.nw-row:hover { background: var(--raised); }
.nw-net { overflow: hidden; color: var(--ink); text-overflow: ellipsis; white-space: nowrap; }
.nw-cell { display: inline-flex; align-items: center; gap: 4px; }
.nw-flag { font-size: 11px; }
.nw-fee { color: var(--ink-2); }
.nw-link { color: var(--ink-3); text-decoration: none; font-size: 10px; }
.nw-link:hover { color: var(--info); }
.nw-contract { padding: 0; border: 0; background: transparent; color: var(--ink-3); font: inherit; font-size: 10px; cursor: pointer; }
.nw-contract:hover { color: var(--ink); text-decoration: underline dotted; }
.nw-contract.is-copied { color: var(--pos); }
.nw-contract-cell { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nw-note { margin-left: auto; padding: 0 4px; border: 1px solid var(--rule-strong); border-radius: 2px; color: var(--warn); font-size: 9px; white-space: nowrap; cursor: help; }
.nw-muted { display: flex; flex-wrap: wrap; gap: 4px 14px; padding: 8px 9px; font-size: 10px; }
.nw-muted-item { color: var(--ink-3); white-space: nowrap; }
.nw-pending { color: var(--ink-3); font-size: 12px; }

/* Index prices: one card per venue, its basket indented under it. The weight
   bar behind a row is the fastest read — one exchange at 45% is a different
   index from five at 20%. */
.ix-head { display: flex; align-items: baseline; gap: 10px; padding: 7px 9px; border-bottom: 1px solid var(--rule); }
.ix-title { color: var(--ink); font-weight: 600; }
.ix-band { margin-left: auto; padding: 0 4px; border: 1px solid var(--rule-strong); border-radius: 2px; color: var(--ink-2); font-size: 10px; white-space: nowrap; cursor: help; }
.ix-band.warn { border-color: var(--warn); color: var(--warn); }
.ix-body { overflow-y: auto; }
.ix-venue { margin-bottom: 6px; }
.ix-venue:last-child { margin-bottom: 0; }
.ix-venue-head { display: flex; align-items: baseline; gap: 8px; padding: 5px 9px 5px 7px; border-left: 2px solid var(--info); background: var(--raised); font-size: 11px; }
.ix-venue-head b { letter-spacing: .04em; text-transform: uppercase; }
.ix-index { color: var(--ink); font-size: 12px; }
.ix-symbol { margin-left: auto; font-size: 10px; }
.ix-note { padding: 0 4px; border: 1px solid var(--rule-strong); border-radius: 2px; color: var(--ink-3); font-size: 9px; white-space: nowrap; cursor: help; }
.ix-row { position: relative; display: grid; grid-template-columns: minmax(80px, 1.4fr) 52px minmax(70px, 1fr) 70px; gap: 6px; align-items: center; padding: 4px 9px 4px 21px; font-size: 11px; border-bottom: 1px solid var(--rule-soft); }
.ix-row::before { content: ''; position: absolute; left: 10px; top: 0; bottom: 0; border-left: 1px solid var(--rule); }
.ix-venue .ix-row:last-child::before { bottom: 50%; }
.ix-row::after { content: ''; position: absolute; left: 21px; right: 9px; bottom: 0; height: 2px; width: var(--w, 0); background: var(--info); opacity: .35; }
.ix-row:last-child { border-bottom: 0; }
.ix-row:hover { background: var(--raised); }
.ix-src { overflow: hidden; color: var(--ink); text-overflow: ellipsis; white-space: nowrap; }
.ix-weight { color: var(--ink-2); }
.ix-muted { display: flex; flex-wrap: wrap; gap: 4px 14px; padding: 8px 9px; font-size: 10px; }

/* DEX chart: one token on one chain, addressed by contract rather than by
   exchange ticker, so the picker is a paste box instead of a search. */
[data-panel][data-type="dex-chart"] .panel-body { display: flex; flex-direction: column; padding: 0; overflow: hidden; min-height: 0; }
/* The address is typed once, the numbers are read constantly: the input keeps
   a fixed slice and the stats take what is left, wrapping rather than eating
   the box you paste into. */
.dx-head { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; padding: 6px 10px; border-bottom: 1px solid var(--rule); }
.dx-addr { flex: 0 1 200px; min-width: 96px; font-size: 11px; }
.dx-title { flex: 0 0 auto; white-space: nowrap; font-size: 10px; letter-spacing: .8px; }
.dx-chains { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; padding: 6px 10px; border-bottom: 1px solid var(--rule); }
.dx-stats { flex: 1 1 140px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 10px; letter-spacing: .4px; }

/* Ratio: two markets divided by each other, so the heading carries the reading
   and the chart is one line. */
[data-panel][data-type="pair-ratio"] .panel-body { display: flex; flex-direction: column; padding: 0; overflow: hidden; min-height: 0; }
.pr-head { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; padding: 6px 10px; border-bottom: 1px solid var(--rule); }
.pr-title { font-size: 11px; letter-spacing: .6px; }
.pr-range { font-size: 10px; letter-spacing: .4px; }

/* ───── usage (admin) block ─────
   Three tiers: the pulse (now), the browsers (who), the load (how hard).
   Hairlines, not cards; the desk's mono and tabular numbers throughout. */
.usage { container-type: inline-size; display: flex; flex-direction: column; gap: 14px; }

/* pulse */
.usage-pulse { display: grid; grid-template-columns: minmax(180px, 1fr) minmax(160px, 1.4fr); gap: 8px 18px; align-items: end; padding-bottom: 12px; border-bottom: 1px solid var(--rule); }
.usage-pulse-now { display: grid; grid-template-columns: auto auto 1fr; grid-template-rows: auto auto; column-gap: 8px; align-items: baseline; }
.usage-live { width: 8px; height: 8px; border-radius: 50%; background: var(--pos); box-shadow: 0 0 0 0 color-mix(in srgb, var(--pos) 45%, transparent); align-self: center; animation: usage-pulse 2.4s ease-out infinite; }
@keyframes usage-pulse { 0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--pos) 45%, transparent); } 70% { box-shadow: 0 0 0 7px transparent; } 100% { box-shadow: 0 0 0 0 transparent; } }
@media (prefers-reduced-motion: reduce) { .usage-live { animation: none; } }
.usage-pulse-n { font-size: 34px; font-weight: 500; line-height: 1; color: var(--ink); letter-spacing: -.5px; }
.usage-pulse-l { color: var(--ink-2); letter-spacing: .6px; }
.usage-pulse-sub { grid-column: 2 / 4; }
.usage-pulse-ts { grid-column: 2 / 4; font-size: 10px; }
.usage-pulse-chart { display: flex; flex-direction: column; gap: 2px; }
.usage-spark { width: 100%; height: 48px; display: block; }
.usage-axis { display: flex; justify-content: space-between; font-size: 10px; letter-spacing: .4px; }

/* tiers */
.usage-tier { display: flex; flex-direction: column; gap: 10px; }
.usage-tier + .usage-tier { padding-top: 12px; border-top: 1px solid var(--rule); }
.usage-tier-head { display: flex; align-items: baseline; gap: 10px; }

/* KPIs: a row of numbers separated by hairlines, wrapping as the block narrows */
.usage-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(92px, 1fr)); row-gap: 10px; }
.usage-kpi { padding: 0 10px; border-left: 1px solid var(--rule); min-width: 0; display: grid; grid-template-rows: 24px auto auto; align-content: start; }
.usage-kpi .lbl { align-self: end; line-height: 12px; }
.usage-kpi:first-child { padding-left: 0; border-left: 0; }
.usage-kpi-v { font-size: 20px; line-height: 1.15; color: var(--ink); margin-top: 3px; font-variant-numeric: tabular-nums; }
.usage-kpi-sub { font-size: 10px; min-height: 12px; }

/* 30-day bars: bottom-aligned, quiet days as a hairline mark */
.usage-days { display: flex; flex-direction: column; gap: 4px; }
.usage-bars { display: flex; align-items: flex-end; gap: 2px; height: 36px; border-bottom: 1px solid var(--rule); }
.usage-bars i { flex: 1; background: var(--info); border-radius: 1px 1px 0 0; min-width: 2px; opacity: .85; }
.usage-bars i.is-zero { background: var(--rule-strong); opacity: 1; }
.usage-bars i:last-child { background: var(--pos); opacity: 1; }

/* horizontal bars: label · track · number */
.usage-hbars { display: flex; flex-direction: column; gap: 4px; }
.usage-hbar { display: grid; grid-template-columns: minmax(80px, 1fr) minmax(60px, 1.2fr) 44px; gap: 8px; align-items: center; font-size: 11px; }
.usage-hbar-track { height: 6px; background: var(--raised); border-radius: 1px; overflow: hidden; }
.usage-hbar-track i { display: block; height: 100%; border-radius: 1px; }
.usage-hbar-n { color: var(--ink); font-variant-numeric: tabular-nums; }

/* load */
.usage-load { display: grid; grid-template-columns: minmax(150px, 1fr) minmax(160px, 1.6fr); gap: 8px 18px; align-items: end; }
.usage-load-main { display: flex; flex-direction: column; gap: 8px; }
.usage-load-main .usage-kpi { padding-left: 0; border-left: 0; }
.usage-load-main .usage-kpi-v { font-size: 26px; }
.usage-pills { display: flex; flex-wrap: wrap; gap: 4px; }
.usage-pill { padding: 1px 7px; border: 1px solid var(--rule); border-radius: 2px; font-size: 10px; letter-spacing: .5px; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.usage-pill.is-warn { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 45%, var(--rule)); background: var(--warn-dim); }
.usage-pill.is-neg { color: var(--neg); border-color: color-mix(in srgb, var(--neg) 45%, var(--rule)); background: var(--neg-dim); }
.usage-load-chart { display: flex; flex-direction: column; gap: 2px; }
.usage-stack { display: flex; height: 8px; gap: 1px; border-radius: 1px; overflow: hidden; background: var(--raised); }
.usage-stack i { display: block; height: 100%; min-width: 1px; }
.usage-legend { display: flex; flex-wrap: wrap; gap: 4px 14px; font-size: 11px; color: var(--ink-2); }
.usage-legend-i { display: inline-flex; align-items: center; gap: 5px; }
.usage-legend-i i { width: 7px; height: 7px; border-radius: 1px; display: inline-block; }
.usage-legend-i b { font-weight: 500; color: var(--ink); font-variant-numeric: tabular-nums; }
.usage-ips, .usage-open { display: flex; flex-direction: column; gap: 6px; }

@container (max-width: 520px) {
  .usage-pulse, .usage-load { grid-template-columns: 1fr; }
  .usage-kpis { grid-template-columns: repeat(auto-fit, minmax(80px, 1fr)); }
}
.account-control { display: inline-flex; align-items: center; gap: 8px; min-width: 0; }
.account-name { max-width: 140px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.account-button:focus-visible { outline: 2px solid var(--accent, #60a5fa); outline-offset: 2px; }
/* A session that ran out: the button is what fixes it, so the button carries it. */
.account-button.is-expired { border-color: var(--warn); color: var(--warn); }
@media (max-width: 600px) { .account-control { max-width: 100%; } }

/* The rate reticks every second and steps between one and three digits. A slot
   as wide as the widest of them stops the whole strip — the login button, the
   clock, everything to its right — from sliding under it. */
#ws-rate .strip-count { display: inline-block; min-width: 3ch; text-align: right; font-variant-numeric: tabular-nums; }

/* Swap through the pool. A size the pool could not fill keeps its row and says
   so across the whole width: the reason is the answer, not the absence of one. */
.dexswap-note { padding: 6px 10px 8px; font-size: 10.5px; line-height: 1.5; }
.dexswap-note:empty { display: none; }
.dexswap-empty td { font-style: italic; opacity: 0.62; }
.dexswap-go { white-space: nowrap; }
.dexswap-go .chip { margin-right: 4px; }
/* The aggregator is a different claim from the pool we priced, and looks it. */
.dexswap-agg { opacity: 0.72; border-style: dashed; }
.dexswap-pool { font-size: 9.5px; letter-spacing: -0.2px; }
/* A transfer tax is not a cost of the pool — it is the token taking a cut on
   the way in and on the way out, and it is already inside the prices above.
   The loudest line in this footer on purpose: every price in the table is
   worse than the pool's own because of it, and a reader who skims and leaves
   is exactly the one it is for. */
.dexswap-tax { color: var(--warn); font-weight: 600; }
/* «Порахувати» and the age beside it: the age is the half that makes a repeat
   press readable as "nothing changed" rather than as a dead button. */
.dexswap-go-btn[disabled] { opacity: 0.55; cursor: default; }
.dexswap-age { font-size: 10px; margin-left: 6px; white-space: nowrap; }

/* Spread across venues. A row is one PAIRING: the two legs stacked, buying on
   top, and the prices they cross at beside them. The skew column is the one
   that says whether the row is a spread at all. */
.vspread-note { padding: 6px 10px 8px; font-size: 10.5px; line-height: 1.45; }
.vspread-note:empty { display: none; }
.vspread-coin { font-weight: 600; font-size: 12.5px; }
/* The rows the one-second pass derived. Both passes feed this table and their
   rows differ in age by up to ten seconds, so the dot is the only thing on
   screen saying which number is current. */
.vspread-live { color: var(--pos); font-size: 7px; vertical-align: middle; margin-right: 3px; }
/* Which legs a click would miss. Above the table and only while it is true: the
   deck remounts the block on every change of its links. */
.vspread-hint { font-size: 11px; padding: 4px 8px 6px; }
.vspread-kind { font-size: 9.5px; }
.vspread-legs { white-space: nowrap; }
.vspread-line { display: flex; align-items: baseline; gap: 6px; line-height: 1.5; }
.vspread-arrow { width: 9px; flex: 0 0 9px; }
.vspread-where { font-size: 11px; }
/* The price sits at the end of its own leg, right-aligned, so the two legs'
   digits line up under each other — the difference between them is the whole
   row, and it has to be readable straight down. */
.vspread-legs { min-width: 240px; }
.vspread-where { flex: 1 1 auto; }
.vspread-px { font-size: 11px; color: var(--ink-2); text-align: right; }
.vspread-entry { font-weight: 600; }
.tbl.vspread td { vertical-align: top; }
.tbl.vspread tr.row-pick { cursor: pointer; }
.tbl.vspread tr.row-pick:hover { background: var(--hover, rgba(127,127,127,0.12)); }

/* A market no multiplier can put on this token's scale — a different coin under
   the same ticker. Below the line and dimmed, never deleted: a reader who really
   does trade that listing would otherwise see nothing and no reason why. */
.tbl tr.is-refused { opacity: 0.45; border-top: 1px solid var(--line); }
.tbl tr.is-refused .vspread-coin, .tbl tr.is-refused td { font-style: italic; }
.carry-fparts { font-size: 9.5px; }
