/* ---------- self-hosted faces ----------
   These used to come from fonts.googleapis.com behind a render-blocking
   stylesheet, which cost a DNS lookup, a TLS handshake and a round trip to a
   third party before a single glyph could paint — and told Google who was
   reading the page. Same files, same origin, one year immutable.
   Archivo is the VARIABLE cut, so one file covers 500-800 rather than four.
   unicode-range keeps latin-ext off the wire for anyone who never needs it. */
@font-face {
  font-family: "Anton";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/assets/fonts/anton-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Anton";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/assets/fonts/anton-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Archivo";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/assets/fonts/archivo-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Archivo";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/assets/fonts/archivo-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ============================================================
   AWAKE — RECURSIVE TRADING PLATFORM (paper stage)
   izzy's terminal: carbon-copy cockpit, dense scan grid, muted
   chrome, monochrome candles like a photocopied broker sheet.
   Mint is the ONLY accent and it means live/risk state — never
   decoration. The book strip under the masthead is his real
   on-chain GMX book, read-only.
   ============================================================ */

:root {
  --paper: #ece7db;
  --paper-deep: #e0dac9;
  --ink: #141312;
  --mint: #d9e8cf;
  --tape: rgba(196, 186, 158, 0.55);
  /* was #6b675f — 4.03:1 on --paper-deep, under AA, and this token carries the
     9.5px labels and 8px fine print. #57534b reads 6.20 on paper / 5.48 on
     paper-deep and stays far quieter than --ink (15.3:1), so the loudness
     ladder is unchanged — only the floor moved up. */
  --muted: #57534b;
  --line: 1px solid var(--ink);
  --pad: clamp(12px, 2vw, 24px);

  /* ---------- the loudness ladder ----------
     Measured before this existed: 91% of every text element on screen sat
     between 8px and 12px at weight 700 — five sizes nobody can tell apart,
     all shouting. Meanwhile the logo was the largest thing on the page and
     equity, the number a trader is actually here for, was 15px.
     Rule: SIZE and WEIGHT are earned by numbers that CHANGE and cost money.
     Furniture (labels, tags, fine print) is small, light and muted, and is
     never bold. Steps are far enough apart to read as different at a glance. */
  --t-hero: 30px;   /* the live price — the loudest thing in the room */
  --t-big: 21px;    /* your equity */
  --t-lead: 15px;   /* P/L, the numbers you stare at */
  --t-data: 12px;   /* table + readout data */
  --t-label: 9.5px; /* labels and furniture — muted, never bold */
  --t-fine: 8px;    /* disclosures and fine print */
  --font: "Archivo", "Helvetica Neue", Arial, sans-serif;
  --display: "Anton", "Archivo", sans-serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --rail-w: 236px;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

/* The terminal shows and hides almost everything through the [hidden]
   attribute, but the browser's `[hidden] { display: none }` is a USER-AGENT
   rule that any author `display` beats — the failure mode is a panel that
   ignores `.hidden = true` and just stays on screen. Six one-off patches
   below this line were written after that bit; this closes the class. */
[hidden] { display: none !important; }

html, body { height: 100%; }

/* iOS: stop text auto-inflating in landscape; kill the default gray tap
   flash so presses read through the brand's own micro-press feedback
   instead (see ":active" rules near the bottom of this file). */
html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  -webkit-tap-highlight-color: transparent;
}

body {
  font-family: var(--font);
  background: var(--paper);
  color: var(--ink);
  font-weight: 500;
  line-height: 1.3;
  -webkit-font-smoothing: antialiased;
  display: flex;
  flex-direction: column;
  min-height: 100dvh;
  overflow-x: hidden;
}

::selection { background: var(--mint); color: var(--ink); }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: none; cursor: pointer; }
input { font: inherit; color: inherit; }

/* print grain over everything — same sheet as the main site */
.grain {
  position: fixed;
  inset: 0;
  z-index: 100;
  pointer-events: none;
  opacity: 0.5;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.10 0'/%3E%3C/filter%3E%3Crect width='240' height='240' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ink, not mint: mint on paper is 1.04:1 — a focus ring nobody can see, and
   it spent the risk accent on chrome. Ink is 15:1 and clears WCAG 1.4.11. */
:focus-visible { outline: 3px solid var(--ink); outline-offset: 2px; }

/* ============ masthead ============ */

.mast {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px var(--pad);
  border-bottom: 2px solid var(--ink);
  flex-wrap: wrap;
  position: relative;
  z-index: 60;
  background: var(--paper);
}

/* mast-row: structural wrapper only (see index.html comment). Desktop/
   tablet unwrap it with display:contents so #mast's own flex-wrap keeps
   laying out the eight children directly, in the sequence pinned by the
   "order" values below — visually identical to the old flat markup. */
.mast-row { display: contents; }

.mast-brand {
  order: 1;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 9px;
  border: var(--line);
  background: var(--paper);
  white-space: nowrap;
}
.mast-brand:hover { box-shadow: 3px 3px 0 rgba(20, 19, 18, 0.9); transform: translateY(-1px); }
.mast-brand-arrow { font-size: 12px; }

.mast-id { order: 2; display: flex; flex-direction: column; align-items: flex-start; gap: 2px; }

.mast-title {
  font-family: var(--display);
  /* a wordmark, not an instrument — it should be legible, not competitive */
  font-size: 16px;
  line-height: 1;
  letter-spacing: 0.02em;
  background: var(--ink);
  color: var(--paper);
  padding: 4px 12px 6px;
  transform: rotate(-0.6deg);
}

.mast-tag {
  font-family: var(--mono);
  font-size: 8px;
  font-weight: 700;
  letter-spacing: 0.22em;
  color: var(--muted);
  padding-left: 2px;
  white-space: nowrap;
}

/* ============ the book strip — izzy's real on-chain positions ============ */

.book-strip {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 6px var(--pad);
  border-bottom: 2px solid var(--ink);
  background: var(--paper-deep);
  font-family: var(--mono);
  overflow: hidden;
  white-space: nowrap;
  transition: box-shadow 0.15s ease;
}
.book-strip[hidden] { display: none; }
.book-strip:hover { box-shadow: inset 0 -4px 0 var(--ink); }
.book-strip:focus-visible { outline: 3px solid var(--ink); outline-offset: -3px; }

.book-label {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.1em;
  padding-right: 13px;
  border-right: 2px solid var(--ink);
}
.book-dot {
  width: 9px;
  height: 9px;
  background: var(--mint);
  outline: 1px solid var(--ink);
  animation: connPulse 2s ease-in-out infinite;
}

.book-rows {
  flex: 0 1 auto;
  min-width: 0;
  display: inline-flex;
  gap: 18px;
  overflow-x: auto;
  scrollbar-width: none;
  overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch;
}
.book-rows::-webkit-scrollbar { display: none; }

.book-row { display: inline-flex; align-items: baseline; gap: 7px; font-size: 11px; font-weight: 700; }
.book-row-sym { font-weight: 800; }
.book-row-side { font-size: 9px; letter-spacing: 0.08em; padding: 1px 4px; border: 1px solid var(--ink); }
.book-row-side--short { background: var(--ink); color: var(--paper); }
.book-row-meta { font-size: 9px; color: var(--muted); font-weight: 600; }
.book-row-pnl { font-variant-numeric: tabular-nums; }
.book-row-pnl--up { background: var(--mint); outline: 1px solid var(--ink); padding: 0 4px; }
.book-row-pnl--down { background: var(--ink); color: var(--paper); padding: 0 4px; }
.book-flat { font-size: 10px; font-weight: 700; letter-spacing: 0.1em; color: var(--muted); }

.book-note {
  flex: 1 1 auto;
  min-width: 0;
  text-align: right;
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
}

.chip {
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  padding: 4px 8px;
  border: var(--line);
  background: var(--paper);
  white-space: nowrap;
}
/* unmissable in CONTRAST, no longer competing in SIZE — it is a fact you
   read once, not a number you watch. It had the largest area on screen. */
.chip-sim { order: 3; background: var(--ink); color: var(--paper); transform: rotate(0.8deg); font-size: var(--t-fine); padding: 3px 6px; }
.chip-btn:hover { box-shadow: 3px 3px 0 rgba(20, 19, 18, 0.9); transform: translateY(-1px); }

/* ============ replay transport — practicing on past bars ============
   sibling of .book-strip. the mint dot follows the app's existing
   "something is currently active" language (conn-dot, book-dot); the
   hatch on .chip-sim / .book-strip is the separate "not live" tell so
   the two states can never be confused for each other. */

.replay-bar {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 6px var(--pad);
  border-bottom: 2px solid var(--ink);
  background:
    repeating-linear-gradient(-45deg, rgba(20, 19, 18, 0.07) 0 8px, transparent 8px 16px),
    var(--paper-deep);
  font-family: var(--mono);
  overflow-x: auto;
  white-space: nowrap;
  scrollbar-width: none;
  overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch;
}
.replay-bar[hidden] { display: none; }
.replay-bar::-webkit-scrollbar { display: none; }

.replay-label {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.1em;
  padding-right: 13px;
  border-right: 2px solid var(--ink);
}
.replay-dot {
  width: 9px;
  height: 9px;
  background: var(--mint);
  outline: 1px solid var(--ink);
  animation: connPulse 2s ease-in-out infinite;
  flex: none;
}

.replay-btn, .replay-exit { flex: none; }
.replay-exit { margin-left: auto; background: var(--ink); color: var(--paper); }
.replay-exit:hover { background: var(--paper); color: var(--ink); box-shadow: 3px 3px 0 rgba(20, 19, 18, 0.9); }

.replay-speed-field {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.1em;
  color: var(--muted);
}
.replay-speed-field select {
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.06em;
  padding: 4px 6px;
  border: var(--line);
  background: var(--paper);
  color: var(--ink);
  -webkit-appearance: none;
  appearance: none;
  cursor: pointer;
}
.replay-speed-field select:hover { background: var(--paper-deep); }

.replay-clock {
  flex: none;
  font-size: 11px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}
.replay-progress {
  flex: none;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.04em;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
}

/* the unmistakable "not live" tell — set on <body> by the JS while
   replay is armed. touches only decorative chrome, never a number. */
body.is-replay .chip-sim {
  background-image: repeating-linear-gradient(-45deg, transparent 0 6px, rgba(217, 232, 207, 0.3) 6px 12px);
}
body.is-replay .book-strip {
  background-image: repeating-linear-gradient(-45deg, rgba(20, 19, 18, 0.08) 0 9px, transparent 9px 18px);
  opacity: 0.55;
}
body.is-replay .book-strip:hover { opacity: 0.85; }

/* pair tabs */
.mast-pairs { order: 5; display: flex; gap: 0; margin-left: 6px; flex-wrap: wrap; }
#whatIs { order: 4; }
#moreMarkets { order: 6; }
.pair-tab {
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.06em;
  padding: 6px 11px;
  border: var(--line);
  margin-left: -1px;
  background: var(--paper);
  position: relative;
}
.pair-tab:first-child { margin-left: 0; }
.pair-tab:hover { background: var(--paper-deep); }
.pair-tab.is-on { background: var(--ink); color: var(--paper); }
.pair-tab .pair-mid {
  display: block;
  font-size: 9px;
  font-weight: 500;
  letter-spacing: 0.03em;
  opacity: 0.75;
}

/* live block */
/* the two instrument clusters — what the market is doing, what your money is
   doing — get walls so the eye lands on a ZONE instead of hunting through a
   row of identically-sized chips */
.mast-live { order: 7; display: flex; align-items: baseline; gap: 12px; margin-left: auto; padding: 2px 12px; border-left: 1px dashed var(--muted); }

.conn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
}
.conn-dot { width: 9px; height: 9px; background: var(--ink); }
.conn[data-state="live"] .conn-dot { background: var(--mint); outline: 1px solid var(--ink); animation: connPulse 2s ease-in-out infinite; }
.conn[data-state="connecting"] .conn-dot,
.conn[data-state="stale"] .conn-dot { animation: connBlink 0.9s steps(2, start) infinite; }
@keyframes connPulse { 50% { opacity: 0.55; } }
@keyframes connBlink { 50% { opacity: 0.15; } }

