@font-face {
  font-family: "Space Grotesk";
  src: url("/fonts/space-grotesk-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Space Grotesk";
  src: url("/fonts/space-grotesk-500.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Space Grotesk";
  src: url("/fonts/space-grotesk-700.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "IBM Plex Mono";
  src: url("/fonts/ibm-plex-mono-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "IBM Plex Mono";
  src: url("/fonts/ibm-plex-mono-500.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "IBM Plex Mono";
  src: url("/fonts/ibm-plex-mono-600.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

:root {
  color-scheme: dark;
  --canvas: #000000;
  --canvas-deep: #050505;
  --surface-1: #0E0E0E;
  --surface-2: #161616;
  --surface-3: #1F1F1F;
  --surface-float: #232323;
  --surface-modal: #262626;
  --surface-hover: #1E1E1E;
  --surface-hover-high: #2C2C2C;
  --surface-selected: #242424;
  --border-subtle: #1C1C1C;
  --border: #2A2A2A;
  --border-strong: #404040;
  --border-control: #4A4A4A;
  --text: #F2F2F2;
  --text-strong: #FFFFFF;
  --muted: #A8A8A8;
  --subtle: #8A8A8A;
  --accent: #F2F2F2;
  --accent-strong: #FFFFFF;
  --accent-ink: #000000;
  --accent-border: #5A5A5A;
  /* Retired as a hue. Kept as a token so existing references resolve,
     but retargeted to the value ladder: chroma is reserved for price
     direction, order side, pending, and destructive states only. */
  --info: #D6D6D6;
  --warning: #EFBE64;
  --danger: #E4505A;
  --danger-strong: #FF8C93;
  --buy: #15C393;
  --sell: #E05C64;
  --up: #2BD5A6;
  --down: #F26D77;
  --focus: #FFFFFF;
  --backdrop: rgb(0 0 0 / 0.72);
  --shadow-panel: inset 0 1px 0 rgba(255,255,255,0.05), 0 1px 2px rgba(0,0,0,0.55), 0 3px 8px rgba(0,0,0,0.35);
  --shadow-float: inset 0 1px 0 rgba(255,255,255,0.07), 0 0 0 1px #060606, 0 12px 28px rgba(0,0,0,0.60), 0 3px 8px rgba(0,0,0,0.45);
  --shadow-modal: inset 0 1px 0 rgba(255,255,255,0.09), 0 0 0 1px #050505, 0 32px 72px rgba(0,0,0,0.70), 0 10px 24px rgba(0,0,0,0.50);
  --shadow-stamp: inset 0 1px 0 rgba(255,255,255,0.18), 0 2px 8px rgba(0,0,0,0.40);
  --depth-buy: rgb(21 195 147 / .08);
  --depth-sell: rgb(224 92 100 / .08);
  --selection: rgba(242, 242, 242, 0.24);
  --hatch: repeating-linear-gradient(135deg, transparent 0 4px, color-mix(in srgb, var(--muted) 20%, transparent) 4px 5px);
  --chart-bg: #0C0C0C;
  --chart-grid: rgb(138 138 138 / .13);
  --chart-text: #8A8A8A;
  --candle-up: #15C393;
  --candle-down: #E05C64;
  --volume-up: rgb(21 195 147 / 0.42);
  --volume-down: rgb(224 92 100 / 0.40);
  --crosshair: rgba(242, 242, 242, 0.5);
  --crosshair-label-bg: #2A2A2A;
  --line: 1px;
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-7: 32px;
  --space-8: 40px;
  --space-9: 48px;
  --space-10: 64px;
  --radius-plate: 0;
  --radius-control: 4px;
  --radius-menu: 6px;
  --font-sans: "Space Grotesk", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-data: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, "Cascadia Mono", "Segoe UI Mono", Consolas, monospace;
  --type-micro: 11px;
  --type-2xs: 11px;
  --type-xs: 12px;
  --type-sm: 13px;
  --type-body: 14px;
  --type-control: 12px;
  --type-title: 15px;
  --type-market: 20px;
  --type-statement: 22px;
  --type-masthead: 26px;
  --type-heading: 26px;
  --weight-medium: 500;
  --weight-semibold: 600;
  --weight-bold: 700;
  --tracking-tight: -0.025em;
  --tracking-label: 0.06em;
  --tracking-brand: 0.14em;
  --leading-tight: 1.15;
  --leading-body: 1.5;
  --control-height: 44px;
  --control-height-compact: 32px;
  --control-height-touch: 48px;
  --header-height: 60px;
  --environment-height: 18px;
  --marketbar-height: 80px;
  --seal-size: 28px;
  --chart-attribution-height: 28px;
  --terminal-ticket-column: 360px;
  --terminal-book-min: 300px;
  --terminal-top: var(--header-height);
  --panel-header-height: 36px;
  --panel-padding: var(--space-4);
  --workspace-padding: var(--space-5);
  --workspace-max: 1920px;
  --content-measure: 72ch;
  --table-min-width: 720px;
  --terminal-chart-row: 340px;
  --terminal-ledger-row: 300px;
  --terminal-orders-row: 240px;
  --spinner-size: 24px;
  --scrollbar-size: 8px;
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --duration-fast: 120ms;
  --duration-base: 180ms;
  font-family: var(--font-sans);
  color: var(--text);
  background: var(--canvas);
  font-synthesis: none;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  background: var(--canvas);
  scroll-behavior: auto;
  scrollbar-color: var(--border-strong) var(--canvas);
  scrollbar-width: thin;
}

body {
  margin: 0;
  min-width: 320px;
  min-height: 100vh;
  background: var(--canvas);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: var(--type-body);
  font-variant-numeric: tabular-nums;
  line-height: var(--leading-body);
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
}

button,
input,
select,
textarea {
  font: inherit;
}

button {
  cursor: pointer;
}

button:disabled {
  cursor: not-allowed;
  opacity: 0.46;
}

a {
  color: inherit;
  text-underline-offset: var(--space-1);
}

p {
  margin-block: 0 var(--space-3);
}

::selection {
  background: var(--selection);
  color: var(--text-strong);
}

::-webkit-scrollbar {
  width: var(--scrollbar-size);
  height: var(--scrollbar-size);
}

::-webkit-scrollbar-track {
  background: var(--canvas);
}

::-webkit-scrollbar-thumb {
  border: calc(var(--line) * 2) solid var(--canvas);
  border-radius: var(--radius-control);
  background: var(--border-strong);
}

[hidden] {
  display: none !important;
}

:focus-visible {
  outline: calc(var(--line) * 2) solid var(--focus);
  outline-offset: calc(var(--line) * 2);
}

.skip-link {
  position: fixed;
  z-index: 100;
  top: var(--space-2);
  left: var(--space-4);
  transform: translateY(calc(-100% - var(--space-4)));
  border-radius: var(--radius-plate);
  background: var(--focus);
  color: var(--accent-ink);
  padding: var(--space-3) var(--space-4);
  font-weight: var(--weight-bold);
  text-decoration: none;
  transition: transform var(--duration-base) var(--ease-out);
}

.skip-link:focus {
  transform: translateY(0);
}

/* Compact exchange chrome */
.app-header {
  position: sticky;
  z-index: 30;
  top: 0;
  display: flex;
  align-items: center;
  gap: var(--space-5);
  height: var(--header-height);
  padding: 0 var(--workspace-padding);
  border-bottom: var(--line) solid var(--border);
  background: #101010;
  box-shadow: 0 1px 0 #000000, 0 2px 6px rgba(0,0,0,0.45);
  font-family: var(--font-data);
}

.brand {
  display: flex;
  align-items: center;
  flex: 0 0 auto;
  gap: var(--space-3);
  min-width: max-content;
  color: var(--text-strong);
  text-decoration: none;
}

.brand-mark {
  display: grid;
  place-items: center;
  width: var(--seal-size);
  height: var(--seal-size);
  color: var(--text-strong);
}

.brand-mark svg {
  display: block;
}

.brand strong,
.brand small {
  display: block;
}

.brand strong {
  font: var(--weight-bold) var(--type-masthead) / 0.9 var(--font-data);
  letter-spacing: var(--tracking-brand);
}

.brand small {
  margin-top: var(--space-1);
  color: var(--subtle);
  font-family: var(--font-data);
  font-size: var(--type-2xs);
  font-weight: var(--weight-semibold);
  letter-spacing: calc(var(--tracking-brand) * 1.5);
  line-height: var(--leading-tight);
}

#primary-nav {
  display: flex;
  align-self: stretch;
  align-items: stretch;
  gap: 0;
  min-width: 0;
  overflow-x: auto;
  border-left: var(--line) solid var(--border-subtle);
  scrollbar-width: none;
}

#primary-nav::-webkit-scrollbar {
  display: none;
}

#primary-nav button {
  position: relative;
  flex: 0 0 auto;
  min-width: max-content;
  height: 100%;
  border: 0;
  border-right: var(--line) solid var(--border-subtle);
  border-radius: 0;
  background: transparent;
  color: var(--muted);
  padding: 0 var(--space-3);
  font: var(--weight-semibold) var(--type-control) / 1 var(--font-data);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  transition:
    color var(--duration-fast) var(--ease-out),
    background-color var(--duration-fast) var(--ease-out);
}

#primary-nav button::after {
  content: "";
  position: absolute;
  right: var(--space-3);
  bottom: 0;
  left: var(--space-3);
  height: calc(var(--line) * 2);
  transform: scaleX(0);
  transform-origin: center;
  background: var(--accent);
  transition: transform var(--duration-base) var(--ease-out);
}

#primary-nav button:hover {
  background: var(--surface-2);
  color: var(--text);
}

#primary-nav button.active {
  background: color-mix(in srgb, var(--accent) 5%, var(--surface-1));
  color: var(--text-strong);
}

#primary-nav button.active::after {
  transform: scaleX(1);
}

.account-actions {
  display: flex;
  align-items: center;
  flex: 0 1 auto;
  gap: var(--space-2);
  min-width: 0;
  margin-left: auto;
}

.environment-rail {
  position: sticky;
  z-index: 25;
  top: var(--header-height);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-6);
  height: var(--environment-height);
  overflow-x: auto;
  border-top: var(--line) solid var(--border-strong);
  border-bottom: var(--line) solid var(--border-strong);
  background: var(--canvas-deep);
  color: var(--warning);
  font: var(--weight-semibold) var(--type-micro) / 1 var(--font-data);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  white-space: nowrap;
  scrollbar-width: none;
}

.environment-rail::before,
.environment-rail::after {
  content: "";
  position: absolute;
  left: var(--space-2);
  width: var(--space-2);
  height: var(--space-2);
  border-left: var(--line) solid var(--warning);
  pointer-events: none;
}

.environment-rail::before {
  top: var(--space-1);
  border-top: var(--line) solid var(--warning);
}

.environment-rail::after {
  bottom: var(--space-1);
  border-bottom: var(--line) solid var(--warning);
}

.environment-rail::-webkit-scrollbar {
  display: none;
}

.environment-rail span {
  color: var(--subtle);
}

.environment-rail span:first-child,
.environment-rail span:last-child {
  color: var(--warning);
}

/* Workspace and feedback states */
#workspace {
  width: 100%;
  max-width: var(--workspace-max);
  min-height: calc(100vh - var(--terminal-top));
  margin: 0 auto;
  padding: var(--workspace-padding);
}

#app {
  min-width: 0;
}

.center-state {
  display: grid;
  place-content: center;
  justify-items: center;
  gap: var(--space-3);
  min-height: 55vh;
  color: var(--muted);
  text-align: center;
}

.center-state p {
  margin: 0;
}

.spinner {
  width: var(--spinner-size);
  height: var(--spinner-size);
  border: calc(var(--line) * 2) solid var(--border);
  border-top-color: var(--accent);
  border-radius: var(--radius-control);
  animation: spin 800ms linear infinite;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

/* Controls */
.button,
.icon-button,
.segmented button,
.tabs button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--control-height);
  border: var(--line) solid var(--border-control);
  border-radius: var(--radius-control);
  background: var(--surface-2);
  color: var(--text);
  padding: 0 var(--space-4);
  /* Controls carry human words, so they speak in sans sentence case. This
     rule previously set mono uppercase, which made every button in the app
     read as a terminal readout. Side tabs (BUY/SELL) keep their caps stamp
     via the later, more specific .side-tabs rule. */
  font-family: var(--font-sans);
  font-size: var(--type-sm);
  font-weight: var(--weight-medium);
  letter-spacing: 0.01em;
  line-height: 1;
  text-align: center;
  text-decoration: none;
  text-transform: none;
  white-space: nowrap;
  transition:
    border-color var(--duration-fast) var(--ease-out),
    background-color var(--duration-fast) var(--ease-out),
    color var(--duration-fast) var(--ease-out),
    transform var(--duration-fast) var(--ease-out);
}

.button:hover:not(:disabled),
.icon-button:hover:not(:disabled),
.segmented button:hover:not(:disabled),
.tabs button:hover:not(:disabled) {
  border-color: var(--border-strong);
  background: var(--surface-hover);
  color: var(--text-strong);
}

.button:active:not(:disabled),
.icon-button:active:not(:disabled),
.segmented button:active:not(:disabled),
.tabs button:active:not(:disabled) {
  transform: translateY(var(--line));
}

.button.primary {
  border-color: var(--accent);
  background: var(--accent);
  color: var(--accent-ink);
  font-weight: var(--weight-bold);
  box-shadow: var(--shadow-stamp);
}

.button.primary:hover:not(:disabled) {
  border-color: var(--accent-strong);
  background: var(--accent-strong);
  color: var(--accent-ink);
}

.button.secondary {
  background: var(--surface-2);
}

.button.danger {
  border-color: color-mix(in srgb, var(--danger) 68%, var(--border));
  background: color-mix(in srgb, var(--danger) 6%, transparent);
  color: var(--danger-strong);
}

.button.danger:hover:not(:disabled) {
  border-color: var(--danger);
  background: color-mix(in srgb, var(--danger) 12%, var(--surface-1));
  color: var(--danger-strong);
}

.button.compact {
  min-height: var(--control-height-compact);
  padding: 0 var(--space-3);
  font-size: var(--type-sm);
}

#nav-dropdown-trigger::after {
  content: "";
  width: 0;
  height: 0;
  margin-left: 8px;
  border-inline: 4px solid transparent;
  border-top: 5px solid currentColor;
}


.icon-button {
  width: var(--control-height);
  padding: 0;
  background: transparent;
  font-family: var(--font-data);
  font-size: var(--type-market);
  font-weight: var(--weight-medium);
}

.text-button {
  min-height: var(--control-height-compact);
  border: 0;
  background: transparent;
  color: var(--accent);
  padding: 0 var(--space-2);
  font-weight: var(--weight-semibold);
}

.text-button:hover {
  color: var(--accent-strong);
  text-decoration: underline;
}

.market-link {
  min-height: var(--control-height);
  border: 0;
  background: transparent;
  color: var(--text-strong);
  padding: 0;
  font: var(--weight-bold) var(--type-control) / 1 var(--font-data);
  text-decoration: none;
}

.market-link:hover {
  color: var(--accent);
}

.favorite-toggle {
  min-width: 64px;
  height: 28px;
  border: 1px solid #4A4A4A;
  border-radius: 4px;
  background: transparent;
  color: #A8A8A8;
  padding: 0 10px;
  font: 600 11px / 1 var(--font-data);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
  transition:
    border-color var(--duration-fast) var(--ease-out),
    background-color var(--duration-fast) var(--ease-out),
    color var(--duration-fast) var(--ease-out);
}

.favorite-toggle:hover {
  border-color: var(--border-strong);
  background: var(--surface-1);
  color: var(--text);
}

.favorite-toggle.active {
  border-color: rgba(43,213,166,0.45);
  background: rgba(43,213,166,0.08);
  color: #2BD5A6;
}

.markets-panel > .panel-body {
  padding: 0;
}

.markets-topbar {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-3) var(--panel-padding);
  border-bottom: var(--line) solid var(--border-strong);
  background: var(--surface-2);
}

.market-category-filter {
  display: grid;
  gap: var(--space-1);
  width: min(220px, 100%);
  color: var(--subtle);
  font: var(--weight-semibold) var(--type-micro) / 1 var(--font-data);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
}

.market-category-select,
.markets-topbar .market-search {
  min-height: var(--control-height);
  border: var(--line) solid var(--border-strong);
  border-radius: var(--radius-plate);
  background: var(--surface-1);
}

.market-category-select {
  font: var(--weight-semibold) var(--type-sm) / 1 var(--font-data);
  letter-spacing: normal;
  text-transform: none;
}

.markets-topbar .market-search {
  width: min(320px, 100%);
}

.markets-panel .empty-state {
  margin: var(--space-4);
}

@media (max-width: 599px) {
  .markets-topbar {
    align-items: stretch;
    flex-direction: column;
  }

  .market-category-filter,
  .markets-topbar .market-search {
    width: 100%;
  }
}

.hide-zero {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  color: var(--muted);
  font-size: var(--type-body);
  cursor: pointer;
}

.hide-zero input {
  accent-color: var(--accent);
}




.address-book-form {
  display: grid;
  grid-template-columns: minmax(90px, .6fr) minmax(100px, .8fr) minmax(160px, 2fr) auto;
  gap: var(--space-2);
  margin-block-end: var(--space-3);
}

.address-book-form input,
.address-book-form select {
  min-height: var(--control-height);
}

.status-chip {
  display: inline-flex;
  align-items: center;
  min-height: var(--space-6);
  border: var(--line) solid color-mix(in srgb, currentColor 42%, transparent);
  border-radius: var(--radius-control);
  background: color-mix(in srgb, currentColor 9%, transparent);
  padding: 0 var(--space-2);
  font-family: var(--font-data);
  font-size: var(--type-micro);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-label);
  line-height: 1;
  text-transform: uppercase;
  white-space: nowrap;
}

.status-chip.neutral {
  color: var(--muted);
}

.status-chip.good {
  color: var(--buy);
}

.status-chip.warning {
  color: var(--warning);
}

.status-chip.danger {
  color: var(--danger);
}

.status-chip.info {
  color: var(--info);
}

.sandbox-badge {
  display: inline-flex;
  align-items: center;
  min-height: var(--space-6);
  border: var(--line) solid color-mix(in srgb, var(--warning) 68%, var(--border));
  border-radius: var(--radius-control);
  color: var(--warning);
  padding: 0 var(--space-2);
  font: var(--weight-semibold) var(--type-micro) / 1 var(--font-data);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  white-space: nowrap;
}

/* Page hierarchy */
.view-heading {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-6);
  margin: var(--space-2) 0 var(--space-6);
}

.view-heading > div:first-child {
  min-width: 0;
}

.view-heading h1 {
  margin: 0;
  color: var(--text-strong);
  font-size: clamp(24px, 2.3vw, var(--type-heading));
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-tight);
  line-height: var(--leading-tight);
}

.view-heading p {
  max-width: var(--content-measure);
  margin: var(--space-2) 0 0;
  color: var(--muted);
  font-size: var(--type-body);
}

.eyebrow {
  margin: 0 0 var(--space-2);
  color: var(--subtle);
  font: var(--weight-semibold) var(--type-micro) / var(--leading-tight) var(--font-data);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
}

.heading-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-2);
  min-width: 0;
  overflow-wrap: anywhere;
}


/* Raised plates establish the workspace elevation system. */
.panel {
  min-width: 0;
  overflow: clip;
  border: var(--line) solid #2A2A2A;
  border-radius: var(--radius-plate);
  background: var(--surface-2);
  box-shadow: var(--shadow-panel);
}

.panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  min-height: var(--panel-header-height);
  padding: var(--space-2) var(--panel-padding);
  border-bottom: var(--line) solid var(--border-strong);
  background: var(--surface-3);
}

.panel-header h2,
.panel-header h3 {
  margin: 0;
  color: var(--text-strong);
  font-size: var(--type-title);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-tight);
}

.panel-body {
  min-width: 0;
  padding: var(--panel-padding);
  background: var(--surface-2);
}

.panel-body:has(> .table-scroll:only-child) {
  padding: 0;
}

.panel-body > .table-scroll:only-child {
  border: 0;
}

.panel-body > form:not(:first-child) {
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: var(--line) solid var(--border);
}

.panel-note {
  margin: 0;
  border-top: var(--line) solid var(--border);
  color: var(--muted);
  padding: var(--space-3) var(--panel-padding);
  font-size: var(--type-sm);
}

.grid-2 {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-3);
}

.grid-3 {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-3);
}

.stack {
  display: grid;
  gap: var(--space-3);
}

/* Dense ledgers and market tables */
.table-scroll {
  max-width: 100%;
  overflow: auto;
  overscroll-behavior-inline: contain;
  border: var(--line) solid var(--border-strong);
  background: var(--surface-1);
  scrollbar-color: var(--border-strong) transparent;
}

.table-scroll:focus-visible {
  outline: calc(var(--line) * 2) solid var(--focus);
  outline-offset: calc(var(--line) * -2);
}

.data-table {
  width: 100%;
  min-width: var(--table-min-width);
  border-spacing: 0;
  border-collapse: separate;
  color: var(--text);
  font-size: var(--type-body);
}

.data-table th {
  position: sticky;
  z-index: 2;
  top: 0;
  border-bottom: var(--line) solid var(--border-strong);
  height: 28px;
  background: var(--surface-3);
  color: var(--subtle);
  font-family: var(--font-sans);
  padding: 6px 12px;
  font-size: 11px;
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-label);
  line-height: 1;
  text-align: left;
  text-transform: none;
  white-space: nowrap;
}

.data-table td {
  height: 40px;
  border-bottom: var(--line) solid var(--border);
  background: var(--surface-1);
  color: var(--text);
  padding: var(--space-2) var(--space-3);
  vertical-align: middle;
  white-space: nowrap;
}

.data-table th + th,
.data-table td + td {
  border-left: var(--line) solid var(--border-subtle);
}

.data-table td.num {
  color: var(--text-strong);
  font-weight: var(--weight-medium);
}

.data-table tbody tr:last-child td {
  border-bottom: 0;
}

.data-table tbody tr {
  transition: background-color var(--duration-fast) var(--ease-out);
}

.data-table tbody tr:hover td,
.data-table tbody tr:focus-within td {
  background: var(--surface-hover);
}

.data-table tbody tr:has(.market-link) {
  cursor: pointer;
}

.num {
  font-family: var(--font-data);
  font-variant-numeric: tabular-nums slashed-zero;
  text-align: right !important;
}

.positive {
  color: var(--up);
}

.negative {
  color: var(--down);
}

.muted {
  color: var(--muted);
}

code,
.identifier {
  font-family: var(--font-data);
  font-variant-ligatures: none;
}

.identifier {
  display: inline-block;
  max-width: 18rem;
  overflow: hidden;
  color: var(--muted);
  font-size: var(--type-xs);
  line-height: 1.4;
  text-overflow: ellipsis;
  vertical-align: middle;
  white-space: nowrap;
}

.empty-state {
  display: grid;
  place-content: center;
  justify-items: center;
  gap: var(--space-4);
  min-height: 132px;
  padding: var(--space-8) var(--space-6);
  color: var(--muted);
  text-align: center;
}

.empty-state-copy {
  display: grid;
  justify-items: center;
  gap: var(--space-2);
  max-width: var(--content-measure);
}

.empty-state h3 {
  margin: 0;
  color: var(--text-strong);
  font-size: var(--type-title);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-tight);
  line-height: var(--leading-tight);
}

.empty-state p {
  max-width: var(--content-measure);
  margin: 0;
  overflow-wrap: anywhere;
  line-height: var(--leading-body);
}

.empty-state-action {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-2);
  margin-top: var(--space-1);
}

/* Premium three-column trading terminal */
.terminal-shell {
  min-width: 0;
  margin: calc(var(--space-2) * -1) calc(var(--workspace-padding) * -1) calc(var(--workspace-padding) * -1);
  border-top: var(--line) solid var(--border);
  border-bottom: var(--line) solid var(--border);
  background: var(--canvas-deep);
}

.terminal-marketbar {
  display: flex;
  align-items: stretch;
  min-height: var(--marketbar-height);
  overflow-x: auto;
  border-bottom: calc(var(--line) * 3) double var(--border-strong);
  background: var(--surface-1);
  scrollbar-width: thin;
}

