/* JARVIS — Command Center shell.
 *
 * The design language is ported from the Rocket build: a near-black field,
 * glass panels with a hairline border, one accent that glows, and tabular
 * mono numerals so figures don't jitter as they update.
 *
 * Colour comes from the same custom properties the rest of the app uses
 * (--gold is the accent, whatever mode is active), so the six colour modes
 * drive this surface too. Nothing here hard-codes cyan — that was the Rocket
 * app's single accent, and hard-coding it would have made the mode picker a
 * lie on this page.
 */

:root {
  /* Neutral defaults shown before modes.js applies the selected accent. */
  --sh-bg: #0d0f12;
  --sh-deep: #101216;
  --sh-panel: rgba(19, 22, 27, 0.98);
  --sh-panel-hi: rgba(24, 28, 34, 0.99);
  --sh-line: #262c35;
  --sh-text: #f2f3f5;
  --sh-dim: #b1b7c1;
  --sh-faint: #858d99;
  --sh-ok: #10b981;
  --sh-warn: #f59e0b;
  --sh-bad: #f45b5b;
  --sh-mono: "JetBrains Mono", "SF Mono", ui-monospace, "IBM Plex Mono", monospace;
  --sh-rail: 232px;
  /* Defined here too, because this page does not load the chat app's
     stylesheet (see shell.html) and would otherwise have no display face. The
     accent variables come from modes.js, which sets them inline on :root. */
  --font-display: -apple-system, BlinkMacSystemFont, "SF Pro Display",
                  "Segoe UI", system-ui, sans-serif;
  --gold: #ffb020;
  --gold-bright: #ffd47a;
}

* { box-sizing: border-box; }

body.shell {
  margin: 0;
  background: var(--sh-bg);
  color: var(--sh-text);
  font-family: var(--font-display), system-ui, sans-serif;
  min-height: 100vh;
  background-image: none;
}

.mono, .kpi-num, .tick, .clock { font-family: var(--sh-mono); font-variant-numeric: tabular-nums; }
/* Wrap-up bodies are prose the model wrote, in a <pre> so nothing in them is
   read as markup. `pre-wrap` because they are paragraphs, not code — without it
   a long decision line scrolls the whole panel sideways. */
.wrap-body { white-space: pre-wrap; overflow-wrap: anywhere; margin: 6px 0 0;
             font-size: 12px; line-height: 1.5; opacity: .85; }

/* One focus ring for the whole shell.
 *
 * Individual controls used to opt in — .tab, .dock-head and the risk sliders had
 * one; the ~700 .switch buttons, every nav row and every text input did not, so
 * a keyboard user tabbing through this page mostly could not see where they
 * were. :focus-visible rather than :focus, so a mouse click does not leave a
 * ring behind on a button that was already answered.
 *
 * Declared before the component rules so a control with a deliberately
 * different ring (the sliders sit inside their track and need the offset) still
 * wins on source order. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
  border-radius: 4px;
}

/* Pressed feedback. Nothing here moved on mousedown, so a click that started a
   slow request looked identical to one the page had ignored. */
.switch:active:not([disabled]), .tab:active, .dock-btn:active { transform: translateY(1px); }
.switch, .tab, .dock-btn { transition: border-color .18s ease, color .18s ease,
                                       background .18s ease, transform .08s ease; }
@media (prefers-reduced-motion: reduce) {
  .switch, .tab, .dock-btn, .avatar { transition: none; }
  .switch:active:not([disabled]), .tab:active, .dock-btn:active,
  .avatar:active { transform: none; }
}

/* ---- layout ------------------------------------------------------------- */

.shell-grid { display: grid; grid-template-columns: var(--sh-rail) 1fr; min-height: 100vh; }
/* A grid item's default `min-width: auto` is its content's intrinsic width, so
   the nowrap ticker inside the main column stretched the whole page and pushed
   the right-hand tiles off screen. This is the fix for that, not a nicety. */
.shell-grid > * { min-width: 0; }

/* ---- rail --------------------------------------------------------------- */

