/* ══════════════════════════════════════════════════════════════════════════
   METRA — feature surface  ·  the layer every module page sits on
   ──────────────────────────────────────────────────────────────────────────
   The modules were each built on their own, so each one invented its own
   margins. Measured across all of them at 1440px, forty of the fifty two put
   their content flush against the window: left 0, right 0, no padding at all.
   Sentences ran 1440px wide. A table's last column ended at the very edge of
   the glass. Nothing was broken, and nothing looked composed.

   This file is the one place those decisions are made. It does not restyle
   any module's logic; it gives them all the same page inset, the same reading
   width, the same table, the same toolbar rhythm, and the same distance
   between a thing and its label. Loaded last, after mt-design and mt-brand.

   The rules follow the mark, same as the rest of the system: black canvas,
   hairlines, no radius, everything on a four pixel grid. The references are
   the desks people already use, which all agree on this much: dense is fine,
   crowded is not.
   ══════════════════════════════════════════════════════════════════════════ */

:root {
  /* The page inset. It matches the header, so content lines up with the
     wordmark above it instead of floating free of the chrome. */
  --mx-inset: 16px;
  --mx-inset-app: 12px;
  --mx-max: 1680px;
  /* Reading width. A line of prose past this is measured in head turns. */
  --mx-measure: 72ch;
  --mx-tape-h: 0px;

  /* One spacing scale. Every gap below is one of these. */
  --sp-1: 4px;  --sp-2: 8px;   --sp-3: 12px;  --sp-4: 16px;
  --sp-5: 20px; --sp-6: 24px;  --sp-8: 32px;  --sp-10: 40px;

  /* The distance between a mark and the word it belongs to. Small enough to
     read as one object, large enough that they are not touching. */
  --gap-icon: 8px;
  --gap-icon-sm: 6px;
}
@media (min-width: 720px)  { :root { --mx-inset: 22px; --mx-inset-app: 16px; } }
@media (min-width: 1200px) { :root { --mx-inset: 28px; --mx-inset-app: 20px; } }

/* ══ 1 · the page inset ═════════════════════════════════════════════════════
   Document pages get the full container: gutters, a ceiling, and centring.
   Workspace pages keep their full-bleed grid but stop touching the glass. */

body.mx-shell:not(.mx-body-app) > .mt-surface,
body.mx-shell:not(.mx-body-app) > [role="main"] {
  box-sizing: border-box;
  width: 100%;
  max-width: var(--mx-max);
  margin-inline: auto;
  padding-inline: max(var(--mx-inset), env(safe-area-inset-left));
  padding-bottom: var(--sp-8);
}
body.mx-shell.mx-body-app > .mt-surface,
body.mx-shell.mx-body-app > .mx-app-main {
  box-sizing: border-box;
  padding-inline: var(--mx-inset-app);
}
/* Pages that already set their own gutter do not get a second one. */
body.mx-page-chart > .mt-surface,
body.mx-page-chart > .mx-app-main { padding-inline: 0; }

/* ══ 2 · reading width ══════════════════════════════════════════════════════
   Running prose is capped. Figures, tables and code are not: a number column
   is read down, not across, and clipping it would lose data. */

.mt-surface :is(p, .lede, .desc, .note, .blurb, .summary, .narr, .deck, .body,
  [class*="-desc"], [class*="-note"], [class*="-narr"], [class*="-lede"],
  [class*="-summary"], [class*="-blurb"], [class*="-context"]):not([class*="row"]):not(td):not(th)
  /* a box that holds other boxes is layout, not prose: the dashboard's summary column was held
     to 72ch and left a quarter of a tablet screen empty */
  :not(:has(> div, > section, > article, > table, > iframe, > canvas, > svg, > ul, > ol)) {
  max-width: var(--mx-measure);
}
/* A page heading is a short line by nature. A row's title in a feed is not a
   heading, so it gets the longer cap: tight enough to read, loose enough that
   a headline does not wrap four times. */
.mt-surface :is(h1, h2) { max-width: 34ch; }
.mt-surface :is(h3, .title, .headline, [class*="-title"]):not(h1):not(h2) { max-width: 84ch; }

