/*
 * Two panels: the chart on top, the trades under it. Everything else is
 * chrome around those two.
 *
 * Every colour is a token of tokens.css (docs/web/DESIGN.md), the same names in
 * both themes, and each has one job: long, a target, a gain and a rising
 * candle are --up; short, a stop, a loss and a falling candle are --down;
 * the entry and the selected trade are --entry. A trade's row and its
 * markers on the chart are deliberately the same colour, because the whole
 * interaction is "this row is that thing up there". Colour is never the
 * only sign: a triangle, a sign, a word or a dash always goes with it.
 * Ochre belongs to the brand and to the page's one main button, nothing else.
 */

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: var(--fs-body)/var(--lh) var(--font-sans);
  /* a slashed zero: 0 and O side by side in an instrument or an ID */
  font-feature-settings: "zero" 1;
}

/* the figures: prices, times, amounts, IDs, code - in the mono, whose
   digits line up in a column whatever they are */
td.num, pre, code, #live-clock, #data-dir,
input[type="number"], input[type="date"], .event {
  font-family: var(--font-mono);
}
/* the trades table's times and numbers, which have no class of their own:
   #, signal, entry and exit */
#trade-rows td:is(:nth-child(1), :nth-child(2), :nth-child(5), :nth-child(7)) {
  font-family: var(--font-mono);
}

a { color: var(--accent-text); }

/* tokens.css says "light dark" and lets the system pick; a theme forced by
   the switch has to say so too, or the browser's own parts - scrollbars, the
   date picker, a select's list - stay in the system's */
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"] { color-scheme: dark; }

/* titoli: nome della pagina, dialog, pannelli (DESIGN.md § 4). PD Instrument
   has one weight: size and face make the order, and 400 with no synthesis
   because an h2 is bold by default and the browser would fake it, badly.
   Only titles - labels, fields, tables and figures stay in Plex */
.page-title, .dialog-title, .panel-title { margin: 0; font-family: var(--font-title); font-weight: 400; font-synthesis: none; letter-spacing: var(--tracking-title); color: var(--text); }
.page-title { font-size: var(--fs-h-page); line-height: 1.1; }
.dialog-title { font-size: var(--fs-h-dialog); line-height: 1.15; }
.panel-title { font-size: var(--fs-h-panel); line-height: 1.2; }
/* a datum of context after a title, on its baseline (DESIGN.md § 6) */
.panel-title .hint { font: var(--fs-small) var(--font-mono); letter-spacing: 0; color: var(--text-3); }
.dialog-title .id { font: 500 17px var(--font-mono); letter-spacing: 0; }
/* a section in a panel, and its parts (docs/ux/analisi-2026-10-02-h3.md, B):
   the h3 in the titles' face, the h4 in Plex at 500 - at 600 it weighed as
   much as the serif above it. The classes above win where an h3 is a title */
h3 { margin: 32px 0 8px; font: 400 var(--fs-h-section)/1.15 var(--font-title); font-synthesis: none; letter-spacing: var(--tracking-title); color: var(--heading); }
h4 { margin: 24px 0 4px; font: 500 var(--fs-h-sub)/1.3 var(--font-sans); color: var(--heading); }

/* ------------------------------------------------------------ header */

/* the header: the logo, the page, where the orders go, and the pages. The
   controls are a bar of their own under it */
header {
  background: var(--panel);
  border-bottom: 1px solid var(--line);
  padding: 0 var(--gutter);
}
#brand {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--header-h);
  padding: var(--space-2) 0;
}
h1 { margin: 0; display: flex; }
h1 img { height: 28px; width: auto; }
/* one logo per theme, shown the way tokens.css picks its values: the light
   one unless the system asks for dark and the switch has not said light, or
   the switch said dark */
.logo-dark { display: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .logo-light { display: none; }
  :root:not([data-theme="light"]) .logo-dark { display: block; }
}
:root[data-theme="dark"] .logo-light { display: none; }
:root[data-theme="dark"] .logo-dark { display: block; }

/* the page's name, after a rule: a title (.page-title, below), not a label */
#page-name {
  padding-left: var(--space-3);
  border-left: 1px solid var(--line);
}
/* a pill: a short word in a rounded frame - where the orders go, a count in a
   title, an outcome, a real account */
.badge, .dialog-count, .outcome, #new-accounts .real { padding: 1px var(--space-2); border-radius: var(--radius-pill); white-space: nowrap; }
/* what the server is and where the orders go, on every page and always in
   sight: whoever looks must know at any moment whether real money is moving */
.badge {
  font-size: var(--fs-small);
  line-height: 18px;
  border: 1px solid var(--border);
  color: var(--text-2);
}
.badge.practice { border-color: var(--entry); color: var(--entry); }
/* the one thing on the screen filled with red */
.badge.live { background: var(--live); border-color: var(--live); color: var(--on-live); font-weight: 700; }
.badge.live::before {
  content: "";
  display: inline-block;
  width: 7px;
  height: 7px;
  margin-right: 6px;
  vertical-align: 1px;
  border-radius: var(--radius-pill);
  background: currentColor;
}
/* the page waiting on the service (menu.js): the three squares of a section
   that reads (.dots, below) */
/* DefunctumEst: the ring that turned (#spinner's border, @keyframes spin), replaced by .dots */
#spinner { margin-left: 0; color: var(--text-2); }
#spinner[hidden] { display: none; }

/* a section that reads (menu.js readingLine): what it reads, three squares as
   tall as the small letters, on the baseline, lit in turn, the seconds from
   5 s. Shown after 250 ms, as the header's, so a quick answer never blinks;
   its room is kept all the same */
.reading, tr.bones, .chart-reading { animation: reading-in 0s .25s both; }
@keyframes reading-in { from { visibility: hidden; } to { visibility: visible; } }
.reading { color: var(--text-2); }
.reading .why, .reading .secs { color: var(--text-3); }
.reading .secs { margin-left: var(--space-2); font: var(--fs-small) var(--font-mono); }
.dots { display: inline-block; margin-left: .3em; white-space: nowrap; }
.dots i { display: inline-block; width: .52em; height: .52em; vertical-align: baseline; background: currentColor;
  animation: dot 1.2s ease-in-out infinite; }
.dots i + i { margin-left: .28em; }
.dots i:nth-child(2) { animation-delay: .2s; }
.dots i:nth-child(3) { animation-delay: .4s; }
@keyframes dot { 0%, 100% { opacity: .25; } 40% { opacity: 1; } }
/* blocks where the figures will be: a row of a table, the axis of a chart */
.bone, .chart-reading .grid i::before { display: inline-block; height: 10px; vertical-align: middle;
  border-radius: 3px; background: var(--line); animation: bone 1.6s ease-in-out infinite; }
.bone + .bone { margin-left: 6px; }
@keyframes bone { 0%, 100% { opacity: 1; } 50% { opacity: .45; } }
tr.bones td { height: var(--target-min); }
tbody tr.bones, tbody tr.bones:hover { cursor: default; background: none; }
/* a reading that failed: the squares stop, the words in down and a try again */
.reading-failed { display: inline-flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); color: var(--down); }
.reading-failed svg { flex: none; }
.reading-failed button { color: var(--text); }
@media (prefers-reduced-motion: reduce) { .dots i, .bone, .chart-reading .grid i::before { animation: none; } }

/* the theme switch: three buttons in one frame, the one in force pressed */
#theme { display: inline-flex; gap: 2px; padding: 2px; border: 1px solid var(--border); border-radius: var(--radius-s); }
/* the language, first in the theme's box (i18n.js): as small as its buttons */
#theme #look-next { display: none; }
#theme :is(#lang, #look) { height: 28px; width: auto; padding: 0 2px; border: 0; background: transparent; font-size: var(--fs-small); color: var(--text-2); }
#theme button { height: 28px; width: 30px; padding: 0; display: inline-flex; align-items: center; justify-content: center;
  border: 0; border-radius: var(--radius-xs); color: var(--text-3); }
#theme button:hover { color: var(--text); }
#theme button[aria-pressed="true"] { background: var(--raised); color: var(--text); box-shadow: inset 0 0 0 1px var(--line); }

/* risorse del server: spia in testata + pannello (DESIGN.md § 6). Was: a
   strip of four green meters always on show, some 690 px of header; now one
   chip that names the worst of them, and the four in a panel on a click
   (menu.js). Never green: a full disk is not a gain */
.sys { position: relative; flex: none; }
.sys-chip { display: inline-flex; align-items: center; gap: 8px; height: 30px; padding: 0 10px 0 9px; border: 1px solid var(--line); border-radius: var(--radius-s); background: transparent; color: var(--text-2); font: 500 12px var(--font-sans); white-space: nowrap; cursor: pointer; }
.sys-chip:hover { border-color: var(--border); color: var(--text); }
.sys-chip:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.sys-chip.warn { border-color: var(--warn); color: var(--warn); }
.sys-chip.crit { border-color: var(--down); color: var(--down); }
.sys-chip.stale { border-style: dashed; color: var(--text-3); }
.sys-chip .v { font: 500 12px var(--font-mono); }
.sys-mini { display: flex; align-items: flex-end; gap: 2px; height: 14px; }
.sys-mini i { width: 3px; border-radius: 1px; background: var(--text-3); }
.sys-mini i.warn { background: var(--warn); }
.sys-mini i.crit { background: var(--down); }
.sys-ico { width: 12px; height: 12px; flex: none; color: var(--down); }
#sys-text { display: inline-flex; align-items: center; gap: 4px; }
.sys-pop { position: absolute; right: 0; top: calc(100% + 8px); z-index: 20; width: 300px; box-sizing: border-box; padding: 12px 14px; background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius-m); box-shadow: var(--shadow-float); }
.sys-pop[hidden] { display: none; }
.sys-pop .panel-title { margin: 0 0 8px; }
.sys-row { --fill: var(--text-3); --val: var(--text-2); --w: 400; display: grid; grid-template-columns: 56px 1fr auto; align-items: center; gap: 4px var(--space-3); padding: 5px 0; }
.sys-row.warn { --fill: var(--warn); --val: var(--warn); --w: 600; }
.sys-row.crit { --fill: var(--down); --val: var(--down); --w: 600; }
.sys-row .l { font-size: 12px; color: var(--text-3); white-space: nowrap; }
.sys-row .path { font-family: var(--font-mono); }
.sys-row .track { display: block; height: 4px; border-radius: 2px; background: var(--line); overflow: hidden; }
.sys-row .fill { display: block; height: 100%; border-radius: 2px; background: var(--fill); }
.sys-row .v { display: inline-flex; align-items: center; justify-content: flex-end; gap: 3px; min-width: 4ch; font: var(--w) 12px var(--font-mono); color: var(--val); }
.sys-row .abs { grid-column: 2 / 4; margin-top: -2px; font: 11px var(--font-mono); color: var(--text-3); }
.sys-foot { margin: 8px 0 0; padding-top: 8px; border-top: 1px solid var(--line); font-size: 11px; color: var(--text-3); }

/* the pages, at the right of every header (menu.js) */
#menu { margin-left: auto; display: flex; gap: var(--space-1); }
#menu a {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: var(--control-h);
  padding: 0 var(--space-3);
  color: var(--text-2);
  text-decoration: none;
  border: 1px solid transparent;
  border-radius: var(--radius-s);
}
#menu a[hidden] { display: none; }
#menu a:hover { color: var(--text); border-color: var(--line); }
#menu [aria-current="page"] { color: var(--text); border-color: var(--border); background: var(--raised); }
/* something going on in the service - a sweep, a live session - lights its
   entry up on every page (menu.js, api/busy). It is news, not a success */
#menu a.busy { color: var(--entry); }
#menu a.busy svg { animation: busy 1.6s ease-in-out infinite; }
@keyframes busy {
  0%, 100% { opacity: 1; }
  50% { opacity: .4; }
}
@media (prefers-reduced-motion: reduce) { #menu a.busy svg { animation: none; } }
@media (max-width: 900px) {
  #menu span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
  #menu a { padding: 0 var(--space-2); }
}
/* the same when the words do not fit beside the rest (menu.js oneRow) */
#brand.icons-only #menu span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
/* 6 px a side: the eighth entry (dashboard) fits where seven did, the target stays 30 px */
#brand.icons-only #menu a { padding: 0 6px; }
/* a phone: three rows - the page, where the orders go, the pages - in some
   120 px. The theme in force only, a tap on it the next one (menu.js); the
   chip its bars, its word kept for a screen reader and its figures in its title */
@media (max-width: 640px) {
  /* 8 px between the pieces: in paper the badges, the chip and the theme's box fill the row to the pixel */
  #brand { row-gap: var(--space-1); column-gap: var(--space-2); padding: var(--space-1) 0; }
  /* the pages last, a row of their own; the chip and the theme beside the badges */
  #menu { order: 1; }
  #theme button[aria-pressed="false"] { display: none; }
  /* the look one button too, "Aa", the next one at a tap (menu.js) */
  #theme #look { display: none; }
  #theme #look-next { display: inline-flex; font: 500 var(--fs-small) var(--font-sans); }
  #sys-text { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
}

/* ------------------------------------------------------------ controls */

/* the controls, under the header: a bar of their own */
.bar {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  align-items: flex-end;
  padding: var(--space-3) var(--gutter) var(--space-4);
  background: var(--panel);
  border-bottom: 1px solid var(--line);
}

form { display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: flex-end; }

label, .field {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  font-size: var(--fs-label);
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  color: var(--text-3);
}
/* the display above beats the browser's own [hidden]: without this a label hidden
   by its page still showed, as the mix's zones did (issue #24) */
:is(label, .field)[hidden] { display: none; }
/* parametri sì/no: segmentato Y | N (DESIGN.md § 6, Campi). Was: two bare
   system checkboxes; still two checkboxes, not a radio - both lit is a run of
   each - each one under its segment, transparent, so a click, Tab, Space and
   a screen reader work on it as they did */
.yn, #mix-views, #mix-mode, #auto-stopat { display: inline-flex; gap: 2px; height: var(--control-h); box-sizing: border-box; padding: 2px; border: 1px solid var(--border); border-radius: var(--radius-s); background: var(--bg); }
.yn label, #mix-views button, #mix-mode button, #auto-stopat button { padding: 0 10px; border-radius: var(--radius-xs); color: var(--text-3); transition: background-color .12s, color .12s; }
.yn label { position: relative; display: inline-flex; flex-direction: row; align-items: center; justify-content: center; min-width: 40px; font: 500 13px var(--font-sans); text-transform: none; letter-spacing: 0; cursor: pointer; user-select: none; }
.yn input { position: absolute; inset: 0; margin: 0; opacity: 0; cursor: pointer; }
.yn label:hover, #mix-views button:hover, #mix-mode button:hover, #auto-stopat button:hover { color: var(--text); background: var(--line); }
.yn label:has(input:checked), #mix-views button[aria-pressed="true"], #mix-mode button[aria-pressed="true"],
  #auto-stopat button[aria-pressed="true"] { color: var(--panel); background: var(--text); font-weight: 600; }
.yn label:has(input:focus-visible) { outline: 2px solid var(--focus); outline-offset: 1px; }
.yn label:has(input:disabled) { opacity: .45; cursor: default; }
.yn:not(:has(input:checked)) { border-color: var(--down); }
/* its own width under its name, not the name's */
.field .yn { align-self: flex-start; }

select, input, button {
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  font-feature-settings: "zero" 1;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-s);
  padding: 0 var(--space-2);
}
/* one height for every control, and a target that stays big enough for a
   finger; a box to tick is its own size */
select, button, input:not([type="checkbox"]):not([type="radio"]):not([type="file"]) {
  height: var(--control-h);
}
input[type="file"] { padding: 6px var(--space-2); }
input:disabled { opacity: .45; cursor: default; }
/* a field's placeholder is its default ("none", "0", "optional"): read, so a
   text colour, not the browser's own grey - #757575 in both themes, 4.2:1 on
   the light ground and 3.8:1 on the dark one */
::placeholder { color: var(--text-3); opacity: 1; }

/* the secondary button, which is every button but one */
button { cursor: pointer; background: transparent; font-weight: 500; }
button:hover { border-color: var(--text-2); }
button:disabled { opacity: .5; cursor: default; }
/* the page's main action - one per page, the only ochre filled on screen */
button.primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); font-weight: 600; }
button.primary:disabled { opacity: 1; background: var(--line); border-color: var(--line); color: var(--text-3); }
/* a secondary in a colour, a link or a button: the colour says where it leads
   (piano-restyle fase 14). Its ground stays clear - on a tint the classic
   blue falls under 4.5:1 - so the hover thickens the border instead */
.tone { --tone: var(--text); display: inline-flex; align-items: center; height: var(--control-h);
        padding: 0 var(--space-2); border: 1px solid var(--tone); border-radius: var(--radius-s);
        background: transparent; color: var(--tone); font: 500 var(--fs-body) var(--font-sans);
        text-decoration: none; vertical-align: middle; }
.tone:hover { border-color: var(--tone); box-shadow: inset 0 0 0 1px var(--tone); }
.tone[hidden] { display: none; }
.tone-journal { --tone: var(--accent-text); }
.tone-verify { --tone: var(--verify); }
.tone-auto { --tone: var(--entry); }

/* the focus ring: always there for the keyboard, never taken away without
   something in its place */
:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
select:focus-visible, input:focus-visible {
  outline: none;
  border-color: var(--focus);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--focus) 20%, transparent);
}

/* ------------------------------------------------------------ messages */

#message {
  margin: 0;
  padding: var(--space-3) var(--gutter);
  background: var(--error-bg);
  border-bottom: 1px solid var(--down);
  color: var(--text);
  white-space: pre-wrap;
}
#message.info { background: var(--info-bg); border-bottom-color: var(--entry); }
/* a set going (sim.js sweepProgress, issue #30 layout C): its runs a 14px box
   each, wrapping on as many rows as they take, a legend counting them beside;
   under a rule the run going now, its bar and its parameters.
   DefunctumEst: the boxes shrinking to 1/N of the width in the message's band
   (#sweep-runs --n), replaced by this panel and its wrapping boxes */