.market-identity {
  display: grid;
  align-content: center;
  flex: 1 0 240px;
  gap: var(--space-1);
  min-width: 240px;
  padding: var(--space-2) var(--space-4);
  border-right: var(--line) solid var(--border);
}

.market-identity .eyebrow {
  margin-bottom: 0;
}

.market-identity > div {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
}

.market-identity h1 {
  margin: 0;
  color: var(--text-strong);
  font: var(--weight-semibold) var(--type-market) / var(--leading-tight) var(--font-data);
  letter-spacing: var(--tracking-tight);
  white-space: nowrap;
}

.feed-state {
  border-left: var(--line) solid var(--border-strong);
  color: var(--danger-strong);
  padding-left: var(--space-2);
  font: var(--weight-semibold) var(--type-micro) / 1 var(--font-data);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  white-space: nowrap;
}

.feed-state.current {
  color: var(--accent);
}

.market-stat {
  display: grid;
  align-content: center;
  flex: 0 1 auto;
  gap: var(--space-1);
  min-width: 88px;
  padding: var(--space-2) var(--space-3);
  border-left: var(--line) solid var(--border-subtle);
}

.market-stat > span {
  overflow: hidden;
  color: var(--subtle);
  font: var(--weight-bold) var(--type-micro) / 1 var(--font-data);
  letter-spacing: var(--tracking-label);
  text-overflow: ellipsis;
  text-transform: uppercase;
  white-space: nowrap;
}

.market-stat > strong {
  overflow: hidden;
  color: var(--muted);
  font: var(--weight-medium) var(--type-sm) / var(--leading-tight) var(--font-data);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.market-stat.primary {
  flex-basis: 190px;
  min-width: 170px;
  border-left: calc(var(--line) * 2) solid var(--accent);
  background: color-mix(in srgb, var(--accent) 4%, var(--surface-1));
}

.market-stat.primary > strong {
  color: var(--accent);
  font-size: var(--type-statement);
  font-weight: var(--weight-semibold);
}

.terminal-controls {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  flex: 0 0 auto;
  gap: var(--space-2);
  min-width: max-content;
  margin-left: auto;
  padding: var(--space-2) var(--space-3);
  border-left: var(--line) solid var(--border);
}

.terminal-controls > select {
  width: auto;
  min-width: 112px;
}

.terminal-grid {
  display: grid;
  grid-template-areas:
    "chart"
    "ticket"
    "book"
    "trades"
    "orders";
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto;
  gap: 6px;
  padding: 6px;
  background: #000000;
}

.terminal-grid > .panel {
  display: flex;
  flex-direction: column;
  min-height: 0;
  border: var(--line) solid #262626;
  border-radius: 0;
}

.terminal-grid > .panel > .panel-body {
  flex: 1 1 auto;
  min-height: 0;
}

.chart-panel {
  grid-area: chart;
}

.book-panel {
  grid-area: book;
}

.trades-panel {
  grid-area: trades;
}

.terminal-orders {
  grid-area: orders;
}

.trade-ticket {
  position: static;
  grid-area: ticket;
  align-self: start;
  width: 100%;
  max-height: none;
}

.chart-panel .panel-header {
  flex: 0 0 auto;
}

.chart-panel .panel-body {
  display: flex;
  flex-direction: column;
  padding: 0;
  background: var(--canvas-deep);
}

.chart-toolbar {
  display: flex;
  align-items: center;
  gap: var(--space-1);
}

.chart-toolbar button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--control-height-compact);
  min-height: var(--control-height-compact);
  border: var(--line) solid transparent;
  border-radius: var(--radius-control);
  background: transparent;
  color: var(--muted);
  padding: 0 var(--space-2);
  font-family: var(--font-data);
  font-size: var(--type-xs);
  font-weight: var(--weight-semibold);
  transition:
    color var(--duration-fast) var(--ease-out),
    background-color var(--duration-fast) var(--ease-out),
    border-color var(--duration-fast) var(--ease-out);
}

.chart-toolbar button:hover {
  border-color: var(--border);
  background: var(--surface-hover-high);
  color: var(--text);
}

.chart-toolbar button.active,
.chart-toolbar button[aria-pressed="true"] {
  border-color: color-mix(in srgb, var(--accent) 35%, var(--border));
  background: var(--surface-selected);
  color: var(--accent);
}

.chart-legend {
  display: flex;
  align-items: center;
  flex: 0 0 auto;
  gap: var(--space-4);
  height: 28px;
  min-height: 28px;
  overflow-x: auto;
  border-bottom: var(--line) solid var(--border-subtle);
  background: var(--surface-1);
  color: var(--muted);
  padding: 0 12px;
  font: var(--weight-medium) 11px / 1 var(--font-data);
  font-variant-numeric: tabular-nums slashed-zero;
  white-space: nowrap;
  scrollbar-width: none;
}

.chart-legend::-webkit-scrollbar {
  display: none;
}

.chart-legend > span {
  display: inline-flex;
  align-items: baseline;
  gap: var(--space-1);
}

.chart-legend small {
  color: var(--subtle);
  font-size: inherit;
}

.chart-legend strong,
.chart-legend b {
  color: var(--text);
  font-weight: var(--weight-semibold);
}

.chart-legend .volume-figure {
  color: #A8A8A8;
}

.chart-surface {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  overflow: hidden;
  background: #050505;
  cursor: crosshair;
  isolation: isolate;
}


.chart-surface > div,
.chart-surface canvas {
  display: block;
  width: 100%;
  height: 100%;
}

.chart-empty {
  position: absolute;
  z-index: 2;
  inset: 0;
  display: grid;
  place-content: center;
  color: var(--muted);
  padding: var(--space-6);
  font-size: var(--type-sm);
  text-align: center;
  pointer-events: none;
}
.depth-chart {
  display: block;
  width: 100%;
  height: 100%;
}

.depth-area.bid {
  fill: color-mix(in srgb, var(--buy) 16%, transparent);
}

.depth-area.ask {
  fill: color-mix(in srgb, var(--sell) 14%, transparent);
}

.depth-line {
  fill: none;
  stroke-width: 1.5;
}

.depth-line.bid {
  stroke: var(--buy);
}

.depth-line.ask {
  stroke: var(--sell);
}

.depth-mid {
  stroke: var(--border-strong);
  stroke-dasharray: 3 4;
}

.depth-tick {
  fill: var(--subtle);
  font: var(--weight-medium) var(--type-2xs) / 1 var(--font-data);
}

.chart-surface > .chart-limited {
  position: absolute;
  z-index: 5;
  top: var(--space-2);
  left: var(--space-2);
  width: max-content;
  height: auto;
  transform: none;
  border: var(--line) solid var(--border-control);
  border-top: calc(var(--line) * 2) solid var(--accent);
  border-radius: var(--radius-plate);
  background: var(--surface-2);
  color: var(--muted);
  padding: var(--space-2) var(--space-3);
  font: var(--weight-semibold) var(--type-micro) / 1 var(--font-data);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  white-space: nowrap;
  pointer-events: none;
}


.chart-attribution {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  flex: 0 0 var(--chart-attribution-height);
  height: var(--chart-attribution-height);
  min-height: var(--chart-attribution-height);
  margin: 0;
  overflow-x: auto;
  border-top: var(--line) solid var(--border-subtle);
  background: var(--surface-1);
  color: var(--subtle);
  padding: var(--space-1) var(--space-3);
  font: var(--weight-medium) var(--type-micro) / 1 var(--font-data);
  letter-spacing: calc(var(--tracking-label) / 2);
  white-space: nowrap;
  scrollbar-width: none;
}

.chart-attribution a {
  color: var(--muted);
}

.chart-attribution a:hover {
  color: #FFFFFF;
}

.book-panel .panel-body {
  overflow: auto;
  padding: 0;
  background: var(--surface-1);
}

.book {
  display: flex;
  flex-direction: column;
  min-height: 100%;
  background: var(--surface-1);
}

.book-header,
.book-row {
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr) minmax(44px, 0.72fr);
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  min-width: 0;
  padding: 0 var(--space-3);
  font-family: var(--font-data);
  font-variant-numeric: tabular-nums slashed-zero;
}

.book-header {
  position: sticky;
  z-index: 2;
  top: 0;
  height: 28px;
  min-height: 28px;
  border-bottom: var(--line) solid var(--border);
  background: var(--surface-2);
  color: var(--subtle);
  font-size: 11px;
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
}

.book-row {
  position: relative;
  min-height: 24px;
  overflow: hidden;
  border: 0;
  border-bottom: var(--line) solid color-mix(in srgb, var(--border-subtle) 72%, transparent);
  border-radius: 0;
  background: transparent;
  color: var(--text);
  font-size: 12px;
  line-height: 1;
  text-align: left;
}

.book-row::before {
  content: "";
  position: absolute;
  z-index: 0;
  top: var(--space-1);
  right: 0;
  bottom: var(--space-1);
  width: var(--depth, 0%);
  border-left: var(--line) solid var(--buy);
  background: var(--depth-buy);
  pointer-events: none;
}

.book-row.negative::before {
  right: auto;
  left: 0;
  border-right: var(--line) solid var(--sell);
  border-left: 0;
  background: var(--depth-sell);
}

.book-row > span {
  position: relative;
  z-index: 1;
  overflow: hidden;
  color: var(--text);
  text-align: right;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.book-header > span {
  text-align: right;
}

.book-header > span:first-child,
.book-row > span:first-child {
  text-align: left;
}

.book-row.positive > span:first-child {
  color: var(--buy);
  font-weight: var(--weight-semibold);
}

.book-row.negative > span:first-child {
  color: var(--sell);
  font-weight: var(--weight-semibold);
}

.book-row:hover,
.book-row:focus-visible {
  background: var(--surface-hover);
}

.book-spread {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: var(--space-9);
  border-block: calc(var(--line) * 3) double var(--border-strong);
  background: var(--surface-2);
  color: var(--muted);
  padding: 0 var(--space-3);
  font: var(--weight-medium) var(--type-xs) / 1 var(--font-data);
}

.book-spread strong {
  color: var(--text-strong);
  font-weight: var(--weight-semibold);
}

.book-side {
  min-width: 0;
  background: var(--surface-1);
}

.book-side > .eyebrow {
  padding: var(--space-3);
}

.book-side .book-row.muted {
  min-height: var(--space-7);
  background: var(--surface-2);
  color: var(--subtle);
  font-size: var(--type-2xs);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
}

.trades-panel .panel-body,
.terminal-orders .panel-body {
  overflow: auto;
  padding: 0;
}

.trades-panel .data-table,
.terminal-orders .data-table {
  min-width: 100%;
}

.trades-panel .data-table th,
.terminal-orders .data-table th {
  height: 24px;
  padding: 4px 10px;
  font-family: var(--font-data);
  font-size: 11px;
  line-height: 1;
}

.trades-panel .data-table td,
.terminal-orders .data-table td {
  height: 26px;
  padding: 4px 10px;
  font-family: var(--font-data);
  font-size: 12px;
  line-height: 1;
}

.terminal-orders-guest {
  display: grid;
  justify-items: start;
  gap: var(--space-3);
  padding: var(--space-4);
}

.terminal-orders-guest .empty-state {
  min-height: 0;
  padding: 0;
}

/* Density changes rhythm only; every market region remains continuously visible */
.terminal-shell.basic {
  --panel-header-height: var(--space-9);
  --panel-padding: var(--space-5);
}







.trade-ticket label {
  font-size: var(--type-sm);
}

.trade-ticket input,
.trade-ticket select {
  font-family: var(--font-data);
  font-variant-numeric: tabular-nums slashed-zero;
}

.trade-ticket .authorization-summary {
  margin-top: var(--space-1);
  padding-bottom: var(--space-4);
  border-bottom: calc(var(--line) * 3) double var(--border-strong);
  background: transparent;
}

.trade-ticket .authorization-summary strong {
  font-size: var(--type-xs);
}

@media (max-width: 760px) {
  .address-book-form {
    grid-template-columns: 1fr;
  }
}



.chart-wrap {
  position: relative;
  height: 360px;
  padding: var(--space-3);
  background: var(--canvas-deep);
}

.chart-wrap canvas {
  display: block;
  width: 100%;
  height: 100%;
}

/* Forms */
form {
  margin: 0;
}

label {
  display: grid;
  gap: var(--space-2);
  min-width: 0;
  color: var(--muted);
  font-size: var(--type-sm);
  font-weight: var(--weight-semibold);
}

input,
select,
textarea {
  width: 100%;
  min-height: var(--control-height);
  border: var(--line) solid var(--border-control);
  border-radius: var(--radius-control);
  outline: 0;
  background: var(--surface-2);
  color: var(--text-strong);
  padding: var(--space-2) var(--space-3);
  caret-color: var(--accent);
  transition:
    border-color var(--duration-fast) var(--ease-out),
    background-color var(--duration-fast) var(--ease-out);
}

input[type="checkbox"],
input[type="radio"] {
  width: var(--space-4);
  height: var(--space-4);
  min-height: var(--space-4);
  padding: 0;
  accent-color: var(--accent);
}

input[type="range"] {
  min-height: 0;
  border: 0;
  background: transparent;
  padding: 0;
}

input::placeholder,
textarea::placeholder {
  color: var(--subtle);
}

input:hover:not(:disabled),
select:hover:not(:disabled),
textarea:hover:not(:disabled) {
  border-color: var(--border-strong);
  background: var(--surface-hover);
}

input:focus,
select:focus,
textarea:focus {
  border-color: var(--focus);
  background: var(--surface-2);
  box-shadow: none;
}

input:focus-visible,
select:focus-visible,
textarea:focus-visible {
  outline: calc(var(--line) * 2) solid var(--focus);
  outline-offset: 0;
}

input[aria-invalid="true"],
select[aria-invalid="true"],
textarea[aria-invalid="true"] {
  border-color: var(--danger);
}

input:disabled,
select:disabled,
textarea:disabled {
  cursor: not-allowed;
  color: var(--subtle);
}

textarea {
  min-height: 112px;
  resize: vertical;
  line-height: var(--leading-body);
}

.form-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-3);
}

.form-grid > .wide-field {
  grid-column: 1 / -1;
}

.form-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-2);
  min-width: 0;
  margin-top: var(--space-2);
}

.field-note {
  min-width: 0;
  margin: 0;
  overflow-wrap: anywhere;
  color: var(--muted);
  font-size: var(--type-sm);
  line-height: 1.45;
}
.order-hint {
  border-left: calc(var(--line) * 2) solid var(--border-control);
  background: var(--surface-1);
  color: var(--text);
  padding: var(--space-2) var(--space-3);
}

.inline-error {
  border: var(--line) solid color-mix(in srgb, var(--danger) 38%, var(--border));
  border-left: calc(var(--line) * 3) solid var(--danger);
  border-radius: var(--radius-control);
  background: color-mix(in srgb, var(--danger) 8%, var(--surface-1));
  color: var(--danger-strong);
  padding: var(--space-3);
  font-size: var(--type-body);
}

.authorization-summary {
  display: grid;
  gap: 0;
  min-width: 0;
  border: 0;
  border-radius: var(--radius-plate);
  background: transparent;
  padding: 0;
  overflow-wrap: anywhere;
  font-size: var(--type-sm);
}

.authorization-summary > div {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  min-width: 0;
  min-height: var(--space-7);
  border-top: var(--line) solid var(--border-subtle);
  padding: var(--space-2) 0;
}

.authorization-summary > div:last-of-type {
  border-bottom: var(--line) solid var(--border-subtle);
}

.authorization-summary > div > span {
  color: var(--muted);
}

.authorization-summary > div > strong,
.authorization-summary > div > code {
  min-width: 0;
  margin-left: auto;
  color: var(--text);
  font: var(--weight-semibold) var(--type-xs) / var(--leading-tight) var(--font-data);
  text-align: right;
}

.authorization-summary > .field-note {
  margin-top: var(--space-2);
}

.tabs,
.segmented {
  display: flex;
  gap: 0;
  overflow-x: auto;
  padding: 0;
  border: 0;
  border-bottom: var(--line) solid var(--border);
  border-radius: var(--radius-plate);
  background: transparent;
  scrollbar-width: none;
}

.tabs button,
.segmented button {
  position: relative;
  min-height: var(--control-height-compact);
  border: 0;
  border-right: var(--line) solid var(--border-subtle);
  border-radius: var(--radius-plate);
  background: transparent;
  color: var(--muted);
  box-shadow: inset 0 calc(var(--line) * -2) transparent;
}

.tabs button.active,
.segmented button.active,
.tabs button[aria-pressed="true"],
.segmented button[aria-pressed="true"] {
  border-color: var(--border-subtle);
  background: var(--surface-2);
  color: var(--accent);
  box-shadow: inset 0 calc(var(--line) * -2) var(--accent);
}

.type-tabs > button {
  flex: 1 1 0;
}

/* Portfolio statement ledger */
.statement-line {
  margin: 0 0 var(--space-4);
  border-block: calc(var(--line) * 3) double var(--border-strong);
  color: var(--text-strong);
  padding: var(--space-3) var(--space-4);
  font: var(--weight-semibold) var(--type-statement) / var(--leading-tight) var(--font-data);
  letter-spacing: var(--tracking-tight);
  text-align: right;
}

.portfolio-balance-card {
  margin: 0 0 var(--space-4);
  overflow: hidden;
  border: var(--line) solid var(--border-strong);
  background: var(--surface-2);
  box-shadow: var(--shadow-panel);
}

.portfolio-balance-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  min-height: var(--space-9);
  padding: var(--space-3) var(--space-4);
  border-bottom: var(--line) solid var(--border-strong);
  background: var(--surface-3);
}

.portfolio-balance-header .eyebrow {
  margin-bottom: var(--space-1);
}

.portfolio-balance-header h2 {
  margin: 0;
  color: var(--text-strong);
  font-size: var(--type-title);
  font-weight: var(--weight-semibold);
}

.valuation-status {
  flex: 0 0 auto;
  border: var(--line) solid var(--border-strong);
  background: var(--surface-1);
  color: var(--muted);
  padding: var(--space-2) var(--space-3);
  font: var(--weight-semibold) var(--type-micro) / 1 var(--font-data);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
}

.valuation-status.partial {
  border-color: color-mix(in srgb, var(--warning) 58%, var(--border-strong));
  color: var(--warning);
}

.portfolio-balance-body {
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(340px, .75fr);
  align-items: stretch;
  min-height: 132px;
}

.portfolio-balance-total {
  display: grid;
  align-content: center;
  gap: var(--space-2);
  min-width: 0;
  padding: var(--space-5) var(--space-6);
}

.portfolio-balance-total strong {
  overflow-wrap: anywhere;
  color: var(--text-strong);
  font: var(--weight-bold) clamp(28px, 4vw, 44px) / 1 var(--font-data);
  letter-spacing: var(--tracking-tight);
}

.portfolio-balance-total span {
  color: var(--muted);
  font: var(--weight-semibold) var(--type-body) / 1 var(--font-data);
}

.portfolio-balance-breakdown {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  margin: 0;
  border-left: var(--line) solid var(--border-strong);
}

.portfolio-balance-breakdown > div {
  display: grid;
  align-content: center;
  gap: var(--space-2);
  min-width: 0;
  padding: var(--space-4);
}

.portfolio-balance-breakdown > div + div {
  border-left: var(--line) solid var(--border-strong);
}

.portfolio-balance-breakdown dt {
  color: var(--subtle);
  font: var(--weight-semibold) var(--type-micro) / var(--leading-tight) var(--font-data);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
}

.portfolio-balance-breakdown dd {
  margin: 0;
  overflow-wrap: anywhere;
  color: var(--text-strong);
  font: var(--weight-semibold) var(--type-sm) / var(--leading-tight) var(--font-data);
}

@media (max-width: 900px) {
  .portfolio-balance-body {
    grid-template-columns: minmax(0, 1fr);
  }

  .portfolio-balance-breakdown {
    border-top: var(--line) solid var(--border-strong);
    border-left: 0;
  }
}

@media (max-width: 599px) {
  .portfolio-balance-header {
    align-items: flex-start;
    flex-direction: column;
  }

  .valuation-status {
    width: 100%;
  }

  .portfolio-balance-total {
    padding: var(--space-5) var(--space-4);
  }

  .portfolio-balance-breakdown {
    grid-template-columns: minmax(0, 1fr);
  }

  .portfolio-balance-breakdown > div + div {
    border-top: var(--line) solid var(--border-strong);
    border-left: 0;
  }
}

.asset-identity {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  min-width: max-content;
  color: var(--text-strong);
  font-family: var(--font-data);
}

.asset-identity > span:last-child {
  display: grid;
  gap: var(--space-1);
}

.asset-identity strong,
.asset-identity small {
  display: block;
}

.asset-identity small {
  color: var(--subtle);
  font-size: var(--type-micro);
  letter-spacing: calc(var(--tracking-label) / 2);
  text-transform: uppercase;
}

.asset-seal {
  display: grid;
  place-items: center;
  width: var(--seal-size);
  height: var(--seal-size);
  border: var(--line) solid var(--accent-border);
  background: var(--canvas-deep);
  color: var(--accent);
  font: var(--weight-bold) var(--type-micro) / 1 var(--font-data);
  letter-spacing: calc(var(--tracking-label) / 2);
}

.reserved-cell {
  display: inline-grid;
  justify-items: end;
  gap: var(--space-1);
  width: min(100%, calc(var(--space-10) * 2));
  font-family: var(--font-data);
}

.reserved-bar {
  position: relative;
  display: block;
  width: 100%;
  height: var(--space-1);
  overflow: hidden;
  border: var(--line) solid var(--border-control);
  background: var(--surface-1);
}

.reserved-bar::after {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--reserved, 0%);
  background-color: color-mix(in srgb, var(--accent) 12%, var(--canvas-deep));
  background-image: var(--hatch);
}

.ledger-actions {
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
  min-width: max-content;
}

.asset-action-trigger {
  display: inline-grid;
  place-items: center;
  width: var(--control-height);
  min-height: var(--control-height-compact);
  border: var(--line) solid var(--border-strong);
  border-radius: var(--radius-plate);
  background: var(--surface-2);
  color: var(--text-strong);
  padding: 0;
  font: var(--weight-bold) 18px / 1 var(--font-data);
  letter-spacing: .08em;
  cursor: pointer;
}

.asset-action-trigger:hover,
.asset-action-trigger[aria-expanded="true"] {
  border-color: var(--text);
  background: var(--surface-3);
}

.asset-action-trigger:focus-visible {
  outline: calc(var(--line) * 2) solid var(--focus);
  outline-offset: var(--line);
}

.asset-action-popover {
  position: fixed;
  z-index: 1000;
  inset: auto;
  display: none;
  width: min(248px, calc(100vw - var(--space-4)));
  margin: 0;
  overflow: clip;
  border: var(--line) solid var(--border-control);
  border-radius: var(--radius-menu);
  background: var(--surface-float);
  color: var(--text);
  padding: var(--space-1);
  box-shadow: var(--shadow-float);
}

@media (max-width: 599px) {
  .asset-action-popover {
    max-width: calc(100vw - var(--space-4));
  }
}

.asset-action-popover:popover-open {
  display: grid;
  /* Without these the grid stretches its rows to fill, so four 40px items
     rendered 147px each and the popover became 600px tall. That inflated height
     then fed the JS placement maths, which flung the menu into a screen corner
     instead of anchoring it under the trigger. #top-nav-menu already does this. */
  align-content: start;
  grid-auto-rows: min-content;
  block-size: max-content;
  max-block-size: min(60dvh, 420px);
  overflow-y: auto;
  overscroll-behavior: contain;
}

#top-nav-menu {
  top: calc(var(--header-height) + var(--space-2));
  right: max(var(--workspace-padding), env(safe-area-inset-right));
  bottom: auto;
  left: auto;
  width: min(240px, calc(100vw - 16px));
  height: auto;
  max-height: calc(100dvh - var(--header-height) - var(--space-5));
  align-content: start;
  grid-auto-rows: min-content;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 4px;
  background: var(--surface-float);
  box-shadow: var(--shadow-float);
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity 100ms cubic-bezier(0.16,1,0.3,1), transform 100ms cubic-bezier(0.16,1,0.3,1), display 100ms allow-discrete, overlay 100ms allow-discrete;
}