.mast-mark {
  font-family: var(--mono);
  font-size: var(--t-hero);
  font-weight: 700;
  letter-spacing: 0.01em;
  font-variant-numeric: tabular-nums;
}
.mast-stat {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.05em;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.mast-stat.is-neg { background: var(--ink); color: var(--paper); padding: 2px 5px; }

/* account block */
.mast-acct { order: 8; display: flex; align-items: center; gap: 10px; }
.equity-spark { border: var(--line); background: var(--paper); image-rendering: pixelated; }
.mast-acct-num { display: flex; flex-direction: column; align-items: flex-end; }
.mast-acct-label { font-family: var(--mono); font-size: 9px; font-weight: 700; letter-spacing: 0.12em; color: var(--muted); }
.mast-acct-val { font-family: var(--mono); font-size: var(--t-big); font-weight: 800; font-variant-numeric: tabular-nums; line-height: 1.05; }

/* ============ cockpit grid ============ */

.cockpit {
  flex: 1;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 300px var(--rail-w);
  grid-template-rows: minmax(320px, 1fr) minmax(180px, 260px);
  grid-template-areas:
    "chart ticket rail"
    "desk  desk   rail";
  gap: 0;
  min-height: 0;
}

.panel { border-right: 2px solid var(--ink); border-bottom: 2px solid var(--ink); min-width: 0; min-height: 0; display: flex; flex-direction: column; }
.panel-chart { grid-area: chart; }
.panel-ticket { grid-area: ticket; overflow-y: auto; }
.panel-desk { grid-area: desk; border-bottom: none; }
.rail { grid-area: rail; border-bottom: none; }

.panel-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 10px;
  border-bottom: 1px dashed var(--muted);
  flex: none;
  min-height: 38px;
}

.panel-tag {
  font-family: var(--display);
  font-size: 12px;
  letter-spacing: 0.05em;
  background: var(--ink);
  color: var(--paper);
  padding: 1px 8px 2px;
}

/* timeframe rail */
.tf-rail { display: flex; }
.tf-btn {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 700;
  padding: 4px 8px;
  border: var(--line);
  margin-left: -1px;
  background: var(--paper);
}
.tf-btn:first-child { margin-left: 0; }
.tf-btn:hover { background: var(--paper-deep); }
.tf-btn.is-on { background: var(--ink); color: var(--paper); }

.ohlc-read {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
  font-variant-numeric: tabular-nums;
}

.chip-follow { margin-left: auto; background: var(--mint); }

.chart-wrap { position: relative; flex: 1; min-height: 0; cursor: crosshair; }
#chart { position: absolute; inset: 0; width: 100%; height: 100%; display: block; touch-action: none; }

.chart-badge {
  position: absolute;
  top: 12px;
  left: 50%;
  transform: translateX(-50%) rotate(-1deg);
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.1em;
  padding: 6px 12px;
  background: var(--ink);
  color: var(--paper);
  animation: connBlink 1.2s steps(2, start) infinite;
}

/* ============ order ticket ============ */

.ticket-bal { margin-left: auto; font-family: var(--mono); font-size: 10px; font-weight: 700; color: var(--muted); font-variant-numeric: tabular-nums; }

.side-switch { display: flex; margin: 10px 10px 0; }
.side-btn {
  flex: 1;
  font-family: var(--display);
  font-size: 19px;
  letter-spacing: 0.06em;
  padding: 8px 0 9px;
  border: 2px solid var(--ink);
  background: var(--paper);
}
.side-short { margin-left: -2px; }
.side-btn.is-on { background: var(--ink); color: var(--paper); }
.side-btn:not(.is-on):hover { background: var(--paper-deep); }

.ticket-row { display: flex; gap: 8px; margin: 10px 10px 0; }
.ticket-type .type-btn {
  flex: 1;
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.1em;
  padding: 5px 0;
  border: 1px dashed var(--muted);
  background: var(--paper);
}
.ticket-type .type-btn.is-on { border: var(--line); background: var(--paper-deep); }

.ticket-field { display: flex; flex-direction: column; gap: 4px; margin: 10px 10px 0; }
/* pre-existing bug fix: any element with an author "display" rule silently
   ignores the [hidden] attribute (author styles beat the UA stylesheet at
   equal specificity) — .ticket-field never had the override that
   .book-strip/.replay-bar/.gate/.intro-banner already carry below, so
   #nameField, #limitField and #stopField rendered even while hidden=true.
   Same bug on .ticket-preview (it hid #ticketPreviewRr in name only). */
.ticket-field[hidden], .ticket-preview[hidden] { display: none; }
.ticket-row .ticket-field { margin: 0; flex: 1; min-width: 0; }
.ticket-triggers { margin: 10px 10px 0; }
.ticket-field > span {
  font-family: var(--mono);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.12em;
  color: var(--muted);
}
.ticket-field em { font-style: normal; opacity: 0.7; }
.ticket-field input {
  font-family: var(--mono);
  font-size: 15px;
  font-weight: 700;
  padding: 7px 9px;
  border: var(--line);
  background: var(--paper);
  width: 100%;
  font-variant-numeric: tabular-nums;
}
.ticket-field input:focus { outline: 3px solid var(--ink); outline-offset: 0; }

/* percent-of-balance sizing — the caption exists because "25%" alone never
   says a percent OF WHAT, and a title attribute is invisible on a phone */
.size-chips-head {
  margin: 8px 10px 3px;
  font-family: var(--mono);
  font-size: var(--t-label);
  font-weight: 600;
  letter-spacing: 0.1em;
  color: var(--muted);
}
.size-chips { display: flex; gap: 6px; margin: 0 10px; }
.size-chip {
  flex: 1;
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.06em;
  padding: 5px 0;
  border: 1px dashed var(--muted);
  background: var(--paper);
}
.size-chip:hover { border-style: solid; border-color: var(--ink); background: var(--paper-deep); }
.size-chip:active { transform: translateY(1px); }

