/* =====================================================================
   EduMarkets — Hedge Fund Simulation, participant app. The file keeps its
   portfolio-sim name, and the app keeps its `pm-` prefix, because the sim
   was renamed on 2026-08-26 and the internal identifiers deliberately did
   not move with it (see backend/games/portfolio/__init__.py).

   Two jobs. First, the shell rules the platform keeps in platform.css:
   this app is standalone, so it carries its own mount container and join
   screen instead of the platform's module loader. Second, the desk
   vocabulary, modelled on the platform's market-making.css and prefixed
   `pm-` so nothing collides with the copied component styles.

   Layout contract, copied from the market-making desk: while a session is
   live the Trading Desk fills ONE viewport with no page scrolling. Only
   the feeds and blotters scroll, inside their own boxes. The
   `pm-desk-active` class on the workspace switches the platform's
   scrolling content area into a fixed fill-the-height layout; every other
   page removes it and normal scrolling returns.
   ===================================================================== */

/* ── Shell ─────────────────────────────────────────────────────────── */

/* Native controls follow the app's own theme, never the OS's. The theme
   toggle drives [data-theme]; without a root color-scheme the browser
   resolves the page's "dark light" meta against the OS preference, and a
   dark-OS machine drew dark checkboxes on the light theme (the positions
   tick column). The same pair console.css already carries. */
:root { color-scheme: dark; }
[data-theme="light"] { color-scheme: light; }

/* The page tokens of the 2026-10 redesign (Claude Design handoff
   design_handoff_economy_charts, owner-approved 2026-10-11: the design
   wins on the look of the shell, Economy and Charts). Every colour
   carries a meaning, named here: selection, the day that is today, a
   print above or below its consensus, a chart's primary line, the
   consensus and the priced path, the policy rate, news, and the
   series identity of a chart with several lines. The ground, surfaces,
   borders, inks and the P&L pair stay base.css's own tokens. Plotly
   cannot read a custom property, so the charts read these through
   chart-config.js `cssVar`, which keeps this file the one source. */
:root {
  --pm-hover:       #1C232C;
  --pm-subtle:      #1e2229;
  --pm-track:       #252830;
  --pm-sel:         #1C2A3A;
  --pm-today-bg:    #14243a;
  --pm-above:       #f59e0b;
  --pm-below:       #38bdf8;
  --pm-line:        #818cf8;
  --pm-est:         #f59e0b;
  --pm-policy:      #38bdf8;
  --pm-policy-band: rgba(56, 189, 248, 0.18);
  --pm-news:        #f59e0b;
  --pm-grid:        rgba(255, 255, 255, 0.06);
  --pm-spike:       rgba(255, 255, 255, 0.25);
  --pm-meter:       #64748b;
  --pm-tip-bg:      #0D1117;
  --pm-series-1:    #818cf8;
  --pm-series-2:    #38bdf8;
  --pm-series-3:    #f472b6;
  --pm-series-4:    #a3e635;
  --pm-series-5:    #e879f9;
  --pm-series-6:    #2dd4bf;
}
[data-theme="light"] {
  --pm-hover:       #f4f6fa;
  --pm-subtle:      #e8ebf4;
  --pm-track:       #e8ebf4;
  --pm-sel:         #e3ecf6;
  --pm-today-bg:    #e3ecf6;
  --pm-above:       #B45309;
  --pm-below:       #0c7da3;
  --pm-line:        #4f52cc;
  --pm-est:         #B45309;
  --pm-policy:      #0c7da3;
  --pm-policy-band: rgba(12, 125, 163, 0.14);
  --pm-news:        #B45309;
  --pm-grid:        rgba(0, 0, 0, 0.08);
  --pm-spike:       rgba(0, 0, 0, 0.30);
  --pm-meter:       #94a3b8;
  --pm-tip-bg:      #ffffff;
  --pm-series-1:    #4f52cc;
  --pm-series-2:    #0c7da3;
  --pm-series-3:    #c0267a;
  --pm-series-4:    #4d7c0f;
  --pm-series-5:    #9333ea;
  --pm-series-6:    #0f766e;
}

/* The type sizes of the four redesigned pages (owner, 2026-10-11, after
   the design's 9.5 to 12px read too small): table rows, lists and
   buttons at the size these pages had before the redesign, notes,
   headings, titles, legends and chart axes one step under it, and only
   the labels of the number cards smaller. The values on the number
   cards keep their own larger sizes. */
:root {
  --pm-fs-main:  14px;
  --pm-fs-note:  13px;
  --pm-fs-label: 12px;
}

/* ── A tipped element ──────────────────────────────────────────────
   The shared JS tooltip answers over anything carrying data-tip; the
   question-mark cursor is the sign of it (owner, 2026-10-12, as on the
   market making setup sidebar). Page-wide here, rows and cards
   included. :where() gives the rule no specificity, so an element that
   sets the cursor its own action needs keeps it (the sortable position
   headings, the chart layers). Buttons, links and form fields are left
   out, so a control keeps the cursor of a control. */
:where([data-tip]:not([data-tip=""]):not(button, a, input, select, textarea)) {
  cursor: help;
}

#module-mount {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

/* The header lockup deliberately carries no size preset (.md / .sm): the
   lockup stylesheet loads after components.css, so a preset would win the
   cascade over the header sizing in components.css. Same convention as the
   platform. */

/* ── One-viewport mode (Trading Desk) ──────────────────────────────── */

#pm-workspace.pm-desk-active .workspace-content {
  overflow-y: hidden;
}
/* Every page's surround matches the sidebar's surface (owner, 2026-08-20):
   with the panels tiled flat, the page ground framing the slab read as a
   black border against the sidebar's grey beside it. Painted on the
   scroll container rather than the capped content area, so a monitor
   wider than the cap does not show the ground beyond the cap. The seams
   between panels keep the ground explicitly, on the tile containers. */
#pm-workspace .workspace-content { background: var(--bg-surface); }
#pm-workspace.pm-desk-active .tab-panel.active {
  flex: 1 1 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
#pm-workspace.pm-desk-active .tab-content-area {
  flex: 1 1 0;
  min-height: 0;
  max-width: 1560px;   /* cap on wide monitors; the desk must stay dense */
  padding: 10px 16px 12px;
  display: flex;
  flex-direction: column;
}
/* The desk page's content host is the flex column the .pm-desk inside it
   stretches into. Without this the desk grid collapses to zero height and
   the overflow:hidden left column clips away entirely. */
#pm-workspace.pm-desk-active #pm-desk-content {
  flex: 1 1 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
#pm-workspace .pm-desk {
  flex: 1 1 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* ── Placeholder used by pages that are not built yet ──────────────── */

#pm-workspace .pm-placeholder {
  color: var(--text-muted);
  font-size: 0.85rem;
  padding: 10px 12px;
}

/* ── Header, right-hand group ──────────────────────────────────────── */

/* ── Header, right-hand controls ───────────────────────────────────── */

/* Copied from the Bank ALM console header (css/console.css .header-controls,
   .theme-toggle and its glyph swap, .btn / .btn-secondary / .btn-sm), so the
   theme toggle and Leave sit exactly where they sit there: one group,
   centred on the header's middle line. Console tokens are substituted by
   their values where the platform has no equivalent: --radius-sm is --r-sm,
   --font-base is --font, and --bg-hover, which the platform does not
   define, is --bg-elevated. */

/* The console header pads itself (.app-header padding: 0 24px in
   console.css); the platform header pads nothing and each right-hand child
   carries its own inset instead. So the group takes the console's 24px on
   the right, which is what puts Leave the same distance from the edge. */
#pm-header-controls {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-shrink: 0;
  padding-right: 24px;
}
#pm-header-controls .theme-toggle {
  background: transparent;
  border: 1px solid transparent;   /* invisible by default, shows on hover */
  color: var(--text-secondary);
  width: 32px;
  height: 32px;
  border-radius: var(--r-sm);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 16px;
  transition: var(--transition);
  /* Desaturate the colour emoji glyphs (yellow moon to grey). */
  filter: grayscale(1);
}
#pm-header-controls .theme-toggle:hover {
  background: var(--bg-elevated);
  border-color: var(--border);
  color: var(--text);
}
.icon-sun, .icon-moon { display: none; }
[data-theme="dark"] .icon-sun { display: inline; }
[data-theme="light"] .icon-moon { display: inline; }

#pm-header-controls .btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 8px 16px;
  border-radius: var(--r-sm);
  font-size: 13px;
  font-weight: 600;
  font-family: var(--font);
  cursor: pointer;
  transition: var(--transition);
  border: none;
}
#pm-header-controls .btn-secondary {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-secondary);
}
#pm-header-controls .btn-secondary:hover {
  background: var(--bg-elevated);
  color: var(--text);
}
#pm-header-controls .btn-sm { padding: 5px 10px; font-size: 12px; }

.pm-connect-error {
  max-width: 480px;
  margin: 80px auto;
  color: var(--negative);
  text-align: center;
}

/* ── Sidebar ───────────────────────────────────────────────────────── */

/* The platform pads sidebar content through a list of module content ids
   (components.css :914-923). This app's id is not in that list, so the
   same declaration is repeated here rather than forking the copied
   stylesheet. Values are the platform's, unchanged. */
#pm-params-content {
  padding: 20px 16px;
  min-width: var(--sidebar-width);   /* prevents reflow during animation */
}

/* Key-value rows and the sub-line, copied from the platform's
   market-making sidebar (css/market-making.css .mkm-sb-row). */

#pm-params-content .pm-sb-desk {
  font-size: 1rem;
  font-weight: 700;
  color: var(--text);
  margin-bottom: 12px;
  line-height: 1.35;
}
/* The member names sit on the same line as the team name, after a plain
   hyphen: "Citadel - RvL". */
#pm-params-content .pm-sb-members {
  font-size: 0.8rem;
  font-weight: 400;
  color: var(--text-muted);
  margin-left: 4px;
}
/* The team name is the rename control: a click puts an input in its place.
   It is drawn as the name and nothing else, so the sidebar reads as it did;
   the hover colour and the block's own tooltip are what say it can be
   clicked. */
#pm-params-content .pm-sb-name {
  appearance: none;
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}
#pm-params-content .pm-sb-name:hover { color: var(--color-accent); }
#pm-params-content .pm-sb-name:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
  border-radius: 2px;
}
/* The editor takes the whole line, member names included, because the
   field needs the width of the sidebar to hold a team name. */
#pm-params-content .pm-sb-name-input { width: 100%; }
#pm-params-content .pm-sb-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 8px;
  /* 2px, with the desk's density pass (2026-08-20): the sidebar is read
     beside the desk all session and follows its rhythm. */
  padding: 2px 0;
  font-size: 0.95rem;
  color: var(--text-secondary);
}
#pm-params-content .pm-sb-row .num {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: var(--text);
  text-align: right;
}
#pm-params-content .pm-sb-row .num.positive { color: var(--positive); }
#pm-params-content .pm-sb-row .num.negative { color: var(--negative); }
/* A value that reads as words: the session state, the pace, the day count.
   Same weight and colour as a figure, the body font instead of mono. */
#pm-params-content .pm-sb-row .pm-sb-word {
  font-weight: 600;
  color: var(--text);
  text-align: right;
}
#pm-params-content .pm-sb-row .pm-sb-word.negative { color: var(--negative); }
/* The sub-line sits inside the value's span, so it would inherit the mono
   face. It reads as a sentence ("30% of capacity", "limit 20%"), and mono
   is for figures alone, so it takes the body font back. */
#pm-params-content .pm-sb-sub {
  display: block;
  text-align: right;
  font-family: var(--font);
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--text-muted);
}
/* The session line: the day, the pace and the connection on one line under
   the team name, spread across the sidebar's width. It replaces four rows
   of key and value, so the figures a desk reads all session start that
   much higher up. Each reading keeps its own tooltip. */
#pm-params-content .pm-sb-status {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  /* Three readings, each unbreakable: the day, the countdown to the next
     one, and the connection dot. The pace reading that used to sit here
     was what pushed the line onto a second row, and the countdown says
     the same thing live. The wrap stays as the last resort for a phone,
     where the sidebar is a fraction of the viewport. */
  flex-wrap: wrap;
  row-gap: 2px;
  margin-bottom: 4px;
  font-size: 0.9rem;
  color: var(--text-secondary);
}
/* The countdown changes width as it passes ten seconds, and every reading
   on this line is placed off the one beside it. Reserving the widest
   reading's width is what stops the line twitching once a second. */
#pm-params-content #pm-next-day {
  display: inline-block;
  min-width: 4ch;
  text-align: right;
  font-variant-numeric: tabular-nums;
}
#pm-params-content .pm-sb-stat {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  white-space: nowrap;
}
#pm-params-content .pm-sb-stat-value { font-weight: 600; color: var(--text); }

/* A standings column heading that carries the formula button beside it.
   The button is part of the heading rather than a second cell, so the
   column stays one column and the label keeps its right alignment. */
#pm-workspace .pm-score-head {
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
  gap: 4px;
}

/* A row that belongs to no block above it: the session overview control
   stands clear of the last section rather than reading as one more
   activity figure. The space is a heading's, so the break reads the same
   as the one between two sections. */
#pm-params-content .pm-sb-row--apart { margin-top: 18px; }

/* The row the ones above it add up to. The rule over it is what says so,
   the way a total is ruled off on a statement.

   The rule is drawn brighter than --border, which at #252830 on the dark
   sidebar surface is a separator between rows and disappears when it has
   to carry meaning. The light theme takes the token back: #dde1ec on white
   reads at a glance already. */
#pm-params-content .pm-sb-row--sum {
  border-top: 1px solid rgba(255, 255, 255, 0.22);
  margin-top: 2px;
  padding-top: 6px;
}
[data-theme="light"] #pm-params-content .pm-sb-row--sum {
  border-top-color: var(--border);
}

/* The dot on its own. The padding is the hover target its tooltip needs,
   an 8px circle being too small to find; the matching negative margin
   keeps it where it was on the line. */
#pm-params-content .pm-sb-conn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px;
  margin: -5px;
  font-size: 0.85rem;
  color: var(--text-secondary);
}
/* The connection dot, copied from the Bank ALM console stylesheet
   (css/console.css .status-dot). The class names are the ones shared/ws.js
   writes, so the socket client is unchanged. */
.status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--text-muted);
}
.status-dot.online { background: var(--positive); }
.status-dot.offline { background: var(--negative); }
.status-dot.reconnecting {
  background: var(--warning);
  animation: pm-pulse-dot 1s ease-in-out infinite;
}
@keyframes pm-pulse-dot { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } }

/* ── Trading Desk ──────────────────────────────────────────────────── */

#pm-workspace .pm-grid {
  flex: 1 1 0;
  min-height: 0;
  display: grid;
  /* The market grid is down to six columns, so the left side needs less
     than it did and the right side, which carries four cards of figures,
     needs more than it had. */
  grid-template-columns: minmax(600px, 44%) 1fr;
  /* The panels tile edge to edge with the page ground showing through the
     1px gaps as the seam between them (owner decision 2026-08-20, the
     terminal chrome pass). The ground is painted here explicitly because
     the desk's surround took the surface tone (see .workspace-content),
     so the gaps no longer sit over it. The columns below carry the same
     gap and ground, so every seam on the desk is the same hairline. */
  gap: 1px;
  background: var(--bg);
}
/* Left: the market grid takes what is left after the ticket, and scrolls
   inside itself, so the ticket never moves down the screen. */
#pm-workspace .pm-col-market {
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
  background: var(--bg);
  overflow: hidden;
}
#pm-workspace .pm-market-frame { flex: 1 1 0; }
#pm-workspace .pm-ticket-frame { flex: 0 0 auto; }
/* Right: the instrument panel, the newsfeed, positions, resting orders.
   The newsfeed sits under the panel, where the story that moves a name
   reads beside the name it moves. The blotter is not here: a fill confirms
   itself the moment the position moves, so the list of them is a record
   rather than something a desk trades from, and it reads on Portfolio
   Analytics.

   Height has one owner per card, and the grid distributes only what is
   genuinely elastic. Tuned fractions were tried for each card in turn and
   kept coming apart, because two things were sizing the same card at once:
   the card asking for its content's height and the grid handing it a share
   of the column regardless. So each card is sized by what it is.

   Fixed: the instrument panel shows one set of fields and one chart, so it
   is a known height and says so itself. That is also what stops it
   resizing when an instrument is picked.

   Content: resting orders is usually empty and never long, so it takes the
   height of what it holds, capped so a full book of orders scrolls rather
   than eating the column.

   Elastic: the newsfeed and positions are lists with no natural end, so
   they take equal shares of whatever the other two leave, down to nothing
   on a short screen. That is what keeps the column ending exactly where
   the ticket beside it does instead of running off the bottom. Any card
   too small to read on the day is opened with its own button. */
#pm-workspace .pm-col-right {
  min-height: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto minmax(0, 1fr) minmax(0, 1fr) auto;
  gap: 1px;
  background: var(--bg);
}
/* The fallback the enlarged card is positioned against on a page with no
   column of its own. The rules for that state live at the very bottom of
   this file, and the comment there says why they have to. */
#pm-workspace { position: relative; }

/* Each region is a flat tiled panel (owner decision 2026-08-20, chosen on
   a rendered mockup against the earlier ALM-style rounded card). No border
   and no radius: the 1px grid gaps above are the only separation, so the
   desk reads as one tiled surface rather than cards floating on a page.
   This supersedes the "cards, not terminal frames" ruling for the Trading
   Desk; the scrolling pages keep their cards until reviewed.

   The head is a caption bar rather than a card header: thin, on the
   elevated background, closed by a hairline. The title drops to 13px (a
   size the desk already uses) and the secondary text colour; the panel's
   working area is the content, and the bar only names it. These panels
   hold scrolling tables inside a fixed viewport, so the head carries the
   inset and the body runs to the panel's edge. */
#pm-workspace .pm-frame {
  min-height: 0;
  display: flex;
  flex-direction: column;
  background: var(--bg-surface);
  overflow: hidden;
}
#pm-workspace .pm-frame-head {
  flex: 0 0 auto;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  padding: 4px 10px;
  background: var(--bg-elevated);
  border-bottom: 1px solid var(--border-subtle);
}
#pm-workspace .pm-frame-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-secondary);
}
#pm-workspace .pm-frame-note {
  font-size: 0.75rem;
  color: var(--text-muted);
}

