/*
 * Markets: a terminal layout in Tibinance's own type and tokens (css/app.css).
 * The chart and the dock fill the viewport under the site header, inside the
 * page margins every Tibinance page shares (.wrap); each panel scrolls on its own.
 * The dock is the tool rail at the right edge and the panel it has open
 * (js/markets-dock.js). Narrow screens stack the chart, the rail as a row and
 * the panels, and scroll the page.
 */
:root {
  --scale-inset:calc(var(--unit) * 3);   /* from the chart's right edge to the end of its price labels */
  --average:#a9a8b3;   /* the daily average: context for the best offer, never competing with it */
  /* Event markers by group: a world's own lifecycle, the game's events and updates, the market and the Store. */
  --event-world:var(--accent); --event-game:var(--caution); --event-market:var(--ink);
  /* Projections: the central path in ink, as the Research draws its scenario; the projected days faintly tinted. */
  --projection:var(--ink); --projection-region:rgb(118 118 128 / .06);
  --watch-width:calc(var(--unit) * 80);
  --rail-width:calc(var(--unit) * 10);
  --toolbar-height:calc(var(--unit) * 11);
  --row-pad:calc(var(--unit) * 0.75);
}

/* ---- the frame -------------------------------------------------------------- */
body { display:flex; flex-direction:column; height:100dvh; overflow:hidden; }
.site { position:static; flex:none; }
/* The terminal sits in the page's own margins (.wrap), however wide the chart is. */
.terminal { flex:1; width:100%; min-height:0; display:grid; grid-template-columns:minmax(0,1fr) auto; }
/* The space every page leaves under the header rule (.hero in css/app.css). */
.terminal:not(.expanded,:fullscreen) { padding-top:var(--space-5); }
@media (max-width:760px) { .terminal:not(.expanded,:fullscreen) { padding-top:var(--space-4); } }

/* ---- chart panel -------------------------------------------------------------- */
/* The toolbar follows the chart's own width (below), which the open panel narrows as much as a small screen does. */
.chart-panel { container:chart / inline-size; display:flex; flex-direction:column; min-width:0; min-height:0; border-right:var(--rule) solid var(--line); background:var(--canvas); }
.toolbar { flex:none; display:flex; align-items:center; gap:var(--space-2) var(--space-4); min-height:var(--toolbar-height); padding:var(--space-1) var(--space-4); font-family:var(--font-ui); }
/* No rule under the first row: a second rule parallel to the header's would join the row to the navigation above.
   The row belongs to the chart beneath it. It reads like the world's row in the list: the world, a step larger, and
   what it is at the start; its quote at the end, over the price scale. One baseline runs through both groups;
   space, not a rule, divides them. The quote's right edge is the price labels' (--scale-inset). */
.toolbar-top { flex-wrap:wrap; align-items:baseline; align-content:center; justify-content:space-between; gap:0 var(--space-5); padding-right:var(--scale-inset); }
.toolbar-bottom { justify-content:space-between; min-height:calc(var(--toolbar-height) - var(--space-3)); padding-block:0; padding-right:var(--scale-inset); border-top:var(--rule) solid var(--line); }
.through { color:var(--muted); font-size:var(--step-n2); font-variant-numeric:lining-nums tabular-nums; white-space:nowrap; }
.symbol { display:flex; align-items:baseline; gap:var(--space-1) var(--space-3); flex-wrap:wrap; min-width:0; }
.symbol h2 { font-size:var(--step-3); white-space:nowrap; }
.symbol-meta { display:inline-flex; gap:var(--space-3); color:var(--muted); font-size:var(--step-n2); white-space:nowrap; }
.symbol-quote { display:flex; align-items:baseline; gap:var(--space-2); margin-left:auto; font-variant-numeric:lining-nums tabular-nums; white-space:nowrap; }
.symbol-last { font-size:var(--step-1); font-weight:var(--weight-strong); }
.symbol-change { font-size:var(--step-n1); }
/* The range the change is measured over: the readout below carries a different change, since the previous observation. */
.symbol-range { color:var(--muted); font-size:var(--step-n2); font-weight:var(--weight-strong); letter-spacing:var(--tracking-caps); }
/* A tool button: an icon on the control track when hovered, pressed or open. */
.tool { display:inline-grid; place-items:center; width:var(--control-height); height:var(--control-height); padding:0; border:0; border-radius:var(--control-radius); background:transparent; color:var(--muted); cursor:pointer; }
.tool:hover,.tool[aria-pressed="true"],.tool[aria-expanded="true"] { background:var(--control-track); color:var(--ink); }
.tool svg { width:calc(var(--unit) * 5); height:calc(var(--unit) * 5); fill:none; stroke:currentColor; stroke-width:1.6; stroke-linecap:round; stroke-linejoin:round; }
.tool:disabled { opacity:var(--opacity-disabled); cursor:default; }
.tool:disabled:hover { background:transparent; color:var(--muted); }
.tool .icon-collapse,.tool[aria-pressed="true"] .icon-expand { display:none; }
.tool[aria-pressed="true"] .icon-collapse { display:block; }