.size-warn {
  margin: 6px 10px 0;
  font-family: var(--mono);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.05em;
  padding: 4px 7px;
  background: var(--ink);
  color: var(--paper);
}

.ticket-field em#sizeAsset { color: var(--ink); opacity: 1; }

.ticket-preview-rr { margin-top: 6px; }
.ticket-preview dd.rr-good { background: var(--mint); padding: 0 3px; display: inline-block; }

.lev-block { margin: 12px 10px 0; }
.lev-head {
  display: flex;
  justify-content: space-between;
  font-family: var(--mono);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.12em;
  color: var(--muted);
}
.lev-val { font-size: 13px; color: var(--ink); }
.lev-block input[type="range"] {
  width: 100%;
  margin: 8px 0 2px;
  -webkit-appearance: none;
  appearance: none;
  height: 2px;
  background: var(--ink);
}
.lev-block input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 16px;
  height: 16px;
  background: var(--paper);
  border: 2px solid var(--ink);
  /* --lev-shadow is set by ticketPreview() via the CSSOM, offset only —
     leverage climbing reads as heavier, not as a new alarm color */
  box-shadow: var(--lev-shadow, 2px) var(--lev-shadow, 2px) 0 rgba(20, 19, 18, 0.9);
  cursor: ew-resize;
}
.lev-block input[type="range"]::-moz-range-thumb {
  width: 12px;
  height: 12px;
  border-radius: 0;
  background: var(--paper);
  border: 2px solid var(--ink);
  box-shadow: var(--lev-shadow, 2px) var(--lev-shadow, 2px) 0 rgba(20, 19, 18, 0.9);
  cursor: ew-resize;
}
.lev-marks { display: flex; justify-content: space-between; font-family: var(--mono); font-size: 8px; color: var(--muted); }

.ticket-preview { display: flex; gap: 0; margin: 12px 10px 0; border: 1px dashed var(--muted); }
.ticket-preview > div { flex: 1; padding: 6px 8px; border-left: 1px dashed var(--muted); }
.ticket-preview > div:first-child { border-left: none; }
.ticket-preview dt { font-family: var(--mono); font-size: 8px; font-weight: 700; letter-spacing: 0.1em; color: var(--muted); }
.ticket-preview dd { font-family: var(--mono); font-size: 13px; font-weight: 800; font-variant-numeric: tabular-nums; }
.ticket-preview dd.is-risk { background: var(--mint); padding: 0 3px; display: inline-block; }

.place-btn {
  display: block;
  margin: 12px 10px;
  width: calc(100% - 20px);
  font-family: var(--display);
  font-size: 22px;
  letter-spacing: 0.06em;
  padding: 10px 0 12px;
  border: 2px solid var(--ink);
  background: var(--ink);
  color: var(--paper);
  transition: box-shadow 0.12s ease, transform 0.12s ease;
}
.place-btn:hover { box-shadow: 5px 5px 0 rgba(20, 19, 18, 0.45); transform: translate(-1px, -1px); }
.place-btn:active { transform: translate(1px, 1px); box-shadow: none; }
.place-btn[disabled] { opacity: 0.4; cursor: not-allowed; box-shadow: none; transform: none; }
/* Not-ready state. Deliberately NOT [disabled]: the button still takes a click
   so it can say what is missing. Hollow + dashed reads "not armed" at a glance
   without the dead-end feel of a greyed-out control. */
.place-btn[aria-disabled="true"] {
  background: var(--paper);
  color: var(--ink);
  border-style: dashed;
}
.place-btn[aria-disabled="true"]:hover { box-shadow: none; transform: none; }
.place-btn[aria-disabled="true"]:active { transform: translate(1px, 1px); }

.ticket-note {
  margin: 0 10px 12px;
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.04em;
  padding: 6px 8px;
  border: var(--line);
  background: var(--paper-deep);
}

/* ============ desk ============ */

.desk-tabs {
  display: flex;
  align-items: center;
  gap: 0;
  padding: 7px 10px 0;
  border-bottom: var(--line);
  flex: none;
}
.desk-tab {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  padding: 6px 10px 5px;
  border: var(--line);
  border-bottom: none;
  margin-left: -1px;
  background: var(--paper-deep);
  position: relative;
  top: 1px;
}
.desk-tab:first-child { margin-left: 0; }
.desk-tab.is-on { background: var(--paper); border-bottom: 2px solid var(--paper); }
.desk-count { opacity: 0.6; }

.desk-stats {
  margin-left: auto;
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.05em;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
  padding-bottom: 4px;
  font-variant-numeric: tabular-nums;
}

.desk-scroll { flex: 1; overflow: auto; min-height: 0; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }

.desk-table { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }
.desk-table th {
  font-family: var(--mono);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.1em;
  color: var(--muted);
  text-align: right;
  padding: 6px 10px 4px;
  border-bottom: 1px dashed var(--muted);
  position: sticky;
  top: 0;
  background: var(--paper);
  white-space: nowrap;
}
.desk-table th:first-child, .desk-table td:first-child { text-align: left; }
.desk-table td {
  font-family: var(--mono);
  font-size: var(--t-data);
  font-weight: 600;
  text-align: right;
  padding: 5px 10px;
  border-bottom: 1px solid rgba(107, 103, 95, 0.25);
  white-space: nowrap;
}
.desk-table tr:hover td { background: var(--paper-deep); }

/* P/L is the number a trader stares at — it outranks every label near it */
.pnl-chip { padding: 2px 6px; font-weight: 800; font-size: var(--t-lead); }
/* the eye should find P/L without reading a header */
#tblPositions td:nth-child(12), #tblPositions th:nth-child(12) { border-left: 1px dashed var(--muted); border-right: 1px dashed var(--muted); }
.pnl-pos { background: var(--mint); outline: 1px solid var(--ink); }
.pnl-neg { background: var(--ink); color: var(--paper); }

.side-cell-long::before { content: "▲ "; font-size: 9px; }
.side-cell-short::before { content: "▼ "; font-size: 9px; }

.row-btn {
  font-family: var(--mono);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.08em;
  padding: 3px 7px;
  border: var(--line);
  background: var(--paper);
}
.row-btn:hover { background: var(--ink); color: var(--paper); }

/* about-to-be-liquidated must NOT look like in-profit — both were mint, the
   best and worst states in the product wearing the same color. Danger reads
   as inverted ink (the same language a losing P/L already speaks) and keeps
   the blink; mint stays for live-and-positive only. */
.liq-near { background: var(--ink); color: var(--paper); animation: connBlink 0.8s steps(2, start) infinite; padding: 1px 5px; font-weight: 700; }

.desk-empty {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--muted);
  padding: 18px 12px;
}

/* ============ receipts rail ============ */

.rail {
  display: flex;
  flex-direction: column;
  min-height: 0;
  background:
    repeating-linear-gradient(0deg, transparent 0 26px, rgba(107, 103, 95, 0.08) 26px 27px),
    var(--paper-deep);
}

.rail-head {
  display: flex;
  align-items: center;
  gap: 0;
  padding: 7px 10px 0;
  border-bottom: 2px solid var(--ink);
  background: var(--paper);
  flex: none;
}

/* ---------- THE WIRE: headlines you can trade off ----------
   This column used to print receipts of trades already done. A record of the
   past is worth less than a reason to act, so the wire owns it now and the
   receipts keep a tab. */

.rail-tab {
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.09em;
  padding: 6px 10px 5px;
  border: var(--line);
  border-bottom: none;
  margin-right: -1px;
  background: var(--paper-deep);
  position: relative;
  top: 1px;
}
.rail-tab.is-on { background: var(--paper); border-bottom: 2px solid var(--paper); }
.rail-head .chip-btn { margin-left: auto; margin-bottom: 5px; }
/* unread count on RECEIPTS — a fill printed while the rail sat on MOVERS
   must say so; flat ink block, no radius, no blur, matches the sheet */
.tab-badge { margin-left: 5px; padding: 0 4px; background: var(--ink); color: var(--paper); font-size: 10px; font-weight: 800; }

.wire, .receipts-pane { display: flex; flex-direction: column; flex: 1; min-height: 0; }
.wire[hidden], .receipts-pane[hidden] { display: none; }

.wire-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  border-bottom: 1px dashed var(--muted);
  flex: none;
}
.wire-sub {
  font-family: var(--mono);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.1em;
  color: var(--muted);
}
#wireRefresh { margin-left: auto; font-size: 12px; line-height: 1; padding: 3px 7px; }

.wire-list { flex: 1; overflow-y: auto; min-height: 0; overscroll-behavior: contain; }