#sweep-progress { display: flex; flex-direction: column; gap: var(--space-4); }
#sweep-progress[hidden] { display: none; }
#sweep-top { display: flex; flex-wrap: wrap; align-items: flex-start; gap: var(--space-4) 32px; }
#sweep-runs { flex: 1 1 320px; min-width: 0; display: flex; flex-wrap: wrap; align-content: flex-start; gap: 3px; }
#sweep-legend {
  flex: 0 0 200px; margin: 0; display: grid; grid-template-columns: minmax(0, 1fr) auto;
  gap: 6px 10px; font-size: var(--fs-small); color: var(--text-2);
}
#sweep-legend > div { display: contents; }
#sweep-legend dt { display: flex; align-items: center; gap: 10px; }
#sweep-legend dd { margin: 0; text-align: right; font: 500 var(--fs-small) var(--font-mono); color: var(--text); }
.sweep-box {
  flex: none; width: 14px; height: 14px; box-sizing: border-box; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--border); border-radius: 3px; font: 600 11px/1 var(--font-mono);
}
.sweep-box[data-kind=done] { background: var(--entry); border-color: var(--entry); }
.sweep-box[data-kind=broke] { background: var(--down); border-color: var(--down); color: var(--panel); font-size: 12px; }
.sweep-box[data-kind=failed] { border: 2px solid var(--warn); color: var(--warn); font-size: 9px; }
/* the run going, filled from the bottom as far as its bar (--pct, sweepProgress) */
.sweep-box[data-kind=now] {
  border-color: var(--entry);
  background: linear-gradient(to top, var(--entry) var(--pct, 0%), transparent var(--pct, 0%));
}
#sweep-run { display: flex; flex-direction: column; gap: 6px; padding-top: var(--space-3); border-top: 1px solid var(--line); }
#sweep-line { margin: 0; display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-3); color: var(--text-3); }
#sweep-text > span:first-child { font-weight: 500; color: var(--text); }
#sweep-pct { font: 500 var(--fs-body) var(--font-mono); color: var(--text); }
#sweep-bar { width: 100%; height: 6px; accent-color: var(--entry); }
/* the run's parameters and how far it got, a label over each value, a gap between the two lists */
#sweep-facts { display: flex; flex-wrap: wrap; gap: var(--space-3) 48px; }
.sweep-facts { margin: 0; display: flex; flex-wrap: wrap; gap: var(--space-3) 24px; }
.sweep-facts:empty { display: none; }
.sweep-facts dt { font-size: var(--fs-small); color: var(--text-3); }
.sweep-facts dd { margin: 0; font: 500 var(--fs-body) var(--font-mono); color: var(--text); }

/* ------------------------------------------------------------ panels */

/* every panel on the page's background: a change of surface and a rule, no
   shadow */
section {
  margin: var(--space-4) var(--gutter);
  padding: var(--space-4);
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-m);
}
/* the two strips live inside the chart panel and are read as part of it: same
   bars, same width, no padding of their own and no gap above. A strip that
   floats a centimetre under the candles is a second chart; one that touches
   them is the same chart with another axis. */
#curve-panel, #levels-panel { margin: 4px 0 0; padding: 0; border: 0; border-radius: 0; background: none; }

#chart-tools, #equity-head, #drawdown-head, #heat-head, #levels-head, #curve-head, #report-head, #trades-head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-2);
  color: var(--text-3);
}
/* the title has its own line. It is a title - what was run, on what, over
   what - and a readout that grows as the cursor moves used to push it about
   and wrap it; the controls and the readouts are in the row under it now,
   which is free to wrap without moving anything above it. */
#chart-head {
  margin-bottom: 4px;
  font-size: var(--fs-title);
  font-weight: 600;
  line-height: 1.4;
}
/* and that row wraps rather than squeezing its buttons off the end */
#chart-tools { flex-wrap: wrap; row-gap: var(--space-2); }
/* a run on its way (app.js start): the title and the row of controls only,
   the rest drawn in one go when the run is in. Coming in piece by piece - the
   strategy's words, the overview, the empty table going - it moved the page
   under the reader by some 800 px */
#chart-panel.waiting > :not(#chart-head):not(#chart-tools), #chart-panel.waiting ~ #trades-panel { display: none; }
/* the disclosure triangle: a <summary> laid out as flex loses the marker the
   browser would draw, so it is drawn again - with borders, since the font has
   no triangle of its own */
#equity-head, #drawdown-head, #heat-head, #levels-head, #curve-head, #report-head { cursor: pointer; list-style: none; }
#equity-head::before, #drawdown-head::before, #heat-head::before, #levels-head::before, #curve-head::before, #report-head::before {
  content: "";
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-top: 5px solid currentColor;
  color: var(--text-3);
}
#equity-box:not([open]) #equity-head::before,
#drawdown-box:not([open]) #drawdown-head::before,
#heat-box:not([open]) #heat-head::before,
#curve-box:not([open]) #curve-head::before,
#levels-box:not([open]) #levels-head::before,
#report-box:not([open]) #report-head::before { transform: rotate(-90deg); }
#equity-head::-webkit-details-marker,
#drawdown-head::-webkit-details-marker,
#heat-head::-webkit-details-marker,
#curve-head::-webkit-details-marker,
#levels-head::-webkit-details-marker,
#report-head::-webkit-details-marker { display: none; }
#chart-title, #equity-title, #drawdown-title, #heat-title, #levels-title, #curve-title, #report-title { color: var(--text); }
/* the curve is not hovered but it is clicked: a click on it goes to the trade
   that made that step */
#equity { cursor: pointer; }
#equity-note, #drawdown-note, #heat-note, #levels-note, #curve-note { color: var(--text-3); font-size: var(--fs-small); }
/* the heatmap (drawHeat in app.js): a cell per stretch of the week, of the
   month or of the year, its colour a step of the gain or loss token mixed with
   --bg (analysis.js heatTint), set on the cell; an empty cell has no fill, it is
   the panel. The events' corner and the hatch of a thin cell are two layers of
   background-image, each cell's own --corner and --hatch */
#heat-controls { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 8px 16px; margin-bottom: var(--space-3); }
#heat-wrap { overflow-x: auto; }
#heat { border-collapse: separate; border-spacing: 2px; font-family: var(--font-mono); font-size: var(--fs-label); }
#heat th { padding: 0 6px; color: var(--text-3); font-weight: normal; text-align: center; white-space: nowrap; }
#heat tbody th { text-align: right; }
#heat-panel { --heat-hatch: repeating-linear-gradient(45deg, color-mix(in srgb, var(--text-3) 45%, transparent) 0 1px, transparent 1px 6px); }
#heat td { --corner: none; --hatch: none; min-width: 46px; height: 22px; padding: 0 4px; text-align: center; white-space: nowrap;
  color: var(--text); background-image: var(--corner), var(--hatch); border-radius: 3px; cursor: default; }
#heat td .heat-bar { display: block; height: 5px; margin: 2px 0; border-radius: 2px; }
#heat td .heat-bar.ok { background: var(--up); }
#heat td .heat-bar.ko { background: var(--down); }
/* nothing to hover on either of the two panels below the chart */
#levels-chart, #curve-chart { cursor: default; }
/* the corner where the calendar's events fell: ink a high one, grey medium only - not the loss's red */
#heat td.news { --corner: linear-gradient(225deg, var(--text) 7px, transparent 7px); }
#heat td.news.medium { --corner: linear-gradient(225deg, var(--text-3) 7px, transparent 7px); }
/* too few trades to judge (HEAT_MIN): hatched over its colour, its text in --text, which every step
   keeps at 4.5:1; a cell a click cuts, and one cut: the skip rule's */
#heat td.thin { --hatch: var(--heat-hatch); }
#heat td.cuttable { cursor: pointer; }
#heat td.cut { outline: 2px solid var(--text); outline-offset: -2px; text-decoration: line-through; }
#heat-hint, #heat-cut .hint { margin: 0 0 var(--space-2); color: var(--text-3); font-size: var(--fs-small); }
/* the scale under it (drawHeatLegend): the steps a side, the extreme's value at each end */
#heat-legend { display: flex; flex-wrap: wrap; align-items: center; gap: 2px; margin: var(--space-2) 0 0;
  color: var(--text-3); font-size: var(--fs-small); }
#heat-legend .heat-swatch { width: 14px; height: 14px; border-radius: 3px; }
#heat-legend .heat-swatch.thin { background-image: var(--heat-hatch); }
#heat-legend .heat-centre { padding: 0 var(--space-1); border-radius: 3px; background: var(--bg); color: var(--text); }
#heat-legend .heat-thin-key { display: inline-flex; align-items: center; margin-left: var(--space-3); }
#heat-legend .heat-words { margin: 0 var(--space-1); font-family: var(--font-mono); }
#heat-cut { margin-top: var(--space-3); }
#heat-cut p { margin: 0 0 var(--space-2); }
#heat-cut-verdict.good { color: var(--up); }
#heat-cut-verdict.bad { color: var(--down); }
/* a line of its own kept even empty: the cursor going on and off the chart
   fills and empties it, and the chart under it would jump */
#chart-zoom { min-height: 1.5em; margin-bottom: 4px; color: var(--entry); }
/* the bar under the cursor (app.js barReadout): each value after its name, in ink, not the trade's blue */
#chart-zoom .v { color: var(--text); font-family: var(--font-mono); }
#chart-zoom .k { margin-left: .6em; color: var(--text-3); }
/* its calendar events (barEvents): a card over the chart, a row an event, on the side away from the cursor */
#bar-events { position: absolute; top: 8px; z-index: 2; display: grid; grid-template-columns: repeat(6, auto);
  gap: 2px 10px; align-items: baseline; max-width: min(60%, 640px); padding: 6px 10px;
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius-s);
  font-size: var(--fs-small); pointer-events: none; }
#bar-events .when, #bar-events .value, #bar-events .forecast { font-family: var(--font-mono); white-space: nowrap; }
#bar-events .who { font-weight: 600; }
#bar-events .impact { color: var(--text-3); }
#bar-events .impact.high { color: var(--text); font-weight: 600; }
#bar-events .what { min-width: 0; }
#bar-events .forecast { color: var(--text-3); }
#bar-events[hidden] { display: none; }
/* the buttons sit together at the right end; only the first one needs the
   push, and 'reset' is display:none while it is hidden rather than a gap */
#chart-tools button:first-of-type { margin-left: auto; }
/* what the strategy says it does: the full width of the panel, with room
   around it so it reads as a paragraph and not as another readout */
#chart-about {
  width: 100%;
  box-sizing: border-box;
  margin: 0 0 var(--space-3);
  padding: 8px var(--space-3);
  color: var(--text-2);
  line-height: var(--lh);
}
/* the trades a bar hides the end of: a paragraph of sentences, not the banner's row */
#bar-note { display: block; margin: 0 0 var(--space-3); }
#bar-note[hidden] { display: none; }
/* what can close the run's trades (renderExitNote): a state to look at, in --warn and not the loss red */
#exit-note { margin: 0 0 var(--space-3); padding: 8px 12px; border-left: 3px solid var(--warn); border-radius: 0 var(--radius-s) var(--radius-s) 0;
  background: var(--raised); color: var(--text); font-size: var(--fs-small); }
#exit-note[hidden] { display: none; }
#exit-note > div + div { margin-top: var(--space-3); }
/* a button a trade, scrolled past three rows */
#exit-note .exit-trades { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-2); max-height: 7.5rem; overflow-y: auto; }
#exit-note .exit-trades button { font-family: var(--font-mono); font-size: var(--fs-small); }
.fact.exits dd { font-family: var(--font-sans); color: var(--text-2); }
.fact.exits.bare dd { color: var(--warn); }
/* a phone: three lines of it, so the chart is on the first screen; a tap or
   enter opens it all and closes it again (app.js) */
@media (max-width: 640px) {
  #chart-about:not(.open):not([hidden]) { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden; }
  #chart-about { cursor: pointer; }
}
/* DefunctumEst: #journal-link's own min-height, replaced by .tone (piano-restyle fase 14) */
/* a pressed toggle, so "are the levels on" is answerable without looking at
   the chart it is a question about. Off is the labels' colour and a dashed
   border, not faded: faded text falls under 4.5:1 and reads as disabled */
#levels[aria-pressed="false"], #slope[aria-pressed="false"] { color: var(--text-3); border-style: dashed; }

#slope-note { color: var(--text-3); }
#calendar-box, #mcp-news-box { margin-top: 14px; padding-top: var(--space-3); border-top: 1px solid var(--line); }
/* what the calendar holds, the thing this box is read for: in the text's
   colour and the figures' mono, the labels dimmer, the missing years loud */
#calendar-state { margin: 4px 0 var(--space-2); }
#calendar-state table { width: auto; }
#calendar-state th { padding-right: var(--space-4); }
#calendar-state td { font-family: var(--font-mono); font-size: var(--fs-small); white-space: normal; }
#calendar-state td .note { font-family: var(--font-sans); }
#calendar-state tr.warn th, #calendar-state tr.warn td { color: var(--warn); }
#calendar-state tr.warn th::before { content: "\26A0\FE0E  "; }
#calendar-ask { margin: 0 0 var(--space-3); }
#mcp-how { color: var(--text-2); margin: 0 0 8px; padding-left: 20px; line-height: 1.6; }
#mcp-state, #mcp-note, #library-note { color: var(--text-3); margin: 4px 0 var(--space-2); }
#mcp-note, #library-note { white-space: pre-line; }
/* settings → server → GitHub and AI provider: the token or the AI kept, in sight, or that there is none
   (piano-restyle fase 16, issue #25); `form` is flex, so the form hidden needs its own none */
#github-held, #ai-held { display: grid; gap: var(--space-3); max-width: 640px; box-sizing: border-box; margin-block: var(--space-3);
  padding: var(--space-3) var(--space-4); border: 1px solid var(--line); border-radius: var(--radius-m); background: var(--bg); }
#github-held[hidden], #github-held [hidden], #github-form[hidden],
#ai-held[hidden], #ai-held [hidden], #ai-form[hidden] { display: none; }
#github-held p, #ai-held p { margin: 0; }
#github-head, #ai-head { font-size: var(--fs-title); font-weight: 600; }
#github-held.missing #github-head, #ai-held.missing #ai-head { color: var(--warn); }
#github-facts, #ai-facts { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: var(--space-1) var(--space-4); margin: 0;
  font-size: var(--fs-small); }
#github-facts dt, #ai-facts dt { color: var(--text-3); }
#github-facts dd, #ai-facts dd { margin: 0; font-family: var(--font-mono); overflow-wrap: anywhere; }
#github-private { font-family: var(--font-sans); }
#github-private.warn { color: var(--warn); }
#github-actions, #ai-actions { display: flex; flex-wrap: wrap; gap: var(--space-3); }
#mcp-how code, #mcp-token code { overflow-wrap: anywhere; }
/* the address a connector is given: the one thing to copy, so it stands out */
#mcp-address { display: flex; flex-wrap: wrap; gap: var(--space-2) 12px; align-items: center; margin: var(--space-3) 0 12px;
  padding: var(--space-3) 12px; background: var(--raised); border: 1px solid var(--accent); border-left-width: 4px; border-radius: var(--radius-s); }
#mcp-address span { color: var(--text-3); font-size: var(--fs-label); text-transform: uppercase; letter-spacing: .04em; flex-basis: 100%; }
#mcp-address code { font-family: var(--font-mono); font-size: var(--fs-title); font-weight: 600; color: var(--accent-text);
  overflow-wrap: anywhere; user-select: all; flex: 1 1 16em; }
#mcp-actions, #mcp-files, #mcp-token { display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: center; margin: 8px 0; }
#mcp-key-new { display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: flex-end; margin: 8px 0; }
#mcp-keys code { overflow-wrap: anywhere; font-size: var(--fs-small); }
#mcp-keys td:last-child { white-space: nowrap; }
#mcp-keys[hidden] { display: none; }
/* the buttons on the line of the file box, not on the middle of its label too */
#mcp-files { align-items: flex-end; }
#mcp-token[hidden], #mcp-strategies[hidden], #mcp-requests[hidden], #mcp-tests-table[hidden], #mcp-walks-table[hidden], #mcp-news[hidden] { display: none; }
#mcp-strategies td:last-child { white-space: nowrap; }
/* a strategy is one line, its description cut to the room left; a double
   click opens the row on all of it */
#mcp-strategies td:nth-child(5) { max-width: 0; width: 100%; overflow: hidden; text-overflow: ellipsis; }
#mcp-strategies tr.open td:nth-child(5) { white-space: normal; }
#mcp-rows td { cursor: default; }
#source-actions { display: contents; }
#mcp-strategies td:last-child button + button { margin-left: 6px; }
/* up to 1000 px - a phone, or a tablet with the side tabs beside it, where
   the table ran 950 px wide: each strategy a block - name and state, its
   description's line under them, then the buttons - and the code's dialog
   puts its buttons under the title */
@media (max-width: 1000px) {
  #mcp-strategies thead { display: none; }
  #mcp-rows tr { display: grid; grid-template-columns: minmax(0, 1fr) auto; border-bottom: 1px solid var(--line); padding: 4px 0; }
  #mcp-rows td { border: 0; }
  #mcp-rows td:nth-child(3), #mcp-rows td:nth-child(4) { display: none; }
  #mcp-rows td:nth-child(5), #mcp-rows td:last-child { grid-column: 1 / -1; }
  #mcp-rows td:nth-child(5) { max-width: none; width: auto; }
  #mcp-rows td:last-child { white-space: normal; }
  #mcp-rows td:last-child button { white-space: nowrap; margin: 2px 6px 2px 0; }
  #source-dialog .dialog-head { flex-wrap: wrap; row-gap: 8px; }
}
/* the indicators, under the strategies and laid out as they are */
#mcp-indicators-box { margin-top: 14px; padding-top: var(--space-3); border-top: 1px solid var(--line); }
#indicators-hint { color: var(--text-3); margin: 4px 0 8px; max-width: 110ch; }
#mcp-indicator-files { display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: flex-end; margin: 8px 0; }
#mcp-indicators[hidden] { display: none; }
#mcp-indicators td:last-child { white-space: nowrap; }
#mcp-indicators td:nth-child(5) { max-width: 0; width: 100%; overflow: hidden; text-overflow: ellipsis; }
#mcp-indicators tr.open td:nth-child(5) { white-space: normal; }
#mcp-indicator-rows td { cursor: default; }
#mcp-indicators td:last-child button + button { margin-left: 6px; }
@media (max-width: 1000px) {
  #mcp-indicators thead { display: none; }
  #mcp-indicator-rows tr { display: grid; grid-template-columns: minmax(0, 1fr) auto; border-bottom: 1px solid var(--line); padding: 4px 0; }
  #mcp-indicator-rows td { border: 0; }
  #mcp-indicator-rows td:nth-child(3), #mcp-indicator-rows td:nth-child(4) { display: none; }
  #mcp-indicator-rows td:nth-child(5), #mcp-indicator-rows td:last-child { grid-column: 1 / -1; }
  #mcp-indicator-rows td:nth-child(5) { max-width: none; width: auto; }
  #mcp-indicator-rows td:last-child { white-space: normal; }
  #mcp-indicator-rows td:last-child button { white-space: nowrap; margin: 2px 6px 2px 0; }
}
#source-dialog { width: min(980px, calc(100vw - 32px)); max-height: calc(100vh - 48px); }
#mcp-source { margin: 0; overflow: auto; font-family: var(--font-mono); font-size: var(--fs-small); background: var(--raised); padding: 8px; border-radius: var(--radius-s); }
/* the buttons sit on the line of the boxes, under the names of the ones that
   have one */