/* A feed is a column of text, so it sits as a column rather than stretching
   the full width of a desktop window with nothing on its right. The container
   is often the growing child the shell adopts, so it can be .mt-surface itself
   rather than something inside it; both are matched. */
/* Live Wire is not in this list: it is a panel beside a filter rail, like
   Crypto News, and its rows start at the panel's edge. */
.mt-surface :is(.news-container, .mt-feed),
.mt-surface:is(.news-container, .mt-feed) > :is(.news-item, li),
.mt-surface:is(.news-container, .mt-feed) {
  max-width: 940px; margin-inline: auto; width: 100%;
}
/* inside a cell or a card the cell is already the limit */
.mt-surface :is(td, th, .mt-cell) :is(p, .desc, .note) { max-width: none; }

/* ══ 3 · a thing and its label ══════════════════════════════════════════════
   The complaint that started this: a feature name and its lock sat one pixel
   apart and read as one smudged word. Rather than patch that one badge, every
   control that carries a mark beside a word now keeps the same distance. */

:is(button, a, label, summary, .chip, .pill, .tag, .badge, .btn, .seg button,
    .md-btn, .hs-btn, .md-tab, .mx-action, .fn-lock, [class*="-badge"], [class*="-chip"])
  :is(svg, img, .ico, .icon, [class*="-ico"]) {
  flex: none;
}
/* Only rows that actually mix a mark with words: a gap on an icon-only button
   would push its glyph off centre. */
:is(button, a, label, summary, .chip, .pill, .tag, .badge, .btn, .md-btn, .hs-btn,
    .md-tab, .mx-action, .fn-lock, .mt-lock, [class*="-badge"], [class*="-chip"]):has(svg + *),
:is(button, a, label, summary, .chip, .pill, .tag, .badge, .btn, .md-btn, .hs-btn,
    .md-tab, .mx-action, .fn-lock, .mt-lock, [class*="-badge"], [class*="-chip"]):has(* + svg) {
  display: inline-flex;
  align-items: center;
  gap: var(--gap-icon);
}
/* a badge set in 9 or 10px type wants a slightly tighter pairing */
.fn-lock, .mt-lock, .badge, .tag, [class*="-badge"] { gap: var(--gap-icon-sm); }

/* A label in front of a control, which is the other half of the same problem:
   "Venue" sat 4px from the segmented buttons it names. */
:is(.toolbar, .md-toolbar, .mt-toolbar, .controls, .filters, .filterbar,
    .commandbar, .ctrl-group, .section-tools) > :is(label, .k, .lbl, .label, .ctrl-label) {
  margin-inline-end: var(--sp-1);
}

/* ══ 4 · toolbars ═══════════════════════════════════════════════════════════
   One rhythm: controls eight apart, groups fourteen apart, and the row wraps
   rather than growing past its box. */

/* Named outright, never by wildcard. A first pass matched [class*="-toolbar"],
   which also caught .md-toolbar-mid: that strip is a horizontal scroller, and
   being told to wrap it grew to 350px inside a 42px bar and painted its
   interval buttons up behind the site header, where they could not be pressed.
   A class name is not a contract about layout. */
.mt-toolbar,
:is(.toolbar, .controls, .filters, .filterbar, .commandbar) {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-3);
  min-width: 0;
}
.mt-toolbar > .mt-group,
.mt-group { display: inline-flex; align-items: center; gap: var(--sp-2); min-width: 0; }
.mt-toolbar .mt-spacer { flex: 1 1 auto; min-width: 0; }
/* a hairline, not a bullet, between groups */
.mt-toolbar > .mt-rule { width: 1px; align-self: stretch; min-height: 20px; background: var(--line); }

/* ══ 5 · panels ═════════════════════════════════════════════════════════════ */