/* mode switch: UP / DOWN / BUSIEST */
.mv-modes { display: flex; gap: 0; }
.mv-mode {
  font-family: var(--mono);
  font-size: 8px;
  font-weight: 700;
  letter-spacing: 0.1em;
  padding: 4px 7px;
  border: 1px solid var(--muted);
  margin-left: -1px;
  background: var(--paper);
}
.mv-mode:first-child { margin-left: 0; }
.mv-mode.is-on { background: var(--ink); color: var(--paper); border-color: var(--ink); }

/* one row per market — rank, symbol, price, move. Tap loads the chart. */
.mv-row {
  display: flex;
  align-items: baseline;
  gap: 7px;
  width: 100%;
  padding: 7px 10px;
  border-bottom: 1px solid rgba(107, 103, 95, 0.22);
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  text-align: left;
}
.mv-row:hover { background: var(--paper-deep); }
.mv-row:focus-visible { outline: 3px solid var(--ink); outline-offset: -3px; }
.mv-row.is-current { background: var(--paper-deep); box-shadow: inset 3px 0 0 var(--ink); }

.mv-rank { font-size: 8px; color: var(--muted); font-weight: 700; min-width: 13px; }
.mv-sym { font-size: 13px; font-weight: 800; letter-spacing: 0.02em; }
.mv-px { font-size: 10px; color: var(--muted); font-weight: 600; margin-left: auto; }
.mv-chg { font-size: var(--t-data); font-weight: 800; padding: 1px 4px; min-width: 58px; text-align: right; }
/* mint stays the live/positive accent; a drop wears inverted ink */
.mv-up { background: var(--mint); outline: 1px solid var(--ink); }
.mv-down { background: var(--ink); color: var(--paper); }
.mv-vol { font-size: var(--t-data); font-weight: 800; min-width: 58px; text-align: right; }

.wire-empty, .wire-note {
  font-family: var(--mono);
  font-size: 8px;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--muted);
  padding: 9px 10px;
  line-height: 1.5;
}
.wire-note { border-top: 1px dashed var(--muted); flex: none; }
.wire-empty { font-size: 10px; }
.rail-sub { font-family: var(--mono); font-size: 9px; font-weight: 700; letter-spacing: 0.14em; color: var(--muted); }
.rail-head .chip-btn { margin-left: auto; }

/* the printer slot the receipts slide out of */
.rail-slot {
  flex: none;
  height: 10px;
  margin: 8px 12px 0;
  background: var(--ink);
  box-shadow: inset 0 3px 0 rgba(236, 231, 219, 0.25);
}

.rail-stack { flex: 1; overflow-y: auto; padding: 10px 12px 16px; min-height: 0; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }

.receipt {
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 600;
  background: #f4f0e6;
  border: 1px solid rgba(20, 19, 18, 0.75);
  padding: 8px 9px 10px;
  margin-bottom: 10px;
  box-shadow: 2px 3px 0 rgba(20, 19, 18, 0.28);
  position: relative;
  font-variant-numeric: tabular-nums;
}
.receipt:nth-child(odd) { transform: rotate(0.7deg); }
.receipt:nth-child(even) { transform: rotate(-0.8deg); }
.receipt.is-new { animation: printOut 0.45s cubic-bezier(0.2, 0.9, 0.3, 1); }
@keyframes printOut {
  from { transform: translateY(-26px) rotate(0deg); clip-path: inset(0 0 100% 0); }
  to { transform: translateY(0); clip-path: inset(0 0 0 0); }
}

/* tear-off perforation */
.receipt::before {
  content: "";
  position: absolute;
  top: -1px;
  left: 0;
  right: 0;
  height: 0;
  border-top: 1px dashed var(--paper);
}

.receipt-head {
  display: flex;
  justify-content: space-between;
  font-size: 8px;
  font-weight: 700;
  letter-spacing: 0.1em;
  border-bottom: 1px dashed rgba(20, 19, 18, 0.5);
  padding-bottom: 4px;
  margin-bottom: 5px;
}
/* the receipt's second header row — was an inline style attribute, which the
   page's style-src CSP refuses; it belongs in the stylesheet anyway */
.receipt-head--sub { border-bottom: none; margin-bottom: 2px; padding-bottom: 0; }

.receipt-body { display: grid; grid-template-columns: auto 1fr; gap: 1px 10px; }
.receipt-body dt { font-size: 8px; font-weight: 700; letter-spacing: 0.08em; color: var(--muted); align-self: baseline; }
.receipt-body dd { text-align: right; }
.receipt-stamp {
  margin-top: 6px;
  text-align: center;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.18em;
  padding: 2px 0;
}
.receipt-stamp.stamp-open { border: 1px solid var(--ink); }
.receipt-stamp.stamp-profit { background: var(--mint); outline: 1px solid var(--ink); }
.receipt-stamp.stamp-loss { background: var(--ink); color: var(--paper); }
.receipt-stamp.stamp-liq { background: var(--ink); color: var(--paper); letter-spacing: 0.3em; }
/* the 0.4s delay lands just after .receipt.is-new's printOut (0.45s) finishes
   — paper first, then the stamp comes down, instead of both arriving in the
   same motion. fill-mode both holds the pre-animation state through the
   delay so it doesn't flash full-size before dropping */
.receipt-stamp.stamp-in { animation: stampDown 0.24s cubic-bezier(0.34, 1.56, 0.64, 1) 0.4s both; }
@keyframes stampDown {
  from { transform: scale(1.7) rotate(-9deg); opacity: 0; }
  to { transform: scale(1) rotate(0deg); opacity: 1; }
}

/* barcode strip */
.receipt-code {
  margin-top: 6px;
  height: 14px;
  background: repeating-linear-gradient(90deg,
    var(--ink) 0 1px, transparent 1px 3px,
    var(--ink) 3px 5px, transparent 5px 6px,
    var(--ink) 6px 7px, transparent 7px 10px);
  opacity: 0.85;
}

.receipt-save {
  position: absolute;
  top: 22px;
  right: 6px;
  font-family: var(--mono);
  font-size: 8px;
  font-weight: 700;
  letter-spacing: 0.08em;
  /* was 8px type in 2px padding — a ~16px-tall target, well under the 24px
     floor and impossible to hit deliberately */
  display: inline-flex;
  align-items: center;
  min-height: 24px;
  padding: 2px 7px;
  border: 1px solid rgba(20, 19, 18, 0.4);
  background: transparent;
  opacity: 0;
  transition: opacity 0.15s ease;
}
.receipt:hover .receipt-save { opacity: 1; }
/* Keyboard reach: opacity forms a rendering group, so at opacity 0 the global
   focus ring is painted at zero alpha too — a Tab stop that is completely
   invisible, ring and all. Focus reveals the button the way hover does. */
.receipt:focus-within .receipt-save,
.receipt-save:focus-visible { opacity: 1; }
@media (pointer: coarse) { .receipt-save { opacity: 0.7; } }
.receipt-save:hover { background: var(--ink); color: var(--paper); }
/* same inverted-ink "confirmed" language .row-btn:hover already uses —
   a download is silent in the OS tray, this is the on-page acknowledgment */
.receipt-save.is-saved { opacity: 1; background: var(--ink); color: var(--paper); border-color: var(--ink); }

.rail-empty {
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.1em;
  color: var(--muted);
  padding: 14px;
}

/* ============ footer ============ */

.paper-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 18px;
  padding: 8px var(--pad) 10px;
  border-top: 2px solid var(--ink);
  font-family: var(--mono);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.07em;
  color: var(--muted);
}
.foot-group {
  background: var(--ink);
  color: var(--paper);
  padding: 1px 6px;
  letter-spacing: 0.14em;
}
.foot-kbd { margin-left: auto; }

/* ============ command palette ============ */

.palette-backdrop {
  position: fixed;
  inset: 0;
  z-index: 190;
  background: rgba(20, 19, 18, 0.35);
}
.palette {
  position: fixed;
  z-index: 200;
  top: 14vh;
  left: 50%;
  transform: translateX(-50%) rotate(-0.4deg);
  width: min(480px, calc(100vw - 32px));
  background: var(--paper);
  border: 2px solid var(--ink);
  box-shadow: 7px 7px 0 rgba(20, 19, 18, 0.85);
}
.palette input {
  width: 100%;
  font-family: var(--mono);
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.04em;
  padding: 11px 13px;
  border: none;
  border-bottom: 2px solid var(--ink);
  background: var(--paper);
}
.palette input:focus { outline: none; }
.palette-list { list-style: none; max-height: 46vh; overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }
.palette-item {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  padding: 8px 13px;
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  border-bottom: 1px solid rgba(107, 103, 95, 0.2);
}
.palette-item .cmd-hint { font-size: 9px; color: var(--muted); letter-spacing: 0.06em; }
.palette-item.is-active { background: var(--ink); color: var(--paper); }
.palette-item.is-active .cmd-hint { color: var(--paper); opacity: 0.7; }
.palette-empty { padding: 12px 13px; font-family: var(--mono); font-size: 11px; color: var(--muted); }