/* ── Market grid ───────────────────────────────────────────────────── */

#pm-workspace .pm-market-wrap {
  flex: 1 1 0;
  min-height: 0;
  overflow-y: auto;          /* the grid is one of the regions that scroll */
  overflow-x: auto;          /* a narrow window scrolls rather than clips */
}

/* Fixed layout, so the columns are shared out rather than sized by their
   longest cell. Numbers keep their width and never truncate; the company and
   sector names give way with an ellipsis. Without this the table ran wider
   than its card and the last columns were cut off at the border. */
#pm-workspace .pm-market,
#pm-workspace .pm-table {
  width: 100%;
  table-layout: fixed;
  border-collapse: collapse;
  font-size: 0.85rem;
}
#pm-workspace .pm-market th,
#pm-workspace .pm-market td,
#pm-workspace .pm-table th,
#pm-workspace .pm-table td {
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Market grid: symbol, beta, bid, ask, daily %, position. Every column is
   given a share, none left to take what is over: under `table-layout:
   fixed` an unsized column gets only the remainder, and that is how the
   company name came to be squeezed to two letters.

   Sector and the company name are not here. Neither prices the instrument,
   the panel beside the grid carries both, and the room they took was
   coming out of the six columns a desk reads on every glance. Beta stays:
   the mandate caps beta-adjusted net exposure, so it is read while
   scanning rather than looked up. */
#pm-workspace .pm-market th:nth-child(1) { width: 13%; }
#pm-workspace .pm-market th:nth-child(2) { width: 13%; }
#pm-workspace .pm-market th:nth-child(3),
#pm-workspace .pm-market th:nth-child(4) { width: 18.5%; }
#pm-workspace .pm-market th:nth-child(5) { width: 18.5%; }
#pm-workspace .pm-market th:nth-child(6) { width: 18.5%; }
/* A universe whose tickers are not the company leads on the name and drops
   the ticker (name, beta, bid, ask, daily %, position). Every column is
   redeclared rather than adjusted, because under `table-layout: fixed` an
   unsized column takes only the remainder. The name is the one column that
   may run out of room, and it takes the ellipsis the table already sets. */
#pm-workspace .pm-market--named th:nth-child(1) { width: 27%; }
#pm-workspace .pm-market--named th:nth-child(2) { width: 9%; }
#pm-workspace .pm-market--named th:nth-child(3),
#pm-workspace .pm-market--named th:nth-child(4) { width: 17%; }
#pm-workspace .pm-market--named th:nth-child(5) { width: 14%; }
#pm-workspace .pm-market--named th:nth-child(6) { width: 16%; }
/* The macro grid runs five columns: a universe without a market factor
   declares no beta. Redeclared in full, as above, because under fixed
   layout the five columns would otherwise take the first five of the six
   widths and the bid would sit in the beta column's 9%. */
#pm-workspace .pm-market--nobeta th:nth-child(1) { width: 30%; }
#pm-workspace .pm-market--nobeta th:nth-child(2),
#pm-workspace .pm-market--nobeta th:nth-child(3) { width: 18%; }
#pm-workspace .pm-market--nobeta th:nth-child(4) { width: 16%; }
#pm-workspace .pm-market--nobeta th:nth-child(5) { width: 18%; }
/* The macro grid with the yield beside the bond futures' price (name,
   bid, ask, yield, daily %, position), redeclared in full for the same
   reason. The yield is two decimals of a single-digit percentage, so it
   is the narrowest column. */
#pm-workspace .pm-market--nobeta.pm-market--yield th:nth-child(1) { width: 27%; }
#pm-workspace .pm-market--nobeta.pm-market--yield th:nth-child(2),
#pm-workspace .pm-market--nobeta.pm-market--yield th:nth-child(3) { width: 16%; }
#pm-workspace .pm-market--nobeta.pm-market--yield th:nth-child(4) { width: 11%; }
#pm-workspace .pm-market--nobeta.pm-market--yield th:nth-child(5) { width: 14%; }
#pm-workspace .pm-market--nobeta.pm-market--yield th:nth-child(6) { width: 16%; }
/* The name leads the grid where it is shown, so it reads as the identity
   column the ticker is on the other universes rather than as a gloss. */
#pm-workspace .pm-market .pm-name { font-weight: 500; }
/* The region heading between blocks of the grid. It is a row rather than a
   separate table so the columns stay in one fixed layout, and it sticks
   under the header the way the header sticks to the top, so the block a
   participant is scrolled into keeps saying which market it is. Weight and
   colour separate it from the rows, not a size of its own. */
/* The offset is the header row's rendered height less one pixel of
   overlap. The header's vertical padding changed in the density pass
   (2026-08-20), so it moved from 27px with it; re-measure in the browser
   if the header's type or padding changes again. */
#pm-workspace .pm-market .pm-market-block td {
  position: sticky;
  top: 23px;
  background: var(--bg-elevated);
  color: var(--text-secondary);
  font-weight: 600;
  padding-top: 7px;
  padding-bottom: 5px;
  border-bottom: 1px solid var(--border);
}
#pm-workspace .pm-market .pm-market-block:hover td { background: var(--bg-elevated); }
/* The blotter and the resting orders both lead with a symbol, which needs
   far less room than the columns of figures beside it. */
#pm-workspace .pm-table th:first-child { width: 84px; }
/* Both tables in the right column declare every column, so neither takes
   the pixel width above. */
#pm-workspace .pm-orders-table th:first-child,
#pm-workspace #pm-positions .pm-table th:first-child { width: auto; }
/* Positions: symbol, quantity, average cost, value, unrealised, close.
   Declared one by one for the same reason the market grid is. Left to share what
   was over, the columns came out uneven and cut the figures to -94... and
   -$8..., which is worse than no column at all. Realised profit and loss
   is a review figure and reads on Portfolio Analytics instead. */
/* Resting orders: side, qty, instrument, type, price, TIF, cancel.
   Without a heading row this table had no sized columns at all, so
   `table-layout: fixed` split it into seven equal parts and cut the price
   to "Limit 22...". The instrument column holds the width the short TIF
   and Qty headings and the cancel cross gave back: at 11% it cut the
   credit tickers to US... (owner, 2026-08-21). */
#pm-workspace .pm-orders-table th:nth-child(1) { width: 10%; }
#pm-workspace .pm-orders-table th:nth-child(2) { width: 13%; }
#pm-workspace .pm-orders-table th:nth-child(3) { width: 28%; }
#pm-workspace .pm-orders-table th:nth-child(4) { width: 10%; }
#pm-workspace .pm-orders-table th:nth-child(5) { width: 18%; }
#pm-workspace .pm-orders-table th:nth-child(6) { width: 11%; }
#pm-workspace .pm-orders-table th:nth-child(7) { width: 10%; }

/* Six columns in the width five had, so the gutters pay rather than the
   figures: the blotter's cells are cut to 4px a side, against the 7px the
   resting orders beside it keep. On the narrowest desk that is 36px given
   back to the columns, which is most of what the close column costs. */
#pm-workspace #pm-positions .pm-table th,
#pm-workspace #pm-positions .pm-table td {
  padding-left: 4px;
  padding-right: 4px;
}
/* The columns are named rather than counted, because the tick and DV01
   columns are in the markup at every width and shown only where the card
   is wide enough (the container query further down): an nth-child count
   would shift under the hidden cells. */
#pm-workspace #pm-positions .pm-table th.pm-pc-sym { width: 20%; }
#pm-workspace #pm-positions .pm-table th.pm-pc-qty { width: 17%; }
#pm-workspace #pm-positions .pm-table th.pm-pc-avg { width: 17%; }
#pm-workspace #pm-positions .pm-table th.pm-pc-val { width: 18%; }
#pm-workspace #pm-positions .pm-table th.pm-pc-unr { width: 18%; }
/* The close column carries a cross, so it asks for a tenth of the card
   rather than the seventh the word would have. */
#pm-workspace #pm-positions .pm-table th.pm-pc-x { width: 10%; }
#pm-workspace .pm-market th,
#pm-workspace .pm-table th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--bg-surface);
  padding: 3px 10px;
  text-align: left;
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
#pm-workspace .pm-market th[data-sort],
#pm-workspace .pm-table th[data-sort] { cursor: pointer; }
/* Re-arranging the positions by hand: the dragged row dims, and the mark
   is drawn on the edge of the row the drop would land against. */
#pm-workspace #pm-positions tr.pm-row-dragging { opacity: 0.45; }
#pm-workspace #pm-positions tr.pm-drop-above td {
  border-top: 2px solid var(--color-accent);
}
#pm-workspace #pm-positions tr.pm-drop-below td {
  border-bottom: 2px solid var(--color-accent);
}
#pm-workspace .pm-market td,
#pm-workspace .pm-table td {
  padding: 2px 10px;
  border-bottom: 1px solid var(--border-subtle);
  white-space: nowrap;
}
/* The blotter and the resting orders sit in the narrow right column and
   carry money figures, which need the room more than the gutters do. */
#pm-workspace .pm-col-right .pm-table th,
#pm-workspace .pm-col-right .pm-table td { padding-left: 7px; padding-right: 7px; }
/* A heading there is allowed a second line. Cut to fit, they were reading
   as AVE, UNR and REA, and a column nobody can name is a column nobody can
   use. The figures underneath still stay on one line. */
#pm-workspace .pm-col-right .pm-table th {
  white-space: normal;
  vertical-align: bottom;
  line-height: 1.15;
}
#pm-workspace .pm-market th.right,
#pm-workspace .pm-market td.right,
#pm-workspace .pm-table th.right,
#pm-workspace .pm-table td.right { text-align: right; }
#pm-workspace .pm-market .num,
#pm-workspace .pm-table .num {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}
/* The identifying column, the ticker or the name, carried by weight and
   colour rather than by size. */
#pm-workspace .pm-sym { font-weight: 600; color: var(--text); }
#pm-workspace .pm-market tbody tr { cursor: pointer; }
/* A quote cell that has just printed a new value. The background flash
   carries recency and nothing else; direction stays in the red and green
   of the text, so the two never compete (the AG Grid split: a neutral
   flash, then a fade). Without the transient, a change outside where the
   reader is looking is invisible. Engines without color-mix skip the
   flash rather than falling back to a wrong colour. */
@keyframes pm-tick-flash {
  0%, 35% { background: color-mix(in srgb, var(--text) 16%, transparent); }
  100% { background: transparent; }
}
#pm-workspace .pm-tick-flash { animation: pm-tick-flash 1.1s ease-out; }
@media (prefers-reduced-motion: reduce) {
  #pm-workspace .pm-tick-flash { animation: none; }
}
/* A region heading is not an instrument, so it is not clickable. */
#pm-workspace .pm-market tbody tr.pm-market-block { cursor: default; }
/* A halted name after a credit default: the row stays so the reader sees
   what happened, muted, with the quote cells replaced by the word. */
#pm-workspace .pm-market tbody tr.pm-row-halted td {
  color: var(--text-muted);
}
/* The instrument panel's halt line under the name tags. Inherits the
   tags' type scale; colour alone carries the state. */
#pm-workspace .pm-ip-halted {
  color: var(--negative);
  margin-top: 2px;
}
#pm-workspace #pm-positions .pm-table tbody tr { cursor: pointer; }
#pm-workspace .pm-market tbody tr:hover,
#pm-workspace #pm-positions .pm-table tbody tr:hover {
  background: var(--bg-elevated);
}
/* The instrument the desk is working on, held until another is picked. The
   tint has to read as chosen rather than as hovered, so it is the accent at
   low strength rather than another step of grey. Older engines that cannot
   mix colours fall back to the hover tint. */
#pm-workspace .pm-market tbody tr.pm-row-selected,
#pm-workspace #pm-positions .pm-table tbody tr.pm-row-selected {
  background: var(--bg-elevated);
  background: color-mix(in srgb, var(--color-accent) 14%, transparent);
}
#pm-workspace tr.pm-row-selected .pm-sym { color: var(--color-accent-text); }
#pm-workspace .positive { color: var(--positive); }
#pm-workspace .negative { color: var(--negative); }
/* A futures contract is worth multiplier times the index price, so its size
   sits next to the symbol. Without it a contract reads like a share. */
#pm-workspace .pm-mult {
  font-size: 0.7rem;
  font-weight: 600;
  color: var(--text-muted);
}

/* ── Ticket ────────────────────────────────────────────────────────── */

#pm-workspace .pm-ticket { padding: 0 10px 10px; }
/* Four tracks, not equal: the first two (Instrument and Order type, Size
   and Limit price) hold short entries and give what they save to the
   third, which must show "% of capital" whole, and the fourth, where
   four position buttons and the Sell and Buy pair need the room. The
   desk only renders at 1024px and up, so the fixed tracks never squeeze
   below their minimums. */
#pm-workspace .pm-ticket-form {
  display: grid;
  grid-template-columns:
      minmax(0, 0.8fr) minmax(0, 0.8fr) minmax(118px, 1fr) minmax(160px, 1.6fr);
  gap: 8px;
  align-items: end;
}
#pm-workspace .pm-field { display: block; }
#pm-workspace .pm-field .sb-label { margin: 0 0 4px; }
/* The four position buttons share one column of the form beside the size
   fields. They carry no label of their own, and the form aligns its row
   on the baseline of the inputs, so they line up with the select next to
   them. The padding is cut to almost nothing, which is what lets four of
   them stand in the width of one field; the percentages are figures, so
   they take the mono face like every other column of numbers. */
#pm-workspace .pm-ticket-close {
  display: flex;
  gap: 4px;
}
#pm-workspace .pm-ticket-close .btn {
  flex: 1 1 0;
  min-width: 0;
  padding: 0 2px;
  font-size: 0.82rem;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}
/* What the typed size works out to. It sits on its own row under the size
   fields rather than taking a grid column of its own, so the fields keep
   their widths as the note appears and disappears. */
#pm-workspace .pm-ticket-size {
  grid-column: 1 / -1;
  min-height: 1.1em;
  margin-top: -2px;
  font-size: 0.8rem;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}
#pm-workspace .pm-ticket-actions {
  display: flex;
  gap: 8px;
  /* Pinned to the wide track: on a market order the price and time in
     force fields are hidden, and auto-placement would otherwise put Sell
     and Buy in a narrow track instead. */
  grid-column: 4;
}
#pm-workspace .pm-ticket-actions .btn { flex: 1 1 0; }
/* The cross on a position row's close and a resting order's cancel: the
   ghost button cut down twice, to the height of a table row, and to a
   cross rather than the word. Gutters and a five-or-six-letter label were
   taking a third of these cards between them, and the credit symbols were
   the ones paying for it (CMCSA-CDS read as CMCS...). The label lives in
   the tooltip and in the accessible name instead. */
#pm-workspace #pm-positions .pm-close-btn,
#pm-workspace .pm-orders-table .pm-close-btn {
  padding: 0 6px;
  font-size: 0.9rem;
  line-height: 1.4;
}

/* The instrument field's match list. It hangs off the body, not off the
   ticket, because .pm-frame clips its own overflow and a list drawn inside
   the ticket would be cut at the frame's edge; so the selector carries no
   #pm-workspace scope and the position is written by the script from the
   field's rectangle, the way the shared tooltip places itself. */
.pm-symbol-search {
  position: fixed;
  z-index: var(--z-dropdown);
  max-width: 340px;
  max-height: 260px;
  overflow-y: auto;
  padding: 2px 0;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-md);
}
.pm-symbol-search[hidden] { display: none; }
.pm-search-row {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 4px 10px;
  font-size: 0.82rem;
  cursor: pointer;
  white-space: nowrap;
}
/* The ticker is what the row is looked up by and the name confirms it, the
   two tiers the market grid already reads in. */
.pm-search-sym {
  flex: 0 0 auto;
  font-weight: 600;
  color: var(--text);
}
.pm-search-name {
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--text-secondary);
}
/* One highlight for both routes into a row: the arrow keys mark the row
   they are on, and the pointer marks the row it is over. */
.pm-search-row:hover,
.pm-search-row--active {
  background: var(--bg-surface);
  background: color-mix(in srgb, var(--color-accent) 14%, transparent);
}

/* A refused order stays here until the next ticket action. */
#pm-workspace .pm-ticket-message {
  margin-top: 8px;
  padding: 8px 10px;
  font-size: 0.85rem;
  color: var(--negative);
  background: var(--negative-bg);
  border: 1px solid color-mix(in srgb, var(--negative) 35%, transparent);
}
/* The preview is two side blocks of seven rows, plus one line for a
   futures contract. Reserving that height keeps the ticket the same size
   whichever instrument is picked, so the grid above it never jumps. A
   curve pack's preview carries an eighth row (the DV01 or CS01 amount)
   and the face-notional line on every row, so its reserve is one row
   taller; without it the ticket grew by the overrun when an instrument
   was picked. */
#pm-workspace .pm-preview {
  margin-top: 8px;
  min-height: 208px;
}
#pm-workspace .pm-preview--curve { min-height: 232px; }
/* The preview's fold (owner decision 2026-08-21): closed by default, so
   the ticket ends at its buttons and the market grid above keeps the
   height the preview was reserving. The reserve still applies open, so
   the ticket does not change height between instruments. */
#pm-workspace .pm-ticket-fold { margin-top: 6px; }
#pm-workspace .pm-ticket-fold:not([open]) { margin-bottom: 2px; }

/* ── The desk's width-aware panels ──────────────────────────────────
   The ticket and the positions card each measure their own panel, not
   the window, so they respond to the seams above being dragged. */
#pm-workspace .pm-ticket-frame { container: pm-ticket / inline-size; }
#pm-workspace .pm-positions-frame { container: pm-positions / inline-size; }

/* A narrow ticket: the fields keep a two-across grid and the button
   groups take whole rows beneath them, rather than eight controls
   fighting for four squeezed tracks. */
@container pm-ticket (max-width: 519px) {
  #pm-workspace .pm-ticket-form {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  #pm-workspace .pm-field--mode,
  #pm-workspace #pm-t-tif-field,
  #pm-workspace .pm-ticket-close,
  #pm-workspace .pm-ticket-actions { grid-column: 1 / -1; }
}

/* A wide positions card earns two more columns: the tick that feeds the
   selected total, and the DV01 on the universes that have one. Narrow,
   both stay in the markup and out of the layout, so the ticked set and
   the figures survive the card being narrowed. */