.rail {
  border-right: 1px solid var(--sh-line);
  background: color-mix(in srgb, var(--sh-deep) 90%, transparent);
  display: flex; flex-direction: column;
  position: sticky; top: 0; height: 100vh; overflow: hidden;
}
.rail-head { display: flex; align-items: center; gap: 10px; min-height: 62px; padding: 12px 14px; }
.rail-mark {
  width: 30px; height: 30px; flex: none; border-radius: 8px;
  background: var(--gold); border: 1px solid var(--gold);
  display: grid; place-items: center; color: var(--on-gold, #201400);
  font: 800 15px/1 var(--sh-mono); letter-spacing: -.04em;
}
.rail-title { min-width: 0; }
.rail-name { font: 700 12px/1 var(--sh-mono); letter-spacing: .16em; }

/* The collapse control. Ghost by default so it does not compete with the mark
   beside it, and only picks up the accent once you are actually on it. */
.rail-toggle {
  margin-left: auto; flex: none; padding: 0;
  width: 30px; height: 30px; border-radius: 50%;
  display: grid; place-items: center;
  background: transparent; border: 1px solid var(--sh-line);
  color: var(--sh-dim); cursor: pointer;
  transition: background .16s ease, border-color .16s ease,
              color .16s ease, transform .1s ease;
}
.rail-toggle:hover {
  color: var(--gold-bright);
  border-color: color-mix(in srgb, var(--gold) 55%, transparent);
  background: color-mix(in srgb, var(--gold) 12%, transparent);
}
.rail-toggle:active { transform: scale(.9); }
.rail-toggle svg { width: 15px; height: 15px; transition: transform .22s ease; }

/* The burger only exists on phones, where the rail is off-canvas. */
.rail-burger {
  display: none; flex: none; padding: 0;
  width: 38px; height: 38px; border-radius: 10px;
  place-items: center;
  background: rgba(255, 255, 255, .04); border: 1px solid var(--sh-line);
  color: var(--sh-dim); cursor: pointer;
  transition: background .16s ease, border-color .16s ease, color .16s ease;
}
.rail-burger:hover {
  color: var(--gold-bright);
  border-color: color-mix(in srgb, var(--gold) 45%, transparent);
}
.rail-scrim {
  position: fixed; inset: 0; z-index: 35;
  background: rgba(0, 0, 0, .55); backdrop-filter: blur(2px);
}
.rail-scrim[hidden] { display: none; }

@media (prefers-reduced-motion: reduce) {
  .rail-toggle, .rail-toggle svg, .rail-burger { transition: none; }
  .rail-toggle:active { transform: none; }
}

.nav { flex: 1; overflow-y: auto; padding: 3px 8px 14px; }
.nav-group-label {
  font: 600 9px/1 var(--sh-mono); letter-spacing: .14em; color: var(--sh-faint);
  padding: 16px 9px 7px;
}
.nav-disclosure { margin: 12px 0 5px; }
.nav-group-toggle {
  display: flex; align-items: center; gap: 10px; width: 100%;
  min-height: 38px; padding: 8px 10px; border-radius: 8px;
  background: transparent; border: 1px solid transparent; color: var(--sh-dim);
  font: 600 12.5px/1 var(--font-display); cursor: pointer; text-align: left;
  transition: background .14s, color .14s, border-color .14s;
}
.nav-group-toggle:hover,
.nav-disclosure.is-open > .nav-group-toggle {
  background: color-mix(in srgb, var(--sh-panel-hi) 72%, transparent);
  border-color: var(--sh-line); color: var(--sh-text);
}
.nav-group-toggle > svg { width: 17px; height: 17px; flex: none; color: var(--sh-faint); }
.nav-disclosure.has-active > .nav-group-toggle > svg:first-child { color: var(--gold); }
.nav-group-chevron {
  margin-left: auto; width: 14px !important; height: 14px !important;
  transform: rotate(180deg); transition: transform .16s ease;
}
.nav-disclosure.is-open > .nav-group-toggle .nav-group-chevron { transform: rotate(270deg); }
.nav-submenu {
  margin: 3px 0 7px 16px; padding-left: 8px;
  border-left: 1px solid var(--sh-line);
}
.nav-submenu[hidden] { display: none; }
.nav-submenu .nav-item { min-height: 33px; padding: 6px 9px; font-size: 12px; }
.nav-item {
  display: flex; align-items: center; gap: 10px; width: 100%;
  min-height: 36px; padding: 7px 10px; margin-bottom: 2px; border-radius: 8px;
  background: none; border: 1px solid transparent; color: var(--sh-dim);
  font: inherit; font-size: 12.5px; cursor: pointer; text-align: left;
  transition: background .14s, color .14s, border-color .14s;
}
.nav-item:hover { background: color-mix(in srgb, var(--sh-panel-hi) 72%, transparent); color: var(--sh-text); }
.nav-item.on {
  color: var(--sh-text);
  background: var(--sh-panel-hi);
  border-color: var(--sh-line);
}
/* The active row gets a lit edge — the one place a border does real work. */
.nav-item.on::before {
  content: ""; position: absolute; left: 0; width: 2px; height: 18px;
  border-radius: 0 2px 2px 0; background: var(--gold);
}
.nav-item { position: relative; }
.nav-item svg { width: 17px; height: 17px; flex: none; color: var(--sh-faint); }
.nav-item.on svg { color: var(--gold); }
.nav-label { flex: 1; }
/* Live counts written by badge() — pending approvals, open tasks, sessions,
   memories, capabilities. Not related to the removed "not built yet" marker,
   which also used this class; that one is gone, these are not. */
.nav-badge {
  font-family: var(--sh-mono); font-size: 11px; min-width: 22px; height: 22px;
  border-radius: 11px; display: grid; place-items: center; padding: 0 6px;
  background: color-mix(in srgb, var(--gold) 16%, transparent);
  color: var(--gold-bright);
}
.rail-foot {
  border-top: 1px solid var(--sh-line); padding: 12px 16px;
  font: 10px/1 var(--sh-mono); letter-spacing: .12em; color: var(--sh-dim);
  display: flex; align-items: center; gap: 10px;
}
.dot { width: 7px; height: 7px; border-radius: 50%; background: var(--sh-ok); flex: none; }
.dot.warn { background: var(--sh-warn); }
.dot.bad  { background: var(--sh-bad); }

/* ---- rail: collapsed ----------------------------------------------------- *
 *
 * Desktop only. Below 780px the rail is already off-canvas, and applying the
 * 68px width there would give the drawer you just opened no labels at all —
 * so every rule here sits behind the breakpoint rather than being undone
 * one-by-one further down. `.collapsed` is on <html>, set before first paint.
 *
 * Names are hidden with `display: none`, which also removes them from the
 * accessibility tree — so buildNav puts the same text on `aria-label` and
 * `title`, and that is what labels the icons here. */

@media (min-width: 781px) {
  .collapsed .shell-grid { --sh-rail: 68px; }

  .collapsed .rail-name, .collapsed .rail-sub,
  .collapsed .nav-label, .collapsed .rail-foot span { display: none; }

  /* 38px mark + 30px button + gap does not fit in 68px, so the head stacks. */
  .collapsed .rail-head { flex-direction: column; gap: 10px; padding: 16px 0 12px; }
  .collapsed .rail-mark { width: 34px; height: 34px; border-radius: 10px; }
  .collapsed .rail-toggle { margin-left: 0; }
  .collapsed .rail-toggle svg { transform: rotate(180deg); }

  /* Group headings carry the rail's structure. Losing the words is fine;
     losing the grouping entirely would turn 68 icons into one flat run. */
  .collapsed .nav { padding: 4px 8px 16px; }
  .collapsed .nav-group-label {
    height: 1px; padding: 0; margin: 14px 10px 10px; overflow: hidden;
    font-size: 0; background: var(--sh-line);
  }
  .collapsed .nav-group-toggle { justify-content: center; gap: 0; padding: 10px 0; }
  .collapsed .nav-group-toggle .nav-label,
  .collapsed .nav-group-toggle .nav-group-chevron { display: none; }
  .collapsed .nav-submenu { display: none; }
  .collapsed .nav-item { justify-content: center; gap: 0; padding: 10px 0; }
  /* A count needs its digits; a dot only needs to say "there is something
     here", which is all 68px has room for. */
  .collapsed .nav-badge {
    position: absolute; top: 6px; right: 10px;
    min-width: 8px; width: 8px; height: 8px; padding: 0;
    border-radius: 50%; font-size: 0; overflow: hidden;
    background: var(--gold); box-shadow: 0 0 8px var(--gold);
  }
  .collapsed .rail-foot { justify-content: center; padding: 14px 0; }
}

/* ---- topbar ------------------------------------------------------------- */

.top {
  display: flex; align-items: center; gap: 18px; min-height: 62px;
  padding: 11px 24px; border-bottom: 1px solid var(--sh-line);
  background: color-mix(in srgb, var(--sh-deep) 94%, transparent); backdrop-filter: blur(10px);
  position: sticky; top: 0; z-index: 20;
}
.search {
  flex: 0 1 360px; display: flex; align-items: center; gap: 9px;
  min-height: 38px; padding: 8px 12px; border-radius: 8px;
  background: var(--sh-panel); border: 1px solid var(--sh-line);
  color: var(--sh-dim); cursor: pointer; font: inherit; font-size: 13px;
}
.search:hover { border-color: color-mix(in srgb, var(--gold) 40%, transparent); }
.search kbd {
  margin-left: auto; font-family: var(--sh-mono); font-size: 11px;
  color: var(--sh-faint); border: 1px solid var(--sh-line);
  border-radius: 5px; padding: 1px 5px;
}
.stat-strip { display: flex; align-items: center; gap: 20px; margin-left: auto;
              font-family: var(--sh-mono); font-size: 12.5px; color: var(--sh-dim); }
.stat-strip b { color: var(--sh-text); font-weight: 600; }
.stat-strip .ok { color: var(--sh-ok); }
.avatar {
  width: 38px; height: 38px; border-radius: 50%; display: grid; place-items: center;
  font-family: var(--sh-mono); font-size: 13px; color: var(--gold-bright);
  background: color-mix(in srgb, var(--gold) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--gold) 40%, transparent);
  padding: 0; cursor: pointer;
  transition: background .18s ease, border-color .18s ease, transform .18s ease;
}
.avatar:hover {
  background: color-mix(in srgb, var(--gold) 24%, transparent);
  border-color: color-mix(in srgb, var(--gold) 65%, transparent);
}
.avatar:active { transform: scale(.94); }
.avatar:focus-visible { outline: 2px solid var(--gold-bright); outline-offset: 2px; }
/* Lit while Profile is the open screen, so the badge reads as navigation. */
.avatar.on {
  background: color-mix(in srgb, var(--gold) 28%, transparent);
  border-color: var(--gold);
}
.account-switcher { position: relative; flex: none; }
.account-menu {
  position: absolute; right: 0; top: calc(100% + 10px); z-index: 30;
  width: min(290px, calc(100vw - 28px)); padding: 8px;
  border: 1px solid var(--sh-line); border-radius: 12px;
  background: color-mix(in srgb, var(--sh-panel-hi) 96%, transparent);
  box-shadow: 0 18px 52px rgba(3, 5, 8, .52), inset 0 1px rgba(255,255,255,.035);
  backdrop-filter: blur(18px);
}
.account-menu[hidden] { display: none; }
.account-menu-id { padding: 10px 11px 12px; border-bottom: 1px solid var(--sh-line); }
.account-menu-id strong, .account-menu-id span { display: block; overflow: hidden; text-overflow: ellipsis; }
.account-menu-id strong { font-size: 13px; font-weight: 650; }
.account-menu-id span { margin-top: 4px; color: var(--sh-faint); font: 10.5px/1.35 var(--sh-mono); }
.account-menu > button, .account-menu > a {
  width: 100%; display: flex; align-items: center; min-height: 38px;
  margin-top: 3px; padding: 8px 11px; border: 0; border-radius: 7px;
  background: transparent; color: var(--sh-dim); text-decoration: none;
  font: 550 12.5px/1 var(--font-display); cursor: pointer; text-align: left;
}
.account-menu > button:hover, .account-menu > a:hover {
  background: color-mix(in srgb, var(--gold) 10%, transparent); color: var(--sh-text);
}
.account-menu > .danger { color: var(--sh-bad); }

/* ---- page --------------------------------------------------------------- */

.page { padding: 28px 30px 48px; max-width: 1680px; overflow-x: hidden; }
.page-head { display: flex; align-items: flex-start; gap: 18px; margin-bottom: 22px; }
/* The controls that belong to a whole screen rather than to one row in it.
   Wraps so a narrow window stacks them instead of pushing the title off. */
.head-actions {
  margin-left: auto; display: flex; flex-wrap: wrap; gap: 8px;
  align-items: center; justify-content: flex-end;
}
.head-actions .msg { font-size: 12.5px; color: var(--sh-faint); }
.head-actions .msg.bad { color: var(--sh-bad); }
.head-actions .msg.ok { color: var(--sh-ok); }
.page-title { font-size: clamp(28px, 3vw, 38px); line-height: 1.05; letter-spacing: -.035em; font-weight: 680; margin: 0 0 8px; }
.page-sub { font-family: var(--font-display); font-size: 13px; letter-spacing: 0;
            color: var(--sh-faint); text-transform: none; }
.live-chip {
  margin-left: auto; display: flex; align-items: center; gap: 8px;
  font-family: var(--sh-mono); font-size: 12px; letter-spacing: .1em;
  padding: 6px 11px; border-radius: 7px; color: var(--sh-ok);
  border: 1px solid color-mix(in srgb, var(--sh-ok) 40%, transparent);
  background: color-mix(in srgb, var(--sh-ok) 10%, transparent);
}