#calendar-actions, #market-actions, .market-row { display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: flex-end; }
#server-state.bad { color: var(--live); font-weight: 600; }
#quality-panel .market-row { margin-top: var(--space-3); }
#data-box[hidden] { display: none; }
#quality-panel [hidden] { display: none; }
#record-feeds { width: min(28em, 80vw); font-family: var(--font-mono); }
#archive-state, #q-note { color: var(--text-3); font-size: var(--fs-small); overflow-wrap: anywhere; }
#q-numbers { margin: var(--space-3) 0 0; padding: 8px; font-family: var(--font-mono); font-size: var(--fs-small); background: var(--raised); border-radius: var(--radius-s); white-space: pre-wrap; }
#q-days { display: block; width: 100%; height: 140px; margin-top: 8px; }
#server-note:empty, #trade-box[hidden], #trade-table[hidden] { display: none; }
#trade-url { width: min(30em, 80vw); }
/* the roles' boxes, and the AI's uses as they are (#ai-uses) */
#roles-box, #ai-uses { display: flex; flex-direction: column; gap: var(--space-2); margin: 12px 0;
  border: 1px solid var(--line); border-radius: var(--radius-s); padding: var(--space-2) 12px 12px; }
#roles-box legend, #ai-uses legend { color: var(--text-3); padding: 0 4px; }
#roles-box label, #ai-uses label { flex-direction: row; align-items: baseline; gap: 8px; text-transform: none;
  letter-spacing: normal; font-size: inherit; cursor: pointer; }
#roles-box button { align-self: flex-start; }
#trade-table td:last-child { white-space: nowrap; }
#backup-note:empty { display: none; }
#storage-box p.dim, #storage-box .storage-steps { margin: 8px 0; color: var(--text-3); font-size: var(--fs-small); }
#storage-s3[hidden], #storage-drive[hidden], #storage-google[hidden], #storage-state:empty { display: none; }
#storage-box .market-row { margin: 8px 0; }
#drive-command { overflow-wrap: anywhere; font-size: var(--fs-small); max-width: min(60em, 90vw); }
#drive-token-box { flex: 1 1 28em; }
#drive-token { width: 100%; font-family: var(--font-mono, monospace); font-size: var(--fs-small); }
#s3-endpoint, #drive-client-id { width: min(26em, 80vw); }
#storage-sets-box[hidden] { display: none; }
#storage-sets-box { margin-top: 14px; overflow-x: auto; }
#storage-sets-box h4 { margin: 0; align-self: center; }
#storage-sets { font-size: var(--fs-small); }
#storage-sets th, #storage-sets td { padding: 3px 8px; border-bottom: 1px solid var(--line); text-align: left; }
#storage-sets th { color: var(--text-3); font-weight: normal; }
#storage-sets .num { text-align: right; }
#storage-sets td:last-child { white-space: nowrap; }
#market-box { margin-bottom: 12px; padding-bottom: var(--space-3); border-bottom: 1px solid var(--line); }
#market-box .market-row { margin-top: var(--space-3); }
#market-box [hidden] { display: none; }
#market-state { margin-bottom: var(--space-2); overflow-wrap: anywhere; }
#market-box p.dim, #trade-box p.dim { margin: var(--space-3) 0 0; color: var(--text-3); font-size: var(--fs-small); }
#market-writer-box { flex-direction: row; align-items: center; gap: var(--space-2); }
#market-dir, #market-upstream { width: min(36em, 80vw); }
#market-candles-every, #market-calendar-every { width: 6em; }
#market-runs, #update-log { margin: var(--space-3) 0 0; padding: 8px; font-family: var(--font-mono); font-size: var(--fs-small); background: var(--raised); border-radius: var(--radius-s); white-space: pre-wrap; }
/* the log away from the cancel button over it (issue #7) */
#update-log-box { margin-top: var(--space-3); }
#data-actions[hidden], #calendar-ask[hidden], #calendar-actions[hidden] { display: none; }
#calendar-format, #draft-format { width: min(720px, calc(100vw - 32px)); max-height: calc(100vh - 48px); }
#calendar-format pre, #draft-format pre { margin: 0 0 12px; padding: 8px; font-family: var(--font-mono); overflow-x: auto; background: var(--raised); border-radius: var(--radius-s); font-size: var(--fs-small); }
#calendar-format dl, #draft-format dl { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: var(--space-2) 14px; margin: 0 0 12px; }
#calendar-format dt, #draft-format dt { font-family: var(--font-mono); color: var(--text); }
#calendar-format dd, #draft-format dd { margin: 0; color: var(--text-2); }
#calendar-format p, #draft-format p { margin: 0 0 8px; color: var(--text-2); line-height: 1.5; }

#detail-box { color: var(--text-3); display: inline-flex; gap: 4px; align-items: flex-start; }
#detail-box[hidden] { display: none; }

canvas {
  width: 100%;
  display: block;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-s);
  cursor: crosshair;
}
/* the price chart is draggable, and a crosshair does not say so. app.js
   swaps this for 'grabbing' while a drag is running. */
#chart { cursor: grab; }
/* the layer app.js and livechart.js draw the crosshair, a measure and a zoom
   box on: over the chart, its size, letting the pointer through to it */
.chart-stack { position: relative; }
.chart-stack canvas.over { position: absolute; inset: 0; pointer-events: none; background: transparent; border-color: transparent; }
/* the grip under a candle chart that makes it taller or shorter (chartGrip in menu.js) */
.grip { height: 14px; display: flex; align-items: center; justify-content: center; cursor: row-resize;
  background: var(--raised); border: 1px solid var(--line); border-top: 0; border-radius: 0 0 var(--radius-s) var(--radius-s); }
.grip::before { content: ''; width: 64px; height: 4px; border-radius: 2px; background: var(--text-3); }
.grip:hover, .grip:focus-visible { background: var(--line); }
.grip:hover::before, .grip:focus-visible::before { background: var(--text-2); }
/* under the run chart: the calendar's events and the selected trade (app.js) */
#chart-under { margin-top: 8px; }
#events-line { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) 12px; margin-bottom: var(--space-2); }
#events-note { color: var(--text-3); font-size: var(--fs-small); }
/* the selected trade's card (tradeCard in app.js): its figures under their
   names, in the colours of their marks on the chart - entry, exit, stop,
   target - and of the table's side, outcome and P&L. Every colour comes with
   its word, as everywhere on this page */
#chart-trade { display: grid; gap: var(--space-3); margin: 0 0 var(--space-2); padding: var(--space-3) 14px; background: var(--raised);
  border: 1px solid var(--line); border-left: 3px solid var(--entry); border-radius: var(--radius-s); }
#chart-trade[hidden] { display: none; }
.trade-head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) 14px; }
.trade-n { font-size: var(--fs-title); font-weight: 600; color: var(--text); }
.trade-head .pl { font-family: var(--font-mono); font-weight: 600; }
/* inside the bar (issue #13): at the end of the head, clear of the figures */
.trade-head .trade-inside { margin-left: auto; }
.trade-held { color: var(--text-2); font-size: var(--fs-small); }
.trade-id { font-family: var(--font-mono); font-size: var(--fs-small); color: var(--text-3); overflow-wrap: anywhere; }
.trade-facts { display: flex; flex-wrap: wrap; gap: 8px 24px; margin: 0; }
.fact { display: grid; gap: 2px; }
.fact dt, .trade-label { color: var(--text-3); font-size: var(--fs-label); text-transform: uppercase; letter-spacing: .04em; }
.fact dd { margin: 0; font-family: var(--font-mono); font-size: var(--fs-small); color: var(--text); }
.fact.entry dd { color: var(--entry); }
.fact.exit dd { color: var(--mark-exit); }
.fact.sl dd { color: var(--down); }
.fact.tp dd { color: var(--up); }
.trade-events { display: grid; gap: 4px; font-size: var(--fs-small); color: var(--text-2); }
/* the calendar from the signal to the exit (tradeCard events): a row an event, in time, scrolled past a dozen;
   the impact a word as on the chart's card (#bar-events), not the loss red (issue #14) */
.trade-calendar { max-height: 21rem; overflow: auto; }
.trade-calendar table { width: 100%; border-collapse: collapse; }
.trade-calendar th { position: sticky; top: 0; padding: 2px 12px 4px 0; background: var(--raised); text-align: left; font-weight: 400;
  color: var(--text-3); font-size: var(--fs-label); text-transform: uppercase; letter-spacing: .04em; white-space: nowrap; }
.trade-calendar td { padding: 3px 12px 3px 0; border-top: 1px solid var(--line); vertical-align: baseline; }
.trade-calendar td:first-child, .trade-calendar td:nth-child(n+5) { font-family: var(--font-mono); white-space: nowrap; }
.trade-calendar th:nth-child(n+5), .trade-calendar td:nth-child(n+5) { text-align: right; }
.trade-calendar td:nth-child(2) { font-weight: 600; }
.trade-calendar td:nth-child(3) { color: var(--text-3); }
.trade-calendar tr.high td:nth-child(3) { color: var(--text); font-weight: 600; }
.trade-calendar tr.before td { color: var(--text-3); }
.trade-calendar tr.last td { color: var(--text); font-weight: 600; }
.event-tag { padding: 0 6px; border: 1px solid var(--border); border-radius: var(--radius-pill); font-size: var(--fs-label);
  font-weight: 400; color: var(--text-3); white-space: nowrap; }
@media (max-width: 640px) { .trade-calendar th:last-child, .trade-calendar td:last-child { display: none; } }
.trade-quiet { color: var(--text-3); }
/* the whole run under the chart (drawNav in app.js) */
#chart-nav { margin-top: 4px; cursor: pointer; }
#chart-nav[hidden], #ranges[hidden] { display: none; }
#ranges, #chart-ranges { display: inline-flex; gap: 4px; }
#chart-tools #ranges button, #chart-ranges button { margin-left: 0; padding: 0 8px; }
#chart-keys { cursor: help; text-decoration: underline dotted; }

/* ------------------------------------------------------------ legend */

.legend { display: flex; flex-wrap: wrap; gap: 14px; margin: var(--space-2) 0 0; color: var(--text-2); font-size: var(--fs-small); }
.k::before {
  content: "";
  display: inline-block;
  width: 14px;
  height: 0;
  margin-right: 6px;
  vertical-align: middle;
  border-top: 2px solid currentColor;
}
/* the entry arrows, which are solid marks rather than levels: the same
   triangle as on the chart, up for a buy and down for a sell */
.k.buy { color: var(--up); }
.k.sell { color: var(--down); }
.k.buy::before, .k.sell::before {
  width: 0;
  border-top: 0;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
}
.k.buy::before { border-bottom: 9px solid currentColor; }
.k.sell::before { border-top: 9px solid currentColor; }
/* one of many - a strategy's curves, a mix's runs, the live feeds: told apart
   by the dash, drawn by the same dashSample() as the line (menu.js) */
.k.series { color: var(--text-3); }
.k.series::before { display: none; }
.k.series.mix-total { color: var(--text); }
.k.series.alarm-key { color: var(--down); }
.k .dash { margin-right: 6px; vertical-align: middle; }
.k.entry { color: var(--entry); }
.k.exit { color: var(--mark-exit); }
.k.exit::before { border-top-width: 1px; }
.k.tp { color: var(--up); }
.k.sl { color: var(--down); }
.k.trail { color: var(--mark-trail); }
.k.tp::before, .k.sl::before { border-top-style: dashed; }
.k.trail::before { border-top-style: dotted; }
/* the swings: neutral, a resistance dashed and a support dotted, as on the
   chart - green and red are taken */
.k.support, .k.resistance { color: var(--text-3); }
.k.resistance::before { border-top-style: dashed; }
.k.support::before { border-top-style: dotted; }
/* the entry-to-exit arrow, which is solid and thicker than a level */
.k.won { color: var(--up); }
.k.lost { color: var(--down); }
.k.won::before, .k.lost::before { border-top-width: 3px; }
/* the box around the bars the entry rule read */
.k.setup { color: var(--text); }
.k.setup::before { border-top-style: dashed; }
/* the slope shading's two sides */
.k.up { color: var(--up); }
.k.down { color: var(--down); }
/* the legend folds away; the help behind its (?) is a dialog */
#legend-box { margin: var(--space-2) 0 0; color: var(--text-3); }
#legend-box > summary { cursor: pointer; width: max-content; }
#help-open { height: var(--target-min); min-width: var(--target-min); padding: 0 7px; border-radius: var(--radius-pill); line-height: 22px; }
#help-dialog { width: min(640px, calc(100vw - 32px)); }
#inside-dialog { width: min(860px, calc(100vw - 32px)); }
#inside-note { margin: var(--space-3) 0 0; }
#help-list { margin: 0; padding-left: 18px; line-height: 1.5; }
#help-list li + li { margin-top: var(--space-2); }

/* ------------------------------------------------------------ report */

#trade-pager { display: flex; align-items: center; justify-content: center; gap: 12px; margin-top: 8px; color: var(--text-3); }
#report-stats { display: flex; flex-wrap: wrap; gap: var(--space-6); }
/* the analysis's table is wider than a phone */
#report-panel { overflow-x: auto; }
#report, #counts { display: flex; flex-wrap: wrap; gap: var(--space-5); }

.stat { display: flex; flex-direction: column; gap: 2px; }
.stat .label { font-size: var(--fs-label); text-transform: uppercase; letter-spacing: var(--tracking-label); color: var(--text-3); }
/* the first row - trades, won, lost, net... - is what the run is judged on;
   the counts under it are how it got there */
.stat .value { font-size: var(--fs-stat); font-weight: 500; }
#report .stat .value { font-size: var(--fs-kpi); }
.stat .value.good { color: var(--up); }
.stat .value.bad { color: var(--down); }

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

table { width: 100%; border-collapse: collapse; }
thead th {
  position: sticky;
  top: 0;
  background: var(--panel);
  text-align: left;
  font-size: var(--fs-label);
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  color: var(--text-3);
  font-weight: 500;
  padding: 6px 8px;
  border-bottom: 1px solid var(--border);
}
th.num, td.num { text-align: right; }
tbody td { padding: 5px 8px; border-bottom: 1px solid var(--line); white-space: nowrap; }
/* a control in a row stays the row's size */
td button, td input:not([type="checkbox"]) { height: auto; padding: 1px 6px; font-size: var(--fs-small); }
/* but a button is at least 24 px tall (WCAG 2.5.8), and the margin hands the
   extra back to the cell's padding: the row keeps its height */