#pm-workspace .pm-pos-tick,
#pm-workspace .pm-pos-dv01 { display: none; }
@container pm-positions (min-width: 620px) {
  #pm-workspace #pm-positions .pm-pos-tick { display: table-cell; }
  #pm-workspace #pm-positions .pm-table--dv01 .pm-pos-dv01 {
    display: table-cell;
  }
  #pm-workspace #pm-positions .pm-table th.pm-pos-tick { width: 24px; }
  #pm-workspace #pm-positions .pm-table th.pm-pc-x { width: 8%; }
  #pm-workspace #pm-positions .pm-table--dv01 th.pm-pc-sym { width: 15%; }
  #pm-workspace #pm-positions .pm-table--dv01 th.pm-pc-qty { width: 13%; }
  #pm-workspace #pm-positions .pm-table--dv01 th.pm-pc-avg { width: 13%; }
  #pm-workspace #pm-positions .pm-table--dv01 th.pm-pc-val { width: 14%; }
  #pm-workspace #pm-positions .pm-table--dv01 th.pm-pc-unr { width: 14%; }
  #pm-workspace #pm-positions .pm-table--dv01 th.pm-pos-dv01 { width: 15%; }
}
#pm-workspace .pm-pos-tick input {
  accent-color: var(--color-accent);
  margin: 0;
  vertical-align: middle;
}

/* What the ticked positions come to. Under the scroller rather than in
   it, so a long book scrolls beneath the total. */
#pm-workspace .pm-pos-agg {
  flex: 0 0 auto;
  padding: 4px 10px;
  font-size: 0.78rem;
  color: var(--text-secondary);
  border-top: 1px solid var(--border-subtle);
}
#pm-workspace .pm-pos-agg .num {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  color: var(--text);
}
#pm-workspace .pm-pos-agg[hidden] { display: none; }

/* ── Resizable seams ────────────────────────────────────────────────
   Invisible 9px handles laid over the desk's 1px gaps (desk_resize.js
   places them), so the tiled look is untouched until a seam is hovered.
   The tint on hover is the affordance; the drag replaces the columns'
   own sizing rules with the reader's shares. */
#pm-workspace .pm-grid { position: relative; }
#pm-workspace .pm-seam { position: absolute; z-index: 5; }
#pm-workspace .pm-seam--v { width: 9px; cursor: col-resize; }
#pm-workspace .pm-seam--h { height: 9px; cursor: row-resize; }
#pm-workspace .pm-seam:hover,
#pm-workspace .pm-seam--active {
  background: color-mix(in srgb, var(--color-accent) 22%, transparent);
}
body.pm-desk-resizing { user-select: none; }

/* A dragged seam replaces the column's own sizing rules with the
   reader's shares, held in the custom properties desk_resize.js writes.
   Every panel already scrolls inside its own box, so a panel given less
   than its content scrolls rather than clips. */
#pm-workspace .pm-col-market.pm-rows-manual .pm-market-frame {
  flex: 0 0 var(--pm-l1);
}
#pm-workspace .pm-col-market.pm-rows-manual .pm-ticket-frame {
  flex: 1 1 0;
  min-height: 0;
}
#pm-workspace .pm-col-market.pm-rows-manual .pm-ticket {
  overflow-y: auto;
  min-height: 0;
}
#pm-workspace .pm-col-right.pm-rows-manual {
  grid-template-rows:
      minmax(56px, var(--pm-r1)) minmax(56px, var(--pm-r2))
      minmax(56px, var(--pm-r3)) minmax(56px, var(--pm-r4));
}
/* In its own rules the instrument panel says its height and the orders
   box caps its scroller; a reader-sized row owns both instead. */
#pm-workspace .pm-col-right.pm-rows-manual .pm-instrument {
  flex: 1 1 0;
  max-height: none;
  min-height: 0;
}
#pm-workspace .pm-col-right.pm-rows-manual .pm-orders-frame .pm-scroll {
  flex: 1 1 0;
  max-height: none;
}
#pm-workspace .pm-preview-unit {
  font-size: 0.78rem;
  color: var(--text-muted);
  margin-bottom: 6px;
}
#pm-workspace .pm-preview-sides {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 10px 28px;
}
/* No box around either side. The gap between the two columns and the
   heading over each one already separate them, and a drawn frame around
   a list of figures adds an edge for the eye to catch on without saying
   anything the layout has not said. */
#pm-workspace .pm-preview-side { padding: 2px 0; }
#pm-workspace .pm-preview-title {
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--text);
  margin-bottom: 4px;
}
#pm-workspace .pm-preview-row {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  font-size: 0.8rem;
  color: var(--text-secondary);
  padding: 1px 0;
}
#pm-workspace .pm-preview-row .num {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  color: var(--text);
}
#pm-workspace .pm-preview-blocked {
  font-size: 0.8rem;
  color: var(--negative);
}

/* ── Blotter, resting orders, feed ─────────────────────────────────── */

#pm-workspace .pm-scroll {
  flex: 1 1 0;
  min-height: 0;
  overflow-y: auto;
  overflow-x: auto;
}
/* The resting-orders box takes its natural height inside an `auto` grid row,
   so its scroller must not stretch: `flex: 1 1 0` there resolves to zero and
   the frame's overflow:hidden then clips the table away entirely. */
#pm-workspace .pm-orders-frame .pm-scroll {
  flex: 0 1 auto;
  max-height: 160px;
}
/* The close and cancel crosses stack into one visual column across the
   two cards, so nothing may shift one table against the other: the
   cancel cell takes the blotter's 4px gutter instead of the orders
   table's 7px, and both scrollers reserve their scrollbar gutter so a
   list that scrolls is not narrower than one that does not. */
#pm-workspace .pm-orders-table td:last-child { padding-right: 4px; }
#pm-workspace .pm-positions-frame .pm-scroll,
#pm-workspace .pm-orders-frame .pm-scroll { scrollbar-gutter: stable; }
#pm-workspace .pm-order-side { font-weight: 600; }
#pm-workspace .pm-order-side--buy  { color: var(--positive); }
#pm-workspace .pm-order-side--sell { color: var(--negative); }

/* Feed, copied from the market-making desk (.mkm-feed). */
#pm-workspace .pm-feed {
  flex: 1 1 0;
  min-height: 0;
  overflow-y: auto;
  padding: 4px 0;
}
#pm-workspace .pm-feed-item {
  display: flex;
  gap: 10px;
  padding: 2px 10px;
  font-size: 0.85rem;
  line-height: 1.5;
}
#pm-workspace .pm-feed-day {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
  flex-shrink: 0;
  min-width: 34px;
  text-align: right;
}
/* The thread filter in the feed's caption bar, kept to the bar's height.
   The bar clears the enlarge button on its right, as the positions bar
   does. */
#pm-workspace .pm-feed-frame .pm-frame-head {
  align-items: center;
  padding-right: 40px;
}
#pm-workspace .pm-feed-filter {
  width: auto;
  margin-top: 0;
  padding: 0 4px;
  font-size: 0.75rem;
}
#pm-workspace .pm-feed-text { color: var(--text-secondary); }
/* The calendar's next releases above the headlines: the feed's own rows,
   closed off from the headlines by a hairline. */
#pm-workspace .pm-feed-next {
  flex-shrink: 0;
  padding: 4px 0;
  border-bottom: 1px solid var(--border);
}
#pm-workspace .pm-feed-next-numbers,
#pm-workspace .pm-feed-next-thread { color: var(--text-muted); }
#pm-workspace .pm-feed-item--news .pm-feed-text {
  color: var(--text);
  font-weight: 600;
}

/* ── Scrolling pages (everything except the Trading Desk) ──────────── */

/* The platform's table wrap rounds its corners (components.css
   .data-table-wrap, --r-lg); square in this app's terminal chrome. The
   border stays: a table inside a padded card still needs its edge. The
   session-overview dialog mounts outside #pm-workspace and draws its
   tables without a box; its own block below owns that. */
#pm-workspace .data-table-wrap {
  border-radius: 0;
}

#pm-workspace .pm-muted {
  font-size: 0.85rem;
  color: var(--text-muted);
  margin: 8px 0;
}

/* The limit meter, copied from the platform's market-making desk
   (css/market-making.css .mkm-meter), which is where the platform shows a
   position against its limit. */
#pm-workspace .pm-meter {
  height: 5px;
  border-radius: 3px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  overflow: hidden;
  margin: 2px 0 6px;
}
/* Neutral at rest (owner decision 2026-08-20, the colour-discipline
   pass): saturated colour is reserved for the warn and breach bands, so
   an amber or red bar is the only warm thing on a healthy screen. The
   accent fill this replaced said nothing at any usage. */
#pm-workspace .pm-meter-fill {
  height: 100%;
  background: var(--neutral);
}
/* Three bands, in the order a desk meets them: inside the cap, inside the
   last 15% of it, past it. The fill is the only thing that carries the
   colour, so a row at rest is as quiet as every other row. */
#pm-workspace .pm-meter--warn .pm-meter-fill { background: var(--warning); }
#pm-workspace .pm-meter--breach .pm-meter-fill { background: var(--negative); }
/* The same bar in the sidebar, sitting under the row it belongs to rather
   than in a cell of its own. */
#pm-params-content .pm-sb-meter { margin: 0 0 6px; }
/* ── Risk-team messages ────────────────────────────────────────────── */

/* These arrive as pop-ups over the desk. The platform toast is a
   translucent tint, which was drawn to sit over a dark page; over the
   instrument panel the message and the panel underneath read through each
   other and neither could be made out. Here they take a solid card: the
   tint is mixed into the surface rather than laid over it, so nothing
   shows through, and the border carries which kind of message it is. */
.em-toast {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  color: var(--text);
  font-weight: 500;
  line-height: 1.4;
}
/* Error toasts follow the one look ruled for every sim (owner, 2026-09-04):
   dark red border, light red fill, black text. The values are base.css's;
   they are repeated here because the `.em-toast` card above would otherwise
   win on source order and paint the error toast as a plain surface card. */
.em-toast-error {
  background: color-mix(in srgb, var(--negative) 18%, #fff);
  border-color: color-mix(in srgb, var(--negative) 60%, #000);
  color: #000;
}
.em-toast-success {
  background: color-mix(in srgb, var(--positive) 12%, var(--bg-surface));
  border-color: var(--positive);
  color: var(--text);
}
.em-toast-info {
  background: color-mix(in srgb, var(--color-accent) 12%, var(--bg-surface));
  border-color: var(--color-accent);
  color: var(--text);
}
/* Light mode needs saying again. base.css carries its own light overrides
   for these three, written as `[data-theme="light"] .em-toast-error`, and
   two selectors beat the one above however the files are ordered. So the
   translucent tint came back in light mode only, and a risk message sat over
   the instrument panel with the panel reading through the text. Same
   selector shape here, and this file loads after base.css. */
[data-theme="light"] .em-toast-error {
  background: color-mix(in srgb, var(--negative) 18%, #fff);
  color: #000;
}
[data-theme="light"] .em-toast-success {
  background: color-mix(in srgb, var(--positive) 12%, var(--bg-surface));
  color: var(--text);
}
[data-theme="light"] .em-toast-info {
  background: color-mix(in srgb, var(--color-accent) 12%, var(--bg-surface));
  color: var(--text);
}

/* ── Instrument panel ──────────────────────────────────────────────── */

/* The detail for whatever the desk has selected. A fixed region rather
   than something that floats over the grid: it is bound to the row's
   identity, not to where that row happens to sit, so a print or a re-sort
   leaves it alone. Capped and scrolling, so a name with three headlines
   never pushes the positions table off the screen. */
/* The panel takes the height of what it holds rather than a share of the
   column, and never more than the ceiling below. A stated height left dead
   space under the limit bar, because how much a name has to show varies:
   a stock carries a limit bar a future does not, and headlines are one line
   or two. Shrinking to the content hands that space to the newsfeed, which
   is the card underneath and the one with no natural end. The ceiling keeps
   a name with two long headlines from eating the column, and the overflow
   is the safety valve for that case rather than the way it is read. */
#pm-workspace .pm-instrument {
  flex: 0 0 auto;
  height: auto;
  max-height: 250px;
  overflow-y: auto;
  padding: 6px 10px 8px;
}
/* Nothing picked yet: the card holds its full height, so the one line sits
   in the middle of it rather than in a strip, and the column does not
   resize the moment a first name is clicked. */
#pm-workspace .pm-instrument--empty {
  min-height: 250px;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
}
/* Two columns, so the panel is read at a glance rather than scrolled. */
#pm-workspace .pm-ip-cols {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 18px;
  margin-top: 2px;
}
#pm-workspace .pm-ip-head {
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: wrap;
}
/* A ticker is a name, not a number, so it is set in the body font like
   every other piece of text. Weight carries it instead. */
#pm-workspace .pm-ip-symbol {
  font-size: 1rem;
  font-weight: 700;
  color: var(--text);
}
#pm-workspace .pm-ip-name { color: var(--text-secondary); font-size: 0.9rem; }
#pm-workspace .pm-ip-tags {
  margin-top: 1px;
  font-size: 0.78rem;
  color: var(--text-muted);
}
/* The region rides beside the sector on a multi-region universe, separated
   by weight rather than by another size or another colour. */
#pm-workspace .pm-ip-region::before { content: '\00b7'; margin: 0 5px; }
/* The price history, with both axes drawn. The room for it came from
   taking bid, ask, the day's move and the position back out of the panel:
   the market grid already prints all four on the row that was clicked. */
#pm-workspace .pm-ip-chart { margin: 6px 0 4px; }
#pm-workspace .pm-ip-chart-svg {
  width: 100%;
  height: auto;
  max-height: 112px;
  display: block;
  font-family: var(--font);
  font-size: 10px;
  /* Moving over the line reads the close under the pointer. */
  cursor: crosshair;
}
/* Axis figures take the mono face, the way every other column of numbers
   on the desk does. The date labels beside them are words and do not. */
#pm-workspace .pm-ip-chart-svg .pm-ip-tick {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}
/* The crosshair readout is what the pointer is there to read, so it is
   larger than the axis ticks. Sizes here are viewBox units: the SVG draws
   at 640 wide and scales to the panel, so 16 renders near 10px. */
#pm-workspace .pm-ip-chart-svg .pm-ip-hover-text { font-size: 16px; }
/* A value that reads as a word rather than a figure. */
#pm-workspace .pm-ip-row .pm-ip-word {
  font-weight: 600;
  color: var(--text);
  text-align: right;
}
#pm-workspace .pm-ip-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 8px;
  padding: 2px 0;
  font-size: 0.85rem;
  color: var(--text-secondary);
}
/* A position's P&L path on hover (owner, 2026-10-07): a card beside the
   positions list, drawn with the instrument panel's chart and its row
   type. It takes no pointer events, so the row under the pointer keeps
   the hover. */
#pm-workspace .pm-pnl-pop {
  position: fixed;
  z-index: 40;
  width: 380px;
  padding: 10px 12px;
  background: var(--bg-elevated);
  /* A neutral edge a step above the --border hairline, which the panels
     under the chart also show (owner, 2026-10-14). */
  border: 1px solid color-mix(in srgb, var(--text-muted) 45%, var(--bg-elevated));
  box-shadow: var(--shadow-md);
  pointer-events: none;
}
#pm-workspace .pm-pnl-pop[hidden] { display: none; }
#pm-workspace .pm-pnl-pop-head,
#pm-workspace .pm-pnl-pop-foot {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 8px;
  font-size: 0.85rem;
  color: var(--text-secondary);
}
#pm-workspace .pm-pnl-pop-head { margin-bottom: 6px; }
#pm-workspace .pm-pnl-pop-foot { margin-top: 6px; }
#pm-workspace .pm-pnl-pop .num {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}
#pm-workspace .pm-pnl-pop .num.positive { color: var(--positive); }
#pm-workspace .pm-pnl-pop .num.negative { color: var(--negative); }
#pm-workspace .pm-ip-row .num {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: var(--text);
}
#pm-workspace .pm-ip-row .num.positive { color: var(--positive); }
#pm-workspace .pm-ip-row .num.negative { color: var(--negative); }
#pm-workspace .pm-ip-subhead {
  font-size: 0.78rem;
  color: var(--text-muted);
  padding: 4px 0 2px;
}
#pm-workspace .pm-ip-limit { margin-top: 4px; }
/* Why a future has no bar where every stock has one. */
#pm-workspace .pm-ip-exempt {
  margin-top: 6px;
  font-size: 0.78rem;
  line-height: 1.35;
  color: var(--text-muted);
}
#pm-workspace .pm-ip-news { margin-top: 4px; }
#pm-workspace .pm-ip-headline {
  display: flex;
  gap: 8px;
  padding: 2px 0;
  font-size: 0.8rem;
  color: var(--text-secondary);
}
#pm-workspace .pm-ip-day { color: var(--text-muted); flex: 0 0 auto; }

/* ── Charts ────────────────────────────────────────────────────────── */


/* The button hangs in the frame's own top-right corner, level with its
   title. The canonical rule anchors it top-left (components.css :2719),
   which lands it on the y-axis labels; overriding the anchor when a frame
   carries a title is the platform's own precedent for that, in futures.css
   .fut-mtm-fs-btn and the lifecycle map. */
#pm-workspace .pm-frame > .chart-fullscreen-btn {
  top: 12px;
  right: 12px;
  left: auto;
}
/* The enlarge button on the positions card anchors to the card, so the
   card is what it is positioned against. */
#pm-workspace .pm-frame { position: relative; }
#pm-workspace .pm-frame > .chart-fullscreen-btn {
  width: 22px;
  height: 22px;
  /* Centred on the caption bar: the bar runs about 28px tall since the
     2026-08-20 chrome pass, so 3px centres a 22px button on it. */
  top: 3px;
  right: 10px;
  z-index: 2;
}
/* The head keeps clear of the button rather than running under it. */
#pm-workspace .pm-positions-frame .pm-frame-head { padding-right: 40px; }