.mt-panel {
  border: 1px solid var(--line);
  background: var(--s-raised);
  min-width: 0;
}
.mt-panel + .mt-panel { margin-top: var(--sp-4); }
.mt-panel-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--sp-3) var(--sp-4); flex-wrap: wrap;
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--line);
}
.mt-panel-title { margin: 0; font-size: 13.5px; font-weight: 600; color: var(--ink); }
.mt-panel-kicker {
  margin: 0 0 3px; font-family: var(--pixel-label); font-size: 9px; color: var(--ink-4);
}
.mt-panel-body { padding: var(--sp-4); }
.mt-panel-body.flush { padding: 0; }

/* ══ 6 · the figure strip ═══════════════════════════════════════════════════
   Volume Screener's strip had five figures and a sixth empty cell, so the row
   ended in a gap that looked like a bug. Cells now size to what is in them
   and the row ends where the data does. */

.mt-stats,
:is(.stats, .kpis):not(table) {
  display: flex; flex-wrap: wrap; gap: 0;
  border: 1px solid var(--line); border-inline: 0;
  min-width: 0;
}
.mt-stat, .mt-stats > * {
  flex: 1 1 140px; min-width: 0;
  padding: var(--sp-3) var(--sp-4);
  border-inline-start: 1px solid var(--line);
}
.mt-stats > :first-child { border-inline-start: 0; }
.mt-stat .k, .mt-stat-k {
  display: block; margin-bottom: var(--sp-1);
  font-family: var(--pixel-label); font-size: 9px; line-height: 1.6; color: var(--ink-4);
}
.mt-stat .v, .mt-stat-v {
  display: block; font-family: var(--mono); font-size: 19px; line-height: 1.2;
  font-variant-numeric: tabular-nums; color: var(--ink);
}
.mt-stat-sub { display: block; margin-top: var(--sp-1); font-size: 11.5px; color: var(--ink-3); }

/* ══ 7 · tables ═════════════════════════════════════════════════════════════
   The desks all landed in the same place and so do we: a quiet header, a
   hairline between rows, figures in mono and right aligned, and a first and
   last cell that keep the page inset rather than butting the frame. */

.mt-surface table { border-collapse: collapse; width: 100%; min-width: 0; }
.mt-surface :is(thead th) {
  font-family: var(--pixel-label); font-size: 9px; font-weight: 400;
  color: var(--ink-4); text-align: start; white-space: nowrap;
  padding: var(--sp-2) var(--sp-3);
  border-bottom: 1px solid var(--line-solid);
  background: var(--s-canvas);
}
.mt-surface :is(tbody td) {
  padding: var(--sp-2) var(--sp-3);
  border-bottom: 1px solid var(--line-2);
  font-size: 12.5px; vertical-align: middle;
}
.mt-surface tbody tr:last-child td { border-bottom: 0; }
.mt-surface :is(th, td):first-child { padding-inline-start: var(--sp-4); }
.mt-surface :is(th, td):last-child  { padding-inline-end: var(--sp-4); }
/* numbers read down a column, so they align on their right edge */
.mt-surface :is(thead th:not(:first-child), tbody td:not(:first-child)) { text-align: end; }
.mt-surface :is(thead th[data-k]) { cursor: pointer; }
.mt-surface tbody tr:hover td { background: var(--s-raised); }
/* a table wider than its page scrolls inside itself and says so */
.mt-scroll { overflow-x: auto; overscroll-behavior-x: contain; min-width: 0; }
.mt-scroll:focus-visible { outline: 2px solid var(--accent-bright); outline-offset: -2px; }

/* ══ 8 · locked ═════════════════════════════════════════════════════════════
   A locked feature is present and fenced, never hidden. The padlock keeps its
   distance from the name, and the whole row says why in one word. */

.mt-lock {
  display: inline-flex; align-items: center; gap: var(--gap-icon-sm); flex: none;
  font-family: var(--pixel-label); font-size: 9px; line-height: 1;
  color: var(--ink-4); border: 1px solid var(--line);
  padding: 4px 8px 4px 6px; white-space: nowrap;
}
.mt-lock svg { width: 9px; height: auto; image-rendering: pixelated; }
.mt-locked-name { display: inline-flex; align-items: center; gap: var(--sp-3); min-width: 0; flex-wrap: wrap; }