/* The first range's label starts on the content edge, under the world and the readout. */
.ranges { display:flex; gap:var(--space-0); margin-left:calc(var(--space-2) * -1); }
.ranges button { min-height:calc(var(--control-height) - var(--space-1)); padding:0 var(--space-2); font-variant-numeric:lining-nums; border:0; border-radius:var(--radius-sm); background:transparent; color:var(--muted); font-family:var(--font-ui); font-size:var(--control-type); cursor:pointer; }
.ranges button:hover { background:var(--control-track); color:var(--ink); }
.ranges button[aria-checked="true"] { background:var(--control-track); color:var(--ink); font-weight:var(--weight-strong); }

/* ---- chart and its status ---------------------------------------------------------- */
.chart-area { position:relative; flex:1; min-height:0; }
.chart { position:absolute; inset:0; }
/* The status: one block over the chart's top left, as a market terminal reads its legend. First the world, what it
   is, and its quote: the latest best offer and its change over the range. Then the market side the chart shows, with
   both sides' latest best offers and the spread between them. Then the readout of the day under the crosshair. It
   stops short of the price scale; only its controls take the pointer, so the chart pans and shows its crosshair
   everywhere else. The price scale starts below it (js/markets.js fitHead). It stands above the chart, its markers and
   the message of a world without data, which covers only the chart. In the page its text starts on the page's edge,
   under Tibinance; at full screen it keeps an inset. */
.chart-head { position:absolute; z-index:6; left:var(--space-4); top:var(--space-2); max-width:calc(100% - var(--space-8) * 2);
  display:flex; flex-direction:column; align-items:flex-start; gap:var(--space-2); pointer-events:none; font-family:var(--font-ui); }
.chart-head :is(button,a) { pointer-events:auto; }
.head-line { display:flex; flex-wrap:wrap; align-items:baseline; gap:0 var(--space-3); max-width:100%; }
.head-line h2 { margin:0; font-size:var(--step-2); white-space:nowrap; }
.head-line .symbol-quote { margin-left:0; }
/* The market side: the segmented control every Tibinance page uses for one choice of two, each side with its latest
   best offer, the spread between them. The side shown is the thumb, written in its side's colour as the chart draws
   it; the other stays a plain figure, one press away. A view of the market, not an order. */
.side-picker { display:inline-flex; align-items:stretch; padding:var(--control-inset); border-radius:var(--control-radius); background:var(--control-track);
  font-variant-numeric:lining-nums tabular-nums; }
.side-picker button { display:inline-flex; align-items:baseline; gap:var(--space-2); min-height:calc(var(--control-height) - var(--control-inset) * 2); padding:var(--space-0) var(--space-2);
  border:0; border-radius:calc(var(--control-radius) - var(--control-inset)); background:transparent; color:var(--ink); font-family:var(--font-ui); font-size:var(--step-n1); line-height:var(--leading-tight); cursor:pointer; }
.side-picker .side-name { color:var(--muted); font-size:var(--step-n2); font-weight:var(--weight-strong); letter-spacing:var(--tracking-caps); text-transform:uppercase; }
.side-picker button:hover .side-name { color:var(--ink); }
.side-picker button[aria-checked="true"] { background:var(--surface); box-shadow:var(--control-thumb-shadow); font-weight:var(--weight-strong); }
.side-picker button[data-side="sell"][aria-checked="true"] :is(.side-name,.side-value) { color:var(--sell); }
.side-picker button[data-side="buy"][aria-checked="true"] :is(.side-name,.side-value) { color:var(--buy); }
.side-picker button:focus-visible { outline-offset:0; }
.side-spread { align-self:center; padding:0 var(--space-2); color:var(--muted); font-size:var(--step-n2); }
/* The readout: one small table, on the world's left edge. The day heads it; under it a row per series: key and name,
   value (right-aligned, so figures line up), and the rest (the best offer's change, the day's traded high and low).
   Values are the chart's, set lighter than the quote above. */
.chart-legend { display:grid; grid-template-columns:auto auto minmax(0,auto); align-items:center; gap:var(--space-1) var(--space-3); max-width:100%;
  color:var(--muted); font-family:var(--font-ui); font-size:var(--step-n1); font-variant-numeric:lining-nums tabular-nums; line-height:var(--leading-tight); }