/* ---------- furniture stops shouting ----------
   Every label in the app was weight 700, the same as the live numbers, so
   weight carried no information at all. Labels are the frame, not the
   picture: lighter, muted, and quieter than anything that moves. Applied
   here in one place so it holds across every panel. */
.ticket-field > span,
.ticket-preview dt,
.mast-acct-label,
.mast-stat,
.mast-substat,
.desk-table th,
.report-grid dt,
.rail-sub,
.wire-sub,
.book-label,
.book-row-meta,
.lev-head,
.lev-marks,
.desk-stats,
.paper-foot,
.receipt-body dt {
  font-weight: 600;
  color: var(--muted);
}
/* the one label that must not fade — it names what the money is */
.mast-acct-label { letter-spacing: 0.14em; }

/* ---------- prose gets its own voice ----------
   Everything in this app was rendering in mono, which is right for data and
   wrong for sentences: it turned the honesty copy into texture nobody reads.
   Archivo was already being downloaded and used by nothing. Mono stays on
   every number, label and chip; these four surfaces are the ones that are
   actually PROSE, so they get read instead of scanned. */
.intro-banner span,
.book-note,
.gate-copy,
.gate-fine {
  font-family: var(--font);
  letter-spacing: 0.005em;
  line-height: 1.5;
  text-transform: none;
}
.intro-banner span { font-size: 12px; font-weight: 600; }
.book-note { font-size: 11px; }
.gate-copy { font-size: 13px; font-weight: 500; }
.gate-fine { font-size: 10.5px; }

/* ============ the account gate ============ */

.gate {
  position: fixed;
  inset: 0;
  z-index: 150;
  display: grid;
  place-items: center;
  padding: 20px;
  background: rgba(236, 231, 219, 0.72);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
}
.gate[hidden] { display: none; }

.gate-card {
  width: min(430px, 100%);
  background: var(--paper);
  border: 2px solid var(--ink);
  box-shadow: 8px 8px 0 rgba(20, 19, 18, 0.85);
  padding: 22px 22px 18px;
  transform: rotate(-0.4deg);
}
.gate-card.gate-shake { animation: gateShake 0.4s ease; }
/* every step bakes in the card's resting rotate(-0.4deg), or the shake
   would snap the print-sheet tilt upright for its whole 0.4s */
@keyframes gateShake {
  0%, 100% { transform: translateX(0) rotate(-0.4deg); }
  10% { transform: translateX(-4px) rotate(-0.4deg); }
  20% { transform: translateX(4px) rotate(-0.4deg); }
  30% { transform: translateX(-4px) rotate(-0.4deg); }
  40% { transform: translateX(4px) rotate(-0.4deg); }
  50% { transform: translateX(-3px) rotate(-0.4deg); }
  60% { transform: translateX(3px) rotate(-0.4deg); }
  70% { transform: translateX(-2px) rotate(-0.4deg); }
  80% { transform: translateX(2px) rotate(-0.4deg); }
  90% { transform: translateX(-1px) rotate(-0.4deg); }
}
.gate-head { display: flex; flex-direction: column; gap: 3px; margin-bottom: 12px; }
.gate-word {
  font-family: var(--display);
  font-size: 42px;
  line-height: 1;
  letter-spacing: 0.02em;
  background: var(--ink);
  color: var(--paper);
  padding: 4px 14px 7px;
  align-self: flex-start;
}
.gate-tag {
  font-family: var(--mono);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.22em;
  color: var(--muted);
}
.gate-copy {
  /* prose, not data — Archivo (see the prose-voice block above) */
  font-family: var(--font);
  font-size: 13px;
  font-weight: 500;
  line-height: 1.5;
  letter-spacing: 0.005em;
  text-transform: none;
  margin-bottom: 14px;
}
.gate-copy strong { font-weight: 800; border-bottom: 2px solid var(--ink); }
/* ---------- password field details a real product ships ---------- */

.pw-wrap { position: relative; display: block; }
.pw-wrap input { padding-right: 56px; }
.pw-peek {
  position: absolute;
  top: 50%;
  right: 6px;
  transform: translateY(-50%);
  font-family: var(--mono);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--muted);
  /* measured 36×24 with 5px padding — under the 24px minimum on the one
     control every single person taps on the way in */
  padding: 7px 8px;
  min-width: 44px;
  min-height: 28px;
  border: 1px solid transparent;
}
.pw-peek:hover { color: var(--ink); border-color: var(--ink); }
.pw-peek[aria-pressed="true"] { color: var(--ink); border-color: var(--ink); background: var(--paper-deep); }

/* strength is guidance, not a gate — it never blocks a submit */
.pw-meter { display: flex; align-items: center; gap: 8px; margin: 6px 10px 0; }
.pw-bar { flex: 1; height: 4px; background: var(--paper-deep); border: 1px solid var(--muted); position: relative; }
.pw-bar i { display: block; height: 100%; width: 0; background: var(--ink); transition: width 0.18s ease; }
.pw-word {
  font-family: var(--mono);
  font-size: 8px;
  font-weight: 700;
  letter-spacing: 0.1em;
  color: var(--muted);
  min-width: 52px;
  text-align: right;
}

.caps-warn {
  margin: 6px 10px 0;
  font-family: var(--mono);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.08em;
  padding: 4px 7px;
  background: var(--ink);
  color: var(--paper);
}

.gate-mode { display: flex; gap: 8px; margin-bottom: 12px; }
.gate-mode .type-btn { flex: 1; padding: 8px 0; font-size: 11px; }

.gate-form .ticket-field { margin: 0 0 10px; }
.gate-form .ticket-field em { font-style: normal; opacity: 0.75; }

/* The two ways out of a stuck sign-in — "forgot password" and "email me a
   link instead" — were 9px of unpadded text: about a 12px-tall target, half
   the 24px minimum, on the one screen where a stuck person needs them most.
   The padding grows the target; the negative margin keeps the sheet's layout
   where it was. */
.gate-link {
  font-family: var(--mono);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-decoration: underline;
  text-underline-offset: 3px;
  display: inline-block;
  padding: 8px 5px;
  margin: -8px -5px;
}
.gate-link:hover { background: var(--paper-deep); }
/* dimming a 10px recovery link on top of muted colour is one veil too many */
.gate-alt-small { margin-top: 12px; }
.gate-btn { margin: 0; width: 100%; font-size: 19px; }
.gate-note {
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.05em;
  margin-top: 10px;
  padding: 7px 9px;
  background: var(--mint);
  outline: 2px solid var(--ink);
}
.gate-note.gate-note-err { background: var(--ink); color: var(--paper); outline: none; }
.gate-alt {
  font-family: var(--mono);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  margin-top: 14px;
}
/* the anchor gets the same grown hit area as .gate-link beside it */
.gate-alt a {
  text-decoration: underline;
  text-underline-offset: 3px;
  display: inline-block;
  padding: 8px 5px;
  margin: -8px -5px;
}
.gate-fine {
  font-family: var(--font);
  font-size: 10.5px;
  font-weight: 500;
  line-height: 1.5;
  letter-spacing: 0.005em;
  color: var(--muted);
  margin-top: 10px;
  border-top: 1px dashed var(--muted);
  padding-top: 8px;
}

.chip-account { max-width: 140px; overflow: hidden; text-overflow: ellipsis; }
.chip-account.is-offline { background: var(--ink); color: var(--paper); }

/* ============ toast (order feedback) ============ */

.toast {
  position: fixed;
  z-index: 210;
  bottom: 18px;
  left: 50%;
  transform: translateX(-50%) rotate(-0.5deg);
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  background: var(--ink);
  color: var(--paper);
  padding: 8px 14px;
  box-shadow: 4px 4px 0 rgba(20, 19, 18, 0.35);
  animation: toastIn 0.18s ease;
}
.toast.toast-mint { background: var(--mint); color: var(--ink); outline: 2px solid var(--ink); }
/* the worst outcome in the app — same ink/paper palette as every other
   toast, but heavier and held a beat longer so it can't be mistaken for a
   routine close */
/* an ink border on an ink toast is invisible — the edge has to be cut in
   paper to read as heavier, the same inversion .toast-mint uses */
.toast.toast-liq { border: 2px solid var(--paper); outline: 2px solid var(--ink); box-shadow: 5px 5px 0 rgba(20, 19, 18, 0.6); animation: toastIn 0.18s ease, toastShake 0.4s ease 0.18s; }
@keyframes toastIn { from { transform: translateX(-50%) translateY(8px) rotate(-0.5deg); opacity: 0; } }
/* keeps the toast's resting translateX(-50%) rotate(-0.5deg) at every step
   so the shake doesn't un-rotate the toast mid-animation */
@keyframes toastShake {
  0%, 100% { transform: translateX(-50%) rotate(-0.5deg); }
  20% { transform: translateX(calc(-50% - 3px)) rotate(-0.5deg); }
  40% { transform: translateX(calc(-50% + 3px)) rotate(-0.5deg); }
  60% { transform: translateX(calc(-50% - 2px)) rotate(-0.5deg); }
  80% { transform: translateX(calc(-50% + 2px)) rotate(-0.5deg); }
}