/* ── The redesigned pages: Economy and Charts (2026-10) ────────────────

   The Claude Design handoff design_handoff_economy_charts, owner-approved
   2026-10-11 with the design winning on the look: bordered panes on the
   page ground with 8px gaps, title bars and number cards. The type is
   the owner's later ruling of the same day, the --pm-fs-* sizes, and the
   rows and columns are set for it. These pages fill the viewport the way
   the Trading Desk does, their panes scroll inside themselves, and the
   sidebar folds as they open (app.js `foldSidebarFor`). */

#pm-workspace.pm-fill-active .workspace-content {
  overflow-y: hidden;
  background: var(--bg);
}
#pm-workspace.pm-fill-active .tab-panel.active {
  flex: 1 1 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
#pm-workspace.pm-fill-active .tab-content-area {
  flex: 1 1 0;
  min-height: 0;
  max-width: none;
  padding: 0;
  display: flex;
  flex-direction: column;
}
#pm-workspace.pm-fill-active #pm-economy-content,
#pm-workspace.pm-fill-active #pm-charts-content,
#pm-workspace.pm-fill-active #pm-performance-content,
#pm-workspace.pm-fill-active #pm-debrief-content {
  flex: 1 1 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  /* Numerals tabular, lining and slashed-zero on these pages, so a
     column of figures reads down its digits. */
  font-feature-settings: 'tnum' 1, 'lnum' 1, 'zero' 1;
  font-size: var(--pm-fs-main);
  color: var(--text);
}

/* A table row is one line high. A cell too narrow for its text cuts the
   text short instead of wrapping it over the next row (owner,
   2026-10-11). */
#pm-workspace :is(.pm-ec-row, .pm-ec-hrow, .pm-ec-irow, .pm-ec-rrow, .pm-ec-crow,
                  .pm-ec-urow, .pm-pr-frow, .pm-pr-limrow, .pm-pr-brow,
                  .pm-pr-trow, .pm-pr-nrow, .pm-db-srow, .pm-db-wrow, .pm-db-lrow,
                  .pm-db-mrow, .pm-db-irow, .pm-db-trow, .pm-db-crow) > * {
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* A pane: the surface, a hairline border, square corners. */
#pm-workspace .pm-pane {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  background: var(--bg-surface);
  border: 1px solid var(--border);
}
#pm-workspace .pm-pane .num,
#pm-workspace .pm-subtabs .num {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}
#pm-workspace .pm-pane .right { text-align: right; }
#pm-workspace .pm-pane-head {
  height: 34px;
  flex: none;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 10px;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
#pm-workspace .pm-pane-label {
  font-size: var(--pm-fs-note);
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--text-secondary);
  overflow: hidden;
  text-overflow: ellipsis;
}
#pm-workspace .pm-pane-title {
  font-size: var(--pm-fs-main);
  font-weight: 600;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
}
#pm-workspace .pm-pane-note {
  min-width: 0;
  font-size: var(--pm-fs-note);
  color: var(--text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
}
#pm-workspace .pm-pane-tools {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 6px;
  flex: none;
}
#pm-workspace .pm-pane-expand {
  margin-left: auto;
  padding: 0 2px;
  border: 0;
  background: none;
  color: var(--text-muted);
  font-size: var(--pm-fs-main);
  line-height: 1;
  cursor: pointer;
}
#pm-workspace .pm-pane-tools + .pm-pane-expand,
#pm-workspace .pm-pane-tools .pm-pane-expand { margin-left: 0; }
#pm-workspace .pm-pane-expand:hover { color: var(--text); }
/* A small reading at the right of a title bar that opens something. */
#pm-workspace .pm-pane-aside {
  margin-left: auto;
  padding: 0;
  border: 0;
  background: none;
  font-family: var(--font);
  font-size: var(--pm-fs-note);
  color: var(--text-muted);
  white-space: nowrap;
  cursor: pointer;
}
#pm-workspace .pm-pane-aside .num { color: var(--text); }
#pm-workspace .pm-pane-aside:hover { color: var(--text); }
#pm-workspace .pm-pane-sublabel {
  font-size: var(--pm-fs-note);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
}

/* The design's segmented control. */
#pm-workspace .pm-seg {
  display: inline-flex;
  gap: 2px;
  padding: 1px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 3px;
}
#pm-workspace .pm-seg-opt {
  padding: 1px 8px;
  border: 0;
  border-radius: 2px;
  background: transparent;
  color: var(--text-muted);
  font-family: var(--font);
  font-size: var(--pm-fs-main);
  line-height: 1.5;
  white-space: nowrap;
  cursor: pointer;
}
#pm-workspace .pm-seg-opt:hover { color: var(--text); }
#pm-workspace .pm-seg-opt.is-active { background: var(--color-accent); color: #fff; }

/* A chip that picks one of a few: a release's numbers, a region. */
#pm-workspace .pm-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 9px;
  border: 1px solid var(--border);
  border-radius: 3px;
  background: transparent;
  color: var(--text-secondary);
  font-family: var(--font);
  font-size: var(--pm-fs-main);
  white-space: nowrap;
  cursor: pointer;
}
#pm-workspace .pm-chip.is-active {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: #fff;
}

/* The number cards: a caption, the figure and one line under it. */
#pm-workspace .pm-kpis {
  flex: none;
  display: grid;
  border-bottom: 1px solid var(--border);
}
#pm-workspace .pm-kpis--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
#pm-workspace .pm-kpis--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
#pm-workspace .pm-kpi {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  padding: 7px 10px;
  overflow: hidden;
  border-right: 1px solid var(--pm-subtle);
}
#pm-workspace .pm-kpi-label {
  font-size: var(--pm-fs-label);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
  white-space: nowrap;
}
#pm-workspace .pm-kpi-value {
  font-size: 17px;
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
}
#pm-workspace .pm-kpis--3 .pm-kpi-value { font-size: 16px; }
#pm-workspace .pm-kpi-sub {
  min-height: 15px;
  font-size: var(--pm-fs-label);
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
#pm-workspace .pm-kpi.is-above .pm-kpi-value { color: var(--pm-above); }
#pm-workspace .pm-kpi.is-below .pm-kpi-value { color: var(--pm-below); }
#pm-workspace .pm-kpi.is-muted .pm-kpi-value { color: var(--text-muted); }
#pm-workspace .pm-kpi.is-today { background: var(--pm-today-bg); }
#pm-workspace .pm-kpi.is-today .pm-kpi-sub { color: var(--color-accent-text); }

/* ── Economy ─────────────────────────────────────────────────────────── */

#pm-workspace .pm-ec {
  flex: 1 1 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
#pm-workspace .pm-subtabs {
  height: 50px;
  flex: none;
  display: flex;
  align-items: stretch;
  padding: 0 6px;
  border-bottom: 1px solid var(--border);
  overflow-x: auto;
  scrollbar-width: none;
}
#pm-workspace .pm-subtab {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 1px;
  padding: 0 13px;
  border: 0;
  border-bottom: 2px solid transparent;
  background: transparent;
  font-family: var(--font);
  text-align: left;
  white-space: nowrap;
  cursor: pointer;
}
#pm-workspace .pm-subtab:hover { background: var(--pm-hover); }
#pm-workspace .pm-subtab.is-active {
  background: var(--bg-surface);
  border-bottom-color: var(--color-accent-text);
}
#pm-workspace .pm-subtab-label {
  font-size: var(--pm-fs-main);
  font-weight: 600;
  color: var(--text-muted);
}
#pm-workspace .pm-subtab.is-active .pm-subtab-label { color: var(--text); }
#pm-workspace .pm-subtab-sub { font-size: var(--pm-fs-note); color: var(--text-muted); }
#pm-workspace .pm-ec-main {
  flex: 1 1 0;
  min-height: 0;
  display: flex;
  gap: 8px;
  padding: 8px;
}

/* The calendar: one 28px line per event under sticky day headings. The
   grid's columns are set on the pane (--pm-cal-cols), because the thread
   column comes and goes with the tab. */
#pm-workspace .pm-ec-cal { flex: none; width: 500px; }
#pm-workspace .pm-ec-cal .pm-pane-head { padding: 0 8px; }
#pm-workspace .pm-ec-colhead,
#pm-workspace .pm-ec-row {
  display: grid;
  grid-template-columns: var(--pm-cal-cols);
  gap: 6px;
  align-items: center;
  padding: 0 8px;
}
#pm-workspace .pm-ec-colhead {
  height: 26px;
  flex: none;
  border-bottom: 1px solid var(--border);
  font-size: var(--pm-fs-note);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-muted);
  white-space: nowrap;
}
#pm-workspace .pm-ec-cal-body {
  flex: 1 1 0;
  min-height: 0;
  overflow: auto;
  position: relative;
}
#pm-workspace .pm-ec-dayhead {
  position: sticky;
  top: 0;
  z-index: 1;
  height: 26px;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 0 8px;
  background: var(--bg);
  border-bottom: 1px solid var(--border);
  font-size: var(--pm-fs-note);
  color: var(--text-secondary);
}
#pm-workspace .pm-ec-dayhead.is-today {
  background: var(--pm-today-bg);
  color: var(--color-accent-text);
}
#pm-workspace .pm-ec-dayrel { color: var(--text-muted); }
#pm-workspace .pm-ec-row {
  height: 28px;
  border-bottom: 1px solid var(--pm-subtle);
  cursor: pointer;
}
#pm-workspace .pm-ec-row:hover { background: var(--pm-hover); }
#pm-workspace .pm-ec-row.is-sel { background: var(--pm-sel); }
#pm-workspace .pm-ec-thread {
  font-size: var(--pm-fs-note);
  font-weight: 600;
  color: var(--text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
#pm-workspace .pm-ec-name {
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
#pm-workspace .pm-ec-row.is-past .pm-ec-name { color: var(--text-secondary); }
#pm-workspace .pm-ec-act,
#pm-workspace .pm-ec-row .pm-ec-cons,
#pm-workspace .pm-ec-prev {
  text-align: right;
  font-size: var(--pm-fs-main);
  white-space: nowrap;
  overflow: hidden;
}
#pm-workspace .pm-ec-act { font-weight: 600; color: var(--text); }
#pm-workspace .pm-ec-cons { color: var(--text-table); }
#pm-workspace .pm-ec-prev { color: var(--text-muted); }
#pm-workspace .pm-ec .is-above:not(.pm-kpi):not(.pm-ec-swatch) { color: var(--pm-above); }
#pm-workspace .pm-ec .is-below:not(.pm-kpi):not(.pm-ec-swatch) { color: var(--pm-below); }
#pm-workspace .pm-ec-cal-foot {
  height: 28px;
  flex: none;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 0 8px;
  border-top: 1px solid var(--border);
  font-size: var(--pm-fs-note);
  color: var(--text-muted);
}
#pm-workspace .pm-ec-key {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
#pm-workspace .pm-ec-swatch {
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 1px;
}
#pm-workspace .pm-ec-swatch.is-above { background: var(--pm-above); }
#pm-workspace .pm-ec-swatch.is-below { background: var(--pm-below); }
#pm-workspace .pm-ec-empty { padding: 10px; }
#pm-workspace .pm-ec-muted { color: var(--text-muted); }
#pm-workspace .pm-ec-sec { color: var(--text-secondary); }
#pm-workspace .pm-ec-table { color: var(--text-table); }
#pm-workspace .pm-ec-strong { font-weight: 500; }
#pm-workspace .pm-ec-ellipsis,
#pm-workspace .pm-ec-strong {
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* The release pane: the four cards, the chips of a release with several
   numbers, the legend, the prints and their surprises, and the history. */
#pm-workspace .pm-ec-rel { flex: 1 1 0; }
#pm-workspace .pm-ec-chips {
  flex: none;
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  padding: 6px 10px 0;
}
#pm-workspace .pm-ec-legend {
  flex: none;
  display: flex;
  gap: 12px;
  padding: 6px 10px 0;
  font-size: var(--pm-fs-note);
  color: var(--text-muted);
  white-space: nowrap;
}
#pm-workspace .pm-ec-legend i { display: inline-block; }
#pm-workspace .pm-ec-line { width: 12px; border-top: 2px solid var(--pm-line); }
#pm-workspace .pm-ec-ring {
  width: 7px;
  height: 7px;
  border: 1.2px solid var(--pm-est);
  border-radius: 50%;
}
#pm-workspace .pm-ec-tick { height: 9px; border-left: 1px solid var(--color-accent-text); }
#pm-workspace .pm-ec-dash { height: 9px; border-left: 1px dashed var(--pm-spike); }
#pm-workspace .pm-ec-chart { flex: none; height: 196px; padding: 2px 6px 0; }
#pm-workspace .pm-ec-caption {
  flex: none;
  padding: 0 10px;
  font-size: var(--pm-fs-note);
  color: var(--text-muted);
}
#pm-workspace .pm-ec-bars { flex: none; height: 46px; padding: 0 6px; }
#pm-workspace .pm-ec-hist {
  flex: 1 1 0;
  min-height: 0;
  margin-top: 4px;
  overflow: auto;
  border-top: 1px solid var(--border);
}
#pm-workspace .pm-ec-hrow {
  display: grid;
  grid-template-columns: 80px repeat(3, minmax(0, 1fr));
  gap: 8px;
  align-items: center;
  height: 28px;
  padding: 0 10px;
  border-bottom: 1px solid var(--pm-subtle);
  font-size: var(--pm-fs-main);
}
#pm-workspace .pm-ec-hrow > span:first-child { color: var(--text-muted); }
#pm-workspace .pm-ec-hrow.is-sel { background: var(--pm-sel); }
#pm-workspace .pm-ec-hhead {
  position: sticky;
  top: 0;
  background: var(--bg-surface);
  border-bottom-color: var(--border);
  font-size: var(--pm-fs-note);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-muted);
}

/* The policy column: the rate, its chart and the yields, then the
   decisions, which take what is left and scroll. */
#pm-workspace .pm-ec-side {
  width: 360px;
  flex: none;
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-height: 0;
}
#pm-workspace .pm-ec-policy { flex: none; }
#pm-workspace .pm-ec-rate {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 8px 10px 0;
}
#pm-workspace .pm-ec-rate-value {
  font-size: 20px;
  font-weight: 600;
  white-space: nowrap;
}
#pm-workspace .pm-ec-priced { font-size: var(--pm-fs-label); color: var(--text-muted); }
#pm-workspace .pm-ec-priced .num { color: var(--text); }
#pm-workspace .pm-ec-pol-chart { height: 140px; padding: 4px 4px 0; }
#pm-workspace .pm-ec-yields-head {
  display: flex;
  align-items: center;
  padding: 5px 10px 3px;
  border-top: 1px solid var(--pm-subtle);
}
#pm-workspace .pm-ec-yields {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  padding: 0 0 6px;
}
#pm-workspace .pm-ec-yield {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 2px 10px;
}
#pm-workspace .pm-ec-yield > span:first-child { font-size: var(--pm-fs-note); color: var(--text-muted); }
#pm-workspace .pm-ec-yield .num { font-size: var(--pm-fs-main); }
#pm-workspace .pm-ec-decisions { flex: 1 1 0; }
#pm-workspace .pm-ec-dec-list { flex: 1 1 0; min-height: 0; overflow: auto; }
#pm-workspace .pm-ec-dec {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 1px;
  min-height: 34px;
  padding: 4px 10px;
  border-bottom: 1px solid var(--pm-subtle);
}
#pm-workspace .pm-ec-dec-line {
  display: grid;
  grid-template-columns: 74px minmax(0, 1fr) auto;
  gap: 6px;
  align-items: center;
  font-size: var(--pm-fs-main);
  color: var(--text);
}
#pm-workspace .pm-ec-dec-line > span:nth-child(2) {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
#pm-workspace .pm-ec-dec-line > :last-child { font-weight: 500; white-space: nowrap; }
#pm-workspace .pm-ec-dec.is-ahead .pm-ec-dec-line { color: var(--text-muted); }
#pm-workspace .pm-ec-vote {
  padding-left: 80px;
  font-size: var(--pm-fs-note);
  color: var(--text-muted);
}
#pm-workspace .pm-ec-vote .num { color: var(--text-secondary); }

/* A sector's middle pane: the issuers and their results (credit), or the
   companies' results (equity). */
#pm-workspace .pm-ec-iss { flex: 1 1 0; }
#pm-workspace .pm-ec-ihead,
#pm-workspace .pm-ec-irow {
  display: grid;
  grid-template-columns: minmax(120px, 1fr) 56px 72px 56px 96px 64px 68px;
  gap: 6px;
  padding: 0 10px;
}
#pm-workspace .pm-ec-ihead,
#pm-workspace .pm-ec-rhead,
#pm-workspace .pm-ec-chead,
#pm-workspace .pm-ec-uhead {
  flex: none;
  align-items: end;
  padding-top: 5px;
  padding-bottom: 5px;
  border-bottom: 1px solid var(--border);
  font-size: var(--pm-fs-note);
  line-height: 1.25;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--text-muted);
}
#pm-workspace .pm-ec-irow {
  height: 34px;
  align-items: center;
  border-bottom: 1px solid var(--pm-subtle);
  font-size: var(--pm-fs-main);
  cursor: pointer;
}
#pm-workspace .pm-ec-ibody { flex: none; }
#pm-workspace .pm-ec-subhead {
  flex: none;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 10px 4px;
}
#pm-workspace .pm-ec-rhead,
#pm-workspace .pm-ec-rrow {
  display: grid;
  grid-template-columns: 32px minmax(100px, 1fr) 92px 92px 100px 82px 56px;
  gap: 6px;
  padding-left: 10px;
  padding-right: 10px;
}
#pm-workspace .pm-ec-chead,
#pm-workspace .pm-ec-crow {
  display: grid;
  grid-template-columns: 32px minmax(120px, 1fr) 74px 72px 100px 82px 60px;
  gap: 6px;
  padding-left: 10px;
  padding-right: 10px;
}
#pm-workspace .pm-ec-uhead,
#pm-workspace .pm-ec-urow {
  display: grid;
  grid-template-columns: 32px minmax(0, 1fr) 76px;
  gap: 6px;
  padding-left: 10px;
  padding-right: 10px;
}
#pm-workspace .pm-ec-uhead { margin-top: 10px; }
#pm-workspace .pm-ec-rbody { flex: 1 1 0; min-height: 0; overflow: auto; }
#pm-workspace .pm-ec-rrow,
#pm-workspace .pm-ec-crow,
#pm-workspace .pm-ec-urow {
  height: 30px;
  align-items: center;
  border-bottom: 1px solid var(--pm-subtle);
  font-size: var(--pm-fs-main);
}
#pm-workspace .pm-ec-rrow { cursor: pointer; }
#pm-workspace .pm-ec-irow:hover,
#pm-workspace .pm-ec-rrow:hover { background: var(--pm-hover); }
#pm-workspace .pm-ec-irow.is-sel,
#pm-workspace .pm-ec-rrow.is-sel { background: var(--pm-sel); }