.legend .meta-label { color:var(--muted); font-size:var(--step-n2); }
/* A label stays with its value when the readout wraps. */
.legend .ohlc > span { white-space:nowrap; }
.legend { display:contents; }
.legend .day { grid-column:1 / -1; color:var(--ink); font-size:var(--step-n2); font-weight:var(--weight-strong); letter-spacing:var(--tracking-caps); }
.legend .label { grid-column:1; display:grid; grid-template-columns:var(--space-4) auto; align-items:center; gap:var(--space-1); white-space:nowrap; }
.legend .label .key { justify-self:center; }
.legend .value { color:var(--ink); font-weight:var(--weight-regular); text-align:right; white-space:nowrap; }
.legend .rest { display:flex; flex-wrap:wrap; gap:0 var(--space-2); }
.legend .note { grid-column:span 2; }
/* ---- events: buttons over the markers the chart draws (js/market-events-ui.js) ------- */
/* The strip is placed by script at the foot of the price pane; only its buttons take the pointer, so the chart still
   pans and shows its crosshair everywhere else. A button is the marker's size; its target is taller for a finger. It
   lies above the chart library's attribution logo (z-index 3), which shares the pane's bottom left corner. */
/* Clipped sideways to the chart: while the chart catches up with a resize, a marker laid out for the old width must
   not widen the page. */
.event-marks { position:absolute; z-index:4; inset-inline:0; height:calc(var(--unit) * 3.5); overflow-x:clip; pointer-events:none; }
.event-mark { position:absolute; top:0; height:100%; padding:0; border:0; border-radius:calc(var(--unit) * 1.75); background:transparent; cursor:pointer; pointer-events:auto; }
.event-mark::before { content:""; position:absolute; inset:calc(var(--space-1) * -1) calc(var(--space-0) * -1); }
.event-mark:focus-visible { outline:var(--rule-strong) solid var(--accent); outline-offset:var(--rule-strong); }
.event-tip { position:fixed; z-index:var(--layer-header); display:grid; gap:var(--space-2); max-width:calc(var(--unit) * 80); padding:var(--space-2) var(--space-3);
  border:var(--rule) solid var(--line); border-radius:var(--radius-sm); background:var(--surface); box-shadow:var(--control-thumb-shadow);
  color:var(--ink); font-family:var(--font-ui); font-size:var(--step-n1); line-height:var(--leading-text); pointer-events:none; }
.event-tip[hidden] { display:none; }
.event-tip-item { display:grid; }
.event-tip-days { color:var(--muted); font-size:var(--step-n2); font-variant-numeric:lining-nums tabular-nums; }
.event-tip-title { display:flex; align-items:center; gap:var(--space-1); font-weight:var(--weight-strong); }
.event-tip-text { color:var(--muted); }
/* The marker itself, as the chart draws it: its category's mark, outlined in its group's colour. */
.event-tip-mark,.key-event { --event:var(--event-world); display:inline-grid; place-items:center; flex:none; min-width:calc(var(--unit) * 3.5); height:calc(var(--unit) * 3.5);
  padding:0 var(--space-1); border:var(--rule) solid var(--event); border-radius:calc(var(--unit) * 1.75); color:var(--event);
  font-size:calc(var(--step-n2) * .85); font-style:normal; font-weight:var(--weight-strong); line-height:1; }
.event-tip-mark[data-group="game"] { --event:var(--event-game); }
.event-tip-mark[data-group="market"] { --event:var(--event-market); }
.key-event { width:fit-content; justify-self:center; }

/* Above the chart's canvases (z-index 1 and 2), its logo (3) and the event markers (4), so a message hides a stale
   price scale. */
.chart-status { position:absolute; z-index:5; inset:0; display:grid; place-items:center; margin:0; color:var(--muted); font-family:var(--font-ui); font-size:var(--step-n1); background:var(--canvas); }
.chart-status[hidden] { display:none; }

/* Line keys, shared by the legends and the help. currentColor is the side colour. */
.side-sell { --side:var(--sell); } .side-buy { --side:var(--buy); }
.key { display:inline-block; flex:none; width:calc(var(--unit) * 4); border-top:var(--rule-strong) solid var(--side,var(--muted)); }
.key-dot { width:var(--space-2); height:var(--space-2); border:0; border-radius:50%; background:var(--side); }
.key-dotted { border-top-style:dotted; }
.key-average { border-top:var(--rule) solid var(--average); }
.key-volume { width:var(--space-2); height:var(--space-3); border:0; background:var(--side); opacity:.33; }
.key-projection { border-top:var(--rule-strong) dashed var(--projection); }

.up { color:var(--positive); } .down { color:var(--negative); }
/* A retired world is labelled wherever it appears. */
.tag { display:inline-block; margin-left:var(--space-1); padding:0 var(--space-1); border:var(--rule) solid var(--line-strong); border-radius:var(--radius-sm);
  color:var(--muted); font-family:var(--font-ui); font-size:var(--step-n2); font-weight:var(--weight-strong); letter-spacing:var(--tracking-caps); line-height:var(--leading-text); text-transform:uppercase; vertical-align:middle; }