/* ============ build-out: chart controls ============ */

.chip-more { align-self: center; }

.ema-rail { display: flex; gap: 0; }
.ema-btn {
  font-family: var(--mono);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.06em;
  padding: 4px 7px;
  border: 1px dashed var(--muted);
  margin-left: -1px;
  background: var(--paper);
  transition: background 0.12s ease;
}
.ema-btn:first-child { margin-left: 0; }
.ema-btn[aria-pressed="true"] { border: 1px solid var(--ink); background: var(--ink); color: var(--paper); }
.ema-btn:not([aria-pressed="true"]):hover { background: var(--paper-deep); }

#alertArm[aria-pressed="true"] { background: var(--mint); outline: 2px solid var(--ink); }

.chart-hint {
  position: absolute;
  bottom: 30px;
  left: 50%;
  transform: translateX(-50%) rotate(-0.5deg);
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  padding: 6px 12px;
  background: var(--mint);
  color: var(--ink);
  outline: 2px solid var(--ink);
  pointer-events: none;
  white-space: nowrap;
}

/* live price tick — mint = up-beat, ink = down-beat, one flash then gone */
.mast-mark { transition: background 0.35s ease, color 0.35s ease; padding: 0 4px; }
.mast-mark.is-tick { background: var(--mint); transition: none; }
.mast-mark.is-tick-down { background: var(--ink); color: var(--paper); transition: none; }

/* feed is stale/offline — every number these read is frozen, not current;
   strike them so nobody trades off a dead price without noticing. 0.65, not
   a rounder number: computed against the real hex values, this is the
   opacity floor that keeps mast-mark/equityVal (ink-on-paper), .pnl-neg
   (paper-on-ink) and .pnl-pos (ink-on-mint) all >= 4.5:1 once faded —
   0.55 measured 3.79-3.87:1 on every one of them. */
body.is-stale .mast-mark, body.is-stale .pnl-chip, body.is-stale #equityVal {
  opacity: 0.65;
  text-decoration: line-through;
  text-decoration-thickness: 1px;
}
body.is-stale .liq-near { animation: none; }

.mast-substat {
  font-family: var(--mono);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.mast-acct-label em { font-style: normal; font-variant-numeric: tabular-nums; }
.mast-acct-label em.is-up { background: var(--mint); padding: 0 3px; color: var(--ink); }
.mast-acct-label em.is-down { background: var(--ink); padding: 0 3px; color: var(--paper); }

/* first-visit banner — impossible to miss, dies on GOT IT */
.intro-banner {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 9px var(--pad);
  /* was full-bleed mint — the largest colored field in the product, spent on
     an onboarding notice. Mint means live-or-at-risk; a welcome message is
     neither. Ink rule carries the emphasis instead. */
  background: var(--paper-deep);
  border-left: 4px solid var(--ink);
  border-bottom: 2px solid var(--ink);
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.05em;
  position: relative;
  z-index: 55;
}
.intro-banner[hidden] { display: none; }
.intro-banner span { flex: 1; min-width: 0; }
.intro-banner .chip-btn { flex: none; }

.book-ro {
  font-style: normal;
  font-size: 8px;
  letter-spacing: 0.1em;
  padding: 1px 4px;
  border: 1px solid var(--ink);
  background: var(--paper);
  margin-left: 6px;
}

/* ============ tape & book ============ */

.desk-table-tape td { padding: 3px 10px; font-size: 11px; }
.tape-sell td { background: rgba(20, 19, 18, 0.05); }
.tape-side { font-weight: 700; }
/* whale prints stand out — size talks */
.tape-whale td { font-weight: 800; border-top: 1px solid var(--ink); border-bottom: 1px solid var(--ink); }

/* book rows load the ticket on click */
.desk-table-book tbody tr:not(.book-spread) { cursor: pointer; }
.desk-table-book tbody tr:not(.book-spread):hover td { background: var(--paper-deep); }
.tape-new td { animation: tapeIn 0.25s ease; }
@keyframes tapeIn { from { background: var(--paper-deep); } }

.desk-table-book td { padding: 3px 10px; font-size: 11px; position: relative; }
.book-bar {
  position: absolute;
  inset: 1px 0;
  background: rgba(20, 19, 18, 0.12);
  pointer-events: none;
}
.book-ask .book-bar { background: rgba(20, 19, 18, 0.2); }
.book-bar-th, .book-bar-td { width: 34%; min-width: 90px; }
.book-spread td {
  font-family: var(--mono);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.1em;
  color: var(--muted);
  text-align: center !important;
  border-top: 1px dashed var(--muted);
  border-bottom: 1px dashed var(--muted);
  background: var(--paper-deep);
}

/* ============ report ============ */

.report { padding: 10px 12px 16px; }
.report-head { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.report-sub { font-family: var(--mono); font-size: 9px; font-weight: 700; letter-spacing: 0.1em; color: var(--muted); }
.report-head .chip-btn { margin-left: auto; }

.report-curve-wrap { position: relative; height: 120px; border: var(--line); background: var(--paper); margin-bottom: 10px; }
#reportCurve { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }

.report-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(118px, 1fr));
  gap: 0;
  border: 1px dashed var(--muted);
  margin-bottom: 12px;
}
.report-grid > div { padding: 7px 9px; border: 1px dashed var(--muted); margin: -1px 0 0 -1px; }
.report-grid dt { font-family: var(--mono); font-size: 8px; font-weight: 700; letter-spacing: 0.1em; color: var(--muted); }
.report-grid dd { font-family: var(--mono); font-size: var(--t-lead); font-weight: 800; font-variant-numeric: tabular-nums; }
.report-grid dd .pnl-chip { font-size: 12px; }
.report-coins { border: var(--line); }
.report-empty { font-family: var(--mono); font-size: 11px; font-weight: 700; color: var(--muted); padding: 12px 0; letter-spacing: 0.08em; }

/* ============ journal — every note, dense ============ */

.report-head-style { margin-top: 16px; padding-top: 12px; border-top: 1px dashed var(--muted); }

.journal-row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px 12px;
  padding: 7px 2px;
  border-bottom: 1px solid rgba(107, 103, 95, 0.25);
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 600;
}
.journal-row:hover { background: var(--paper-deep); }
.journal-row .jr-date { flex: none; width: 74px; color: var(--muted); font-size: 10px; font-variant-numeric: tabular-nums; }
.journal-row .jr-pair { flex: none; width: 58px; font-weight: 800; }
.journal-row .jr-side { flex: none; width: 44px; font-size: 9px; letter-spacing: 0.08em; }
.journal-row .jr-pnl { flex: none; width: 76px; text-align: right; font-variant-numeric: tabular-nums; }
.journal-row .jr-note {
  flex: 1 1 160px;
  min-width: 0;
  color: var(--ink);
  font-weight: 600;
  font-style: normal;
  white-space: normal;
  word-break: break-word;
}
.journal-empty { font-family: var(--mono); font-size: 11px; font-weight: 700; color: var(--muted); padding: 14px 2px; letter-spacing: 0.08em; }

/* ============ inline TP/SL cell editing ============ */

.cell-editable { cursor: pointer; text-decoration: underline dotted rgba(107, 103, 95, 0.7); text-underline-offset: 3px; }
.cell-editable:hover { background: var(--paper-deep); }

/* note column — positions (editable) and history (read of what was set) */
.cell-note {
  max-width: 150px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-align: left !important;
  cursor: pointer;
  text-decoration: underline dotted rgba(107, 103, 95, 0.7);
  text-underline-offset: 3px;
}
.cell-note:hover { background: var(--paper-deep); }
.note-empty { color: var(--muted); font-weight: 600; opacity: 0.65; }
.cell-edit-input {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 700;
  width: 78px;
  padding: 2px 4px;
  border: 2px solid var(--ink);
  background: var(--paper);
  font-variant-numeric: tabular-nums;
}

/* micro-press feedback everywhere buttons live */
.chip-btn:active, .tf-btn:active, .ema-btn:active, .desk-tab:active,
.pair-tab:active, .row-btn:active, .type-btn:active, .side-btn:active { transform: translateY(1px); }

/* ============ responsive ============ */

@media (max-width: 1180px) {
  :root { --rail-w: 200px; }
}

@media (max-width: 1020px) {
  .cockpit {
    grid-template-columns: minmax(0, 1fr) 280px;
    grid-template-rows: minmax(300px, 1fr) minmax(170px, 240px) auto;
    grid-template-areas:
      "chart ticket"
      "desk  desk"
      "rail  rail";
  }
  .rail { border-top: 2px solid var(--ink); max-height: 300px; }
  .panel-desk { border-bottom: none; }
  .rail-stack { display: flex; gap: 10px; overflow-x: auto; padding: 12px; }
  .receipt { flex: 0 0 190px; margin-bottom: 0; }
  .rail-slot { display: none; }
}