td button { min-height: var(--target-min); margin-block: -4px; }
tbody tr { cursor: pointer; }
tbody tr:hover { background: var(--raised); }
tbody tr.selected { background: var(--row-selected); }
tbody tr.selected td:first-child { box-shadow: inset 3px 0 0 var(--entry); }
/* on it the green and the red fall under 4.5:1 (piano-restyle N4): the text's colour, ✓ ✗ ▲ ▼ and the sign still say it */
:is(#sim-rows, #kpi-rows, #mix-rows, #runs-rows) tr.selected td:is(.good, .bad) { color: var(--text); }
tbody tr.empty td, tbody tr.empty { cursor: default; color: var(--text-3); }
tbody tr.empty:hover { background: none; }

/* the side, in its colour and with its triangle: a short in profit has a red
   side and a green P&L, and the triangle is what says which is which */
.side.long { color: var(--up); }
.side.short { color: var(--down); }
.side.long::before, .side.short::before {
  content: "";
  display: inline-block;
  margin-right: 5px;
  vertical-align: 1px;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
}
.side.long::before { border-bottom: 8px solid currentColor; }
.side.short::before { border-top: 8px solid currentColor; }
.outcome {
  font-size: var(--fs-label);
  border: 1px solid currentColor;
}
.outcome.tp { color: var(--up); }
.outcome.sl { color: var(--down); }
/* an exit this page has no opinion about: it closed, on the strategy's own
   rule, and the badge says which rather than pretending to grade it */
.outcome.other { color: var(--text-3); }
.outcome.open { color: var(--text-3); }
.pl.good { color: var(--up); }
.pl.bad { color: var(--down); }

/* ------------------------------------------------------------ dialogs */

/* the dialogs; the settings page's panels are plain sections, full width */
dialog {
  background: var(--panel);
  color: var(--text);
  border: 1px solid var(--line);
  border-radius: var(--radius-m);
  padding: 12px 16px;
  width: min(760px, calc(100vw - 32px));
}
/* a dialog: open, it is a column - the head stays put and only the body under
   it scrolls, so the scrollbar starts under the head. No shadow: the backdrop
   is what sets it off the page (DESIGN.md § 5) */
dialog { padding: 0; overflow: hidden; }
dialog[open] { display: flex; flex-direction: column; }
dialog::backdrop { background: var(--backdrop); }

/* dialog: foglio e testata "titolo con contesto" (DESIGN.md § 6, Dialog). Was:
   a band of another colour over the table, a round close with a fill of its
   own, and a <strong> for a title that a screen reader did not announce; now
   the sheet's own surface, an h2 the dialog is labelled by, how many there
   are and what to do with them under it */
dialog.sheet { box-sizing: border-box; padding: 0; border: 1px solid var(--line); border-radius: var(--radius-m); background: var(--panel); color: var(--text); overflow: hidden; }
dialog.sheet[open] { display: flex; flex-direction: column; }
dialog.sheet::backdrop { background: var(--backdrop); } /* token in tokens.css: nessun rgba in app.css */
/* nowrap: every form here wraps (the controls bar), and a head that wrapped
   would drop its close under the title instead of cutting the help line */
.dialog-head { flex: none; display: flex; flex-wrap: nowrap; align-items: center; gap: 16px; margin: 0; padding: 13px 12px 13px 20px; border-bottom: 1px solid var(--line); }
.dialog-heading { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.dialog-title { display: flex; align-items: center; gap: 8px; margin: 0; min-width: 0; white-space: nowrap; } /* font e misura: aggiunta "font dei titoli" */
.dialog-count { flex: none; font: 500 11px/18px var(--font-mono); color: var(--text-2); border: 1px solid var(--line); }
.dialog-count:empty { display: none; }
.dialog-sub { margin: 0; font-size: var(--fs-small); color: var(--text-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dialog-sub.mono { font-family: var(--font-mono); }
.dialog-sub:empty { display: none; }
.dialog-tools { margin-left: auto; flex: none; display: flex; align-items: center; gap: 8px; }
.kbd { font: 500 11px/18px var(--font-mono); color: var(--text-3); padding: 0 5px; border: 1px solid var(--line); border-bottom-width: 2px; border-radius: var(--radius-xs); }
.dialog-close { flex: none; width: var(--control-h); height: var(--control-h); display: grid; place-items: center; padding: 0; border: 0; border-radius: var(--radius-s); background: transparent; color: var(--text-2); cursor: pointer; transition: background-color .12s, color .12s; }
.dialog-close:hover { background: var(--line); color: var(--text); }
.dialog-close:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.dialog-body { min-height: 0; flex: 1; overflow: auto; padding: 16px 20px 20px; }
.dialog-body.flush { padding: 0; }
.dialog-body.flush th:first-child, .dialog-body.flush td:first-child { padding-left: 20px; }
/* the question asked instead of confirm() and prompt(), askUser() in
   menu.js: the sheet and its head like every dialog, the answers at the foot
   on the right - cancel, then the yes, the dialog's one main action */
#ask-dialog { width: min(520px, calc(100vw - 32px)); }
/* asked without a modal, so the menu stays in reach (sim.js): in the middle of
   the screen all the same, over a page that is locked and says so */
#ask-dialog[open]:not(:modal) { position: fixed; inset: 0; margin: auto; height: fit-content; z-index: 100; }
[inert] { opacity: .45; }
/* a column, not the forms' wrapping row */
#ask-dialog form.dialog-body { display: block; }
#ask-text { white-space: pre-line; margin: 0 0 var(--space-4); }
#ask-input { box-sizing: border-box; width: 100%; margin: 0 0 var(--space-4); }
#ask-input[hidden] { display: none; }
.dialog-actions { display: flex; justify-content: flex-end; gap: var(--space-2); }
/* what the stores hold, a table like the import sets under it; on a phone
   it scrolls in its own box, so no date breaks in two */
#data-loaded-box { margin-bottom: var(--space-3); overflow-x: auto; }
#data-loaded { width: auto; }
#data-loaded td.built { white-space: normal; }
#data-loaded td.num { font-size: var(--fs-small); }
#data-loaded td.built, #data-dir { color: var(--text-3); }
#data-dir { margin-bottom: var(--space-2); overflow-wrap: anywhere; font-size: var(--fs-small); }
#data-files, #mcp-strategies, #mcp-requests, #mcp-tests-table, #mcp-walks-table, #mcp-news { margin-bottom: var(--space-3); }
#data-files th, #data-files td, #data-loaded th, #data-loaded td, #calendar-state th, #calendar-state td,
#mcp-strategies th, #mcp-strategies td, #mcp-requests th, #mcp-requests td, #mcp-tests-table th, #mcp-tests-table td,
#mcp-walks-table th, #mcp-walks-table td,
#mcp-news th, #mcp-news td { text-align: left; padding: 3px 6px; border-bottom: 1px solid var(--line); }
#data-files th, #data-loaded th, #calendar-state th, #mcp-strategies th, #mcp-requests th, #mcp-tests-table th, #mcp-walks-table th, #mcp-news th { color: var(--text-3); font-weight: normal; }
#data-loaded .num { text-align: right; }
/* on a phone a set's name says its instrument and timeframe already: the
   room goes to the name, which would break in five lines otherwise */
@media (max-width: 640px) {
  #data-files :is(th, td):is(:nth-child(3), :nth-child(4)) { display: none; }
  /* the stores' table scrolls in its box here: a row stays one line */
  #data-loaded td.built { white-space: nowrap; }
  /* the calendar's facts a label over its value, not a label in four lines */
  #calendar-state :is(table, tbody, tr, th, td) { display: block; }
  #calendar-state th { padding-bottom: 0; border-bottom: 0; }
}
/* a request is read, not scanned: its text wraps */
#mcp-requests td:nth-child(4) { white-space: pre-wrap; min-width: 24em; }
#mcp-requests tbody tr, #mcp-tests-table tbody tr, #mcp-walks-table tbody tr { cursor: default; vertical-align: top; }
#mcp-tests-table td button + button { margin-left: var(--space-2); }
#mcp-tests-table td:nth-child(4), #mcp-walks-table td:nth-child(4) { white-space: normal; }
#mcp-tests { margin-top: var(--space-4); }
/* auto-split's zones, a choice of four: as wide as its words (sim.html #windows-split) */
#windows-split select { width: auto; }
/* a news is one line - its title, what it says, the strategies it names -
   cut to the room left; a double click opens it: the title over the text,
   the strategies wrapping */
#mcp-news td { white-space: nowrap; }
#mcp-news td:nth-child(3), #mcp-news td:nth-child(4) { max-width: 0; overflow: hidden; text-overflow: ellipsis; }
#mcp-news td:nth-child(3) { width: 65%; }
#mcp-news td:nth-child(4) { width: 35%; }
#mcp-news td:nth-child(3) strong { margin-right: .6em; }
#mcp-news tr.open td:nth-child(3) { white-space: pre-wrap; }
#mcp-news tr.open td:nth-child(3) strong { display: block; margin: 0 0 2px; }
#mcp-news tr.open td:nth-child(4) { white-space: normal; }
#mcp-news tbody tr { vertical-align: top; cursor: default; }
#news-hint { color: var(--text-3); margin: 4px 0 8px; max-width: 110ch; }
/* a phone: a news or a request is a block, its cells one under the other */
@media (max-width: 600px) {
  #mcp-news thead, #mcp-requests thead, #mcp-tests-table thead, #mcp-walks-table thead { display: none; }
  #mcp-news tr, #mcp-news td, #mcp-requests tr, #mcp-requests td, #mcp-tests-table tr, #mcp-tests-table td,
  #mcp-walks-table tr, #mcp-walks-table td { display: block; }
  #mcp-news td, #mcp-requests td, #mcp-tests-table td, #mcp-walks-table td { min-width: 0; border: 0; padding: 2px 0; }
  #mcp-news, #mcp-news tbody { display: block; }
  #mcp-news td:nth-child(3), #mcp-news td:nth-child(4) { max-width: none; width: auto; }
  #mcp-news tr, #mcp-requests tr, #mcp-tests-table tr, #mcp-walks-table tr { border-bottom: 1px solid var(--line); padding: var(--space-2) 0; }
}
#data-files td:nth-child(2) { white-space: normal; overflow-wrap: anywhere; }
#data-files td.missing { color: var(--down); }
#data-rows tr { cursor: pointer; }
#data-rows tr:hover td { background: var(--raised); }
#data-progress-box { display: flex; align-items: center; gap: var(--space-3); margin-top: var(--space-3); }
#data-progress-box[hidden] { display: none; }
#data-progress { flex: 1; height: 10px; accent-color: var(--entry); }
#data-progress-text { color: var(--text-3); white-space: nowrap; }
#data-actions { display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-end; }
/* the export's format, folded away under the upload */
#data-format { margin: var(--space-3) 0 0; color: var(--text-2); }
#data-format > summary { cursor: pointer; width: max-content; color: var(--text-3); }
#data-format p { margin: 8px 0 4px; max-width: 110ch; line-height: 1.5; }
#data-format pre { margin: 0; padding: 8px; overflow-x: auto; background: var(--raised); border-radius: var(--radius-s); font-size: var(--fs-small); }
#data-log {
  margin: var(--space-3) 0 0;
  padding: 8px;
  max-height: 40vh;
  overflow: auto;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--radius-s);
  white-space: pre-wrap;
}

/* ------------------------------------------------------------ simulate */

/* the values to try
   on the simulate page: a box of fields on a line of their own */
#grid, #grid-money, #windows {
  display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-end;
  flex-basis: 100%;
  margin: 0;
  border: 1px solid var(--line); border-radius: var(--radius-s); padding: 8px var(--space-3) var(--space-3);
}
#grid legend, #grid-money legend, #windows legend { color: var(--text-3); font-size: var(--fs-label); padding: 0 4px; }
/* a walk-forward's windows (walkforward.js): four dates a line, in place of from and to */
#windows[hidden], #skip-propose[hidden] { display: none; }
/* the calendar (sim.js calendarShow, calendarDraw; piano-restyle phase 11, B): in the form a
   line of what it holds and "edit"; in its dialog a level's grid, a day's name the day's switch
   and a cell a term of the skip rule, in the value picked of its list */
/* a phone: the line wraps, the button under it, and the page never scrolls sideways */
#calendar-field { max-width: 100%; }
#calendar-line { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
#calendar-summary { box-sizing: border-box; display: flex; align-items: center; min-width: min(300px, 100%); min-height: var(--control-h);
  padding: 4px 10px; border: 1px solid var(--border); border-radius: var(--radius-s); background: var(--bg);
  font-size: var(--fs-body); line-height: 1.3; text-transform: none; letter-spacing: 0; color: var(--text); }
#calendar-summary.warn { border-color: var(--warn); color: var(--warn); }
#calendar-help { max-width: 46ch; }
#calendar-dialog { width: min(980px, calc(100vw - 32px)); max-height: calc(100vh - 32px); }
#calendar-main { display: flex; flex-wrap: wrap; align-items: flex-start; gap: var(--space-5); margin-top: var(--space-4); }
/* a phone scrolls the grid sideways; down it is as tall as the grid, a pixel's rounding no scroll bar */
#calendar-panel { max-width: 100%; overflow-x: auto; overflow-y: hidden; }
#calendar-panel[hidden] { display: none; }
#calendar-side { flex: 1 1 280px; display: flex; flex-direction: column; gap: var(--space-3); min-width: 0; }
#calendar-side p { margin: 0; }
.calendar-key { display: flex; align-items: flex-start; gap: 10px; }
.calendar-key strong { font-weight: 500; }
.calendar-swatch { flex: none; box-sizing: border-box; width: 28px; height: 20px; border: 1px solid var(--border); }
/* one block of cells, joined by a line as a sheet's: a row 26px, a cell a switch that fills it,
   a drag over them cuts a rectangle (sim.js calendarDrag) - no text picked up on the way */
#skip-grid { border-collapse: collapse; font: var(--fs-label) var(--font-mono); user-select: none; }
#skip-grid th { padding: 0 4px; border: 0; color: var(--text-3); font-weight: normal; white-space: nowrap; }
#skip-grid thead th { padding: 0 2px 4px; }
#skip-grid tbody th { padding: 1px 6px 1px 0; text-align: right; }
/* a grid of switches, not a table of rows: its own lines, not the tables' rules */
#skip-grid td { padding: 0; border: 1px solid var(--border); }
#skip-grid td button { display: block; width: 100%; min-width: 40px; height: 25px; margin: 0; padding: 0; border: 0; border-radius: 0; background: var(--bg); cursor: pointer; }
#skip-grid td button:not(:disabled):hover { background-color: var(--line); }
#skip-grid td button:focus-visible { outline-offset: -2px; }
/* all on to start, as the days; off - a cell cut, a day's cells - hatched, the same whatever switched
   it off: not an opacity (DESIGN.md § 10.2), not --down, a loss's (DESIGN.md § 3) */
#skip-grid :is(td button, .calendar-day, .calendar-line)[aria-pressed="false"], .calendar-swatch.off {
  background: repeating-linear-gradient(135deg, var(--hatch, var(--border)) 0 2px, transparent 2px 6px); }
#skip-grid td button:disabled { opacity: 1; cursor: default; }
/* quiet at a step that does not vary them: the lines lighter */
#skip-grid td:has(> .step-off) { border-color: var(--line); }
:is(.calendar-day, .calendar-line) { width: 100%; min-width: 40px; height: var(--target-min); padding: 0 4px; border: 1px solid var(--border); border-radius: 3px;
  background: var(--panel); font: 500 var(--fs-label) var(--font-mono); color: var(--text); }
/* a name off - a day, a line all off - hatched as its cells, lighter under its text, and struck through;
   dashed is a step's quiet */
:is(.calendar-day, .calendar-line)[aria-pressed="false"] { --hatch: var(--line); color: var(--text-2); text-decoration: line-through; }
#skip-grid tbody :is(.calendar-day, .calendar-line) { width: auto; min-width: 40px; }
/* the weeks of the month as wide as the widest name, 15–21: five characters */
#skip-grid[data-level="month"] thead .calendar-line { min-width: calc(5ch + 10px); }
/* the part a step does not vary, there and editable but quiet, as the form's (sim.js setStep) */
#calendar-dialog .step-off { border-style: dashed; color: var(--text-3); }
#calendar-values { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-2); }
#calendar-values li { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.calendar-pick { height: 28px; padding: 0 10px; font-size: var(--fs-small); }
.calendar-pick[aria-pressed="true"] { background: var(--row-selected); border-color: var(--entry); color: var(--text); }
.calendar-chip { display: inline-flex; align-items: center; gap: 2px; height: 26px; padding: 0 2px 0 10px; border: 1px solid var(--border);
  border-radius: var(--radius-pill); background: var(--panel); font-size: var(--fs-small); color: var(--text); white-space: nowrap; }
.calendar-chip.warn { border-color: var(--warn); color: var(--warn); }
.calendar-chip button { width: var(--target-min); height: var(--target-min); padding: 0; border: 0; border-radius: var(--radius-pill); background: none; color: var(--text-3); }
.calendar-chip button:hover { color: var(--text); background: var(--line); }
.calendar-none { font-size: var(--fs-small); font-style: italic; color: var(--text-3); }
.calendar-drop { width: 28px; height: 28px; padding: 0; }
.calendar-drop::before { margin-right: 0; }
#calendar-tools { display: flex; flex-wrap: wrap; gap: var(--space-2); }
/* the protocol over the grid: free, step by step or auto, a row of tabs (DESIGN.md § 6), stood up on the rail beside the page */
#steps-box { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 4px var(--space-4); }
#mix-mode button, #auto-stopat button { height: auto; border: 0; background: none; font: 500 13px var(--font-sans); cursor: pointer; }
/* a set run keeps its kind (sim.js rail): both segments shut, its own still lit - not by an opacity (DESIGN.md § 10.2) */
/* a mix too (mix.js renderSteps) */
:is(#sim-mode, #mix-mode) button:disabled { opacity: 1; cursor: default; }
:is(#sim-mode, #mix-mode) button:disabled:not([aria-pressed="true"], [aria-selected="true"]),
  :is(#sim-mode, #mix-mode) button:disabled:not([aria-pressed="true"], [aria-selected="true"]):hover { color: var(--text-3); background: none; box-shadow: none; }
#step-hint { margin: 0 0 8px; }
#step-hint a { display: inline-block; min-height: var(--target-min); line-height: var(--target-min); }
/* the step lit (sim.js rail): what it keeps fixed and varies, beside the fields it lights */
#step-card { flex-basis: 100%; margin: 0 0 8px; font-size: 13px; }
#step-card[hidden], .set-folded #step-card { display: none; }
/* a step lit: the fields of the other steps spent - there, and editable, but
   quiet (DESIGN.md § 10.2: a colour and a dashed border, not an opacity) */
#sim-controls .step-off, #sim-controls .step-off .field-label, #sim-controls .step-off .param-help { color: var(--text-3); }
#sim-controls .step-off input, #sim-controls .step-off select, #sim-controls .step-off .yn, #sim-controls .step-off #calendar-summary { border-style: dashed; }
/* the path, step by step (sim.js rail): beside the page from 1280 px, still
   while it scrolls, the page's other parts in the column beside it; under, a
   bar at the page's foot with the step lit and its way on, the path a click away */
#step-rail { box-sizing: border-box; display: flex; flex-direction: column; gap: var(--space-3); padding: var(--space-4); background: var(--panel); font-size: var(--fs-body); color: var(--text-2); }
#step-rail[hidden], #rail-go button[hidden] { display: none; }
#step-rail p { margin: 0; }
#rail-where { font-size: var(--fs-label); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--text-3); }
#rail-steps { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-3); }
#rail-steps > li { display: grid; grid-template-columns: 22px minmax(0, 1fr); gap: 0 10px; }
.rail-num { width: 22px; height: 22px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border-radius: var(--radius-xs); font: 500 var(--fs-small) var(--font-mono); border: 1px solid var(--border); color: var(--text-3); }
#rail-steps .done .rail-num { background: var(--text-3); border-color: var(--text-3); color: var(--panel); }
#rail-steps .now .rail-num { background: var(--text); border-color: var(--text); color: var(--panel); }
#rail-steps .now { margin: 0 calc(-1 * var(--space-2)); padding: var(--space-3) var(--space-2); border: 1px solid var(--border); border-radius: var(--radius-s); }
.rail-body { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; min-width: 0; }
.rail-name { font-weight: 600; color: var(--text); }
#rail-steps .shut .rail-name, #rail-steps .skipped .rail-name { font-weight: 500; color: var(--text-3); }
/* a set of the path, a click away: a link's look, a button's keys */
.rail-open { height: auto; min-height: var(--target-min); padding: 0; border: 0; text-align: left; font-weight: 600; color: var(--accent-text); }
.rail-open:hover { text-decoration: underline; }
/* the sets a stage of an auto ran, a link each under it (auto.js autoSetLinks); the one on show marked */
.rail-sets { display: flex; flex-direction: column; align-items: flex-start; }
.rail-sets .rail-open { min-height: 28px; font-weight: 400; font-size: var(--fs-small); }
.rail-sets .rail-open.on { font-weight: 600; }
#rail-now { display: flex; flex-direction: column; gap: var(--space-2); margin-top: var(--space-1); }
#rail-verdict { color: var(--text); }
#rail-detail { display: flex; flex-direction: column; gap: var(--space-2); }
#rail-checks { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
#rail-checks .good { color: var(--up); font-weight: 600; }
#rail-checks .bad { color: var(--down); font-weight: 600; }
#rail-others { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; }
#rail-others:empty { display: none; }
#rail-go { display: flex; flex-direction: column; align-items: stretch; gap: var(--space-2); }
#rail-go button { height: auto; min-height: var(--control-h); padding: 6px var(--space-3); text-align: left; white-space: normal; }
/* on the rail the mix's two segments share its width, the simulate's three tabs stand up in all of it */
#rail-mode [role="group"] { display: flex; }
#rail-mode [role="group"] button { flex: 1 1 auto; white-space: nowrap; }
#rail-mode .tabs.vertical { align-self: stretch; }
#rail-path::after { content: " \25B4"; }
#rail-path[aria-expanded="true"]::after { content: " \25BE"; }
/* auto, the third mode (auto.js, piano-restyle phase 10): its recipe in the form in place of
   the grid, its card on the path under the stage going now, what it chose over the chart */
/* its own pause and stop on the path: the set's, beside the form, would hold only the set going now */
.autoing #grid, .autoing #step-card, .autoing #combos, .autoing #rerun, .autoing #rerun-auto, .autoing #pause, .autoing #stop { display: none; }
#auto-recipe {
  display: flex; flex-direction: column; gap: var(--space-3); flex-basis: 100%; margin: 0;
  border: 1px solid var(--line); border-radius: var(--radius-s); padding: 8px var(--space-3) var(--space-3);
}
#auto-recipe[hidden], .set-folded #auto-recipe { display: none; }
#auto-recipe legend { color: var(--text-3); font-size: var(--fs-label); padding: 0 4px; }
#auto-recipe p, #rail-auto p { margin: 0; }
.auto-step { display: flex; flex-direction: column; gap: var(--space-2); padding-bottom: var(--space-3); border-bottom: 1px solid var(--line); }
.auto-step-head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); }
.auto-step-name { font-weight: 600; color: var(--text); }
/* a box ticked beside its words, not under them as a form's labels are */
.auto-after-box, #auto-bands label { flex-direction: row; align-items: center; gap: 6px; text-transform: none; letter-spacing: 0; font-size: var(--fs-body); color: var(--text-2); }
.auto-set, .auto-add, #auto-options { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--space-2) var(--space-3); }
/* what a set tries, a line of its own over its fields */
.auto-set .auto-why { flex-basis: 100%; }
/* the steps of the recipe before, faded while the service works out the new ones (auto.js autoRecipe) */
#auto-steps[aria-busy="true"] { opacity: .45; pointer-events: none; }
#auto-reading:empty { display: none; }
.auto-runs { align-self: center; font: var(--fs-small) var(--font-mono); color: var(--text-3); }
.auto-drop { min-width: var(--target-min); padding: 0 8px; }
#auto-total { font: 500 var(--fs-body) var(--font-mono); color: var(--text); }
#auto-error { color: var(--down); }
#auto-error[hidden] { display: none; }
#rail-auto { display: flex; flex-direction: column; gap: var(--space-2); margin-top: var(--space-1); }
#rail-auto[hidden], #auto-go button[hidden], #auto-cap-box[hidden], #auto-progress[hidden] { display: none; }
#auto-verdict { color: var(--text); }
#auto-detail { display: flex; flex-direction: column; gap: var(--space-2); }
#auto-progress { width: 100%; height: 6px; accent-color: var(--entry); }
#auto-bands { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
#auto-bands:empty, #auto-wait-since:empty, #auto-left:empty { display: none; }
/* one line each (autoCard): the whole auto, then the set going now */
#auto-left { white-space: pre-line; }
#auto-wait-since { color: var(--warn); }
#auto-stopat { display: flex; }
#auto-stopat button { flex: 1 1 auto; padding: 0 6px; white-space: nowrap; }
#auto-go { display: flex; flex-direction: column; align-items: stretch; gap: var(--space-2); }
#auto-go button { height: auto; min-height: var(--control-h); padding: 6px var(--space-3); text-align: left; white-space: normal; }
#auto-panel { overflow-x: auto; }
#auto-panel[hidden] { display: none; }
#auto-table td:last-child { white-space: normal; min-width: 16ch; }
/* the simulate's main is .modes-beside (sim.html): its rail there in every mode, free with its tabs alone */
@media (min-width: 1280px) {
  .stepping main, main.modes-beside { display: grid; grid-template-columns: var(--rail-w) minmax(0, 1fr); align-items: start; }
  .stepping main > *, main.modes-beside > * { grid-column: 2; }
  .modes-beside > #step-rail[hidden] { display: flex; }
  :root:not(.stepping) .modes-beside > #step-rail > :not(#rail-mode) { display: none; }
  .stepping #step-rail, .modes-beside > #step-rail { grid-column: 1; grid-row: 1 / span 12; position: sticky; top: 0; max-height: 100vh; overflow-y: auto; border-right: 1px solid var(--line); }
  #rail-path { display: none; }
}
@media (max-width: 1279px) {
  #step-rail { position: fixed; left: 0; right: 0; bottom: 0; z-index: 5; max-height: 75vh; overflow-y: auto; gap: var(--space-2); padding: var(--space-3) var(--space-4); border-top: 1px solid var(--line); box-shadow: var(--shadow-float); }
  #step-rail:not(.open) { flex-flow: row wrap; align-items: flex-start; }
  #step-rail:not(.open) > :not(#rail-steps, #rail-path), #step-rail:not(.open) #rail-steps > :not(.now),
  #step-rail:not(.open) :is(#rail-detail, #auto-detail), #step-rail:not(.open) .now > .rail-num { display: none; }
  #step-rail:not(.open) #rail-steps { flex: 1 1 0; min-width: 0; }
  #step-rail:not(.open) #rail-steps > .now { display: block; margin: 0; padding: 0; background: none; border: 0; }
  #step-rail:not(.open) :is(#rail-go, #auto-go) { flex-flow: row wrap; }
  .stepping main { padding-bottom: var(--rail-h, 0px); }
}
/* a phone: the bar folded is the verdict and the one way on (sim.js rail, .lead) */
@media (max-width: 640px) {
  #step-rail:not(.open) .now .rail-name, #step-rail:not(.open) :is(#rail-go, #auto-go) button:not(.lead) { display: none; }
}
/* the mix step by step (mix.js renderSteps): no tabs, every tab's panel at
   once, and of their parts the open step's alone - each says its steps in
   data-mix-steps, none for the parts of the free page only */