/* A sector's right pane: the issuer picked (credit), or the sector's
   expected earnings growth (equity). */
#pm-workspace .pm-ec-detail { width: 300px; flex: none; }
#pm-workspace .pm-ec-dlabel { padding: 8px 10px 2px; }
#pm-workspace .pm-ec-ruled { border-top: 1px solid var(--pm-subtle); }
#pm-workspace .pm-ec-cds-chart { flex: none; height: 150px; padding: 0 4px; }
#pm-workspace .pm-ec-lev {
  flex: none;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 8px 10px 4px;
  border-top: 1px solid var(--pm-subtle);
}
#pm-workspace .pm-ec-lev-track { position: relative; height: 18px; }
#pm-workspace .pm-ec-lev-track::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: 8px;
  height: 2px;
  background: var(--pm-track);
}
#pm-workspace .pm-ec-lev-tick {
  position: absolute;
  top: 3px;
  height: 12px;
  border-left: 1px solid var(--text-muted);
}
#pm-workspace .pm-ec-lev-dot {
  position: absolute;
  top: 4px;
  width: 10px;
  height: 10px;
  margin-left: -5px;
  border-radius: 50%;
  background: var(--text);
}
#pm-workspace .pm-ec-lev-labels {
  position: relative;
  height: 17px;
  font-size: var(--pm-fs-note);
  color: var(--text-muted);
}
#pm-workspace .pm-ec-lev-labels > span {
  position: absolute;
  transform: translateX(-50%);
  white-space: nowrap;
}
#pm-workspace .pm-ec-dlines { padding: 0 0 6px; overflow: auto; }
#pm-workspace .pm-ec-dline {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 6px;
  padding: 3px 10px;
  font-size: var(--pm-fs-main);
}
#pm-workspace .pm-ec-dline > span:last-child { white-space: nowrap; color: var(--text); }
#pm-workspace .pm-ec-detail .pm-pane-head + .pm-ec-dlines { padding-top: 6px; }

/* ── Charts ──────────────────────────────────────────────────────────

   The chart in focus, the saved charts and the Curves card in the left
   column, the position tiles in a 560px column beside them. The grid's
   rows are set by the page (charts.js `layoutGrid`), because the Curves
   row comes and goes. */

#pm-workspace .pm-ch {
  flex: 1 1 0;
  min-height: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 560px;
  gap: 8px;
  padding: 8px;
}
#pm-workspace .pm-ch-focus { grid-area: focus; }
#pm-workspace .pm-ch-saved { grid-area: saved; }
#pm-workspace .pm-ch-curves { grid-area: curves; }
#pm-workspace .pm-ch-pos { grid-area: positions; }
#pm-workspace .pm-ch .num { font-family: var(--font-mono); }
#pm-workspace .pm-ch .is-pos:not(.pm-ch-key-box) { color: var(--positive); }
#pm-workspace .pm-ch .is-neg:not(.pm-ch-key-box) { color: var(--negative); }
#pm-workspace .pm-ch-table { color: var(--text-table); }
#pm-workspace .pm-ch-muted { color: var(--text-muted); }

/* The toolbar: the instrument, the comparison, the range and the saves. */
#pm-workspace .pm-ch-toolbar {
  position: relative;
  height: 42px;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 0 8px;
  border-bottom: 1px solid var(--border);
}
#pm-workspace .pm-ch-search {
  width: 240px;
  height: 30px;
  flex: none;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 0 8px;
  border: 1px solid var(--border);
  border-radius: 3px;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: var(--pm-fs-main);
  cursor: pointer;
}
#pm-workspace .pm-ch-glyph { color: var(--text-muted); font-size: var(--pm-fs-main); }
#pm-workspace .pm-ch-search-sym { font-weight: 600; white-space: nowrap; }
#pm-workspace .pm-ch-search-name {
  min-width: 0;
  color: var(--text-secondary);
  font-size: var(--pm-fs-main);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
#pm-workspace .pm-ch-caret { margin-left: auto; color: var(--text-muted); font-size: 12px; }
/* The field a name is typed into: in the toolbar while the instrument in
   focus is picked, at the head of the picker while one is added to the
   comparison. */
#pm-workspace .pm-ch-search.is-open {
  border-color: var(--color-accent);
  cursor: text;
}
#pm-workspace .pm-ch-query {
  flex: 1 1 auto;
  min-width: 0;
  height: 100%;
  padding: 0;
  border: 0;
  outline: none;
  background: transparent;
  color: var(--text);
  font-family: var(--font);
  font-size: var(--pm-fs-main);
}
#pm-workspace .pm-ch-query::placeholder { color: var(--text-muted); }
#pm-workspace .pm-ch-chip {
  height: 28px;
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 0 4px 0 7px;
  border: 1px solid var(--border);
  border-radius: 3px;
  white-space: nowrap;
}
#pm-workspace .pm-ch-swatch {
  display: inline-block;
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 2px;
}
#pm-workspace .pm-ch-swatch--sm { width: 6px; height: 6px; border-radius: 1px; }
#pm-workspace .pm-ch-chip-sym { font-size: var(--pm-fs-main); font-weight: 600; }
#pm-workspace .pm-ch-x {
  padding: 0 3px;
  border: 0;
  background: none;
  color: var(--text-muted);
  font-size: var(--pm-fs-main);
  line-height: 1;
  cursor: pointer;
}
#pm-workspace .pm-ch-x:hover { color: var(--text); }
#pm-workspace .pm-ch-add {
  height: 28px;
  display: flex;
  align-items: center;
  padding: 0 8px;
  border: 1px dashed var(--border);
  border-radius: 3px;
  background: none;
  color: var(--text-secondary);
  font-family: var(--font);
  font-size: var(--pm-fs-main);
  white-space: nowrap;
  cursor: pointer;
}
#pm-workspace .pm-ch-add:hover { color: var(--text); }
#pm-workspace .pm-ch-tools {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 6px;
  flex: none;
}
#pm-workspace .pm-ch-name {
  width: 130px;
  height: 28px;
  padding: 0 6px;
  border: 1px solid var(--color-accent);
  border-radius: 3px;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: var(--pm-fs-main);
  outline: none;
}
#pm-workspace .pm-ch-btn {
  height: 28px;
  display: flex;
  align-items: center;
  padding: 0 9px;
  border: 1px solid var(--border);
  border-radius: 3px;
  background: transparent;
  color: var(--text);
  font-family: var(--font);
  font-size: var(--pm-fs-main);
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
}
#pm-workspace .pm-ch-btn.is-active {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: #fff;
}
#pm-workspace .pm-ch-btn--quiet { font-weight: 400; color: var(--text-secondary); }
#pm-workspace .pm-ch-btn:hover:not(:disabled):not(.is-active) { background: var(--pm-hover); }
#pm-workspace .pm-ch-btn:disabled,
#pm-workspace .pm-ch-add:disabled { opacity: 0.5; cursor: default; }

/* The instrument picker: the one dropdown with a shadow. */
#pm-workspace .pm-ch-picker {
  position: absolute;
  left: 8px;
  top: 38px;
  z-index: 5;
  width: 360px;
  max-height: 420px;
  overflow: auto;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
}
#pm-workspace .pm-ch-picker-head {
  position: sticky;
  top: 0;
  z-index: 1;
  height: 34px;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 0 8px;
  background: var(--bg-surface);
  border-bottom: 1px solid var(--border);
  color: var(--text-muted);
}
#pm-workspace .pm-ch-picker-head .pm-ch-x { margin-left: auto; }
#pm-workspace .pm-ch-pick-group {
  padding: 6px 8px 2px;
  font-size: var(--pm-fs-note);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
}
#pm-workspace .pm-ch-pick-row {
  width: 100%;
  height: 30px;
  display: grid;
  grid-template-columns: 70px minmax(0, 1fr) auto;
  gap: 6px;
  align-items: center;
  padding: 0 8px;
  border: 0;
  background: transparent;
  color: var(--text);
  font-family: var(--font);
  font-size: var(--pm-fs-main);
  text-align: left;
  cursor: pointer;
}
#pm-workspace .pm-ch-pick-row:hover,
#pm-workspace .pm-ch-pick-row.is-active { background: var(--pm-hover); }
#pm-workspace .pm-ch-pick-row.is-sel { background: var(--pm-sel); }
#pm-workspace .pm-ch-pick-sym,
#pm-workspace .pm-ch-pick-name {
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
#pm-workspace .pm-ch-pick-sym { font-weight: 600; }
#pm-workspace .pm-ch-pick-name { color: var(--text-secondary); }
#pm-workspace .pm-ch-pick-held { font-size: var(--pm-fs-note); }

/* The reading line and the legend under the toolbar. */
#pm-workspace .pm-ch-info {
  height: 30px;
  flex: none;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 0 10px;
  border-bottom: 1px solid var(--pm-subtle);
  white-space: nowrap;
  overflow: hidden;
}
#pm-workspace .pm-ch-info:empty { display: none; }
#pm-workspace .pm-ch-info-item { display: flex; align-items: baseline; gap: 5px; }
#pm-workspace .pm-ch-info-label { font-size: var(--pm-fs-note); color: var(--text-muted); }
#pm-workspace .pm-ch-info-value { font-size: var(--pm-fs-main); color: var(--text); }
#pm-workspace .pm-ch-info-value.is-strong { font-weight: 600; }
#pm-workspace .pm-ch-legend {
  height: 22px;
  flex: none;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 0 10px;
  font-size: var(--pm-fs-note);
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
}
#pm-workspace .pm-ch-legend:empty { display: none; }
#pm-workspace .pm-ch-key { display: inline-flex; align-items: center; gap: 4px; }
#pm-workspace .pm-ch-key i { display: inline-block; }
#pm-workspace .pm-ch-key-line { width: 12px; border-top: 2px solid; }
#pm-workspace .pm-ch-key-diamond {
  width: 7px;
  height: 7px;
  background: var(--pm-news);
  transform: rotate(45deg);
}
#pm-workspace .pm-ch-key-box { width: 7px; height: 7px; border-radius: 1px; }
#pm-workspace .pm-ch-key-box.is-pos { background: var(--positive); }
#pm-workspace .pm-ch-key-box.is-neg { background: var(--negative); }
#pm-workspace .pm-ch-key-dash { width: 14px; border-top: 1px dashed var(--text-secondary); }
#pm-workspace .pm-ch-key-day0 { width: 2px; height: 10px; background: var(--pm-spike); }

/* The plot and, under it on the same days, the position strip. Each has
   a layer for the crosshair laid over it, placed on the plot's own box. */
#pm-workspace .pm-ch-plot {
  position: relative;
  flex: 1 1 0;
  min-height: 0;
  padding: 0 4px;
}
#pm-workspace .pm-ch-chart { width: 100%; height: 100%; }
#pm-workspace .pm-ch-empty {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0;
}
#pm-workspace .pm-ch-cross {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 4px;
  right: 4px;
  pointer-events: none;
}
#pm-workspace .pm-ch-vline {
  position: absolute;
  width: 0;
  border-left: 1px dashed var(--text-secondary);
  opacity: 0.7;
}
#pm-workspace .pm-ch-hline {
  position: absolute;
  height: 0;
  border-top: 1px dashed var(--text-secondary);
  opacity: 0.5;
}
#pm-workspace .pm-ch-ybox {
  position: absolute;
  transform: translateY(-50%);
  height: 20px;
  padding: 0 4px;
  border: 1px solid var(--border);
  background: var(--pm-tip-bg);
  color: var(--text);
  font-size: var(--pm-fs-note);
  line-height: 18px;
  white-space: nowrap;
}
#pm-workspace .pm-ch-dot {
  position: absolute;
  width: 7px;
  height: 7px;
  margin: -3.5px 0 0 -3.5px;
  border-radius: 50%;
  box-shadow: 0 0 0 1.5px var(--bg-surface);
}
#pm-workspace .pm-ch-tip {
  position: absolute;
  z-index: 2;
  padding: 5px 8px;
  border: 1px solid var(--border);
  border-radius: 2px;
  background: var(--pm-tip-bg);
  color: var(--text-muted);
  font-size: var(--pm-fs-note);
  white-space: nowrap;
  max-width: 280px;
}
/* A headline wraps inside the box's width; the readings above it do not. */
#pm-workspace .pm-ch-tip-text {
  margin: 2px 0;
  line-height: 18px;
  white-space: normal;
}
#pm-workspace .pm-ch-tip-line {
  display: flex;
  justify-content: space-between;
  gap: 14px;
  line-height: 18px;
}
#pm-workspace .pm-ch-tip-line.is-bold { font-weight: 600; }
#pm-workspace .pm-ch-tip-line .num { color: var(--text); }
#pm-workspace .pm-ch-strip {
  position: relative;
  flex: none;
  height: 51px;
  padding: 0 4px;
  border-top: 1px solid var(--pm-subtle);
}
#pm-workspace .pm-ch-strip-chart { width: 100%; height: 50px; }
#pm-workspace .pm-ch-strip-label {
  position: absolute;
  left: 8px;
  top: 50%;
  z-index: 1;
  transform: translateY(-50%);
  font-size: var(--pm-fs-note);
  color: var(--text-muted);
}

/* The saved charts: four tiles to the row's width, more by scrolling. */
#pm-workspace .pm-ch-saved-title {
  height: 30px;
  flex: none;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 10px;
}
#pm-workspace .pm-ch-saved-grid {
  flex: 1 1 0;
  min-height: 0;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: calc((100% - 18px) / 4);
  gap: 6px;
  padding: 0 6px 6px;
  overflow-x: auto;
}
#pm-workspace .pm-ch-saved-tile,
#pm-workspace .pm-ch-tile {
  min-width: 0;
  display: flex;
  flex-direction: column;
  border: 1px solid var(--border);
  cursor: pointer;
}
#pm-workspace .pm-ch-saved-tile:hover,
#pm-workspace .pm-ch-tile:hover { background: var(--pm-hover); }
#pm-workspace .pm-ch-saved-tile.is-sel,
#pm-workspace .pm-ch-tile.is-sel {
  background: var(--pm-sel);
  border-color: var(--color-accent);
}
#pm-workspace .pm-ch-saved-head {
  height: 22px;
  flex: none;
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 0 6px;
}
#pm-workspace .pm-ch-saved-name {
  min-width: 0;
  font-size: var(--pm-fs-main);
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
#pm-workspace .pm-ch-saved-head .pm-ch-x { margin-left: auto; }
/* The lines are drawn again with every print, so they take no pointer:
   the click lands on the tile, which stays put. */
#pm-workspace .pm-ch-saved-spark,
#pm-workspace .pm-ch-tile-spark {
  flex: 1 1 0;
  min-height: 0;
  pointer-events: none;
}
#pm-workspace .pm-ch-saved-spark svg,
#pm-workspace .pm-ch-tile-spark svg { display: block; height: 100%; }

/* The Curves card, open or folded to one line. */
#pm-workspace .pm-ch-curves-head {
  height: 34px;
  padding: 0 8px;
  border-bottom-color: var(--pm-subtle);
}
#pm-workspace .pm-ch-modes {
  min-width: 0;
  display: flex;
  overflow-x: auto;
  scrollbar-width: none;
}
#pm-workspace .pm-ch-toggle { margin-left: auto; height: 26px; font-size: var(--pm-fs-main); }
#pm-workspace .pm-ch-summary {
  min-width: 0;
  display: flex;
  gap: 10px;
  overflow: hidden;
  font-size: var(--pm-fs-note);
  color: var(--text-muted);
  white-space: nowrap;
}
#pm-workspace .pm-ch-summary b { color: var(--text-secondary); font-weight: 600; }
#pm-workspace .pm-ch-summary .pm-ch-text { color: var(--text); }
#pm-workspace .pm-ch-curve-chips {
  height: 34px;
  flex: none;
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 0 8px;
  overflow: hidden;
}
#pm-workspace .pm-ch-region { padding: 1px 7px; }
#pm-workspace .pm-ch-region.is-picked {
  background: var(--pm-sel);
  border-color: var(--color-accent);
}
#pm-workspace .pm-ch-region:not(.is-picked) { color: var(--text-muted); }
#pm-workspace .pm-ch-curve-legend {
  margin-left: auto;
  display: flex;
  gap: 10px;
  font-size: var(--pm-fs-note);
  color: var(--text-muted);
  white-space: nowrap;
}
#pm-workspace .pm-ch-curve-body { flex: 1 1 0; min-height: 0; padding: 0 4px 4px; }
#pm-workspace .pm-ch-curve-chart { width: 100%; height: 100%; }

/* The position tiles: two to a row, sorted by the header's chips. */
#pm-workspace .pm-ch-pos-head { height: 34px; gap: 6px; padding: 0 8px; }
#pm-workspace .pm-ch-sorts { gap: 2px; font-size: var(--pm-fs-note); color: var(--text-muted); }
#pm-workspace .pm-ch-sort {
  padding: 1px 6px;
  border: 0;
  border-radius: 2px;
  background: transparent;
  color: var(--text-secondary);
  font-family: var(--font);
  font-size: var(--pm-fs-main);
  white-space: nowrap;
  cursor: pointer;
}
#pm-workspace .pm-ch-sort.is-active { background: var(--color-accent); color: #fff; }
#pm-workspace .pm-ch-tiles {
  flex: 1 1 0;
  min-height: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-auto-rows: 134px;
  align-content: start;
  gap: 6px;
  padding: 6px;
  overflow: auto;
}
#pm-workspace .pm-ch-empty-msg { grid-column: 1 / -1; padding: 4px; }
#pm-workspace .pm-ch-tile-head {
  height: 26px;
  flex: none;
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 0 6px;
}
#pm-workspace .pm-ch-tile-sym { font-weight: 600; }
#pm-workspace .pm-ch-tile-name {
  min-width: 0;
  color: var(--text-muted);
  font-size: var(--pm-fs-note);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