.symbol-meta .tag { margin-left:0; }
.world-link { padding:0; border:0; background:none; color:var(--accent); font:inherit; text-decoration:underline; text-underline-offset:var(--space-0); cursor:pointer; }

/* ---- help: a dock panel ----------------------------------------------------------- */
.help-panel { display:flex; flex-direction:column; min-height:0; font-family:var(--font-ui); }
.panel-body { flex:1; min-height:0; overflow:auto; overscroll-behavior:contain; padding:var(--space-3); color:var(--ink); font-size:var(--step-n1); line-height:var(--leading-text); }
.panel-body p { margin:var(--space-3) 0 0; }
.help-keys { display:grid; gap:var(--space-1); margin:0; padding:0; list-style:none; }
.help-keys li { display:grid; grid-template-columns:calc(var(--unit) * 5) 1fr; align-items:center; gap:var(--space-2); }
.help-fine { color:var(--muted); font-size:var(--step-n2); }

/* ---- watchlist ------------------------------------------------------------------- */
.watchlist { display:flex; flex-direction:column; min-height:0; font-family:var(--font-ui); }
/* A panel opens with a head as tall as the chart's toolbar: its name in capitals, and its own controls. */
.watch-head,.panel-head { flex:none; display:flex; align-items:center; gap:var(--space-2); min-height:var(--toolbar-height); padding:var(--space-1) var(--space-3); }
.panel-title { margin:0; font-family:var(--font-ui); line-height:var(--leading-tight); }
.watch-title,.panel-title { color:var(--ink); font-size:var(--step-n2); font-weight:var(--weight-strong); letter-spacing:var(--tracking-caps); text-transform:uppercase; white-space:nowrap; }
.watch-count { color:var(--muted); font-weight:var(--weight-regular); }
.watch-head .filter { flex:1; min-width:0; width:auto; min-height:calc(var(--control-height) - var(--space-1)); }
.watch-scroll { flex:1; min-height:0; overflow:auto; overscroll-behavior:contain; }
table.watch { width:100%; border-collapse:collapse; font-size:var(--step-n1); font-variant-numeric:lining-nums tabular-nums; }
table.watch thead th { position:sticky; top:0; z-index:1; padding:var(--space-1) var(--space-2); border-bottom:var(--rule) solid var(--line); background:var(--canvas);
  color:var(--muted); font-size:var(--step-n2); font-weight:var(--weight-strong); letter-spacing:var(--tracking-caps); text-align:left; text-transform:uppercase; white-space:nowrap; }
table.watch thead th.num { text-align:right; }
table.watch thead th:first-child,table.watch tbody th { padding-left:var(--space-3); }
table.watch thead th:last-child,table.watch td:last-child { padding-right:var(--space-3); }
table.watch th button { padding:0; border:0; background:none; color:inherit; font:inherit; letter-spacing:inherit; text-transform:inherit; cursor:pointer; }
table.watch th[aria-sort="ascending"] button::after { content:" ↑"; }
table.watch th[aria-sort="descending"] button::after { content:" ↓"; }
table.watch tbody tr { cursor:pointer; }
table.watch tbody tr:hover { background:var(--surface-hover); }
table.watch tbody tr[aria-selected="true"] { background:var(--accent-soft); box-shadow:inset var(--rule-strong) 0 var(--accent); }
table.watch tbody th,table.watch td { padding:var(--row-pad) var(--space-2); white-space:nowrap; }
/* A stale world's date or a Retired tag wraps under the name only where the row lacks room. */
/* position: the row's screen-reader note stays inside the scrolling list, not the page. */
table.watch tbody th { position:relative; font-weight:var(--weight-regular); text-align:left; }
table.watch td { text-align:right; }
table.watch .pick { padding:0; border:0; background:none; color:var(--ink); font:inherit; text-align:left; cursor:pointer; }
table.watch tr[aria-selected="true"] .pick { font-weight:var(--weight-strong); }
/* Compact row indicators, set as a small raised letter after the name, as a watchlist marks a delayed quote: R
   (retired) and i (latest best offer is old). The note is in the tooltip; the target stays a finger's width. */
table.watch .flag { position:relative; display:inline-block; margin-left:var(--space-0); padding:0 var(--space-0); border-radius:var(--radius-sm);
  color:var(--muted); font-size:calc(var(--step-n2) * .85); font-weight:var(--weight-strong); line-height:1; vertical-align:super; cursor:help; }