/* ---- tenant/runtime and downloads -------------------------------------- */
.tenant-kicker {
  margin-bottom: 9px; color: var(--gold-bright);
  font: 650 10px/1 var(--sh-mono); letter-spacing: .16em;
}
.runtime-chip {
  margin-left: auto; padding: 7px 10px; border-radius: 6px;
  border: 1px solid color-mix(in srgb, var(--sh-warn) 48%, transparent);
  color: var(--sh-warn); font: 650 10px/1 var(--sh-mono); letter-spacing: .12em;
}
.runtime-chip.ok { color: var(--sh-ok); border-color: color-mix(in srgb, var(--sh-ok) 48%, transparent); }
.tenant-layout { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(280px, .8fr); gap: 16px; }
.tenant-primary { padding: clamp(24px, 4vw, 46px); min-height: 310px; display: flex; flex-direction: column; align-items: flex-start; }
.tenant-primary h2, .download-shell-card h2 { margin: 20px 0 10px; font-size: clamp(25px, 3vw, 38px); letter-spacing: -.04em; }
.tenant-primary p, .download-shell-card p { max-width: 62ch; margin: 0; color: var(--sh-dim); line-height: 1.65; }
.tenant-icon { width: 50px; height: 50px; display: grid; place-items: center; border-radius: 13px; color: var(--gold-bright); background: color-mix(in srgb, var(--gold) 15%, transparent); }
.tenant-icon svg { width: 24px; height: 24px; }
.tenant-actions { display: flex; flex-wrap: wrap; gap: 9px; margin-top: auto; padding-top: 28px; }
.tenant-catalog-card { margin-top: 16px; }
.tenant-catalog { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); }
.tenant-cap { min-height: 78px; padding: 16px; border-top: 1px solid var(--sh-line); border-right: 1px solid var(--sh-line); }
.tenant-cap strong { display: block; font-size: 12.5px; }
.tenant-cap span { display: block; margin-top: 7px; color: var(--sh-faint); font: 10px/1.2 var(--sh-mono); text-transform: uppercase; letter-spacing: .08em; }
.tenant-cap .ready { color: var(--sh-ok); }
.tenant-cap .setup_required { color: var(--sh-warn); }
.download-shell-card { display: flex; align-items: flex-end; justify-content: space-between; gap: 28px; padding: clamp(24px, 4vw, 46px); }
.download-shell-card h2 { margin-top: 10px; }
.download-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; margin-top: 16px; }
.download-tile { padding: 22px; min-height: 180px; display: flex; flex-direction: column; }
.download-tile h3 { margin: 0 0 8px; font-size: 21px; }
.download-tile p { margin: 0 0 22px; color: var(--sh-dim); line-height: 1.5; }
.download-tile .switch { margin-top: auto; align-self: flex-start; }
@media (max-width: 900px) {
  .tenant-layout, .download-grid { grid-template-columns: 1fr; }
  .download-shell-card { align-items: flex-start; flex-direction: column; }
}

/* ---- ticker ------------------------------------------------------------- */

.ticker {
  overflow: hidden; border: 1px solid var(--sh-line); border-radius: 10px;
  background: var(--sh-panel); padding: 10px 0; margin-bottom: 16px;
}
.ticker-track { display: flex; gap: 34px; white-space: nowrap; padding-left: 18px;
                animation: tick-scroll 42s linear infinite; }
.ticker:hover .ticker-track { animation-play-state: paused; }
.tick { font-size: 13px; color: var(--sh-dim); }
.tick b { color: var(--sh-text); margin-right: 6px; }
.up { color: var(--sh-ok); } .down { color: var(--sh-bad); }
@keyframes tick-scroll { from { transform: translateX(0); } to { transform: translateX(-50%); } }

/* ---- panels & bento ----------------------------------------------------- */

.glass {
  background: var(--sh-panel); border: 1px solid var(--sh-line);
  border-radius: 12px;
  /* A short shadow keeps hierarchy without turning every data panel into
     floating glass. */
  box-shadow: 0 1px 2px rgba(0, 0, 0, .18);
}
.glass.lit {
  background: var(--sh-panel-hi);
  border-color: color-mix(in srgb, var(--gold) 36%, var(--sh-line));
  box-shadow: inset 2px 0 0 color-mix(in srgb, var(--gold) 80%, transparent);
}
.glass.bad { border-color: color-mix(in srgb, var(--sh-bad) 42%, transparent);
             box-shadow: inset 2px 0 0 color-mix(in srgb, var(--sh-bad) 80%, transparent); }

.bento { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; margin-bottom: 12px; }
/* Four columns is the house grid, but a screen with three readings has three —
   forcing it into four leaves a column of nothing that reads as a card which
   failed to load. Declared per screen rather than derived, because the slot
   count depends on which children are .wide and CSS cannot count that. */
.bento.cols-3 { grid-template-columns: repeat(3, 1fr); }
/* Two columns wide, one row tall. Spanning two rows as well left a tall empty
   well under the number on every screen that has no chart to put there.
   Any bento child, not only .kpi: the panels on the Android Bridge already
   said class="glass wide" and silently got one column, so that row ended half
   empty with nothing in the markup to explain why. */
.bento > .wide { grid-column: span 2; }
.bento > .span3 { grid-column: span 3; }
.kpi { padding: 18px; display: flex; flex-direction: column; gap: 4px; min-height: 148px; }
/* Only the trading tile earns the extra row — it holds a sparkline. */
#v-trading .kpi.wide, #v-finance .kpi.wide { grid-row: span 2; }
.kpi-top { display: flex; align-items: center; margin-bottom: 10px; }
.kpi-icon {
  width: 34px; height: 34px; border-radius: 8px; display: grid; place-items: center;
  background: color-mix(in srgb, var(--gold) 10%, transparent); color: var(--gold);
}
.kpi-icon.red { background: color-mix(in srgb, var(--sh-bad) 15%, transparent); color: var(--sh-bad); }
.kpi-delta { margin-left: auto; font-family: var(--sh-mono); font-size: 12px; color: var(--sh-dim); }
.kpi-num { font-size: 34px; font-weight: 650; line-height: 1.1; letter-spacing: -.035em; }
.kpi.wide .kpi-num { font-size: 52px; }
/* The lead tile on a grid whose card count already divides by four. Spanning
   two columns there left a single orphan on the last row — three empty columns
   that read as a layout which failed to finish loading. It keeps the emphasis
   (the lit surface, the larger figure) and gives up only the floor space. */
.kpi.hero .kpi-num { font-size: 48px; }
.kpi-label { font-size: 11px; letter-spacing: .1em; text-transform: uppercase; color: var(--sh-dim); }
.kpi-foot { font-size: 12.5px; color: var(--sh-faint); margin-top: auto; }
.meter { height: 4px; border-radius: 2px; background: rgba(255,255,255,.07); margin-top: 12px; overflow: hidden; }
.meter i { display: block; height: 100%; border-radius: 2px; background: var(--gold);
           box-shadow: 0 0 10px var(--gold); }
.meter i.ok { background: var(--sh-ok); box-shadow: 0 0 10px var(--sh-ok); }

/* ---- lists / tables ----------------------------------------------------- */

.row2 { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 12px; }
.panel-head { display: flex; align-items: center; gap: 10px; padding: 16px 18px;
              border-bottom: 1px solid var(--sh-line); }