#pm-workspace .pm-ch-tile-side { margin-left: auto; font-size: var(--pm-fs-note); white-space: nowrap; }
#pm-workspace .pm-ch-tile-cmp {
  padding: 0 0 0 2px;
  border: 0;
  background: none;
  color: var(--text-muted);
  font-size: var(--pm-fs-main);
  line-height: 1;
  cursor: pointer;
}
#pm-workspace .pm-ch-tile-cmp.is-on { color: var(--color-accent-text); }
#pm-workspace .pm-ch-tile-cmp:hover { color: var(--text); }
#pm-workspace .pm-ch-tile-foot {
  height: 40px;
  flex: none;
  display: grid;
  grid-template-columns: auto auto minmax(0, 1fr) auto;
  gap: 8px;
  align-items: center;
  padding: 0 6px;
  border-top: 1px solid var(--pm-subtle);
  white-space: nowrap;
}
#pm-workspace .pm-ch-tile-foot > span { display: flex; flex-direction: column; }
#pm-workspace .pm-ch-tile-foot > span.right { align-items: flex-end; }
#pm-workspace .pm-ch-cell-label { font-size: var(--pm-fs-label); color: var(--text-muted); }
#pm-workspace .pm-ch-tile-foot .num { font-size: var(--pm-fs-note); }

/* ── Performance & Risk ──────────────────────────────────────────────

   Analytics and Risk in one page with four sub-pages (the 2026-10
   redesign, direction 5c). Each sub-page is a grid of panes that fills
   the viewport; the tables inside the panes scroll. */

#pm-workspace .pm-pr,
#pm-workspace .pm-db {
  flex: 1 1 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
#pm-workspace .pm-pr .num,
#pm-workspace .pm-db .num { font-family: var(--font-mono); }
#pm-workspace .pm-pr .is-pos,
#pm-workspace .pm-db .is-pos { color: var(--positive); }
#pm-workspace .pm-pr .is-neg,
#pm-workspace .pm-db .is-neg { color: var(--negative); }
#pm-workspace .pm-pr .is-warn { color: var(--warning); }
#pm-workspace .pm-pr .is-strong,
#pm-workspace .pm-db .is-strong { font-weight: 600; }
#pm-workspace .pm-pr-muted,
#pm-workspace .pm-db-muted { color: var(--text-muted); }
#pm-workspace .pm-pr-sec,
#pm-workspace .pm-db-sec { color: var(--text-secondary); }
#pm-workspace .pm-pr-table,
#pm-workspace .pm-db-table { color: var(--text-table); }
#pm-workspace .pm-pr-text,
#pm-workspace .pm-db-text { color: var(--text); }
#pm-workspace .pm-pr-ellipsis,
#pm-workspace .pm-db-ellipsis {
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
#pm-workspace .pm-pr-empty { padding: 10px; }
/* A chart as tall as its rows, scrolling inside its pane (Volatility by
   position, the P&L decomposition). The chart's height is written by the
   script. */
#pm-workspace .pm-pr-rows { flex: 1 1 0; min-height: 0; overflow-x: hidden; overflow-y: auto; }
#pm-workspace .pm-pr-rows > .pm-pr-chart { flex: none; padding: 0; }
/* A chart on Performance & Risk has no padding: Plotly sizes its plot to
   the whole element, padding included, and draws it inside the padding,
   so a padded chart ran past its element. An enlarged pane scrolls what
   runs past, and the overflow showed as a scroll bar (owner, 2026-10-13). */
#pm-workspace .pm-pr-chart {
  flex: 1 1 0;
  min-height: 0;
}
#pm-workspace .pm-db-chart {
  flex: 1 1 0;
  min-height: 0;
  padding: 4px 4px 2px;
}

/* The line of an open breach, above every sub-page. The colour is the
   breach's: a negative ground at low alpha with a negative rule under it. */
#pm-workspace .pm-pr-banner {
  height: 34px;
  flex: none;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 14px;
  background: rgba(239, 68, 68, 0.12);
  border-bottom: 1px solid var(--negative);
  font-size: var(--pm-fs-main);
  white-space: nowrap;
  overflow: hidden;
}
[data-theme="light"] #pm-workspace .pm-pr-banner { background: rgba(220, 38, 38, 0.08); }
#pm-workspace .pm-pr-banner-title { color: var(--negative); font-weight: 700; }
#pm-workspace .pm-pr-banner-sec { color: var(--text-secondary); }
#pm-workspace .pm-pr-banner-go {
  margin-left: auto;
  padding: 0;
  border: 0;
  background: none;
  color: var(--color-accent-text);
  font-family: var(--font);
  font-size: var(--pm-fs-main);
  font-weight: 600;
  cursor: pointer;
}

#pm-workspace .pm-pr-grid {
  flex: 1 1 0;
  min-height: 0;
  display: grid;
  gap: 8px;
  padding: 8px;
}
#pm-workspace .pm-pr-grid--pnl {
  grid-template-columns: minmax(0, 600fr) minmax(0, 534fr);
  grid-template-rows: minmax(0, 330fr) minmax(0, 270fr) auto;
  grid-template-areas: 'decomp names' 'equity names' 'costs names';
}
/* The ladder's row never shrinks below the ladder's scale and steps, so
   the steps stay on screen in a short window; the VaR chart above gives
   way instead. */
#pm-workspace .pm-pr-grid--risk {
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  grid-template-rows: minmax(0, 300fr) auto minmax(auto, 254fr);
  grid-template-areas: 'var vol' 'measures vol' 'ladder vol';
}
#pm-workspace .pm-pr-grid--risk.has-dv01 {
  grid-template-rows: minmax(0, 1fr) minmax(0, 1fr) auto minmax(auto, 1fr);
  grid-template-areas: 'var vol' 'dv01 vol' 'measures vol' 'ladder vol';
}
#pm-workspace .pm-pr-grid--risk.no-ladder {
  grid-template-rows: minmax(0, 1fr) auto;
  grid-template-areas: 'var vol' 'measures vol';
}
#pm-workspace .pm-pr-grid--risk.has-dv01.no-ladder {
  grid-template-rows: minmax(0, 1fr) minmax(0, 1fr) auto;
  grid-template-areas: 'var vol' 'dv01 vol' 'measures vol';
}
#pm-workspace .pm-pr-grid--limits {
  grid-template-columns: minmax(0, 640fr) minmax(0, 494fr);
  grid-template-rows: minmax(0, 530fr) minmax(0, 262fr);
  grid-template-areas: 'limits usage' 'limits breaches';
}
#pm-workspace .pm-pr-grid--trades {
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: minmax(0, 1fr);
}
#pm-workspace .pm-pr-decomp { grid-area: decomp; }
#pm-workspace .pm-pr-equity { grid-area: equity; }
#pm-workspace .pm-pr-costs { grid-area: costs; }
#pm-workspace .pm-pr-names { grid-area: names; }
#pm-workspace .pm-pr-var { grid-area: var; }
#pm-workspace .pm-pr-dv01 { grid-area: dv01; }
#pm-workspace .pm-pr-vol { grid-area: vol; }
#pm-workspace .pm-pr-measures { grid-area: measures; }
#pm-workspace .pm-pr-ladder { grid-area: ladder; min-height: auto; }
#pm-workspace .pm-pr-limits { grid-area: limits; }
#pm-workspace .pm-pr-usage { grid-area: usage; }
#pm-workspace .pm-pr-breaches { grid-area: breaches; }

/* A legend in a title bar, and its keys. */
#pm-workspace .pm-pr-legend {
  display: flex;
  gap: 10px;
  font-size: var(--pm-fs-note);
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
}
#pm-workspace .pm-pr-key { display: inline-flex; align-items: center; gap: 4px; }
#pm-workspace .pm-pr-key > i {
  display: inline-block;
  width: 12px;
  border-top: 2px solid;
}
#pm-workspace .pm-pr-key > i.pm-pr-sq { width: 8px; height: 8px; border: 0; }
#pm-workspace .pm-pr-note { font-size: var(--pm-fs-note); color: var(--text-muted); white-space: nowrap; }
#pm-workspace .pm-pr-total { font-size: var(--pm-fs-note); color: var(--text-muted); }

/* The decomposition: the waterfall and the factor table beside it. */
#pm-workspace .pm-pr-decomp-body { flex: 1 1 0; min-height: 0; display: flex; }
#pm-workspace .pm-pr-decomp-body .pm-pr-rows { min-width: 0; padding-top: 4px; }
#pm-workspace .pm-pr-factors {
  flex: none;
  display: flex;
  flex-direction: column;
  min-height: 0;
  border-left: 1px solid var(--pm-subtle);
}
#pm-workspace .pm-pr-fhead,
#pm-workspace .pm-pr-frow {
  display: grid;
  grid-template-columns: 12px minmax(0, 1fr) auto;
  gap: 2px;
  align-items: center;
  height: 28px;
  padding: 0 8px;
}
#pm-workspace .pm-pr-fhead {
  flex: none;
  grid-template-columns: minmax(0, 1fr) auto;
  border-bottom: 1px solid var(--border);
  font-size: var(--pm-fs-note);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-muted);
}
#pm-workspace .pm-pr-fbody { flex: 1 1 0; min-height: 0; overflow: auto; }
#pm-workspace .pm-pr-frow {
  border-bottom: 1px solid var(--pm-subtle);
  font-size: var(--pm-fs-main);
}
#pm-workspace .pm-pr-frow.is-toggle { cursor: pointer; }
#pm-workspace .pm-pr-frow:hover { background: var(--pm-hover); }
#pm-workspace .pm-pr-frow.is-sub {
  padding-left: 20px;
  font-size: var(--pm-fs-note);
  color: var(--text-secondary);
}
#pm-workspace .pm-pr-frow.is-total { font-weight: 600; }
#pm-workspace .pm-pr-arrow { font-size: 12px; color: var(--text-muted); }

/* Trading costs: two columns of label and value rows, filled downwards. */
#pm-workspace .pm-pr-cost-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-template-rows: repeat(4, 30px);
  grid-auto-flow: column;
}
#pm-workspace .pm-pr-cost {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 0 10px;
  border-bottom: 1px solid var(--pm-subtle);
  border-right: 1px solid var(--pm-subtle);
}
#pm-workspace .pm-pr-cost.is-strong { font-weight: 600; }
#pm-workspace .pm-pr-cost-label {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  color: var(--text-secondary);
  white-space: nowrap;
}

/* The formula and Reference buttons as the design's small chip, as in
   the sidebar. */
#pm-workspace .pm-pr .formula-btn,
#pm-workspace .pm-db .formula-btn {
  width: auto;
  height: 18px;
  padding: 0 4px;
  margin-left: 4px;
  border-radius: 3px;
  background: transparent;
}

/* P&L by name: a sortable table with an inline bar of the after-charges
   P&L, every name on one scale, and the total pinned under it. The
   heading, the rows and the total are rows of one grid (each row a
   subgrid), so the columns line up and size to their content. The
   empty row before the total takes the space the rows leave, which
   keeps the total at the foot of the pane; when the rows overflow,
   the heading and the total stay in view while the rows scroll. */
/* The columns are as wide as their widest number and every number is set
   to the right, so the gap is all that separates one column's numbers from
   the next: at 6px commissions and carry ran together (owner, 2026-10-13). */
#pm-workspace .pm-pr-ntable {
  flex: 1 1 0;
  min-height: 0;
  overflow: auto;
  display: grid;
  column-gap: 16px;
}
#pm-workspace .pm-pr-nhead,
#pm-workspace .pm-pr-nrow {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: subgrid;
  align-items: center;
  padding: 0 10px;
}
#pm-workspace .pm-pr-nspan { grid-column: 1 / -1; }
#pm-workspace .pm-pr-nhead {
  position: sticky;
  top: 0;
  z-index: 1;
  align-items: end;
  padding-top: 4px;
  padding-bottom: 4px;
  background: var(--bg-surface);
  border-bottom: 1px solid var(--border);
}
#pm-workspace .pm-pr-sorthead {
  padding: 0;
  border: 0;
  background: none;
  font-family: var(--font);
  font-size: var(--pm-fs-note);
  line-height: 1.25;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--text-muted);
  text-align: left;
  cursor: pointer;
}
#pm-workspace .pm-pr-sorthead.right { text-align: right; }
/* A heading is as wide as its words, and the sort mark sits after it in
   the gap between the columns: in the heading's width it pushed a heading
   onto a second line when the column was sorted (owner, 2026-10-13). */
#pm-workspace .pm-pr-sorthead { position: relative; justify-self: start; }
#pm-workspace .pm-pr-sorthead.right { justify-self: end; }
#pm-workspace .pm-pr-sortmark { position: absolute; left: 100%; bottom: 0; padding-left: 2px; }
#pm-workspace .pm-pr-sorthead:hover,
#pm-workspace .pm-pr-sorthead.is-on { color: var(--text); }
#pm-workspace .pm-pr-nrow {
  height: 28px;
  border-bottom: 1px solid var(--pm-subtle);
  font-size: var(--pm-fs-main);
}
#pm-workspace .pm-pr-nrow:hover { background: var(--pm-hover); }
#pm-workspace .pm-pr-nrow.is-group {
  background: var(--bg);
  font-size: var(--pm-fs-main);
  font-weight: 600;
}
#pm-workspace .pm-pr-ngroup {
  grid-column: 1 / span 2;
  min-width: 0;
  color: var(--text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
#pm-workspace .pm-pr-nrow.is-total {
  position: sticky;
  bottom: 0;
  background: var(--bg-surface);
  height: 30px;
  border-top: 1px solid var(--border);
  border-bottom: 0;
  font-weight: 600;
}
#pm-workspace .pm-pr-nbar { position: relative; height: 10px; }
#pm-workspace .pm-pr-nbar > i { position: absolute; }
#pm-workspace .pm-pr-nzero {
  left: 50%;
  top: -2px;
  bottom: -2px;
  border-left: 1px solid var(--pm-spike);
}
#pm-workspace .pm-pr-nfill { top: 0; bottom: 0; opacity: 0.85; }
#pm-workspace .pm-pr-nfill.is-pos { background: var(--positive); }
#pm-workspace .pm-pr-nfill.is-neg { background: var(--negative); }

/* The risk measures: a 3 by 2 grid of readings, then the band. */
#pm-workspace .pm-pr-measure-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }
#pm-workspace .pm-pr-measure {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 5px 10px;
  border-right: 1px solid var(--pm-subtle);
  border-bottom: 1px solid var(--pm-subtle);
}
#pm-workspace .pm-pr-measure-label {
  display: inline-flex;
  align-items: center;
  font-size: var(--pm-fs-label);
  color: var(--text-muted);
  white-space: nowrap;
}
#pm-workspace .pm-pr-measure-value { font-size: 16px; font-weight: 600; white-space: nowrap; }
#pm-workspace .pm-pr-caption { padding: 8px 10px 0; font-size: var(--pm-fs-note); color: var(--text-muted); }
/* The scale's height is the chart's, set by the script (performance.js
   SCALE). */
#pm-workspace .pm-pr-scale { flex: none; padding: 0 6px; }

/* The drawdown ladder: its scale, the steps and what has happened. */
/* The ladder's log of the steps taken takes the room left and scrolls. */
#pm-workspace .pm-pr-ladder-body { flex: 1 0 auto; display: flex; flex-direction: column; }
#pm-workspace .pm-pr-llog {
  flex: 1 1 0;
  min-height: 0;
  overflow: auto;
  padding: 4px 10px;
  font-size: var(--pm-fs-note);
  color: var(--text-secondary);
}
#pm-workspace .pm-pr-llog > div { padding: 3px 0; }

/* The limits: every limit with a meter scaled to 125% of the limit, the
   ticks at the limit, and a centre line where the limit has two sides. */
#pm-workspace .pm-pr-chip {
  padding: 0 6px;
  border: 1px solid var(--warning);
  border-radius: 3px;
  font-size: var(--pm-fs-note);
  color: var(--warning);
  white-space: nowrap;
}
/* The limits: the heading and the rows are rows of one grid (each row a
   subgrid), as in P&L by name, so every column takes the width of its
   widest heading or number and the measure's name takes what is left.
   Fixed widths cut the numbers and ran the headings into each other
   (owner, 2026-10-13). The heading stays in view while the rows scroll,
   and the rows keep their own height however tall the pane is. */
#pm-workspace .pm-pr-limtable {
  flex: 1 1 0;
  min-height: 0;
  overflow: auto;
  display: grid;
  grid-template-columns: minmax(80px, 1fr) auto auto auto minmax(120px, 170px) auto auto;
  align-content: start;
  column-gap: 16px;
}
#pm-workspace .pm-pr-limhead,
#pm-workspace .pm-pr-limrow {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: subgrid;
  align-items: center;
  padding: 0 10px;
}
#pm-workspace .pm-pr-limhead {
  position: sticky;
  top: 0;
  z-index: 1;
  height: 28px;
  background: var(--bg-surface);
  border-bottom: 1px solid var(--border);
  font-size: var(--pm-fs-note);
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--text-muted);
  white-space: nowrap;
}
#pm-workspace .pm-pr-limrow {
  height: 30px;
  border-bottom: 1px solid var(--pm-subtle);
  font-size: var(--pm-fs-main);
}
#pm-workspace .pm-pr-limrow:hover { background: var(--pm-hover); }
#pm-workspace .pm-pr-limrow.is-sel { background: var(--pm-sel); }
#pm-workspace .pm-pr-limgroup {
  grid-column: 1 / -1;
  height: 26px;
  display: flex;
  align-items: center;
  padding: 0 10px;
  background: var(--bg);
  border-bottom: 1px solid var(--pm-subtle);
  font-size: var(--pm-fs-note);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
}
#pm-workspace .pm-pr-meter {
  position: relative;
  height: 12px;
  background: var(--pm-track);
}
#pm-workspace .pm-pr-meter > i { position: absolute; }
#pm-workspace .pm-pr-tick { top: -2px; bottom: -2px; border-left: 1px solid var(--text-muted); }
#pm-workspace .pm-pr-centre { top: -1px; bottom: -1px; border-left: 1px solid var(--text-muted); }
#pm-workspace .pm-pr-mfill { top: 2px; bottom: 2px; }
#pm-workspace .pm-pr-mfill.is-ok { background: var(--pm-meter); }
#pm-workspace .pm-pr-mfill.is-warn { background: var(--warning); }
#pm-workspace .pm-pr-mfill.is-neg { background: var(--negative); }