#top-nav-menu:popover-open {
  opacity: 1;
  transform: translateY(0);
  transition-duration: 140ms;
}

@starting-style {
  #top-nav-menu:popover-open {
    opacity: 0;
    transform: translateY(-4px);
  }
}

@media (prefers-reduced-motion: reduce) {
  #top-nav-menu {
    transition: none;
  }
}

.asset-action-item {
  width: 100%;
  min-height: 40px;
  border: 0;
  border-radius: calc(var(--radius-menu) - 2px);
  background: transparent;
  color: var(--muted);
  padding: var(--space-2) var(--space-3);
  font: var(--weight-medium) var(--type-sm) / 1.25 var(--font-sans);
  letter-spacing: 0.01em;
  text-align: left;
  cursor: pointer;
  transition:
    background-color var(--duration-fast) var(--ease-out),
    color var(--duration-fast) var(--ease-out);
}

.asset-action-item + .asset-action-item {
  margin-top: var(--line);
}

.asset-action-item:hover:not(:disabled),
.asset-action-item:focus-visible {
  background: var(--surface-3);
  color: var(--text-strong);
}

.asset-action-item.active,
.asset-action-item[aria-current="page"] {
  background: var(--surface-selected);
  color: var(--text-strong);
}

#top-nav-menu .asset-action-item {
  min-height: 36px;
  border-bottom: 0;
  padding: 0 12px;
  font: 600 12px / 1 var(--font-data);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #A8A8A8;
}

#top-nav-menu .asset-action-item:hover:not(:disabled),
#top-nav-menu .asset-action-item:focus-visible {
  background: var(--surface-hover-high);
  color: #FFFFFF;
}

#top-nav-menu .asset-action-item.active {
  color: #FFFFFF;
  box-shadow: inset 2px 0 0 #F2F2F2;
}

.menu-separator {
  height: 1px;
  margin: 4px 8px;
  background: #2E2E2E;
}

.asset-action-item:focus-visible {
  outline: var(--line) solid var(--focus);
  outline-offset: calc(var(--line) * -1);
}

.asset-action-item:disabled {
  color: var(--subtle);
  cursor: not-allowed;
}

.listing-dossier {
  border-top: var(--line) solid var(--border);
  padding-top: var(--space-3);
}

.listing-dossier summary {
  cursor: pointer;
  color: var(--accent);
  font-weight: var(--weight-semibold);
}

.listing-dossier summary:hover {
  color: var(--accent-strong);
}

.listing-dossier summary::marker {
  color: var(--subtle);
}

.listing-dossier .detail-list {
  margin-top: var(--space-3);
}

.panel-body > .stack > .authorization-summary:not(.pending-deposit-card) {
  border-radius: 0;
  background: transparent;
}
.pending-deposit-list {
  gap: var(--space-3);
}

.pending-deposit-card {
  border-left: 2px solid #EFBE64;
  background: rgba(239,190,100,0.09);
  padding: 10px 12px;
}

.pending-deposit-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  border-bottom: var(--line) solid var(--border-subtle);
  padding-bottom: var(--space-3);
}

.pending-deposit-header strong {
  color: var(--text-strong);
  font: var(--weight-semibold) var(--type-sm) / var(--leading-tight) var(--font-sans);
}

.pending-deposit-header .status-chip {
  flex: 0 0 auto;
}

.pending-deposit-header + div {
  border-top: 0;
}

/* Administration and security */
.admin-grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--space-3);
}

.admin-grid > .panel {
  grid-column: span 6;
}

.admin-grid > .panel.wide {
  grid-column: 1 / -1;
}

.detail-list {
  display: grid;
  gap: var(--space-2);
  margin: 0;
}

.detail-list > div {
  display: grid;
  grid-template-columns: 136px minmax(0, 1fr);
  gap: var(--space-3);
  padding-bottom: var(--space-2);
  border-bottom: var(--line) solid var(--border-subtle);
}

.detail-list > div:last-child {
  padding-bottom: 0;
  border-bottom: 0;
}

.detail-list dt {
  color: var(--subtle);
  font-size: var(--type-sm);
}

.detail-list dd {
  min-width: 0;
  margin: 0;
  overflow-wrap: anywhere;
  color: var(--text);
}

.detail-list a {
  color: var(--info);
}

.detail-list a:hover {
  color: #FFFFFF;
}

.code-block {
  margin: 0;
  overflow-wrap: anywhere;
  border: var(--line) solid var(--border);
  border-radius: var(--radius-control);
  background: var(--surface-1);
  color: var(--accent);
  padding: var(--space-3);
  font: var(--weight-medium) var(--type-sm) / 1.6 var(--font-data);
  white-space: pre-wrap;
}

/* Dialogs and transient feedback */
dialog {
  width: min(480px, calc(100vw - var(--space-7)));
  max-height: calc(100dvh - var(--space-7));
  overflow: auto;
  border: var(--line) solid var(--border-strong);
  border-radius: var(--radius-plate);
  background: var(--surface-modal);
  color: var(--text);
  padding: 0;
  box-shadow: var(--shadow-modal);
}

dialog[open] {
  animation: dialog-in var(--duration-base) var(--ease-out);
}

dialog::backdrop {
  background: var(--backdrop);
}

@keyframes dialog-in {
  from {
    transform: translateY(var(--space-2));
    opacity: 0;
  }
}

.dialog-form {
  display: grid;
  gap: var(--space-4);
  padding: var(--space-6);
  background: var(--surface-modal);
}

.dialog-heading {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  padding-bottom: var(--space-4);
  border-bottom: var(--line) solid var(--border-strong);
}

.dialog-heading h2 {
  margin: 0;
  color: var(--text-strong);
  font-size: var(--type-market);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-tight);
}

.dialog-heading p {
  margin: 0 0 var(--space-2);
}

.dialog-actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-2);
  padding-top: var(--space-4);
  border-top: var(--line) solid var(--border-strong);
}

#confirm-message {
  min-width: 0;
  margin: 0;
  overflow-wrap: anywhere;
  color: var(--muted);
}

.toast-region {
  position: fixed;
  z-index: 100;
  right: var(--space-5);
  bottom: var(--space-5);
  display: grid;
  gap: var(--space-2);
  width: min(400px, calc(100vw - var(--space-7)));
  pointer-events: none;
}

.toast {
  max-width: 100%;
  border: var(--line) solid var(--border-strong);
  border-top: calc(var(--line) * 3) double var(--border-strong);
  border-bottom: calc(var(--line) * 2) solid var(--border-strong);
  border-radius: var(--radius-plate);
  background: var(--surface-float);
  color: var(--text);
  padding: var(--space-3) var(--space-4);
  overflow-wrap: anywhere;
  box-shadow: var(--shadow-float);
  font: var(--weight-medium) var(--type-body) / var(--leading-body) var(--font-sans);
  pointer-events: auto;
  animation: toast-in var(--duration-base) var(--ease-out) both;
}

.toast.error {
  border-bottom-color: var(--danger);
}

.toast.success {
  border-bottom-color: var(--buy);
}

.toast.leaving {
  pointer-events: none;
  animation: toast-out var(--duration-base) var(--ease-out) both;
}

@keyframes toast-in {
  from {
    transform: translateX(var(--space-4));
    opacity: 0;
  }
}

@keyframes toast-out {
  to {
    transform: translateX(var(--space-3));
    opacity: 0;
  }
}

/* Broad terminal: chart and ledgers frame a fixed order counterfoil. */
@media (min-width: 1440px) {
  :root {
    --terminal-chart-row: 380px;
    --terminal-ledger-row: 320px;
    --terminal-orders-row: 280px;
  }

  @media (min-height: 880px) {
    .terminal-shell {
      height: calc(100dvh - var(--terminal-top) - 84px);
      display: flex;
      flex-direction: column;
      overflow: hidden;
    }
  }

  .terminal-grid {
    grid-template-areas:
      "chart ticket book"
      "trades ticket book"
      "orders orders orders";
    grid-template-columns:
      minmax(0, var(--chart-flex, 1fr))
      minmax(300px, var(--terminal-ticket-column))
      minmax(var(--terminal-book-min), 0.8fr);
    grid-template-rows:
      minmax(var(--terminal-chart-row, 340px), 1.3fr)
      minmax(230px, 0.9fr)
      minmax(190px, 0.65fr);
    flex: 1 1 auto;
  }

  .trade-ticket {
    display: flex;
    flex-direction: column;
  }

  .trade-ticket {
    max-height: calc(100dvh - var(--terminal-top) - var(--marketbar-height) - var(--space-8));
  }

  .trade-ticket > .panel-body {
    flex: 1 1 auto;
    min-height: 0;
  }
}

/* Mid-width terminal: the ticket remains an instrument rail for chart and book. */
@media (min-width: 1024px) and (max-width: 1439px) {
  :root {
    --workspace-padding: var(--space-4);
    --terminal-chart-row: 340px;
    --terminal-ledger-row: 340px;
    --terminal-orders-row: 260px;
  }

  .terminal-grid {
    grid-template-areas:
      "chart ticket"
      "book ticket"
      "trades trades"
      "orders orders";
    grid-template-columns:
      minmax(0, 1fr)
      minmax(320px, var(--terminal-ticket-column));
    grid-template-rows:
      var(--terminal-chart-row)
      var(--terminal-ledger-row)
      minmax(280px, auto)
      minmax(240px, var(--terminal-orders-row));
  }

  .trade-ticket {
    max-height: none;
  }

  .admin-grid > .panel {
    grid-column: 1 / -1;
  }
}

/* Tablet terminal: a single, auditable workflow in DOM order. */
@media (min-width: 600px) and (max-width: 1023px) {
  :root {
    --workspace-padding: var(--space-4);
    --table-min-width: 680px;
  }

  .app-header {
    gap: var(--space-3);
    padding-inline: var(--workspace-padding);
  }

  .environment-rail {
    justify-content: flex-start;
    padding-inline: var(--workspace-padding);
  }

  .terminal-shell {
    min-height: 0;
  }

  .terminal-marketbar {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    min-height: 0;
    overflow-x: visible;
  }

  .market-identity,
  .market-stat.primary,
  .terminal-controls {
    grid-column: 1 / -1;
  }

  .market-identity {
    min-width: 0;
    border-right: 0;
    border-bottom: var(--line) solid var(--border);
  }

  .market-stat {
    min-width: 0;
    border-bottom: var(--line) solid var(--border-subtle);
    border-left: 0;
  }

  .market-stat:nth-of-type(even) {
    border-left: var(--line) solid var(--border-subtle);
  }

  .market-stat.primary {
    min-width: 0;
    border-left: 0;
  }

  .terminal-controls {
    justify-content: flex-end;
    min-width: 0;
    margin-left: 0;
    border-left: 0;
  }

  .terminal-grid {
    grid-template-areas:
      "chart"
      "ticket"
      "book"
      "trades"
      "orders";
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto;
  }

  .terminal-grid > .chart-panel {
    min-height: 460px;
  }

  .chart-surface {
    min-height: 360px;
  }

  .terminal-grid > .book-panel {
    min-height: 460px;
  }

  .terminal-grid > .trades-panel {
    min-height: 320px;
  }

  .terminal-grid > .terminal-orders {
    min-height: 300px;
  }

  .trade-ticket {
    position: static;
    max-height: none;
  }

  .trade-ticket > .panel-body {
    overflow: visible;
  }


  .trade-ticket .type-tabs,
  .trade-ticket .authorization-summary {
    grid-column: 1 / -1;
  }

  .admin-grid > .panel {
    grid-column: 1 / -1;
  }
}

/* Handheld terminal: one column, full-size type entry, touch-safe instruments. */
@media (min-width: 320px) and (max-width: 599px) {
  :root {
    --panel-padding: var(--space-3);
    --workspace-padding: var(--space-2);
    --table-min-width: 640px;
  }

  .app-header {
    position: sticky;
    z-index: 30;
    top: 0;
    flex-wrap: wrap;
    gap: var(--space-2);
    height: auto;
    min-height: var(--header-height);
    /* viewport-fit=cover is set, so without the safe-area pad the header
       slides under the notch on a real device. */
    padding: max(var(--space-2), env(safe-area-inset-top)) var(--workspace-padding) 0;
  }

  /* The whole wordmark block was hidden here, which left the phone header
     showing only an unlabelled seal glyph — no product name anywhere on the
     screen. Keep the wordmark, drop only the EXCHANGE sub-line. */
  .brand span:last-child {
    display: block;
  }

  .brand span:last-child strong {
    font-size: 15px;
  }

  .brand span:last-child small {
    display: none;
  }

  .account-actions {
    flex: 1 1 auto;
    justify-content: flex-end;
    min-width: 0;
    gap: var(--space-1);
  }

  /* The environment rail already reports connection state; the header chip is
     redundant on phones and its width pushes Sign in off-screen. */
  .account-actions #connection-state {
    display: none;
  }

  .account-actions .status-chip,
  .account-actions .sandbox-badge {
    min-height: var(--space-6);
    padding-inline: var(--space-2);
  }

  #primary-nav {
    order: 3;
    width: calc(100% + var(--workspace-padding) + var(--workspace-padding));
    height: var(--control-height-touch);
    margin-inline: calc(var(--workspace-padding) * -1);
    border-top: var(--line) solid var(--border-subtle);
    scroll-snap-type: x proximity;
  }

  #primary-nav button {
    min-height: var(--control-height-touch);
    padding-inline: var(--space-3);
    scroll-snap-align: center;
  }

  .environment-rail {
    position: relative;
    top: auto;
    flex-wrap: wrap;
    justify-content: flex-start;
    gap: var(--space-1) var(--space-4);
    height: auto;
    min-height: var(--environment-height);
    padding-block: var(--space-1);
    padding-inline: var(--space-6);
    white-space: normal;
  }

  .view-heading {
    align-items: flex-start;
    flex-direction: column;
    gap: var(--space-3);
    margin-top: 0;
    margin-bottom: var(--space-5);
  }

  .view-heading h1 {
    font-size: var(--type-market);
  }

  .heading-actions {
    flex-wrap: wrap;
    justify-content: flex-start;
  }

  .grid-2,
  .grid-3,
  .form-grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .form-grid > .wide-field {
    grid-column: auto;
  }

  .terminal-shell {
    min-height: 0;
    margin-top: 0;
  }

  .terminal-marketbar {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    min-height: 0;
    overflow-x: visible;
  }

  .market-identity,
  .market-stat.primary,
  .terminal-controls {
    grid-column: 1 / -1;
  }

  .market-identity {
    min-width: 0;
    border-right: 0;
    border-bottom: var(--line) solid var(--border);
  }

  .market-identity h1 {
    font-size: var(--type-market);
  }

  .market-stat {
    min-width: 0;
    border-bottom: var(--line) solid var(--border-subtle);
    border-left: 0;
    padding: var(--space-2);
  }

  .market-stat:nth-of-type(even) {
    border-left: var(--line) solid var(--border-subtle);
  }

  .market-stat.primary {
    min-width: 0;
    border-left: 0;
  }

  .terminal-controls {
    align-items: stretch;
    justify-content: space-between;
    flex-wrap: wrap;
    min-width: 0;
    margin-left: 0;
    border-left: 0;
  }

  .terminal-controls > select {
    flex: 1 1 auto;
    min-width: 0;
  }

  .terminal-controls .segmented {
    flex: 1 1 auto;
  }

  .terminal-controls .segmented button {
    flex: 1 1 0;
  }

  .terminal-grid {
    grid-template-areas:
      "chart"
      "ticket"
      "book"
      "trades"
      "orders";
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto;
  }

  .terminal-grid > .chart-panel {
    min-height: 360px;
  }

  .chart-surface {
    min-height: 272px;
  }

  .chart-toolbar {
    max-width: 58vw;
    overflow-x: auto;
  }

  .chart-toolbar button {
    min-width: var(--control-height);
    min-height: var(--control-height);
  }

  .chart-legend {
    gap: var(--space-3);
  }

  .terminal-grid > .book-panel {
    min-height: 384px;
  }

  .book-row,
  .terminal-shell.basic .book-row,
  .terminal-shell.pro .book-row {
    min-height: var(--control-height);
  }

  .terminal-grid > .trades-panel {
    min-height: 272px;
  }

  .terminal-grid > .terminal-orders {
    min-height: 280px;
  }

  .trade-ticket {
    position: static;
    max-height: none;
  }

  .trade-ticket > .panel-body {
    overflow: visible;
  }


  .trade-ticket .type-tabs,
  .trade-ticket .authorization-summary {
    grid-column: auto;
  }

  input:not([type="checkbox"]):not([type="radio"]):not([type="range"]),
  select,
  textarea {
    min-height: var(--control-height-touch);
    font-size: 16px;
  }

  .button,
  .button.compact,
  .icon-button,
  .text-button,
  .market-link,
  .segmented button,
  .tabs button {
    min-height: var(--control-height-touch);
  }

  .icon-button {
    width: var(--control-height-touch);
  }

  .authorization-summary > div {
    flex-wrap: wrap;
  }

  .statement-line {
    font-size: var(--type-market);
  }

  .ledger-actions .text-button {
    padding-inline: var(--space-3);
  }

  .trades-panel .data-table,
  .terminal-orders .data-table {
    min-width: 480px;
  }

  .detail-list > div {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-1);
  }

  .form-actions {
    flex-wrap: wrap;
  }

  .form-actions .button {
    flex: 1 1 auto;
  }

  dialog {
    max-height: calc(100dvh - var(--space-4));
  }

  .dialog-form {
    padding: var(--space-4);
  }

  .dialog-actions .button {
    flex: 1 1 0;
  }

  .toast-region {
    right: var(--space-2);
    bottom: max(var(--space-2), env(safe-area-inset-bottom));
    width: calc(100vw - var(--space-4));
  }
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    scroll-behavior: auto !important;
    transition: none !important;
    animation: none !important;
  }

  .spinner {
    border-top-color: var(--border);
  }
}

@media (forced-colors: active) {
  :root {
    --canvas: Canvas;
    --canvas-deep: Canvas;
    --surface-1: Canvas;
    --surface-2: Canvas;
    --surface-3: Canvas;
    --surface-float: Canvas;
    --surface-modal: Canvas;
    --surface-hover: Canvas;
    --surface-hover-high: Canvas;
    --surface-selected: Canvas;
    --border-subtle: CanvasText;
    --border: CanvasText;
    --border-strong: CanvasText;
    --border-control: CanvasText;
    --text: CanvasText;
    --text-strong: CanvasText;
    --muted: CanvasText;
    --subtle: CanvasText;
    --accent: Highlight;
    --accent-strong: Highlight;
    --accent-ink: HighlightText;
    --info: LinkText;
    --warning: Mark;
    --danger: LinkText;
    --danger-strong: LinkText;
    --buy: Highlight;
    --sell: LinkText;
    --up: Highlight;
    --down: LinkText;
    --focus: Highlight;
    --backdrop: Canvas;
    --shadow-float: none;
    --shadow-panel: none;
    --shadow-stamp: none;
    --shadow-modal: none;
    --depth-buy: transparent;
    --depth-sell: transparent;
    --hatch: none;
  }

  :focus-visible,
  input:focus-visible,
  select:focus-visible,
  textarea:focus-visible {
    outline: calc(var(--line) * 2) solid Highlight;
  }

  .button.primary {
    border: calc(var(--line) * 2) solid ButtonText;
    background: ButtonFace;
    color: ButtonText;
  }

  .status-chip,
  .sandbox-badge {
    border: var(--line) solid currentColor;
  }

  #primary-nav button.active,
  .tabs button.active,
  .segmented button.active,
  .tabs button[aria-pressed="true"],
  .segmented button[aria-pressed="true"] {
    border-bottom: calc(var(--line) * 2) solid Highlight;
    box-shadow: none;
  }

  .book-row::before {
    display: none;
  }

  .book-row.positive {
    border-right: calc(var(--line) * 3) solid Highlight;
  }

  .book-row.negative {
    border-left: calc(var(--line) * 3) solid LinkText;
  }

  .chart-surface {
    border: var(--line) solid CanvasText;
  }


  .reserved-bar {
    border-color: CanvasText;
  }

  .reserved-bar::after {
    background: Highlight;
  }
}

/* 24h market details: desktop renders inline, phones collapse into a disclosure */
.market-details {
  display: contents;
}

.market-details-toggle {
  display: none;
}

@media (max-width: 599px) {
  .market-details {
    display: none;
    flex: 1 0 100%;
    border-left: var(--line) solid var(--border-subtle);
  }

  .market-details.expanded {
    display: contents;
  }

  .market-details-toggle {
    display: flex;
    align-items: center;
    min-height: var(--control-height-touch);
    border: 0;
    border-left: var(--line) solid var(--border-subtle);
    background: transparent;
    cursor: pointer;
    color: var(--muted);
    padding: var(--space-2) var(--space-3);
    font: var(--weight-semibold) var(--type-micro) / 1 var(--font-data);
    letter-spacing: var(--tracking-label);
    text-transform: uppercase;
  }

  .market-details-toggle::after {
    content: "+";
    margin-left: var(--space-2);
    color: var(--accent);
  }

  .market-details-toggle[aria-expanded="true"]::after {
    content: "\2013";
  }
}

/* Marketbar density: drop lowest-priority stats before allowing truncation */
@media (max-width: 1599px) and (min-width: 600px) {
  .terminal-marketbar .market-details .market-stat:nth-child(4),
  .terminal-marketbar .market-details .market-stat:nth-child(5) {
    display: none;
  }
}

@media (max-width: 1279px) and (min-width: 600px) {
  .terminal-marketbar .market-details .market-stat:nth-child(1),
  .terminal-marketbar .market-details .market-stat:nth-child(2),
  .terminal-marketbar .market-details .market-stat:nth-child(3) {
    display: none;
  }

  .terminal-marketbar .market-stat {
    min-width: 104px;
  }
}

@media (max-width: 1599px) and (min-width: 600px) {
  .market-stat.primary {
    flex-basis: 170px;
    min-width: 150px;
  }

  .market-stat.primary > strong {
    font-size: var(--type-market);
  }
}

@media (max-width: 1599px) and (min-width: 600px) {
  .market-stat.primary .stat-unit {
    display: none;
  }
}

@media (min-width: 1600px) {
  .market-stat.primary {
    flex-basis: 232px;
    min-width: 210px;
  }
}

/* Ticket affordances: SafeTrade-grade available line and total */
.ticket-available {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  border-bottom: var(--line) solid var(--border-subtle);
  padding-bottom: var(--space-2);
  color: var(--muted);
  font: var(--weight-semibold) var(--type-sm) / 1 var(--font-data);
}

.ticket-total {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2);
  border-top: var(--line) solid var(--border-strong);
  padding-top: var(--space-2);
}

.ticket-total span {
  color: var(--subtle);
  font: var(--weight-semibold) var(--type-micro) / 1 var(--font-data);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
}

.ticket-total strong {
  color: var(--text-strong);
  font: var(--weight-bold) var(--type-title) / 1 var(--font-data);
}

/* Market search and combobox */
.market-search {
  min-width: 180px;
  min-height: var(--control-height);
  border: var(--line) solid var(--border-control);
  border-radius: var(--radius-control);
  background: var(--surface-2);
  color: var(--text);
  padding: 0 var(--space-3);
  font: var(--weight-medium) var(--type-sm) / 1 var(--font-data);
}

.market-combo {
  width: 132px;
  min-height: var(--control-height);
  border: var(--line) solid var(--border-control);
  border-radius: var(--radius-control);
  background: var(--surface-2);
  color: var(--text-strong);
  padding: 0 var(--space-3);
  font: var(--weight-semibold) var(--type-sm) / 1 var(--font-data);
  text-transform: uppercase;
}

/* Ticket: counterfoil scrolls inside the panel body; the stamp stays pinned */


/* ---- Premium critique consolidation ---- */

/* Finding 1: ticket action as a pinned non-scrolling footer; hide the redundant ticket title */
.trade-ticket > .panel-header {
  display: none;
}

.trade-ticket > .panel-body {
  display: flex;
  flex-direction: column;
  overflow: hidden;
}




/* Finding 2: tonal surface hierarchy — the ticket is a dedicated execution rail */
.terminal-grid > .trade-ticket {
  background: var(--surface-2);
}