table.watch .flag::before { content:""; position:absolute; inset:calc(var(--space-1) * -1); }
table.watch .flag-retired { color:var(--caution); }
table.watch .flag:hover,table.watch .flag:focus-visible { color:var(--accent); }
table.watch .flag:focus-visible { outline-offset:var(--rule); }
.watch-tip { position:fixed; z-index:var(--layer-header); max-width:calc(var(--unit) * 70); padding:var(--space-1) var(--space-2); border-radius:var(--radius-sm);
  background:var(--ink); color:var(--canvas); font-family:var(--font-ui); font-size:var(--step-n2); line-height:var(--leading-text); pointer-events:none; }
.details-status { margin:calc(var(--space-1) * -1) 0 var(--space-2); color:var(--muted); font-size:var(--step-n1); }
table.watch td.stale { color:var(--muted); }
.watchlist .empty { padding:var(--space-5) var(--space-3); }

/* ---- the dock: the open panel, then the rail -------------------------------------- */
.dock { display:flex; min-width:0; min-height:0; }
.dock-panel { width:var(--watch-width); border-right:var(--rule) solid var(--line); }
.dock-panel:not(.is-open) { display:none; }
/* The rail launches tools and holds no chart state. It is regions by meaning (markets.html): the tools that analyse
   or navigate the market from the top, level with the chart's status, then flexible space, and the utilities at the
   bottom, level with the ranges row. Every tool is one square slot; on, open or pressed, a slot holds the control
   track. */
.dock-rail { flex:none; display:flex; flex-direction:column; align-items:center; width:var(--rail-width);
  padding-block:var(--space-1) calc((var(--toolbar-height) - var(--space-3) - var(--space-6)) / 2); }
.dock-group { display:flex; flex-direction:column; align-items:center; gap:var(--space-1); }
.dock-space { flex:1; }
.dock-tool { width:var(--space-6); height:var(--space-6); }

/* ---- selected world: under the list, as a watchlist shows its symbol ------------------------ */
/* The world and what it is; its quote for the side shown, large, with its change over the range; when it was
   observed; both sides and the spread; then its change over every range, each one press from the chart. */
.details { flex:none; padding:var(--space-3); border-top:var(--rule) solid var(--line); font-family:var(--font-ui); font-variant-numeric:lining-nums tabular-nums; }
:where(.details) p { margin:0; }
.details-title { margin:0; font-family:var(--font-editorial); font-size:var(--step-1); font-weight:var(--weight-regular); line-height:var(--leading-tight); }
.details-meta { display:flex; flex-wrap:wrap; gap:0 var(--space-3); margin-top:var(--space-0); color:var(--muted); font-size:var(--step-n2); }
.details-quote { display:flex; align-items:baseline; gap:var(--space-2); margin-top:var(--space-2); }
.details-last { font-size:var(--step-3); font-weight:var(--weight-strong); letter-spacing:var(--tracking-tight); line-height:var(--leading-tight); }
.details-unit { color:var(--muted); font-size:var(--step-n2); font-weight:var(--weight-regular); }
.details-change { display:flex; align-items:baseline; gap:var(--space-2); font-size:var(--step-0); font-weight:var(--weight-strong); }
.details-note { margin-top:var(--space-1); color:var(--muted); font-size:var(--step-n2); line-height:var(--leading-text); }
.details-note span { color:var(--ink); }
/* Both sides and the spread on one line: the chart's status shows them too, so here they stay small. */
.details-book { display:flex; flex-wrap:wrap; gap:0 var(--space-4); margin:var(--space-2) 0 0; font-size:var(--step-n1); }
.details-book div { display:flex; align-items:baseline; gap:var(--space-1); }
.details-book dt { color:var(--muted); font-size:var(--step-n2); }
.details-book dd { margin:0; font-weight:var(--weight-strong); white-space:nowrap; }
.details-heading { margin:var(--space-3) 0 var(--space-1); color:var(--muted); font-size:var(--step-n2); font-weight:var(--weight-strong); letter-spacing:var(--tracking-caps); text-transform:uppercase; }
.performance { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:var(--space-1); }
.performance button { display:grid; gap:0; padding:var(--space-1); border:0; border-radius:var(--radius-sm); background:var(--surface-soft); color:var(--ink);
  font-family:var(--font-ui); font-variant-numeric:lining-nums tabular-nums; line-height:var(--leading-tight); text-align:center; cursor:pointer; }
.performance button:hover { background:var(--control-track); }
.performance button[aria-pressed="true"] { background:var(--surface); box-shadow:inset 0 0 0 var(--rule) var(--line-strong); }
.perf-value { font-size:var(--step-n1); font-weight:var(--weight-strong); }
.perf-range { color:var(--muted); font-size:var(--step-n2); }

/* ---- full screen: the whole terminal, rail and open panel included; true full screen, or the whole viewport
   where that is unavailable. The page's margins give way to the screen's edges. ---- */