/* The breaches: one row per limit breach with its days drawn as a bar on
   the session's day scale (owner, 2026-10-13: a separate timeline named
   every limit a second time and ran into the table). The heading and the
   rows are rows of one grid, as on Limits, so every column takes the width
   of its widest heading or entry and the bar takes what is left. */
#pm-workspace .pm-pr-breach-body { flex: 1 1 0; min-height: 0; display: flex; flex-direction: column; }
#pm-workspace .pm-pr-btable {
  flex: 1 1 0;
  min-height: 0;
  overflow: auto;
  display: grid;
  grid-template-columns: minmax(80px, auto) auto auto auto auto minmax(120px, 1fr);
  align-content: start;
  column-gap: 16px;
}
#pm-workspace .pm-pr-btable > .pm-pr-empty { grid-column: 1 / -1; }
#pm-workspace .pm-pr-bhead,
#pm-workspace .pm-pr-brow {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: subgrid;
  align-items: center;
  padding: 0 10px;
}
#pm-workspace .pm-pr-bhead {
  position: sticky;
  top: 0;
  z-index: 1;
  height: 28px;
  background: var(--bg-surface);
  border-top: 1px solid var(--pm-subtle);
  border-bottom: 1px solid var(--border);
  font-size: var(--pm-fs-note);
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--text-muted);
  white-space: nowrap;
}
#pm-workspace .pm-pr-bscale { display: flex; justify-content: space-between; }
#pm-workspace .pm-pr-brow {
  height: 28px;
  border-bottom: 1px solid var(--pm-subtle);
  font-size: var(--pm-fs-main);
}
#pm-workspace .pm-pr-bfill { top: 2px; bottom: 2px; min-width: 2px; opacity: 0.85; }
#pm-workspace .pm-pr-bfill.is-active { background: var(--negative); }
#pm-workspace .pm-pr-bfill.is-cured { background: var(--positive); }
#pm-workspace .pm-pr-bfill.is-forced_reduction { background: var(--warning); }
#pm-workspace .pm-pr-bdue { top: -2px; bottom: -2px; border-left: 1px dashed var(--negative); }

/* The trade record. */
#pm-workspace .pm-pr-select {
  height: 26px;
  padding: 0 4px;
  border: 1px solid var(--border);
  border-radius: 3px;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: var(--pm-fs-main);
}
/* The trade record: the heading and the rows are rows of one grid (each
   row a subgrid), as on Limits, so every column takes the width of its
   widest heading or entry and the note takes what is left. A fixed width
   cut a currency amount such as 4,000,000 EUR (owner, 2026-10-13). */
#pm-workspace .pm-pr-ttable {
  flex: 1 1 0;
  min-height: 0;
  overflow: auto;
  display: grid;
  grid-template-columns: repeat(7, auto) minmax(0, 1fr);
  align-content: start;
  column-gap: 16px;
}
#pm-workspace .pm-pr-ttable > .pm-pr-empty { grid-column: 1 / -1; }
#pm-workspace .pm-pr-thead,
#pm-workspace .pm-pr-trow {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: subgrid;
  align-items: center;
  padding: 0 10px;
}
#pm-workspace .pm-pr-thead {
  position: sticky;
  top: 0;
  z-index: 1;
  height: 28px;
  background: var(--bg-surface);
  border-bottom: 1px solid var(--border);
  font-size: var(--pm-fs-note);
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--text-muted);
  white-space: nowrap;
}
#pm-workspace .pm-pr-trow {
  height: 28px;
  border-bottom: 1px solid var(--pm-subtle);
  font-size: var(--pm-fs-main);
}
#pm-workspace .pm-pr-trow:hover { background: var(--pm-hover); }

/* ── Debrief ─────────────────────────────────────────────────────────

   The report in three sub-pages (the 2026-10 redesign, direction 7a).
   The bar carries the sub-pages and the team report; the grid under it
   scrolls when a sub-page runs longer than the screen. */

#pm-workspace .pm-db-bar { align-items: stretch; }
#pm-workspace .pm-db-report {
  margin: auto 6px auto auto;
  height: 30px;
  padding: 0 12px;
  border: 0;
  border-radius: 3px;
  background: var(--color-accent);
  color: #fff;
  font-family: var(--font);
  font-size: var(--pm-fs-main);
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
}
#pm-workspace .pm-db-grid {
  flex: 1 1 0;
  min-height: 0;
  display: grid;
  gap: 8px;
  padding: 8px;
  overflow: auto;
}
#pm-workspace .pm-db-grid--result {
  grid-template-columns: minmax(0, 560fr) minmax(0, 574fr);
  grid-template-rows: 78px minmax(262px, 262fr) minmax(304px, 304fr) minmax(276px, 276fr);
  grid-template-areas: 'hero hero' 'standings working' 'scorecard measures' 'leaders measures';
}
#pm-workspace .pm-db-grid--risk {
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  grid-template-rows: minmax(300px, 360fr) minmax(320px, 410fr);
  grid-template-areas: 'equity usage' 'decomp decomp';
}
#pm-workspace .pm-db-grid--story {
  grid-template-columns: minmax(0, 1fr);
  grid-auto-rows: auto;
  align-content: start;
}
#pm-workspace .pm-db-hero { grid-area: hero; flex-direction: row; }
#pm-workspace .pm-db-standings { grid-area: standings; }
#pm-workspace .pm-db-working { grid-area: working; }
#pm-workspace .pm-db-scorecard { grid-area: scorecard; }
#pm-workspace .pm-db-leaders { grid-area: leaders; }
#pm-workspace .pm-db-measures { grid-area: measures; }
#pm-workspace .pm-db-equity { grid-area: equity; }
#pm-workspace .pm-db-usage { grid-area: usage; }
#pm-workspace .pm-db-grid--risk .pm-pr-decomp { grid-area: decomp; }

/* The result strip. */
#pm-workspace .pm-db-hero-cell {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 2px;
  padding: 0 14px;
  border-right: 1px solid var(--pm-subtle);
}
#pm-workspace .pm-db-hero-cell.is-wide { flex: 0 0 190px; }
#pm-workspace .pm-db-hero-label {
  font-size: var(--pm-fs-label);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
  white-space: nowrap;
}
#pm-workspace .pm-db-hero-line { display: flex; align-items: baseline; gap: 6px; white-space: nowrap; }
#pm-workspace .pm-db-hero-big { font-size: 26px; font-weight: 600; line-height: 1; }
#pm-workspace .pm-db-hero-value { font-size: 18px; font-weight: 600; }
#pm-workspace .pm-db-hero-sub { font-size: var(--pm-fs-label); color: var(--text-muted); }

/* Tables of the result: the standings, the score working, the scorecard,
   the leaders and the measures. */
#pm-workspace .pm-db-shead,
#pm-workspace .pm-db-srow {
  display: grid;
  grid-template-columns: 30px minmax(0, 1fr) 70px 80px 90px;
  gap: 6px;
  align-items: center;
  padding: 0 10px;
}
#pm-workspace .pm-db-whead,
#pm-workspace .pm-db-wrow {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 70px 70px 112px;
  gap: 6px;
  align-items: center;
  padding: 0 10px;
}
#pm-workspace .pm-db-mhead,
#pm-workspace .pm-db-mrow {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 100px 100px;
  gap: 6px;
  align-items: center;
  padding: 0 10px;
}
#pm-workspace .pm-db-shead,
#pm-workspace .pm-db-whead,
#pm-workspace .pm-db-mhead,
#pm-workspace .pm-db-ehead,
#pm-workspace .pm-db-thead,
#pm-workspace .pm-db-ihead {
  flex: none;
  min-height: 28px;
  border-bottom: 1px solid var(--border);
  font-size: var(--pm-fs-note);
  line-height: 1.25;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--text-muted);
}
#pm-workspace .pm-db-sbody { flex: 1 1 0; min-height: 0; overflow: auto; }
#pm-workspace .pm-db-srow,
#pm-workspace .pm-db-wrow,
#pm-workspace .pm-db-lrow {
  height: 30px;
  border-bottom: 1px solid var(--pm-subtle);
  font-size: var(--pm-fs-main);
}
#pm-workspace .pm-db-srow.is-sel,
#pm-workspace .pm-db-lrow.is-sel { background: var(--pm-sel); font-weight: 600; }
#pm-workspace .pm-db-team { display: flex; align-items: center; gap: 8px; white-space: nowrap; }
#pm-workspace .pm-db-tag {
  padding: 0 5px;
  border: 1px solid var(--color-accent-text);
  border-radius: 3px;
  font-size: var(--pm-fs-note);
  font-weight: 600;
  line-height: 17px;
  color: var(--color-accent-text);
}
#pm-workspace .pm-db-wrow > span:first-child { display: inline-flex; align-items: center; }
#pm-workspace .pm-db-wrow.is-ruled { border-top: 1px solid var(--border); }
#pm-workspace .pm-db-wrow.is-strong { font-weight: 600; }
#pm-workspace .pm-db-cgrid {
  flex: 1 1 0;
  min-height: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-auto-flow: column;
  align-content: start;
  overflow: auto;
}
#pm-workspace .pm-db-cgrid--flow { grid-auto-flow: row; grid-template-rows: none; flex: none; }
#pm-workspace .pm-db-crow {
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 0 10px;
  border-bottom: 1px solid var(--pm-subtle);
  border-right: 1px solid var(--pm-subtle);
  white-space: nowrap;
}
#pm-workspace .pm-db-crow > span:first-child {
  display: inline-flex;
  align-items: center;
  overflow: hidden;
}
#pm-workspace .pm-db-lrow {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 130px 110px;
  gap: 6px;
  align-items: center;
  padding: 0 10px;
}
#pm-workspace .pm-db-legend { gap: 10px; font-size: var(--pm-fs-note); color: var(--text-muted); }
#pm-workspace .pm-db-mbody { flex: 1 1 0; min-height: 0; overflow: auto; }
#pm-workspace .pm-db-mgroup {
  width: 100%;
  height: 30px;
  display: grid;
  grid-template-columns: 14px minmax(0, 1fr) auto;
  gap: 4px;
  align-items: center;
  padding: 0 10px;
  border: 0;
  border-bottom: 1px solid var(--pm-subtle);
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: var(--pm-fs-main);
  text-align: left;
  cursor: pointer;
}
#pm-workspace .pm-db-mgroup:hover { background: var(--pm-hover); }
#pm-workspace .pm-db-mcount {
  display: flex;
  gap: 8px;
  font-size: var(--pm-fs-note);
  color: var(--text-muted);
  white-space: nowrap;
}
#pm-workspace .pm-db-mrow {
  height: 28px;
  padding-left: 28px;
  border-bottom: 1px solid var(--pm-subtle);
  font-size: var(--pm-fs-main);
}
#pm-workspace .pm-db-mrow:hover { background: var(--pm-hover); }
#pm-workspace .pm-db-qmark { margin-right: 5px; font-size: 12px; }
#pm-workspace .pm-db-arrow { font-size: 12px; color: var(--text-muted); }

/* The story: the capture chart, the mispricings and the mandate's own
   blocks, each as tall as it needs. */
#pm-workspace .pm-db-capture .pm-db-chart { flex: none; height: 300px; }
#pm-workspace .pm-db-chart--tall { flex: none; height: 360px; }
#pm-workspace .pm-db-ehead,
#pm-workspace .pm-db-erow {
  display: grid;
  grid-template-columns: 12px minmax(0, 1fr) 110px 100px 220px 160px;
  gap: 8px;
  align-items: center;
  padding: 0 10px;
}
#pm-workspace .pm-db-erow {
  min-height: 36px;
  border-bottom: 1px solid var(--pm-subtle);
  font-size: var(--pm-fs-main);
  cursor: pointer;
}
#pm-workspace .pm-db-erow:hover { background: var(--pm-hover); }
#pm-workspace .pm-db-erow.is-sel { background: var(--pm-sel); border-bottom: 0; }
#pm-workspace .pm-db-edesc {
  padding: 2px 10px 10px 36px;
  border-bottom: 1px solid var(--pm-subtle);
  background: var(--bg);
  font-size: var(--pm-fs-main);
  line-height: 1.5;
  color: var(--text-secondary);
}
#pm-workspace .pm-db-edesc p { max-width: 860px; margin: 6px 0 0; }
#pm-workspace .pm-db-chartbtns { display: flex; flex-wrap: wrap; gap: 4px; }
#pm-workspace .pm-db-chartbtn {
  padding: 1px 8px;
  border: 1px solid var(--border);
  border-radius: 3px;
  background: transparent;
  color: var(--text);
  font-family: var(--font);
  font-size: var(--pm-fs-main);
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
}
#pm-workspace .pm-db-chartbtn:hover { background: var(--pm-hover); }
#pm-workspace .pm-db-thead,
#pm-workspace .pm-db-trow {
  display: grid;
  gap: 8px;
  align-items: center;
  padding: 0 10px;
}
#pm-workspace .pm-db-thead { align-items: end; padding-top: 4px; padding-bottom: 4px; }
#pm-workspace .pm-db-trow {
  height: 30px;
  border-bottom: 1px solid var(--pm-subtle);
  font-size: var(--pm-fs-main);
}

/* Before the report: the interim standings and the note. */
#pm-workspace .pm-db-pre {
  flex: 1 1 0;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
  padding: 8px;
}
#pm-workspace .pm-db-interim,
#pm-workspace .pm-db-note { width: 940px; max-width: 100%; }
#pm-workspace .pm-db-note { padding: 14px; font-size: var(--pm-fs-main); color: var(--text-secondary); }
#pm-workspace .pm-db-ihead,
#pm-workspace .pm-db-irow {
  display: grid;
  grid-template-columns: 36px minmax(0, 1fr) repeat(6, 90px);
  gap: 6px;
  align-items: center;
  padding: 0 10px;
}
#pm-workspace .pm-db-irow { height: 34px; background: var(--pm-sel); font-size: var(--pm-fs-main); }
#pm-workspace .pm-db-ihead .pm-score-head { justify-content: flex-end; }

/* ── Briefing ──────────────────────────────────────────────────────── */

/* The same reading layout the trainer guide uses, copied from the console
   stylesheet (css/console.css :1055-1090 and the .doc-* block at :348-366):
   a sticky table of contents beside flowing prose. The two reference
   surfaces of this sim read the same way. */

/* The Briefing is a document, so it takes the handbook's own geometry: the
   nav rail and reading measure the platform's chapter pages use, from the
   tokens base.css already carries. The params sidebar is collapsed on this
   page (app.js sets the class), because the live book has nothing to do
   with reading the mechanics, and the document centres in what that
   leaves. The collapse reuses the platform's own sidebar-collapsed rule
   rather than a second mechanism. */
#pm-workspace.pm-briefing-active .params-sidebar.visible {
  width: 0;
  min-width: 0;
  overflow: hidden;
}
/* This page owns the collapse, so the workspace toggle would do nothing
   here. It is hidden rather than left as a dead control. */
#pm-workspace.pm-briefing-active .sidebar-toggle-btn { display: none; }
/* A document opens below the header rather than against it. The shared
   `.tab-content-area` pads 16px, which is right for a page of panels and
   too tight for the first line of prose and the top of the chapter index. */
#pm-workspace.pm-briefing-active .tab-content-area { padding-top: 48px; }
#pm-workspace .ref-mech-layout {
  display: grid;
  grid-template-columns: 200px minmax(0, 62rem);
  gap: 32px;
  align-items: start;
  justify-content: center;
  margin: 0 auto;
}
/* The reading measure caps the prose itself rather than the column, so a
   table that genuinely needs more room can opt out of it. Same split
   `.learn-chapter-body` uses on the platform. */
#pm-workspace .ref-mechanics > p,
#pm-workspace .ref-mechanics > .doc-part,
#pm-workspace .ref-mechanics > .ref-section,
#pm-workspace .doc-param-body p {
  max-width: var(--measure-prose, 46rem);
}
/* Tables read at the same measure by default. A table of three short
   columns stretched across the full column put yawning space between a
   label and its number. The global `thead th { white-space: nowrap }` is
   what forces a table past a cap, so headers wrap here and the columns
   shrink to their content, exactly as the handbook does it. Tables that
   need the room opt out with `data-table-wide`. */
/* A table is a block in the prose, so it gets the same air above and below
   that the handbook gives one. Neither `.data-table-wrap` nor a bare
   `.data-table` carries a margin of its own, so the paragraph after a table
   sat flush against it. */
#pm-workspace .ref-mechanics .data-table-wrap,
#pm-workspace .ref-mechanics .pm-limit-table {
  max-width: var(--measure-prose, 46rem);
  margin: var(--space-subsection, 32px) 0;
}
#pm-workspace .ref-mechanics .data-table-wrap.data-table-wide {
  max-width: none;
  width: 100%;
}
#pm-workspace .ref-mechanics .data-table { table-layout: auto; }
#pm-workspace .ref-mechanics .data-table thead th { white-space: normal; }
/* The chapter index, on the platform handbook's own `.learn-nav` model: a
   quiet group label per chapter, and rows that carry the reading position
   through weight and colour rather than a filled block. The grey pill this
   page used read as a UI control sitting in a document. */
#pm-workspace .ref-toc {
  position: sticky;
  top: 8px;
  align-self: start;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding-right: 8px;
  padding-bottom: 40px;
  max-height: calc(100vh - 140px);
  overflow-y: auto;
  /* Section numbering by CSS counter, so adding or removing a section
     renumbers the index without touching the markup. */
  counter-reset: ref-section;
}
#pm-workspace .ref-toc-group {
  font-size: 0.96rem;
  font-weight: 700;
  color: var(--text-secondary);
  padding: 6px 10px 4px 6px;
  margin-top: 14px;
}
#pm-workspace .ref-toc-group:first-child { margin-top: 0; padding-top: 2px; }
/* A number column and a title column, so a title that wraps hangs under
   itself rather than under its own number. */