.trade-ticket input,
.trade-ticket select {
  background: var(--surface-3);
}

/* Finding 3: chrome in sans, data stays mono, headers lose the shout */
.app-header,
#primary-nav button,
.panel-header,
.market-stat > span,
.book-header,
.data-table th {
  font-family: var(--font-sans);
}

.book-header,
.data-table th {
  font-size: var(--type-micro);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-label);
  text-transform: none;
}

/* Finding 4: quiet seams — single rules, no console scaffolding */
.environment-rail {
  border-top: 0;
  border-bottom: var(--line) solid var(--border-subtle);
  letter-spacing: 0.08em;
}

.environment-rail::before,
.environment-rail::after {
  display: none;
}

.terminal-marketbar {
  border-bottom: var(--line) solid var(--border);
}

.market-identity,
.market-stat,
.terminal-controls {
  border-inline: 0;
}

.market-stat.primary {
  border-left: 0;
  background: transparent;
}

/* Finding 6: chart integrated as one surface; attribution becomes a quiet overlay */

.chart-panel > .panel-header h2 {
  display: none;
}

.chart-panel > .panel-header {
  justify-content: flex-start;
}

.chart-panel > .panel-body {
  position: relative;
  padding: 0;
}


/* Finding 7: quiet continuous book ladder with a real mid-price */
.book-header {
  background: var(--surface-1);
  font-size: var(--type-micro);
}

.book-row {
  min-height: var(--space-6);
  border-bottom: 0;
  font-size: var(--type-xs);
}

.trades-panel .data-table td {
  background: transparent;
}
.book-spread {
  border-block: var(--line) solid var(--border);
  background: var(--surface-1);
}

.book-spread strong {
  font-size: var(--type-market);
  line-height: 1;
  white-space: nowrap;
}

.book-spread span {
  overflow: hidden;
  color: var(--muted);
  font-size: var(--type-micro);
  text-align: right;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Finding 8: tabs carry hierarchy; compact ledgers */
.trades-panel > .panel-header h2,
.terminal-orders > .panel-header h2 {
  display: none;
}

.trades-panel > .panel-header,
.terminal-orders > .panel-header {
  justify-content: flex-start;
}




/* Buy-side stamp scoped to market-buy green; brand accent reserved for chrome */

/* Watchlist rail: persistent market list like top-tier terminals */
.watchlist {
  display: none;
  grid-area: watch;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
  border: var(--line) solid var(--border-strong);
  border-radius: var(--radius-plate);
  background: var(--surface-2);
  box-shadow: var(--shadow-panel);
}

.watch-tools {
  display: grid;
  flex: 0 0 auto;
  gap: var(--space-2);
  padding: var(--space-2);
  border-bottom: var(--line) solid var(--border-subtle);
}

.watch-search {
  width: 100%;
  min-width: 0;
}

.watch-tabs {
  display: flex;
}

.watch-tabs button {
  flex: 1;
  min-height: 28px;
}

.watch-rows {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  background: var(--surface-1);
}

.watch-row {
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr) auto;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  min-height: 34px;
  border: 0;
  border-bottom: var(--line) solid color-mix(in srgb, var(--border-subtle) 45%, transparent);
  background: transparent;
  color: var(--text);
  padding: 0 var(--space-2);
  font: var(--weight-medium) var(--type-xs) / 1 var(--font-data);
  font-variant-numeric: tabular-nums slashed-zero;
  text-align: left;
  cursor: pointer;
}

.watch-row:hover {
  background: var(--surface-hover);
}

.watch-row.active {
  background: var(--surface-selected);
  box-shadow: inset 2px 0 0 var(--accent);
}

.watch-pair {
  overflow: hidden;
  color: var(--text-strong);
  font-weight: var(--weight-semibold);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.watch-price {
  overflow: hidden;
  color: var(--text);
  text-align: right;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.watch-change {
  min-width: 52px;
  text-align: right;
}

@media (min-width: 1280px) {
  .terminal-grid {
    grid-template-areas:
      "watch chart ticket book"
      "watch trades ticket book"
      "watch orders orders orders";
    grid-template-columns:
      236px
      minmax(0, var(--chart-flex, 1fr))
      minmax(300px, var(--terminal-ticket-column))
      minmax(var(--terminal-book-min), 0.72fr);
    grid-template-rows:
      minmax(var(--terminal-chart-row, 340px), 1.3fr)
      minmax(230px, 0.9fr)
      minmax(190px, 0.65fr);
  }

  .watchlist {
    display: flex;
  }
}

@media (min-width: 1024px) and (max-width: 1439px) {
  .terminal-grid {
    grid-template-areas:
      "watch chart ticket"
      "watch book ticket"
      "watch trades trades"
      "watch orders orders";
    grid-template-columns: 200px minmax(0, 1fr) minmax(320px, var(--terminal-ticket-column));
  }

  .watchlist {
    display: flex;
  }
}

/* Full-height terminal: grid tracks constrain, panels scroll inside */
.terminal-grid {
  min-height: 0;
}

.terminal-grid > * {
  min-height: 0;
}

.terminal-grid > .panel > .panel-body {
  max-height: 100%;
  overflow: auto;
  overscroll-behavior: contain;
}

/* Dual buy/sell ticket columns (SafeTrade signature) */
.order-columns {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-3);
  border: var(--line) solid var(--border-strong);
  background: var(--surface-2);
  padding: var(--space-3);
  box-shadow: var(--shadow-panel);
}

.order-column {
  display: grid;
  align-content: start;
  gap: var(--space-2);
}

.order-column label {
  position: relative;
  display: block;
}

.order-column .input-unit {
  position: absolute;
  top: 50%;
  right: var(--space-2);
  transform: translateY(-50%);
  color: var(--subtle);
  font: var(--weight-semibold) var(--type-micro) / 1 var(--font-data);
  pointer-events: none;
}

.order-column input[inputmode="decimal"] {
  width: 100%;
  padding-right: var(--space-8);
}

.column-total {
  color: var(--muted);
  font: var(--weight-medium) var(--type-xs) / 1.3 var(--font-data);
  min-height: var(--space-4);
}

.column-stamp {
  width: 100%;
  min-height: var(--control-height-touch);
  font-size: var(--type-sm);
}

.column-stamp.buy {
  border-color: var(--buy);
  background: var(--buy);
  color: #04120D;
  box-shadow: 0 2px 10px color-mix(in srgb, var(--buy) 26%, transparent);
}

.column-stamp.sell {
  border-color: var(--sell);
  background: var(--sell);
  color: #FFF5F5;
  box-shadow: 0 2px 10px color-mix(in srgb, var(--sell) 26%, transparent);
}

.ticket-options {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-3);
  margin-top: var(--space-3);
  border-top: var(--line) solid var(--border-strong);
  padding-top: var(--space-3);
}

.ticket-trigger {
  flex: 1 1 120px;
}

.ticket-tif select {
  min-height: var(--control-height-compact);
}

@media (max-width: 1279px) {
  .order-columns {
    grid-template-columns: 1fr;
  }
}

/* Continuous balance allocation control */
.allocation-control {
  --slider-color: var(--buy);
  display: grid;
  gap: var(--space-1);
  margin-block: var(--space-1);
}

.order-column.buy .allocation-control {
  --slider-color: var(--buy);
}

.order-column.sell .allocation-control {
  --slider-color: var(--sell);
}

.allocation-heading {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  min-height: 24px;
}

.allocation-label {
  color: var(--muted);
  font-size: var(--type-micro);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
}

.allocation-value {
  display: inline-grid;
  min-width: 44px;
  min-height: 24px;
  place-items: center;
  border: var(--line) solid color-mix(in srgb, var(--slider-color) 42%, var(--border-control));
  border-radius: var(--radius-control);
  background: var(--surface-float);
  color: var(--slider-color);
  padding-inline: var(--space-2);
  box-shadow: var(--shadow-panel);
  font: var(--weight-bold) var(--type-xs) / 1 var(--font-data);
  transition:
    border-color var(--duration-fast) var(--ease-out),
    color var(--duration-fast) var(--ease-out);
}

.order-column .allocation-slider {
  display: block;
  width: 100%;
  height: 32px;
  min-height: 32px;
  margin: 0;
  border: 0;
  border-radius: 0;
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  cursor: pointer;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
}

.order-column .allocation-slider::-webkit-slider-runnable-track {
  height: 4px;
  border: 0;
  border-radius: var(--radius-control);
  background: linear-gradient(
    to right,
    var(--slider-color) 0%,
    var(--slider-color) var(--fill, 0%),
    var(--surface-3) var(--fill, 0%),
    var(--surface-3) 100%
  );
  box-shadow: inset 0 0 0 var(--line) color-mix(in srgb, var(--slider-color) 12%, var(--border-control));
}

.order-column .allocation-slider::-webkit-slider-thumb {
  width: 22px;
  height: 22px;
  margin-top: -9px;
  border: 2px solid var(--slider-color);
  border-radius: 50%;
  appearance: none;
  -webkit-appearance: none;
  background: var(--surface-float);
  box-shadow: 0 0 0 2px var(--surface-2), var(--shadow-panel);
  touch-action: none;
  transition:
    background-color var(--duration-fast) var(--ease-out),
    box-shadow var(--duration-fast) var(--ease-out);
}

.order-column .allocation-slider::-moz-range-track {
  height: 4px;
  border: 0;
  border-radius: var(--radius-control);
  background: var(--surface-3);
  box-shadow: inset 0 0 0 var(--line) color-mix(in srgb, var(--slider-color) 12%, var(--border-control));
}

.order-column .allocation-slider::-moz-range-progress {
  height: 4px;
  border-radius: var(--radius-control);
  background: var(--slider-color);
}

.order-column .allocation-slider::-moz-range-thumb {
  width: 22px;
  height: 22px;
  border: 2px solid var(--slider-color);
  border-radius: 50%;
  background: var(--surface-float);
  box-shadow: 0 0 0 2px var(--surface-2), var(--shadow-panel);
  touch-action: none;
  transition:
    background-color var(--duration-fast) var(--ease-out),
    box-shadow var(--duration-fast) var(--ease-out);
}

.order-column .allocation-slider:hover::-webkit-slider-thumb,
.order-column .allocation-slider:active::-webkit-slider-thumb {
  background: color-mix(in srgb, var(--slider-color) 12%, var(--surface-float));
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--slider-color) 14%, transparent), var(--shadow-panel);
}

.order-column .allocation-slider:hover::-moz-range-thumb,
.order-column .allocation-slider:active::-moz-range-thumb {
  background: color-mix(in srgb, var(--slider-color) 12%, var(--surface-float));
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--slider-color) 14%, transparent), var(--shadow-panel);
}

.allocation-marks {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--space-1);
}

.allocation-mark {
  min-width: 0;
  min-height: 28px;
  border: var(--line) solid var(--border-control);
  border-radius: var(--radius-control);
  appearance: none;
  background: var(--surface-2);
  color: var(--muted);
  padding: 0 var(--space-1);
  font: var(--weight-semibold) var(--type-micro) / 1 var(--font-data);
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  transition:
    border-color var(--duration-fast) var(--ease-out),
    background-color var(--duration-fast) var(--ease-out),
    color var(--duration-fast) var(--ease-out);
}

.allocation-mark:hover {
  border-color: color-mix(in srgb, var(--slider-color) 50%, var(--border-control));
  background: var(--surface-hover);
  color: var(--text-strong);
}

.allocation-mark.active,
.allocation-mark[aria-pressed="true"] {
  border-color: color-mix(in srgb, var(--slider-color) 70%, var(--border-control));
  background: color-mix(in srgb, var(--slider-color) 10%, var(--surface-2));
  color: var(--slider-color);
}

.allocation-mark:focus-visible {
  outline: calc(var(--line) * 2) solid var(--focus);
  outline-offset: 1px;
}

@media (max-width: 599px) {
  .order-column .allocation-slider {
    height: 36px;
    min-height: 36px;
  }

  .allocation-value {
    min-height: 26px;
    font-size: var(--type-sm);
  }

  .allocation-mark {
    min-height: 32px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .allocation-value,
  .allocation-mark,
  .order-column .allocation-slider::-webkit-slider-thumb,
  .order-column .allocation-slider::-moz-range-thumb {
    transition: none;
  }
}

/* Attribution: dock into the chart toolbar row instead of overlaying the axis */
.chart-attribution {
  position: static;
  display: inline-flex;
  margin-left: auto;
  border: 0;
  background: transparent;
  padding: 0 var(--space-2);
  opacity: 0.55;
  font-size: var(--type-micro);
  white-space: nowrap;
}

/* Chart toolbar: intervals stay horizontal, attribution yields */
.chart-toolbar {
  flex-wrap: nowrap;
  overflow-x: auto;
  scrollbar-width: none;
}

.chart-toolbar::-webkit-scrollbar {
  display: none;
}

.chart-toolbar button {
  flex: 0 0 auto;
  min-width: var(--control-height-compact);
  white-space: nowrap;
}

.chart-panel .panel-header .chart-attribution {
  flex: 0 0 auto;
}

/* Chart topline: legend left, attribution right */
.chart-topline {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  border-bottom: var(--line) solid var(--border-subtle);
  background: var(--surface-1);
}

.chart-topline .chart-legend {
  flex: 1 1 auto;
  border-bottom: 0;
}

.chart-topline .chart-attribution {
  flex: 0 0 auto;
  margin: 0;
  white-space: nowrap;
}

/* Phone order ticket: tabs and options flow cleanly */
@media (max-width: 599px) {
  .trade-ticket .type-tabs {
    display: flex;
    width: 100%;
  }

  .trade-ticket .type-tabs button {
    flex: 1 1 auto;
    min-width: 0;
  }

  .trade-ticket .ticket-options {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2) var(--space-3);
  }

  .trade-ticket .ticket-tif select {
    max-width: 110px;
  }
}

/* Narrow watch rail: two-line rows keep pair, price, and change readable */
@media (max-width: 1439px) and (min-width: 1024px) {
  .watch-row {
    grid-template-columns: 1fr auto;
    grid-template-areas:
      "pair change"
      "price change";
    row-gap: 2px;
    padding-block: var(--space-1);
  }

  .watch-pair {
    grid-area: pair;
  }

  .watch-price {
    grid-area: price;
    color: var(--muted);
    text-align: left;
  }

  .watch-change {
    grid-area: change;
    align-self: center;
  }
}

/* New trade flash: one factual 240ms side-color decay */
@keyframes trade-flash-decay {
  from {
    background: color-mix(in srgb, currentColor 9%, transparent);
  }
  to {
    background: transparent;
  }
}

.trade-flash.positive {
  color: var(--buy);
  animation: trade-flash-decay 240ms var(--ease-out) 1;
}

.trade-flash.negative {
  color: var(--sell);
  animation: trade-flash-decay 240ms var(--ease-out) 1;
}

@media (prefers-reduced-motion: reduce) {
  .trade-flash.positive,
  .trade-flash.negative {
    animation: none;
  }
}

/* Book tick grouping selector */
.book-tick-select {
  min-height: var(--control-height-compact);
  border: var(--line) solid var(--border-control);
  border-radius: var(--radius-control);
  background: var(--surface-2);
  color: var(--text);
  padding: 0 var(--space-2);
  font: var(--weight-medium) var(--type-xs) / 1 var(--font-data);
}

/* TradingView hosted widget frame */
.tv-frame {
  display: block;
  width: 100%;
  height: 100%;
  min-height: 320px;
  border: 0;
  flex: 1 1 auto;
  background: #050505;
}

.tv-note {
  margin: 0;
  border-top: var(--line) solid var(--border-subtle);
  padding: var(--space-2) var(--space-3);
  color: var(--subtle);
  font-size: var(--type-micro);
}

.chart-panel > .panel-body:has(> .tv-frame) {
  display: flex;
  flex-direction: column;
}

/* TradingView truth warning: unmissable, above the frame */
.tv-warning {
  margin: 0;
  border-bottom: var(--line) solid color-mix(in srgb, var(--warning) 55%, transparent);
  background: color-mix(in srgb, var(--warning) 8%, transparent);
  color: var(--warning);
  padding: var(--space-2) var(--space-3);
  font: var(--weight-semibold) var(--type-xs) / 1.4 var(--font-data);
}

/* Current market label in market bar */
.market-current {
  color: var(--text-strong);
  font: var(--weight-bold) var(--type-control) / 1 var(--font-data);
  white-space: nowrap;
}

/* Panel header tabs get full room */
.chart-panel > .panel-header .segmented button {
  white-space: nowrap;
}

/* Trades and book stay compact so orders remain on the same page */
.trades-panel > .panel-body {
  max-height: 340px;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.book-panel > .panel-body {
  max-height: 560px;
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* Narrow book columns: cumulative yields to readable price/size */
@media (max-width: 1439px) {
  .book-row,
  .book-header {
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr) minmax(36px, 0.6fr);
  }
}

/* Single-form side tabs: one order form visible at a time */
.order-columns.single {
  grid-template-columns: 1fr;
}

.side-tabs {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--line);
  border: var(--line) solid var(--border);
  border-radius: var(--radius-control);
  background: var(--surface-2);
  padding: var(--line);
}

.side-tabs button {
  min-height: var(--control-height);
  border: 0;
  border-radius: calc(var(--radius-control) - 1px);
  background: transparent;
  color: var(--muted);
  font: var(--weight-semibold) var(--type-sm) / 1 var(--font-data);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.side-tabs button:hover {
  color: var(--text);
  background: var(--surface-hover);
}

.side-tabs button.active.buy {
  background: color-mix(in srgb, var(--buy) 16%, var(--surface-2));
  color: var(--buy);
}

.side-tabs button.active.sell {
  background: color-mix(in srgb, var(--sell) 16%, var(--surface-2));
  color: var(--sell);
}

/* Panel resize handles */
.resize-handle {
  position: relative;
  z-index: 4;
  border-radius: 2px;
  background: transparent;
  cursor: col-resize;
}

.resize-handle.resize-row {
  cursor: row-resize;
}

.resize-handle:hover,
.resize-handle:focus-visible,
.resize-handle:active {
  background: color-mix(in srgb, var(--accent) 30%, transparent);
  outline: none;
}

.resize-handle::after {
  content: "";
  position: absolute;
  inset: 0 2px;
  border-radius: 1px;
  background: var(--border);
  opacity: 0;
  transition: opacity 120ms;
}

.resize-handle:hover::after,
.resize-handle:active::after {
  opacity: 1;
}

/* The column handles need side-by-side columns, which only exist on wide
   desktop. The ROW handle sets chart height and is useful at every width, so it
   stays available down to tablet. */
@media (max-width: 1279px) {
  .resize-handle.resize-col-a,
  .resize-handle.resize-col-b {
    display: none;
  }
}

@media (max-width: 599px) {
  .resize-handle {
    display: none;
  }
}

/* A drag target nobody can see is a feature nobody uses: the chart's bottom
   edge now carries a permanent grip that brightens on hover. */
.resize-handle.resize-row::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 44px;
  height: 3px;
  transform: translate(-50%, -50%);
  border-radius: 2px;
  background: var(--border-control);
  opacity: 0.75;
  transition: opacity var(--duration-hover) var(--ease-out), background-color var(--duration-hover) var(--ease-out);
}

.resize-handle.resize-row:hover::before,
.resize-handle.resize-row:focus-visible::before,
.resize-handle.resize-row:active::before {
  background: var(--accent);
  opacity: 1;
}

@media (pointer: coarse) {
  /* Comfortable drag target for a thumb. */
  .resize-handle.resize-row { height: 22px; }
  .resize-handle.resize-row::before { width: 56px; height: 4px; }
}

/* Panel resize handles: absolutely positioned on panel boundaries */
.terminal-grid {
  position: relative;
}

.resize-handle {
  position: absolute;
  z-index: 6;
  width: 12px;
  height: 12px;
  border: 0;
  border-radius: 2px;
  background: transparent;
  cursor: col-resize;
  transform: translate(-50%, 0);
}

.resize-handle.resize-col-a,
.resize-handle.resize-col-b {
  top: 0;
  bottom: 0;
  height: auto;
}

.resize-handle.resize-row {
  right: 0;
  left: 0;
  width: auto;
  height: 12px;
  cursor: row-resize;
  transform: translate(0, -50%);
}

.resize-handle:hover,
.resize-handle:focus-visible,
.resize-handle:active {
  background: color-mix(in srgb, var(--accent) 26%, transparent);
  outline: none;
}

/* ============================================================
   Mobile ledger cards
   Phone widths turn every `.data-table.responsive-rows` into a
   stacked card list so no column hides behind a sideways scroll.
   The table helper already emits `data-label` on every cell, so
   each value carries its own field name.
   ============================================================ */
@media (max-width: 599px) {
  .table-scroll {
    overflow-x: visible;
    border: 0;
  }

  .data-table.responsive-rows,
  .data-table.responsive-rows tbody {
    display: block;
    width: 100%;
  }

  /* The desktop ledger keeps a `--table-min-width` floor so columns stay
     readable. Card mode stacks those columns, so the floor must be released
     or the table keeps forcing a sideways scroll. */
  .data-table.responsive-rows {
    min-width: 0;
  }

  /* Each cell renders its own visible field name from `data-label`, so the
     column header row is redundant here. Table internals ignore positioning,
     so it must be removed from the box tree outright to stop it forcing the
     table back to its full multi-column width. */
  .data-table.responsive-rows thead {
    display: none;
  }

  .data-table.responsive-rows tbody tr {
    display: block;
    padding: var(--space-2) var(--space-3);
    border-bottom: var(--line) solid var(--border);
    background: var(--surface-2);
  }

  .data-table.responsive-rows tbody tr:last-child {
    border-bottom: 0;
  }

  .data-table.responsive-rows td {
    display: grid;
    grid-template-columns: minmax(84px, 38%) 1fr;
    align-items: center;
    gap: var(--space-3);
    min-height: 30px;
    height: auto;
    padding: 2px 0;
    border: 0;
    text-align: left;
  }

  .data-table.responsive-rows td::before {
    content: attr(data-label);
    color: var(--subtle);
    font-family: var(--font-sans);
    font-size: 11px;
    font-weight: var(--weight-semibold);
    letter-spacing: 0.06em;
    text-transform: uppercase;
  }

  /* Numeric values keep their right edge so decimals stay comparable
     down the card, matching the desktop ledger grid. */
  .data-table.responsive-rows td.num {
    text-align: right;
  }

  /* A cell with no field name (row-action or watchlist columns) spans the
     full card width instead of leaving an empty label gutter. */
  .data-table.responsive-rows td[data-label=""] {
    grid-template-columns: 1fr;
    justify-items: start;
  }

  .data-table.responsive-rows td[data-label=""]::before {
    display: none;
  }
}

/* ------------------------------------------------------------
   Compact two-line phone rows
   Tables that tag their columns with a `mobile` role render a dense
   Coinbase-style row instead of stacked label/value pairs:

       TITLE                        PRIMARY
       secondary                       meta        [action]

   Untagged tables keep the label/value fallback above.
   ------------------------------------------------------------ */
@media (max-width: 599px) {
  .data-table.compact-rows tbody tr {
    display: grid;
    grid-template-columns: 1fr auto auto;
    grid-template-areas:
      "title primary action"
      "secondary meta action";
    column-gap: var(--space-3);
    row-gap: 2px;
    align-items: center;
    align-content: center;
    min-height: 58px;
    padding: var(--space-2) var(--space-3);
  }

  /* Field names are carried by position in compact mode, not by a label. */
  .data-table.compact-rows td::before {
    display: none;
  }

  /* Cells must shed the desktop ledger chrome (fixed row height, cell fill and
     hairline rules) or each value renders as its own nested box inside the row. */
  .data-table.compact-rows td {
    display: block;
    height: auto;
    min-height: 0;
    padding: 0;
    border: 0;
    background: transparent;
    line-height: 1.25;
  }

  .data-table.compact-rows td[data-m="title"] {
    grid-area: title;
    color: var(--text-strong);
    font-size: 14px;
    font-weight: var(--weight-semibold);
  }

  .data-table.compact-rows td[data-m="primary"] {
    grid-area: primary;
    color: var(--text-strong);
    font-size: 14px;
    font-weight: var(--weight-semibold);
    text-align: right;
  }

  .data-table.compact-rows td[data-m="secondary"] {
    grid-area: secondary;
    color: var(--subtle);
    font-size: 12px;
  }

  .data-table.compact-rows td[data-m="meta"] {
    grid-area: meta;
    font-size: 12px;
    text-align: right;
  }

  .data-table.compact-rows td[data-m="action"] {
    grid-area: action;
    align-self: center;
    padding-left: var(--space-2);
  }

  .data-table.compact-rows td[data-m="hide"] {
    display: none;
  }
}