/* ══ 9 · states ═════════════════════════════════════════════════════════════
   Empty, loading and error look like each other so the page does not appear
   to change shape while it waits. */

.mt-state {
  display: grid; place-items: center; gap: var(--sp-3);
  padding: var(--sp-10) var(--sp-4); text-align: center;
}
.mt-state p { margin: 0; color: var(--ink-3); font-size: 13px; max-width: 40ch; }
.mt-state .mt-state-k {
  font-family: var(--pixel-label); font-size: 9px; color: var(--ink-4);
}

/* The module loader inside the terminal: the figure, not a word in caps. */
.mt-mini {
  display: inline-flex; gap: 3px; align-items: flex-end; height: 10px;
}
.mt-mini i { width: 3px; height: 3px; background: var(--ink-4); animation: mtMini .9s steps(1,end) infinite; }
.mt-mini i:nth-child(2) { animation-delay: .15s; }
.mt-mini i:nth-child(3) { animation-delay: .3s; }
.mt-mini i:nth-child(4) { animation-delay: .45s; }
@keyframes mtMini { 0%,24% { background: var(--ink); height: 9px } 25%,100% { background: var(--ink-4); height: 3px } }

/* ══ 10 · the price tape ════════════════════════════════════════════════════
   A strip across the bottom of every page. It reserves its own height so the
   workspace pages give it room instead of hiding under it. */

html.mt-has-tape { --mx-tape-h: 26px; }
@media (min-width: 720px) { html.mt-has-tape { --mx-tape-h: 28px; } }

.mt-tape {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 940;
  display: flex; align-items: stretch;
  height: var(--mx-tape-h);
  background: var(--s-canvas);
  border-top: 1px solid var(--line);
  padding-bottom: env(safe-area-inset-bottom);
  contain: layout paint;
}
.mt-tape-lead {
  display: inline-flex; align-items: center; gap: var(--gap-icon-sm);
  flex: none; margin: 0; padding: 0 var(--sp-3);
  border: 0; border-inline-end: 1px solid var(--line);
  background: var(--s-canvas); cursor: pointer;
  font-family: var(--pixel-label); font-size: 9px; color: var(--ink-3);
}
.mt-tape-lead:hover { color: var(--ink); }
.mt-tape-lead-t { min-width: 4ch; text-align: start; }
.mt-tape-dot { width: 5px; height: 5px; background: var(--up); flex: none; animation: mtTapeDot 2s steps(1,end) infinite; }
@keyframes mtTapeDot { 0%,69% { opacity: 1 } 70%,100% { opacity: .25 } }

.mt-tape-win { flex: 1 1 0%; min-width: 0; overflow: hidden; position: relative; display: flex; }
/* The track and its rows fill the strip's height so every item centres in
   the bar. They used to size to their 11px line box and sit on the top edge
   with no headroom, while the Live control beside them sat centred. */
.mt-tape-track {
  display: flex; width: max-content; height: 100%;
  animation: mtTape var(--mt-tape-dur, 60s) linear infinite;
}
@keyframes mtTape { to { transform: translate3d(-50%, 0, 0); } }
.mt-tape:hover .mt-tape-track,
.mt-tape:focus-within .mt-tape-track,
.mt-tape.is-paused .mt-tape-track { animation-play-state: paused; }
.mt-tape.is-paused .mt-tape-dot { background: var(--ink-4); animation: none; }
.mt-tape.is-paused .mt-tape-win { overflow-x: auto; overscroll-behavior-x: contain; }

