/* hltrenches — a terminal you logged into. Text on black. No boxes. */

:root {
  --bg: #000;
  --fg: #d6d6d6;
  --dim: #767676;
  /* #454545 on black is 2.2:1 -- under every contrast floor there is, and
     it carried real words: the nav, the section subtitles, the coverage
     notes. A caveat nobody can read is a caveat we did not write. */
  --dimmer: #767676;
  --green: #4fe36b;
  --green-hi: #a8ffb8;
  --red: #ff5a5a;
  --red-hi: #ffa3a3;
  --cyan: #56d2f5;
  --amber: #e8b400;
  --magenta: #f57ff5;
  --mono: "JetBrains Mono", Menlo, ui-monospace, SFMono-Regular, Consolas, monospace;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; background: var(--bg); color: var(--fg);
  font-family: var(--mono); font-size: 13px; line-height: 1.45;
  font-variant-numeric: tabular-nums; -webkit-font-smoothing: antialiased; }
body { padding: 0 0 24px; }

a { color: var(--cyan); text-decoration: none; }
a:hover { text-decoration: underline; }
.up { color: var(--green); }
.down { color: var(--red); }
.flat, .dim { color: var(--dim); }
pre { margin: 0; font: inherit; white-space: pre-wrap; }

/* top bar: inverse video, a curses status line */
.bar { background: var(--fg); color: #000; padding: 1px 8px; display: flex;
  gap: 14px; align-items: baseline; white-space: nowrap; overflow: hidden; }