/* ------------------------------------------------------------
   Market list identity and controls
   Ticker monograms, colour-carrying change chips and filter pills.
   These replace a bare OS select and plain text values, which were
   the most generic-looking elements on the directory.
   ------------------------------------------------------------ */
.coin-mark {
  display: inline-grid;
  place-items: center;
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  border: var(--line) solid var(--border-strong);
  border-radius: 50%;
  background: var(--surface-3);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06);
  color: var(--text);
  font-family: var(--font-data);
  font-size: 9px;
  font-weight: var(--weight-bold);
  letter-spacing: 0.02em;
}

.market-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}

.market-link-label {
  font-weight: var(--weight-semibold);
}

.change-chip {
  display: inline-block;
  min-width: 62px;
  padding: 2px 7px;
  border: var(--line) solid transparent;
  border-radius: var(--radius-control, 4px);
  font-family: var(--font-data);
  font-variant-numeric: tabular-nums slashed-zero;
  text-align: right;
}

.change-chip.positive {
  border-color: color-mix(in srgb, var(--up) 34%, transparent);
  background: color-mix(in srgb, var(--up) 12%, transparent);
  color: var(--up);
}

.change-chip.negative {
  border-color: color-mix(in srgb, var(--down) 34%, transparent);
  background: color-mix(in srgb, var(--down) 12%, transparent);
  color: var(--down);
}

.change-chip.flat {
  color: var(--muted);
}

.market-category-pills {
  display: inline-flex;
  gap: 4px;
  padding: 3px;
  border: var(--line) solid var(--border);
  border-radius: 6px;
  background: var(--surface-1);
}

.filter-pill {
  min-height: 28px;
  padding: 0 12px;
  border: var(--line) solid transparent;
  border-radius: 4px;
  background: transparent;
  color: var(--muted);
  font-family: var(--font-data);
  font-size: 11px;
  font-weight: var(--weight-semibold);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background-color 120ms ease, color 120ms ease, border-color 120ms ease;
}

.filter-pill:hover:not(.active) {
  background: var(--surface-hover);
  color: var(--text);
}

.filter-pill.active {
  border-color: var(--border-strong);
  background: var(--surface-3);
  color: var(--text-strong);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.07);
}

/* ------------------------------------------------------------
   Phone trade terminal: put the ticket above the fold
   The market bar previously stacked label/price/change vertically
   (191px) and the chart took 421px, which pushed the order form off
   screen on a 844px device. The bar collapses to one line and the
   chart is capped so Buy/Sell and the price field are reachable
   without scrolling.
   ------------------------------------------------------------ */
@media (max-width: 599px) {
  .terminal-marketbar {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--space-2) var(--space-3);
    padding: var(--space-2) var(--space-3);
  }

  /* "Spot market" is redundant once the pair name is on the same line. */
  .terminal-marketbar .market-identity .eyebrow {
    display: none;
  }

  .terminal-marketbar .market-identity {
    flex: 0 0 auto;
    padding: 0;
    border: 0;
  }

  .terminal-marketbar .market-identity h1 {
    font-size: 17px;
  }

  .terminal-marketbar .market-stat {
    flex: 0 0 auto;
    gap: 0 var(--space-2);
    padding: 0;
    border: 0;
  }

  /* Field names collapse away; the pair, price and change read as one line. */
  .terminal-marketbar .market-stat > span {
    display: none;
  }

  .terminal-marketbar .market-stat > strong {
    font-size: 15px;
  }

  .terminal-marketbar .market-stat.primary > strong {
    font-size: 19px;
  }

  /* The pair name already leads the line, so the duplicate label is noise. */
  .terminal-marketbar .market-current {
    display: none;
  }

  /* Only price and 24h change ride the top line; everything else stays behind
     the existing details expander. Scoped to direct children because the
     expander holds `.market-stat` elements too. */
  .terminal-marketbar > .market-stat {
    display: flex;
  }

  .terminal-grid > .chart-panel {
    max-height: 300px;
  }
}

/* A `wide` cell claims its own full-width line below the two-line row. It is
   for values that must stay tappable and legible but are too long for a
   gutter, such as a blockchain transaction link. */
@media (max-width: 599px) {
  .data-table.compact-rows td[data-m="wide"] {
    grid-column: 1 / -1;
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    gap: var(--space-2);
    margin-top: 5px;
    padding-top: 5px;
    border-top: var(--line) solid var(--border-subtle);
    min-height: 26px;
  }

  .data-table.compact-rows td[data-m="wide"]::before {
    display: block;
    content: attr(data-label);
    color: var(--subtle);
    font-family: var(--font-sans);
    font-size: 10px;
    font-weight: var(--weight-semibold);
    letter-spacing: 0.06em;
    text-transform: uppercase;
  }

  /* Hashes must truncate rather than wrap, and stay a comfortable tap target. */
  .data-table.compact-rows td[data-m="wide"] .identifier {
    display: block;
    overflow: hidden;
    min-height: 24px;
    line-height: 24px;
    white-space: nowrap;
    text-overflow: ellipsis;
    font-size: 11px;
  }
}

/* ============================================================
   R3 SURFACE LIGHT — gloss layer over R2 FELT DEPTH.
   Benchmark finding: the perceived "gloss" of comparable venues is
   translucency, hairline light and motion — NOT gradient fills.
   Invariants preserved: no gradient on .panel, zero-radius plates,
   R2 shadow tokens and --up/--down/--surface-float untouched.
   ============================================================ */
:root {
  --chrome-veil: rgba(16, 16, 16, 0.78);
  --chrome-blur: blur(14px) saturate(1.5);
  --thead-veil: rgba(31, 31, 31, 0.82);
  --sheen: linear-gradient(180deg, rgba(255,255,255,0.045) 0%, rgba(255,255,255,0.015) 42%, rgba(255,255,255,0) 100%);
  --sheen-strong: linear-gradient(180deg, rgba(255,255,255,0.10) 0%, rgba(255,255,255,0.03) 48%, rgba(255,255,255,0) 100%);
  --row-rule: #1F1F1F;
  --thead-rule: #303030;
  --duration-hover: 140ms;
  --duration-press: 90ms;
  --duration-release: 160ms;
  --ease-press: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-touch: cubic-bezier(0, 0, 0.2, 1);
}

/* Chrome becomes glass: content slides under the masthead. */
.app-header {
  background: var(--chrome-veil);
  -webkit-backdrop-filter: var(--chrome-blur);
  backdrop-filter: var(--chrome-blur);
}

@supports not (backdrop-filter: blur(1px)) {
  .app-header { background: #101010; }
}

/* De-grid the ledger: horizontal hairlines only. Vertical column rules were
   the strongest spreadsheet signal separating us from a finished product. */
.data-table th + th,
.data-table td + td {
  border-left: 0;
}

.data-table td {
  border-bottom-color: var(--row-rule);
}

/* The column-header band floats as a veil over scrolling rows. */
.data-table th {
  background: var(--thead-veil);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  border-bottom-color: var(--thead-rule);
}

@supports not (backdrop-filter: blur(1px)) {
  .data-table th { background: var(--surface-3); }
}

/* Row hover carries a top light, not just a fill. */
.data-table tbody tr:hover td,
.data-table tbody tr:focus-within td {
  background: var(--surface-hover);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.028);
}

/* Sheen rides sub-plate chrome only; `.panel` itself stays a flat fill. */
.panel-header,
.portfolio-balance-header {
  background-color: var(--surface-3);
  background-image: var(--sheen);
}