.stepping #mix-page { display: block; }
.stepping #mix-tabs { display: none; }
.stepping #mix-page > [role="tabpanel"][hidden] { display: block; }
/* beside the page its field is the rail's from the first paint: in the bar, before mix.js moves it, it would shift the bar */
@media (min-width: 1280px) { .stepping #mix-controls > #mode-field { display: none; } }
/* under #mix-page, to weigh more than a part's own display (#mix-walk-form, #kpi-head) */
[data-mix-step="1"] #mix-page [data-mix-steps]:not([data-mix-steps~="1"]), [data-mix-step="2"] #mix-page [data-mix-steps]:not([data-mix-steps~="2"]),
[data-mix-step="3"] #mix-page [data-mix-steps]:not([data-mix-steps~="3"]), [data-mix-step="4"] #mix-page [data-mix-steps]:not([data-mix-steps~="4"]),
[data-mix-step="5"] #mix-page [data-mix-steps]:not([data-mix-steps~="5"]) { display: none; }
/* in the column beside the rail the runs' table keeps its weights in sight at 1440: its words wrap, its
   cells closer, and each run's opening capital - the default one's, on every row - is the free page's */
.stepping #mix-table td { white-space: normal; }
.stepping #mix-table :is(th, td) { padding-inline: var(--space-1); }
.stepping #mix-table .start { display: none; }
/* "mix ready?", a check a row: the open step's marked at its edge, those of the steps shut quiet; at
   390 px its five columns are wider than the panel, and scroll in it as the runs' table does */
#mix-ready { overflow-x: auto; }
#mix-ready[hidden] { display: none; }
#mix-ready-rows tr { cursor: default; }
#mix-ready-rows td { white-space: normal; }
#mix-ready-rows td:last-child { white-space: nowrap; }
#mix-ready-rows tr.here td:first-child { box-shadow: inset 3px 0 0 var(--text); }
#mix-ready-rows tr.later td { color: var(--text-3); }
/* the checks of a step in the KPI table: columns of their own, their heads on the
   raised ground - the cells not, whose green and red on it fall under 4.5:1 */
#kpi-thead th.step-check { cursor: default; white-space: normal; min-width: 11ch; background: var(--raised); }
#kpi-rows td.step-check { white-space: nowrap; }
.walk-window { display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-end; flex-basis: 100%; }
/* a walk-forward read back: its windows' table, then the tests end to end */
.walk-scroll { overflow-x: auto; }
.walk-table td.good { color: var(--up); }
.walk-table td.bad { color: var(--down); }
/* a window not done: waiting, going now or left by a stop (walkforward.js walkShow) */
.walk-table tr.walk-waiting td { color: var(--text-3); }
.walk-table tr.walk-waiting td.walk-now { color: var(--text-2); }
/* a walk-forward's failure or stop, over its windows */
.walk-why { margin-block: var(--space-2); color: var(--down); }
.walk-table tfoot td { font-weight: 600; border-top: 1px solid var(--line); padding: 5px 8px; }
/* the checks that failed, in words, right after the dates: they wrap rather than widen the table */
.walk-table td.walk-verdict { white-space: normal; min-width: 22ch; }
.walk-curve { display: block; width: 100%; height: 220px; margin-top: var(--space-2); }
#windows-rows, .walk-rows { display: flex; flex-direction: column; gap: 12px; flex-basis: 100%; }
/* the mix's tests out of sample, a path of four cards (mix.html, issue #17): a numbered head opens and shuts
   its card, its state on the right; the card open on the page's ground, the shut ones on the raised one */
.walk-path { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-3); }
.walk-card { border: 1px solid var(--line); border-radius: var(--radius-m); background: var(--raised); min-width: 0; }
.walk-card:has(> h3 > [aria-expanded="true"]) { background: var(--panel); border-color: var(--border); }
.walk-card > h3 { margin: 0; }
.walk-card-head { position: relative; display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px var(--space-3); width: 100%; height: auto;
  padding: var(--space-3) 40px var(--space-3) var(--space-4); border: 0; border-radius: var(--radius-m); background: none; font: inherit; color: inherit; text-align: left; }
/* open or shut, in its top corner: on a phone the state wraps under the name, the arrow stays */
.walk-card-head::after { content: "\25B8"; position: absolute; top: 18px; right: var(--space-4); font: var(--fs-body)/1 var(--font-sans); color: var(--text-3); }
.walk-card-head[aria-expanded="true"]::after { content: "\25BE"; }
.walk-card-n { font-variant-numeric: tabular-nums; }
.walk-card-state { margin-left: auto; font: var(--fs-small)/1.4 var(--font-mono); letter-spacing: 0; color: var(--text-3); }
.walk-card-body { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-3); padding: 0 var(--space-4) var(--space-4); min-width: 0; }
.walk-card-body[hidden] { display: none; }
/* the body's gap spaces its parts: a paragraph's own margins would double it, an empty line take a row */
.walk-card-body > p { margin: 0; }
.walk-card-body > p:empty { display: none; }
.walk-choices { display: grid; grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr)); gap: var(--space-2); width: 100%; }
label.walk-choice { display: grid; grid-template-columns: auto 1fr; align-items: baseline; gap: 2px var(--space-2); padding: var(--space-2) var(--space-3);
  border: 1px solid var(--line); border-radius: var(--radius-s); background: var(--panel); cursor: pointer;
  font-size: var(--fs-small); text-transform: none; letter-spacing: 0; color: var(--text-2); }
/* ticked, in the selection's colour: the ochre is the main action's, never a state's (DESIGN.md § 3) */
label.walk-choice:has(input:checked) { border-color: var(--entry); box-shadow: 0 0 0 1px var(--entry); }
label.walk-choice > span { grid-column: 2; }
.walk-choice-name { font: 600 var(--fs-body) var(--font-sans); color: var(--text); }
.walk-choice-tag { margin-left: var(--space-1); font: 500 var(--fs-label) var(--font-sans); text-transform: uppercase; letter-spacing: var(--tracking-label); color: var(--text-2); }
.walk-mode { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-2); width: 100%; }
.walk-mode[hidden] { display: none; }
.walk-mode h4 { margin: var(--space-2) 0 0; }
#mix-walk-body, .walk-result { width: 100%; min-width: 0; }
.walk-result h4 { margin: var(--space-4) 0 0; }
.walk-result h5 { margin: var(--space-4) 0 0; font: 500 var(--fs-body) var(--font-sans); color: var(--heading); }
/* three runs' ids in the holdout's value column: cut, whole in their title (mix.js renderHoldout) */
#mix-holdout-rows td.num { max-width: 24ch; overflow: hidden; text-overflow: ellipsis; }
#walks-table caption { text-align: left; padding: var(--space-2) var(--space-3); color: var(--text-3); }
/* the strategy's own description, a line the width of the bar over its fields */
/* three lines kept for it from the first paint, the length most have: it
   comes with the stores, and coming later it pushed the whole form down */
#strategy-about { flex-basis: 100%; margin: 0; min-height: calc(3 * var(--lh) * var(--fs-small)); color: var(--text-2); font-size: var(--fs-small); }
#strategy-about[hidden] { display: none; }
/* what a strategy's parameter is, in a few words under its box */
.param-help { max-width: 24ch; text-transform: none; letter-spacing: 0; line-height: 1.3; }
#grid-strategy, #grid-account { display: flex; flex-wrap: wrap; gap: 12px; }
/* the strategy's own ladder off its orders (sim.js ladderNote): what goes unread, said in --warn */
#ladder-note { flex-basis: 100%; margin: var(--space-2) 0 0; color: var(--warn); font-size: var(--fs-small); }
#ladder-note[hidden] { display: none; }
#grid-strategy label.unread { color: var(--text-3); }
#grid-strategy label.unread input { color: var(--text-3); text-decoration: line-through; }
#grid-account { border-left: 1px solid var(--line); padding-left: 12px; }
.hint { text-transform: none; letter-spacing: 0; }
/* the count of runs, then the buttons: pushed to the right end together */
#combos { color: var(--text-3); align-self: center; margin-left: auto; }
/* a set opened to be read (sim.html, sim.js): the form folds into what the set
   varied, the set's own actions beside it, and the results come up to the top */
#form-summary { display: none; }
.set-folded #form-summary { display: flex; flex: 1 1 auto; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); margin: 0; color: var(--text-2); }
.set-folded #sim-controls > :is(label, fieldset, #strategy-about, #combos, #run) { display: none; }
#sim-head, #mix-head { display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: var(--space-2); color: var(--text-3); }
/* the height of replay on one account from the first paint: shown once the mix has an id, it pushed the chart 12 px down (piano-restyle N6) */
#mix-head { min-height: var(--control-h); }
#sim-title, #mix-title { font-size: var(--fs-title); font-weight: 600; color: var(--text); }
#sim-equity { display: block; width: 100%; }
/* the run going now is the line drawn in the text's colour, the one picked
   the selection's, the finished ones the grey that makes forty a spread */
.k.sim-run { color: var(--text); }
.k.sim-pick { color: var(--entry); }
.k.sim-done { color: var(--text-3); }
.k.sim-done::before { border-top-width: 1px; }
/* a varied parameter and its values, one pressed lighting its runs' curves
   (renderLight in sim.js): pressed is ink, like the lit curves */
#sim-light { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin-top: var(--space-2); }
#sim-light[hidden] { display: none; }
#sim-light label { flex-direction: row; align-items: center; gap: 6px; }
#light-values { display: flex; flex-wrap: wrap; gap: var(--space-1); }
#light-values button, #entries-bars button { padding: 0 8px; font-family: var(--font-mono); font-size: var(--fs-small); }
#light-values button[aria-pressed="true"], #entries-bars button[aria-pressed="true"] { color: var(--text); border-color: var(--text); background: var(--raised); }
/* the parameter analysis (renderEffects in sim.js): no colour of its own, a
   verdict that decides is ink and bold, one that matters little is grey */
#sim-effects { margin-top: var(--space-4); overflow-x: auto; }
#sim-effects[hidden] { display: none; }
#effects-head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); margin-bottom: var(--space-2); }
#effects-head label { flex-direction: row; align-items: center; gap: 6px; }
#effects-table td, #effects-values td { font-family: var(--font-mono); font-size: var(--fs-small); }
#effects-table .verdict { font-family: var(--font-sans); }
#effects-table .verdict.strong { color: var(--text); font-weight: 600; }
#effects-table .verdict.weak, #effects-values .hint { color: var(--text-3); }
#effects-values { margin-top: var(--space-3); }
#effects-values[hidden] { display: none; }
#sim-rows td.good, #mix-rows td.good { color: var(--up); }
#sim-rows td.bad, #mix-rows td.bad { color: var(--down); }
#sim-thead th { cursor: pointer; }
.run-actions { white-space: nowrap; }
@media (max-width: 640px) {
  #grid-account { border-left: 0; padding-left: 0; }
  #sim-table-panel { overflow-x: auto; }
}
#sim-table-panel, #mix-table-panel { overflow-x: auto; }
#sim-table-title { margin-bottom: var(--space-2); }
/* the period on two lines, as the parameters beside it already are: the row fits a 1440 screen */
#mix-table td.period { white-space: normal; }
#mix-journal td.when { white-space: nowrap; font-family: var(--font-mono); font-size: var(--fs-small); }
/* a row's long run names break where they must: they ran the page 118 px wide of a 1440 window */
#mix-journal td:not(.when):not(.hint) { white-space: normal; overflow-wrap: anywhere; }
/* the mix's tabs at the page's edge, beside their panels' cards (mix.html #mix-page); the tabs stay in
   sight down a long analysis */