.terminal:fullscreen { padding:0; background:var(--canvas); }
.terminal.expanded { position:fixed; inset:0; z-index:var(--layer-header); max-width:none; padding:0; background:var(--canvas); }
/* In the page, the chart's text starts on the page's edge, under Tibinance; at full screen it keeps an inset. */
.terminal:not(.expanded,:fullscreen) .toolbar { padding-left:0; }
.terminal:not(.expanded,:fullscreen) .chart-head { left:0; }

/* ---- narrow: chart first, then the list; the page scrolls ------------------------- */
@media (max-width:900px) {
  body { display:block; height:auto; overflow:visible; }
  .terminal { display:flex; flex-direction:column; }
  .chart-panel { height:clamp(calc(var(--unit) * 95), 72dvh, calc(var(--unit) * 160)); border-right:0; border-bottom:var(--rule) solid var(--line); }
  .watch-scroll { overflow:visible; }
  table.watch thead th { position:static; }
  .details { order:-1; border-top:0; border-bottom:var(--rule) solid var(--line); }
  /* Under the chart, the rail as a row, then the panel it opens; the default panel stands last, open or not,
     so its button is not shown. */
  .dock { display:flex; flex-direction:column; }
  /* The same regions, start to end: the market tools, space, the utilities. */
  .dock-rail { order:-1; flex-direction:row; width:auto; padding:var(--space-1) 0; border-bottom:var(--rule) solid var(--line); }
  .dock-group { flex-direction:row; }
  /* With Worlds always listed below, its tool is not shown. */
  .dock-tool[data-dock-default] { display:none; }
  .dock-panel { width:auto; border-right:0; }
  .dock-panel:not([data-dock-default]) { border-bottom:var(--rule) solid var(--line); }
  .dock-panel[data-dock-default] { display:flex; order:1; }
  /* At full screen a phone shows the chart and the rail's actions. */
  .terminal:is(.expanded,:fullscreen) { display:flex; flex-direction:column; overflow:hidden; }
  .terminal:is(.expanded,:fullscreen) .chart-panel { flex:1; height:auto; border-bottom:0; }
  .terminal:is(.expanded,:fullscreen) :is(.dock-panel,[data-dock-target]) { display:none; }
  .terminal:is(.expanded,:fullscreen) .dock-rail { padding-inline:var(--space-2); border-top:var(--rule) solid var(--line); border-bottom:0; }
}
/* A narrow chart (a phone, or the panel open on a small screen): the status keeps the world, its quote and the side,
   and gives the price scale's column more of the width. The world's metadata is in the details under the chart. */
@container chart (max-width:471.98px) {
  .chart-head .symbol-meta,.legend .meta,.through { display:none; }
  .chart-head { max-width:calc(100% - var(--space-8)); }
  .head-line h2 { font-size:var(--step-1); }
  /* The readout may run up to the price scale, so the change keeps to one line. */
  .chart-legend { column-gap:var(--space-2); }
  .legend .rest { flex-wrap:nowrap; white-space:nowrap; }
  /* The projection's band and day take their own line under its name, where there is no room beside its value. */
  .legend .rest.projected { grid-column:1 / -1; flex-wrap:wrap; padding-left:calc(var(--space-4) + var(--space-1)); }
  /* So do the day's traded high and low (a token's open, high and low): under the value, never past the chart's edge. */
  .legend .rest.ohlc { grid-column:1 / -1; flex-wrap:wrap; padding-left:calc(var(--space-4) + var(--space-1)); }
}

/* Events shares the dock's width and independent scrolling, leaving the chart visible. */
.events-panel { display:flex; flex-direction:column; min-height:0; }
.events-panel .panel-head { justify-content:space-between; }
.events-panel label,.events-panel small,.event-calendar-key { font-size:var(--step-n2); color:var(--muted); }
.events-panel .panel-body > p:first-child { margin-top:0; }
.events-panel h3 { font-size:var(--step-n1); margin:var(--space-3) 0 var(--space-2); }
.events-panel button,.events-panel select,.events-panel input[type="month"] { font:inherit; color:var(--ink); background:var(--surface); border:var(--rule) solid var(--line); border-radius:var(--control-radius); padding:var(--space-1); min-height:32px; }
.events-panel button { cursor:pointer; }
.events-panel button:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
.event-filters { display:grid; grid-template-columns:1fr 1fr; gap:var(--space-2); margin-block:var(--space-3); }
.event-filters label { display:grid; gap:var(--space-1); min-width:0; }
.event-filters select { width:100%; }
.event-month-nav { display:flex; gap:var(--space-1); align-items:center; }
.event-month-nav input { min-width:0; flex:1; width:100px; }
.event-calendar { display:grid; grid-template-columns:repeat(7,minmax(0,1fr)); gap:3px; margin-top:var(--space-2); text-align:center; }
.event-calendar > span { font-size:10px; color:var(--muted); }
.event-calendar button { position:relative; display:grid; padding:2px; min-height:36px; }
.event-calendar small { font-size:10px; color:var(--accent); min-height:12px; }
.event-calendar button[aria-current] { border-color:var(--accent); }
.events-panel button[aria-pressed="true"] { background:var(--control-track); border-color:var(--accent); }
.event-span { position:absolute; inset:auto 2px 1px; height:2px; background:var(--accent); }
.event-row { display:grid; text-align:left; gap:3px; width:100%; margin-bottom:var(--space-1); }
.event-row strong { font-weight:var(--weight-strong); }
.event-details { border-block:var(--rule) solid var(--line); padding-block:var(--space-2); margin-block:var(--space-3); }
.event-details p { margin-top:var(--space-2); }
.event-agenda-head { display:flex; justify-content:space-between; gap:var(--space-2); align-items:center; }
.event-agenda-head select { min-width:0; max-width:70%; }
@media(max-width:760px) { .events-panel .panel-body { overflow:visible; } .events-panel button { min-height:44px; } }