/* Primary action reads as a machined stamp. */
.button.primary {
  background-color: #F2F2F2;
  background-image: linear-gradient(180deg, #FFFFFF 0%, #EDEDED 100%);
  border-color: #FFFFFF;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.9), inset 0 -1px 0 rgba(0,0,0,0.18), 0 2px 8px rgba(0,0,0,0.40);
}

.button.primary:hover:not(:disabled) {
  background-image: linear-gradient(180deg, #FFFFFF 0%, #F6F6F6 100%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.95), inset 0 -1px 0 rgba(0,0,0,0.14), 0 3px 10px rgba(0,0,0,0.45);
}

.button.primary:active:not(:disabled) {
  background-image: linear-gradient(180deg, #E9E9E9 0%, #F2F2F2 100%);
  box-shadow: inset 0 1px 2px rgba(0,0,0,0.22);
}

/* Buy/sell stamps keep their colour fill and gain a glass top. */
.column-stamp.buy,
.column-stamp.sell {
  background-image: var(--sheen-strong);
}

/* Recessed inputs: one inner shadow line. */
input:not([type="checkbox"]):not([type="radio"]):not([type="range"]),
select,
textarea {
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.35);
}

/* Floating surfaces get a glass top over their existing fills. */
#top-nav-menu,
.asset-action-popover,
dialog {
  background-image: linear-gradient(180deg, rgba(255,255,255,0.03) 0%, rgba(255,255,255,0) 56%);
}

/* Ledger links read as live evidence. */
.data-table a.identifier { color: var(--info); }
.data-table a.identifier:hover { color: #FFFFFF; }

::-webkit-scrollbar-thumb:hover { background: #4A4A4A; }

/* ------------------------------------------------------------
   R3 interaction physics: two speeds, two curves.
   Hover 140ms out-expo; press 90ms in / 160ms release.
   Focus is instant — never transitioned.
   ------------------------------------------------------------ */
.button, .icon-button, .segmented button, .tabs button,
.filter-pill, .favorite-toggle, .chart-toolbar button,
.watch-tabs button, .side-tabs button, .allocation-mark,
.asset-action-trigger {
  transition:
    background-color var(--duration-hover) var(--ease-out),
    border-color var(--duration-hover) var(--ease-out),
    color var(--duration-hover) var(--ease-out),
    box-shadow var(--duration-hover) var(--ease-out),
    transform var(--duration-release) var(--ease-press);
}

.button:active:not(:disabled),
.icon-button:active:not(:disabled),
.segmented button:active:not(:disabled),
.tabs button:active:not(:disabled),
.filter-pill:active,
.favorite-toggle:active,
.chart-toolbar button:active,
.side-tabs button:active {
  transform: translateY(1px) scale(0.985);
  transition-duration:
    var(--duration-hover), var(--duration-hover), var(--duration-hover),
    var(--duration-hover), var(--duration-press);
}

.data-table tbody tr { transition: background-color 100ms var(--ease-touch); }
.watch-row, .asset-action-item { transition: background-color 100ms var(--ease-touch), color 100ms var(--ease-touch); }
.asset-action-item:active { background: var(--surface-hover-high); }
.book-row { transition: background-color 75ms var(--ease-touch); }
input, select, textarea { transition: border-color 120ms var(--ease-out), background-color 120ms var(--ease-out); }
:focus-visible { transition: none; }

@starting-style {
  .asset-action-popover:popover-open { opacity: 0; transform: translateY(-4px); }
}

.asset-action-popover:popover-open {
  transition: opacity var(--duration-base) var(--ease-out), transform var(--duration-base) var(--ease-out);
}

@media (prefers-reduced-motion: reduce) {
  .button:active:not(:disabled),
  .icon-button:active:not(:disabled),
  .segmented button:active:not(:disabled),
  .tabs button:active:not(:disabled),
  .filter-pill:active, .favorite-toggle:active,
  .chart-toolbar button:active, .side-tabs button:active { transform: none; }
  .asset-action-popover:popover-open { transition: none; }
}

/* Compact phone rows adopt the benchmark 64px rhythm and touch feedback. */
@media (max-width: 599px) {
  .data-table.compact-rows tbody tr { min-height: 64px; padding: 10px 12px; }
  .data-table.compact-rows tbody tr:active { background: var(--surface-hover); }
  .data-table.compact-rows td[data-m="primary"] {
    font-family: var(--font-data);
    font-variant-numeric: tabular-nums slashed-zero;
  }
  .data-table.compact-rows td[data-m="secondary"].num { font-family: var(--font-data); }
  .data-table.compact-rows td[data-m="meta"] { color: var(--muted); }
  .data-table.compact-rows td[data-m="meta"] .status-chip { padding: 2px 8px; }
  .data-table.compact-rows td[data-m="action"] .asset-action-trigger,
  .data-table.compact-rows td[data-m="action"] .favorite-toggle { width: 32px; min-width: 32px; height: 32px; }
  .data-table.compact-rows td[data-m="wide"] a.identifier { color: var(--info); }
}

/* Watchlist control becomes a star glyph rather than a boxed word. */
.favorite-toggle {
  display: inline-grid;
  place-items: center;
  min-width: 32px;
  width: 32px;
  height: 32px;
  padding: 0;
  border-color: transparent;
  border-radius: 6px;
  background: transparent;
  color: #6E6E6E;
}

.favorite-toggle:hover {
  border-color: transparent;
  background: var(--surface-float);
  color: var(--text);
}

.favorite-toggle.active {
  border-color: transparent;
  background: transparent;
  color: var(--warning);
}

.favorite-toggle.active:hover { background: var(--surface-float); }

.favorite-toggle svg { display: block; width: 16px; height: 16px; }
.favorite-toggle svg path { fill: none; stroke: currentColor; stroke-width: 1.25; stroke-linejoin: round; }
.favorite-toggle.active svg path { fill: currentColor; stroke: none; }

/* ------------------------------------------------------------
   Deposit panel: address first, one primary action, policy after.
   ------------------------------------------------------------ */
.wallet-action-panel {
  scroll-margin-top: calc(var(--header-height) + var(--space-2));
}

.wallet-action-loading {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: 112px;
  color: var(--muted);
}

.wallet-action-loading .spinner {
  flex: 0 0 auto;
}

.wallet-action-loading strong {
  display: block;
  color: var(--text);
  font-size: var(--type-body);
}

.wallet-action-loading p {
  margin: var(--space-1) 0 0;
  font-size: var(--type-sm);
}

.deposit-network {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  min-height: 36px;
  padding-bottom: var(--space-2);
  border-bottom: var(--line) solid var(--border-subtle);
}

.deposit-network > span {
  color: var(--muted);
  font-size: var(--type-sm);
}

.deposit-network > strong {
  color: var(--text);
  font-family: var(--font-data);
  font-size: var(--type-sm);
}

.deposit-address {
  margin-top: var(--space-3);
  /* A tap selects the whole address rather than a fragment of it. */
  user-select: all;
  word-break: break-all;
}

.deposit-copy {
  width: 100%;
  margin-top: var(--space-2);
}

@media (max-width: 599px) {
  .deposit-copy { min-height: var(--control-height-touch); }
}

/* ------------------------------------------------------------
   Tablet ledger density (600-1023px)
   Card mode has not engaged yet at these widths, but the full
   desktop cell rhythm overruns the narrower workspace and pushes
   columns behind a sideways scroll. Tightening horizontal padding
   and the figure size keeps every column on screen without hiding
   any data.
   ------------------------------------------------------------ */
@media (min-width: 600px) and (max-width: 1279px) {
  .data-table {
    min-width: 0;
  }

  .data-table th,
  .data-table td {
    padding-inline: var(--space-2);
  }

  .data-table td {
    font-size: var(--type-xs);
  }

  .data-table th {
    font-size: var(--type-2xs);
  }

  /* Identifiers are the widest incompressible cells; cap and ellipsis them
     so they yield space to the numeric columns rather than forcing a scroll. */
  .data-table .identifier {
    display: inline-block;
    max-width: 14ch;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    vertical-align: middle;
  }
}

/* On wide desktop the terminal grid rows are definite, so the ticket should
   occupy its full area instead of leaving a void beneath it. */
@media (min-width: 1280px) {
  .terminal-grid > .trade-ticket {
    align-self: stretch;
  }
}

/* ------------------------------------------------------------
   Touch feel
   The browser's default tap flash is the clearest "web page, not
   app" tell, and several controls sat below the 44px touch
   minimum. Visual sizes are preserved; the hit areas are expanded
   with a centred pseudo-element so nothing shifts in layout.
   ------------------------------------------------------------ */
html {
  -webkit-tap-highlight-color: transparent;
  overscroll-behavior-y: contain;
}

@media (pointer: coarse) {
  #top-nav-menu .asset-action-item,
  .asset-action-popover .asset-action-item {
    min-height: 44px;
  }

  /* Keep the 32px visual button but give it a 44px touch target. */
  .asset-action-trigger,
  .favorite-toggle {
    position: relative;
  }

  .asset-action-trigger::after,
  .favorite-toggle::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 44px;
    height: 44px;
    transform: translate(-50%, -50%);
  }

  /* Checkboxes are 16px glyphs; the label row carries the real target. */
  label:has(> input[type="checkbox"]) {
    min-height: 44px;
    display: flex;
    align-items: center;
  }

  input[type="checkbox"] {
    width: 20px;
    height: 20px;
  }
}

@media (pointer: coarse) {
  /* Home link and in-row evidence links also need a thumb-sized target. */
  .brand {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }

  .data-table a.identifier {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }
}

@media (pointer: coarse) {
  /* The wide evidence line sets a 24px rule for density; on touch the link
     inside it still needs a thumb-sized target. */
  .data-table.compact-rows td[data-m="wide"] a.identifier {
    min-height: 44px;
    line-height: 44px;
  }
}

@media (pointer: coarse) {
  .filter-pill {
    min-height: 40px;
    padding-inline: 16px;
  }

  .market-category-pills {
    width: 100%;
  }

  .filter-pill { flex: 1 1 auto; }
}

/* ============================================================
   R3 follow-up: verified deltas from the independent polish audit.
   ============================================================ */

/* Delta 2: `overflow: auto` on the scroll wrapper made it the sticky
   containing block, so the column-header veil could never pin. `clip` does not
   create a scroll container, so the header binds to the real scroller — the
   panel body inside the terminal, the window elsewhere. */
@media (min-width: 600px) {
  .table-scroll {
    overflow-x: clip;
    overflow-y: visible;
  }

  /* `clip` is not scrollable, so it may only be used where the table is known
     to fit. The operator grids are intentionally denser than the viewport at
     tablet widths, and silently clipping them would make columns unreachable
     rather than merely hidden. */
  .admin-grid .table-scroll {
    overflow-x: auto;
    overflow-y: hidden;
  }

  .data-table th {
    top: var(--header-height);
  }

  .terminal-grid .data-table th {
    top: 0;
  }
}

/* Delta 3: the chart toolbar clipped its own labels at desktop widths, which
   reads as a rendering fault rather than a design. */
@media (min-width: 600px) {
  .chart-panel .panel-header {
    flex-wrap: wrap;
    row-gap: var(--space-1);
  }

  .chart-toolbar {
    flex-wrap: wrap;
    overflow: visible;
  }
}

/* Delta 7: the machined primary is right at phone width but unbalanced when
   stretched across a desktop panel. */
@media (min-width: 900px) {
  .deposit-address { max-width: 560px; }
  .deposit-copy {
    width: auto;
    min-width: 240px;
    padding-inline: var(--space-6);
  }
}

@media (max-width: 599px) {
  /* Delta 4: the change value carries the row's colour, pinned right. */
  .data-table.compact-rows td[data-m="meta"] .change-chip {
    display: inline-block;
    min-width: 72px;
    padding: 5px 8px;
  }

  .data-table.compact-rows td[data-m="secondary"] {
    text-align: right;
  }

  /* Delta 8: legend and the licence-required attribution stop fighting for
     one line on the mobile terminal. */
  .chart-topline { flex-wrap: wrap; }
  .chart-topline .chart-legend { flex: 1 1 100%; }
  .chart-topline .chart-attribution {
    flex: 1 1 100%;
    justify-content: flex-start;
    overflow-x: visible;
    white-space: normal;
  }

  /* iOS zooms the page when a field smaller than 16px receives focus. */
  input, select, textarea { font-size: 16px; }
}

/* Remaining touch targets called out by the audit. */
@media (pointer: coarse) {
  .allocation-mark { min-height: 44px; }
  select { min-height: 44px; }
  .order-column .allocation-slider { height: 44px; min-height: 44px; }

  /* Long-press on a ledger row should not raise a text selection. */
  .data-table tbody tr,
  .watch-row,
  .book-row {
    -webkit-user-select: none;
    user-select: none;
  }
}

/* The row action trigger was wired for transitions but missing from the press
   transform group. */
.asset-action-trigger:active { transform: translateY(1px) scale(0.985); }

@media (prefers-reduced-motion: reduce) {
  .asset-action-trigger:active { transform: none; }
}

/* Ticker monograms stay monochrome: the theme is black and white, so asset
   identity is carried by the letterform and a value step, never by hue.
   Chroma is reserved for functional market direction only. */
.coin-mark {
  background: var(--surface-3);
  border-color: var(--border-strong);
  color: var(--text);
}

/* ------------------------------------------------------------
   Phone terminal section switcher
   The mobile terminal is a single long scroll; a fixed switcher gives
   it app-style section navigation. Desktop keeps the full grid, so the
   control is hidden there.
   ------------------------------------------------------------ */
.terminal-jump {
  display: none;
}

@media (max-width: 599px) {
  .terminal-jump {
    position: fixed;
    z-index: 28;
    right: 0;
    bottom: 0;
    left: 0;
    display: grid;
    grid-auto-columns: 1fr;
    grid-auto-flow: column;
    border-top: var(--line) solid var(--border-strong);
    background: var(--chrome-veil);
    -webkit-backdrop-filter: var(--chrome-blur);
    backdrop-filter: var(--chrome-blur);
    padding-bottom: env(safe-area-inset-bottom);
    box-shadow: 0 -1px 0 #000000, 0 -2px 10px rgba(0, 0, 0, 0.5);
  }

  @supports not (backdrop-filter: blur(1px)) {
    .terminal-jump { background: #101010; }
  }

  .terminal-jump-item {
    min-height: 48px;
    border: 0;
    background: transparent;
    color: var(--subtle);
    font-family: var(--font-data);
    font-size: 11px;
    font-weight: var(--weight-semibold);
    letter-spacing: 0.06em;
    text-transform: uppercase;
  }

  .terminal-jump-item.active {
    color: var(--text-strong);
    box-shadow: inset 0 2px 0 var(--accent);
  }

  .terminal-jump-item:active { background: var(--surface-hover); }

  /* Content must clear the fixed bar. */
  .terminal-shell {
    padding-bottom: calc(48px + env(safe-area-inset-bottom));
  }

  /* Sections land below the pinned masthead when jumped to. */
  .terminal-grid > .panel {
    scroll-margin-top: calc(var(--header-height) + var(--space-2));
  }
}

@media (max-width: 599px) {
  /* The tape is a high-frequency read: one compact line per fill, price left
     carrying its side colour, size right, time beneath. */
  .trades-panel .data-table.compact-rows tbody tr {
    min-height: 44px;
    padding-block: 6px;
  }

  .trades-panel .data-table.compact-rows td[data-m="title"] {
    font-family: var(--font-data);
  }
}


/* View loading and transition states use the existing monochrome surface
   ladder, so navigation gains continuity without adding a brand hue. */
.view-frame {
  min-width: 0;
}

.view-frame.view-entering {
  animation: view-enter var(--duration-base) var(--ease-out) both;
}

@keyframes view-enter {
  from {
    transform: translateY(var(--space-1));
    opacity: 0;
  }
}

.view-skeleton {
  display: grid;
  gap: var(--space-6);
  min-width: 0;
}

.skeleton-heading {
  display: grid;
  gap: var(--space-2);
  margin: var(--space-2) 0 0;
}

.skeleton-line {
  display: block;
  width: 100%;
  height: var(--space-2);
  overflow: hidden;
  border-radius: var(--radius-plate);
  background-color: var(--surface-2);
  background-image: linear-gradient(90deg, var(--surface-2), var(--surface-3), var(--surface-2));
  background-position: 200% 0;
  background-size: 200% 100%;
  animation: skeleton-shimmer calc(var(--duration-base) * 8) linear infinite;
}

.skeleton-line-short {
  width: 24%;
}

.skeleton-line-medium {
  width: 48%;
}

.skeleton-line-wide {
  width: 72%;
}

.skeleton-line-title {
  width: 42%;
  height: var(--space-6);
}

.skeleton-line-description {
  width: 64%;
  height: var(--space-3);
}

@keyframes skeleton-shimmer {
  to {
    background-position: -200% 0;
  }
}

.skeleton-panel-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-3);
  min-width: 0;
}

.skeleton-panel {
  min-width: 0;
  overflow: hidden;
  border: var(--line) solid var(--border);
  border-radius: var(--radius-plate);
  background: var(--surface-2);
  box-shadow: var(--shadow-panel);
}

.skeleton-panel-header {
  display: flex;
  align-items: center;
  min-height: var(--panel-header-height);
  padding: var(--space-2) var(--panel-padding);
  border-bottom: var(--line) solid var(--border-strong);
  background: var(--surface-3);
}

.skeleton-panel-header .skeleton-line {
  background-color: var(--surface-1);
  background-image: linear-gradient(90deg, var(--surface-1), var(--surface-2), var(--surface-1));
}

.skeleton-panel-fill {
  display: grid;
  align-content: center;
  gap: var(--space-4);
  min-height: calc(var(--space-10) * 2);
  padding: var(--space-6);
  background: var(--surface-2);
}

.skeleton-panel-fill-chart {
  min-height: calc(var(--space-10) * 4);
  background: var(--surface-1);
}

.skeleton-panel-fill-summary {
  min-height: calc(var(--space-10) * 2);
}

.skeleton-ledger {
  background: var(--surface-1);
}

.skeleton-ledger-head,
.skeleton-ledger-row {
  display: grid;
  grid-template-columns: minmax(0, 2fr) repeat(3, minmax(0, 1fr));
  align-items: center;
  gap: var(--space-6);
  min-height: var(--control-height-compact);
  padding: var(--space-2) var(--space-3);
  border-bottom: var(--line) solid var(--border);
}

.skeleton-ledger-head {
  background: var(--surface-3);
}

.skeleton-ledger-row {
  min-height: var(--control-height);
}

.skeleton-ledger-row:last-child {
  border-bottom: 0;
}

.view-skeleton-markets .skeleton-panel,
.view-skeleton-orders .skeleton-panel,
.view-skeleton-portfolio .skeleton-panel:nth-child(2),
.view-skeleton-security .skeleton-panel:nth-child(2) {
  grid-column: 1 / -1;
}

.view-skeleton-trade .skeleton-panel:first-child {
  grid-row: span 2;
}

@media (max-width: 599px) {
  .view-skeleton {
    gap: var(--space-4);
  }

  .skeleton-heading {
    padding-inline: var(--space-2);
  }

  .skeleton-line-short {
    width: 36%;
  }

  .skeleton-line-title {
    width: 64%;
  }

  .skeleton-line-description {
    width: 88%;
  }

  .skeleton-panel-grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .skeleton-panel {
    grid-column: 1 / -1 !important;
    grid-row: auto !important;
  }

  .skeleton-panel-fill-chart {
    min-height: calc(var(--space-10) * 3);
  }

  .skeleton-ledger-head {
    display: none;
  }

  .skeleton-ledger-row {
    grid-template-columns: minmax(0, 1fr) minmax(var(--space-10), 32%);
    gap: var(--space-2) var(--space-4);
    min-height: calc(var(--control-height-touch) + var(--space-4));
    padding: var(--space-3);
  }

  .skeleton-ledger-row .skeleton-line:nth-child(n + 3) {
    display: none;
  }

  .toast {
    padding-inline: var(--space-3);
  }
}

@media (prefers-reduced-motion: reduce) {
  .view-frame.view-entering,
  .skeleton-line,
  .toast,
  .toast.leaving {
    animation: none;
    transform: none;
  }
}
/* =========================================================================
   R4 PREMIUM MONOCHROME — type ladder repair, chroma retirement, seam craft
   -------------------------------------------------------------------------
   Two measured defects drive this layer.

   1. The sans weight ladder was collapsed. Only the Space Grotesk 400 and
      700 faces are self-hosted, yet h1, table headers and panel titles all
      declared weight 600. CSS font matching resolves an unavailable 600
      upward, so an 11px column header rendered at the same 700 as the 26px
      headline. Nothing in the chrome had a middle weight. The 500 face is
      loaded and unused; this layer puts it to work so a real 400/500/700
      ladder exists.

   2. The chrome spoke in mono uppercase almost everywhere (~85% of glyphs
      at 390px), which is the register of a terminal readout rather than a
      product. Rule from here on: if a human wrote the string it is sans;
      if the machine produced it (figure, ticker, identifier, timestamp,
      state code) it stays mono.
   ========================================================================= */

:root {
  /* Value ladder. White must stay scarce to read as premium, so it is
     reserved for data and active state, never for chrome labels. */
  --ink-2: #D6D6D6;
  --ink-5: #6E6E6E;
  --ink-disabled: #4A4A4A;
  /* Seam system. Four hairline weights were competing within 110px of the
     markets panel; these collapse them to a hierarchy. */
  --seam: #242424;
  --row-rule: #1C1C1C;
  --thead-rule: #2E2E2E;
  --radius-float: 8px;
}

/* --- Type: human strings become sans ----------------------------------- */

/* View eyebrow was mono 14/600 caps: a machine label on top of an editorial
   heading. Sans 11 caps is the same signal without the terminal voice. */
.eyebrow,
/* `.view-heading p` is specificity 0,1,1 and the eyebrow is a <p> inside it,
   so a bare `.eyebrow` loses no matter how late it appears in the file. */
.view-heading .eyebrow {
  color: var(--subtle);
  font: var(--weight-medium) var(--type-micro) / 1 var(--font-sans);
  letter-spacing: 0.1em;
}

/* h1 declared 600 (rendered 700 by fallback). Made explicit and given the
   size and negative tracking that carry a headline. */
.view-heading h1 {
  font-family: var(--font-sans);
  font-size: 28px;
  font-weight: var(--weight-bold);
  line-height: 1.1;
  letter-spacing: -0.02em;
}

/* Panel titles step down from #FFFFFF: they are wayfinding, not data. */
.panel-header h2,
.panel-header h3 {
  color: var(--ink-2);
  font-family: var(--font-sans);
  font-size: var(--type-body);
  font-weight: var(--weight-bold);
  letter-spacing: -0.01em;
}

/* Column headers: the institutional ledger band. Caps at 10 with tracking
   reads as structure; at 11/700 it competed with the row content. */
.data-table th {
  color: var(--subtle);
  border-bottom: var(--line) solid var(--thead-rule);
  font: var(--weight-medium) 10px / 1 var(--font-sans);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* Segmented controls, tabs and filter pills carried mono caps. Their labels
   are already written in sentence case in app.js; the uppercase was applied
   in CSS, so dropping it restores the authored words. */
.segmented button,
.tab-button,
.filter-pill,
.market-category-pills button {
  font-family: var(--font-sans);
  font-weight: var(--weight-medium);
  letter-spacing: 0.01em;
  text-transform: none;
}

.segmented button.active,
.tab-button.active,
.filter-pill.active,
.market-category-pills button.active {
  color: var(--text-strong);
  font-weight: var(--weight-bold);
}

/* --- Chroma retirement -------------------------------------------------- */
/* Only price direction, order side, pending, and destructive keep colour.
   Everything below was decorative and is converted to value. */

.status-chip.good {
  color: var(--ink-2);
  border-color: rgba(255, 255, 255, 0.18);
  background: transparent;
}

.status-chip.info {
  color: var(--subtle);
  border-color: var(--border);
  background: transparent;
}

/* Explorer links were blue. Underline plus value carries "this leaves the
   app" without spending a hue on it. */
.data-table a.identifier {
  color: var(--ink-2);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.data-table a.identifier:hover {
  color: var(--text-strong);
}

/* The volume figure was gold; the chart attribution hover was blue. */
.chart-legend .volume-figure {
  color: var(--muted);
}

.chart-attribution {
  height: 20px;
  font-size: 10px;
}

.chart-attribution,
.chart-attribution a {
  color: var(--ink-5);
}

.chart-attribution a:hover {
  color: var(--ink-2);
}

/* Watchlist star was amber. A filled white star is the stronger signal in a
   monochrome field anyway. */
.favorite-toggle.active {
  color: var(--text-strong);
}

/* --- Seam and surface craft -------------------------------------------- */

/* The markets toolbar sat at #161616 between the #1F1F1F header band and the
   #0E0E0E field: a three-step lightness flicker across 144px. Dropping it to
   the field value makes the panel read as one band over one field. */
.markets-topbar {
  background: var(--surface-1);
  border-bottom-color: var(--seam);
}

/* Row rules and internal seams separated from interactive control borders.
   --border-strong (#404040) is now reserved for controls only. */
.data-table tbody tr + tr td {
  border-top-color: var(--row-rule);
}

/* Radius 6 is retired: plates 0, controls 4, floating surfaces 8. */
.dropdown-menu,
#top-nav-menu {
  border-radius: var(--radius-float);
}

/* A 3px double border is a Victorian rule; statements get single hairlines. */
.statement-line {
  border-width: var(--line) 0;
  border-style: solid;
  border-color: var(--border);
}

/* Disabled state used opacity, which muddied text, border and fill together.
   Value-only dimming keeps edges crisp. */
button:disabled,
select:disabled,
input:disabled {
  opacity: 1;
  color: var(--ink-disabled);
  border-color: var(--border-subtle);
  background: transparent;
}

/* --- Measured layout defects ------------------------------------------- */

@media (max-width: 599px) {
  :root {
    /* Heading text sat at x12 while panels sat at x8: a 4px jog down the
       whole left edge of every phone view. One value fixes both. */
    --workspace-padding: 12px;
  }

  /* The legend used nowrap with a hidden scrollbar, so the volume figure was
     silently truncated at the right edge instead of wrapping. */
  .chart-legend {
    flex-wrap: wrap;
    row-gap: 4px;
    overflow: visible;
  }
}

/* Dormant data: a market with no trades yet, an absent high/low. It must
   recede so that real figures own the white. Measured before this rule:
   "No fills" rendered #FFFFFF at weight 700, the loudest cell in the row. */
.data-table td .dormant,
.data-table td.num .dormant {
  color: var(--ink-5);
  font-weight: 400;
}

@media (max-width: 599px) {
  /* Uniform phone ledger rows. Measured 98/86/98/85 before this rule: the
     row height tracked its content, so a market with a padded change chip
     stood 12px taller than one showing a dash. Pinning both grid tracks
     makes the rag a straight line. Rows carrying a full-width `wide` cell
     (transaction links) are excluded — they legitimately need a third row. */
  .data-table.compact-rows tbody tr:not(:has(td[data-m="wide"])) {
    grid-template-rows: 22px 20px;
    height: 68px;
    min-height: 0;
    padding: var(--space-3);
  }

  /* The chip's own padding was what inflated line two. */
  .data-table.compact-rows td[data-m="meta"] .change-chip {
    padding: 2px 8px;
  }

  /* Last blue link in the app: this selector is specificity 0,4,1 and beat
     the earlier monochrome rule for `.data-table a.identifier`. */
  .data-table.compact-rows td[data-m="wide"] a.identifier {
    color: var(--ink-2);
  }
}/* Orders composition: preserve heading controls and replace the empty canvas. */
.view-heading .segmented {
  flex: 0 0 auto;
  overflow: visible;
}

.view-heading .heading-actions {
  flex-wrap: wrap;
  column-gap: var(--space-3);
  row-gap: var(--space-2);
}

.orders-compose-orders-panel > .panel-body {
  padding: 0;
}

.orders-compose-empty {
  gap: var(--space-4);
  min-height: 280px;
  padding: var(--space-7) var(--space-6);
}

.orders-compose-empty .empty-state-copy {
  gap: var(--space-2);
  max-width: 44ch;
}

.orders-compose-empty h3 {
  color: var(--text-strong);
  font-family: var(--font-sans);
  font-size: var(--type-title);
  font-weight: var(--weight-bold);
  line-height: 1.2;
}

.orders-compose-empty p {
  max-width: 44ch;
  color: var(--muted);
  font-family: var(--font-sans);
  font-size: var(--type-sm);
  font-weight: 400;
  line-height: var(--leading-body);
}

.orders-compose-empty .empty-state-action {
  gap: var(--space-2);
  margin-top: 0;
}

.orders-compose-empty .orders-compose-action {
  height: 36px;
  min-height: 36px;
  border-radius: var(--radius-control);
}

.orders-compose-terms-panel {
  margin-top: var(--space-6);
  border-color: var(--border);
  border-radius: var(--radius-plate);
  background: var(--surface-2);
}

.orders-compose-terms-panel > .panel-header {
  height: 44px;
  min-height: 44px;
  padding: 0 var(--space-4);
  border-bottom-color: var(--border);
  background: var(--surface-3);
}

.orders-compose-terms-panel > .panel-header h2 {
  color: var(--ink-2);
  font-family: var(--font-sans);
  font-size: var(--type-body);
  font-weight: var(--weight-bold);
  line-height: 1;
}

.orders-compose-terms-panel > .panel-body {
  padding: 0;
  background: var(--surface-2);
}

.orders-compose-terms-list {
  min-width: 0;
}

.orders-compose-term-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  height: 28px;
  min-height: 28px;
  padding: 0 var(--space-4);
}

.orders-compose-term-row + .orders-compose-term-row {
  border-top: var(--line) solid var(--row-rule);
}

.orders-compose-term-key {
  flex: 0 0 auto;
  min-width: 0;
  color: var(--subtle);
  font-family: var(--font-sans);
  font-size: var(--type-xs);
  font-weight: 400;
  line-height: 1;
  white-space: nowrap;
}

.orders-compose-term-value {
  min-width: 0;
  color: var(--ink-2);
  font-family: var(--font-data);
  font-size: var(--type-xs);
  font-weight: var(--weight-medium);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  line-height: 1;
  text-align: right;
  white-space: nowrap;
}

@media (max-width: 599px) {
  .orders-compose-empty {
    min-height: 240px;
  }

  .orders-compose-term-row {
    align-items: flex-start;
    height: auto;
    padding-block: var(--space-2);
  }

  .orders-compose-term-key,
  .orders-compose-term-value {
    line-height: 1.4;
  }

  .orders-compose-term-value {
    white-space: normal;
  }
}

/* The chart topline docks the OHLC legend and the licence attribution in one
   row. The attribution is nowrap and ~300px wide, so on a 1440 terminal it
   squeezed the legend, whose `overflow-x: auto` plus hidden scrollbar then
   truncated HIGH / LOW / CLOSE / VOLUME without any visible affordance.
   Measured: legend and attribution vertical ranges intersected, and only
   "OPEN 100.4 H" survived. Allowing the row to wrap keeps both readable:
   they share a line when there is room and the attribution drops beneath
   when there is not. Height stays on --chart-attribution-height so the
   chart's calc() sizing is unaffected. */
.chart-topline {
  flex-wrap: wrap;
}

.chart-topline .chart-legend {
  flex: 1 1 320px;
  flex-wrap: wrap;
  row-gap: 2px;
  overflow: visible;
}

.orders-compose-export-select {
  flex: 0 0 auto;
  width: auto;
}

/* =========================================================================
   R5 LIT SURFACES — the wireframe-versus-solid correction
   -------------------------------------------------------------------------
   Sixth design pass. The founder could see and feel a gap but not name it.
   Measured answer: our boxes are DRAWN, the references' are LIT.

   A resting button here is a #161616 fill inside a #4A4A4A border, so the
   outline sits 3.4x brighter than the surface it encloses — the loudest
   luminance event on the screen. The measured reference edge is 1.07x: a
   whisper. Premium dark UIs define a box by MASS (a lighter slab on a darker
   page), cut WELLS into that slab for inputs, and show state as translucent
   light washing over the same material. We had inverted all three: quiet
   fills, loud wireframe, opaque state swaps, and inputs sitting BRIGHTER
   than the panel that supposedly contains them.

   Three corrections, in order of perceptual weight.
   ========================================================================= */

:root {
  /* 1. Demote the resting edge. Rest lands at 1.6x fill instead of 3.4x —
        still scannable on #161616, no longer shouting. */
  --border-control: #2E2E2E;
  /* Interaction now RAISES edge contrast. Previously hover moved the border
     to --border-strong #404040, ten steps DARKER than rest, so touching a
     control made its outline retreat. That is inverted physics. */
  --edge-hover: #4A4A4A;

  /* 2. State as translucent light over one material, not an opaque swap.
        Opaque greys erased the depth tint, zebra banding and inset accent
        bars underneath them. */
  --wash-hover: rgb(255 255 255 / 0.045);
  --wash-press: rgb(255 255 255 / 0.08);
  --wash-selected: rgb(255 255 255 / 0.06);

  /* 3. Wells: an input belongs BELOW its host surface. Ticket fields were
        #1F1F1F on a #161616 panel — nine steps above the thing containing
        them, a raised sticker claiming to be a hole. */
  --well: #0E0E0E;
  --well-modal: #1A1A1A;

  /* Row cadence without a grid: +11 steps over the field instead of +14. */
  --row-rule: #191919;

  /* Glass that actually transmits. At 0.78/0.82 we paid the render cost of a
     backdrop blur while passing almost nothing through it, which is
     indistinguishable from paint. */
  --chrome-veil: rgba(16, 16, 16, 0.68);
  --thead-veil: rgba(31, 31, 31, 0.72);

  /* A dialog should win against its backdrop. */
  --backdrop: rgb(0 0 0 / 0.80);

  /* A favourite is a personal mark, not system state, so it is the one place
     colour is earned in an otherwise monochrome product. */
  --favorite: #E3B341;

  /* Width the pair rail keeps when collapsed, enough for its reopen control. */
  --rail-collapsed: 30px;
}

/* --- Correction 1: edges quiet at rest, brighter under the hand ---------- */

@media (hover: hover) and (pointer: fine) {
  .button:hover:not(:disabled),
  .icon-button:hover:not(:disabled),
  .segmented button:hover:not(:disabled),
  .tabs button:hover:not(:disabled) {
    border-color: var(--edge-hover);
  }
}

/* Controls pick up the same top-lit direction the panels already use, so the
   light in the product agrees with itself. */
.button,
.icon-button {
  box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.04);
}

/* --- Correction 2: translucent washes on shared material ---------------- */
/* Scoped to elements that sit ON a surface they do not own. Full-surface
   buttons keep their opaque fills. */

@media (hover: hover) and (pointer: fine) {
  .watch-row:hover,
  .book-row:hover,
  .market-link:hover,
  .filter-pill:hover:not(:disabled),
  .market-category-pills button:hover:not(:disabled),
  .asset-action-item:hover:not(:disabled),
  .data-table tbody tr:hover td {
    background-color: var(--wash-hover);
  }
}

.watch-row.active,
.filter-pill.active,
.market-category-pills button.active,
.asset-action-item.active {
  background-color: var(--wash-selected);
  color: var(--text-strong);
}

/* --- Correction 3: wells are cut in, and stay cut while focused --------- */

.order-column input,
.order-column select,
.market-search.watch-search,
.book-tick-select {
  background: var(--well);
}

dialog input,
dialog select,
dialog textarea {
  background: var(--well-modal);
}

/* The base sheet sets `input:focus { box-shadow: none }`, which deleted the
   machined recess at the exact moment of attention — rest and focus computed
   identical. The ring is drawn as a box-shadow hugging the radius so the well
   survives underneath it, and no layout shifts. */
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
  outline: none;
  border-color: var(--focus);
  box-shadow:
    0 0 0 2px rgb(255 255 255 / 0.28),
    inset 0 1px 2px rgb(0 0 0 / 0.35);
}

/* Hovering a well must not lift it brighter than its host. */
@media (hover: hover) and (pointer: fine) {
  input:hover:not(:disabled),
  select:hover:not(:disabled),
  textarea:hover:not(:disabled) {
    background: var(--well);
    border-color: var(--edge-hover);
  }
}

/* Loading should read as composed rather than nervous: the sweep was 1440ms
   against a 2000ms reference. */
.skeleton-line {
  animation-duration: calc(var(--duration-base) * 12);
}

/* --- Favourites are gold ------------------------------------------------ */
/* The star is built through svgIcon with stroke: currentColor and fill: none,
   so colour drives the outline and the fill is promoted only when active. */
.favorite-toggle.active {
  border-color: transparent;
  background: transparent;
  color: var(--favorite);
}

.favorite-toggle.active svg {
  fill: var(--favorite);
  stroke: var(--favorite);
}

/* --- Collapsible watchlist rail ---------------------------------------- */
/* The trade view carries a persistent pair rail. On a narrow desktop or when
   the founder wants the chart to breathe, it collapses; the grid falls back to
   the same templates used at widths where the rail never appears. */
/* The collapse control sits in the rail it governs. Compact, square, and
   never wider than the collapsed gutter it has to survive inside. */
.watch-collapse {
  flex: 0 0 auto;
  width: 22px;
  min-width: 0;
  min-height: 22px;
  height: 22px;
  padding: 0;
  border-color: transparent;
  background: transparent;
  color: var(--subtle);
}

@media (hover: hover) and (pointer: fine) {
  .watch-collapse:hover {
    color: var(--text-strong);
    border-color: var(--edge-hover);
  }
}

/* Collapsed, the rail keeps a slim gutter so its own reopen button survives.
   Hiding the rail outright removed the only control that could bring it back. */
.watchlist-collapsed {
  width: var(--rail-collapsed);
  min-width: 0;
  padding: var(--space-2) 0;
  align-items: center;
  overflow: hidden;
}

.watchlist-collapsed .watch-collapse {
  margin-inline: auto;
}

@media (min-width: 1280px) {
  .terminal-shell.watch-hidden .terminal-grid {
    grid-template-columns:
      var(--rail-collapsed)
      minmax(0, var(--chart-flex, 1fr))
      minmax(300px, var(--terminal-ticket-column))
      minmax(var(--terminal-book-min), 0.8fr);
  }
}

@media (min-width: 1024px) and (max-width: 1279px) {
  .terminal-shell.watch-hidden .terminal-grid {
    grid-template-columns: var(--rail-collapsed) minmax(0, 1fr) minmax(320px, var(--terminal-ticket-column));
  }
}

/* ============================================================
   UNIVERSAL MONOCHROME INTERACTION PHYSICS
   The browser tap flash is intentionally transparent, so every tappable
   surface supplies its own hover, press and keyboard-focus acknowledgement.
   Rows depress in place; compact controls carry the restrained 0.97 scale.
   ============================================================ */

:root {
  --radius-control: 6px;
}

.filter-pill,
.market-category-pills button,
.markets-topbar .market-search,
.segmented {
  border-radius: var(--radius-control);
}

/* A live external reference is actionable evidence, but never masquerades as
   this venue's own last trade: white remains reserved for locally filled data. */
.reference-price {
  color: var(--muted);
  font-family: var(--font-data);
  font-variant-numeric: tabular-nums;
}

/* All current and future buttons share one physical contract. The explicit
   role/onclick branches cover non-native controls without inventing classes. */
:is(button, select, [role="button"], [onclick]):not(:disabled):not([aria-disabled="true"]) {
  transform-origin: center;
  transition:
    background-color var(--duration-fast) var(--ease-out),
    transform var(--duration-fast) var(--ease-out);
}

:is(a[href], summary):not([aria-disabled="true"]),
label:has(> input:is([type="checkbox"], [type="radio"]):not(:disabled)),
input[type="range"]:not(:disabled) {
  transition: background-color var(--duration-fast) var(--ease-out);
}

.market-link .coin-mark {
  transition: background-color var(--duration-fast) var(--ease-out);
}

:is(button, select, [role="button"], [onclick]):not(:disabled):not([aria-disabled="true"]):active {
  background-color: var(--surface-hover-high);
  transform: scale(0.97);
}

/* A filled primary reverses while held so its dark label never disappears
   against the pressed dark surface. Destructive controls retain their
   functional text and border colour. */
.button.primary:active:not(:disabled) {
  color: var(--text-strong);
}

:is(a[href], summary):not([aria-disabled="true"]):active,
label:has(> input:is([type="checkbox"], [type="radio"]):not(:disabled)):active,
input[type="range"]:not(:disabled):active {
  background-color: var(--surface-hover-high);
}