#mix-page { margin: var(--space-4) var(--gutter) 0; gap: var(--space-4); grid-template-columns: var(--side-tabs-w) minmax(0, 1fr); }
#mix-page > [role="tabpanel"] > section { margin: 0 0 var(--space-4); }
#mix-tabs { position: sticky; top: var(--space-3); }
/* real money: the rule of the real accounts' red down its side, as its badge */
#mix-prod-box { margin-top: var(--space-5); padding-left: var(--space-3); border-left: 3px solid var(--down); }
#mix-prod-box h3 .badge { margin-left: var(--space-2); vertical-align: middle; }
/* a finger picks the account a mix starts on: 44 px of it where the pointer is one */
@media (pointer: coarse) { #mix-start-accounts label { min-height: 44px; display: inline-flex; align-items: center; } }
/* words for a screen reader only: a header a column's lines or buttons fill */
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.mix-tab-reading { margin: var(--space-3) 0; }
.mix-tab-reading[hidden] { display: none; }
#mix-start-accounts { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-4); margin: var(--space-2) 0; }
.mix-account { flex-direction: row; align-items: center; gap: var(--space-1); text-transform: none; letter-spacing: 0;
  font-size: var(--fs-body); color: var(--text); }
#mix-start input { width: 14ch; font-family: var(--font-mono); }
/* wide enough for what the simulation held, the numbers the cap is chosen by */
#mix-start input#mix-start-cap { width: 48ch; max-width: 100%; }
/* a run's weight in the mix, a number to type over */
.mix-weight { width: 7ch; font-family: var(--font-mono); text-align: right; }
#mix-weights button { margin-left: var(--space-1); }
#grid-strategy:empty + #grid-account { border-left: 0; padding-left: 0; }

/* the saved sets of simulations */
#sets-dialog { width: calc(100vw - 32px); max-width: none; }
#sets-dialog, #ask-dialog { max-height: calc(100vh - 48px); }
/* the sets table has the trades table's look (a sticky head, the rows' rule),
   flush with the sheet: see .dialog-body.flush */
#runs-table th, #runs-table td { text-align: left; padding: 3px 6px; border-bottom: 1px solid var(--line); }
#runs-table th { color: var(--text-3); font-weight: normal; }
#runs-table .num { text-align: right; }
#sets-table tbody tr, #runs-table tbody tr { cursor: pointer; }
/* the mix's pick of a run from the simulation, see renderRuns() in mix.js */
#runs-panel { overflow-x: auto; }
#runs-panel[hidden] { display: none; }
#runs-head { margin-bottom: var(--space-2); color: var(--text-3); }
#runs-title { font-size: var(--fs-title); font-weight: 600; color: var(--text); }
/* a run the mix has says so in its first cell; a click draws the row's run
   on the chart, and that row is the selected one */
#runs-table tr.in-mix td:first-child { font-weight: 600; white-space: nowrap; }
#mix-add { margin-bottom: var(--space-3); }
/* a head sorts the runs, its arrow says which way (ranked() in mix.js) */
/* a head that sorts its table: the mix's runs, the run page's trades (app.js TRADE_SORTS) */
:is(#runs-table, #trades) th[data-col] { cursor: pointer; }
:is(#runs-table, #trades) th[aria-sort="ascending"]::after { content: ' \25B2'; }
:is(#runs-table, #trades) th[aria-sort="descending"]::after { content: ' \25BC'; }
#runs-fav[aria-pressed="true"] { border-color: var(--entry); color: var(--text); }
#runs-table tbody tr:hover { background: var(--raised); }
#runs-table tr.selected { background: var(--row-selected); }
#runs-table td.good { color: var(--up); }
#runs-table td.bad { color: var(--down); }
#runs-table .spark { display: block; color: var(--text-2); }
.set-name { width: 10em; }
#sets-table td.set-actions { white-space: nowrap; }
#sets-table td.varied { white-space: normal; min-width: 32ch; }
/* the picker of a list (picker.js): the search and the group by under the
   head, the groups' heads in the table, what an action did at the foot */
dialog.picker { width: min(1100px, calc(100vw - 32px)); max-height: calc(100vh - 48px); }
.picker-tools { flex: none; display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); padding: 10px 20px; border-bottom: 1px solid var(--line); }
.picker-tools input[type="search"] { flex: 1 1 16em; min-width: 0; }
.picker-table td { max-width: 48ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.picker-table tbody tr[data-id] { cursor: pointer; }
.picker-table tbody tr[data-id]:hover { background: var(--raised); }
.picker-table tr.current { background: var(--row-selected); }
.picker-table.multi th:first-child { width: 1%; }
.picker-table tr.off { color: var(--text-3); cursor: default; }
tr.picker-group td { font-weight: 600; color: var(--text-2); background: var(--bg); }
.picker-table.multi tr.picker-group { cursor: pointer; }
.picker-empty { color: var(--text-3); }
/* what came over the buttons, the whole width */
.dialog-foot { flex: none; display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--space-2); padding: 12px 20px; border-top: 1px solid var(--line); }
.dialog-foot[hidden] { display: none; }
.picker-state { flex: 1 1 100%; margin: 0; max-height: 8em; overflow: auto; white-space: pre-line; font-size: var(--fs-small); color: var(--text-2); }
.picker-state:empty { display: none; }
.set-delete:hover { border-color: var(--down); }

/* the run page's walk through the table it was opened from */
#run-nav { display: inline-flex; align-items: center; gap: var(--space-2); color: var(--text-3); }
#run-nav[hidden] { display: none; }
/* the way back to the table, a secondary like prev and next beside it */
#run-back { border-color: var(--border); }
#run-back:hover { border-color: var(--text-2); box-shadow: none; }

/* the mix page: its whole, under its runs */
#add-set { max-width: 34em; }
/* the run's name and its parameters wrap, rather than widen the table */
#mix-rows td:nth-child(2), #mix-rows td:nth-child(3), #mix-rows td:nth-child(5) { white-space: normal; }
#mix-rows tr.mix-total td { font-weight: 600; border-top: 1px solid var(--line); }
/* view and remove one over the other, in rows five lines tall: the table fits the analysis tab's column */
#mix-rows td.run-actions button { display: flex; margin: 2px 0; }
#mix-rows tr.mix-total { cursor: default; }

/* the KPI comparison: a verdict colour always comes with its mark, and the
   one in the middle has no colour at all - it is neither a gain nor a loss */
#kpi-head { display: flex; flex-wrap: wrap; gap: 12px; align-items: baseline; margin-bottom: var(--space-2); }
#kpi-head .hint { color: var(--text-3); }
#kpi-panel { overflow-x: auto; }
#kpi-thead th { cursor: pointer; }
#kpi-rows td.good { color: var(--up); }
#kpi-rows td.ok { color: var(--text-2); }
#kpi-rows td.bad { color: var(--down); }

/* one run's KPIs in words */
#analysis-dialog { width: min(980px, calc(100vw - 32px)); max-height: calc(100vh - 48px); }
#analysis-body table { margin: 8px 0 4px; }
/* the run's parameters, name over value, as many a line as the width takes */
.run-params {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: var(--space-2) var(--space-4);
  margin: 0 0 var(--space-5); padding: var(--space-3) var(--space-4);
  background: var(--bg); border: 1px solid var(--line); border-radius: var(--radius-s);
}
.run-params dt { font-size: var(--fs-small); color: var(--text-3); overflow-wrap: anywhere; }
.run-params dd { margin: 0; font-family: var(--font-mono); overflow-wrap: anywhere; }
#analysis-body th, #analysis-body td { text-align: left; padding: 3px 8px; border-bottom: 1px solid var(--line); }
#analysis-body th { color: var(--text-3); font-weight: normal; }
#analysis-body td.num { text-align: right; }
#analysis-body td.good { color: var(--up); }
#analysis-body td.ok { color: var(--text-2); }
#analysis-body td.bad { color: var(--down); }
/* DefunctumEst: #analysis-body h3 at the body's size, replaced by the h3 rule under the titles */
#analysis-body p { margin: var(--space-2) 0 2px; }
#analysis-body ul { margin: 2px 0 var(--space-2); padding-left: 20px; }
.analysis-summary { font-weight: 600; }
/* the score on top of it (analysis.js analysisNodes): the scale in its zones,
   weak, middling and good, each a solid mix of its colour with the panel; two
   triangles in ink, above and below, point at the score (--score); the zone
   reached and the word above take the verdict's colour. Red and green on
   the panel ≥ 3:1, the triangles ≥ 13:1 (docs/ux/analisi-2026-10-01-score-bar.md) */
#analysis-body .score-head { font-size: var(--fs-stat); font-weight: 600; margin: 0 0 var(--space-2); }
.score-bar { --zone-tint: 70%; position: relative; height: 32px; }
/* classic's paler green and darker red: at 70 % they fell to 2.77 and 2.94:1 */
:root[data-look="classic"] .score-bar { --zone-tint: 75%; }
.score-bar span { position: absolute; top: 10px; height: 12px; }
.score-bar span:first-child { border-radius: var(--radius-pill) 0 0 var(--radius-pill); }
.score-bar span:last-child { border-radius: 0 var(--radius-pill) var(--radius-pill) 0; }
.score-bar .bad { background: color-mix(in srgb, var(--down) var(--zone-tint), var(--panel)); }
.score-bar .ok { background: color-mix(in srgb, var(--border) var(--zone-tint), var(--panel)); }
.score-bar .good { background: color-mix(in srgb, var(--up) var(--zone-tint), var(--panel)); }
.score-bar::before, .score-bar::after { content: ''; position: absolute; left: calc(var(--score) - 7px); border-inline: 7px solid transparent; }
.score-bar::before { top: 0; border-top: 9px solid var(--text); }
.score-bar::after { top: 23px; border-bottom: 9px solid var(--text); }
/* under it the zones' words; a bar too narrow for "middling · 40–70" keeps the words alone */
.score-zones { container-type: inline-size; position: relative; height: 16px; margin-top: 4px; font-size: var(--fs-label); line-height: 16px; color: var(--text-3); }
.score-zones span { position: absolute; top: 0; text-align: center; white-space: nowrap; }
.score-zones small { font-size: inherit; }
@container (max-width: 519px) { .score-zones small { display: none; } }
.score-zones .on { font-weight: 600; }
:is(.score-zones .on, .score-head span).bad { color: var(--down); }
:is(.score-zones .on, .score-head span).ok { color: var(--text-2); }
:is(.score-zones .on, .score-head span).good { color: var(--up); }
#analysis-body .score-parts { color: var(--text-3); font-size: var(--fs-small); margin: var(--space-2) 0 12px; }


/* ------------------------------------------------------------ live */

#live-clock { margin-left: auto; font-size: var(--fs-small); }
#live-back { margin-left: auto; }
/* what the page is once it knows (live.js shape): nothing before the first
   round is in; with no session at all, the list and the form to start one */
body.waiting > main > section, body.no-sessions :is(#skew-board, #live-chart-panel, #trade-skew) { display: none; }
#live-panel, #live-detail, #trade-servers, #fill-gaps { overflow-x: auto; }
#trade-servers[hidden], #new-live[hidden] { display: none; }
#push-form { margin-top: var(--space-3); }
#push-note:empty { display: none; }
/* a session started from the live page itself */
#new-live h3 { margin: 0 0 8px; }
/* a strategy with its run is longer than a phone at 14 px (★ M1502-SBR · EUR_USD M15 · +21589 (108 trade)):
   the select and its label give way, the option is cut */
#new-form, #new-form > label { min-width: 0; max-width: 100%; }
#new-strategy { max-width: 100%; }
#new-accounts { border: 1px solid var(--line); border-radius: var(--radius-s); margin: 0; padding: 4px var(--space-3) 8px;
  flex-basis: 100%; }
#new-accounts legend { color: var(--text-3); padding: 0 4px; }
#new-accounts label { display: block; padding: 2px 0; cursor: pointer; text-transform: none;
  letter-spacing: 0; font-size: var(--fs-body); color: var(--text); }
#new-accounts .hint { color: var(--text-3); margin: 2px 0; }
/* an account that trades real money says so the way the header's badge does */
#new-accounts .real { margin-left: 4px;
  background: var(--live); color: var(--on-live); font-weight: 700; font-size: var(--fs-label); }
#new-description { color: var(--text-2); margin: 8px 0 0; max-width: 110ch; }
#new-message { color: var(--entry); margin: var(--space-2) 0 0; }
#live-table th, #live-table td, .live-small th, .live-small td {
  text-align: left; padding: 3px 6px; border-bottom: 1px solid var(--line); white-space: nowrap; }
#live-table th, .live-small th { color: var(--text-3); font-weight: normal; }
#live-table .num, .live-small .num { text-align: right; }
#live-table tbody tr[data-id] { cursor: pointer; }
#live-table td.good, .live-small td.good { color: var(--up); }
#live-table td.bad, .live-small td.bad { color: var(--down); }
/* the fill gaps by the hour of the week (live.js renderGapCells): a cell an hour, red where the broker cost more */
#gap-cells details { margin-top: var(--space-2); overflow-x: auto; }
#gap-cells summary { cursor: pointer; color: var(--text-3); font-size: var(--fs-small); }
.gap-heat { border-collapse: separate; border-spacing: 2px; margin-top: 4px; font: var(--fs-label) var(--font-mono); }
.gap-heat th { padding: 0 6px; color: var(--text-3); font-weight: normal; white-space: nowrap; }
.gap-heat tbody th { text-align: right; }
.gap-heat td { min-width: 40px; height: 18px; padding: 0 4px; text-align: center; border-radius: 3px; }
#live-foot td { color: var(--text-3); border-bottom: 0; }
#live-equity { width: 100%; display: block; margin: 8px 0; }
#detail-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 16px; }
@media (max-width: 900px) { #detail-grid { grid-template-columns: minmax(0, 1fr); } }
#detail-title { font-size: var(--fs-title); font-weight: 600; }
#live-detail h3 { margin: 16px 0 var(--space-2); }
#event-list { max-height: 360px; overflow-y: auto; font-size: var(--fs-small); background: var(--bg);
  border: 1px solid var(--line); border-radius: var(--radius-s); padding: 4px 8px; }
.event { white-space: pre; }
.event-transaction { color: var(--up); }
.event-signal, .event-order { color: var(--entry); }
.event-status { color: var(--down); }
/* a parity status is a divergence from the reference, not an error */
.event-parity { color: var(--text-2); }
.event-candle { color: var(--text-3); }
#console { max-height: 260px; overflow: auto; font-size: var(--fs-label); background: var(--bg);
  border: 1px solid var(--line); border-radius: var(--radius-s); padding: var(--space-2) 8px; margin: 0; }
.hint { color: var(--text-3); }

/* the skew board, the live chart and the trade skew tables */
#skew-board, #live-chart-panel, #trade-skew { overflow-x: auto; }
#skew-table tr.hint td { color: var(--text-3); }
#skew-table td.bad, #trade-skew tr.bad td, #skew-note.bad { color: var(--down); }
#skew-note { margin: var(--space-2) 0 0; }
#chart-controls { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin-bottom: var(--space-2); }
#chart-controls label { flex-direction: row; align-items: center; gap: 6px; text-transform: none;
  letter-spacing: 0; font-size: inherit; cursor: pointer; }
#chart-hover { flex: 1 1 300px; }
/* the two canvases are one chart: same bars, same margins, no gap to speak of */
#live-skew { margin-top: 4px; }
#live-chart, #live-skew { cursor: grab; }
#trade-skew h3 { font-size: var(--fs-body); margin: 12px 0 4px; color: var(--text-3); font-weight: normal; }
#trade-skew tbody tr[data-signal] { cursor: pointer; }

/* the favourite star: a run marked as one of the forms the live page trades.
   A button drawn as a glyph, so it sits in a title or a table cell without a
   box of its own; a full star when pressed, an empty one when not */
.fav-star { height: auto; min-width: var(--target-min); min-height: var(--target-min); background: none; border: 0; color: var(--text-3); cursor: pointer; font-size: 16px; line-height: 1; padding: 0 4px; }
.fav-star[aria-pressed="true"] { color: var(--text); }
.fav-star:hover { color: var(--text); }

/* the live page's new session: the favourites to pick from on the left, what
   the picked one is on the right; one column when the two would not fit */
#new-live .new-grid { display: grid; grid-template-columns: minmax(280px, 1fr) minmax(320px, 1.2fr); gap: 18px; align-items: start; }
@media (max-width: 900px) { #new-live .new-grid { grid-template-columns: 1fr; } }
#new-summary { background: var(--bg); border: 1px solid var(--line); border-radius: var(--radius-s); padding: var(--space-3) 12px; }
#new-summary h4 { margin: 0 0 var(--space-2); }
#new-summary dl { display: grid; grid-template-columns: max-content 1fr; gap: 3px 12px; margin: 0; }
#new-summary dt { color: var(--text-3); }
#new-summary dd { margin: 0; }
#new-summary .hint { margin-top: 8px; }
#new-summary h5 { margin: var(--space-3) 0 4px; font-size: inherit; }
#new-summary dd.hint { margin-top: 0; }
/* the way back to the run this form came from: a secondary button, not a
   word in the hint */
#new-summary a.open-backtest { display: inline-block; margin-top: 10px; padding: 7px 10px; color: var(--text);
  font-weight: 500; border: 1px solid var(--border); border-radius: var(--radius-s); text-decoration: none; }
#new-summary a.open-backtest:hover { border-color: var(--text-2); }
#sim-dialog td.params { font-size: 0.85em; color: var(--text-3); max-width: 360px; }
/* the favourites dialog on the live page: the sets table's look */
#sim-dialog { width: min(980px, calc(100vw - 32px)); }
/* flush with the sheet like the sets table (.live-small is its look); what is
   not the table keeps the head's 20 px */
#sim-list:not(:has(> table)) { padding: 8px 20px; }
#sim-list:has(> table) > :not(table), #sim-message { margin: 8px 20px; }
#sim-dialog tr[data-pick] { cursor: pointer; }
#sim-dialog tr[data-pick]:hover { background: var(--raised); }
/* its tabs a strip under the head, the first word on the title's line */
#sim-tabs { padding: 0 20px; }

/* a phone: the page's margin shrinks, the panels keep their frame */
@media (max-width: 640px) {
  header, .bar, #message { padding-left: var(--space-4); padding-right: var(--space-4); }
  section { margin-left: var(--space-3); margin-right: var(--space-3); }
}

/* the mix page's two readings of one account: the profits added up, or the
   runs traded together (mix.js view()); pressed is the one on show */
/* summed | together: one of two, the Y | N switch's rules (.yn above;
   DESIGN.md § 6, Campi). Was: two bordered buttons, the one on show ringed in
   the entry blue, a colour of the data */
#mix-views[hidden] { display: none; }
#mix-views button { height: auto; border: 0; }
#mix-views button:focus-visible { outline-offset: 1px; }
/* the margin's line and the chart keep their room from the first paint: they
   came in later and moved the table under them */
#mix-margin { margin: 0 0 var(--space-2); min-height: calc(var(--lh) * 1em); color: var(--text-3); }
#mix-equity, #mix-reading { height: 340px; }
#mix-equity[hidden] { display: none; }
/* the chart while the mix is read (mix.js openMix): its room, its grid with
   blocks for the axis's figures, and what it reads in the middle of the plot,
   on the panel's ground over the grid; 46 px is half of AXIS.left in mix.js */
.chart-reading { position: relative; background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius-s); }
.chart-reading .grid { position: absolute; inset: 12px 14px 22px 0; display: flex; flex-direction: column; justify-content: space-between; }
.chart-reading .grid i { display: flex; align-items: center; gap: var(--space-3); }
.chart-reading .grid i::before { content: ""; width: 48px; height: 8px; margin-left: 32px; }
.chart-reading .grid i::after { content: ""; flex: 1; height: 1px; background: var(--grid); }
.chart-reading > .reading, .chart-reading > .reading-failed { position: absolute; top: 50%; left: calc(50% + 46px);
  transform: translate(-50%, -50%); padding: 0 var(--space-3); background: var(--panel); }
.chart-reading > .reading { white-space: nowrap; }
#mix-margin.bad { color: var(--down); }
/* the mix read as a whole (renderAnalysis in mix.js), in the analysis
   dialog's look: its body has that dialog's id */
#mix-analysis { overflow-x: auto; }
#mix-analysis[hidden] { display: none; }
#mix-warning { color: var(--text-2); }
#mix-warning[hidden] { display: none; }

/* an action's picture before its word: <button data-icon="stop">. A mask
   filled with the text's colour, so it follows the theme and the disabled
   look, and a ::before, so a script that rewrites the word keeps it */