#pm-workspace .ref-toc-link {
  display: grid;
  grid-template-columns: 2.2em 1fr;
  align-items: baseline;
  gap: 6px;
  padding: 7px 10px 7px 6px;
  border-radius: 4px;
  font-size: 0.92rem;
  font-weight: 500;
  line-height: 1.45;
  color: var(--text-muted);
  text-decoration: none;
  transition: color 0.15s ease, background 0.15s ease;
  counter-increment: ref-section;
}
#pm-workspace .ref-toc-link::before {
  content: counter(ref-section) ".";
  font-family: var(--font);
  font-size: 0.82rem;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
  text-align: right;
  padding-right: 4px;
}
#pm-workspace .ref-toc-link:hover {
  color: var(--text-secondary);
  background: color-mix(in srgb, var(--text) 4%, transparent);
}
#pm-workspace .ref-toc-link:hover::before { color: var(--text-secondary); }
#pm-workspace .ref-toc-link.active {
  color: var(--text);
  font-weight: 600;
  background: transparent;
}
/* The number is the only ink marker on the active row. */
#pm-workspace .ref-toc-link.active::before {
  color: var(--color-accent);
  font-weight: 600;
}
#pm-workspace .ref-mech-layout .ref-mechanics .ref-section,
#pm-workspace .ref-mech-layout .ref-mechanics .doc-part { scroll-margin-top: 16px; }
@media (max-width: 900px) {
  #pm-workspace .ref-mech-layout { grid-template-columns: 1fr; }
  #pm-workspace .ref-toc { display: none; }
}
/* Reading type, not UI type: the same body size and leading the platform's
   handbook chapters use, from the tokens base.css already carries. */
#pm-workspace .ref-mechanics {
  font-size: var(--text-body);
  line-height: var(--line-body);
  color: var(--text);
}
#pm-workspace .ref-mechanics p { margin: 0 0 var(--space-block, 16px); }
#pm-workspace .ref-mechanics .ref-lead {
  margin: 0 0 24px;
  font-size: 16px;
  color: var(--text);
}
/* On the platform's typography scale, so a section heading sits above the
   18px body rather than under it. Chapter at h2, section at h3. */
#pm-workspace .ref-mechanics .ref-section {
  margin: 36px 0 10px;
  font-size: var(--text-h3);
  line-height: var(--line-tight);
  font-weight: 600;
  color: var(--text);
  display: flex;
  align-items: center;
  gap: 6px;
}
#pm-workspace .doc-part {
  font-size: var(--text-h2);
  line-height: var(--line-tight);
  font-weight: 700;
  margin: 48px 0 4px;
  color: var(--text);
}
#pm-workspace .doc-part:first-child { margin-top: 0; }

/* The Reference button beside a formula button. It shares .formula-btn's
   chassis, and that class draws its glyph with ::before (the button's own
   text is hidden by font-size: 0), so without this override the "i"
   rendered as a second f. An upright i has no hook descender, so the
   f's optical-centring nudge comes off too. */
.briefing-btn::before {
    content: 'i';
    transform: none;
}

#pm-workspace .doc-param { padding: 14px 0; border-top: 1px solid var(--border); }
#pm-workspace .doc-param-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}
/* No sizes of their own. A named block is prose on a page of prose, and
   three bespoke sizes here (14.5 for the name, 13.5 for the body, 12 for a
   gloss that no longer exists) made the order types read smaller than
   everything around them and the name read smaller than its own paragraph.
   Weight and colour separate the name from the body; the page decides how
   big any of it is. */
#pm-workspace .doc-param-name { font-weight: 600; color: var(--text); }
#pm-workspace .doc-param-body { margin-top: 6px; }
#pm-workspace .doc-param-body p {
  margin: 0 0 8px;
  color: var(--text-secondary);
}
#pm-workspace .doc-param-body p:last-child { margin-bottom: 0; }

/* ── Desktop-only notice ───────────────────────────────────────────── */

/* Below 1200px the sidebar and the desk's two columns (600px market
   minimum plus the cards column) no longer fit beside each other. The
   workspace toggle (app.js initSidebarToggle) starts collapsed there, so
   a landscape tablet (1024px and up) opens the desk at full width and
   the sidebar stays one tap away. */

#pm-workspace .pm-desktop-notice { display: none; }
/* Below 1024px even the full viewport is narrower than the desk's two
   columns, so the notice replaces the desk. 1023 rather than the 1024
   tablet tier, so a 1024px-wide tablet in landscape gets the desk. */
@media (max-width: 1023px) {
  #pm-workspace .pm-desk { display: none; }
  #pm-workspace .pm-desktop-notice {
    display: block;
    padding: 24px 4px;
    max-width: 520px;
  }
  #pm-workspace.pm-desk-active .workspace-content { overflow-y: auto; }
}

/* The read-only bar a trainer gets when they open a desk from Room Control.
   What sits below it is the desk's own screen, ticket and all, so without
   the bar it reads as a book that can be traded. Copied from the Bank ALM
   sim's observer banner, which is where the platform already answers this. */
#pm-observer-banner {
  flex: 0 0 auto;
  background: #f8d7da;
  color: #1a1a1a;
  font-size: 13px;
  font-weight: 600;
  text-align: center;
  padding: 7px 16px;
}
/* The analysis pause of a heavy data day: a bar above the desk with the
   time left until trading reopens, in the observer bar's place and size.
   The desk stays readable; the ticket's two buttons are greyed while the
   room is closed for trading. */
#pm-pause-banner {
  flex: 0 0 auto;
  background: var(--bg-elevated);
  border-bottom: 1px solid var(--border);
  color: var(--text);
  font-size: 13px;
  font-weight: 600;
  text-align: center;
  padding: 7px 16px;
}
body.pm-analysis-pause #pm-t-buy,
body.pm-analysis-pause #pm-t-sell { pointer-events: none; opacity: 0.55; }

/* Lock what would otherwise be sent to the room, so the bar's statement
   holds rather than relying on the server dropping the message. Everything
   that only reads stays live: pages, sorting, selection, the enlarge
   buttons and the theme toggle. */
body.pm-observer #pm-t-buy,
body.pm-observer #pm-t-sell,
body.pm-observer .pm-ticket-close,
body.pm-observer .pm-orders-frame [data-cancel],
body.pm-observer .pm-positions-frame [data-close],
body.pm-observer #pm-rename { display: none; }
body.pm-observer .pm-ticket input,
body.pm-observer .pm-ticket select { pointer-events: none; opacity: 0.55; }

/* The Briefing's limits table. What each limit caps is a sentence, and a
   sentence in a fifth column pushed the table past the width of the page, so
   the figures could only be reached by scrolling sideways. The sentence sits
   under the name it belongs to instead. The name column takes what is left
   after three narrow ones, so the prose wraps and the figures stay put. */
#pm-workspace .pm-limit-table { width: 100%; table-layout: auto; }
#pm-workspace .pm-limit-table td:first-child { width: 100%; }
#pm-workspace .pm-limit-table th:not(:first-child),
#pm-workspace .pm-limit-table td:not(:first-child) { white-space: nowrap; }
/* No size of its own either: it takes the table's, which is the size every
   other cell on the page is already set in. */
#pm-workspace .pm-limit-note {
  display: block;
  margin-top: 3px;
  max-width: 60ch;
  color: var(--text-muted);
  white-space: normal;
}
#pm-workspace .pm-limit-note:empty { display: none; }

/* ── Dialog shell ──────────────────────────────────────────────────────
   openDialog() in shared/dialog.js builds .iro-dialog-overlay markup, and
   this bundle carried only the two modifier rules for it, never the base
   ones. The dialog therefore rendered as unstyled text at the foot of the
   page. These rules are copied from the platform's platform.css, which the
   participant page does not load, so the sim now styles what it renders.
   The close button colour is the only change: the platform's is fixed white
   for a dark shell, and this sim runs light and dark. */
.iro-dialog-overlay {
  position: fixed;
  inset: 0;
  z-index: var(--z-max);
  background: rgba(0,0,0,0.7);
  display: flex;
  align-items: center;
  justify-content: center;
  backdrop-filter: blur(var(--blur-sm));
}
.iro-dialog {
  background: var(--bg-surface, #151518);
  border: 1px solid var(--border, #333);
  border-radius: 12px;
  /* The platform sizes this for charts and tables at 960px. The only
     dialog here holds a paragraph, so it takes the width the trainer and
     admin shells give the same disclaimer, which is 460px in console.css.
     A dialog that needs the room can still pass wide. */
  width: min(460px, 92vw);
  max-height: 85vh;
  display: flex;
  flex-direction: column;
  box-shadow: var(--shadow-lg);
}
.iro-dialog.iro-dialog-wide { width: min(1100px, 94vw); }
.iro-dialog-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border, #333);
  flex-shrink: 0;
}
.iro-dialog-header h3 { margin: 0; font-size: 1.1rem; font-weight: 700; }
.iro-dialog-close {
  background: none;
  border: none;
  color: var(--text-muted);
  font-size: 1.4rem;
  cursor: pointer;
  padding: 4px 8px;
  border-radius: 6px;
  transition: color 0.2s, background 0.2s;
}
.iro-dialog-close:hover { color: var(--text); background: var(--bg-elevated); }
.iro-dialog-body { flex: 1; overflow-y: auto; padding: 20px 24px; }

/* ── Session overview dialog ───────────────────────────────────────────
   The shared dialog's wide shell, made the app's own (owner, 2026-10-07):
   a flat tile at a fixed size, no border and no radius, the way every
   panel on the desk is drawn. The header carries the mandate as the
   title, the session's facts under it and the section buttons beside it
   on the same rule; the body scrolls between that header and a footer
   with the one action. The sections are laid out in two columns, so the
   wide shell is used rather than filled with one long line, which is
   what the former 74ch cap on the shell existed to prevent.

   The dialog mounts on <body>, outside #pm-workspace, so nothing scoped
   to the workspace reaches it and every rule it needs is written here. */
.iro-dialog.pm-overview {
  width: min(1100px, 94vw);
  /* Fixed, so switching between a long section and a short one never
     moves the dialog; the body scrolls inside it. */
  height: 85vh;
  max-height: none;
  border: 0;
  border-radius: 0;
}
/* The title block, the section buttons and the close cross on one row.
   The buttons sit on the header's rule: their own nav rule is dropped and
   the selected underline, drawn 1px under the button, lands on the
   header's. */
.pm-overview .iro-dialog-header {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: end;
  gap: 0 32px;
  padding: 22px 28px 0;
  border-bottom: 1px solid var(--border);
}
.pm-ov-heading {
  min-width: 0;
  padding-bottom: 14px;
}
/* The caption size and colour of a desk frame head (.pm-frame-title). */
.pm-ov-eyebrow {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-secondary);
}
/* The platform's h3 step, the size the MM lobby card gives its title. */
.pm-ov-title {
  font-size: var(--text-h3);
  font-weight: 600;
  color: var(--text);
  margin-top: 2px;
}
.pm-ov-subtitle {
  font-size: 0.95rem;
  color: var(--text-muted);
  margin-top: 4px;
}
.pm-overview .pm-ov-nav {
  margin: 0;
  border-bottom: 0;
  flex-wrap: nowrap;
}
.pm-overview .iro-dialog-close {
  align-self: start;
  margin-top: -6px;
}
.pm-overview .iro-dialog-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 20px 28px 24px;
}
.pm-ov-footer {
  flex: none;
  display: flex;
  gap: 10px;
  padding: 14px 28px;
  border-top: 1px solid var(--border);
}

/* Numbers inside a line of words take the numeric face alone, the way the
   sidebar's rows set them; the words around them stay in the interface
   face. */
.pm-overview .num {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}
.iro-dialog-body p { margin: 0 0 12px; }
.iro-dialog-body p:last-child { margin-bottom: 0; }

/* A section heading inside the body, in the frame-head caption style. */
.pm-ov-head {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-secondary);
  margin: 0 0 8px;
}
.pm-ov-col > .pm-ov-head:not(:first-child) { margin-top: 20px; }

/* Two columns, equal, the prose on the left at a reading measure and the
   tables on the right. */
.pm-ov-cols {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 0 40px;
  align-items: start;
}
.pm-ov-col { min-width: 0; }
.pm-ov-prose,
.pm-ov-col > p { max-width: 66ch; }
/* A table in a half column wraps its words rather than scrolling
   sideways. The platform table sets every cell nowrap, and the macro
   backdrop's economies table (six columns, headed "Priced over the next
   year") measures about 760px that way against a column of about 500px.
   Headings and text cells wrap; a printed number never does. */
.pm-ov-col .data-table thead th,
.pm-ov-col .data-table tbody td:not(.num) { white-space: normal; }
.pm-ov-update + .pm-ov-update { margin-top: 28px; }

/* The mandate's facts: one key-value row per fact on a hairline, the
   value right-aligned, in the idiom of the sidebar rows and the MM lobby
   card. */
.pm-ov-rows {
  display: grid;
  grid-template-columns: minmax(0, 1fr) max-content;
  column-gap: 24px;
  margin-bottom: 16px;
}
.pm-ov-row { display: contents; }
.pm-ov-row > * {
  padding: 6px 0;
  border-bottom: 1px solid var(--border);
  font-size: 0.95rem;
}
.pm-ov-label { color: var(--text-muted); }
.pm-ov-value {
  color: var(--text);
  font-weight: 600;
  text-align: right;
}

/* No table box: the rule under the headings and the row hairlines are
   the structure, as on the MM lobby card. The platform wrap keeps its
   horizontal scroll for a table wider than its column. */
.pm-backdrop-body .data-table-wrap {
  border: 0;
  border-radius: 0;
  margin-bottom: 12px;
}

@media (max-width: 900px) {
  .pm-ov-cols { grid-template-columns: minmax(0, 1fr); }
}


/* ── A card holding a table or a feed, enlarged ─────────────────────────

   A card is laid over the column it already lives in, not over the page.
   On the desk that means the right-hand column: the four cards there are
   the ones with no natural end, and enlarging one gives it the room the
   other three were using while the market grid and the ticket beside it
   stay put and keep working. Covering the whole desk to read the book would
   take the prices away at the same time.

   What it fills is decided by the nearest positioned ancestor, so the
   column below is what makes it the column rather than the page. Portfolio
   Analytics has no such column, so its cards fall back to `#pm-workspace`
   and fill the page, which is right for a card that is already the width of
   the page.

   THIS BLOCK MUST STAY LAST IN THE FILE. Enlarging a card overrides the
   normal sizing of whichever card it is, and those rules are written per
   card further up with the same specificity as these. Three of them had
   overtaken this state by sitting later in the file. The fatal one was
   `#pm-workspace .pm-frame { position: relative }`, added to anchor the
   enlarge button to its card corner: same weight as the rule below, later
   in the file, so `position: absolute` lost, `inset: 0` did nothing, and
   the card stayed exactly where it was. The button appeared dead. Do not
   fix a future collision by adding an id or an !important here; keep this
   block at the bottom, where the state that overrides everything belongs. */
/* An enlarged card fills the column it lives in, never the page. Each
   column states `position: relative` so `inset: 0` below is measured
   against the column. A column that omits it sends the card to
   #pm-workspace instead, which is the sidebar and both columns, and the
   card reads as a full-screen takeover. That is what the market grid did
   until 2026-08-11. */
#pm-workspace .pm-col-right,
#pm-workspace .pm-col-market { position: relative; }
/* On Performance & Risk an enlarged pane fills its column from the top of
   the grid to the bottom (owner, 2026-10-13). A pane placed in a named grid area
   measures `inset: 0` against that area, so the enlarged pane keeps the
   area's column and spans every row. */
#pm-workspace .pm-pr-grid { position: relative; }
#pm-workspace .pm-pr-grid > .pm-card-max { grid-row: 1 / -1; }
#pm-workspace .pm-card-max {
  position: absolute;
  inset: 0;
  z-index: 6;
  margin: 0;
  display: flex;
  flex-direction: column;
  box-shadow: var(--shadow-md);
}
/* Whatever height the card normally states gives way, and its body fills
   what it has been given. */
#pm-workspace .pm-card-max .pm-instrument,
#pm-workspace .pm-card-max .pm-scroll,
#pm-workspace .pm-card-max .pm-feed,
#pm-workspace .pm-card-max .pm-market-wrap,
#pm-workspace .pm-card-max > [id] {
  flex: 1 1 0;
  height: auto;
  min-height: 0;
  max-height: none;
  overflow-y: auto;
}
/* The selected-positions total is a footer, enlarged or not: the rule
   above stretches the card's body regions by their ids, and the total
   carries an id without being one of them. */
#pm-workspace .pm-card-max .pm-pos-agg {
  flex: 0 0 auto;
  overflow-y: visible;
}
/* A chart fills an enlarged pane and never scrolls in it. */
#pm-workspace .pm-card-max > .pm-pr-chart { overflow: hidden; }

/* ── Pause overlay ─────────────────────────────────────────────────────────
   The full-screen hold shown to every desk while the trainer has the session
   paused. Ported from the ALM sim (css/alm.css) so the two sims give the same
   participant a single pause experience. */
.pause-overlay {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: rgba(11, 11, 12, 0.85);
  backdrop-filter: blur(6px);
  display: flex;
  align-items: center;
  justify-content: center;
  animation: pauseFadeIn 0.3s ease;
}
[data-theme="light"] .pause-overlay {
  background: rgba(245, 245, 247, 0.85);
}
@keyframes pauseFadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}
.pause-overlay-content {
  text-align: center;
  max-width: 520px;
  padding: 48px 40px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}
.pause-overlay-icon {
  font-size: 48px;
  margin-bottom: 16px;
  opacity: 0.7;
}
.pause-overlay-title {
  font-size: 24px;
  font-weight: 700;
  color: var(--warning);
  margin-bottom: 16px;
}
.pause-overlay-hint {
  font-size: 13px;
  color: var(--text-muted);
  animation: pausePulse 2s ease-in-out infinite;
}
@keyframes pausePulse {
  0%, 100% { opacity: 0.5; }
  50% { opacity: 1; }
}
/* ── Formula panel ─────────────────────────────────────────────────── */

/* The panel keeps the platform's 560px (owner, 2026-08-20; a 680px
   override once lived here and made every panel in the sim wider than
   the platform's). An identity too long for 518px of content wraps in
   its own definition instead: the P&L decomposition's numeric line
   stacks one term per line in pm_formulas.js, the same aligned form its
   factor split already uses. Do not widen the panel for a long formula. */

/* A variable whose value is a list rather than a number: the borrow tiers,
   the margin haircuts, the largest beta contributions. One reading per
   line, because a comma-separated run in a narrow column reads as one
   long string. */
.formula-var-table .formula-var-item { display: block; }