.market-link:active:not(:disabled) .coin-mark {
  background-color: var(--surface-hover-high);
}

/* Ledger, watchlist, book and tape rows must not scale: scaled data blurs and
   moves adjacent rows. A surface step plus a low-alpha white inset is the
   stationary equivalent of a physical depression. */
:is(.watch-row, .book-row):not(:disabled):not([aria-disabled="true"]) {
  transition: background-color var(--duration-fast) var(--ease-out);
}

:is(.watch-row, .book-row):not(:disabled):not([aria-disabled="true"]):active {
  background-color: var(--wash-press);
  box-shadow: inset 1px 0 0 rgb(255 255 255 / 0.28);
  transform: none;
}

.data-table tbody tr:has(.market-link) > td,
.market-trades-table tbody tr > td {
  transition: background-color var(--duration-fast) var(--ease-out);
}

.data-table tbody tr:has(.market-link):active > td,
.market-trades-table tbody tr:active > td {
  background-color: var(--wash-press);
}

.data-table tbody tr:has(.market-link):active > td:first-child,
.market-trades-table tbody tr:active > td:first-child {
  box-shadow: inset 1px 0 0 rgb(255 255 255 / 0.28);
}

/* Hover is a capability, not a sticky post-tap state. No transform belongs in
   this block: a pointer lifts the surface by one value step only. */
@media (hover: hover) and (pointer: fine) {
  :is(button, select, [role="button"], [onclick]):not(:disabled):not([aria-disabled="true"]):hover,
  :is(a[href], summary):not([aria-disabled="true"]):hover,
  label:has(> input:is([type="checkbox"], [type="radio"]):not(:disabled)):hover,
  input[type="range"]:not(:disabled):hover {
    background-color: var(--surface-hover);
  }

  .button.primary:hover:not(:disabled) {
    background-color: var(--accent-strong);
    color: var(--accent-ink);
  }

  .market-link:hover:not(:disabled) .coin-mark {
    background-color: var(--surface-hover-high);
  }

  :is(.watch-row, .book-row):not(:disabled):not([aria-disabled="true"]):hover {
    background-color: var(--wash-hover);
  }

  .data-table tbody tr:has(.market-link):hover > td,
  .market-trades-table tbody tr:hover > td {
    background-color: var(--wash-hover);
  }
}

/* A two-pixel outer ring is visible without changing geometry. Checkbox and
   radio labels receive the same ring when their nested control owns focus. */
:is(button, select, [role="button"], [onclick]):not(:disabled):not([aria-disabled="true"]):focus-visible,
:is(a[href], summary):not([aria-disabled="true"]):focus-visible,
input[type="range"]:not(:disabled):focus-visible,
label:has(> input:is([type="checkbox"], [type="radio"]):not(:disabled):focus-visible) {
  outline: 2px solid rgb(255 255 255 / 0.9);
  outline-offset: 2px;
}

.market-link:focus-visible .coin-mark {
  background-color: var(--surface-hover-high);
}

@media (prefers-reduced-motion: reduce) {
  :is(button, select, [role="button"], [onclick]):not(:disabled):not([aria-disabled="true"]):active {
    transform: none;
  }
}

@media (max-width: 599px) {
  .panel,
  .terminal-grid > .panel {
    border-radius: 10px;
  }
}

/* Two pointer surfaces the coverage audit found still inert: the masthead
   wordmark, which navigates home, and the skip link, which is the first thing a
   keyboard user touches. Both are real navigation and must acknowledge a press
   like everything else. Measured before this rule: 200 of 261 pointer-cursor
   elements had a press state; these were the only unclassed genuine gaps. */
.brand:active,
.skip-link:active {
  transform: scale(0.97);
  transform-origin: center;
}

@media (hover: hover) and (pointer: fine) {
  .brand:hover {
    background-color: var(--wash-hover);
  }
}

.brand:focus-visible,
.skip-link:focus-visible {
  outline: 2px solid rgb(255 255 255 / 0.9);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  .brand:active,
  .skip-link:active {
    transform: none;
  }
}

/* Final two pointer surfaces with no press acknowledgement: the 24h market
   details disclosure on the trade view, and the checkbox labels that toggle
   "hide zero assets" and "this pair only". A label wrapping a checkbox is a
   real tap target and was landing dead. */
.market-details-toggle:active:not(:disabled),
label.hide-zero:active {
  transform: scale(0.97);
  transform-origin: center;
}

@media (hover: hover) and (pointer: fine) {
  .market-details-toggle:hover:not(:disabled),
  label.hide-zero:hover {
    background-color: var(--wash-hover);
  }
}

@media (prefers-reduced-motion: reduce) {
  .market-details-toggle:active:not(:disabled),
  label.hide-zero:active {
    transform: none;
  }
}

/* =========================================================================
   R6 EARNED COLOUR
   -------------------------------------------------------------------------
   The founder opened the monochrome doctrine: colour is welcome where it adds
   depth and life, gold on a favourite being the industry-standard template.

   The governing test, and it is strict enough to reject future proposals:
   colour must state a currently-true fact about market, money, or connection
   that grey misses at a glance. Chrome and interaction stay achromatic,
   because in this product WHITE is the accent. Every colour gets exactly one
   job, at least 3:1 contrast, and a non-colour cue carrying the same meaning.

   The deliberate refusal: all three benchmarked exchanges spend colour on
   interactive accent (Kraken #7132F5 across 469 declarations, SafeTrade
   #0095FF, AnonKYC #FF6600). We spend white, which measures 19.3:1 on our
   field against Kraken purple's 3.2:1. The refusal is the brand.
   ========================================================================= */

:root {
  /* Recognised asset brand colours. These are not decoration: they import
     knowledge the user already has from the wider market, which is why they
     succeed where the earlier hash-derived hues failed. A generated hue stated
     something untrue about an asset and was applied to everything; these state
     a real identity and are caged to a single glyph. */
  --asset-btc: #F7931A;
  --asset-xmr: #FF6600;
  --asset-zec: #ECB244;
  --asset-usdt: #26A17B;
}

/* Caged strictly to the monogram glyph and a faint ring. Rows, prices, discs,
   balances and buttons NEVER take asset colour — the moment an asset hue
   touches a figure it starts competing with price direction, which is the one
   meaning that must never be ambiguous in an exchange. NOCK has no recognised
   brand colour and stays ink; SOV stays white, because the house colour IS its
   brand. The letters remain the non-colour cue. */
.coin-mark[data-asset="BTC"] {
  color: var(--asset-btc);
  border-color: color-mix(in srgb, var(--asset-btc) 28%, transparent);
}

.coin-mark[data-asset="XMR"] {
  color: var(--asset-xmr);
  border-color: color-mix(in srgb, var(--asset-xmr) 28%, transparent);
}

.coin-mark[data-asset="ZEC"] {
  color: var(--asset-zec);
  border-color: color-mix(in srgb, var(--asset-zec) 28%, transparent);
}

.coin-mark[data-asset="USDT"] {
  color: var(--asset-usdt);
  border-color: color-mix(in srgb, var(--asset-usdt) 28%, transparent);
}

/* Connection health is a currently-true fact that grey hides. The dot reuses
   the existing direction and warning hues rather than introducing new ones,
   and the adjacent word ("Feed OK", "Feed stale") is the non-colour cue. */
.feed-state.current {
  color: var(--up);
}

.feed-state.stale {
  color: var(--warning);
}

/* Watchlist tick flash. Reuses the trade tape's existing 240ms decay keyframe,
   which paints `currentColor` at 9% and fades to transparent, so this adds
   motion and zero standing pixels. Direction is also carried by the price
   moving, so colour is never the sole cue. */
.watch-row.tick-up {
  color: var(--up);
  animation: trade-flash-decay 240ms var(--ease-out) 1;
}

.watch-row.tick-down {
  color: var(--down);
  animation: trade-flash-decay 240ms var(--ease-out) 1;
}

@media (prefers-reduced-motion: reduce) {
  .watch-row.tick-up,
  .watch-row.tick-down {
    animation: none;
  }
}

/* Users who ask for more contrast get the meaning without the hue. */
@media (prefers-contrast: more) {
  .coin-mark[data-asset] {
    color: var(--text-strong);
    border-color: var(--border-strong);
  }
}

@media (forced-colors: active) {
  .coin-mark[data-asset] {
    color: CanvasText;
    border-color: CanvasText;
  }
}

/* =========================================================================
   R7 COMPOSED FIGURES AND THE DISPLAY TIER
   -------------------------------------------------------------------------
   Mined from Coinbase's shipped design system (@coinbase/cds-web 9.10.2 and
   @coinbase/cds-common 9.10.2 on npm; coinbase.com itself is Cloudflare-blocked
   from here, so the package tokens are the evidence and they are authoritative
   rather than scraped).

   Two findings drive this layer.

   1. Money is a composition, not a string. Their money renderer ships separate
      styled parts for symbol, value and affix. Ours printed one flat run, so in
      `100.400000` the five trailing zeros shouted as loudly as the leading 1.
      Nothing here rounds anything away: the full precision stays on screen, it
      is simply ranked so magnitude arrives first and dust arrives last.

   2. Their type ladder steps 1.25-1.43x per tier (16 -> 20 -> 28 -> 40 -> 48 ->
      64) and every display size is weight 400, with 600 the maximum weight
      anywhere in the system. Ours stepped 1.07-1.18x at the top and made
      everything large weight 700. Big and quiet reads as authority; small and
      bold reads as dense chrome.
   ========================================================================= */

:root {
  --type-display: 40px;
  /* Trailing insignificant zeros. Dimmer than --ink-5 placeholders because
     this is real precision, not absent data - it must be legible on demand
     without competing with the significant digits. */
  --figure-dust: #5A5A5A;
}

.figure {
  font-variant-numeric: tabular-nums slashed-zero;
  white-space: nowrap;
}

.figure-dust {
  color: var(--figure-dust);
}

.figure-unit {
  margin-left: 0.4em;
  color: var(--muted);
  font-family: var(--font-sans);
  font-size: 0.68em;
  font-weight: var(--weight-medium);
  letter-spacing: 0.06em;
}

/* The hero balance is the one figure that earns display size. Weight 500 at
   40px, not 700: the size carries the authority so the weight does not have to. */
.portfolio-balance-total strong {
  font-family: var(--font-data);
  font-size: var(--type-display);
  font-weight: var(--weight-medium);
  line-height: 1.2;
  letter-spacing: -0.01em;
}

.portfolio-balance-total .figure-frac,
.portfolio-balance-total .figure-dust {
  font-size: 0.55em;
  font-weight: 400;
}

.portfolio-balance-total .figure-unit {
  font-size: 0.34em;
}

/* Weight inversion at display sizes. Anything 28px and over stops being bold. */
.view-heading h1 {
  font-weight: var(--weight-medium);
  line-height: 1.28;
}

@media (max-width: 599px) {
  :root {
    --type-display: 30px;
  }
}

/* A price that changes should say so in the figure itself, not only by tinting
   its row. 600ms is long enough to notice and short enough not to linger. */
@keyframes price-pulse-up {
  from { color: var(--up); }
}

@keyframes price-pulse-down {
  from { color: var(--down); }
}

.watch-row.tick-up .watch-price {
  animation: price-pulse-up 600ms var(--ease-out) 1;
}

.watch-row.tick-down .watch-price {
  animation: price-pulse-down 600ms var(--ease-out) 1;
}

@media (prefers-reduced-motion: reduce) {
  .watch-row.tick-up .watch-price,
  .watch-row.tick-down .watch-price {
    animation: none;
  }
}

@media (prefers-contrast: more) {
  .figure-dust {
    color: var(--muted);
  }
}

/* The approximation sign is chrome around a figure, not part of it. */
.figure-approx {
  color: var(--subtle);
  font-family: var(--font-data);
}

/* Ledger figures keep their cell size; only the ranking changes. */
.data-table .figure-frac {
  font-size: 1em;
}

/* A pre-existing `.portfolio-balance-total span` rule (0,1,1) was written when
   the only span in this block was the BTC conversion line. The composed figure
   introduces spans INSIDE the hero <strong>, which that rule then captured and
   reset to 14px muted — so the em-based part sizes compounded off 14px and the
   fraction rendered at 7.7px with the unit at 4.76px. These selectors carry
   enough specificity to restore inheritance from the hero itself. */
.portfolio-balance-total strong .figure,
.portfolio-balance-total strong .figure-int {
  color: var(--text-strong);
  font: inherit;
}

.portfolio-balance-total strong .figure-frac {
  color: var(--text-strong);
  font-size: 0.6em;
  font-weight: 400;
}

.portfolio-balance-total strong .figure-dust {
  color: var(--figure-dust);
  font-size: 0.6em;
  font-weight: 400;
}

.portfolio-balance-total strong .figure-unit {
  color: var(--muted);
  font-family: var(--font-sans);
  font-size: 0.34em;
  font-weight: var(--weight-medium);
}

/* Nav items that need a session: present so the product's scope is visible,
   clearly not yet available. Dimmed text plus a lock glyph, so the state does
   not rely on colour alone. */
#top-nav-menu .asset-action-item.gated {
  color: var(--ink-5);
}

#top-nav-menu .asset-action-item.gated::after {
  content: "";
  width: 10px;
  height: 10px;
  margin-left: auto;
  border: var(--line) solid currentColor;
  border-bottom: 0;
  border-radius: 5px 5px 0 0;
  opacity: 0.75;
}

@media (hover: hover) and (pointer: fine) {
  #top-nav-menu .asset-action-item.gated:hover {
    color: var(--ink-2);
  }
}

/* --- The rail collapse control needs to be findable ---------------------- */
/* Measured: 22px, transparent background, transparent border, grey chevron,
   no label. Technically visible, practically invisible beside a search field.
   It becomes a real button with an edge, sized to the touch minimum, and the
   rail's tool row gives it its own slot. */
.watch-collapse {
  width: auto;
  min-width: 28px;
  height: 28px;
  min-height: 28px;
  padding-inline: var(--space-1);
  border-color: var(--border-control);
  border-radius: var(--radius-control);
  background: var(--surface-2);
  color: var(--ink-2);
}

@media (hover: hover) and (pointer: fine) {
  .watch-collapse:hover {
    border-color: var(--edge-hover);
    background: var(--wash-hover);
    color: var(--text-strong);
  }
}

/* Collapsed, it is the only thing in the gutter, so it fills it. */
.watchlist-collapsed .watch-collapse {
  width: 26px;
  min-width: 26px;
}

/* `.watch-tools` is a single-column grid, so a grid item stretches to the full
   column: the collapse button measured 218px of a 236px rail. Giving it its own
   row alongside a label keeps it compact and states what it does in words
   rather than relying on a chevron nobody finds. */
.watch-tools {
  grid-template-columns: 1fr auto;
}

.watch-tools .market-search,
.watch-tools .watch-tabs {
  grid-column: 1 / -1;
}

.watch-collapse {
  grid-column: 2;
  grid-row: 1;
  justify-self: end;
  width: auto;
  min-width: 28px;
  gap: var(--space-1);
}

/* The rail header gains a caption so the control has something to sit against
   and the region names itself. */
.watch-tools::before {
  content: "Pairs";
  grid-column: 1;
  grid-row: 1;
  align-self: center;
  color: var(--subtle);
  font: var(--weight-medium) 10px / 1 var(--font-sans);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.watchlist-collapsed .watch-tools::before {
  content: none;
}

/* Custody warning. This is the one place risk copy must be impossible to miss:
   a sandbox adapter synthesises addresses that are valid on no network, and a
   real ZEC deposit was nearly sent to one because the old note read as ordinary
   guidance. --danger is the correct functional colour - this is loss of funds,
   not a stylistic accent - and the border plus the ALERT role carry the meaning
   without relying on colour alone. */
.custody-warning {
  display: grid;
  gap: var(--space-2);
  border: var(--line) solid color-mix(in srgb, var(--danger) 55%, transparent);
  border-left-width: 3px;
  border-radius: var(--radius-control);
  background: color-mix(in srgb, var(--danger) 10%, transparent);
  padding: var(--space-3);
}

.custody-warning strong {
  color: var(--danger-strong, var(--danger));
  font: var(--weight-bold) var(--type-sm) / 1.3 var(--font-sans);
  letter-spacing: 0.01em;
}

.custody-warning span {
  color: var(--ink-2);
  font: 400 var(--type-xs) / 1.55 var(--font-sans);
}

/* An address that cannot receive funds must not look like one that can. */
.deposit-address-unusable {
  border-color: color-mix(in srgb, var(--danger) 40%, transparent);
  color: var(--muted);
  text-decoration: line-through;
  text-decoration-color: color-mix(in srgb, var(--danger) 70%, transparent);
  text-decoration-thickness: 1px;
}

/* =========================================================================
   R8 REAL DEPTH — fills, occlusion, and glass that actually transmits
   -------------------------------------------------------------------------
   Measured findings that drive this layer:

   1. A drop shadow on the #000000 canvas is optically NOTHING. Sampling the
      pixels directly below a `.panel` returned all zeros: black shadow on black
      canvas is a no-op, so three carefully layered shadows were doing no work
      at all. Depth on a black canvas has to come from FILL separation, a
      one-sided light inset along the top edge, and a dark occlusion RING that
      is darker than the surface it sits on rather than darker than black.

   2. The top of the surface ladder was squeezed below the just-noticeable
      difference: the nav menu rendered #242424 against a #212121 header band
      (delta 3), and float to modal was also delta 3. Coinbase's DARK theme
      steps its elevations by +10 and +11. Ours now do too.

   3. The veils were paint, not glass. The table-header veil measured min 26 and
      max 26 across twenty-one scan buckets - perfectly uniform, nothing
      ghosting through. The blur hardware does work: the same veil showed a
      delta of about 22 mid-scroll on a phone. Glass needs a SUBJECT behind it
      and enough alpha to let the subject through.

   This does not revert R5. Edges stay quiet: --border-control remains #2E2E2E
   and --border remains #2A2A2A. On the new float fill the #2A2A2A border now
   equals its own fill, so the drawn outline disappears entirely and lighting
   replaces it. R5 is completed here, not undone.
   ========================================================================= */

:root {
  /* Elevation by fill, stepped so each tier is actually felt. */
  --surface-float: #2A2A2A;
  --surface-modal: #303030;
  --surface-hover-high: #333333;

  /* Light from above, occlusion from a ring. The wide ambient layers stay for
     surfaces that sit over content rather than over the canvas. */
  --shadow-panel:
    inset 0 1px 0 rgba(255, 255, 255, 0.06),
    0 1px 0 rgba(0, 0, 0, 0.85);
  --shadow-float:
    inset 0 1px 0 rgba(255, 255, 255, 0.10),
    inset 0 -1px 0 rgba(0, 0, 0, 0.40),
    0 0 0 1px rgba(0, 0, 0, 0.9),
    0 2px 3px rgba(0, 0, 0, 0.55),
    0 16px 40px rgba(0, 0, 0, 0.55);
  --shadow-modal:
    inset 0 1px 0 rgba(255, 255, 255, 0.14),
    inset 0 -1px 0 rgba(0, 0, 0, 0.50),
    0 0 0 1px rgba(0, 0, 0, 0.9),
    0 10px 24px rgba(0, 0, 0, 0.55),
    0 32px 72px rgba(0, 0, 0, 0.65);

  /* Veils thin enough to transmit. Measured: the previous alphas passed nothing. */
  --chrome-veil: rgba(20, 20, 20, 0.55);
  --thead-veil: rgba(36, 36, 36, 0.62);
}

/* A well reads as cut IN when its lower lip catches light. */
.order-column input,
.order-column select,
.market-search,
.book-tick-select,
dialog input,
dialog select,
dialog textarea {
  box-shadow:
    inset 0 1px 2px rgba(0, 0, 0, 0.35),
    inset 0 -1px 0 rgba(255, 255, 255, 0.045);
}

/* Floating chrome is the one place glass earns its cost: it always has content
   behind it, which is exactly the subject the blur needs. */
#top-nav-menu,
.asset-action-popover {
  background-color: rgba(46, 46, 46, 0.72);
}

@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  #top-nav-menu,
  .asset-action-popover {
    -webkit-backdrop-filter: blur(24px) saturate(1.5);
    backdrop-filter: blur(24px) saturate(1.5);
  }
}

/* Without blur support, or when the reader has asked for less transparency,
   the surface becomes opaque rather than a washed-out sheet. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  #top-nav-menu,
  .asset-action-popover {
    background-color: var(--surface-float);
  }
}

@media (prefers-reduced-transparency: reduce) {
  #top-nav-menu,
  .asset-action-popover {
    background-color: var(--surface-float);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }

  .app-header {
    background-color: #141414;
  }
}

.app-header {
  -webkit-backdrop-filter: blur(20px) saturate(1.6);
  backdrop-filter: blur(20px) saturate(1.6);
}

.data-table th {
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}

/* =========================================================================
   R9 MEASURED POLISH — scoped press fills, one blur token, reduced-
   transparency coverage, a deeper field, and hover that is felt.
   -------------------------------------------------------------------------
   Every value below is measurement-driven (see /tmp/s0vshot/DEPTH-R9.md):

   1. --surface-hover-high was retuned for popover grounds in R8 (#333333)
      but leaked into eight consumers, five of which are panel-tier press
      and hover fills tuned against much darker rests. Those five return to
      the pre-R8 value via --press-fill; popover items keep the bump. The
      two :focus-visible consumers are intentionally untouched.

   2. .terminal-jump still consumed the stale --chrome-blur (14px/1.5)
      while the header moved to 20px/1.6 in R8. The token itself now
      carries the header value, so every consumer agrees and the token is
      again the single source of truth.

   3. prefers-reduced-transparency covered popovers and the header
      background, but left the header's backdrop-filter running against an
      opaque fill, and missed the phone terminal bar and the table-header
      veil entirely.

   4. --surface-1 #0E0E0E -> #0C0C0C. Measured: field->panel was the
      weakest plate step (delta 8, CR 1.067); this widens it to delta 10
      (CR 1.081) while canvas->field keeps a felt step (delta 12, CR
      1.074). The chart vendor ground already renders #0C0C0C, so the
      terminal's wells and the chart become one field tier. Wells deepen;
      figures on the field gain contrast (19.3:1 -> 19.6:1); no grey creep.

   5. --wash-hover 0.045 -> 0.055: rendered row hover moves from delta 11
      to delta 13-15 over the field (CR 1.113+) and stays below
      --wash-selected (0.06) and --wash-press (0.08) in the state order.

   6. The thead veil measured 27 at rest against the panel's 22 (delta 5,
      CR 1.051, the weakest adjacency on screen). A one-pixel top glint
      (~38 on the lit line) separates veil from plate without raising veil
      alpha, so scroll transmission is untouched. th had no prior
      box-shadow anywhere in this sheet; nothing is clobbered.

   The panel->band raise considered for this round is REJECTED by
   measurement: band top already renders 33 against the popover ground
   floor of 38 (delta 5); raising the band collapses that step entirely.
   The lower ladder is deepened instead (item 4), per the R8 A/B captures.

   No :focus rule appears in this block; focus belongs to a parallel fix.
   ========================================================================= */

@media (forced-colors: none) {
  :root {
    --surface-1: #0C0C0C;
    --press-fill: #2C2C2C;
    --wash-hover: rgb(255 255 255 / 0.055);
    --chrome-blur: blur(20px) saturate(1.6);
  }
}

/* (1) Press and hover fills return to panel-tier tuning; the popover keeps
   --surface-hover-high. Selectors are verbatim copies of their originals so
   each tie resolves here by source order. */