.panel-title { font-size: 16px; font-weight: 600; }
.panel-note { margin-left: auto; font-family: var(--sh-mono); font-size: 11.5px; color: var(--sh-faint); }
.panel-body { padding: 14px 18px 18px; }
.line {
  display: flex; align-items: center; gap: 12px; padding: 11px 0;
  border-bottom: 1px solid rgba(255,255,255,.045); font-size: 14px;
}
.line:last-child { border-bottom: 0; }
.line .grow { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.line .val { font-family: var(--sh-mono); font-size: 13px; color: var(--sh-dim); }
.tag {
  font-family: var(--sh-mono); font-size: 10.5px; letter-spacing: .1em; text-transform: uppercase;
  padding: 3px 8px; border-radius: 5px; border: 1px solid var(--sh-line); color: var(--sh-dim);
}
.tag.ok { color: var(--sh-ok); border-color: color-mix(in srgb, var(--sh-ok) 38%, transparent); }
.tag.bad { color: var(--sh-bad); border-color: color-mix(in srgb, var(--sh-bad) 38%, transparent); }
.tag.warn { color: var(--sh-warn); border-color: color-mix(in srgb, var(--sh-warn) 38%, transparent); }
.empty { color: var(--sh-faint); font-size: 13.5px; padding: 10px 0; }

/* A row carrying an explanation under its label.
   .line clips its cells to one line, which is right for a label and a reading
   but silently eats a second line — so a stress scenario's description needs a
   row that is allowed to be two lines tall rather than an ellipsis. */
.line.tall { align-items: flex-start; }
.line.tall .grow, .line.tall .val { white-space: normal; overflow: visible; text-overflow: clip; }
.line.tall .val { text-align: right; }
.dim { color: var(--sh-faint); font-size: 12px; line-height: 1.45; }

/* ---- filters & long lists ----------------------------------------------- */

.filter {
  margin-left: auto; font: inherit; font-size: 13px; width: 220px;
  padding: 7px 12px; border-radius: 8px; color: var(--sh-text);
  background: rgba(255, 255, 255, .04); border: 1px solid var(--sh-line);
}
.filter::placeholder { color: var(--sh-faint); }
.filter:focus { outline: none; border-color: color-mix(in srgb, var(--gold) 45%, transparent); }
.panel-head .filter + .panel-note { margin-left: 14px; }

/* Registries run to hundreds of rows. Capping the height keeps the page
   navigable instead of turning one panel into the whole document. */
.scroll-tall { max-height: 460px; overflow-y: auto; }

.line .desc {
  color: var(--sh-faint); font-size: 12.5px; margin-left: 8px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.line.stacked { flex-direction: column; align-items: stretch; gap: 3px; }
.line.stacked .top-row { display: flex; align-items: center; gap: 10px; }
.line.stacked .desc { margin: 0; white-space: normal; }
.switch {
  font: inherit; font-size: 11px; font-family: var(--sh-mono); cursor: pointer;
  min-height: 30px; padding: 5px 10px; border-radius: 7px; background: var(--sh-panel-hi);
  border: 1px solid var(--sh-line); color: var(--sh-dim);
}
.switch:hover { border-color: color-mix(in srgb, var(--gold) 45%, transparent); color: var(--sh-text); }
.switch.on { color: var(--sh-ok); border-color: color-mix(in srgb, var(--sh-ok) 45%, transparent); }
.switch.primary {
  color: var(--on-gold, #201400); background: var(--gold); border-color: var(--gold);
  font-weight: 600; padding: 6px 16px;
}
.switch[disabled] { opacity: .5; cursor: default; }
/* A cross-reference to the screen that owns a control, styled like the control
   it replaces. Two buttons writing one value is how two screens start
   disagreeing about what is on, so where a setting already has a home this
   points at it rather than copying it. The arrow says "you will leave here". */
a.switch { display: inline-block; text-decoration: none; }
a.switch::after { content: " →"; opacity: .55; }

.inp {
  font: inherit; font-size: 13.5px; font-family: var(--sh-mono);
  min-height: 36px; padding: 7px 10px; border-radius: 7px; min-width: 190px;
  background: var(--sh-deep); border: 1px solid var(--sh-line);
  color: var(--sh-text);
}
.inp:focus { outline: none; border-color: color-mix(in srgb, var(--gold) 45%, transparent); }
.inp:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
textarea.inp { width: 100%; resize: vertical; line-height: 1.5; margin: 8px 0; }

/* A row of controls that belongs to the panel body rather than the page head.
   .head-actions handles the header bar; a form inside a panel needs to wrap on
   a narrow window instead of pushing the panel wider than the column. */
.form-row { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.form-row + .form-row { margin-top: 8px; }
.form-row .inp { flex: 1 1 190px; }
.form-row .switch, .form-row .chk { flex: 0 0 auto; }
#v-language .switch { min-height: 32px; }
#v-language .panel-note, #v-language .page-sub { color: var(--sh-dim); }

.chk {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 13px; color: var(--sh-dim); cursor: pointer;
}
.chk input { accent-color: var(--gold); }

/* Plain text that arrived from outside — a search result, a tool's output.
   <pre> keeps its shape, but a search result has long URLs in it, so it has
   to be allowed to wrap or the panel scrolls sideways forever. */
pre.wrap {
  white-space: pre-wrap; word-break: break-word; margin: 0;
  font-family: var(--sh-mono); font-size: 13px; line-height: 1.55;
  color: var(--sh-dim); max-height: 60vh; overflow-y: auto;
}

/* Volume-by-price bars. The bar is drawn as a background gradient on the row
   so the label stays readable on top of it rather than being pushed aside. */
.vbar { position: relative; margin: 2px 0; }
.vbar .line { position: relative; z-index: 1; }
.vbar .fill {
  position: absolute; left: 0; top: 2px; bottom: 2px; border-radius: 4px;
  background: color-mix(in srgb, var(--gold) 14%, transparent);
}
.vbar.poc .fill { background: color-mix(in srgb, var(--gold) 30%, transparent); }
.vbar.va .fill { background: color-mix(in srgb, var(--gold) 20%, transparent); }

/* ---- action bars --------------------------------------------------------- */

/* Every screen that lists something also has to change it, so the composer row
   is one shared shape rather than a bespoke form per panel. */
.act-bar {
  display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
  padding: 12px 18px; border-bottom: 1px solid var(--sh-line);
}
.act-bar .inp { min-width: 0; flex: 1 1 180px; }
.act-bar .inp.narrow { flex: 0 0 108px; min-width: 0; }
.act-bar .msg { font-size: 12.5px; color: var(--sh-faint); flex-basis: 100%; }
.act-bar .msg.bad { color: var(--sh-bad); }
.act-bar .msg.ok { color: var(--sh-ok); }

select.inp { cursor: pointer; }

.patch {
  margin: 8px 0 0; padding: 12px 14px; border-radius: 8px; max-height: 320px;
  overflow: auto; font-family: var(--sh-mono); font-size: 12px; line-height: 1.55;
  background: rgba(0, 0, 0, .28); border: 1px solid var(--sh-line);
  color: var(--sh-dim); white-space: pre;
}

.switch.danger { color: var(--sh-bad); border-color: color-mix(in srgb, var(--sh-bad) 40%, transparent); }
.switch.danger:hover { border-color: var(--sh-bad); color: var(--sh-bad); }
/* Destructive actions stay visually secondary through their compact shape,
   never by reducing text contrast below the readable threshold. */
.line .kill { opacity: 1; background: transparent; }

/* ---- trading ------------------------------------------------------------ */

.sym-pick {
  margin-left: auto; font: inherit; font-family: var(--sh-mono); font-size: 14px;
  padding: 9px 14px; border-radius: 10px; color: var(--gold-bright);
  background: color-mix(in srgb, var(--gold) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--gold) 38%, transparent);
}
.guide-picks {
  margin-left: auto; display: flex; align-items: flex-end; justify-content: flex-end;
  gap: 9px; flex-wrap: wrap;
}
.guide-control {
  display: grid; gap: 6px; min-width: 150px;
  color: var(--sh-faint); font-size: 10px; letter-spacing: .11em;
  text-transform: uppercase;
}
.guide-control:first-child { min-width: 210px; }
.guide-control .sym-pick { width: 100%; margin-left: 0; text-transform: none; letter-spacing: 0; }
#v-guide .page-head { flex-wrap: wrap; }

@media (max-width: 620px) {
  .guide-picks { width: 100%; margin-left: 0; justify-content: stretch; }
  .guide-control, .guide-control:first-child { flex: 1 1 180px; min-width: 0; }
}
.spark { width: 100%; height: 96px; margin-top: auto; display: block; overflow: visible; }
.spark polyline { fill: none; stroke: var(--gold); stroke-width: 2; vector-effect: non-scaling-stroke; }
.spark polygon { fill: color-mix(in srgb, var(--gold) 14%, transparent); }
.spark.down polyline { stroke: var(--sh-bad); }
.spark.down polygon { fill: color-mix(in srgb, var(--sh-bad) 14%, transparent); }
/* The monitor's charts. Taller because they carry a fixed 0–100% axis rather
   than a price wiggle, and a squat box makes the difference between an idle
   machine and a busy one look like noise. */
.spark.tall { height: 160px; }
/* Drawn as lines rather than text: preserveAspectRatio="none" stretches the
   viewBox to the panel width, which would smear any label inside the SVG.
   The numbers live in the reading line underneath, where they stay legible. */
.spark .grid { stroke: var(--sh-line); stroke-width: 1;
               vector-effect: non-scaling-stroke; opacity: 0.55; }

/* ---- funnel -------------------------------------------------------------- */

.funnel { display: flex; gap: 10px; flex-wrap: wrap; }
.funnel .stage {
  flex: 1 1 120px; padding: 14px 16px; border-radius: 10px;
  border: 1px solid var(--sh-line); background: rgba(255, 255, 255, .025);
}
.funnel .stage b { display: block; font-family: var(--sh-mono); font-size: 26px; }
.funnel .stage span { font-size: 11.5px; letter-spacing: .1em; text-transform: uppercase;
                      color: var(--sh-dim); }
.funnel .stage.bad { border-color: color-mix(in srgb, var(--sh-bad) 40%, transparent); }
.funnel .stage.bad b { color: var(--sh-bad); }
.funnel .stage.lit { border-color: color-mix(in srgb, var(--gold) 40%, transparent); }
.funnel .stage.lit b { color: var(--gold-bright); }

.accent-row { display: flex; gap: 8px; }
.accent-dot {
  width: 26px; height: 26px; border-radius: 50%; border: 2px solid transparent;
  cursor: pointer; padding: 0;
}
.accent-dot.on { border-color: var(--sh-text); }

/* ---- rendered markdown --------------------------------------------------- */

.doc { max-height: 74vh; overflow-y: auto; line-height: 1.62; font-size: 14.5px; }
.doc h1 { font-size: 26px; margin: 22px 0 10px; }
.doc h2 { font-size: 20px; margin: 26px 0 8px; color: var(--gold-bright); }
.doc h3 { font-size: 16px; margin: 20px 0 6px; }
.doc p, .doc li { color: var(--sh-text); }
.doc ul { padding-left: 20px; margin: 8px 0; }
.doc code {
  font-family: var(--sh-mono); font-size: 12.5px; padding: 2px 5px;
  border-radius: 4px; background: rgba(255, 255, 255, .06); color: var(--gold-bright);
}
.doc pre {
  background: rgba(255, 255, 255, .04); border: 1px solid var(--sh-line);
  border-radius: 8px; padding: 12px 14px; overflow-x: auto;
}
.doc pre code { background: none; padding: 0; color: var(--sh-text); }
.doc table { border-collapse: collapse; width: 100%; min-width: 560px; margin: 12px 0; }
.doc th, .doc td { border: 1px solid var(--sh-line); padding: 7px 10px; text-align: left; font-size: 13.5px; }
.doc th { color: var(--sh-dim); font-weight: 600; }
.doc hr { border: 0; border-top: 1px solid var(--sh-line); margin: 22px 0; }
.doc a { color: var(--gold-bright); }

.sev {
  width: 3px; align-self: stretch; border-radius: 2px; background: var(--sh-warn);
}
.sev.high { background: var(--sh-bad); box-shadow: 0 0 10px var(--sh-bad); }

/* ---- views -------------------------------------------------------------- */

.view { display: none; }
.view.on { display: block; }

/* Every breakpoint on this page used to read the window, and the window does
 * not change when you collapse the rail — the pane does, by 200px. So a screen
 * laid out for an expanded rail stayed in that layout after the rail closed,
 * and the width it freed went to the gutter instead of to a column: two bento
 * cards where four now fit, one field per row on a pane wide enough for three.
 * A container query measures the pane, so collapsing the rail is a real layout
 * change on every screen rather than a wider margin.
 *
 * Declared on .view and not on main.page because container-type carries layout
 * containment, which would make the container the containing block for any
 * position:fixed descendant — and #v-chat is exactly that, inset against the
 * viewport. Containing .view itself is harmless: containment applies to what is
 * inside an element, never to the element's own positioning. */
.view { container: pane / inline-size; }

/* The chat is the existing PWA, framed rather than rewritten. Reimplementing
   streaming, approvals, Live mode, wake-word and gestures inside this shell
   would risk all of it to gain a shared scrollbar. */
#v-chat { position: fixed; inset: 62px 0 0 var(--sh-rail); display: none; flex-direction: row; }
#v-chat.on { display: flex; }

/* Chat sessions sidebar */
.chat-side {
  width: 220px;
  flex-shrink: 0;
  background: var(--sh-deep);
  border-right: 1px solid var(--sh-line);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  padding: 10px 8px;
  gap: 6px;
}
.chat-new-btn {
  display: flex;
  align-items: center;
  gap: 7px;
  width: 100%;
  padding: 8px 10px;
  border-radius: 8px;
  border: 1px solid var(--sh-line);
  background: var(--sh-panel);
  color: var(--sh-text);
  font-family: var(--font-display);
  font-size: 13px;
  cursor: pointer;
  transition: background .15s, border-color .15s;
}
.chat-new-btn:hover { background: var(--sh-panel-hi); border-color: var(--gold); color: var(--gold); }
.chat-side-label {
  font-family: var(--sh-mono);
  font-size: 10px;
  letter-spacing: .1em;
  color: var(--sh-faint);
  padding: 6px 4px 2px;
  text-transform: uppercase;
}
.chat-session-list {
  flex: 1;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.chat-sess-item {
  display: flex;
  align-items: center;
  padding: 7px 8px;
  border-radius: 6px;
  cursor: pointer;
  color: var(--sh-dim);
  font-size: 12.5px;
  border: 1px solid transparent;
  transition: background .12s, color .12s, border-color .12s;
  gap: 6px;
}
.chat-sess-item:hover { background: var(--sh-panel); color: var(--sh-text); }
.chat-sess-item.active { background: var(--sh-panel); border-color: var(--sh-line); color: var(--sh-text); }
.chat-sess-title { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chat-sess-del {
  flex-shrink: 0;
  opacity: 0;
  background: none;
  border: 0;
  color: var(--sh-faint);
  cursor: pointer;
  padding: 2px;
  transition: opacity .12s, color .12s;
  display: flex;
  align-items: center;
}
.chat-sess-item:hover .chat-sess-del { opacity: 1; }
.chat-sess-del:hover { color: var(--sh-bad); }

#chatFrame { flex: 1; height: 100%; border: 0; display: block; min-width: 0; }

/* Settings and the Binance panel are the same PWA mounted as a page rather
   than a chat (see index.html's ?panel= flag). They scroll with this page, not
   inside themselves, so the height is set from the frame's own content once it
   reports back — a fixed height would either clip the drawer or leave a gap. */
.panel-frame {
  width: 100%; border: 0; display: block; margin-top: 16px;
  min-height: 520px; background: transparent;
  /* Do NOT add `transition: height` here. The first measurement lands before
     the panel's async fills do (Binance limits, the environment, the
     scheduler), so on first open the frame is briefly about half its final
     size and then snaps — 1388px -> 2867px, measured. Easing that snap looks
     like the obvious fix and breaks the panel: mountPanel sets the height
     while the view is still display:none, the transition therefore never
     starts, and the computed height stays at the old value while
     style.height already reads the new one. Observed stuck at a rendered
     1388px against a style of 2867px — half the settings page unreachable.
     The snap is cosmetic; that is not. */
}
.panel-frame.tall { min-height: 720px; }

/* ---- responsive --------------------------------------------------------- */

/* Pane widths, not window widths — see the container declaration on .view.
 * The numbers are the old ones minus the furniture: 1180px of window with the
 * rail out and 26px of page padding each side is ~860px of pane, and 780px of
 * window (where the rail leaves the grid) is ~730px. Collapsing the rail now
 * crosses these thresholds, which is the whole point of them. */
@container pane (max-width: 880px) {
  .bento, .bento.cols-3 { grid-template-columns: repeat(2, 1fr); }
  /* A three-column child on a two-column grid overflows its own container. */
  .bento > .span3 { grid-column: span 2; }
  .row2 { grid-template-columns: 1fr; }
}
@container pane (max-width: 620px) {
  .bento, .bento.cols-3 { grid-template-columns: 1fr; }
  .bento > .wide, .bento > .span3 { grid-column: span 1; }
}
/* The rail and the topbar are not in the pane, so these stay on the window. */
@media (max-width: 780px) {
  .shell-grid { grid-template-columns: 1fr; }
  .rail { position: fixed; z-index: 40; width: var(--sh-rail); transform: translateX(-100%);
          transition: transform .2s; }
  .rail.open { transform: none; }
  .rail-burger { display: grid; }
  .stat-strip { display: none; }
}
@media (max-width: 780px) and (prefers-reduced-motion: reduce) {
  .rail { transition: none; }
}

/* A continuation line that belongs to the row above it: the detail behind a
   headline reading. Dimmer and tighter, and it carries no bottom rule so the
   pair reads as one entry rather than two. */
.line.sub {
  border-bottom: 0; padding-top: 0; margin-top: -6px;
  font-size: 12px; opacity: 0.72;
}
.line.sub .grow { white-space: normal; }

/* ---- command palette ----------------------------------------------------- *
 *
 * Twenty-eight destinations in a rail you have to scroll is a list you find
 * things in by scrolling. ⌘K jumps straight to one by name.
 *
 * Every colour here comes from the same variables the rest of the shell uses,
 * so the palette recolours with the mode picker. Hard-coding the accent would
 * have made this the one surface that stayed gold in cyan mode. */

.cmdk {
  position: fixed; inset: 0; z-index: 200;
  display: flex; justify-content: center; align-items: flex-start;
  /* Not centred vertically: the box grows downwards as results appear, and a
     centred box would slide up the screen on every keystroke. */
  padding: 12vh 16px 16px;
  background: color-mix(in srgb, var(--sh-deep) 74%, transparent);
  backdrop-filter: blur(6px);
}
.cmdk[hidden] { display: none; }

.cmdk-box {
  width: min(620px, 100%);
  display: flex; flex-direction: column;
  background: var(--sh-panel-hi);
  border: 1px solid color-mix(in srgb, var(--gold) 30%, var(--sh-line));
  border-radius: 14px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.6),
              0 0 0 1px rgba(255, 255, 255, 0.03) inset;
  overflow: hidden;
}

.cmdk-input {
  border: 0; border-bottom: 1px solid var(--sh-line);
  background: transparent; color: var(--sh-text);
  font: 16px/1.4 var(--font-display), system-ui, sans-serif;
  padding: 16px 18px; outline: none;
}
.cmdk-input::placeholder { color: var(--sh-faint); }

.cmdk-list { max-height: 46vh; overflow-y: auto; padding: 6px; }

/* The group heading repeats the rail's own grouping, so a result found here
   tells you where it lives there. */
.cmdk-group {
  font-size: 10px; letter-spacing: 0.12em; color: var(--sh-faint);
  padding: 10px 12px 4px;
}

.cmdk-item {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 12px; border-radius: 8px; cursor: pointer;
  font-size: 14px; color: var(--sh-text);
}
.cmdk-item:hover { background: rgba(255, 255, 255, 0.04); }
/* The keyboard cursor. Distinct from :hover, because the mouse pointer resting
   somewhere must not look like the row Enter would open. */
.cmdk-item.on {
  background: color-mix(in srgb, var(--gold) 16%, transparent);
  box-shadow: inset 2px 0 0 var(--gold);
}
.cmdk-item .grow { flex: 1; white-space: nowrap; overflow: hidden;
                   text-overflow: ellipsis; }
.cmdk-item .cmdk-grp { font-size: 10px; color: var(--sh-faint);
                       letter-spacing: 0.08em; }
.cmdk-item svg { width: 15px; height: 15px; opacity: 0.7; flex: none; }

.cmdk-empty { padding: 22px 14px; color: var(--sh-dim); font-size: 13px;
              text-align: center; }

.cmdk-foot {
  display: flex; align-items: center; gap: 14px;
  padding: 8px 14px; border-top: 1px solid var(--sh-line);
  font-size: 11px; color: var(--sh-faint);
}
.cmdk-foot .grow { flex: 1; }
.cmdk-foot kbd {
  font-family: var(--sh-mono); font-size: 10px;
  border: 1px solid var(--sh-line); border-radius: 4px;
  padding: 1px 5px; margin-right: 3px; color: var(--sh-dim);
}

/* ---- risk dock ----------------------------------------------------------- *
 *
 * Pinned bottom-right, above everything except the palette. It exists because
 * a trading halt is worth knowing about from the screen you are on, not from
 * the screen it is filed under.
 *
 * Sized in ch and vh rather than fixed pixels so a long halt reason wraps
 * instead of pushing the dismiss button off the edge. */

.dock {
  position: fixed; right: 16px; bottom: 16px; z-index: 150;
  width: min(340px, calc(100vw - 32px));
  display: flex; flex-direction: column;
  background: color-mix(in srgb, var(--sh-deep) 97%, transparent);
  backdrop-filter: blur(14px);
  border: 1px solid color-mix(in srgb, var(--gold) 22%, var(--sh-line));
  border-radius: 14px; overflow: hidden;
  box-shadow: 0 18px 48px rgba(0, 0, 0, 0.55);
}
.dock[hidden] { display: none; }
/* Any high-severity item repaints the whole frame red. The severity of the
   worst item is the only thing worth reading from across the room. */
.dock.urgent { border-color: color-mix(in srgb, var(--sh-bad) 45%, transparent); }

.dock-head {
  display: flex; align-items: center; gap: 8px;
  padding: 9px 11px; cursor: pointer; user-select: none;
  background: color-mix(in srgb, var(--sh-panel-hi) 55%, transparent);
  border-bottom: 1px solid var(--sh-line);
}
.dock.urgent .dock-head { background: color-mix(in srgb, var(--sh-bad) 12%, transparent); }
.dock-head:focus-visible { outline: 2px solid var(--gold); outline-offset: -2px; }

.dock-bell { position: relative; display: flex; }
.dock-bell svg { width: 15px; height: 15px; color: var(--gold); }
.dock.urgent .dock-bell svg { color: var(--sh-bad); }
.dock-count {
  position: absolute; top: -5px; right: -6px;
  min-width: 14px; height: 14px; padding: 0 3px;
  border-radius: 8px; background: var(--sh-warn); color: #0b0f18;
  font: 700 9px/14px var(--sh-mono); text-align: center;
}
.dock.urgent .dock-count { background: var(--sh-bad); color: #fff; }

.dock-title { font-size: 11px; letter-spacing: 0.14em; color: var(--sh-text); }
.dock.urgent .dock-title { color: var(--sh-bad); }
.dock-chev { color: var(--sh-faint); font-size: 11px; }
.dock.folded .dock-body { display: none; }
.dock.folded .dock-chev { transform: rotate(-90deg); display: inline-block; }

.dock-btn {
  background: none; border: 1px solid var(--sh-line); border-radius: 6px;
  color: var(--sh-dim); font: 10px/1 var(--sh-mono); letter-spacing: 0.06em;
  padding: 4px 7px; cursor: pointer;
}
.dock-btn:hover { color: var(--sh-text); border-color: var(--gold); }
.dock-btn.on { color: var(--sh-warn); border-color: var(--sh-warn); }

.dock-list { max-height: 44vh; overflow-y: auto; }

.dock-item {
  display: flex; gap: 8px; padding: 9px 11px;
  border-bottom: 1px solid color-mix(in srgb, var(--sh-line) 60%, transparent);
}
.dock-item:last-child { border-bottom: 0; }
/* The severity tint is on the row, not on a chip in the corner: a scanning
   eye reads the block of colour long before it reads the label. */
.dock-item.high { background: color-mix(in srgb, var(--sh-bad) 11%, transparent); }
.dock-item.medium { background: color-mix(in srgb, var(--sh-warn) 10%, transparent); }
.dock-item.low { background: color-mix(in srgb, var(--gold) 8%, transparent); }
.dock-item .bar { width: 2px; border-radius: 2px; background: var(--sh-dim); flex: none; }
.dock-item.high .bar { background: var(--sh-bad); }
.dock-item.medium .bar { background: var(--sh-warn); }
.dock-item.low .bar { background: var(--gold); }
.dock-item .body { flex: 1; min-width: 0; }
.dock-item .kind {
  font: 9px/1.4 var(--sh-mono); letter-spacing: 0.1em;
  color: var(--sh-faint); text-transform: uppercase;
}
.dock-item .what { font-size: 12.5px; color: var(--sh-text); margin: 1px 0; }
.dock-item .why { font-size: 11px; color: var(--sh-dim); }
.dock-item .acts { display: flex; gap: 5px; margin-top: 6px; flex-wrap: wrap; }
.dock-item .x {
  background: none; border: 0; color: var(--sh-faint); cursor: pointer;
  font-size: 13px; line-height: 1; padding: 0 2px; flex: none;
}
.dock-item .x:hover { color: var(--sh-text); }

.dock-foot {
  display: flex; align-items: center; gap: 8px;
  padding: 7px 11px; border-top: 1px solid var(--sh-line);
  background: color-mix(in srgb, var(--sh-panel) 60%, transparent);
}
.dock-foot .msg { font-size: 10px; }
.dock-empty { padding: 18px 12px; text-align: center;
              font-size: 11.5px; color: var(--sh-dim); }

/* ---- toasts -------------------------------------------------------------- *
 *
 * Bottom centre, clear of the dock on the right and the rail on the left.
 * They announce; they never carry the only copy of anything actionable. */

.toasts {
  position: fixed; left: 50%; bottom: 16px; transform: translateX(-50%);
  z-index: 300; display: flex; flex-direction: column-reverse;
  gap: 8px; align-items: center; pointer-events: none;
}
.toast {
  pointer-events: auto;
  display: flex; align-items: flex-start; gap: 10px;
  min-width: 260px; max-width: min(380px, calc(100vw - 32px));
  padding: 10px 13px; border-radius: 12px;
  background: color-mix(in srgb, var(--sh-panel) 97%, transparent); backdrop-filter: blur(14px);
  border: 1px solid var(--sh-line);
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.55);
  /* Starts off-screen to the right and slides in; the class is added on the
     next frame so the transition has two states to move between. */
  opacity: 0; transform: translateY(8px);
  transition: opacity 220ms ease, transform 220ms ease;
}
.toast.in { opacity: 1; transform: translateY(0); }
.toast.ok { border-color: color-mix(in srgb, var(--sh-ok) 45%, transparent); }
.toast.bad { border-color: color-mix(in srgb, var(--sh-bad) 45%, transparent); }
.toast.warn { border-color: color-mix(in srgb, var(--sh-warn) 45%, transparent); }
.toast.info { border-color: color-mix(in srgb, var(--gold) 40%, transparent); }
.toast .dot { width: 7px; height: 7px; border-radius: 50%; margin-top: 5px; flex: none;
              background: var(--gold); }
.toast.ok .dot { background: var(--sh-ok); }
.toast.bad .dot { background: var(--sh-bad); }
.toast.warn .dot { background: var(--sh-warn); }
.toast .body { flex: 1; min-width: 0; }
.toast .t { font-size: 13px; color: var(--sh-text); }
.toast .m { font-size: 11.5px; color: var(--sh-dim); margin-top: 2px; }
.toast .x { background: none; border: 0; color: var(--sh-faint);
            cursor: pointer; font-size: 13px; line-height: 1; padding: 0 2px; }

/* On a phone the dock would cover most of the screen, so it sits flush across
   the bottom and gives up less height to the list. */
@media (max-width: 560px) {
  .dock { left: 8px; right: 8px; bottom: 8px; width: auto; }
  .dock-list { max-height: 34vh; }
}

@media (prefers-reduced-motion: reduce) {
  .toast, .nav-group-chevron { transition: none; }
}

/* ---- risk console -------------------------------------------------------- *
 *
 * The limits screen is a form, not a report. Each guardrail gets a labelled
 * row with a slider and a number box wired to the same value, so a limit can
 * be dragged roughly into place or typed exactly — and the ends of the range
 * are printed, because the operator is allowed to reach them.
 */

.risk-bar {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 12px 18px; border-bottom: 1px solid var(--sh-line);
}
.risk-bar .grow { flex: 1; }

.risk-row { padding: 16px 0; border-bottom: 1px solid rgba(255, 255, 255, .045); }
.risk-row:last-child { border-bottom: 0; }
/* An edited-but-unsaved row is marked on its leading edge rather than by a
   background wash, so a screen with every field touched stays readable. */
.risk-row.dirty { box-shadow: inset 2px 0 0 var(--gold); padding-left: 12px; }
.risk-head { display: flex; align-items: center; gap: 8px; }
.risk-label { font-size: 14.5px; font-weight: 600; }
.risk-help {
  margin: 4px 0 10px; font-size: 12.5px; line-height: 1.5;
  color: var(--sh-faint); max-width: 66ch; text-wrap: pretty;
}
.risk-ctl { display: flex; align-items: center; gap: 12px; }
.risk-num {
  min-width: 0; width: 110px; text-align: right;
  font-variant-numeric: tabular-nums;
}
.risk-unit {
  font-family: var(--sh-mono); font-size: 12px; color: var(--sh-dim);
  min-width: 58px;
}
.risk-scale {
  display: flex; justify-content: space-between; gap: 12px; margin-top: 8px;
  font-family: var(--sh-mono); font-size: 11px; color: var(--sh-faint);
  font-variant-numeric: tabular-nums;
}
.switch.tiny { padding: 3px 8px; font-size: 10px; letter-spacing: .08em; }

.risk-range {
  flex: 1; min-width: 120px; height: 4px; appearance: none; -webkit-appearance: none;
  border-radius: 2px; background: rgba(255, 255, 255, .1); cursor: pointer;
}
.risk-range::-webkit-slider-thumb {
  appearance: none; -webkit-appearance: none; width: 14px; height: 14px;
  border-radius: 50%; background: var(--gold); border: 0; cursor: pointer;
  box-shadow: 0 0 10px color-mix(in srgb, var(--gold) 55%, transparent);
}
.risk-range::-moz-range-thumb {
  width: 14px; height: 14px; border-radius: 50%; background: var(--gold);
  border: 0; cursor: pointer;
}
.risk-range:focus-visible { outline: 2px solid var(--gold); outline-offset: 4px; }

/* A toggle list where the state is the whole control — used for the symbol
   whitelist, where a checkbox column would read as a form to submit rather
   than a switch that takes effect on click. */
.chips { display: flex; flex-wrap: wrap; gap: 8px; }
.chip {
  font: inherit; font-size: 12px; font-family: var(--sh-mono); cursor: pointer;
  padding: 6px 12px; border-radius: 999px; background: none;
  border: 1px solid var(--sh-line); color: var(--sh-faint);
  transition: border-color .18s ease, color .18s ease, background .18s ease;
}
.chip:hover { color: var(--sh-text); border-color: color-mix(in srgb, var(--gold) 45%, transparent); }
.chip.on {
  color: var(--gold); border-color: color-mix(in srgb, var(--gold) 55%, transparent);
  background: color-mix(in srgb, var(--gold) 10%, transparent);
}
.chip:active { transform: translateY(1px); }
/* The whitelist is drawn from Binance's whole USDT listing, so the panel needs
   a filter and a ceiling — several hundred chips would otherwise push
   everything below them off the screen. */
.rk-sym-search {
  width: 100%; margin-bottom: 10px; padding: 8px 11px;
  font: inherit; font-size: 12px; font-family: var(--sh-mono);
  color: var(--sh-text); background: none;
  border: 1px solid var(--sh-line); border-radius: 8px;
}
.rk-sym-search:focus {
  outline: none;
  border-color: color-mix(in srgb, var(--gold) 55%, transparent);
}
#rkSymbols .chips { max-height: 168px; overflow-y: auto; margin-bottom: 8px; }
.kpi.warn .kpi-num { color: var(--sh-warn); }

@media (prefers-reduced-motion: reduce) {
  .chip { transition: none; }
}

/* ---- tabs ---------------------------------------------------------------- *
 *
 * Four sections of one screen rather than four sidebar rows: they are all
 * answers to "who is this for and what is it connected to", and splitting them
 * across the nav is how the sidebar got long enough to need pruning.
 */

.tabs {
  display: flex; gap: 4px; flex-wrap: wrap; margin-bottom: 18px;
  padding: 4px; border-radius: 12px; width: fit-content;
  background: rgba(255, 255, 255, .03); border: 1px solid var(--sh-line);
}
.tab {
  font: inherit; font-size: 13px; cursor: pointer; padding: 8px 16px;
  border: 0; border-radius: 8px; background: none; color: var(--sh-dim);
  transition: color .18s ease, background .18s ease;
}
.tab:hover { color: var(--sh-text); }
.tab.on {
  color: var(--on-gold, #201400); background: var(--gold); font-weight: 600;
}
.tab:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.tab-pane { display: none; }
.tab-pane.on { display: block; }

/* ---- labelled form fields ------------------------------------------------- */

.field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px; max-width: 560px; }
.field label {
  font-size: 11.5px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--sh-faint);
}
.field .inp { width: 100%; }
.inp.wide { min-width: 0; width: 100%; }
/* A minutes box has a known width; letting it flex to 190px like the free-text
   inputs beside it makes a two-digit number look like a missing field. */
.form-row .inp.narrow { flex: 0 0 108px; min-width: 0; }
/* A textarea inherits the .inp border but not its single-line height. */
textarea.inp { min-height: 84px; resize: vertical; line-height: 1.5; }

/* ---- structured trading alerts ------------------------------------------ */

.alert-config-grid {
  display: grid;
  grid-template-columns: minmax(240px, 2fr) repeat(5, minmax(130px, 1fr));
  gap: 10px;
  align-items: end;
}
.alert-config-grid .field { max-width: none; margin: 0; }
.alert-condition-head {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  margin-top: 20px; padding-bottom: 9px; border-bottom: 1px solid var(--sh-line);
}
.alert-condition-head .panel-note { margin-top: 4px; }
.alert-conditions { display: grid; }
.alert-condition {
  display: grid;
  grid-template-columns: minmax(150px, 1.2fr) minmax(92px, .7fr)
                         minmax(130px, 1fr) minmax(110px, .8fr)
                         minmax(110px, .8fr) auto;
  gap: 8px; align-items: end; padding: 12px 0;
  border-bottom: 1px solid var(--sh-line);
}
.alert-condition .field { max-width: none; margin: 0; }
.alert-condition-remove { margin-bottom: 1px; }
.alert-submit-row { margin-top: 14px; }
.alert-submit-row .primary { margin-left: auto; }
.alert-values { margin-top: 6px; color: var(--sh-faint); font-size: 11.5px; }

@media (max-width: 1180px) {
  .alert-config-grid { grid-template-columns: repeat(3, minmax(150px, 1fr)); }
  .alert-name-field { grid-column: span 2; }
  .alert-condition { grid-template-columns: repeat(3, minmax(120px, 1fr)); }
}
@media (max-width: 720px) {
  .alert-config-grid, .alert-condition { grid-template-columns: 1fr; }
  .alert-name-field { grid-column: auto; }
  .alert-condition-head { align-items: flex-start; flex-direction: column; }
  .alert-condition-remove { justify-self: start; }
  .alert-submit-row .primary { margin-left: 0; width: 100%; }
}

/* Opt-in two-column form. .field caps itself at 560px so a column of short
   inputs does not stretch to the width of a full-bleed panel — correct for the
   line length, wrong for the panel, which was then half empty with the Save
   button pushed under the fold. Grid puts the pairs side by side and lets the
   long ones span; the field's own max-width still governs each cell.
   Opt-in rather than global: most panels here hold one or two fields, where a
   second column would only leave a hole. */
.field-grid {
  display: grid;
  /* auto-fill rather than a hard two: a fixed count plus a max-width meant the
     width a collapsed rail hands back became margin, because two columns of
     520px is two columns of 520px whatever the pane does. Now the pane decides
     how many fit. The 360px floor is what keeps a wide pane from producing six
     narrow boxes, and the 1fr ceiling replaces the old max-width — four columns
     of 380px rather than two of 740, which was a lot of box for a time zone. */
  grid-template-columns: repeat(auto-fill, minmax(360px, 1fr));
  column-gap: 28px; align-items: start;
}
.field-grid > .field { max-width: none; }
.field-grid > .span2 { grid-column: 1 / -1; max-width: 100%; }

/* ---- modal ------------------------------------------------------------------
 *
 * Built on the command palette's surface rather than a second one: the same
 * dimmed field, the same accent-tinted hairline, the same 14px radius. A
 * dialog that introduced its own card styling would be the one place on this
 * page that didn't look like this page.
 *
 * Centred vertically, unlike .cmdk — this box has a fixed set of fields and
 * doesn't grow as you type, so there is nothing to slide out from under the
 * cursor. */

.modal {
  position: fixed; inset: 0; z-index: 220;
  display: flex; justify-content: center; align-items: center;
  padding: 24px 16px;
  background: color-mix(in srgb, var(--sh-deep) 74%, transparent);
  backdrop-filter: blur(6px);
}
.modal[hidden] { display: none; }

.modal-box {
  width: min(560px, 100%);
  max-height: calc(100dvh - 48px);
  display: flex; flex-direction: column;
  background: var(--sh-panel-hi);
  border: 1px solid color-mix(in srgb, var(--gold) 30%, var(--sh-line));
  border-radius: 14px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.6),
              0 0 0 1px rgba(255, 255, 255, 0.03) inset;
  overflow: hidden;
}

.modal-head {
  display: flex; align-items: center; gap: 12px;
  padding: 18px 20px 14px; border-bottom: 1px solid var(--sh-line);
}
.modal-title { margin: 0; font-size: 18px; font-weight: 600; letter-spacing: -0.01em; }
.modal-x {
  margin-left: auto; background: transparent; border: 0; cursor: pointer;
  color: var(--sh-faint); font-size: 15px; line-height: 1; padding: 6px 8px;
  border-radius: 8px; transition: color .18s ease, background .18s ease;
}
.modal-x:hover { color: var(--sh-text); background: rgba(255, 255, 255, .05); }
.modal-x:active { transform: translateY(1px); }

/* The body scrolls, not the page behind it: opening Advanced settings on a
   short window must not push the Add button off the bottom of the box. */
.modal-body { padding: 18px 20px 6px; overflow-y: auto; }

.modal-lede { margin: 0 0 18px; font-size: 13.5px; line-height: 1.55; color: var(--sh-dim); }
.modal-lede .mono { font-size: 12.5px; color: var(--sh-text); }

.modal-box .field { max-width: none; }
.field-hint { font-size: 12px; line-height: 1.5; color: var(--sh-faint); }
.modal-box .field label em {
  font-style: normal; text-transform: none; letter-spacing: 0;
  color: var(--sh-faint); opacity: .8; margin-left: 6px;
}

.adv { margin: 4px 0 16px; border-top: 1px solid var(--sh-line); padding-top: 12px; }
.adv-head {
  cursor: pointer; list-style: none; font-size: 13px; color: var(--sh-dim);
  display: flex; align-items: center; gap: 8px;
  transition: color .18s ease;
}
.adv-head::-webkit-details-marker { display: none; }
.adv-head::before {
  content: "›"; display: inline-block; font-size: 15px; color: var(--sh-faint);
  transition: transform .18s ease;
}
.adv[open] .adv-head::before { transform: rotate(90deg); }
.adv-head:hover { color: var(--sh-text); }
.adv-body { padding-top: 14px; }
.adv-body .field-hint { display: block; margin-bottom: 14px; }

.modal-warn {
  margin: 0 0 4px; font-size: 12.5px; line-height: 1.55; color: var(--sh-faint);
  border-left: 2px solid color-mix(in srgb, var(--sh-warn) 55%, transparent);
  padding-left: 12px;
}

/* Inline, above the buttons that caused it — the shell has no alert() anywhere
   and a dialog is exactly where one would otherwise creep back in. */
.modal-error {
  margin: 16px 0 0; font-size: 13px; line-height: 1.5; color: var(--sh-bad);
  background: color-mix(in srgb, var(--sh-bad) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--sh-bad) 32%, transparent);
  border-radius: 8px; padding: 10px 12px;
}
.modal-error[hidden] { display: none; }

.modal-foot {
  display: flex; justify-content: flex-end; gap: 8px;
  padding: 16px 20px; border-top: 1px solid var(--sh-line);
  background: rgba(255, 255, 255, .015);
}

/* A connector row carries four actions, which on a narrow window is wider than
   the name beside them. Wrapping keeps the buttons on the row rather than
   squeezing the name to an ellipsis. */
.line.conn { flex-wrap: wrap; row-gap: 8px; }
.line.conn .grow { flex: 1 1 220px; }
.line.conn .switch { padding: 4px 10px; font-size: 12px; }

/* Column labels for the connector list. A header only earns its line when there
   are rows under it, so it is drawn with the list rather than sitting in the
   markup above an empty state. */
.line.conn-head {
  padding-bottom: 6px; border-bottom: 1px solid var(--sh-line);
  font-size: 10.5px; letter-spacing: .10em; text-transform: uppercase;
  color: var(--sh-faint);
}
.line.conn-head .col { flex: 0 0 92px; text-align: center; }
.line.conn .col-auth, .line.conn .col-state { flex: 0 0 92px; text-align: center; }
.line.conn .col-auth .tag, .line.conn .col-state .tag { width: 100%; }

/* Columns need a row wide enough to hold them. Below that the row wraps, and a
   header sitting above wrapped rows labels nothing — it points at whatever
   happens to land under it, which is worse than no header. So under the
   breakpoint the table becomes the plain wrapped list it was before. */
@media (max-width: 760px) {
  .line.conn-head { display: none; }
  .line.conn .col-auth, .line.conn .col-state { flex: 0 0 auto; }
  .line.conn .col-auth .tag, .line.conn .col-state .tag { width: auto; }
}

/* Add ▾ — the menu is positioned against the button, not the panel, so it
   stays attached when the panel head reflows on a narrow window. */
.menu-wrap { position: relative; display: inline-flex; }
/* "Add ▾" is two glyphs and a space; letting it wrap turns the button into a
   two-line block that shoves the panel note off the head. */
#connAdd { white-space: nowrap; }
.menu {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 40;
  min-width: 208px; padding: 5px;
  background: var(--sh-panel-hi);
  border: 1px solid color-mix(in srgb, var(--gold) 26%, var(--sh-line));
  border-radius: 11px;
  box-shadow: 0 16px 40px rgba(0, 0, 0, .55);
}
.menu[hidden] { display: none; }
.menu-item {
  display: block; width: 100%; text-align: left;
  padding: 8px 11px; border: 0; border-radius: 7px;
  background: transparent; color: var(--sh-dim);
  font: inherit; font-size: 13px; cursor: pointer;
  transition: background .16s ease, color .16s ease;
}
.menu-item:hover { background: rgba(255, 255, 255, .05); color: var(--sh-text); }
.menu-item:focus-visible { outline: 2px solid var(--gold); outline-offset: -2px; }
.menu-item:active { transform: translateY(1px); }

/* Browse. Two columns so a blurb has room to be a sentence — three made every
   card a truncated label, which is the thing the list exists to avoid. */
.modal-box.wide { width: min(760px, 100%); }
.modal-box.compact { width: min(500px, 100%); }
.credential-link {
  display: inline-flex; margin: 2px 0 14px; color: var(--sh-dim);
  font-size: 12.5px; text-decoration: none;
  border-bottom: 1px solid var(--sh-line);
}
.credential-link:hover { color: var(--sh-text); border-color: var(--gold); }
.credential-link[hidden] { display: none; }
.cat-tools {
  display: grid; grid-template-columns: minmax(0, 1fr) 190px;
  gap: 10px; margin-bottom: 12px;
}
.cat-tools .inp { width: 100%; min-width: 0; }
.cat-grid { display: grid; gap: 10px; grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (max-width: 620px) {
  .cat-tools, .cat-grid { grid-template-columns: 1fr; }
}
.cat-empty { grid-column: 1 / -1; }
.cat-card {
  display: flex; flex-direction: column; gap: 7px;
  padding: 13px 14px; border-radius: 11px;
  border: 1px solid var(--sh-line);
  background: rgba(255, 255, 255, .015);
  transition: border-color .18s ease;
}
.cat-card:hover { border-color: color-mix(in srgb, var(--gold) 34%, var(--sh-line)); }
.cat-top { display: flex; align-items: center; gap: 8px; }
.cat-name { font-size: 14px; font-weight: 600; }
.cat-vendor { font-size: 11.5px; color: var(--sh-faint); }
.cat-top .tag { margin-left: auto; }
.cat-blurb { font-size: 12.5px; line-height: 1.5; color: var(--sh-dim); text-wrap: pretty; }
.cat-url {
  font-family: var(--sh-mono); font-size: 11px; color: var(--sh-faint);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cat-foot { display: flex; align-items: center; gap: 8px; margin-top: auto; padding-top: 4px; }
.cat-foot .switch { padding: 4px 12px; font-size: 12px; }
.cat-category { font-size: 11px; color: var(--sh-faint); }
.cat-doc {
  color: var(--sh-dim); font-size: 11.5px; text-decoration: none;
  border-bottom: 1px solid var(--sh-line);
}
.cat-doc:hover { color: var(--sh-text); border-color: var(--gold); }
.cat-foot .switch, .cat-foot > .tag:last-child { margin-left: auto; }
.modal-foot .panel-note { margin-left: 0; margin-right: auto; }

@media (prefers-reduced-motion: reduce) {
  .tab { transition: none; }
  .modal-x, .adv-head, .adv-head::before { transition: none; }
}

/* ---- futures position cards --------------------------------------------- */

/* An exchange-style card per open position. The previous single-line rows put
   PNL, entry, mark and liquidation in one run of text at equal weight, so the
   figure you actually watch had to be hunted for. */
.postcard {
  border: 1px solid var(--sh-line);
  border-radius: 14px;
  padding: 16px 18px;
  margin-bottom: 12px;
  background: color-mix(in srgb, var(--sh-panel-hi) 55%, transparent);
}
.pc-head { display: flex; align-items: center; gap: 8px; margin-bottom: 14px; }
.pc-sym { font-size: 17px; font-weight: 700; letter-spacing: .02em; }
.pc-tag {
  font-family: var(--sh-mono); font-size: 11px; padding: 3px 8px;
  border-radius: 5px; color: var(--sh-dim);
  background: color-mix(in srgb, var(--sh-line) 55%, transparent);
}
.pc-pnl {
  display: grid; grid-template-columns: 1fr auto; gap: 10px;
  padding-bottom: 14px; margin-bottom: 14px;
  border-bottom: 1px solid color-mix(in srgb, var(--sh-line) 70%, transparent);
}
.pc-pnl .pc-val { font-size: 26px; }
/* Three across on desktop, two when the rail eats the width, one on phones —
   measured on the pane, so "when the rail eats the width" is now literally
   true rather than a guess made from the window size. */
.pc-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px 18px; }
@container pane (max-width: 580px) { .pc-grid { grid-template-columns: repeat(2, 1fr); } }
@container pane (max-width: 460px) {
  .pc-grid { grid-template-columns: 1fr; }
  .pc-pnl .pc-val { font-size: 22px; }
}
.pc-cell { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.pc-cell.right { text-align: right; }
.pc-lab { font-size: 11.5px; color: var(--sh-faint); letter-spacing: .04em; }
.pc-val {
  font-family: var(--sh-mono); font-variant-numeric: tabular-nums;
  font-size: 15px; color: var(--sh-text);
}
/* Profit and loss take the shell's semantic colours, never a literal green or
   red — those would survive a mode change and break the palette. */
.pc-val .ok  { color: var(--sh-ok); }
.pc-val .bad { color: var(--sh-bad); }

/* Protection and size, on their own line above the actions. TP/SL is the one
   figure on the card that says what happens when nobody is watching, so it sits
   apart from the grid rather than becoming a seventh cell in it. */
.pc-tpsl {
  display: grid; grid-template-columns: 1fr auto; gap: 14px 18px;
  margin-top: 14px; padding-top: 14px;
  border-top: 1px solid color-mix(in srgb, var(--sh-line) 70%, transparent);
}
.pc-acts {
  display: flex; flex-wrap: wrap; gap: 8px;
  margin-top: 14px; padding-top: 14px;
  border-top: 1px solid color-mix(in srgb, var(--sh-line) 70%, transparent);
}
/* Every one of these blocks on an approval that can take up to three minutes,
   so the disabled state is the normal state, not an edge case. It has to read
   as "waiting", not as "broken". */
.pc-acts .switch[disabled] { opacity: .55; cursor: progress; }
@media (max-width: 520px) {
  .pc-acts .switch { flex: 1 1 auto; }
}