@media (max-width: 760px) {
  /* ============ VERTICAL BUDGET: masthead rebuilt as 3 explicit rows ============
     Was up to 6 wrapped lines (brand, title, acct, live-stats, pairs each
     landing wherever flex-wrap happened to break them) eating ~270px before
     a single chart pixel showed. Rebuilt with "order" into exactly three
     deliberate rows so the chart — not the header — owns the first screen:
       row 1  brand + wordmark  ................  price + 24h delta
       row 2  PAPER STAGE + WHAT IS THIS  .......  equity + CTRL-K
       row 3  market tabs + MORE
     Funding/mark/volume drop to the CTRL-K palette + panel tooltips —
     real numbers, just not fighting for space on the smallest screen. */
  .mast { padding: 7px 10px; gap: 0; }
  /* each wrapper becomes a real flex row now — the "order" values set on
     the children (base rules, above) sort correctly inside every row
     since they're already ascending in the sequence this layout wants. */
  .mast-row { display: flex; align-items: center; flex-wrap: wrap; column-gap: 8px; row-gap: 5px; width: 100%; }
  .mast-row + .mast-row { margin-top: 6px; }

  .mast-brand { font-size: 9px; padding: 4px 6px; }
  .mast-title { font-size: 13px; padding: 2px 7px 3px; }
  .mast-tag { display: none; } /* tagline is decoration once you're on the page */

  .mast-live { margin-left: auto; gap: 7px; }
  .mast-mark { font-size: 21px; }
  .mast-stat { font-size: 9px; }
  /* secondary readouts: real data, just not first-screen real estate —
     still reachable via CTRL-K / the panel that already carries them */
  #realMark, #dayVol, #fundingRate { display: none; }

  .chip-sim { font-size: 8px; padding: 5px 7px; }

  .mast-acct { margin-left: auto; gap: 7px; }
  .equity-spark { display: none; }
  .mast-acct-label { font-size: 8px; }
  .mast-acct-val { font-size: 16px; }

  /* row 3: WHAT IS THIS + the market scroller + MORE. The scroller is the
     one flexible member — min-width:0 is the fix, not decoration: without
     it a flex item's minimum width defaults to its *content* width, so a
     10-market nav would refuse to shrink and blow the row wide instead of
     scrolling internally. */
  #whatIs { flex: none; font-size: 8px; padding: 5px 7px; }
  /* flex-basis:0 (not auto) is what actually keeps this on the same line
     as WHAT IS THIS/MORE — with "auto" the wrap algorithm sizes it by its
     scrollable *content* (multiple markets wide) before shrinking, which
     alone busts the row; starting from 0 and growing into the leftover
     space is what lets it dock beside its siblings and scroll inside that
     space instead of pushing them onto their own lines. */
  .mast-pairs { flex: 1 1 0; min-width: 0; margin-left: 0; overflow-x: auto; flex-wrap: nowrap; scrollbar-width: none; overscroll-behavior-x: contain; -webkit-overflow-scrolling: touch; }
  .mast-pairs::-webkit-scrollbar { display: none; }
  #moreMarkets { flex: none; font-size: 9px; padding: 6px 8px; }

  /* A phone page SCROLLS — it does not squeeze four panels into one screen.
     The old rows were sized against the viewport (46vh) while the grid's box
     is the viewport minus ~395px of chrome, so the tracks summed ~175px taller
     than their container and, with overflow visible, the desk and rail painted
     straight over the footer (and the receipts rail collapsed to 2px).
     flex-shrink:0 lets the cockpit keep its natural height and hand the
     overflow to the page, where it belongs. */
  .cockpit {
    flex: 0 0 auto;
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: minmax(300px, 52vh) auto minmax(190px, auto) auto;
    grid-template-areas:
      "chart"
      "ticket"
      "desk"
      "rail";
  }
  .panel, .rail { min-height: 0; }
  /* the receipts ARE the signature mechanism — give them real height on a
     phone instead of the 2px sliver the overflowing grid left behind */
  .rail { max-height: none; }
  .rail-stack { min-height: 168px; align-items: flex-start; }
  .receipt { flex: 0 0 200px; }
  .panel { border-right: none; }
  .panel-ticket { border-top: 2px solid var(--ink); overflow-y: visible; }
  .foot-kbd { display: none; }
  /* paper-foot padding-bottom: set once, further down, sized to clear the
     fixed PLACE bar (safe-area + bar height), not just the home indicator */

  /* CRITICAL: iOS Safari zooms the whole page on focus of any text input
     under 16px — every ticket/gate field was 15px, every trade or sign-in
     attempt would yank the viewport in. 16px kills the zoom outright. */
  .ticket-field input, .palette input { font-size: 16px; }

  /* GATE: comfortable on a phone, no scrolling behind an open keyboard.
     The .ticket-field[hidden] bug fix above already removed the spurious
     NAME field (~60px); the rest is tighter spacing and a smaller (still
     unmistakable) wordmark — copy itself is never shortened. Measured
     504px before this block, ~420px after, against an 812px-tall phone. */
  .gate { padding: 14px; }
  .gate-card { padding: 16px 16px 14px; }
  .gate-head { margin-bottom: 8px; }
  .gate-word { font-size: 28px; padding: 3px 10px 5px; }
  .gate-copy { font-size: 10px; line-height: 1.45; margin-bottom: 10px; }
  .gate-mode { margin-bottom: 8px; }
  .gate-mode .type-btn { padding: 9px 0; }
  .gate-form .ticket-field { margin: 0 0 8px; }
  .gate-btn { padding: 10px 0 12px; font-size: 17px; }
  .gate-alt { margin-top: 8px; }
  .gate-alt-small { margin-top: 4px; }
  .gate-fine { margin-top: 8px; padding-top: 6px; }

  /* thumb-sized touch targets */
  .tf-btn { padding: 9px 11px; font-size: 12px; }
  .ema-btn { padding: 8px 9px; }
  .desk-tab { padding: 10px 12px 9px; }
  .pair-tab { padding: 10px 13px; }
  .row-btn { padding: 8px 11px; font-size: 10px; }
  .side-btn { padding: 12px 0 13px; }
  .place-btn { padding: 14px 0 16px; }
  .chip { padding: 7px 10px; }
  .panel-head { flex-wrap: wrap; min-height: 0; row-gap: 6px; }
  /* the OHLC readout is a hover affordance — desktop only */
  .ohlc-read { display: none; }
  /* the chart-head row already scrolls horizontally (nowrap below), so
     extra side padding here is free — it doesn't cost the vertical budget
     item 1 spent this whole pass cutting, only a bit more swipe distance.
     Measured 39x39 before (fails 44px on both axes); the wider padding
     clears 44px of width, same height. */
  .tf-btn { padding: 11px 17px; }
  /* chart controls: one swipeable row — the chart keeps its height */
  .panel-chart .panel-head { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }
  .panel-chart .panel-head::-webkit-scrollbar { display: none; }
  .tf-rail, .ema-rail { flex: none; }
  /* the action column stays reachable while wide tables scroll */
  #tblPositions .cell-actions,
  #tblPositions th:last-child,
  #tblOrders td:last-child,
  #tblOrders th:last-child { position: sticky; right: 0; background: var(--paper); box-shadow: -6px 0 6px -4px rgba(20, 19, 18, 0.25); }
  .cell-actions .row-btn { margin-left: 4px; }
  .book-note { display: none; }
  .intro-banner { position: sticky; top: 0; }
  .size-chip { padding: 9px 0; }

  /* replay bar: stays one swipeable row, thumb-sized controls */
  .replay-bar { padding: 8px 10px; gap: 10px; }
  .replay-label { font-size: 9px; padding-right: 10px; }
  .replay-btn, .replay-exit { padding: 8px 10px; }
  .replay-speed-field select { padding: 7px 6px; }

  /* note column stays out of the way of the sticky action column */
  .cell-note { max-width: 90px; }
  #tblHistory .cell-note { max-width: 70px; }

  /* TABLES: 14 columns is a lot at 375px. Positions keeps scrolling with
     its sticky action column, but ENTRY/LEV/FUNDING are the ones you
     check least — hidden with display:none on the th/td pair only, so
     the JS's tds[4]/[5]/[10]/[11]/[12] index binding (MID/LIQ/FUNDING/
     P&L/NOTE — see bindTriggerCell/posRowRefs in awake.js) never sees a
     cell removed or reordered, only skinnier rows. */
  #tblPositions th:nth-child(4), #tblPositions td:nth-child(4),   /* ENTRY */
  #tblPositions th:nth-child(9), #tblPositions td:nth-child(9),   /* LEV */
  #tblPositions th:nth-child(11), #tblPositions td:nth-child(11) /* FUNDING */
  { display: none; }

  /* the chart's own horizontal-scroll strip (timeframe + EMA rail) */
  .panel-chart .panel-head { overscroll-behavior-x: contain; -webkit-overflow-scrolling: touch; }
  .panel-ticket { overscroll-behavior-y: contain; -webkit-overflow-scrolling: touch; }

  /* touch targets that live OUTSIDE the vertical-budget-critical header/
     chart-head chrome get a fuller bump — a table row's CLOSE/CANCEL and
     the identity row's CTRL-K don't cost first-screen space to grow.
     (tf-rail/ema-rail/pair-tab stay as sized above: those sit in the
     chrome we just spent this whole pass cutting, and width already
     clears 44px there, so height wasn't inflated back in — see report.) */
  .row-btn { padding: 10px 12px; }
  .cell-actions .row-btn + .row-btn { margin-left: 6px; }
  .desk-tab { padding: 11px 13px 10px; }
  .mast-acct .chip-btn { padding: 8px 10px; }
  #whatIs, #moreMarkets { padding: 8px 9px; }

  /* ============ THUMB REACH ============
     Chosen approach: PLACE stays pinned to the viewport bottom rather than
     reordering the grid so the ticket comes before the chart. Reordering
     would win back a few inches of thumb travel but directly fights the
     #1 priority above — the chart owning the first screen — since the
     ticket's own height (side switch, size, leverage, TP/SL, preview) is
     substantial. A fixed CTA is the standard trading-app resolution to
     that exact tension (Robinhood/Coinbase do the same): the chart still
     opens the page, and PLACE is never more than a thumb away regardless
     of whether you're reading the chart, scrolling the desk, or checking
     receipts. The ticket itself stays second in scroll order (right after
     the chart, before desk/rail) for anyone who wants the full context. */
  .panel-ticket { padding-bottom: 62px; }
  #placeBtn {
    position: fixed;
    left: 10px;
    right: 10px;
    bottom: calc(10px + env(safe-area-inset-bottom, 0px));
    margin: 0;
    width: auto;
    z-index: 45;
    box-shadow: 0 4px 0 rgba(20, 19, 18, 0.9), 0 8px 20px rgba(20, 19, 18, 0.35);
  }
  #placeBtn:active { box-shadow: 0 2px 0 rgba(20, 19, 18, 0.9); }
  /* room so the fixed bar never covers the last thing on the page */
  .paper-foot { padding-bottom: calc(74px + env(safe-area-inset-bottom, 0px)); }
  /* the browser's own scroll-into-view for a focused field should stop
     short of the fixed bar, not underneath it */
  .ticket-field input { scroll-margin-bottom: 76px; }
}