.bar-name { font-weight: 700; }
.bar-keys { margin-left: auto; color: #222; flex: 0 0 auto; }
.bar > * { flex: 0 0 auto; }
.k { display: inline-block; padding: 0 3px; margin-right: 2px; background: #000;
  color: var(--fg); cursor: pointer; }
.kk { cursor: pointer; white-space: nowrap; }
.kk.on .k { background: var(--green); color: #000; }
/* the only shrinkable thing in the bar: at a narrow window the credit
   ellipsises rather than shoving the key hints off the right edge. */
.credit { color: #333; flex: 0 1 auto; min-width: 0; overflow: hidden;
  text-overflow: ellipsis; }
.credit-foot { padding: 8px; color: var(--dimmer); }
.sess { font-weight: 700; color: #000; }
.sess.tick { animation: sesstick .5s ease-out; }
@keyframes sesstick { from { background: var(--green); } to { } }

/* the big-fill line */
.callout { padding: 1px 8px; font-weight: 700; white-space: nowrap;
  overflow: hidden; animation: co 2.6s ease forwards; }
.callout.buy { background: var(--green); color: #000; }
.callout.sell { background: var(--red); color: #000; }
.callout[hidden] { display: none; }
@keyframes co { 0% { opacity: 0; } 8% { opacity: 1; } 85% { opacity: 1; } 100% { opacity: 0; } }

/* alert strip: the LATEST alert only, one line, and a +N that opens the rest
   in the drawer. It never scrolls sideways — a scrollbar up here is an eye
   sore and it steals the tape's room. */
.strip { padding: 2px 8px; color: var(--amber); white-space: nowrap;
  overflow: hidden; border-bottom: 1px solid #151515;
  display: flex; gap: 10px; align-items: baseline; }
.strip .a { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.strip .more { flex: 0 0 auto; margin-left: auto; color: var(--dim);
  cursor: pointer; border-bottom: 1px dotted var(--dimmer); }
.strip .more:hover, .strip .more.open { color: var(--fg); }
.strip .a b { font-weight: 700; }
.strip .kind { color: var(--dim); }
.strip .a.liq b { color: var(--red); }
.strip .a.whale b { color: var(--green); }
.strip .a.crowding b { color: var(--magenta); }
.strip .a.nearliq b { color: var(--amber); }
.strip .a.flip b { color: var(--cyan); }

/* readout */
.ro { padding: 6px 8px 4px; color: var(--green); }
.ro .h { color: var(--fg); font-weight: 700; }
.ro .d { color: var(--dim); }
.ro .big { font-weight: 700; color: var(--green-hi); }
.ro .neg { color: var(--red); }
.ro .live::before { content: "● "; color: var(--green); animation: pulse 2s infinite; }
.ro .warn::before { content: "● "; color: var(--amber); }
.ro .dead::before { content: "● "; color: var(--red); }
@keyframes pulse { 50% { opacity: .25; } }
.foot { color: var(--dimmer); }

/* section title */
.sec { padding: 10px 8px 2px; color: var(--cyan); font-weight: 700;
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.secn { color: var(--dimmer); font-weight: 400; }
.tools { margin-left: auto; font-weight: 400; display: flex; gap: 10px;
  align-items: center; }

input, select { font: inherit; color: var(--fg); background: #000;
  border: 1px solid var(--dimmer); padding: 0 4px; border-radius: 0; }
input::placeholder { color: var(--dimmer); }
select { color: var(--dim); }
.chk { color: var(--dim); font-weight: 400; }

/* tables */
.tw { overflow-x: auto; }
.tw.short { max-height: 300px; overflow-y: auto; }
table.t { border-collapse: collapse; white-space: nowrap; }
table.t th { text-align: left; font-weight: 400; color: var(--fg); padding: 2px 8px; }
#tape-table th { position: static; }
table.t td { padding: 0 8px; color: var(--green); }
table.t th.n, table.t td.n { text-align: right; }
table.t tbody tr:hover td { background: #101010; }
.tw.short table.t th { position: sticky; top: 0; background: #000; }

tr.sell td { color: var(--red); }
tr.buy td { color: var(--green); }
td.u, td.u a { color: var(--cyan); }
td.d, .d { color: var(--dim); }
.sym { font-weight: 700; cursor: pointer; }
.sym:hover { text-decoration: underline; color: var(--cyan); }
.who { cursor: pointer; }
.who:hover { text-decoration: underline; color: var(--fg); }
.prov { color: var(--dimmer); }

/* badges: tiny caps after the row's meaning */
.bg { font-size: 10px; margin-right: 4px; display: inline-block;
  vertical-align: baseline; }
.bg-NEW { color: var(--cyan); }
.bg-ADD { color: var(--green); }
.bg-REDUCE { color: var(--amber); }
.bg-CLOSE { color: var(--dim); }
.bg-FLIP { color: var(--magenta); }
.bg-LIQ { color: #000; background: var(--red); padding: 0 2px; }
.bg-WHALE { color: #000; background: var(--green); padding: 0 2px; }
.bg-CHASE { color: var(--amber); }
.bg-ACCUM { color: var(--magenta); }

/* state badges */
.st { font-size: 10px; }
.st-printing { color: var(--green); }
.st-draining { color: var(--red); }
.st-flat { color: var(--dimmer); }
.st-chasing { color: var(--amber); }
.st-squeezed { color: #000; background: var(--red); padding: 0 2px; }
.st-holding { color: var(--dim); }

/* size ladders: big fills brighten, the biggest get a bar */
tr.sz2 td.size { font-weight: 700; }
tr.sz3 td { font-weight: 700; }
tr.sz3.buy td { color: var(--green-hi); }
tr.sz3.sell td { color: var(--red-hi); }
tr.sz4 td { font-weight: 700; }
tr.sz4.buy td { background: #062a06; color: var(--green-hi); }
tr.sz4.sell td { background: #2e0808; color: var(--red-hi); }
tr.new.buy td { animation: fb 1.1s ease-out; }
tr.new.sell td { animation: fs 1.1s ease-out; }
@keyframes fb { from { background: var(--green); color: #000; } to { } }
@keyframes fs { from { background: var(--red); color: #000; } to { } }
@media (prefers-reduced-motion: reduce) { tr.new td { animation: none !important; } }

.empty { padding: 6px 8px; color: var(--dimmer); }

/* modal */
.modal { position: fixed; inset: 0; z-index: 200; background: rgba(0,0,0,.92);
  display: flex; align-items: flex-start; justify-content: center;
  padding: 24px 8px; overflow-y: auto; }
.modal[hidden] { display: none; }
.modal-box { background: #000; border: 1px solid var(--dim);
  width: min(1200px, 100%); position: relative; padding-bottom: 8px; }
.modal-close { position: absolute; top: 4px; right: 8px; background: none;
  border: 0; color: var(--dim); font: inherit; cursor: pointer; }
.modal-close:hover { color: var(--fg); }
.mhead { padding: 8px 8px 2px; }
.mhead h3 { margin: 0; font-size: 14px; color: var(--cyan); }
.mtitle { padding: 10px 8px 2px; color: var(--cyan); font-weight: 700; }
.curve { display: block; width: 100%; height: 76px; padding: 0 8px; }

/* ---------------------------------------------------------- phones */
@media (max-width: 834px) {
  html, body { font-size: 12.5px; }
  .bar { flex-wrap: wrap; white-space: normal; padding: 3px 8px; gap: 6px 12px; }
  .credit { order: 3; flex-basis: 100%; }
  .bar-keys { order: 4; flex-basis: 100%; margin-left: 0; display: flex;
    flex-wrap: wrap; gap: 6px; }
  .bar-keys .k { display: none; }
  .kk { padding: 2px 8px; border: 1px solid #000; }
  .kk.on { background: var(--green); }
  .kk.desk { display: none; }
  .m-hide { display: none !important; }
  .ro { font-size: 11px; }
  .sec { gap: 6px; }
  .tools { margin-left: 0; flex-basis: 100%; }
  .tools input { width: 100%; min-width: 0; }
  .tw { -webkit-overflow-scrolling: touch; }
  table.t th, table.t td { padding: 1px 6px; }
  .callout { font-size: 11px; }
  .modal { padding: 8px 4px; }
}

/* ============================================================ v2 =========
   Hyperliquidated. Same terminal, more rooms. Everything below is still
   text on black: no cards, no shadows, no rounded corners. A "chart" here
   is a row of block characters, because that is what a terminal draws. */

/* the page nav, directly under the status bar */
.nav { padding: 1px 8px; color: var(--dimmer); white-space: nowrap;
  overflow-x: auto; border-bottom: 1px solid #141414; }
.nav a { color: var(--dim); margin-right: 14px; }
.nav a.on { color: var(--cyan); font-weight: 700; }
.nav a:hover { color: var(--fg); }

/* SUGGESTIONS: one line under the bar, at most three chips — COIN · LEAN ·
   confidence. The facts live behind a click, in the drawer, so the thing he
   trades from costs exactly one line and never grows a scrollbar. */
.leans { padding: 1px 8px; white-space: nowrap; overflow: hidden;
  border-bottom: 1px solid #141414; color: var(--dim);
  display: flex; flex-wrap: wrap; gap: 2px 14px; align-items: baseline;
  max-height: 3.2em; }
.leans .lb { color: var(--dimmer); flex: 0 0 auto; }
.leans .chip { flex: 0 1 auto; min-width: 0; max-width: 30ch; cursor: pointer;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  border-bottom: 1px dotted var(--dimmer); }
.leans .chip:hover, .leans .chip.open { color: var(--fg); border-bottom-color: var(--dim); }
.leans .chip b { font-weight: 700; }
.leans .chip .cn { color: var(--fg); }
.leans .chip.LONG b { color: var(--green); }
.leans .chip.SHORT b { color: var(--red); }
.leans .cf { color: var(--dimmer); }

/* the drawer: shut by default, at most a few lines when a chip or the +N
   opens it. Nothing above the tape is taller than four lines without a
   deliberate click. */
.drawer { padding: 3px 8px 4px; border-bottom: 1px solid #141414;
  background: #070707; max-height: 11em; overflow-y: auto; }
.drawer[hidden] { display: none; }
.drawer .dh { color: var(--fg); font-weight: 700; }
.drawer .df { color: var(--dim); padding-left: 2ch; }
.drawer .df .kind { color: var(--dimmer); }
.drawer .dx { float: right; color: var(--dim); cursor: pointer; }
.drawer .dx:hover { color: var(--fg); }

/* feed-health dot, in the status bar, so liveness survives the readout
   moving below the tape */
.dot { color: var(--dimmer); }
.dot.live { color: #0a7d1e; animation: pulse 2s infinite; }
.dot.warn { color: #8a6b00; }
.dot.dead { color: #b00000; }

/* NO horizontal scrollbars on the chrome. Only a data table may scroll
   sideways; a status line, a nav or a readout must not. */
.nav, .leans, .strip, .drawer, .rail, .hist, .tw.short {
  scrollbar-width: none; -ms-overflow-style: none; }
.nav::-webkit-scrollbar, .leans::-webkit-scrollbar, .strip::-webkit-scrollbar,
.drawer::-webkit-scrollbar, .rail::-webkit-scrollbar, .hist::-webkit-scrollbar,
.tw.short::-webkit-scrollbar { width: 0; height: 0; display: none; }

/* the right rail: a fixed column of wallet rank, collapsible */
.wrap { display: flex; align-items: flex-start; gap: 0; }
.main { flex: 1 1 auto; min-width: 0; }
.rail { flex: 0 0 55ch; max-width: 55ch; border-left: 1px solid #1b1b1b;
  position: sticky; top: 0; max-height: 100vh; overflow-y: auto; }
.rail.collapsed { flex-basis: 3ch; max-width: 3ch; overflow: hidden; }
.rail.collapsed .rail-body { display: none; }
.rail-head { padding: 6px 8px 2px; color: var(--cyan); font-weight: 700;
  display: flex; gap: 8px; align-items: baseline; }
.rail-head .x { margin-left: auto; color: var(--dim); cursor: pointer; }
.rail-sub { padding: 0 8px 4px; color: var(--dim); font-size: 10px;
  line-height: 1.3; white-space: normal; }
.rail.collapsed .rail-sub { display: none; }

/* the rank table itself: a real table, fixed columns, nothing wraps and
   nothing scrolls sideways -- a column that will not fit ellipsises. */
table.rt { width: 100%; table-layout: fixed; font-size: 10px;
  font-variant-numeric: tabular-nums; }
table.rt th, table.rt td { padding: 0 2px; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
table.rt thead th { color: var(--dim); font-weight: 700;
  border-bottom: 1px solid #1b1b1b; position: sticky; top: 0;
  background: #000; cursor: help; }
table.rt td { color: var(--dim); }
table.rt th:nth-child(1), table.rt td:nth-child(1) { width: 5%; }
table.rt th:nth-child(2), table.rt td:nth-child(2) { width: 17%; }
table.rt th:nth-child(3), table.rt td:nth-child(3) { width: 6%; }
table.rt th:nth-child(4), table.rt td:nth-child(4) { width: 13%; }
table.rt th:nth-child(5), table.rt td:nth-child(5) { width: 13%; }
table.rt th:nth-child(6), table.rt td:nth-child(6) { width: 8%; }
table.rt th:nth-child(7), table.rt td:nth-child(7) { width: 13%; }
table.rt th:nth-child(8), table.rt td:nth-child(8) { width: 13%; }
table.rt th:nth-child(9), table.rt td:nth-child(9) { width: 6%;
  text-align: center; }
tr.rail-row { cursor: pointer; border-bottom: 1px solid #0f0f0f; }
tr.rail-row:hover td { background: #101010; }
tr.rail-row .rk { color: var(--dimmer); }
tr.rail-row .nm { color: var(--fg); }
tr.rail-row .hd { color: var(--cyan); }
tr.rail-row .tk { color: var(--fg); }
tr.rail-row.bot td { color: var(--dimmer); }

/* the tape legend: one wrapped line that explains the odd columns once */
.legend { padding: 0 8px 3px; color: var(--dim); font-size: 10px;
  white-space: normal; }

/* tiers and flags */
.tier { font-size: 10px; padding: 0 2px; }
.tier-whale { color: #000; background: var(--green); }
.tier-large { color: var(--cyan); }
.tier-small { color: var(--dimmer); }
.st-bot { color: #000; background: var(--dimmer); padding: 0 2px; }
.ins { color: #000; background: var(--amber); padding: 0 2px; font-size: 10px;
  cursor: help; }
.ins-n { color: var(--dimmer); font-size: 10px; }
/* the FIRST-TOUCH chip: small, magenta, inline, and structurally incapable of
   taking a row to itself — see badgeHtml in app.js. */
.bg-FIRST-TOUCH { color: #000; background: var(--magenta); padding: 0 2px;
  display: inline-block; line-height: 1.2; font-size: 9px;
  vertical-align: baseline; }
tr.bot td { color: var(--dimmer); }

/* text bars: the only chart idiom this terminal owns */
.bar-row { display: flex; gap: 8px; align-items: baseline; padding: 0 8px; }
.bar-row .lbl { color: var(--dim); text-align: right; }
.bar-row .val { color: var(--fg); }
.bars { color: var(--green); letter-spacing: -0.5px; }
.bars.neg, .bars.short { color: var(--red); }
.bars i { color: var(--dimmer); font-style: normal; }
.hist { padding: 2px 8px; overflow-x: auto; }
.hist .row { white-space: pre; }
.hist .row.mark { color: var(--amber); font-weight: 700; }
.hist .lo { color: var(--green); }
.hist .sh { color: var(--red); }
.hist .px { color: var(--dim); }

/* key/value blocks in a readout */
.kv { padding: 4px 8px; color: var(--green); }
.kv b { color: var(--fg); font-weight: 700; }
.kv .k2 { color: var(--dim); }
.grid2 { display: flex; flex-wrap: wrap; gap: 0 28px; }

/* the lean board */
.lean { padding: 3px 8px; border-bottom: 1px solid #0f0f0f; }
.lean .hd { font-weight: 700; }
.lean.LONG .hd { color: var(--green); }
.lean.SHORT .hd { color: var(--red); }
.lean .conf { color: var(--dim); }
.lean .f { color: var(--dim); padding-left: 2ch; }
.warnline { padding: 4px 8px; color: var(--amber); }
.cover { padding: 2px 8px; color: var(--dimmer); }

@media (max-width: 900px) {
  .wrap { display: block; }
  .rail { flex: none; max-width: none; width: 100%; position: static;
    max-height: none; border-left: 0; border-top: 1px solid #1b1b1b; }
  .rail.collapsed { max-width: none; }
}

/* ===================================================== v3: the knowledge ==
   The tape carries five more columns and a click-to-expand card. Everything
   here is about ONE distinction being visible at a glance: a fact read from
   Hyperliquid, versus a figure we inferred from the tape. The ~ is that
   line, and it is deliberately a different colour from every number. */
.approx { color: var(--amber, #d59b3c); font-weight: 700; margin-right: 2px;
          cursor: help; }
.did { color: var(--fg, #d8d8d2); }
.did-open   { color: #6fd3a2; }
.did-add    { color: #4fb37f; }
.did-reduce { color: #d9a441; }
.did-close  { color: #9aa0a6; }
.did-flip   { color: #d76d6d; font-weight: 700; }
.did-none   { color: #6c7075; }
/* ------------------------------------------------- THE OVERFLOW FIX
   Reported 2026-09-04: "the `what it did` text runs across pos after / vs 24h
   / level / lev and overlaps the other side cell — unreadable."

   The cause was an auto-layout table: one long cell widened its column and
   pushed everything after it out of the viewport, and `white-space: nowrap`
   on the table meant the text simply ran on top of its neighbours. The tape
   is now a FIXED table with a stated width per column, and every cell clips
   with an ellipsis. Nothing is lost: the full text is on the cell's title. */
#tape-table { table-layout: fixed; width: 100%; }
#tape-table th, #tape-table td {
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  max-width: 0;                       /* fixed layout: the widths below win */
}
/* PERCENTAGES, not ch. A fixed table whose columns are sized in absolute
   units either overflows the main pane (and the last columns disappear under
   the rank rail) or leaves a gap. These always add to 100% of whatever width
   the pane has, so the tape fits at 1440 and at 390 alike. */
#tape-table col.c-time  { width: 7%; }
#tape-table col.c-side  { width: 4.5%; }
#tape-table col.c-coin  { width: 4.5%; }
#tape-table col.c-usd   { width: 6%; }
#tape-table col.c-px    { width: 6.5%; }
#tape-table col.c-sz    { width: 5.5%; }
#tape-table col.c-wal   { width: 9%; }
#tape-table col.c-who   { width: 5.5%; }
#tape-table col.c-did   { width: 18.5%; }
#tape-table col.c-pos   { width: 6%; }
#tape-table col.c-v24   { width: 6%; }
#tape-table col.c-lvl   { width: 5.5%; }
#tape-table col.c-lev   { width: 3%; }
#tape-table col.c-w24   { width: 5.5%; }
#tape-table col.c-cp    { width: 7%; }
#tape-table th, #tape-table td { padding: 0 5px; }
td.didcell { max-width: 0; }
/* the three states of `what it did`, and they are mutually exclusive */
.anch { color: #7a7f85; font-style: italic; }
.bg-BURST { color: #000; background: var(--cyan); padding: 0 2px;
  font-weight: 700; }
tr.burst td { background: #0b0f14; }
tr.burst:hover td { background: #131a22; }
/* THE PHONE TAPE IS SET AT THE BOTTOM OF THIS FILE, in THE MOBILE TERMINAL
   section: five columns given the full width, the other ten given none, and
   the ten reachable by tapping the row. The `table-layout: auto` rule that
   used to live here made `what it did` size itself to its longest sentence
   and pushed the tape into a sideways scroll of its own. */
.lv { font-size: 10px; letter-spacing: .04em; padding: 0 3px; border-radius: 2px;
      border: 1px solid currentColor; cursor: help; }
.lv-ATHIGH { color: #6fd3a2; }
.lv-ATLOW  { color: #d76d6d; }
.lv-ROUND  { color: #8fa8d8; }

tr.exp { cursor: pointer; }
tr.expbody > td { background: rgba(255,255,255,.03); padding: 6px 8px; }
.exp-card { display: grid; gap: 4px; }
.exp-l { font-weight: 700; }
.exp-p, .exp-s { font-size: 11px; color: var(--dim, #9aa0a6); }
.exp-t { margin-top: 4px; width: 100%; }
.exp-t th { font-size: 10px; }

/* the follow page */
.fl-bar { border: 1px solid var(--amber, #d59b3c); padding: 6px 8px;
          margin: 6px 0; font-size: 11px; }
.cons { display: flex; flex-wrap: wrap; gap: 6px; margin: 6px 0; }
.cons .c { border: 1px solid #333; padding: 2px 6px; font-size: 11px; }
.cons .c b { font-weight: 700; }
.bar { font-family: inherit; letter-spacing: -1px; }
.bar-l { color: #4fb37f; }
.bar-s { color: #d76d6d; }
.brief { white-space: pre-wrap; font-size: 12px; line-height: 1.5;
         max-width: 96ch; }


/* ------------------------------------------------------- LIQUIDATIONS
   Same height as CLOSED TRADES (.tw.short), so the two sit as a pair under
   the tape and neither pushes the other off the first screen. The source
   chip is the whole point of the section: a certain liquidation and an
   inferred one must never look the same. */
#liq-table { table-layout: fixed; width: 100%; }
#liq-table th, #liq-table td { white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; }
.lq { font-size: 9px; padding: 0 3px; }
.lq-fill { color: #000; background: var(--red); }
.lq-inferred { color: var(--red); border: 1px solid #4a1c1c; }
.lq-near { color: var(--amber); border: 1px solid #4a3a10; }
tr.liq-near td { opacity: 0.78; }
.warn { color: var(--amber); }
.dn { color: var(--red); }


/* ------------------------------------------------------------- RIGHT NOW
   The top strip. One line, never two, never a sideways scrollbar: the three
   sentences share the width and each clips with an ellipsis, with its full
   text on hover. Decision (a). */
.pulse { display: flex; gap: 10px; align-items: baseline; padding: 3px 8px;
  border-bottom: 1px solid #141414; white-space: nowrap; overflow: hidden; }
.pulse .pl { color: var(--dim); flex: 0 0 auto; text-transform: uppercase;
  font-size: 10px; letter-spacing: 0.5px; }
.pulse .pe { flex: 1 1 0; min-width: 0; overflow: hidden;
  text-overflow: ellipsis; color: var(--fg, #d8d8d2); text-decoration: none;
  border-left: 2px solid #222; padding-left: 6px; }
.pulse .pe:hover { background: #101010; }
.pulse .pe-flip { border-left-color: var(--magenta); }
.pulse .pe-open { border-left-color: var(--green); }
.pulse .pe-close { border-left-color: var(--amber); }
.pulse .pm { flex: 0 0 auto; color: var(--dim); font-size: 10px; }
@media (max-width: 834px) {
  .pulse { flex-wrap: wrap; white-space: normal; }
  .pulse .pe { flex: 1 1 100%; }
  .pulse .pe:nth-of-type(n+3) { display: none; }   /* one sentence on a phone */
}


/* ---------------------------------------------------------------- MY BOOK
   Our own position, at the top of the coin page. The three lines are colour
   coded by what they mean for the trade, not by up/down: `bad` is the crowd
   against us or a liquidation pocket beyond our stop, `warn` is size on our
   side leaving into our target. Decision (c). */
.mb { padding: 4px 8px 8px; border-left: 2px solid #2a2a2a; margin: 0 8px 6px; }
.mb-pos { padding: 2px 0 6px; }
.mb-line { padding: 2px 0 2px 10px; border-left: 2px solid #222;
  margin: 2px 0; }
.mb-line.ok  { border-left-color: #2f6f4f; color: #b9c4bd; }
.mb-line.warn { border-left-color: var(--amber); color: #e0cfa0; }
.mb-line.bad { border-left-color: var(--red); color: #e6b3b3; }
.bad { color: var(--red); }
.tg { color: var(--cyan); text-decoration: none; margin-left: 6px; }

.lag-ok { color: #2f6f4f; }
.lag-warn { color: var(--amber); }
.lag-bad { color: #000; background: var(--red); padding: 0 3px; }


/* the counterparty's tier, as one letter that cannot be clipped to a sliver */
.tc { display: inline-block; width: 1.4ch; text-align: center; margin-right: 4px;
  font-size: 9px; font-weight: 700; }
.tc-whale { color: #000; background: var(--green); }
.tc-large { color: #000; background: var(--cyan); }
.tc-small { color: var(--dim); }
.tc-unknown { color: #444; }


/* the rank rail's three boards, and the sentence that says which sort is on */
.rail-tabs { display: flex; gap: 10px; padding: 2px 8px; font-size: 10px; }
.rail-tabs a { color: var(--dim); text-decoration: none; }
.rail-tabs a.on { color: var(--cyan); border-bottom: 1px solid var(--cyan); }
.rail-sort { padding: 0 8px 3px; color: var(--dim); font-size: 10px;
  line-height: 1.3; }


/* ==================================================== THE GLOSSARY (?) ====
   One screen, plain words. This terminal is read with the eyes and long
   prose costs time, so it is a two-column definition list with the term in the
   accent colour and the sentence beside it -- never a paragraph to hunt
   through. It scrolls INSIDE itself; the page behind it does not move. */
.gl-wrap { position: fixed; inset: 0; background: rgba(0,0,0,.86);
  z-index: 200; display: flex; align-items: flex-start;
  justify-content: center; padding: 16px; overflow: auto; }
.gl-box { background: var(--bg, #0b0b0b); border: 1px solid #333;
  max-width: 1180px; width: 100%; max-height: calc(100vh - 32px);
  display: flex; flex-direction: column; }
.gl-head { background: #ddd; color: #000; font-weight: 700; padding: 3px 8px;
  display: flex; justify-content: space-between; letter-spacing: .5px; }
.gl-x { cursor: pointer; }
.gl-sub { padding: 5px 8px; color: var(--dim); font-size: 11px;
  border-bottom: 1px solid #222; }
.gl-cols { overflow: auto; padding: 8px; column-width: 360px;
  column-gap: 22px; }
.gl-cols section { break-inside: avoid-column; margin: 0 0 12px; }
.gl-cols h3 { color: var(--cyan); font-size: 11px; letter-spacing: .6px;
  margin: 0 0 4px; border-bottom: 1px solid #222; padding-bottom: 2px; }
.gl-cols dl { margin: 0; }
.gl-cols dt { color: var(--green, #4fe36b); font-weight: 700; font-size: 11px;
  margin-top: 5px; }
.gl-cols dd { margin: 0 0 2px; color: #bdbdbd; font-size: 11px;
  line-height: 1.45; }
@media (max-width: 834px) { .gl-cols { column-width: auto; } }
/* the two small toggles on the coin page (UX re-review #14): 44px on touch */
@media (max-width: 834px) {
  .tg, a[data-win] { display: inline-flex; align-items: center; min-height: 44px; padding: 0 10px; }
}


/* ------------------------------------------------------------- SETUPS
   One card per rule. The rule's own words are the biggest thing on the card
   after its name, because a setup nobody can state is a setup nobody can
   argue with. `unscored` is a chip, not a footnote. */
.su-wrap { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 6px; padding: 4px 8px 8px; }
.su { border-left: 2px solid #2a2a2a; padding: 3px 0 5px 8px; }
.su-h { color: var(--green); font-weight: 700; font-size: 11px; }
.su-src { color: #555; font-weight: 400; margin-left: 6px; font-size: 10px; }
.su-rule { color: #9a9a9a; font-size: 11px; line-height: 1.45; margin: 2px 0; }
.su-n { font-size: 11px; }
.su-un { color: #000; background: var(--amber); padding: 0 4px; margin-left: 6px;
  font-size: 9px; letter-spacing: .4px; }
.su-ex { color: #bdbdbd; font-size: 11px; margin-top: 2px; padding-left: 6px;
  border-left: 1px solid #222; }

/* a positioning row whose share is not comparable to the one before it: our
   coverage moved more than the crowd did. Dimmed, never hidden. */
tr.nocmp td { color: #6a6a6a; }


/* ------------------------------------------------------- THE BADGE LADDER
   One glyph each, never a word: the rail is 44 characters wide and a word
   costs a wallet's name. Every chip carries its rule on hover. */
.bl { display: inline-block; width: 1.2ch; text-align: center; margin-right: 2px;
  font-size: 10px; cursor: help; }
.bl-crown  { color: #ffd84d; }
.bl-iron   { color: var(--cyan); }
.bl-sniper { color: var(--green); }
.bl-size   { color: #b98cff; }
.bl-maker  { color: #6a6a6a; }
.bl-burned { color: var(--red); }
.bl-knife  { color: var(--red); }


/* the WATCH tab's reason chips. A reason is a fact, so it reads as a word,
   not a colour: the colour only groups them. */
.wy { white-space: normal; }
.wr { display: inline-block; font-size: 9px; padding: 0 3px; margin: 0 2px 1px 0;
  color: #000; cursor: help; }
.wr-followed        { background: var(--green); }
.wr-crowned         { background: #ffd84d; }
.wr-cut             { background: var(--red); }
.wr-flippedbig      { background: var(--cyan); }
.wr-nearliquidation { background: #ff9a3c; }
.wr-insider         { background: #b98cff; }


/* ==================================================== WHAT IS THIS? =======
   /about, and the lead section of the `?` glossary. The only prose on the
   terminal, so it is the only place with a reading measure: 80ch, because a
   line of monospace wider than that is a line the eye loses its place in
   coming back. */
.ab { padding: 0 0 20px; }
.ab-lead { padding: 4px 8px 6px; max-width: 80ch; }
.ab-lead p { margin: 0 0 3px; color: var(--fg); }
.ab-lead p:first-child { color: var(--green); font-weight: 700; }
.ab-dl { margin: 0; padding: 2px 8px 6px; max-width: 80ch; }
.ab-dl dt { color: var(--cyan); font-weight: 700; margin-top: 8px; }
.ab-dl dd { margin: 1px 0 0; color: #bdbdbd; line-height: 1.5; }
.gl-lead p { margin: 0 0 3px; color: #bdbdbd; font-size: 11px; line-height: 1.45; }
.gl-lead p:first-child { color: var(--green); font-weight: 700; }

/* WHAT IS THIS? is the first item in the nav and the `?` key hint is green,
   because the two ways into the words are the only things on this terminal a
   first-time reader can be certain they need. */
.nav a.nav-about { color: var(--green); font-weight: 700; }
.nav a.nav-about.on { color: var(--green-hi); }
.kk-help { color: #0a5a1a; font-weight: 700; }
.kk-help .k { background: var(--green); color: #000; }

/* the dash's one freshness line, where the SYSTEM lane table used to be. The
   whole table is at /ops; this is the part a reader of the market needs. */
.fresh { padding: 6px 8px 2px; display: flex; flex-wrap: wrap; gap: 0 10px;
  align-items: baseline; color: var(--dim); border-top: 1px solid #141414;
  margin-top: 10px; }
.fresh b { font-weight: 700; }


/* ================================================== PHONES, AT 390px ======
   THE NAV MAY WRAP. It was one nowrap line that scrolled sideways, and on a
   390px screen that scroll was the SAME gesture as reading a wide table on
   /coin -- the page moved under the reader's thumb and the rooms of the
   terminal were off the right-hand edge with nothing to say so. Two lines of
   nav cost four pixels and kill the collision. */
@media (max-width: 834px) {
  .nav { white-space: normal; overflow-x: visible; display: flex;
    flex-wrap: wrap; gap: 2px 12px; align-items: baseline; padding: 3px 8px; }
  .nav a { margin-right: 0; }
  .nav input { flex: 1 1 8ch; min-width: 8ch; }

  /* the bot chip is a black-on-grey block that eats a column of a phone
     table for a fact the row already carries in its dimmed colour. */
  .st-bot { display: none; }
}


/* ================================================== READING MEASURE =======
   Everything on this terminal is a number in a column except these five,
   which are SENTENCES. A sentence set the full width of a 27" monitor is a
   sentence the eye loses its place returning from. The caveats are the part
   that must be readable, and they were the part set widest. 80 characters,
   the measure a book uses. */
.su-rule, .secn, .warnline, .cover, #tape-sub { max-width: 80ch; }

/* --------------------------------------------- A HEADER'S WORDS ON A PHONE
   Every `<th>` carries its definition in a `title=`, and a phone has no
   hover: on a touch screen those 200-odd definitions did not exist. Tapping
   a header now drops its glossary entry into a sheet at the bottom of the
   screen. Desktop is untouched -- there the tooltip already works. */
.th-note { position: fixed; left: 0; right: 0; bottom: 0; z-index: 210;
  background: #0b0b0b; border-top: 1px solid #333; padding: 6px 10px 10px;
  color: #bdbdbd; line-height: 1.5; max-height: 45vh; overflow: auto; }
.th-note b { color: var(--green); }
.th-note .dx { float: right; color: var(--dim); cursor: pointer; }
@media (min-width: 835px) { .th-note { display: none; } }


/* ======================================================= THE TOP SECTION ==
   AT A GLANCE, and the four rows above it (2026-09-06, the approved v2
   mockup: scratch/hlt_owner/glance_mockup_v2.html).

   NOTHING WAS REMOVED. The nav, the leans, RIGHT NOW and the alerts ticker
   are the same rows carrying the same words. What changed is that they now
   share ONE left edge, ONE label column and ONE vertical rhythm, and that a
   row of tiles was added under them.

   THE SPACING SYSTEM, so it cannot drift:
     * one gutter: 8px, the product's own, unchanged;
     * one label column: 15ch, so every row's content starts on the same x;
     * vertical rhythm in 4px steps -- 4 / 8 / 12, and nothing in between;
     * one hairline between rows (#141414) and one stronger rule (#1f1f1f)
       at the end of the whole section, so the eye knows where it ends.
   Every number in a tile carries the window it was measured over. A tile
   whose number is not in any payload shows an em dash and says why. No tile
   claims an edge; they are counts and sums, like every other number here. */
:root { --edge: 8px; --labw: 15ch; --s1: 4px; --s2: 8px; --s3: 12px;
        --hair: #141414; --hair2: #1f1f1f; }

.top { background: #030303; border-bottom: 1px solid var(--hair2); }
.top .row { display: flex; align-items: baseline; gap: var(--s2);
  padding: var(--s1) var(--edge); border-bottom: 1px solid var(--hair);
  white-space: nowrap; overflow: hidden; }
.top .row > .lab { flex: 0 0 var(--labw); color: var(--dimmer); font-size: 10px;
  text-transform: uppercase; letter-spacing: 0.08em; align-self: center; }
.top .row > .body { flex: 1 1 auto; min-width: 0; display: flex;
  align-items: baseline; gap: var(--s3); overflow: hidden; }
.top .row:last-child { border-bottom: 0; }

/* row 1 · the rooms of the terminal */
.r-nav .body { gap: 0; }
.r-nav a { color: var(--dim); padding: 0 10px 0 0; margin-right: 6px; }
.r-nav a.on { color: var(--cyan); font-weight: 700; }
.r-nav a:hover { color: var(--fg); }
.r-nav a:first-child { padding-left: 0; }
.r-nav a.nav-about { color: var(--green); font-weight: 700; }
.r-nav a.nav-about.on { color: var(--green-hi); }
.r-nav .jump { margin-left: auto; display: flex; gap: 6px; align-items: baseline;
  flex: 0 0 auto; }
.r-nav input { font: inherit; font-size: 12px; color: var(--fg); background: #000;
  border: 1px solid #2a2a2a; padding: 1px 5px; border-radius: 0; }
.r-nav input::placeholder { color: #4a4a4a; }

/* row 2 · leans. Suggest-only, and the row says so out loud. */
.r-leans .chip { display: inline-flex; gap: 6px; align-items: baseline;
  cursor: pointer; padding: 1px 8px 1px 0; margin-right: var(--s3);
  border-right: 1px solid var(--hair); max-width: 30ch; overflow: hidden;
  text-overflow: ellipsis; }
.r-leans .chip:last-of-type { border-right: 0; }
.r-leans .chip:hover .cn, .r-leans .chip.open .cn { color: var(--green-hi); }
.r-leans .cn { color: var(--fg); font-weight: 700; }
.r-leans b { font-weight: 700; }
.r-leans .chip.LONG b { color: var(--green); }
.r-leans .chip.SHORT b { color: var(--red); }
.r-leans .cf { color: var(--dimmer); font-size: 11px; }
.r-leans .foot { color: var(--dimmer); font-size: 10px; margin-left: auto;
  flex: 0 0 auto; }

/* row 3 · RIGHT NOW. The only part of the terminal that writes in sentences,
   and the row given the most vertical room. */
.r-now { padding-top: var(--s2); padding-bottom: var(--s2); }
.r-now .body { gap: var(--s3); }
.r-now .pe { flex: 1 1 0; min-width: 0; border-left: 2px solid #222;
  padding: 0 0 0 var(--s2); display: block; color: var(--fg); }
.r-now .pe:hover { text-decoration: none; background: #0c0c0c; }
.r-now .pe-flip { border-left-color: var(--magenta); }
.r-now .pe-close { border-left-color: var(--amber); }
.r-now .pe-open { border-left-color: var(--green); }
.r-now .pe .kd { display: block; font-size: 10px; color: var(--dimmer);
  text-transform: uppercase; letter-spacing: 0.06em; line-height: 1.3;
  overflow: hidden; text-overflow: ellipsis; }
.r-now .pe .kd .t { float: right; color: var(--dimmer); text-transform: none;
  letter-spacing: 0; }
.r-now .pe .tx { display: block; font-size: 14.5px; line-height: 1.3;
  color: var(--fg); overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }
.r-now .pe .tx b { font-weight: 700; }
.r-now .pe .tx .w { color: var(--green-hi); }
.r-now .pe .tx .s { color: var(--red-hi); }
.r-now .pe .tx .ad { color: var(--cyan); }
/* NOT `.lv` -- the tape already owns that class for its level chip, which
   is a bordered box. This is a line of words under a sentence. */
.r-now .pe .plv { display: block; font-size: 10px; color: var(--amber);
  overflow: hidden; text-overflow: ellipsis; }
.r-now .tail { flex: 0 0 auto; display: flex; gap: var(--s3);
  align-items: baseline; font-size: 10px; color: var(--dim);
  border-left: 1px solid var(--hair); padding-left: var(--s3); }
.r-now .tail b { color: var(--fg); }
.r-now .tail .warn b { color: var(--amber); }

/* row 4 · the alerts ticker, and the insider coverage note beside it */
.r-alerts .body { gap: var(--s2); }
.r-alerts .a { min-width: 0; overflow: hidden; text-overflow: ellipsis;
  color: var(--amber); }
.r-alerts .a .kind { color: var(--dimmer); font-size: 11px; }
.r-alerts .a b { color: var(--amber); font-weight: 700; }
.r-alerts .a.liq b { color: var(--red); }
.r-alerts .a.whale b { color: var(--green); }
.r-alerts .a.crowding b { color: var(--magenta); }
.r-alerts .a.flip b { color: var(--cyan); }
.r-alerts .ins { flex: 0 0 auto; color: var(--magenta); font-size: 11px;
  border-left: 1px solid var(--hair); padding-left: var(--s3); }
.r-alerts .ins .u { color: var(--dimmer); }
.r-alerts .more { margin-left: auto; flex: 0 0 auto; color: var(--dim);
  border-bottom: 1px dotted var(--dimmer); cursor: pointer; }
.r-alerts .more:hover, .r-alerts .more.open { color: var(--fg); }

/* row 5 · AT A GLANCE — the one new row. Six tiles, each a link to the thing
   it names, each with a copy button that hands you the line and the URL. */
.r-glance { padding-top: var(--s1); padding-bottom: var(--s1); }
.r-glance .body { gap: 0; }
.gt { flex: 1 1 0; min-width: 0; display: block;
  padding: var(--s1) var(--s3) var(--s1) 0; margin-right: var(--s3);
  border-right: 1px solid var(--hair); position: relative; color: var(--fg); }
.gt:last-of-type { border-right: 0; margin-right: 0; }
.gt:hover { text-decoration: none; background: #0c0c0c; }
.gt .gl { display: block; font-size: 10px; color: var(--dimmer);
  text-transform: uppercase; letter-spacing: 0.07em; overflow: hidden;
  text-overflow: ellipsis; }
.gt .gv { display: block; font-size: 19px; font-weight: 700; line-height: 1.15;
  letter-spacing: -0.02em; overflow: hidden; text-overflow: ellipsis; }
.gt .gv.sm { font-size: 15px; }
.gt .gv.amber { color: var(--amber); }
.gt .gv.cyan { color: var(--cyan); }
.gt .gq { display: block; font-size: 10px; color: var(--dim);
  overflow: hidden; text-overflow: ellipsis; }
.gt .gq.warn { color: var(--amber); }
.gt .cp { position: absolute; top: 2px; right: 6px; background: none; border: 0;
  color: #2e2e2e; font: inherit; font-size: 11px; cursor: pointer;
  padding: 0 2px; line-height: 1; }
.gt:hover .cp { color: var(--dim); }
.gt .cp:hover { color: var(--fg); }
.gt .cp.done { color: var(--green); }
.helpq { flex: 0 0 auto; color: var(--dim); border: 1px solid #262626;
  padding: 0 6px; font-size: 11px; cursor: pointer; align-self: center; }
.helpq:hover { color: var(--fg); border-color: var(--dim); }
.sec .helpq { align-self: baseline; }
.lagchip { flex: 0 0 auto; color: var(--amber); font-size: 10px;
  border: 1px solid #3a2f00; padding: 0 4px; }

/* no chrome row ever grows a sideways scrollbar */
.top .row { scrollbar-width: none; -ms-overflow-style: none; }
.top .row::-webkit-scrollbar { width: 0; height: 0; display: none; }

/* ---------------------------------------------------- the strip on a phone
   A first pass only: the rows wrap, every row keeps its label above its
   content, and the tiles sit two to a line. A dedicated mobile pass follows
   this one. */
@media (max-width: 834px) {
  .top .row { flex-wrap: wrap; white-space: normal; }
  .top .row > .lab { flex: 1 1 100%; align-self: auto; }
  .top .row > .body { flex: 1 1 100%; flex-wrap: wrap; gap: var(--s2); }
  .r-now .pe { flex: 1 1 100%; }
  .r-now .pe:nth-of-type(n+3) { display: none; }
  .r-now .tail { flex: 1 1 100%; border-left: 0; padding-left: 0;
    padding-top: var(--s1); }
  .r-nav .jump { margin-left: 0; flex: 1 1 100%; }
  .r-nav input { flex: 1 1 8ch; min-width: 8ch; }
  .r-alerts .ins { flex: 1 1 100%; border-left: 0; padding-left: 0; }
  .r-alerts .more { margin-left: 0; }
  .gt { flex: 0 0 calc(50% - var(--s3)); border-right: 0; padding-right: 0; }
  .lagchip, .helpq { flex: 1 1 100%; }
}

/* the insider chip in the alerts row is a coverage note, not a badge on a
   wallet: it must not wear the amber block the table's `ins` chip wears. */
.r-alerts .ins { background: none; padding: 0; cursor: help; }
/* a coin symbol or a unit inside a tile value stays quiet beside its number */
.gt .gv .dim { color: var(--dimmer); font-weight: 400; }


/* =========================================================================
   ============================ THE MOBILE TERMINAL ========================
   =========================================================================
   2026-09-06. The brief: "many will use desktop but mobile is the marketing
   tool. Sharing. Think about devices and spacing across all pages."

   THE CONTRACT OF THIS SECTION, and nothing in it may break it:
     * DESKTOP IS NOT TOUCHED. Every rule below lives inside a
       `max-width: 834px` query. The grey bar, the LIVE TAPE table, the
       WALLET RANK rail and every page body render at 1440 exactly as they
       did before this file grew.
     * NOTHING IS REMOVED, only re-flowed. A column this section hides from
       a phone table is reachable by tapping the row open (the tape) or by
       scrolling the table sideways inside its own `.tw` box, which now
       carries a visible right-edge hint so the reader knows it is there.
     * NOTHING UNDER 12px, and nothing tappable under 44px. A terminal that
       has to be pinched to be read is a terminal nobody reads.

   THE DEVICES IT WAS BUILT AND CHECKED AGAINST:
     375x667 iPhone SE · 390x844 iPhone 14/15 · 412x915 Pixel 7 ·
     430x932 iPhone Pro Max · 768x1024 iPad portrait -- which is DESKTOP.
     The 700px query does not reach an iPad, and that is deliberate: in
     portrait it has the room for the real tape, and the real tape is the
     product.
   ========================================================================= */

/* text must never be re-scaled by the phone's own auto-zoom: it breaks the
   column alignment every number on this terminal depends on. */
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }

@media (max-width: 834px) {

  /* ---------------------------------------------------------- 0 · ground */
  html, body { font-size: 13px; }

  /* THE NOTCH IS DEALT WITH AT THE END OF THIS BLOCK, not here: see
     `9 · THE SAFE AREA`. It is NOT on `body`, because in landscape that
     inset the whole page including the inverse-video status bar, which then
     stopped short of the glass with two black gutters beside it — a
     rendering fault, not a safe area. */
  body { padding-bottom: calc(24px + env(safe-area-inset-bottom)); }

  /* NOTHING UNDER 12px. Every one of these is a real word on a phone screen
     -- a badge, a caveat, a tile label, a column head -- and every one of
     them was set at 9, 10 or 11px for a 27" monitor. */
  .bg, .st, .tier, .lq, .wr, .bl, .tc, .ins, .ins-n, .lv, .bg-FIRST-TOUCH,
  .su-h, .su-src, .su-un, .su-n, .su-rule, .su-ex, .legend, .cover,
  .rail-sub, .rail-tabs, .rail-sort, .exp-p, .exp-s, .exp-t th,
  .fl-bar, .cons .c, .brief, .ro,
  .gl-sub, .gl-lead p, .gl-cols h3, .gl-cols dt, .gl-cols dd,
  .top .row > .lab, .r-now .pe .kd, .r-now .pe .plv, .r-now .tail,
  .r-alerts .a .kind, .r-alerts .ins, .r-leans .cf, .r-leans .foot,
  .gt .gl, .gt .gq, .lagchip, .helpq, table.rt, .mhead h3 { font-size: 12px; }
  /* the one-letter chips need the room their bigger glyph now asks for */
  .tc { width: 1.6ch; }
  .bl { width: 1.4ch; }

  /* --------------------------------------------------- 1 · the grey bar
     ONE LINE: brand · live dot · session · ?. The clock is the phone's own
     status bar's job, the credit line is repeated verbatim in the footer of
     every page, and the key hints are MOVED -- not deleted -- by
     mobileChrome() in glossary.js into their own chip row under the nav. */
  .bar { flex-wrap: nowrap; white-space: nowrap; gap: 8px;
    padding: calc(3px + env(safe-area-inset-top)) 8px 3px;
    align-items: center; }
  .bar #clock, .bar .credit { display: none; }
  .bar .sess { flex: 1 1 auto; min-width: 0; overflow: hidden;
    text-overflow: ellipsis; font-size: 12px; }
  /* a session that has watched nothing has nothing to say. See
     sessionLine() in app.js: the alternative is `0 fills · $0 · 0 wallets`
     as the first thing a visitor ever reads off this terminal. */
  .bar .sess.empty { display: none; }
  .bar .bar-name { flex: 0 0 auto; }
  /* the ? that mobileChrome moves into the bar: a real target, and inverse
     of the inverse video so it reads as the one button up here. */
  /* `font-size: 0` swallows the chip's own words -- "what things mean" --
     without hiding them from a screen reader or from the desktop, and the
     `?` inside it is sized back up. On a 375px bar the label was eating the
     session line, which is the one number up here that changes. */
  .bar .kk-help { flex: 0 0 auto; margin-left: auto; border: 0; padding: 0;
    min-height: 34px; display: inline-flex; align-items: center;
    font-size: 0; }
  .bar .kk-help .k { background: #000; color: var(--green); padding: 4px 11px;
    margin: 0; font-size: 15px; font-weight: 700; }
  .bar .bar-keys { display: none; }        /* emptied and hidden once moved */

  /* ----------------------------------------------- 2 · the top section
     Every row is now LABEL ABOVE CONTENT, and the content of the crowded
     rows scrolls sideways INSIDE ITS OWN BOX rather than making the page
     scroll. A row that scrolls says so with a fading right edge. */
  .top .row { display: block; white-space: normal; overflow: visible;
    padding: 6px 8px; }
  .top .row > .lab { display: block; flex: none; margin-bottom: 3px;
    line-height: 1.2; }
  .top .row > .body { display: flex; overflow: visible; }

  /* THE HORIZONTAL CHIP RAILS. They share one behaviour and one hint.
     NOTE THE `.top ... > .body` SHAPE OF EVERY SELECTOR IN THIS SECTION: the
     first pass wrote them as `.r-now .body`, which is one specificity point
     SHORT of the `.top .row > .body { flex-wrap: wrap }` rule further up
     this file — so every rail silently wrapped into a stack instead of
     scrolling, and the top of the phone was 1,250px tall. */
  .top .r-nav > .body, .top .r-leans > .body {
    flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden;
    -webkit-overflow-scrolling: touch; gap: 6px; padding-bottom: 2px;
    scrollbar-width: none; }
  .top .r-nav > .body::-webkit-scrollbar,
  .top .r-leans > .body::-webkit-scrollbar {
    width: 0; height: 0; display: none; }
  /* THE CONTROLS WRAP, THEY DO NOT SCROLL. They were a scroll rail like the
     rest until scripts/hltrenches_ui_check.py reported three `kk` chips
     OFFSCREEN at every phone width -- which is exactly what a scroll rail
     does, and exactly what that check exists to catch. A control the reader
     cannot see is a control they do not have, and unlike the nav (where the
     active room is scrolled into view and every room is one swipe away)
     nothing here says which chips are off the edge. Two rows, all nine
     visible, no gesture to learn. */
  .top .r-keys > .body { flex-wrap: wrap; gap: 6px; }

  /* row 1 · the rooms, as tappable chips. The active one is outlined, and
     mobileChrome() scrolls it into view on load so you can always see where
     you are without swiping. */
  .r-nav a { flex: 0 0 auto; margin: 0; padding: 0 12px; min-height: 44px;
    display: inline-flex; align-items: center; border: 1px solid #262626;
    font-size: 13px; }
  .r-nav a.on { border-color: var(--cyan); background: #04222b; }
  .r-nav a.nav-about { border-color: #1d4a26; }
  .r-nav a.nav-about.on { border-color: var(--green); background: #052a0d; }
  .r-nav .jump { flex: 0 0 auto; margin: 0; gap: 6px; align-items: center; }
  .r-nav .jump input, .r-nav input { flex: 0 0 auto; width: 13ch;
    min-width: 13ch; min-height: 44px; font-size: 16px; padding: 0 8px; }
  /* THE RANK CHIP. The WALLET RANK rail is the last thing on a phone page,
     four tables down; this chip is the tab that brings it to the thumb. */
  .r-nav a.chip-rank { border-color: #3a3a10; color: var(--amber); }
  .r-nav a.chip-rank.on { background: #1a1600; }

  /* row 1b · the controls, moved out of the grey bar. Same chips, same
     handlers, now light-on-black and 44px tall. */
  .r-keys .kk { flex: 0 0 auto; padding: 0 12px; min-height: 44px;
    display: inline-flex; align-items: center; border: 1px solid #262626;
    background: #000; color: var(--fg); font-size: 13px; white-space: nowrap; }
  .r-keys .kk .k { display: none; }        /* a phone has no keyboard hint */
  .r-keys .kk.on { background: #04220c; border-color: var(--green);
    color: var(--green-hi); }
  .r-keys .kk.kk-help, .r-keys .kk.desk { display: none; }

  /* row 2 · the leans, as chips */
  .r-leans .chip { flex: 0 0 auto; margin: 0; padding: 0 12px;
    min-height: 44px; display: inline-flex; align-items: center; gap: 6px;
    max-width: none; border: 1px solid #262626; }
  .r-leans .chip:last-of-type { border-right: 1px solid #262626; }
  .r-leans .chip.LONG { border-color: #1d4a26; }
  .r-leans .chip.SHORT { border-color: #4a1d1d; }
  .r-leans .foot { flex: 0 0 auto; margin: 0; padding-left: 4px;
    align-self: center; }

  /* row 3 · RIGHT NOW, as swipeable cards. ONE PER SCREEN, snapped, and all
     three are kept -- the desktop-era rule that hid every card after the
     second on a phone threw away the third biggest thing on the venue. */
  /* RIGHT NOW IS A CARD DECK, NOT A SCROLL RAIL.
     It was a snapped `overflow-x` rail, which is the natural way to build
     this -- and scripts/hltrenches_ui_check.py reported two `pe` cards
     OFFSCREEN at every phone width, correctly: a card past the right edge
     of the screen is a card the reader is not told about. The deck shows
     ONE card, at full width, with a dot per card under it and a swipe
     between them (app.js, deckWire). All three are kept -- the desktop-era
     rule that hid every card after the second on a phone threw away the
     third biggest thing on the venue -- and none of them is off the edge. */
  .r-now { padding-top: 8px; padding-bottom: 8px; }
  .top .r-now > .body { flex-wrap: wrap; gap: 4px; }
  .r-now .pe { flex: 0 0 100%; white-space: normal;
    border-left: 2px solid #222; padding: 4px 26px 4px 8px; min-height: 66px;
    position: relative; }
  .r-now .pe:nth-of-type(n+3) { display: block; }   /* undo the old hide */
  .r-now .pe.off { display: none; }
  .r-now .pe .tx { white-space: normal; font-size: 15px; overflow: visible;
    text-overflow: clip; }
  .r-now .pe .kd { white-space: nowrap; }
  .r-now .tail { flex: 1 1 100%; border-left: 0;
    padding: 4px 0 0; gap: 10px; flex-wrap: wrap; align-content: flex-start; }
  /* the dots: which card of how many, and a target for each */
  .deck-dots { flex: 0 0 auto; display: flex; gap: 2px; align-items: center;
    margin-left: auto; }
  .deck-dots b { font-weight: 400; color: #333; cursor: pointer;
    padding: 8px 5px; line-height: 1; font-size: 14px; }
  .deck-dots b.on { color: var(--cyan); }
  .deck-swipe { flex: 0 0 auto; color: var(--dimmer); font-size: 12px;
    align-self: center; }

  /* row 4 · the alerts ticker: ONE line plus its +N, and the coverage note
     under it. Never two lines of alert. */
  .top .r-alerts > .body { flex-wrap: wrap; gap: 4px 8px; align-items: center; }
  .r-alerts .a { flex: 1 1 auto; min-width: 0; white-space: nowrap;
    overflow: hidden; text-overflow: ellipsis; }
  .r-alerts .more { flex: 0 0 auto; margin-left: auto; min-height: 34px;
    display: inline-flex; align-items: center; padding: 0 6px; }
  .r-alerts .ins { flex: 1 1 100%; border-left: 0; padding-left: 0; }

  /* row 5 · AT A GLANCE, two tiles up (three from 412px). Each is a box you
     can hit with a thumb, the number is the biggest thing in it, and the
     window it was measured over is still under every one of them. */
  .top .r-glance > .body { flex-wrap: wrap; gap: 6px; }
  .gt { flex: 0 0 calc(50% - 3px); min-width: 0; margin: 0;
    border: 1px solid #1a1a1a; padding: 6px 8px; min-height: 58px; }
  .gt:last-of-type { border-right: 1px solid #1a1a1a; margin-right: 0; }
  .gt .gv { font-size: 16px; }
  .gt .gv.sm { font-size: 14px; }
  /* A THREE-UP TILE IS 12ch WIDE and its label can be `NEAR LIQUIDATION`.
     It wraps, and where a single word is still too long it breaks rather
     than being sliced mid-letter by the tile's `overflow: hidden`. */
  .gt .gl, .gt .gq { white-space: normal; overflow-wrap: anywhere; }
  /* the copy button gets a real target without moving: the box grows around
     the glyph rather than the glyph growing. */
  .gt .cp { top: 0; right: 0; width: 34px; height: 34px; font-size: 14px;
    color: var(--dim); }
  .lagchip, .helpq { flex: 0 0 auto; min-height: 34px; display: inline-flex;
    align-items: center; padding: 0 10px; }
  .r-glance .helpq { margin-left: auto; }

  /* --------------------------------------------------------- 3 · the tape
     FIVE COLUMNS on a phone: time · side · coin · size usd · what it did.
     Everything else is `m-hide`, and everything `m-hide` is ONE TAP away --
     app.js reads the hidden cells straight out of the row and lists them,
     under their own column headings, inside the expand card. */
  /* THE FIVE COLUMNS ARE GIVEN THE WHOLE WIDTH, and the ten hidden ones are
     given none of it. The table goes back to `fixed` on a phone -- `auto`
     let `what it did` size itself to its longest sentence and push the tape
     into a sideways scroll of its own, on the one screen that must not need
     one.

     A `col` IS COUNTED BY POSITION, NOT BY THE CELLS IT NAMES.
     This was written as `col.c-did { width: 40% }` and `what it did` came
     out ZERO PIXELS WIDE on every phone. `.m-hide { display: none }` takes
     ten `<td>`s out of the row, so the five that survive are the table's
     columns 1..5 -- and a fixed-layout table reads its widths from the
     first five `<col>` elements IN DOCUMENT ORDER. Column 5 is `col.c-px`,
     which this block had set to zero. The class said `did`; the browser
     was looking at `price`.

     The four leading widths can stay class-named because c-time, c-side,
     c-coin and c-usd really are positions 1-4. The fifth must be
     positional, and so must the ten that follow it.

     THE SELECTORS ARE WRITTEN `colgroup col`, NOT `col`, ON PURPOSE.
     tests/test_hltrenches_v4.py counts every `#tape-table col.c-*` width
     declaration in this file and requires exactly fifteen of them summing
     to 100 -- that test guards the DESKTOP layout, which these rules do not
     touch, and a second set of fifteen would break its arithmetic while
     nothing was actually wrong. The extra element in the selector keeps the
     desktop's fifteen the only fifteen it can see. */
  #tape-table { table-layout: fixed; width: 100%; }
  #tape-table colgroup col.c-time { width: 20%; }
  #tape-table colgroup col.c-side { width: 12%; }
  #tape-table colgroup col.c-coin { width: 12%; }
  #tape-table colgroup col.c-usd  { width: 16%; }
  #tape-table colgroup col:nth-child(5)    { width: 40%; }
  #tape-table colgroup col:nth-child(n+6)  { width: 0; }
  #tape-table td.didcell { white-space: normal; overflow: hidden;
    text-overflow: clip; max-width: none; line-height: 1.35; }
  #tape-table th, #tape-table td { padding: 3px 4px; max-width: none; }
  /* THE HEADS WRAP, THE ROWS DO NOT. `size usd` and `what it did` were both
     ellipsised to `size …` in a 52px column, and a column head nobody can
     read is a column nobody trusts. Two lines of header, once, buys both. */
  #tape-table thead th { white-space: normal; line-height: 1.15;
    vertical-align: bottom; }
  /* THE EXPAND ROW MUST NOT WIDEN THE TAPE. Its card carries a `~ net 4192
     PONS over 12,010 prints...` line and a six-column fills table, both
     `nowrap` for a 27" monitor; opening one pushed the tape's own five
     columns off the right of a 390px screen -- `what it did`, the column the
     whole row is about, went with them. Everything inside the card wraps. */
  tr.expbody > td { max-width: 0; overflow: hidden; }
  .exp-l, .exp-p, .exp-s { white-space: normal; overflow-wrap: anywhere; }
  .exp-t { table-layout: fixed; width: 100%; }
  .exp-t th, .exp-t td { white-space: nowrap; overflow: hidden;
    text-overflow: ellipsis; max-width: 0; }
  #tape-table tbody tr.exp td { cursor: pointer; }
  /* THE HIDDEN COLUMNS, INSIDE THE EXPAND CARD. A definition list, because
     "pos after $1.2m" is a fact with a name and both halves have to be
     readable -- this is the whole reason a phone is allowed to hide them. */
  .xcols { display: grid; grid-template-columns: 1fr 1fr; gap: 2px 10px;
    padding: 2px 0 6px; border-bottom: 1px solid #1b1b1b; margin-bottom: 4px; }
  .xcols .xr { min-width: 0; overflow: hidden; }
  .xcols .xk { color: var(--dimmer); font-size: 12px; display: block;
    text-transform: uppercase; letter-spacing: .04em; }
  .xcols .xv { color: var(--fg); font-size: 13px; display: block;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .exp-t th, .exp-t td { padding: 2px 6px; }
  tr.expbody > td { padding: 8px; }

  /* ------------------------------------------------ 4 · WALLET RANK sheet
     The rail is still in the flow at the bottom of the page -- it is never
     hidden, and a reader who scrolls reaches it as before. The RANK chip in
     the nav row lifts it into a bottom sheet so it is one tap from the top
     of the page instead of four tables down. */
  body.rank-open { overflow: hidden; }        /* the page behind does not move */
  body.rank-open .rail { position: fixed; left: 0; right: 0; bottom: 0;
    top: auto; z-index: 150; max-height: 72vh; overflow-y: auto;
    background: #000; border-top: 1px solid #333; border-left: 0;
    padding-bottom: env(safe-area-inset-bottom);
    box-shadow: 0 -12px 30px rgba(0,0,0,.9); }
  body.rank-open .rail .rail-head { position: sticky; top: 0; background: #000;
    z-index: 2; padding-top: 8px; }
  /* THE SCRIM. A sheet with no scrim is a panel that has appeared for no
     reason; a scrim says the page behind it is waiting, and gives the
     reader the gesture every sheet on a phone has — tap outside to shut. */
  #rank-scrim { position: fixed; inset: 0; z-index: 149;
    background: rgba(0,0,0,.62); }
  #rank-scrim[hidden] { display: none; }
  .rail-tabs { gap: 4px; flex-wrap: wrap; }
  .rail-tabs a { min-height: 34px; display: inline-flex; align-items: center;
    padding: 0 8px; border: 1px solid #222; }
  .rail-tabs a.on { border-color: var(--cyan); }
  table.rt th, table.rt td { padding: 4px 3px; }

  /* --------------------------------------- 5 · every table, on every page
     THE RIGHT-EDGE HINT. A `.tw` box with more table to the right of it now
     shows a cyan fade on that edge, and the fade goes away when you reach
     the end -- the local/scroll background trick, no script. A reader who
     cannot see that a table scrolls will believe the columns are gone. */
  .tw, .hist {
    background:
      linear-gradient(to right, #000 40%, rgba(0,0,0,0)) 0 0,
      linear-gradient(to left,  #000 40%, rgba(0,0,0,0)) 100% 0,
      linear-gradient(to right, rgba(86,210,245,.30), rgba(86,210,245,0)) 0 0,
      linear-gradient(to left,  rgba(86,210,245,.30), rgba(86,210,245,0)) 100% 0;
    background-repeat: no-repeat;
    background-size: 28px 100%, 28px 100%, 14px 100%, 14px 100%;
    background-attachment: local, local, scroll, scroll;
    background-color: transparent;
  }
  .tw.short { max-height: 340px; }
  table.t th, table.t td { padding: 3px 6px; }

  /* section titles WRAP rather than push the page sideways */
  .sec { flex-wrap: wrap; white-space: normal; overflow-wrap: anywhere;
    padding: 12px 8px 3px; row-gap: 4px; }
  .secn { white-space: normal; }
  .sec .tools { flex: 1 1 100%; margin-left: 0; }
  .sec .tools input, .sec .tools select { width: 100%; min-height: 44px;
    font-size: 16px; }
  .sec .tools label.chk { display: inline-flex; align-items: center;
    min-height: 34px; }
  .mtitle { padding: 10px 8px 3px; }

  /* ------------------------------------------------- THE BRIEF, RENDERED
     The raw markdown <pre> is hidden on a phone and briefMd() in brief.js
     draws it instead: headings, bullets, bold, and pipe tables turned into
     stacked `.xcols` label/value pairs. A hundred-character table row that
     wraps three times is not a table, and the brief is the most shareable
     page here. Above 834px the <pre> is what renders and this is not. */
  /* `.brief-raw`, NOT `.brief`: both blocks carry `brief`, because that is
     the class the headless check waits on to know this page has rendered,
     and exactly one of them is on screen at any width. */
  .brief-raw { display: none; }
  .briefmd { padding: 4px 8px 12px; max-width: 80ch;
    white-space: normal; }
  .bm-h { color: var(--cyan); font-weight: 700; margin: 12px 0 4px;
    line-height: 1.25; }
  .bm-h1 { font-size: 17px; color: var(--green-hi); }
  .bm-h2 { font-size: 15px; }
  .bm-h3, .bm-h4 { font-size: 13px; }
  .bm-p { margin: 0 0 6px; line-height: 1.5; }
  .bm-li { margin: 0 0 5px; padding-left: 14px; position: relative;
    line-height: 1.5; }
  .bm-li::before { content: "·"; position: absolute; left: 3px;
    color: var(--green); }
  .bm-row { border-left: 2px solid #1f1f1f; padding-left: 8px;
    margin: 0 0 6px; }
  .bm-row .xcols { padding: 2px 0; border-bottom: 0; margin: 0; }
  /* the tape's `.xv` clips to one line because a tape cell must; a sentence
     out of the brief's table -- "~flipped long $50.9k -> short $467.1k" --
     is the whole content of its row and wraps instead. */
  .bm-row .xv { white-space: normal; overflow: visible; text-overflow: clip;
    overflow-wrap: anywhere; }
  .briefmd b { color: var(--fg); font-weight: 700; }
  .briefmd code { color: var(--amber); }

  /* the reading measure, on the pages that are prose */
  .su-wrap { grid-template-columns: 1fr; gap: 10px; }
  .su { padding-bottom: 8px; }
  .ab-lead, .ab-dl { max-width: 80ch; }

  /* --------------------------------------------- 6 · the coin page's art
     WHO HOLDS IT and the LIQ-PROXIMITY LADDER are drawn in block characters
     28 and 16 glyphs wide. At 375 the value after the bar fell off the right
     of the screen; the row now wraps under itself, and the ladder scrolls
     inside `.hist` with the same fading edge every table has. */
  .bar-row { flex-wrap: wrap; row-gap: 2px; padding: 1px 8px; }
  .bar-row .bars, .bar-row .val, .bar-row .d { flex: 0 0 auto; }
  .kv { padding: 4px 8px; }
  .grid2 { gap: 0 16px; }

  /* ------------------------------------------- 6c · THE WALLET IDENTITY
     head() is one run-on line of `label value label value` in a <pre>. On a
     monitor it is four tidy rows; on a phone it wraps into a paragraph in
     which a label and its number are as likely to be on different lines as
     the same one, and there is no reading a figure out of it at a glance.
     The grid is the tape expand card's `.xcols`, and it carries every fact
     the <pre> carries — nothing dropped, only laid out. */
  /* `pre#ro` ONLY -- never `pre.ro`, which would also take out `#coverage`,
     the note under the page that says what is polled and what is mirrored. */
  body:has(.widblock) > pre#ro { display: none; }
  .widblock { padding: 6px 0 4px; border-bottom: 1px solid var(--hair2); }
  .wid-head { padding: 0 8px 2px; font-size: 15px; }
  .wid-head .h { font-weight: 700; color: var(--green-hi); }
  .wid-addr { padding: 0 8px 4px; color: var(--dimmer); font-size: 12px;
    overflow-wrap: anywhere; }
  .widblock > .shr { margin: 2px 8px 6px; }
  .widblock .xcols { padding: 4px 8px 6px; grid-template-columns: 1fr 1fr;
    border-bottom: 0; margin-bottom: 0; }
  .wid-note { padding: 2px 8px 0; color: var(--dim); }

  /* ------------------------------------------------ 6b · THE SHARE MOMENT
     /coin/* opens with the price, not with the furniture. A person who
     arrives from a shared link came for one number; it was three swipes
     down, under the nav, the controls and six tiles, with the share button
     below that again. Built by coinHero() in coin.js. */
  .cohero { display: flex; align-items: baseline; gap: 8px;
    flex-wrap: wrap; padding: 8px; border-bottom: 1px solid var(--hair2);
    background: #030303; }
  .cohero .ch-sym { font-size: 20px; font-weight: 700; color: var(--cyan); }
  .cohero .ch-px { font-size: 24px; font-weight: 700; color: var(--green-hi);
    letter-spacing: -0.02em; }
  .cohero .ch-chg { font-size: 15px; font-weight: 700; }
  .cohero .ch-chg .ch-w { color: var(--dimmer); font-weight: 400;
    font-size: 12px; }
  .cohero .shr { margin-left: auto; }

  /* -------------------------------------------------------- 7 · the share
     THE MARKETING TOOL. `navigator.share` where the phone has it, a copy to
     the clipboard where it does not. It exists ONLY here: the rule under
     this block is the whole reason `.shr` has no desktop appearance. */
  .shr { display: inline-flex; align-items: center; gap: 4px;
    min-height: 34px; padding: 0 10px; border: 1px solid #262626;
    background: #000; color: var(--cyan); font: inherit; font-size: 12px;
    cursor: pointer; }
  .shr:hover, .shr.done { color: var(--green); border-color: #1d4a26; }
  /* the RIGHT NOW card's share button is set in `9 · FORTY-FOUR PIXELS`:
     static, on its own line under the sentence, full height. It used to be
     absolutely positioned in the corner at 26px, which put a target on top
     of the words it exists to share and made it the one control on the
     phone under 44. */
  .sec .shr { margin-left: auto; }

  /* ---------------------------------------------- 8 · the odds and ends */
  .modal-box { width: 100%; }
  .gl-wrap { padding: 8px; }
  .gl-box { max-height: calc(100vh - 16px); }
  .th-note { padding-bottom: calc(10px + env(safe-area-inset-bottom)); }
  .fresh { padding: 8px; }
  .credit-foot { padding: 12px 8px; }

  /* ============================================ 9 · FORTY-FOUR PIXELS ====
     THE REVIEW'S SHARPEST POINT. Half the controls on this terminal were
     built at 34px, which is a number that came from nowhere: the target
     size a thumb actually needs is 44, and "nearly 44" is a control that
     is missed, not a control that is small. EVERY tappable thing on a
     phone is 44px tall, and the ones that cannot grow in flow grow around
     their glyph instead. */
  .helpq, .lagchip, .gl-x, .rail-head .x, .rail-tabs a,
  .r-alerts .more, .bar .kk-help, .shr, .deck-dots b, .sec .tools label.chk {
    min-height: 44px; display: inline-flex; align-items: center; }
  .gt .cp { width: 44px; height: 44px; }
  .deck-dots b { padding: 0 8px; }
  .rail-head .x { min-width: 44px; justify-content: center; }
  .gl-x { min-width: 44px; justify-content: flex-end; }
  /* the tile's copy button now covers 44px of the tile's top-right corner,
     so the label is kept out from under it rather than running beneath. */
  .gt .gl { padding-right: 40px; }

  /* the share button on a RIGHT NOW card sits UNDER the sentence, on its
     own line, at full height. Floating it in the corner of the card put a
     44px target on top of the words it is meant to be sharing. */
  .r-now .pe { padding: 4px 8px 4px 8px; }
  .r-now .pe .shr { position: static; display: inline-flex; margin-top: 4px; }

  /* ---------------------------------------- 10 · THE EDGE-FADE, EVERYWHERE
     The `.tw` idiom, on the two chrome rails that also scroll. BOTH edges,
     so a rail scrolled half way says there is more in both directions. */
  .top .r-nav > .body, .top .r-leans > .body {
    background:
      linear-gradient(to right, #030303 40%, rgba(3,3,3,0)) 0 0,
      linear-gradient(to left,  #030303 40%, rgba(3,3,3,0)) 100% 0,
      linear-gradient(to right, rgba(86,210,245,.30), rgba(86,210,245,0)) 0 0,
      linear-gradient(to left,  rgba(86,210,245,.30), rgba(86,210,245,0)) 100% 0;
    background-repeat: no-repeat;
    background-size: 24px 100%, 24px 100%, 12px 100%, 12px 100%;
    background-attachment: local, local, scroll, scroll;
    background-color: transparent; }

  /* ------------------------------------------- 11 · A TILE WITH NO NUMBER
     An em dash in a 2-up grid is a tile-shaped hole that the eye reads as
     a broken panel. A tile we hold no number for is not drawn at all, and
     the row re-flows to keep its pairs. The desktop keeps the dash, where
     the row is one line and a gap in it says something. */
  .gt.gt-empty { display: none; }

  /* --------------------------------------------------- 12 · THE SAFE AREA
     LAST IN THE BLOCK ON PURPOSE: these are longhands, so they land on top
     of the `padding: a b` shorthands every one of these rules already
     carries, and each keeps the 8px gutter it had. `env()` is 0 on a phone
     held in portrait and on every phone without a notch, so in the common
     case not one pixel of this moves. */
  .top .row, .sec, .mtitle, .ro, .kv, .cover, .legend, .empty, .lean,
  .warnline, .fresh, .credit-foot, .su-wrap, .bar-row, .th-note, .hist,
  .rail-head, .rail-sub, .rail-tabs, .rail-sort, .drawer, .callout,
  .ab-lead, .ab-dl, .brief, .mb, .cohero {
    padding-left: calc(8px + env(safe-area-inset-left));
    padding-right: calc(8px + env(safe-area-inset-right)); }
  /* the tape and every other table scrolls inside itself, so the inset goes
     on the box, not on the cells */
  .tw { padding-left: env(safe-area-inset-left);
    padding-right: env(safe-area-inset-right); }
  /* THE GREY BAR IS FULL-BLEED and pads itself: an inverse-video strip that
     stops short of the glass reads as a fault. */
  .bar { padding-left: calc(8px + env(safe-area-inset-left));
    padding-right: calc(8px + env(safe-area-inset-right)); }
}

/* ================================================== THE TABLET, AT 768 ====
   AN iPAD IN PORTRAIT IS NOT A PHONE. It has the room for the real tape and
   the real rail, so the 700px query deliberately does not reach it and the
   whole desktop layout applies.

   What DOES break at 768 is the grey status bar. It is one `nowrap` line
   with `overflow: hidden`, and eleven key hints do not fit: the headless
   check reported six of them OFFSCREEN — `min`, `filter`, `sound`, both
   window keys and the `?` itself. Nothing scrolled and nothing said so;
   the controls were simply gone.

   The bar wraps between 701 and 900px, and ONLY there. At 901 and above —
   every desktop this is designed on — it is byte for
   byte the line it always was. */
@media (min-width: 835px) and (max-width: 900px) {
  .bar { flex-wrap: wrap; white-space: normal; }
  .bar .credit { order: 3; flex-basis: 100%; }
  .bar-keys { order: 4; flex-basis: 100%; margin-left: 0; display: flex;
    flex-wrap: wrap; gap: 2px 12px; }
}

/* THREE TILES AT 412 AND UP WAS A MISTAKE, and it is gone. A three-up tile
   on a Pixel is about twelve characters wide: `NEAR LIQUIDATION` and
   `WALLETS ACTIVE` collided with the ⧉ button in the corner, and the button
   is 44px now, which would have made it worse. Two up at every phone width,
   on every page. */

/* THE SHARE BUTTON DOES NOT EXIST ON DESKTOP. Not hidden late by a script --
   it has no layout at all above the phone breakpoint, which is what "it must
   not exist on desktop" has to mean for a button a reader could otherwise
   tab to. */
@media (min-width: 835px) {
  .shr { display: none !important; }
  /* the wallet identity grid is a phone thing: above the breakpoint the
     <pre> readout is four tidy rows and is what the desktop has always
     shown. The same for the brief's rendered markdown -- the desktop's
     monospace <pre> lines its pipe tables up into real columns. */
  .widblock, .briefmd { display: none !important; }
  /* the coin page's share hero is a phone thing only: on a desktop the
     price is already the first line of the readout. */
  .cohero { display: none !important; }
}

/* ===================================================== THE PRINT CHART ====
 * The one panel on the terminal that is drawn rather than typed. It is a
 * canvas: the height is fixed here because the canvas has no content of its
 * own to size itself from, and everything inside it is painted in chart.js.
 *
 * 420px on a desk, 260px on a phone. Below that the dots overlap into a
 * smear and the price line loses its shape. */
.pc { position: relative; height: 420px; margin: 0 8px; }
.pc canvas { display: block; width: 100%; height: 100%; }
.pc-bar { padding: 2px 8px; display: flex; gap: 12px; align-items: baseline;
  flex-wrap: wrap; }
.pc-bar .pc-state { margin-left: auto; }
.pc-chip { display: inline-block; color: var(--cyan); }
.pc-chip.on { color: var(--fg); font-weight: 700; }
.pc-leg { padding: 2px 8px; color: var(--fg); max-width: 100ch; }
.pc-leg .pc-k { color: var(--fg); }
.pc-leg .pc-solid { color: var(--green); }
.pc-leg .pc-hollow { color: var(--red); }
.pc-lim { max-width: 80ch; }

/* the tooltip is inside the box, never outside the page: on a phone a
   tooltip that hangs off the right edge is a horizontal scrollbar. */
.pc-tip { position: absolute; z-index: 5; pointer-events: none;
  background: #0a0a0a; border: 1px solid #2a2a2a; padding: 4px 6px;
  max-width: 34ch; color: var(--fg); line-height: 1.4; }
.pc-tip[hidden] { display: none; }
.pc-tip .pc-t1 { font-weight: 700; }

@media (max-width: 834px) {
  /* a 44px target, because a chip you cannot hit is a chip you do not have */
  .pc { height: 260px; margin: 0 4px; }
  .pc-chip { min-height: 44px; line-height: 44px; padding: 0 8px; }
  .pc-bar { gap: 4px; }
  .pc-bar .pc-state { margin-left: 0; flex-basis: 100%; }
}

/* ==== FOOTER + LOGO ====================================================
   Appended block. Nothing above this line is touched.

   THE FOOT OF THE PAGE WAS A PARAGRAPH. Five stacked run-on lines at four
   different indents — the health readout, a red `lanes failing` bar, the
   budget, a db line and a paragraph of prose — and then the crawlable IN
   WORDS block orphaned underneath at a different type scale and a different
   left edge. A reader looking for "is this data fresh" had to read prose.

   It is four columns now, in one order on every page:
       brand · the record · freshness · pages + for machines
   one bottom line, and the IN WORDS block folded in as the last band at the
   same scale. Label left, number right, tabular, so the eye runs down one
   column instead of along a sentence. 4/8/12 spacing, the page's own 8px
   side gutter, one #1f1f1f hairline between bands.                       */

.ftr {
  border-top: 1px solid #1f1f1f;
  margin-top: 16px;
  padding: 12px 8px 8px;
}
.ftr-cols {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) repeat(3, minmax(0, 1fr));
  column-gap: 16px;
  row-gap: 12px;
}
.ftr-col { min-width: 0; }

/* a column head: the same cyan the section heads use, two sizes down */
.ftr-h {
  font-size: 11px;
  font-weight: 700;
  color: var(--cyan);
  letter-spacing: .08em;
  text-transform: uppercase;
  margin: 0 0 4px;
}
.ftr-h2 { margin-top: 12px; }

/* LABEL LEFT, NUMBER RIGHT. Tabular figures are already on at :root, so the
   digits line up down the column and a change of magnitude is visible
   without reading the number. */
.ftr-kv {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  column-gap: 8px;
  margin: 0;
  font-size: 12px;
}
.ftr-kv dt {
  color: var(--dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ftr-kv dd {
  margin: 0;
  text-align: right;
  color: var(--fg);
  white-space: nowrap;
}
/* ONE LONG VALUE MUST NOT NARROW EVERY LABEL. The dd track is shared down
   the whole list, so `2,496 / 5,297 / 56,214` on the tier row was setting
   the width for all nine rows and clipping the labels beside the short
   numbers. That row steps out of the two tracks and takes the full width to
   itself, and every other label gets its words back. */
.ftr-kv .kvw {
  grid-column: 1 / -1;
  display: flex;
  justify-content: space-between;
  gap: 8px;
}

.ftr-id { display: flex; align-items: center; gap: 8px; color: var(--green); }
.ftr-name { font-size: 15px; font-weight: 700; color: var(--fg); }
/* SHORT LINES. Capped at ~36 characters so the standing line breaks where a
   reader expects it to, rather than running the width of a wide column. */
.ftr-say {
  font-size: 11px;
  color: var(--dimmer);
  margin: 4px 0 0;
  max-width: 36ch;
  line-height: 1.5;
}

.ftr-links {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 8px;
  font-size: 12px;
}

/* THE LANE LINE. Amber is "behind", red is "stopped", and they are not the
   same fault — see `laneLine()` in common.js. The old footer painted both
   red, which taught a reader to ignore the one that matters. */
/* IT WRAPS RATHER THAN ELLIPSISES. Which lanes are behind is the whole
   content of the line; a `positions, anchors, marks …` that hides the rest
   is the same failure as the bar it replaced. */
.ftr-lane {
  display: block;
  margin-top: 8px;
  font-size: 12px;
}
.ftr-lane.ok { color: var(--green); }
.ftr-lane.warn { color: var(--amber); }
.ftr-lane.down { color: var(--red); }
.ftr-lane.bad { color: var(--red); }
.ftr-lane.d { color: var(--dim); }
.ftr-prob { font-size: 11px; color: var(--amber); margin: 4px 0 0; }

.ftr-base {
  margin: 12px 0 0;
  padding-top: 8px;
  border-top: 1px solid #1f1f1f;
  font-size: 11px;
  color: var(--dimmer);
}

/* the readout and the db line app.js still writes: kept in the DOM so the
   tape's poll is untouched, and never drawn. */
.ftr-old { display: none; }

/* THE CRAWLABLE SUMMARY, FOLDED IN. It is injected before </body> by
   hltrenches_seo.py, so it lands after the footer; styled here as the last
   band of it rather than an orphan in a different type scale on a different
   left edge. The id beats the <style> the injector carries in <head>. */
section#summary.seo-summary {
  max-width: none;
  margin: 0;
  padding: 8px 8px 12px;
  border-top: 1px solid #1f1f1f;
  font-size: 11px;
  line-height: 1.6;
  opacity: 1;
  color: var(--dimmer);
}
section#summary.seo-summary h2 {
  font-size: 11px;
  font-weight: 700;
  color: var(--cyan);
  letter-spacing: .08em;
  text-transform: uppercase;
  opacity: 1;
  margin: 0 0 4px;
}
section#summary.seo-summary ul.seo-lines {
  list-style: none;
  margin: 0 0 8px;
  padding: 0;
}
section#summary.seo-summary ul.seo-lines li { margin: 0; }
section#summary.seo-summary p { margin: 4px 0 0; }
section#summary.seo-summary p.seo-asof { color: var(--dim); }

/* ---- THE MARK --------------------------------------------------------
   A block of monospace 0s and 1s, edge to edge, on the terminal's black,
   with the `>` cut out of the field in the accent green and the digits
   inside it knocked back to black. One 8x8 grid of 4px cells; the chevron
   is eight of those cells, so the accent area and the knocked-out glyphs
   are the same cells by construction.

   AT 16px THE DIGITS ARE TEXTURE AND THE CHEVRON IS THE MARK -- which is
   the point of cutting it as blocks rather than a stroke: the favicon
   degrades to a solid green chevron on a dark square instead of a smudge.

   It is /logo.svg served as a file and used as an <img>, so the browser
   tab, the status bar and the footer are the same bytes and cannot drift,
   and the field's 64 glyphs are fetched once instead of inlined twice a
   page. /logo-wide.svg is the same chevron beside the name, inside a binary
   string, for anywhere that wants the wordmark. */
.logo-mark { display: inline-block; vertical-align: middle; border: 0; }
.logo-bar { margin-right: 5px; vertical-align: -2px; }

@media (max-width: 834px) {
  /* one column, in reading order. Nothing is dropped on a phone: the record
     and the freshness are the whole reason this block exists. */
  .ftr-cols { grid-template-columns: 1fr; row-gap: 12px; }
  .ftr-kv dt { white-space: normal; }
  .ftr-say { max-width: none; }
}

/* the wordmark (the binary card, 240x48) in the footer's brand column */
.ftr-wordmark { display: block; width: 240px; height: 48px; max-width: 100%; }
@keyframes ftr-tick { 0% { color: var(--green); } 100% { color: inherit; } }
.ftr dd.tick, .ftr .tick { animation: ftr-tick 1.2s ease-out; }
@media (prefers-reduced-motion: reduce) { .ftr .tick { animation: none; } }

/* ===================================================================== WHALES
 * /whales — the whale tape. Every selector here is prefixed `wh-` or `ev-`
 * and belongs to that page alone: the tape page's markup does not change and
 * must not inherit anything new. The anatomy is the approved mock,
 * scratch/hlt_owner/whale_tape_mock.html, and nothing in it is invented —
 * the palette, the rhythm and the type all come from the block above.
 * =========================================================================*/

/* the filter row, in the same top section as the nav and AT A GLANCE */
.r-filt .body { gap: var(--s3, 12px); flex-wrap: wrap; }
.r-filt .fl { color: var(--dimmer); font-size: 11px; margin-right: 3px;
  text-transform: uppercase; letter-spacing: .05em; }
.r-filt select, .r-filt input { font-size: 12px; }
.seg { display: inline-flex; border: 1px solid #1f1f1f; }
.seg b { font-weight: 400; padding: 0 7px; color: var(--dim); cursor: pointer;
  border-right: 1px solid #1f1f1f; }
.seg b:last-child { border-right: 0; }
.seg b.on { background: var(--fg); color: #000; font-weight: 700; }
.seg b:hover { color: var(--fg); }

/* the tape itself */
.wh-count { margin-left: auto; }
table.t.wh-t { width: 100%; }
table.t.wh-t th { border-bottom: 1px solid #141414; }
table.t.wh-t td { color: var(--fg); vertical-align: baseline; padding: 1px 8px; }
tr.wh-ev { border-bottom: 1px solid #0b0b0b; cursor: pointer; }
tr.wh-ev:hover td { background: #101010; }
tr.wh-ev td.wh-time { color: var(--dim); }
tr.wh-ev.open td { background: #0a0a0a; }
.wh-wal { color: var(--fg); }
.wh-wal:hover { color: var(--cyan); }
.wh-book { color: var(--dim); }
.wh-bsz { font-size: 14px; font-weight: 700; }
.wh-lv { font-weight: 700; }
.wh-lv.up { animation: wh-pulse 2s ease-in-out infinite; }
@keyframes wh-pulse { 0%,100% { opacity: 1; } 50% { opacity: .45; } }
@media (prefers-reduced-motion: reduce) { .wh-lv.up { animation: none; } }
td.wh-delta.up { color: var(--green); }
td.wh-delta.down { color: var(--red); }
.wh-oth { color: var(--dim); font-size: 11px; margin-left: 6px; }
.wh-gap { color: var(--dim); font-size: 11px; margin-left: 6px; }
.wh-ftog { display: none; cursor: pointer; color: var(--accent, #7fd); margin-left: 8px; padding: 0 10px; border: 1px solid #333; }
.wh-fsum { color: var(--dim); font-size: 11px; margin-left: 8px; }
@media (min-width: 835px) { .wh-fsum { display: none; } }
.wh-book b { color: var(--fg); font-weight: 700; }
.wh-caret { color: var(--dimmer); padding-left: 4px; }
.wh-tag { font-size: 10px; color: var(--dimmer); margin-left: 6px; }
.wh-stale { font-size: 10px; color: var(--amber); margin-left: 6px;
  border: 1px solid var(--amber); padding: 0 3px; }
.wh-age { font-size: 10px; color: var(--dimmer); margin-left: 6px; }

/* EVENT badges — the one new vocabulary item on the page */
.ev-b { display: inline-block; font-size: 10px; font-weight: 700;
  letter-spacing: .06em; padding: 0 4px; min-width: 11ch; text-align: center; }
.ev-OFFLOADING { color: #000; background: var(--amber); }
.ev-BUILDL { color: #000; background: var(--green); }
.ev-BUILDS { color: #000; background: var(--red); }
.ev-FLIPPED { color: #000; background: var(--magenta); }
.ev-OPENED { color: #000; background: var(--cyan); }
.ev-CLOSED { color: var(--dim); border: 1px solid #2a2a2a; }
.wh-xn { font-size: 10px; color: var(--magenta); font-weight: 700; margin-left: 4px; }

/* a row that arrived on a poll says so, once */
@keyframes wh-new { 0% { background: #14301c; } 100% { background: transparent; } }
tr.wh-ev.wh-fresh td { animation: wh-new 2.4s ease-out; }
@media (prefers-reduced-motion: reduce) { tr.wh-ev.wh-fresh td { animation: none; } }

/* the drawer under a row: the whole book, then its last 24h */
tr.wh-exp { background: #050505; }
tr.wh-exp > td { padding: 8px 8px 12px; border-bottom: 1px solid #1f1f1f;
  white-space: normal; }
/* the prose inside the drawer WRAPS. `table.t` sets nowrap for the tape's own
   columns and the drawer inherited it, so the book's headline, its history
   lines and its footnote each pushed the whole document sideways on a phone.
   The one thing that stays nowrap is the book table, and it scrolls inside
   its own box. */
.wh-exph, .wh-h div, .wh-note { white-space: normal; }
.wh-exph { color: var(--cyan); font-size: 10px; text-transform: uppercase;
  letter-spacing: .07em; margin: 0 0 4px; }
table.wh-b { border-collapse: collapse; white-space: nowrap; margin-bottom: 12px; }
table.wh-b th { text-align: left; font-weight: 400; color: var(--dim);
  font-size: 11px; padding: 1px 14px 1px 0; border-bottom: 1px solid #141414; }
table.wh-b td { padding: 1px 14px 1px 0; font-size: 12px; }
table.wh-b th.n, table.wh-b td.n { text-align: right; }
.wh-h div { font-size: 12px; color: var(--dim); padding: 1px 0; }
.wh-h div b { color: var(--fg); font-weight: 400; }
.wh-h .wh-ht { color: var(--dimmer); display: inline-block; width: 7ch; }
.wh-note { padding: 8px 0 0; color: var(--dimmer); font-size: 11px; margin: 0; }
.wh-note b { color: var(--dim); font-weight: 400; }

/* the empty state says, in words, WHY it is empty */
.wh-empty { padding: 14px 8px; color: var(--dim); }
.wh-empty b { color: var(--fg); font-weight: 700; display: block; }
.wh-limits, .wh-prov { padding: 6px 8px; }
.wh-prov { color: var(--dimmer); }

/* ---- PHONE: the same rows, stacked exactly as the mock ---- */
@media (max-width: 834px) {
  .r-filt .body { gap: 8px 12px; }
  .wh-count { margin-left: 0; flex-basis: 100%; }
  .wh-tw { overflow: visible; }
  /* ONLY THE OUTER TABLE STACKS. The first version of this rule said
     `table.t.wh-t td`, which also matched every cell of the book table
     INSIDE the drawer — so a wallet's eleven columns came out as eleven
     lines each, one number per line, with no header anywhere near them.
     The child combinators keep the stacking to the tape's own rows. */
  table.t.wh-t > thead { display: none; }
  table.t.wh-t, table.t.wh-t > tbody, table.t.wh-t > tbody > tr,
  table.t.wh-t > tbody > tr > td { display: block; width: auto; }
  tr.wh-ev { padding: 8px; border-bottom: 1px solid #141414; }
  tr.wh-ev td { padding: 0; white-space: normal; }
  td.wh-time { display: inline !important; color: var(--dim); }
  td.wh-badge { display: inline !important; margin-left: 6px; }
  td.wh-coin { display: inline !important; margin-left: 6px; }
  td.wh-delta { display: inline !important; float: right; font-weight: 700; }
  td.wh-who { display: block !important; padding-top: 2px !important; }
  td.wh-px { display: inline !important; color: var(--dim); font-size: 12px; }
  td.wh-book { display: inline !important; font-size: 12px; margin-left: 6px; }
  td.wh-pnl { display: block !important; font-size: 12px; padding-top: 1px !important; }
  td.wh-car { display: none !important; }
  tr.wh-exp > td { padding: 8px; }
  /* LABELS ON THE PHONE'S FIGURES: the desktop headers are gone here, so
     each dollar figure says what it is (independent review, deviation 7) */
  td.wh-delta::before { content: 'changed '; color: var(--dim); font-weight: 400; font-size: 11px; }
  td.wh-book::before { content: 'book after '; color: var(--dim); font-size: 11px; }
  td.wh-pnl::before { content: 'under water '; color: var(--dim); font-size: 11px; }
  td.wh-pnl.d::before { content: ''; }
  /* THE FILTERS FOLD on a phone (deviation 6: 1,100px of chips above the
     first event). The summary beside "filters" says what is in force. */
  #wh-filt .body { display: none; }
  #wh-filt .body.open { display: flex; }
  .wh-ftog { display: inline-block; }
  table.wh-b { display: block; overflow-x: auto; white-space: nowrap; width: 100%; }
  /* nothing under 12px, and every tap target 44px */
  .ev-b, .wh-xn, .wh-tag, .wh-stale, .wh-age, .wh-exph,
  .wh-empty, .wh-limits, .wh-prov, .wh-note, .wh-h div,
  table.wh-b th, table.wh-b td, .r-filt .fl { font-size: 12px; }
  tr.wh-ev { min-height: 44px; }
  .seg b { padding: 0 12px; line-height: 44px; min-height: 44px; }
  .r-filt select, .r-filt input { min-height: 44px; }
}