.event-section-nav { display:flex; gap:var(--space-2); padding:var(--space-1) var(--space-3); border-bottom:var(--rule) solid var(--line); flex:none; }
.event-section-nav button { flex:1; }

/* ---- screener: every world side by side, in the chart's place (js/market-screener-panel.js) ---------------- */
/* The same frame as the chart: a head as tall as its toolbar, the controls under it, the grid scrolling on its own and
   the ranges at the foot. In the page its text starts on the page's edge, under Tibinance. */
.screener { container:screener / inline-size; display:flex; flex-direction:column; min-width:0; min-height:0; border-right:var(--rule) solid var(--line); background:var(--canvas); font-family:var(--font-ui); }
.screener .toolbar,.screener-controls,.screener-scroll { padding-right:var(--space-4); }
.screener-head { align-items:center; }
.screener-head .symbol { margin-right:auto; }
.screener-side { min-height:calc(var(--control-height) - var(--space-1)); }
.screener-side [data-side="sell"][aria-checked="true"] { color:var(--sell); }
.screener-side [data-side="buy"][aria-checked="true"] { color:var(--buy); }
.screener-find { display:flex; flex:0 1 var(--filter-width); gap:var(--space-2); min-width:0; }
.screener-head .filter { flex:1; min-width:0; width:auto; min-height:calc(var(--control-height) - var(--space-1)); }
.screener-controls { flex:none; display:flex; flex-wrap:wrap; align-items:center; gap:var(--space-2) var(--space-4); padding-left:var(--space-4); padding-bottom:var(--space-2); }
.terminal:not(.expanded,:fullscreen) .screener-controls { padding-left:0; }
.screener-controls label { display:inline-flex; align-items:center; gap:var(--space-2); color:var(--muted); font-size:var(--step-n2); font-weight:var(--weight-strong); letter-spacing:var(--tracking-caps); text-transform:uppercase; white-space:nowrap; }
.screener-controls select { min-height:calc(var(--control-height) - var(--space-1)); max-width:calc(var(--unit) * 48); padding:0 var(--space-1); border:var(--rule) solid var(--line-strong); border-radius:var(--control-radius);
  background:var(--surface); color:var(--ink); font-family:var(--font-ui); font-size:var(--step-n1); font-weight:var(--weight-regular); letter-spacing:normal; text-transform:none; }
.screener-controls select:focus { border-color:var(--accent); }
.screener-sort { display:inline-flex; align-items:center; gap:var(--space-1); }
.screener-sort .tool { width:calc(var(--control-height) - var(--space-1)); height:calc(var(--control-height) - var(--space-1)); }
.screener-sort .tool svg { width:calc(var(--unit) * 4); height:calc(var(--unit) * 4); }
#screenerDirection[data-dir="ascending"] .icon-descending,#screenerDirection[data-dir="descending"] .icon-ascending { display:none; }
.screener-button { flex:none; min-height:calc(var(--control-height) - var(--space-1)); padding:0 var(--space-2); border:0; border-radius:var(--radius-sm); background:transparent; color:var(--muted); font-family:var(--font-ui); font-size:var(--control-type); cursor:pointer; white-space:nowrap; }
.screener-button:hover,.screener-button[aria-expanded="true"] { background:var(--control-track); color:var(--ink); }
.screener-filters-toggle { display:none; }
.screener-scroll { flex:1; min-height:0; overflow:auto; overscroll-behavior:contain; padding-top:var(--space-3); padding-bottom:var(--space-4); border-top:var(--rule) solid var(--line); }
.screener .empty { margin:0; padding:var(--space-5) 0; color:var(--muted); font-size:var(--step-n1); }