.mt-tape-row { display: flex; height: 100%; margin: 0; padding: 0; list-style: none; }
.mt-tape-dock { flex: none; display: flex; align-items: stretch; }
.mt-tape-dock:empty { display: none; }
.mt-tape-item {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  padding-inline: var(--sp-4);
  border-inline-end: 1px solid var(--line-2);
  font-size: 12.5px; line-height: 1; white-space: nowrap;
}
.mt-tape-item .sym { font-weight: 600; color: var(--ink); font-family: var(--mono); }
.mt-tape-item .px  { color: var(--ink-3); font-family: var(--mono); font-variant-numeric: tabular-nums; }
.mt-tape-item .ch  { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.mt-tape-item .ch.up   { color: var(--up); }
.mt-tape-item .ch.down { color: var(--down); }
.mt-tape-item .ch.flat { color: var(--ink-4); }

/* Without motion the tape is simply a row you can push along yourself. */
@media (prefers-reduced-motion: reduce) {
  .mt-tape-track { animation: none; width: auto; }
  .mt-tape-echo { display: none; }
  .mt-tape-win { overflow-x: auto; overscroll-behavior-x: contain; }
  .mt-tape-dot { animation: none; }
}
/* Phones get the tape too, but the dense pairs are the first thing to go if
   the strip would crowd a small screen's chrome. */
@media (max-width: 420px) { .mt-tape-lead { padding: 0 var(--sp-2); } }

/* ══ 11 · clearance ═════════════════════════════════════════════════════════
   Two things float above the page: the assistant and now the tape. Anything
   that scrolls has to end above both of them. */

html.mt-has-tape body.mx-shell:not(.mx-body-app) :is(.mt-surface, #app, .vk-list, .ad-main) {
  padding-bottom: calc(var(--mx-tape-h) + 72px);
}
html.mt-has-tape body.mx-shell.mx-body-app > :is(.mt-surface, .mx-app-main) {
  height: calc(100dvh - var(--mx-top, 130px) - var(--mx-tape-h)) !important;
  max-height: calc(100dvh - var(--mx-top, 130px) - var(--mx-tape-h)) !important;
}
html.mt-has-tape [class*="fab"]:not([class*="fab-item"]) { bottom: calc(var(--mx-tape-h) + 14px); }
html.mt-has-tape .mt-ai-panel { bottom: var(--mx-tape-h); }
/* a fixed status bar of the terminal's own sits directly on the tape */
html.mt-has-tape #md-statusbar { bottom: var(--mx-tape-h) !important; }

/* ══ 12 · the measured tight spots ══════════════════════════════════════════
   Not a guess. A probe walked every module at 1440px and at 390px and listed
   every pair of neighbours sitting on the same line less than eight pixels
   apart. These are the ones that were text against a mark, or a label against
   the control it names. The order book is deliberately left alone: its columns
   are a grid of figures read down, and space between them would be noise. */

/* news: the coin tags under a headline were three pixels apart */
.coin-tags { display: flex; flex-wrap: wrap; gap: 6px; }
.coin-tags > * { margin: 0 !important; }

/* breadcrumb crumbs, and the separator between them */
.mx-crumb ol, .mx-crumb ul { gap: 10px; }

/* two badges side by side: pattern name against its confidence */
.md-rs-card-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.md-rs-card-meta > * { margin: 0 !important; }

/* a chart legend swatch and the series it names */
.md-leg-item { display: inline-flex; align-items: center; gap: 8px; }

/* a label in front of the control it names */
.vk-grp { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; }
.vk-grp > .vk-k { margin: 0; }

/* the chrome buttons that pair a mark with a word */
.mx-fav.mx-fav-page, .mx-why, .mx-action { gap: 8px; }
.mx-tools { gap: 8px; }

/* toolbar: a segmented group then the label of the next group */
:is(.md-toolbar, [class*="-toolbar"], .md-bar, .md-controls) > :is(.lbl, .k, label) {
  margin-inline-start: 4px;
}

/* ══ 13 · figure strips that predate this file ══════════════════════════════
   Several modules built their own strip out of `.stat` cells in a plain flex
   row. On a phone the labels wrapped to two lines and the row went ragged,
   and on Volume Screener the row carried a sixth empty cell that read like a
   missing figure. Two columns on a phone, an even row above it, and cells
   that end where the data does. */

:is(#stats, .stats, .kpis, .kpi-strip):has(> :is(.stat, .kpi, .metric)) {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0;
}
@media (min-width: 720px) {
  :is(#stats, .stats, .kpis, .kpi-strip):has(> :is(.stat, .kpi, .metric)) {
    display: flex; flex-wrap: wrap;
  }
  :is(#stats, .stats, .kpis, .kpi-strip) > :is(.stat, .kpi, .metric) { flex: 1 1 130px; }
}
:is(#stats, .stats, .kpis, .kpi-strip) > :is(.stat, .kpi, .metric) {
  display: flex; flex-direction: column; justify-content: flex-start;
  gap: var(--sp-1); min-width: 0;
  padding: var(--sp-3) var(--sp-4);
  border-block-end: 1px solid var(--line-2);
}
:is(#stats, .stats, .kpis) > :is(.stat, .kpi, .metric) > .k { margin: 0; line-height: 1.5; }
:is(#stats, .stats, .kpis) > :is(.stat, .kpi, .metric) > .v { margin: 0; }
/* an empty trailing cell is a hole in the row, not a figure */
:is(#stats, .stats, .kpis) > :is(.stat, .kpi, .metric):empty { display: none; }

/* ══ 14 · a table that is wider than its page ═══════════════════════════════
   The screener and the flow modules are meant to be dense, so they keep every
   column and scroll inside their own box. No fade over the right edge: this is
   a desk, and dimming a figure to hint at a gesture costs more than it says. */

.mt-surface :is(#wrap, .table-wrap, [class*="-tablewrap"], .mt-scroll) {
  overscroll-behavior-x: contain;
}

/* A strip with an odd number of figures leaves a hole in the bottom right of
   a two column grid. The last one takes the whole row instead. */
@media (max-width: 719px) {
  :is(#stats, .stats, .kpis) > :is(.stat, .kpi, .metric):last-child:nth-child(odd) {
    grid-column: 1 / -1;
  }
}

/* ══ 15 · rows that spilled ═════════════════════════════════════════════════
   Measured at 390px. Each of these is a single row of controls or figures
   whose children refuse to shrink, so the row grew past its box: a label and
   its select, a group of buttons pushed right by margin-left auto, a strip of
   dates. Two answers, chosen per row: a group of controls wraps, and a strip
   meant to be read along scrolls inside itself. */
@media (max-width: 719px) {
  .mt-surface :is(.ctrl-group, .section-tools, .lw-bar, .sectionbar) {
    flex-wrap: wrap; min-width: 0;
  }
  .mt-surface :is(.md-book-metrics, .md-mor-history-list, .md-toolbar-mid) {
    min-width: 0; max-width: 100%;
    overflow-x: auto; overscroll-behavior-x: contain;
  }
  .mt-surface .status { min-width: 0; }
  .mt-surface .status > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
}

/* ══ 16 · reach on a touch screen ═══════════════════════════════════════════
   A 26px button is a miss on a phone. Controls grow to 32px where the pointer
   is coarse, which is the floor the rest of the terminal already keeps. Only a
   minimum, so nothing that is already comfortable changes. */
@media (pointer: coarse) {
  .mt-surface :is(button, select, .btn, .sel, .seg-btn, .cv-btn, .plm-tab,
                  .md-layer-btn, .lw-btn, .sam-btn-go, input:not([type="checkbox"]):not([type="radio"]):not([type="range"])) {
    min-height: 32px;
  }
  .mt-surface :is(input[type="checkbox"], input[type="radio"]) { width: 18px; height: 18px; }
}

/* Two rows that still spilled after section 15, each for its own reason.

   .ctrl-group becomes a grid below 800px on the pages that use a command bar,
   so telling it to wrap does nothing; its children needed permission to be
   narrower than their content instead.

   .vk-stack is a proportional bar of contributors. Every segment carried a 2px
   floor, and with thirty of them the floors plus the gaps added up to more than
   the bar. One pixel is still a visible segment and the sum now fits. */
@media (max-width: 719px) {
  .mt-surface :is(.ctrl-group, .section-tools) > * { min-width: 0; max-width: 100%; }
  .mt-surface .vk-stack { min-width: 0; }
  .mt-surface .vk-stack > button { min-width: 1px; }
}