[data-icon]::before {
  content: ''; display: inline-block; width: 1.15em; height: 1.15em;
  margin-right: .4em; vertical-align: -.2em; background: currentColor;
  -webkit-mask: var(--icon) center / contain no-repeat; mask: var(--icon) center / contain no-repeat;
}
[data-icon="play"] { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath fill='black' d='M7 4.5v15a1 1 0 0 0 1.5.9l12-7.5a1 1 0 0 0 0-1.8l-12-7.5A1 1 0 0 0 7 4.5z'/%3E%3C/svg%3E"); }
[data-icon="pause"] { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect fill='black' x='6' y='4' width='4' height='16' rx='1'/%3E%3Crect fill='black' x='14' y='4' width='4' height='16' rx='1'/%3E%3C/svg%3E"); }
[data-icon="stop"] { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect fill='black' x='5' y='5' width='14' height='14' rx='2'/%3E%3C/svg%3E"); }
[data-icon="rerun"] { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 12a9 9 0 1 0 3-6.7L3 8'/%3E%3Cpath d='M3 3v5h5'/%3E%3C/svg%3E"); }
[data-icon="delete"] { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 6h18M8 6V4h8v2M19 6l-1 14H6L5 6M10 11v6M14 11v6'/%3E%3C/svg%3E"); }
[data-icon="close"] { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 6 6 18M6 6l12 12'/%3E%3C/svg%3E"); }
[data-icon="yes"] { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E"); }
[data-icon="view"] { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7S2 12 2 12z'/%3E%3Ccircle cx='12' cy='12' r='3'/%3E%3C/svg%3E"); }
[data-icon="analysis"] { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14 3H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z'/%3E%3Cpath d='M14 3v6h6M8 13h8M8 17h5'/%3E%3C/svg%3E"); }
[data-icon="sets"] { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z'/%3E%3C/svg%3E"); }
[data-icon="list"] { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 6h13M8 12h13M8 18h13M3 6h.01M3 12h.01M3 18h.01'/%3E%3C/svg%3E"); }
[data-icon="add"] { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 5v14M5 12h14'/%3E%3C/svg%3E"); }
[data-icon="remove"] { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14'/%3E%3C/svg%3E"); }
[data-icon="calendar"] { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='5' width='18' height='16' rx='2'/%3E%3Cpath d='M3 10h18M8 3v4M16 3v4'/%3E%3C/svg%3E"); }
[data-icon="upload"] { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M17 8l-5-5-5 5M12 3v12'/%3E%3C/svg%3E"); }
[data-icon="import"] { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M7 10l5 5 5-5M12 15V3'/%3E%3C/svg%3E"); }
[data-icon="copy"] { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='9' y='9' width='13' height='13' rx='2'/%3E%3Cpath d='M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1'/%3E%3C/svg%3E"); }
[data-icon="expand"] { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7'/%3E%3C/svg%3E"); }
[data-icon="entries"] { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 12h4l3-8 4 16 3-8h4'/%3E%3C/svg%3E"); }
[data-icon="next"] { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14M13 6l6 6-6 6'/%3E%3C/svg%3E"); }
[data-icon="server"] { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='3' width='18' height='7' rx='2'/%3E%3Crect x='3' y='14' width='18' height='7' rx='2'/%3E%3Cpath d='M7 6.5h.01M7 17.5h.01'/%3E%3C/svg%3E"); }
[data-icon="cloud"] { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M17.5 19H9a7 7 0 1 1 6.7-9h1.8a4.5 4.5 0 1 1 0 9z'/%3E%3C/svg%3E"); }
[data-icon="candles"] { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 3v16a2 2 0 0 0 2 2h16M9 5v4M9 15v2M17 3v2M17 13v3'/%3E%3Crect x='7' y='9' width='4' height='6' rx='1'/%3E%3Crect x='15' y='5' width='4' height='8' rx='1'/%3E%3C/svg%3E"); }
[data-icon="shield"] { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z'/%3E%3Cpath d='m9 12 2 2 4-4'/%3E%3C/svg%3E"); }
[data-icon="sparkle"] { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M11 3l1.9 5.1L18 10l-5.1 1.9L11 17l-1.9-5.1L4 10l5.1-1.9zM19 15v6M16 18h6'/%3E%3C/svg%3E"); }
[data-icon="globe"] { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='M2 12h20M12 2a15 15 0 0 1 0 20 15 15 0 0 1 0-20'/%3E%3C/svg%3E"); }
[data-icon="lock"] { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='4' y='11' width='16' height='10' rx='2'/%3E%3Cpath d='M8 11V7a4 4 0 0 1 8 0v4'/%3E%3C/svg%3E"); }
[data-icon="phone"] { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='6' y='2' width='12' height='20' rx='2'/%3E%3Cpath d='M11 18h2'/%3E%3C/svg%3E"); }
[data-icon="bell"] { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9'/%3E%3Cpath d='M10.3 21a1.94 1.94 0 0 0 3.4 0'/%3E%3C/svg%3E"); }
[data-icon="bug"] { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='8' y='6' width='8' height='14' rx='4'/%3E%3Cpath d='M12 10v10M4 13h4M16 13h4M5 7l3 2M19 7l-3 2M5 20l3-2M19 20l-3-2M10 6 9 3M14 6l1-3'/%3E%3C/svg%3E"); }
/* the report dialog (issue.js): a column like the question's, the note as wide as it in a control's frame */
#issue-dialog { width: min(600px, calc(100vw - 32px)); }
#issue-dialog form.dialog-body { display: grid; gap: var(--space-3); }
#issue-dialog p { margin: 0; }
/* the AI's words (ai.js, chat.js): its own lines, wrapped, never translated (data-i18n-skip) */
#ai-dialog { width: min(680px, calc(100vw - 32px)); }
#ai-dialog form.dialog-body { display: grid; gap: var(--space-3); }
#ai-dialog p { margin: 0; }
.ai-answer { white-space: pre-wrap; overflow-wrap: anywhere; max-height: 60vh; overflow: auto; line-height: 1.5; }
.auto-ai-box { display: flex; flex-wrap: wrap; gap: 8px; align-items: baseline; }
#issue-note-box { display: grid; gap: var(--space-1); }
/* the body's type, not its label's capitals */
#issue-note { box-sizing: border-box; width: 100%; min-height: 8em; resize: vertical; padding: var(--space-2);
  font: var(--fs-body)/1.5 var(--font-sans); text-transform: none; letter-spacing: normal;
  color: var(--text); background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius-s); }
#issue-say.bad { color: var(--down); }
#issue-parts { margin: calc(-1 * var(--space-2)) 0 0; padding-left: 1.2em; overflow-wrap: anywhere; }
/* where price went after a run's entries (openEntries in sim.js): one N on show */
#entries-bars { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1); margin: 8px 0; }
#entries-bars button { height: 28px; }
#entries-bars input { height: 28px; width: 16ch; font-family: var(--font-mono); }
#analysis-body .hint { color: var(--text-3); font-size: var(--fs-small); }

/* ------------------------------------------------------------ docs */

/* tabs (DESIGN.md § 6, Tab): words on a rule, the open one in the text's
   colour with a 2 px bar of it on the rule. Was: every tab a bordered button
   and the open one ringed in the entry blue, a colour of the data. Neutral
   like the Y | N switch: ochre is the main button's and the focus's. The bar
   is the signal as much as the colour; the weight stays 500, or the words
   would move as the tab changes. A phone scrolls the row, it never wraps */
.tabs { display: flex; gap: 0 var(--space-5); border-bottom: 1px solid var(--line); overflow-x: auto; scrollbar-width: none; }
.tabs [role="tab"] { flex: none; height: var(--control-h); min-width: var(--target-min); padding: 0 2px; border: 0; border-radius: 0;
  background: transparent; color: var(--text-2); white-space: nowrap; box-shadow: inset 0 -2px 0 transparent; }
.tabs [role="tab"]:hover { color: var(--text); box-shadow: inset 0 -2px 0 var(--line); }
.tabs [role="tab"][aria-selected="true"] { color: var(--text); box-shadow: inset 0 -2px 0 var(--text); }
/* inside, not outside: the row scrolls, and would cut a ring drawn around it */
.tabs [role="tab"]:focus-visible { outline-offset: -2px; border-radius: var(--radius-s); }
#docs-tabs, #settings-tabs { margin: var(--space-4) var(--gutter) 0; }
#docs-guide[hidden], #docs-api[hidden], #docs-testing[hidden], section[role="tabpanel"][hidden] { display: none; }
@media (max-width: 640px) { #docs-tabs, #settings-tabs { margin-left: var(--space-3); margin-right: var(--space-3); } }

/* how a strategy is written, and the helpers read off the code: prose kept to
   a readable measure, the names and signatures in the mono face */
#docs-how, #docs-guide, #docs-api, #docs-testing { line-height: 1.55; }
#docs-how p, #docs-how dl, #docs-guide p, #docs-guide dl, #docs-guide ol, .docs-note { max-width: 110ch; }
/* DefunctumEst: #docs-how :is(h3, h4) and #docs-guide h3 at the body's size, replaced by the h3 and h4 rules under the titles */
.doc-module-name { margin: 22px 0 var(--space-2); font: 600 var(--fs-body) var(--font-sans); color: var(--text); scroll-margin-top: 12px; }
/* a vertical tab's part opens on its name, level with the tab's */
:is(#docs-how, #docs-guide) .side-tabs > [role="tabpanel"] > h3:first-child, .doc-module-name { margin-top: 6px; }
#docs-how p, #docs-guide p { margin: 0 0 8px; color: var(--text-2); }
/* how it works: the pictures of the architectures, and the pages copied from
   claude.ai in a frame docs.js makes as tall as the page it holds */
#docs-how .testing-figure { margin: 0 0 var(--space-5); }
#docs-how .testing-figure img { display: block; width: 100%; height: auto; }
#docs-how figcaption strong { color: var(--text-2); }
.docs-page { display: block; width: 100%; height: 80vh; border: 1px solid var(--line); border-radius: var(--radius-s); }
.docs-sources { font-size: var(--fs-small); }
/* DefunctumEst: .docs-steps, the testing tab's lists, replaced by .testing-list */

/* the testing tab: one reading column, as the protocol's page on claude.ai -
   the trade drawn once, a card a step, then each step with its drawing, its
   question and its rows. The gaps do the spacing, so nothing has a margin.
   A step's colour is its piece of the trade in the first drawing: the entry
   blue, the stop red, the trailing stop and the exit as the chart marks them */
#docs-testing .testing { display: flex; flex-direction: column; gap: 44px; max-width: 720px; margin-top: var(--space-4); }
.testing-part, .testing-step { display: flex; flex-direction: column; gap: var(--space-3); scroll-margin-top: 12px; }
#docs-testing p, #docs-testing ul, #docs-testing ol, #docs-testing dl, #docs-testing h3, #docs-testing h4 { margin: 0; }
#docs-testing p, #docs-testing li { color: var(--text-2); }
/* DefunctumEst: #docs-testing h3 in the serif at --fs-h-dialog, replaced by the h3 rule under the titles */
#docs-testing h4 { font: 600 var(--fs-body) var(--font-sans); }
.testing-lede { font-size: var(--fs-title); }
#docs-testing .testing-muted { color: var(--text-3); }
.testing-list { padding-left: 22px; }
.testing-list li + li, .testing-rows li + li { margin-top: 4px; }
.step-1 { --step: var(--entry); }
.step-2 { --step: var(--down); }
.step-3 { --step: var(--mark-trail); }
.step-4 { --step: var(--mark-exit); }
.step-5 { --step: var(--text-2); }
.testing-n { font: 500 var(--fs-label) var(--font-mono); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--step); }
.testing-cards { list-style: none; padding: 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-3); }
.testing-cards li { min-width: 0; }
.testing-cards a { display: flex; flex-direction: column; gap: 2px; height: 100%; padding: var(--space-3) var(--space-4);
  background: var(--raised); border: 1px solid var(--line); border-radius: var(--radius-m); color: var(--text-2); text-decoration: none; }
.testing-cards a:hover { border-color: var(--border); }
.testing-t { font-weight: 600; color: var(--text); }
.testing-head { display: flex; flex-direction: column; gap: 4px; }
.testing-q { font-size: var(--fs-title); }
.testing-pair { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-3); }
.testing-note { display: flex; flex-direction: column; gap: 4px; padding: var(--space-3) var(--space-4);
  background: var(--raised); border: 1px solid var(--line); border-radius: var(--radius-m); }
/* fixed, varied, read, next when: the label in a column of its own, as the table of a wizard */
.testing-rows { display: grid; grid-template-columns: 8.5em minmax(0, 1fr); gap: var(--space-4) var(--space-5); }
.testing-rows dt { padding-top: 2px; font: 500 var(--fs-label) var(--font-mono); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--text-3); }
.testing-rows dd { display: flex; flex-direction: column; gap: 4px; min-width: 0; margin: 0; color: var(--text-2); }
.testing-rows ul, .testing-rows ol { padding-left: 20px; }
.testing-name { margin-right: 4px; font-family: var(--font-mono); color: var(--text); }
/* the drawings: SVG in the page's colours, so both themes; a phone scrolls
   one sideways rather than shrink its words below reading */
.testing-figure { display: flex; flex-direction: column; gap: var(--space-2); margin: 0; }
.testing-figure figcaption { font-size: var(--fs-small); color: var(--text-3); }
.testing-chart { overflow-x: auto; padding-block: var(--space-3); border-block: 1px solid var(--line); }
.testing-chart svg { display: block; width: 100%; min-width: 560px; height: auto; }
/* a label over a line stays legible: a rim of the panel's colour under it */
.testing-chart text { font-family: var(--font-mono); font-size: 11px; fill: var(--text-2);
  paint-order: stroke; stroke: var(--panel); stroke-width: 3px; stroke-linejoin: round; }
.testing-chart .axis { font-size: 10px; fill: var(--text-3); }
.testing-chart line, .testing-chart polyline, .testing-chart path { fill: none; }
.testing-chart .gridline { stroke: var(--grid); }
.testing-chart .price { stroke: var(--text-2); stroke-width: 1.75; stroke-linejoin: round; }
.testing-chart .path { stroke: var(--text-3); stroke-opacity: .45; stroke-linejoin: round; }
.testing-chart .stop { stroke: var(--down); stroke-width: 1.5; stroke-dasharray: 5 4; }
.testing-chart .ghost-stop { stroke: var(--down); stroke-dasharray: 2 4; }
.testing-chart .target { stroke: var(--up); stroke-width: 1.5; stroke-dasharray: 5 4; }
.testing-chart .trail { stroke: var(--mark-trail); stroke-width: 2; }
.testing-chart .be { stroke: var(--mark-trail); stroke-width: 1.5; stroke-dasharray: 5 4; }
.testing-chart .best { stroke: var(--mark-trail); stroke-dasharray: 1 3; }
.testing-chart .exit { stroke: var(--mark-exit); stroke-width: 1.5; }
.testing-chart .mean { stroke: var(--entry); stroke-width: 2.5; }
.testing-chart .rand { stroke: var(--text-3); stroke-width: 2; stroke-dasharray: 6 4; }
.testing-chart .mfe { stroke: var(--up); stroke-width: 2; }
.testing-chart .mae { stroke: var(--down); stroke-width: 2; }
.testing-chart .bracket { stroke: var(--text); stroke-width: 1.25; }
.testing-chart .x-mark { stroke: var(--down); stroke-width: 2; }
.testing-chart .cell { fill: var(--up); }
/* step 5's week and shuffled calendars (docs.html #testing-5) */
.testing-chart .cell-down { fill: var(--down); }
.testing-chart .cell-none { fill: var(--bg); stroke: var(--line); }
.testing-chart .cut { fill: none; stroke: var(--text); stroke-width: 2; }
.testing-chart .rand-bar { fill: var(--text-3); fill-opacity: .45; }
.testing-chart .plateau { fill: none; stroke: var(--text); stroke-width: 1.5; }
.testing-chart .entry-dot, .testing-chart .l-entry { fill: var(--entry); }
.testing-chart .up-dot, .testing-chart .l-target { fill: var(--up); }
.testing-chart .l-stop { fill: var(--down); }
.testing-chart .mark, .testing-chart .l-trail { fill: var(--mark-trail); }
.testing-chart .exit-dot, .testing-chart .l-exit { fill: var(--mark-exit); }
@media (max-width: 600px) {
  #docs-testing .testing { gap: 36px; }
  .testing-cards, .testing-pair { grid-template-columns: minmax(0, 1fr); }
  .testing-rows { grid-template-columns: minmax(0, 1fr); gap: 4px; }
  .testing-rows dd { margin-bottom: var(--space-3); }
}
.docs-note { color: var(--text-3); margin: 4px 0 var(--space-3); }
/* DefunctumEst: .docs-toc, the links over the guide and the helpers, replaced by their vertical tabs */
.docs-list { display: flex; flex-wrap: wrap; gap: 4px var(--space-3); }
.docs-terms { display: grid; grid-template-columns: fit-content(40%) minmax(0, 1fr); gap: var(--space-2) 16px; margin: 0 0 8px; }
.docs-terms dt { font-family: var(--font-mono); color: var(--text); }
.docs-terms dd { margin: 0; color: var(--text-2); }
#docs-example, #docs-guide-text, .doc pre { margin: 0 0 var(--space-3); padding: var(--space-3); overflow-x: auto; background: var(--raised); border-radius: var(--radius-s); font-size: var(--fs-small); tab-size: 4; }
#docs-rules { margin: 0 0 var(--space-3); padding-left: 22px; color: var(--text-2); }
#docs-rules li + li { margin-top: 4px; }
#docs-told > summary, .doc-about > summary { cursor: pointer; width: max-content; color: var(--text-3); }
#docs-told pre { margin-top: 8px; white-space: pre-wrap; }
/* the version and license tab: the commits a list, the license wrapped at a phone's width */
.about-lines { margin: 0 0 var(--space-3); padding-left: 20px; max-width: 110ch; }
#about-text { margin: 0; padding: var(--space-3); max-width: 80ch; white-space: pre-wrap; background: var(--raised); border-radius: var(--radius-s); font-size: var(--fs-small); }
/* the helpers' column: the filter over the modules' tabs */
#docs-api-head { display: flex; flex-direction: column; gap: var(--space-2); align-self: start; min-width: 0; }
#docs-api-head .tabs.vertical { align-self: stretch; }
#docs-filter { width: 100%; }
#docs-reference { min-width: 0; }
/* the h3 rule turns synthesis off for the serif; Plex Mono has no 600, and a module's name was always drawn bold */
.doc-module-name { font-family: var(--font-mono); font-synthesis: initial; scroll-margin-top: 12px; }
.doc-about { margin: 0 0 8px; }
.doc-item { padding: var(--space-3) 0 4px; border-top: 1px dashed var(--line); }
.doc-item h4 { margin: 0 0 4px; font-weight: 600; }
.doc-sig { font-family: var(--font-mono); font-size: var(--fs-small); color: var(--text); overflow-wrap: anywhere; }
.doc { color: var(--text-2); max-width: 110ch; }
.doc p { margin: 0 0 var(--space-2); }
.doc ul { margin: 0 0 var(--space-2); padding-left: 20px; }
.doc-method { margin: 8px 0 0 18px; }
.doc-method .doc { margin-top: 2px; }
.doc-constants { display: grid; grid-template-columns: fit-content(45%) minmax(0, 1fr); gap: 4px 16px; margin: var(--space-2) 0; }
.doc-constants dd { margin: 0; color: var(--text-3); }
.doc-constants dt, .docs-terms dt { overflow-wrap: anywhere; }
.doc-item[hidden], .doc-method[hidden], .doc-module[hidden] { display: none; }
@media (max-width: 600px) {
  .docs-terms, .doc-constants { grid-template-columns: minmax(0, 1fr); }
  .docs-terms dd, .doc-constants dd { margin-bottom: var(--space-2); }
  .doc-method { margin-left: 8px; }
}

/* the alerts open (alerts.js, web/notify.py), under the header of the live and logs pages */
#alert-banners { display: flex; flex-direction: column; gap: var(--space-2); margin: var(--space-4) var(--gutter) 0; }
#alert-banners:empty { display: none; }
.alert-banner { display: flex; gap: 12px; align-items: baseline; padding: 8px 12px; border-radius: var(--radius-s);
                background: var(--error-bg); color: var(--down); overflow-wrap: anywhere; }
.alert-banner.info { background: var(--info-bg); color: var(--entry); }
.alert-banner .text { flex: 1; }
.alert-banner button { flex: none; }
#phone-qr { margin: 12px 0; }
/* which alerts go where (settings.js ALERT_GROUPS): a group a row, its name over what it holds, a tick a channel */
#route-table th[scope="row"] { padding: 5px 8px 5px 0; border-bottom: 1px solid var(--line); font-weight: 500; text-align: left; }
#route-table tbody tr { cursor: default; }
#route-table th[scope="row"] .dim { display: block; font-weight: 400; font-size: var(--fs-small); color: var(--text-3); }
#route-table td { text-align: center; }
#phone-qr-img { image-rendering: pixelated; background: #fff; padding: 8px; border-radius: var(--radius-s); }
#gate-rows td.good, #mix-holdout-rows td.good, #mix-ready-rows td.good { color: var(--up); }
#gate-rows td.bad, #mix-holdout-rows td.bad, #mix-ready-rows td.bad { color: var(--down); }
/* the run's trades: fifteen columns, which a narrow window scrolls rather than the page */
#trades-panel { overflow-x: auto; }
/* the entry analysis (performance/entry.py): a row a feature, a cell a band */
#entry-wrap { overflow-x: auto; }
#entry-table td { white-space: nowrap; padding: 4px 10px; }
#entry-table td.good { color: var(--up); }
#entry-table td.bad { color: var(--down); }
#entry-candidates div { margin-top: var(--space-2); }
/* the price-action patterns, under the indicators and laid out as they are */
#mcp-patterns-box { margin-top: 14px; padding-top: var(--space-3); border-top: 1px solid var(--line); }
#patterns-hint { color: var(--text-3); margin: 4px 0 8px; max-width: 110ch; }
#mcp-pattern-files { display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: flex-end; margin: 8px 0; }
#mcp-patterns[hidden] { display: none; }
#mcp-patterns td:last-child { white-space: nowrap; }
#mcp-patterns td:nth-child(5) { max-width: 0; width: 100%; overflow: hidden; text-overflow: ellipsis; }
#mcp-patterns tr.open td:nth-child(5) { white-space: normal; }
#mcp-pattern-rows td { cursor: default; }
#mcp-patterns td:last-child button + button { margin-left: 6px; }
@media (max-width: 1000px) {
  #mcp-patterns thead { display: none; }
  #mcp-pattern-rows tr { display: grid; grid-template-columns: minmax(0, 1fr) auto; border-bottom: 1px solid var(--line); padding: 4px 0; }
  #mcp-pattern-rows td { border: 0; }
  #mcp-pattern-rows td:nth-child(3), #mcp-pattern-rows td:nth-child(4) { display: none; }
  #mcp-pattern-rows td:nth-child(5), #mcp-pattern-rows td:last-child { grid-column: 1 / -1; }
  #mcp-pattern-rows td:nth-child(5) { max-width: none; width: auto; }
  #mcp-pattern-rows td:last-child { white-space: normal; }
  #mcp-pattern-rows td:last-child button { white-space: nowrap; margin: 2px 6px 2px 0; }
  #editor-dialog .dialog-head { flex-wrap: wrap; row-gap: 8px; }
}
/* the code editor (settings.js editorOpen): the name, the code with its
   lines' numbers beside it, what the checks found under it */
#editor-dialog { width: min(1100px, calc(100vw - 32px)); height: calc(100vh - 48px); }
#editor-dialog .dialog-body { display: flex; flex-direction: column; gap: var(--space-3); }
#editor-dialog label { align-self: flex-start; }
#editor-name { width: 34ch; font-family: var(--font-mono); }
#editor-code { flex: 1; min-height: 200px; display: flex; border: 1px solid var(--border); border-radius: var(--radius-s); background: var(--bg); overflow: hidden; }
#editor-code:focus-within { border-color: var(--focus); box-shadow: 0 0 0 3px color-mix(in srgb, var(--focus) 20%, transparent); }
#editor-lines, #editor-source { margin: 0; padding: 8px; font: 13px/18px var(--font-mono); font-feature-settings: "zero" 1; tab-size: 4; }
/* further down than the text: the text's own scrollbar lets it scroll that much more */
#editor-lines { flex: none; min-width: 3ch; padding-bottom: 40px; overflow: hidden; text-align: right; color: var(--text-3); border-right: 1px solid var(--line); user-select: none; }
#editor-source { flex: 1; min-width: 0; resize: none; border: 0; outline: none; background: transparent; color: var(--text); white-space: pre; overflow: auto; }
#editor-problems { flex: none; max-height: 30vh; overflow: auto; margin: 0; padding: 0; list-style: none; font: var(--fs-small)/1.5 var(--font-mono); color: var(--text-3); white-space: pre-wrap; overflow-wrap: anywhere; }
#editor-problems.bad { color: var(--down); }
#editor-problems button { height: auto; padding: 0; border: 0; font: inherit; color: inherit; text-align: left; text-decoration: underline; white-space: pre-wrap; }

/* the library of settings: a vertical tab a kind - strategies, indicators,
   patterns - beside its lists. The same neutral tabs, stood up: the rule on
   their right and the open one's bar on it. A phone lays them back down in a
   row over the lists, as every other row of tabs */
/* the market data's parts and access's are the same stood up tabs beside their panel */
.library, .side-tabs { display: grid; grid-template-columns: var(--side-tabs-w) minmax(0, 1fr); gap: var(--space-5); margin-top: var(--space-3); }
.side-tabs > [role="tabpanel"] { min-width: 0; overflow-x: auto; }
.side-tabs #calendar-box { margin-top: 0; padding-top: 0; border-top: 0; }
/* the vertical tabs a folder's (docs/ux/analisi-2026-09-29-contrasto.md,
   proposal 4): the column a well in the page's ground with a rule on its side,
   the open tab in the panel's own colour and edge, open on its panel's side
   and over the rule, so it reads joined to what it opens. Under the name a
   line or two of state (menu.js tabState()), each on one line. Was: the words
   alone and a 2 px bar on the far side of the column, 170 px from the word */
.tabs.vertical { flex-direction: column; align-self: start; gap: 2px; padding: var(--space-1) 0 var(--space-1) var(--space-1);
  border-bottom: 0; border-right: 1px solid var(--line); border-radius: var(--radius-s) 0 0 var(--radius-s); background: var(--bg); overflow: visible; }
.tabs.vertical [role="tab"] { flex-direction: column; align-items: flex-start; justify-content: center; gap: 1px; height: auto;
  min-height: var(--control-h); margin-right: -1px; padding: 6px var(--space-3); border: 1px solid transparent; border-right: 0;
  border-radius: var(--radius-s) 0 0 var(--radius-s); text-align: left; white-space: normal; box-shadow: none; }
.tabs.vertical [role="tab"]:hover { box-shadow: inset 2px 0 0 var(--line); }
.tabs.vertical [role="tab"][aria-selected="true"] { background: var(--panel); border-color: var(--line); box-shadow: none; }
.tab-state { display: flex; flex-direction: column; align-self: stretch; min-width: 0; font: 400 var(--fs-small) var(--font-mono); color: var(--text-3); }
.tab-state > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tab-state > .warn { color: var(--warn); }
.library h3 { margin: 0 0 var(--space-2); }
.library h3 ~ h3 { margin-top: var(--space-5); padding-top: var(--space-3); border-top: 1px solid var(--line); }
.library #mcp-indicators-box, .library #mcp-patterns-box { margin-top: 0; padding-top: 0; border-top: 0; }
#lib-strategy-table, #lib-indicator-table, #lib-pattern-table { margin-bottom: var(--space-3); }
/* beside the side tabs a tablet has no room for them: they scroll on their own, not the page */
@media (max-width: 1000px) {
  #lib-strategy-table, #lib-indicator-table, #lib-pattern-table { display: block; overflow-x: auto; }
}
.library table th, .library table td { text-align: left; padding: 3px 6px; border-bottom: 1px solid var(--line); vertical-align: top; }
.library table th { color: var(--text-3); font-weight: normal; }
/* a built-in one is a line, its description cut to the room left; a double
   click opens the row on all of it, as the ones written here */
#lib-strategy-rows td:nth-child(4), #lib-indicator-rows td:nth-child(3), #lib-pattern-rows td:nth-child(3) {
  max-width: 0; width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#lib-strategy-rows tr.open td, #lib-indicator-rows tr.open td, #lib-pattern-rows tr.open td { white-space: normal; }
#lib-strategy-rows td:first-child, #lib-indicator-rows td:first-child, #lib-pattern-rows td:first-child { white-space: nowrap; font-family: var(--font-mono); font-size: var(--fs-small); }
/* the parameters cut too, and opened with the row: a strategy's dozen names
   in full would make every row a paragraph */
#lib-pattern-rows td:nth-child(2), #lib-strategy-rows td:nth-child(3) { font-family: var(--font-mono); font-size: var(--fs-small);
  max-width: 22em; overflow: hidden; text-overflow: ellipsis; }
#lib-strategy-rows td:nth-child(2), #lib-indicator-rows td:nth-child(2) { white-space: nowrap; }
@media (max-width: 700px) {
  .library, .side-tabs, #mix-page { grid-template-columns: minmax(0, 1fr); gap: var(--space-3); }
  #mix-tabs { position: static; }
  /* a phone: the row of the other tabs again, the names alone */
  .tabs.vertical { flex-direction: row; gap: 0 var(--space-5); padding: 0; border-right: 0; border-bottom: 1px solid var(--line);
    border-radius: 0; background: transparent; overflow-x: auto; }
  .tabs.vertical [role="tab"] { height: var(--control-h); margin: 0; padding: 0 2px; border: 0; border-radius: 0; background: transparent;
    white-space: nowrap; box-shadow: inset 0 -2px 0 transparent; }
  .tabs.vertical [role="tab"]:hover { box-shadow: inset 0 -2px 0 var(--line); }
  .tabs.vertical [role="tab"][aria-selected="true"] { background: transparent; box-shadow: inset 0 -2px 0 var(--text); }
  .tab-state { display: none; }
  /* a phone: each one a block - its name and its view, its description
     under them; what it is meant for and its parameters are in its code */
  .library thead { display: none; }
  #lib-strategy-rows tr, #lib-indicator-rows tr, #lib-pattern-rows tr { display: grid;
    grid-template-columns: minmax(0, 1fr) auto; border-bottom: 1px solid var(--line); padding: 4px 0; }
  .library tbody td { border: 0; }
  #lib-strategy-rows td, #lib-indicator-rows td, #lib-pattern-rows td { display: none; }
  #lib-strategy-rows td:first-child, #lib-indicator-rows td:first-child, #lib-pattern-rows td:first-child {
    display: block; white-space: normal; overflow-wrap: anywhere; }
  #lib-strategy-rows td:last-child, #lib-indicator-rows td:last-child, #lib-pattern-rows td:last-child { display: block; }
  #lib-strategy-rows td:nth-child(4), #lib-indicator-rows td:nth-child(3), #lib-pattern-rows td:nth-child(3) {
    display: block; order: 3; grid-column: 1 / -1; max-width: none; width: auto; white-space: normal; color: var(--text-2); }
}

/* ------------------------------------------------------------ network */

/* the network tab (static/network.js): a star with the archive at its center,
   the PCs, mirrors and data feeders on its left, the trade servers on its
   right, each with its AI clients in a strip under it; the one picked in
   detail beside. A card is the design's A1 (claude.ai canvas "Collegamenti
   PD"): what it is, where it runs, the token it uses, three lights - disk, cpu,
   ram - and, on a trade server, its brokers, accounts and the strategies running */
[data-icon="network"] { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='5' r='3'/%3E%3Ccircle cx='5' cy='19' r='3'/%3E%3Ccircle cx='19' cy='19' r='3'/%3E%3Cpath d='M12 8v4M12 12l-5 4.5M12 12l5 4.5'/%3E%3C/svg%3E"); }
.net-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-2) var(--space-3); }
.net-head .hint { color: var(--text-3); }
.net-legend { margin-left: auto; display: inline-flex; align-items: center; gap: var(--space-2); font-size: var(--fs-small); color: var(--text-2); }
.net-key { display: inline-block; width: 22px; border-top: 1.5px solid var(--border); margin-left: var(--space-2); }
.net-key.ai { border-top-style: dashed; }
.net-body { display: grid; grid-template-columns: minmax(0, 1fr) 340px; gap: var(--space-5); margin-top: var(--space-3); align-items: start; }
.net-body:has(> .net-detail[hidden]) { grid-template-columns: minmax(0, 1fr); }
.net-map { position: relative; padding: var(--space-5) var(--space-4); border: 1px solid var(--line); border-radius: var(--radius-s); background: var(--raised); }
.net-cols { position: relative; z-index: 1; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr) minmax(0, 1fr); gap: var(--space-5) 150px; align-items: center; }
.net-col { display: flex; flex-direction: column; gap: var(--space-5); min-width: 0; }
.net-lines { position: absolute; top: 0; left: 0; z-index: 0; pointer-events: none; }
.net-lines path { fill: none; stroke: var(--border); stroke-width: 1.5; }
.net-edge { position: absolute; z-index: 1; transform: translate(-50%, -50%); max-width: 130px; padding: 0 4px; background: var(--raised); font-size: 11px; line-height: 1.3; text-align: center; color: var(--text-3); pointer-events: none; }
.net-node { display: flex; flex-direction: column; gap: var(--space-2); min-width: 0; }
button.net-card { height: auto; width: 100%; padding: 10px 12px; display: flex; flex-direction: column; gap: 8px; text-align: left;
  font-weight: 400; color: var(--text); background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius-m); }
button.net-card.center { border: 2px solid var(--text); padding: 9px 11px; }
button.net-card.real { border-color: var(--down); }
button.net-card[aria-pressed="true"] { background: var(--row-selected); box-shadow: 0 0 0 2px var(--entry); }
.net-top { display: flex; gap: 12px; min-height: 88px; }
.net-id { flex: 1; min-width: 0; display: flex; flex-direction: column; justify-content: space-between; gap: 4px; }
.net-title { display: flex; align-items: center; gap: 8px; min-width: 0; }
.net-names { display: flex; flex-direction: column; min-width: 0; }
.net-name { font-size: 13px; font-weight: 600; overflow-wrap: anywhere; }
.net-ver { margin-left: 6px; font: 400 11px var(--font-mono); color: var(--text-3); }
.net-type { font-size: 11px; color: var(--text-2); }
.net-type.real { color: var(--down); font-weight: 500; }
.net-tile { width: 30px; height: 30px; flex: none; border-radius: 8px; background: var(--bg); display: inline-flex; align-items: center; justify-content: center; color: var(--text); }
.net-tile img { width: 26px; height: 26px; border-radius: 4px; }
.net-os, .net-token { display: flex; align-items: center; gap: 6px; min-width: 0; font-size: 11px; color: var(--text-2); overflow-wrap: anywhere; }
.net-os img { width: 15px; height: 15px; flex: none; }
.net-token { font-family: var(--font-mono); color: var(--text-3); }
.net-token svg { flex: none; }
.net-leds { display: flex; gap: 6px; align-items: flex-end; }
.net-led { display: flex; flex-direction: column; align-items: center; gap: 3px; font: 10px var(--font-mono); line-height: 1; color: var(--text-3); }
.net-led .net-bar { width: 10px; height: 60px; border-radius: 2px; background: var(--line); display: flex; align-items: flex-end; overflow: hidden; }
.net-led .net-bar i { display: block; width: 100%; background: var(--text-3); }
.net-led .net-k { font-size: 9px; }
.net-led.warn .net-bar i { background: var(--warn); }
.net-led.warn .net-v { color: var(--warn); font-weight: 600; }
.net-led.crit .net-bar i { background: var(--down); }
.net-led.crit .net-v { color: var(--down); font-weight: 600; }
.net-led.none .net-bar { opacity: .45; }
.net-trades { display: flex; flex-direction: column; gap: 4px; padding-top: 8px; border-top: 1px solid var(--line); font-size: 11px; }
.net-acct, .net-run { display: flex; align-items: center; gap: 8px; min-width: 0; }
.net-acct .grow, .net-run .grow { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.net-broker { flex: none; min-width: 64px; box-sizing: border-box; padding: 0 6px; border: 1px solid var(--border); border-radius: 4px;
  background: var(--panel); font-size: 10px; line-height: 16px; font-weight: 600; text-align: center; }
.net-acct.real .net-broker, .net-acct.bad .net-broker { border-color: var(--down); }
.net-unread { flex-wrap: wrap; gap: 4px; }
.net-acct.real .net-kind-word, .net-acct.bad { color: var(--down); font-weight: 600; }
.net-run svg { flex: none; }
.net-warn { font-size: 11px; color: var(--down); }
.net-label { font-size: var(--fs-label); text-transform: uppercase; letter-spacing: var(--tracking-label); color: var(--text-3); font-weight: 500; }
.net-empty { color: var(--text-3); }
.net-ais { display: flex; flex-wrap: wrap; gap: 6px; margin-left: var(--space-4); padding-left: var(--space-3); border-left: 1.5px dashed var(--border); }
button.net-ai { height: 28px; padding: 0 10px; display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 400;
  background: var(--panel); border: 1px dashed var(--border); border-radius: var(--radius-pill); }
button.net-ai[aria-pressed="true"] { background: var(--row-selected); border: 1px solid var(--entry); }
.net-ai img { width: 16px; height: 16px; }
/* a mark in the ink, lightened in the dark theme as the text is */
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) img.mono { filter: invert(.9); } }
:root[data-theme="dark"] img.mono { filter: invert(.9); }
.net-detail { display: flex; flex-direction: column; gap: 10px; padding: 12px 16px; border: 1px solid var(--line); border-radius: var(--radius-s); background: var(--panel); }
.net-detail .net-title .panel-title { flex: 1; margin: 0; }
.net-detail dl { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 4px 12px; margin: 0; font-size: 12px; }
.net-detail dt { color: var(--text-3); }
.net-detail dd { margin: 0; overflow-wrap: anywhere; }
.net-detail dd.bad { color: var(--down); }
.net-detail dd.mono, .net-detail .mono, .net-trades .mono { font-family: var(--font-mono); }
.net-res { display: flex; flex-direction: column; }
.net-actions { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.net-new { margin-top: var(--space-5); padding-top: var(--space-4); border-top: 1px solid var(--line); display: flex; flex-direction: column; gap: var(--space-3); }
.net-row { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--space-3); }
.net-row .hint { color: var(--text-3); padding-bottom: 8px; }
.net-seg { display: inline-flex; border: 1px solid var(--border); border-radius: var(--radius-s); overflow: hidden; }
.net-seg button { border: 0; border-radius: 0; padding: 0 14px; }
.net-seg button + button { border-left: 1px solid var(--border); }
.net-seg button[aria-pressed="true"] { background: var(--text); color: var(--panel); }
.net-seg button:disabled { text-decoration: line-through; }
.net-kinds { margin: 0; padding: 0; border: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: var(--space-3); }
.net-kinds legend { margin-bottom: var(--space-2); padding: 0; }
.net-kind { display: flex; flex-direction: column; gap: 4px; padding: 10px 12px; border: 1px solid var(--border); border-radius: var(--radius-s); font-size: 12px; color: var(--text-2); cursor: pointer; }
.net-kind strong { display: flex; align-items: center; gap: 6px; font-size: 13px; font-weight: 600; color: var(--text); }
.net-kind:has(input:checked) { padding: 9px 11px; border: 2px solid var(--entry); background: var(--row-selected); }
.net-namefield { display: flex; flex-direction: column; gap: 4px; }
.net-made { display: flex; flex-direction: column; gap: 6px; padding: 12px 16px; border: 1px solid var(--line); border-radius: var(--radius-s); background: var(--raised); }
.net-made code { font-family: var(--font-mono); overflow-wrap: anywhere; }
@media (max-width: 900px) {
  .net-body { grid-template-columns: minmax(0, 1fr); }
  .net-cols { grid-template-columns: minmax(0, 1fr); gap: var(--space-4); }
  .net-col.center { order: -1; }
  .net-lines, .net-edge { display: none; }
}
/* what hides them, over their own display */
.net-detail[hidden], .net-made[hidden], #net-subs[hidden] { display: none; }
/* a tile is a choice to read, not a field's label */
.net-kind, .net-kind strong { text-transform: none; letter-spacing: 0; }