/* A card per world, like a mini chart on a market overview: the world and its latest best offer, what it is and its
   change over the range, the mini chart, then its figures. The selected world is marked as in the list. */
.screener-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(calc(var(--unit) * 60),1fr)); gap:var(--space-3); margin:0; padding:0; list-style:none; }
.screen-card { display:flex; flex-direction:column; gap:var(--space-1); height:100%; padding:var(--space-3); border:var(--rule) solid var(--line); border-radius:var(--radius);
  background:var(--canvas); color:var(--ink); font-variant-numeric:lining-nums tabular-nums; text-decoration:none; }
.screen-card:hover { border-color:var(--line-strong); background:var(--surface-hover); }
.screen-card:focus-visible { outline-offset:0; }
.screen-card[aria-current="true"] { border-color:var(--accent); box-shadow:inset 0 0 0 var(--rule) var(--accent); }
.screen-head,.screen-sub { display:flex; align-items:baseline; justify-content:space-between; gap:var(--space-2); min-width:0; }
.screen-name { min-width:0; overflow:hidden; font-family:var(--font-editorial); font-size:var(--step-1); line-height:var(--leading-tight); text-overflow:ellipsis; white-space:nowrap; }
.screen-last { flex:none; font-size:var(--step-0); font-weight:var(--weight-strong); }
.screen-last.stale { color:var(--muted); }
.screen-day { color:var(--muted); font-size:var(--step-n2); white-space:nowrap; }
.screen-change { flex:none; margin-left:auto; font-size:var(--step-n2); white-space:nowrap; }
/* What the world is, at the foot: it wraps rather than cutting a word. */
.screen-meta { display:flex; flex-wrap:wrap; gap:0 var(--space-3); margin-top:auto; padding-top:var(--space-1); color:var(--muted); font-size:var(--step-n2); }
/* The mini chart: the chart's own marks, small. The SVG stretches to the card; its lines keep their width. */
.screen-spark { display:block; width:100%; height:calc(var(--unit) * 14); margin-block:var(--space-1); overflow:hidden; }
.screen-spark path { fill:none; vector-effect:non-scaling-stroke; stroke-linejoin:round; }
.screen-spark .spark-solid,.screen-spark .spark-dotted { stroke:var(--side); stroke-width:1.5; }
.screen-spark .spark-dotted { stroke-dasharray:2 2; }
.screen-spark .spark-area { fill:var(--side); opacity:.08; }
.screen-spark .spark-base { stroke:var(--line-strong); stroke-width:1; stroke-dasharray:2 3; }
.screen-spark .spark-last { stroke:var(--side); stroke-width:5; stroke-linecap:round; }
.screen-none { display:grid; place-items:center; border-radius:var(--radius-sm); background:var(--surface-soft); color:var(--muted); font-size:var(--step-n2); }
.screen-stats { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:var(--space-1) var(--space-2); margin:0; }
.screen-stats div { min-width:0; }
.screen-stats dt { color:var(--muted); font-size:var(--step-n2); }
.screen-stats dd { margin:0; overflow:hidden; font-size:var(--step-n1); text-overflow:ellipsis; white-space:nowrap; }
/* The selected side's best offer in its side's colour, as the chart draws it. */
.screen-stats .on dd { color:var(--side); font-weight:var(--weight-strong); }
/* Narrow, the filters fold behind a button beside the search, so the grid keeps the room. */
@container screener (max-width:599.98px) {
  .screener-filters-toggle { display:block; }
  .screener:not(.filters-open) .screener-controls { display:none; }
  .screener-find { flex:1 1 100%; }
}
@container screener (max-width:471.98px) {
  .screener .through { display:none; }
}

@media (max-width:900px) {
  /* In the chart's place and at its height, the grid scrolling inside; the list under it would repeat the grid. */
  /* With the list hidden, the grid may take the screen under the header, less the rail's row. */
  .screener { height:max(calc(var(--unit) * 95), calc(100dvh - var(--header-height) - var(--space-4) - var(--unit) * 12)); border-right:0; border-bottom:var(--rule) solid var(--line); }
  .terminal.is-screening .dock-panel[data-dock-default] { display:none; }
  .terminal:is(.expanded,:fullscreen) .screener { flex:1; height:auto; border-bottom:0; }
  .screener-controls { gap:var(--space-2) var(--space-3); }
}
@media (max-width:760px) {
  .screener-controls label,.screener-sort { flex:1 1 calc(50% - var(--space-3)); justify-content:space-between; }
  .screener-controls select { flex:1; max-width:none; min-height:calc(var(--unit) * 11); }
  .screener-sort label { flex:1; }
  .screener-button { min-height:calc(var(--unit) * 11); }
}
/* Dense event clusters remain inspectable on small screens. */
.event-tip { max-height:calc(100dvh - 24px); overflow-y:auto; }