/* ============ LANDSCAPE PHONE (e.g. 812x375) ============
   Width alone (812px) sits above the 760px breakpoint, so none of the
   portrait rules above fire here — the masthead was rendering at full
   desktop density (wrapping to ~207px) inside a viewport that's only
   375px tall, leaving the chart under 120px of visible canvas. Keyed off
   height, not width: a short viewport is the actual signal, regardless
   of how wide it is. Restores a real 2-pane cockpit (chart|ticket over
   desk|rail) instead of the portrait single-column stack, which would
   make the chart even shorter here, not taller. */
@media (max-height: 500px) and (orientation: landscape) {
  .mast { padding: 4px 10px; gap: 6px 8px; }
  /* height is the scarce axis here, not width: unwrap the three mobile rows
     back into ONE wrapping line (as on desktop) so 812px of width absorbs
     what would otherwise cost three stacked rows of vertical budget */
  .mast-row { display: contents; }
  /* the explainer is one tap away in the command palette — its chip is the
     cheapest thing to drop when every pixel of height is chart */
  #whatIs { display: none; }
  .mast-brand { font-size: 9px; padding: 3px 6px; }
  .mast-title { font-size: 12px; padding: 2px 6px 3px; }
  .mast-tag { display: none; }
  .mast-live { margin-left: auto; gap: 7px; }
  .mast-mark { font-size: 18px; }
  .mast-stat { font-size: 9px; }
  #realMark, #dayVol, #fundingRate { display: none; }
  .chip-sim { font-size: 8px; padding: 4px 6px; }
  .mast-acct { margin-left: auto; gap: 7px; }
  .equity-spark { display: none; }
  .mast-acct-label { font-size: 8px; }
  .mast-acct-val { font-size: 14px; }
  .mast-pairs { flex: 1 1 0; min-width: 0; margin-left: 0; overflow-x: auto; flex-wrap: nowrap; scrollbar-width: none; overscroll-behavior-x: contain; }
  .pair-tab { padding: 4px 9px; font-size: 11px; }
  .pair-tab .pair-mid { font-size: 8px; }
  /* the chart's own control row is the last big vertical cost above it */
  .panel-chart .panel-head { padding: 3px 8px; min-height: 0; }
  .tf-btn, .ema-btn { padding: 5px 8px; }
  .panel-head .chip { padding: 4px 7px; }
  .mast-pairs::-webkit-scrollbar { display: none; }
  #moreMarkets { flex: none; font-size: 9px; padding: 4px 7px; }
  .book-strip, .replay-bar { padding-top: 4px; padding-bottom: 4px; }
  /* the footer's ~8 fact chips wrap to 2-3 lines at this width and were
     quietly eating 98px of a 375px-tall viewport (body is a flex column,
     so the footer's natural height competes with the cockpit's flex:1
     for real space) — the one disclosure that matters at a glance, PAPER
     STAGE, already stays pinned in the masthead above. */
  .paper-foot { display: none; }

  /* the real fix: 2 columns x 2 rows, not 1 column x 4 rows.
     Track sizing note: a non-flexible minmax() track (no fr) gets grown
     toward its max in an earlier pass than any fr track, so a generous
     max on the desk/rail row was winning the fight for space against the
     "flexible" chart row and leaving the chart shorter than the table
     below it — backwards. Giving the chart row its own floor (140px)
     fixes the priority: bases are reserved first (140 + 96 = 236 of
     266px available), then the small remainder tops up desk/rail toward
     its own cap, and chart only ever loses to an explicit floor, not to
     the other row's ceiling. */
  .cockpit {
    grid-template-columns: minmax(0, 1fr) 260px;
    /* chart floor raised now that the masthead unwrapped: the desk row keeps
       enough height for two readable rows, everything else goes to price */
    grid-template-rows: minmax(180px, 1fr) minmax(90px, 124px);
    grid-template-areas:
      "chart ticket"
      "desk  rail";
  }
  .panel-desk { border-right: 2px solid var(--ink); border-bottom: none; }
  .rail { border-top: none; border-left: 2px solid var(--ink); max-height: none; }
  .rail-stack { display: flex; flex-direction: column; overflow-y: auto; }
  .receipt { flex: none; }

  /* ticket keeps the desktop behavior here (scrolls in its own column —
     it's a side panel again, not a stacked block in page flow) */
  .ticket-field input, .palette input { font-size: 16px; }

  #tblPositions th:nth-child(4), #tblPositions td:nth-child(4),
  #tblPositions th:nth-child(9), #tblPositions td:nth-child(9),
  #tblPositions th:nth-child(11), #tblPositions td:nth-child(11)
  { display: none; }

  /* GATE: same reasoning as the portrait block — see the comment there */
  .gate { padding: 10px; }
  .gate-card { padding: 12px 16px 10px; max-height: calc(100vh - 20px); overflow-y: auto; }
  .gate-head { margin-bottom: 6px; }
  .gate-word { font-size: 22px; padding: 2px 8px 3px; }
  .gate-copy { font-size: 9px; line-height: 1.35; margin-bottom: 6px; }
  .gate-mode { margin-bottom: 6px; }
  .gate-form .ticket-field { margin: 0 0 6px; }
  .gate-btn { padding: 7px 0 8px; font-size: 15px; }
  .gate-alt, .gate-fine { margin-top: 5px; padding-top: 4px; }
}

/* reduced motion: no print theater, no pulses */
/* A just-opened position, marked once where it lives. Rows are only rebuilt on
   a structural change, so this plays a single time — never on a price tick. */
@keyframes rowFresh {
  0% { background: rgba(20, 19, 18, 0.2); }
  100% { background: transparent; }
}
.desk-table tr.row-fresh td { animation: rowFresh 1.6s ease-out 1; }

/* Same not-ready language as the place button, chip-sized. Still clickable so
   it can say why. */
.chip-btn[aria-disabled="true"] {
  border-style: dashed;
  opacity: 0.55;
}
.chip-btn[aria-disabled="true"]:hover { box-shadow: none; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .receipt.is-new { animation: none; }
  .receipt-stamp.stamp-in { animation: none; opacity: 1; }
  .conn-dot, .chart-badge, .liq-near { animation: none !important; }
  .toast { animation: none; }
  /* the heavier border/shadow still has to land — only the shake is motion */
  .toast.toast-liq { animation: none; }
  .desk-table tr.row-fresh td { animation: none; background: rgba(20, 19, 18, 0.09); }
  .mast-brand:hover, .chip-btn:hover, .place-btn:hover { transform: none; }
  .gate-card.gate-shake { animation: none; }
}