.chart-toolbar button:hover {
  background: var(--press-fill, #2C2C2C);
}

:is(button, select, [role="button"], [onclick]):not(:disabled):not([aria-disabled="true"]):active {
  background-color: var(--press-fill, #2C2C2C);
}

input[type="range"]:not(:disabled):active {
  background-color: var(--press-fill, #2C2C2C);
}

.market-link:active:not(:disabled) .coin-mark {
  background-color: var(--press-fill, #2C2C2C);
}

@media (hover: hover) and (pointer: fine) {
  .market-link:hover:not(:disabled) .coin-mark {
    background-color: var(--press-fill, #2C2C2C);
  }
}

/* (2) One blur token again: the header re-points to the token it used
   before R8 hardcoded the same value; the phone bar inherits it for free. */
.app-header {
  -webkit-backdrop-filter: var(--chrome-blur);
  backdrop-filter: var(--chrome-blur);
}

/* (6) The veil catches light on its top edge; its body still transmits. */
.data-table th {
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);
}

/* (3) Less transparency means opaque fills AND idle blur hardware.
   This block stays last in R9 so it wins the header rule above. */
@media (prefers-reduced-transparency: reduce) {
  .app-header {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }

  .terminal-jump {
    background: #141414;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }

  .data-table th {
    background: var(--surface-3);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}

/* ====================== end R9 MEASURED POLISH ====================== */

/* R9 (cont.) — the well follows the field. Ticket/search wells ride their
   own --well token (R7), which stayed at #0E0E0E when --surface-1 deepened;
   measured: order-ticket inputs rendered 14 while every ledger/field surface
   rendered 12. One token aligns all wells with the deepened field: well
   sits delta 10 below its panel (CR 1.081), and the field tier is uniform
   at 12 across ledger, book, search, chart and ticket. --well-modal is
   deliberately untouched (dialog wells: 26 under modal 48). This block is
   contiguous with R9 above; the R9 region ends at the footer below. */
@media (forced-colors: none) {
  :root {
    --well: #0C0C0C;
  }
}

/* ================== end R9 MEASURED POLISH (incl. cont.) ================== */


/* ===== WAVE-1 FOCUS RESTORATION (Main) =====
   Fixes the R8 regression: input:focus-visible (0,1,1) set outline:none and drew
   its ring via box-shadow, which the later wells block replaced at equal
   specificity on source order. WCAG 2.4.11 failed on 2px thickness. Drawn with
   outline instead, which the wells block never touches, so no tie exists.
   ===== */
/* S0VRAN Wave 1 — append-only keyboard-focus restoration.
 * [R] This compound selector deliberately outranks the observed (0,1,1)
 * input reset without !important; appending it therefore wins the cascade.
 * [R] A solid outline preserves the existing inset well shadows because
 * outline and box-shadow are independent properties, and it cannot shift layout.
 * [R] :focus-visible preserves keyboard modality, so pointer-only button clicks
 * do not acquire a persistent focus ring.
 */
:is(a[href], button, input, select, textarea, [contenteditable="true"], [tabindex]):not([disabled]):not([aria-disabled="true"]):not([tabindex="-1"]):focus-visible {
  outline: 2px solid var(--focus, #ffffff);
  outline-offset: 2px;
}

/* [R] Users requesting more contrast receive a stronger, still layout-neutral ring. */
@media (prefers-contrast: more) {
  :is(a[href], button, input, select, textarea, [contenteditable="true"], [tabindex]):not([disabled]):not([aria-disabled="true"]):not([tabindex="-1"]):focus-visible {
    outline-width: 3px;
    outline-offset: 3px;
  }
}

/* ===== W2-COPYPOLISH: copy & disclosure (CopyPolish, Wave 2) =====
   Generated-content disclosures on existing DOM hooks only. No layout, no
   focus rules, no selectors owned by other lanes. Evidence, copy sources,
   and the removal/condition contract: /tmp/s0vshot/COPY-SHIPPED.md.

   RULE 1 — deposit-open / withdrawals-closed disclosure (UX-DEPTH #1).
   Shows at the top of any deposit panel that renders a usable (non-sandbox)
   address. Today that states the venue-wide truth: every live asset has
   withdrawals disabled (/api/public/status, 2026-08-04). Forward contract:
   when the client stamps data-withdrawals="on" on .panel-body (spec in
   COPY-SHIPPED.md §1b), this rule auto-disarms for that panel; the second
   selector keeps the disclosure for panels stamped "off". */
.panel-body:has(> .deposit-address):not(:has(> .custody-warning)):not([data-withdrawals="on"])::before,
.panel-body[data-withdrawals="off"]:has(> .deposit-address)::before {
  content: "Deposits are open. Withdrawals are not.\A Every live asset on this venue currently has withdrawals switched off while custody hardening completes. Coins sent to this address will be credited — and will stay here until withdrawals reopen. No reopening date is promised. Deposit only what you can afford to leave parked.";
  white-space: pre-line;
  display: block;
  border: var(--line) solid color-mix(in srgb, var(--danger) 55%, transparent);
  border-left-width: 3px;
  border-radius: var(--radius-control);
  background: color-mix(in srgb, var(--danger) 10%, transparent);
  padding: var(--space-3);
  color: var(--ink-2);
  font: 400 var(--type-xs) / 1.55 var(--font-sans);
}

/* RULE 2 — development-mode chip (UX-DEPTH #4). Dormant until the
   #environment-label span lands in index.html (spec in COPY-SHIPPED.md §3);
   JS populates it from /api/public/config. :empty guard keeps an
   unpopulated span invisible, so this rule can never show a stale label. */
#environment-label {
  text-transform: uppercase;
  letter-spacing: 0.08em;
  border-color: color-mix(in srgb, var(--warning, #e8a13d) 55%, transparent);
  background: color-mix(in srgb, var(--warning, #e8a13d) 12%, transparent);
  color: var(--warning-strong, var(--warning, #e8a13d));
}
#environment-label:empty { display: none; }

/* RULE 3 — single-operator honesty at account creation (SCALE-INVARIANTS
   §5 discipline; permanent posture, true in every environment). Extends the
   existing #auth-guidance field-note in the sign-in dialog. */
#auth-guidance::after {
  content: " One person operates this venue. Withdrawals are reviewed by hand before broadcast; while the operator is unavailable, they wait.";
}
/* ===== end W2-COPYPOLISH ===== */

/* ===== W2-MOBILEDEPTH: measured small-viewport fixes (MobileDepth, Wave 2) =====
   Scope: every rule below sits inside @media (max-width: ...) or (pointer: coarse).
   Justification: /tmp/s0vshot/MOBILE-DEPTH.md - each value measured live at
   390x844 / 360x800 / 768x1024, dpr 2, touch emulation, Chrome 150. */

/* M1 - phone ledger cards rendered at the panel value (22) on panel-body (22):
   measured delta 0 where desktop R9 keeps field->panel at 12->22 (CR 1.081).
   Cards return to the ledger-well identity the rest of the phone UI keeps
   (search 12, marketbar 12, ticket wells 12, book 12). Row :active
   (surface-hover) now reads delta 18 over the row instead of 8; figures land
   255-on-12 = CR 19.6:1, the desktop value. */
@media (max-width: 599px) {
  .data-table.responsive-rows tbody tr,
  .data-table.compact-rows tbody tr {
    background: var(--surface-1);
  }
}

/* M2 - touch targets measured under the 44px platform floor (WCAG 2.5.8's
   24px hard minimum was already met by each of these; listed sizes are the
   measured BEFORE boxes). Floors, not redesigns. */

/* Favorite star: 32x32 at 390 and at 768 (both icon-only presentations).
   The labelled 64x28 desktop pill above 1023px is untouched. */
@media (pointer: coarse) and (max-width: 1023px) {
  .favorite-toggle,
  .data-table.compact-rows td[data-m="action"] .favorite-toggle {
    width: 44px;
    min-width: 44px;
    height: 44px;
    min-height: 44px;
  }
}

@media (pointer: coarse) {
  /* Asset action trigger: 32x32 phone, 44x32 tablet. It opens Deposit /
     Withdraw / Transfer - the highest-stakes small target measured. A 44px
     box seats inside the 64px card row with zero pitch growth (44 + 2x10
     padding = 64). */
  .asset-action-trigger,
  .data-table.compact-rows td[data-m="action"] .asset-action-trigger {
    width: 44px;
    min-width: 44px;
    height: 44px;
    min-height: 44px;
  }

  /* Chart interval buttons: 32.4w x 44h at 390, 32.4 x 32 at 768, inside a
     horizontally scrollable strip - widening costs scroll length only. */
  .chart-toolbar button {
    min-width: 44px;
    min-height: 44px;
  }

  /* Order-semantics selects measured under floor: TIF 110x41 at 390 and
     240x32 at 768 (the generic coarse select floor loses to a later height);
     book tick-size 124.5x32. The book band grows ~6px to seat 44. */
  .ticket-tif select,
  .book-tick-select {
    min-height: 44px;
  }

  /* Header Menu/account: 48h at 390 but 77x32 and 90x32 at 768 - the tablet
     media shrinks them below the floor the phone media grants. */
  #nav-dropdown-trigger,
  #account-button {
    min-height: 44px;
  }
}

/* M3 - the portfolio total's unit suffix rendered at 8.16px (0.34em of a
   24px figure; sibling instance 10.2px) at every width measured below
   desktop, while desktop renders ~11.6px (0.34em of 34px). An 11px floor
   restores the intended reading size; the figure stays ~3x larger and
   remains the brightest element on the view. */
@media (max-width: 1023px) {
  .portfolio-balance-total .figure-unit,
  .portfolio-balance-total strong .figure-unit {
    font-size: 11px;
  }
}

/* ===== end W2-MOBILEDEPTH ===== */

/* ===== W2-MOBILEDEPTH continuation (measured corrections, same wave) =====
   Two follow-ups the AFTER measurement demanded - the fence above remains
   one contiguous MobileDepth region ending at the footer below. */

/* C1 - the M2 header floor (min-height 44 at coarse) out-ordered the phone
   media's own min-height 48 and shrank Menu/account from 48h to 44h at 390.
   Measured: before 48, after M2 44. Restore the phone value; the 44 floor
   keeps doing its intended work in the 600-1023 tablet band where these
   buttons measured 77x32 and 90x32. */
@media (pointer: coarse) and (max-width: 599px) {
  #nav-dropdown-trigger,
  #account-button {
    min-height: 48px;
  }
}

/* C2 - the 8.16px unit suffixes that survived M3 live in ledger cells, not
   the portfolio total: span.figure-unit inside td.num figures (12px parent x
   0.68em = 8.16px), measured at 390 and 768. 10px keeps the suffix clearly
   subordinate to its 12px figure while clearing the legibility floor. */
@media (max-width: 1023px) {
  .data-table .figure-unit {
    font-size: 10px;
  }
}

/* ===== end W2-MOBILEDEPTH (incl. cont.) ===== */

/* ===== W5-SCROLLARCH =====
   Architecture A: the desktop terminal is one viewport-locked instrument.
   The page has no competing scroll range; only bounded data regions scroll. */
@media (min-width: 1024px) {
  /* Derive the terminal context from the dynamic viewport and remove every
     visible-overflow break in the workspace -> view -> shell chain. */
  body:has(.terminal-shell) {
    height: 100dvh;
    min-height: 0;
    overflow: hidden;
  }

  #workspace:has(.terminal-shell) {
    height: calc(100dvh - var(--terminal-top));
    min-height: 0;
    padding: var(--space-2) 0 0;
    overflow: hidden;
  }

  #workspace:has(.terminal-shell) > #app,
  #workspace:has(.terminal-shell) .view-frame {
    height: 100%;
    min-height: 0;
    overflow: hidden;
  }

  /* Flex all remaining height into the grid. Removing the shell's negative
     workspace margins lets the clipped ancestor boxes share exact bounds. */
  .terminal-shell {
    display: flex;
    flex-direction: column;
    width: 100%;
    height: 100%;
    min-height: 0;
    margin: 0;
    overflow: hidden;
  }

  .terminal-marketbar {
    flex: 0 0 var(--marketbar-height);
    min-height: 0;
  }

  .terminal-grid {
    flex: 1 1 0;
    min-height: 0;
    overflow: hidden;
  }

  .terminal-grid > *,
  .terminal-grid > .panel,
  .terminal-grid > .panel > .panel-body {
    min-height: 0;
  }

  /* The ticket owns the full grid height and never scrolls; chart pixels
     shrink with their track. Book, trades, orders and watch rows retain the
     existing auto + contain policy because the document no longer scrolls. */
  .terminal-grid > .trade-ticket {
    align-self: stretch;
  }

  .terminal-grid > .trade-ticket > .panel-body {
    overflow: clip;
  }

  .chart-panel > .panel-body {
    overflow: hidden;
  }

  .chart-panel .chart-surface {
    flex: 1 1 0;
    min-height: 0;
  }

  /* The row grip follows the actual first track (including its safety floor)
     and is bounded to the chart stack instead of crossing ticket controls. */
  .terminal-grid > .resize-handle.resize-row {
    grid-column: 2 / 3;
    grid-row: 1 / 2;
    top: 100% !important;
  }

  /* Remove only phantom vertical scrolling; genuine narrow-width horizontal
     tab scrolling remains available. */
  .terminal-shell .segmented,
  .terminal-shell .chart-attribution,
  .terminal-shell .terminal-marketbar {
    overflow-y: clip;
  }
}

/* At mid widths the ticket spans all four data tracks. The persisted chart
   row remains effective between a 180px control-safe floor and a 40% cap. */
@media (min-width: 1024px) and (max-width: 1439px) {
  .terminal-grid {
    grid-template-areas:
      "watch chart ticket"
      "watch book ticket"
      "watch trades ticket"
      "watch orders ticket";
    grid-template-rows:
      minmax(180px, min(var(--terminal-chart-row, 340px), 40%))
      minmax(0, 1.15fr)
      minmax(0, 0.85fr)
      minmax(0, 0.75fr);
  }
}

/* Broad terminals keep watch, ticket and book as full-height rails while the
   central chart/trades/orders stack consumes the remaining tracks. */
@media (min-width: 1440px) {
  .terminal-grid {
    grid-template-areas:
      "watch chart ticket book"
      "watch trades ticket book"
      "watch orders ticket book";
    grid-template-rows:
      minmax(180px, min(var(--terminal-chart-row, 380px), 55%))
      minmax(0, 0.9fr)
      minmax(0, 0.7fr);
  }
}

/* At 700px the ticket needs 42px less chrome, not smaller controls. Compact
   padding and place TIF/maker semantics side by side; inputs and submit retain
   their measured 44-48px heights. */
@media (min-width: 1024px) and (max-height: 760px) {
  .trade-ticket > .panel-body {
    padding: var(--space-2);
  }

  .trade-ticket .order-columns {
    padding: var(--space-2);
  }

  .trade-ticket .ticket-options {
    display: grid;
    grid-template-columns: minmax(140px, 0.85fr) minmax(0, 1.15fr);
    align-items: center;
    gap: var(--space-2);
    margin-top: var(--space-2);
    padding-top: var(--space-2);
  }

  .trade-ticket .ticket-tif,
  .trade-ticket .ticket-tif select {
    width: 100%;
    min-width: 0;
  }

  .trade-ticket .ticket-options > .hide-zero {
    min-width: 0;
    line-height: 1.25;
  }
}
/* ===== end W5-SCROLLARCH ===== */

/* ===== W6-CHARTFIT =====
   Corrects a regression introduced by W5-SCROLLARCH. Viewport-locking the grid
   gave the chart row its 180px floor, but the chart panel's own chrome measures
   154px of that (panel-header 85px, wrapping to two rows, plus chart-topline
   69px), leaving a 24px chart surface. Measured at 1600x800 [O].

   Two corrections: raise the floor so a usable surface survives the chrome, and
   compact the chrome itself at short viewport heights.

   The lightweight-charts attribution is NOT hidden — that notice is a licence
   obligation. It is moved onto the legend's row instead, which reclaims its
   height while keeping it visible. */

@media (min-width: 1024px) {
  /* A usable chart needs roughly 200px of surface. With compacted chrome at
     ~100px that puts the floor near 300px; the fr-based rows below still let
     the chart grow on tall screens. */
  .terminal-grid {
    --terminal-chart-floor: 300px;
  }
}

@media (min-width: 1024px) and (max-width: 1439px) {
  .terminal-grid {
    grid-template-rows:
      minmax(var(--terminal-chart-floor), min(var(--terminal-chart-row, 340px), 45%))
      minmax(0, 1.15fr)
      minmax(0, 0.85fr)
      minmax(0, 0.75fr);
  }
}

@media (min-width: 1440px) {
  .terminal-grid {
    grid-template-rows:
      minmax(var(--terminal-chart-floor), min(var(--terminal-chart-row, 380px), 55%))
      minmax(0, 0.9fr)
      minmax(0, 0.7fr);
  }
}

/* Short viewports: reclaim chart chrome without shrinking any control below its
   touch target, and without removing the attribution. */
@media (min-width: 1024px) and (max-height: 900px) {
  /* The interval row and the panel tabs were wrapping onto two lines. Keep them
     on one line and let the interval strip scroll horizontally if it must. */
  .chart-panel > .panel-header {
    flex-wrap: nowrap;
    align-items: center;
    gap: var(--space-2);
    padding-block: var(--space-1);
  }

  .chart-panel > .panel-header .chart-toolbar {
    flex: 1 1 auto;
    min-width: 0;
    overflow-x: auto;
    overflow-y: clip;
    scrollbar-width: none;
  }

  .chart-panel > .panel-header .chart-toolbar::-webkit-scrollbar { display: none; }

  /* Legend and attribution share one row rather than stacking. The notice stays
     visible; only its layout changes. */
  .chart-topline {
    display: flex;
    flex-wrap: nowrap;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-2);
    padding-block: 0;
    min-height: 0;
  }

  .chart-legend {
    flex: 1 1 auto;
    min-width: 0;
    white-space: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
  }

  .chart-legend::-webkit-scrollbar { display: none; }

  .chart-attribution {
    flex: 0 0 auto;
    margin: 0;
    min-height: 0;
    font-size: var(--text-2xs, 10px);
    opacity: .72;
  }
}
/* ===== end W6-CHARTFIT ===== */

/* ===== W7-CHARTROW =====
   Corrects two faults in the W5/W6 row sizing, both measured at 1600px wide [O].

   1. A persisted drag was acting as a hard CAP, not a preference. The rule was
      minmax(floor, min(var(--terminal-chart-row), 55%)). With a stored
      chartRow of 120px — a real value found in localStorage — min() resolved to
      120px, minmax clamped up to the floor, and the chart could then NEVER grow
      beyond the floor no matter how tall the screen. clamp() expresses the
      intended semantic: honour the user's drag, but only inside safe bounds.

   2. The floor did not account for the chart panel's own chrome. At full chrome
      the header and topline measure 154px, so a 300px row left 144px of surface
      — less than the 188px the SHORTER viewports were getting after W6's
      compaction. The floor is now set per chrome state. */

@media (min-width: 1024px) {
  /* Full chrome (154px measured): 340 - 154 = ~186px of usable surface. */
  .terminal-grid { --terminal-chart-floor: 340px; }
}

@media (min-width: 1024px) and (max-height: 900px) {
  /* W6 compacts chrome to ~110px here, so a lower floor still yields ~170px. */
  .terminal-grid { --terminal-chart-floor: 280px; }
}

@media (min-width: 1024px) and (max-width: 1439px) {
  .terminal-grid {
    grid-template-rows:
      clamp(var(--terminal-chart-floor), var(--terminal-chart-row, 340px), 45%)
      minmax(0, 1.15fr)
      minmax(0, 0.85fr)
      minmax(0, 0.75fr);
  }
}

@media (min-width: 1440px) {
  .terminal-grid {
    grid-template-rows:
      clamp(var(--terminal-chart-floor), var(--terminal-chart-row, 380px), 55%)
      minmax(0, 0.9fr)
      minmax(0, 0.7fr);
  }
}
/* ===== end W7-CHARTROW ===== */

/* ===== W8-TVNOTICE =====
   The TradingView panel is a cross-origin iframe, so order price lines and fill
   dots cannot be drawn on it. This strip states that plainly, repeats the order
   prices as text so the information survives, and offers one click to the chart
   that does draw them. It sits above the frame and must not steal chart height. */
.tv-notice {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  flex: 0 0 auto;
  padding: var(--space-1) var(--space-2);
  border-bottom: var(--line) solid var(--border-control);
  background: var(--surface-2);
  font-size: var(--text-xs, 11px);
  line-height: 1.3;
}

.tv-notice-text { color: var(--text-secondary, #A0A0A0); }

/* The prices are the reason to read this line, so they carry the data font and
   full contrast — consistent with prices being the highest-contrast elements. */
.tv-notice-orders {
  font-family: var(--font-data);
  color: var(--text-primary, #F2F2F2);
  white-space: nowrap;
  overflow-x: auto;
  min-width: 0;
  scrollbar-width: none;
}

.tv-notice-orders::-webkit-scrollbar { display: none; }

.tv-notice .button { margin-inline-start: auto; flex: 0 0 auto; }

/* The frame takes the remaining height rather than a fixed size, so adding the
   notice does not push the iframe out of the panel. */
.chart-panel .tv-frame { flex: 1 1 0; min-height: 0; width: 100%; border: 0; }
/* ===== end W8-TVNOTICE ===== */

/* ===== W9-SLIMCHROME =====
   Measured at 1600x900 [O]: the marketbar was 80px tall with .market-identity
   alone 545px wide (34% of the screen for the pair name and feed status), and the
   chart tab strip was 42px. That is ~122px of chrome above a chart that needs
   every pixel. All three reductions below are height and width only — no control
   drops below its touch target, and nothing is hidden.

   W8-TVNOTICE is superseded: its strip cost 63px of chart height, so the
   TradingView limitation now lives in that tab's tooltip instead. Its .tv-frame
   flex rule is retained below because the frame still needs to fill the panel. */

@media (min-width: 1024px) {
  /* 80 -> 52px. The stats are single-line values; they never needed 80px. */
  :root { --marketbar-height: 52px; }

  .terminal-marketbar {
    align-items: center;
    padding-block: 0;
    gap: var(--space-3);
  }

  /* The identity block was sized by its longest possible content. Cap it and let
     the stats reclaim the width. */
  .terminal-marketbar .market-identity {
    flex: 0 1 auto;
    max-width: 260px;
    min-width: 0;
  }

  .terminal-marketbar .market-identity > * {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  /* Stats stop being fixed-width columns and share the reclaimed space. */
  .terminal-marketbar .market-stat {
    flex: 0 1 auto;
    min-width: 0;
  }

  /* The tab strip: 42 -> 30px. Buttons keep a 26px hit box, which is still above
     the 24px WCAG 2.5.8 minimum for pointer targets. */
  .chart-panel > .panel-header {
    min-height: 30px;
    padding-block: 0;
    align-items: center;
  }

  .chart-panel > .panel-header .heading-actions {
    align-items: center;
    gap: var(--space-2);
  }

  .chart-panel .chart-toolbar,
  .chart-panel > .panel-header .segmented {
    min-height: 26px;
  }

  .chart-panel .chart-toolbar button,
  .chart-panel > .panel-header .segmented button {
    min-height: 26px;
    padding-block: 0;
    line-height: 26px;
  }
}

/* Retained from W8: the frame fills the panel rather than taking a fixed size. */
.chart-panel .tv-frame { flex: 1 1 0; min-height: 0; width: 100%; border: 0; }
/* ===== end W9-SLIMCHROME ===== */

/* ===== W10-TOOLBAR-NOWRAP =====
   W9 slimmed the tab strip to 30px, but only while the chart column was wide.
   With the watchlist visible the column narrows and .chart-toolbar — which
   carries its own flex-wrap: wrap — pushed "1W" onto a second row, taking the
   strip back to 61px measured [O].

   The intervals now stay on one line and scroll horizontally if they must. That
   keeps the strip at one row at every column width. Scroll affordance is kept via
   the existing scrollbar-width: none plus overflow-x: auto from W6, so the row
   never shows a bar but can still be dragged or wheeled sideways. */
@media (min-width: 1024px) {
  .chart-panel .chart-toolbar {
    flex-wrap: nowrap;
    overflow-x: auto;
    overflow-y: clip;
    scrollbar-width: none;
    min-width: 0;
  }

  .chart-panel .chart-toolbar::-webkit-scrollbar { display: none; }

  .chart-panel .chart-toolbar button { flex: 0 0 auto; }

  /* The header itself must not wrap either, or the segmented tabs drop below the
     interval row and re-create the same two-row strip. */
  .chart-panel > .panel-header,
  .chart-panel > .panel-header .heading-actions {
    flex-wrap: nowrap;
    min-width: 0;
  }

  .chart-panel > .panel-header .segmented { flex: 0 0 auto; }
}
/* ===== end W10-TOOLBAR-NOWRAP ===== */
