/* The console's stylesheet (kb/console-style). It loads AFTER static/basecoat.min.css, which is Basecoat 1.0.2's
   prebuilt sheet: Tailwind's reset plus the shadcn-look components (.btn, .badge, .alert, .card, .select, .input).
   Basecoat's rules live in cascade layers and this file is unlayered, so a rule here always wins.

   THE RULES THIS FILE ENFORCES BY STRUCTURE, so a page written by any session gets them without a class:
     - a colour is a TOKEN. No hex appears below the two token blocks.
     - depth is a hairline, never a shadow.
     - only a TOP-LEVEL section of main.page has a surface; a section inside a section is a group (spacing and
       an h3). A card never contains a card.
     - every table in main.page is the one table style; .num right-aligns a numeric column in tabular figures.
   Dark mode is the browser's prefers-color-scheme and swaps tokens only; Basecoat's own .dark class is not used. */

/* ------------------------------------------------------------------ 0. the typeface
   The owner, 2026-09-20: "the font should be good for consoles so it should all use the same space per character."
   ONE monospaced family for everything -- prose, headings, tables, logs -- so columns line up without asking.
   JetBrains Mono (OFL 1.1, static/fonts/OFL.txt), the latin subset in two weights, self-hosted because the
   security policy allows a font from nowhere else; about 21 KB each. A glyph outside the subset (an arrow)
   falls back to the system's own monospace. */
@font-face { font-family: "JetBrains Mono"; font-style: normal; font-weight: 400; font-display: swap;
  src: url("fonts/jetbrains-mono-latin-400.woff2") format("woff2"); }
@font-face { font-family: "JetBrains Mono"; font-style: normal; font-weight: 600; font-display: swap;
  src: url("fonts/jetbrains-mono-latin-600.woff2") format("woff2"); }

/* ------------------------------------------------------------------ 1. tokens: light (the owner's palette) */
:root {
  color-scheme: light dark;
  --page: #f0f7ff;            /* Ice White */
  --surface: #ffffff;
  --sunken: #e6effd;          /* a well inside a surface: table heads, hovers */
  --ink: #101733;
  --ink-muted: #4c5675;
  --line: #cfdcf7;
  --line-strong: #a9c0f0;
  --brand: #0033e5;           /* Cobalt Voltage: the ONE accent */
  --brand-hover: #0029b8;
  --brand-ink: #f0f7ff;       /* text on a filled brand surface */
  --brand-soft: #e1ebff;
  --bar: #0033e5;             /* the site header */
  --bar-ink: #f0f7ff;
  --ok: #137333;      --ok-soft: #e6f4ea;
  --warn: #9a5200;    --warn-soft: #fef3d6;
  --bad: #c5221f;     --bad-soft: #fce8e6;
  --code-bg: #0b0e1a; --code-ink: #e8eefc;
  --s1: #0033e5; --s2: #d9650a; --s3: #137333; --s4: #4c5675; --s5: #8e24aa;   /* chart series */
  /* Central banks > Timeline (task-64fec52653): the stance poles red and blue around a grey midpoint, FinBERT's tone
     green and violet; checked in both modes with the dataviz palette validator, every pair (the session's close) */
  --stl-hawkish: #e34948; --stl-dovish: #2a78d6; --stl-neutral: #8a8a86; --stl-good: #008300; --stl-bad: #4a3aa7;
  --fresh: rgba(253, 214, 99, .42);

  --r-input: 4px; --r-surface: 10px; --r-pill: 999px;
  --gap: 1rem;

  /* the names Basecoat reads (shadcn's theme). NOTE shadcn's --accent is a HOVER tint, not the brand. */
  --background: var(--page);       --foreground: var(--ink);
  --card: var(--surface);          --card-foreground: var(--ink);
  --popover: var(--surface);       --popover-foreground: var(--ink);
  --primary: var(--brand);         --primary-foreground: var(--brand-ink);
  --secondary: var(--brand-soft);  --secondary-foreground: var(--brand);
  --muted: var(--sunken);          --muted-foreground: var(--ink-muted);
  --accent: var(--brand-soft);     --accent-foreground: var(--brand);
  --destructive: var(--bad);
  --border: var(--line);           --input: var(--line-strong);      --ring: var(--brand);
  --radius: .5rem;
  /* Basecoat reads --font-sans for everything that is not code; here both names are the one monospaced family */
  --font-mono: "JetBrains Mono", ui-monospace, "Cascadia Mono", Consolas, Menlo, "DejaVu Sans Mono", "Liberation Mono", monospace;
  --font-sans: var(--font-mono);
}

/* ------------------------------------------------------------------ 1b. tokens: dark (the ONE dark block) */
@media (prefers-color-scheme: dark) {
  :root {
    --page: #0b0e1a;
    --surface: #12162a;
    --sunken: #181d36;
    --ink: #e8eefc;
    --ink-muted: #9aa6c4;
    --line: #232941;
    --line-strong: #343c5e;
    --brand: #7b9cf5;          /* lifted from Cobalt Mist so it clears 4.5:1 on the surface as well as the page */
    --brand-hover: #9db6f8;
    --brand-ink: #0b0e1a;
    --brand-soft: #1a2348;
    --bar: #0033e5;
    --bar-ink: #f0f7ff;
    --ok: #81c995;      --ok-soft: #173224;
    --warn: #fdd663;    --warn-soft: #3a2c0d;
    --bad: #f28b82;     --bad-soft: #3c1f1d;
    --code-bg: #070912; --code-ink: #e8eefc;
    --s1: #7b9cf5; --s2: #fcad70; --s3: #81c995; --s4: #9aa6c4; --s5: #ce93d8;
    --stl-hawkish: #e66767; --stl-dovish: #256abf; --stl-neutral: #8f8e88; --stl-good: #008300; --stl-bad: #9085e9;
  }
}

/* ------------------------------------------------------------------ 2. base (Basecoat's reset strips all of it) */
html { font-family: var(--font-sans); }
body { margin: 0; background: var(--page); color: var(--ink); font-size: .875rem; line-height: 1.55; font-variant-ligatures: none; }
a { color: var(--brand); text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 2px; }
:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; border-radius: 2px; }
h1 { font-size: 1.45rem; font-weight: 600; line-height: 1.25; margin: 0; }
h2 { font-size: 1.1rem; font-weight: 600; line-height: 1.3; margin: 0; }
h3 { font-size: 1rem; font-weight: 600; line-height: 1.35; margin: 0; }
p { margin: 0 0 .75rem; }
strong { font-weight: 600; }
code, pre { font-family: var(--font-mono); }
/* break-word, not anywhere: `anywhere` lets a table column shrink to ONE character, and a monospaced path then
   breaks mid-word (fleet-console.s / ervice). A word that fits nowhere still breaks; a column no longer starves. */
code { font-size: 1em; overflow-wrap: break-word; }
main ul, main ol { margin: 0 0 .75rem; padding-left: 1.25rem; }
main ul { list-style: disc; }
main ol { list-style: decimal; }
main li { margin: .15rem 0; }

/* status: three colours that MEAN something, used once per row on the cell that carries the verdict */
.ok { color: var(--ok); }
.warn { color: var(--warn); }
.bad { color: var(--bad); font-weight: 600; }
.note { color: var(--ink-muted); font-size: .875rem; }
.note.ok { color: var(--ok); } .note.warn { color: var(--warn); } .note.bad { color: var(--bad); }

/* ------------------------------------------------------------------ 3. the frame: the bar, the page, the page header */
header.top {
  position: sticky; top: 0; z-index: 5;
  display: flex; align-items: center; gap: 1.5rem;
  padding: .6rem max(1rem, calc((100% - 80rem) / 2 + 1rem));
  background: var(--bar); color: var(--bar-ink);
}
header.top a { color: var(--bar-ink); }
header.top .brand { font-weight: 600; }
/* the nav bar (task-046516aaf7): Work, then Desk and Console as menus that drop below the bar; on a phone the bar
   gives way to one Menu button whose panel is the header's full width (the phone block, section 10) */
header.top .navbar { display: flex; align-items: center; gap: .25rem; flex: 1; }
header.top .navtop, header.top details > summary { padding: .25rem .7rem; border-radius: var(--r-pill); font-weight: 500; font-size: inherit; color: var(--bar-ink); }
header.top .navtop:hover, header.top .navtop[aria-current], header.top details > summary:hover, header.top details > summary.current,
header.top details[open] > summary { background: rgba(240, 247, 255, .16); color: var(--bar-ink); text-decoration: none; }
header.top details { position: relative; }
header.top details > :not(summary) { margin-top: 0; }
header.top .navgroup > ul { position: absolute; top: calc(100% + .75rem); left: 0; z-index: 6; min-width: 12rem; margin: 0; padding: .35rem;
  list-style: none; background: var(--surface); border: 1px solid var(--line-strong); border-radius: var(--r-surface); }
header.top .navgroup li, header.top .navpanel li { margin: 0; }
header.top .navgroup li a, header.top .navpanel a { display: block; padding: .4rem .7rem; border-radius: var(--r-input); color: var(--ink); }
header.top .navgroup li a:hover, header.top .navpanel a:hover { background: var(--sunken); color: var(--brand); text-decoration: none; }
header.top .navgroup li a[aria-current], header.top .navpanel a[aria-current] { background: var(--brand-soft); color: var(--brand); font-weight: 600; }
.navbadge { display: inline-block; min-width: 1.25rem; margin-left: .35rem; padding: 0 .35rem; border-radius: var(--r-pill);
  background: var(--warn-soft); color: var(--warn); font-size: .75rem; font-weight: 600; line-height: 1.25rem; text-align: center; }
.navbadge[hidden] { display: none; }
header.top .navphone, header.top .navpanel { display: none; }
header.top form { margin: 0; }
header.top button.quiet { color: var(--bar-ink); border-color: rgba(240, 247, 255, .45); }
header.top button.quiet:hover { background: rgba(240, 247, 255, .16); }

main.page { box-sizing: border-box; width: calc(100% - 2rem); max-width: 80rem; margin: 1.5rem auto 4rem; }
main.page > * + * { margin-top: var(--gap); }

/* the page header: crumbs, title, ONE purpose sentence, the meta line (read-at stamp and at most three links) */
.page-head { margin-bottom: 1.5rem; }
.page-head > * + * { margin-top: .35rem; }
.crumbs { margin: 0; color: var(--ink-muted); font-size: .8125rem; }
.crumbs a { color: var(--ink-muted); }
.crumbs a:hover { color: var(--brand); }
/* what a fleet spec IS, on Plans and on every plan (task-4d96818810): a plan, never the state of the box -- set
   apart from the page's own words so it is read first and never taken for part of the plan */
.planmark { margin: 0; padding: .5rem .75rem; border-left: 3px solid var(--brand); background: var(--sunken);
  border-radius: var(--r-input); font-size: .875rem; }
/* a knowledge-base page as its own markdown (task-31e20975ee): the Copy button, the raw link that always works,
   and the line saying what the button did -- one row, which wraps on a phone rather than running off it */
.kbcopy { display: flex; flex-wrap: wrap; align-items: baseline; gap: .35rem .9rem; margin: 0; font-size: .875rem; }
.kbcopy [data-kb-said] { flex-basis: 100%; }
.purpose { margin: 0; max-width: 60rem; color: var(--ink-muted); }
.meta { margin: 0; color: var(--ink-muted); font-size: .8125rem; }
/* 25 pills are three lines of header: they sit behind one disclosure, below the title */
.jumpbox > .jump { margin-top: .4rem; }
.jump { display: flex; flex-wrap: wrap; gap: .25rem; margin: 0; font-size: .8125rem; }
.jump a, .jump strong { padding: .15rem .6rem; border-radius: var(--r-pill); box-shadow: inset 0 0 0 1px var(--line); }
.jump a:hover { box-shadow: inset 0 0 0 1px var(--brand); text-decoration: none; }
.jump strong { background: var(--brand); color: var(--brand-ink); box-shadow: none; font-weight: 500; }

/* sign-in and refusal pages: the one place the palette inverts -- a cobalt page, an ice-white card */
body:has(> main.gate) { background: var(--bar); }
main.gate {
  box-sizing: border-box; width: calc(100% - 2rem); max-width: 26rem; margin: 16vh auto 2rem; padding: 2rem 2.25rem;
  border-radius: 16px; background: var(--surface); color: var(--ink);
}
main.gate > * + * { margin-top: .9rem; }

/* ------------------------------------------------------------------ 4. surfaces: the section, the group, the tile, the strip */
/* ONLY a top-level section has a surface. kb.html wraps its sections in .kbkind, and the editor's Edit page its form's
   sections in form.sections (task-492418c391), so that depth counts as top level. */
main.page > section, main.page > .kbkind > section, main.page > form.sections > section, article.doc, .tile, main.page > .stats {
  background: var(--surface); border-radius: var(--r-surface); box-shadow: inset 0 0 0 1px var(--line);
}
/* overflow-x: a table wider than its section scrolls inside the section instead of escaping it */
main.page > section, main.page > .kbkind > section, main.page > form.sections > section { padding: 1.25rem 1.5rem 1.4rem; scroll-margin-top: 4.5rem; overflow-x: auto; }
main.page > section > * + *, main.page > .kbkind > section > * + *, main.page > form.sections > section > * + * { margin-top: .85rem; }
section > header > h2 + p, section > h2 + p.note, section > h2 + p.purpose { margin-top: .2rem; }
/* a section inside a section is a GROUP: an h3, spacing, a hairline above -- never a second surface */
section section, section .group { padding-top: .9rem; border-top: 1px solid var(--line); }
section section > * + *, section .group > * + * { margin-top: .6rem; }
.kbkind > * + *, form.sections > * + * { margin-top: var(--gap); }
.kindhead { font-size: .75rem; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-muted); }

.tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(15.5rem, 1fr)); gap: .75rem; }
.tile { display: block; padding: 1rem 1.15rem 1.1rem; color: inherit; }
a.tile:hover { box-shadow: inset 0 0 0 1px var(--brand); text-decoration: none; }
.tile h2 { font-size: .9375rem; color: var(--brand); }
a.tile h2::after { content: " \2192"; opacity: 0; transition: opacity .12s; }
a.tile:hover h2::after { opacity: 1; }
.tile p { margin: 0; color: var(--ink-muted); font-size: .8125rem; line-height: 1.45; }
.tile p.big { margin: .2rem 0 .4rem; color: var(--ink); font-size: 1.05rem; font-weight: 600; line-height: 1.3; }
.tile p.big.ok { color: var(--ok); } .tile p.big.warn { color: var(--warn); } .tile p.big.bad { color: var(--bad); }
.tile.muted { opacity: .6; }

/* Desk > Ladder (task-a07dd2d5be): the six stages as rungs, six across on a wide screen, three on a narrow one, and
   stacked one above the next on a phone; each a well inside its section, never a second surface */
.rungs { display: grid; grid-template-columns: 1fr; gap: .75rem; margin: 0; padding: 0; list-style: none; }
.rung { min-width: 0; padding: .85rem 1rem 1rem; border-radius: var(--r-surface); background: var(--sunken); }
.rung > * + * { margin-top: .45rem; }
.rung h3 { margin: 0; color: var(--brand); font-size: .8125rem; letter-spacing: .08em; text-transform: uppercase; }
.rung h3 .step { color: var(--ink-muted); font-weight: 500; }
.rung p { margin-bottom: 0; }
.rung p.big { margin-top: .15rem; font-size: 1.6rem; font-weight: 600; line-height: 1.15; font-variant-numeric: tabular-nums; }
.rung p.big.bad { font-size: 1.05rem; }
.rung p.big .lc { display: inline-block; margin-right: 1.1rem; }
.rung p.big .lc .mk { margin-left: .3rem; color: var(--ink-muted); font-size: .78rem; font-weight: 500; }
.rung p.big .lc.bad { color: var(--bad); font-size: 1.05rem; }
.rung p.rule { color: var(--ink); font-size: .8125rem; line-height: 1.4; }
.rung .sub { display: block; color: var(--ink-muted); font-size: .78rem; }
ol.rung-top { margin-top: .2rem; padding-left: 1.1rem; font-size: .8125rem; line-height: 1.4; }
ol.rung-top li + li { margin-top: .25rem; }
ul.today { margin: 0; padding-left: 1.1rem; }
ul.today li + li { margin-top: .5rem; }
.stats.sources a.stat { color: inherit; text-decoration: none; }
.stats.sources a.stat:hover { background: var(--sunken); }
/* a strategy's own page (task-0052de484f): the rung it stands on, outlined in the brand */
.rung.here { box-shadow: inset 0 0 0 2px var(--brand); }
@media (min-width: 46rem) { .rungs { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 78rem) { .rungs { grid-template-columns: repeat(6, minmax(0, 1fr)); } }

/* the summary strip: ONE surface cut by hairlines, not a row of cards. Inside a section it has no surface at all. */
.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(11.5rem, 1fr)); overflow: hidden; }
.stat { display: flex; flex-direction: column; gap: .1rem; padding: .85rem 1.15rem; min-width: 0;
  box-shadow: 1px 0 0 var(--line), 0 1px 0 var(--line); }
section .stats { margin-left: -1.15rem; margin-right: -1.15rem; }
.stat .k { color: var(--ink-muted); font-size: .75rem; font-weight: 500; letter-spacing: .04em; text-transform: uppercase; }
.stat .v { font-size: 1.1rem; font-weight: 600; line-height: 1.3; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.stat .v code { font-size: .9em; }
.stat .n { color: var(--ink-muted); font-size: .78rem; line-height: 1.4; overflow-wrap: anywhere; }

/* ------------------------------------------------------------------ 5. tables: ONE style, for every table in the page */
.scroll, .table-container { overflow-x: auto; }
main table { width: 100%; border-collapse: collapse; font-size: .8438rem; }
main th, main td { padding: .5rem .7rem; border-bottom: 1px solid var(--line); text-align: left; vertical-align: top; }
main th { color: var(--ink-muted); font-size: .72rem; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; white-space: nowrap; }
main tbody tr:last-child td, main table > tr:last-child td { border-bottom: 0; }
main tbody tr:hover td, main table > tr:hover td { background: var(--sunken); }
main table.dense th, main table.dense td { padding: .3rem .55rem; }
.num, main td.num, main th.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
/* a parent strategy's row over its models (Desk > Strategies, task-d41a3a408a): its name, not a column heading */
main tr.group th { color: var(--ink); font-size: .9rem; font-weight: 600; letter-spacing: 0; text-transform: none; white-space: normal; padding-top: 1rem; }
/* a graded reading nested under the row whose test reading covers it (Desk > Strategies, task-64a75f4508): its
   results alone, indented under its row */
main tr.reading td { font-size: .85rem; }
main tr.reading td:first-child { padding-left: 1.6rem; }
/* a table whose columns are numeric FROM the Nth on: an empty `--` cell lines up with the figures without carrying
   a class of its own (a test counts the bare `<td>--</td>` on the yields page) */
table[data-num-from="2"] :is(td, th):nth-child(n+2), table[data-num-from="3"] :is(td, th):nth-child(n+3),
table[data-num-from="4"] :is(td, th):nth-child(n+4) { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
/* the shape of an API's answer, indented by depth. This was an inline style until 2026-09-20, which the site's
   security policy refuses without a word: the indent had never once been drawn on the box. */
main td.depth-0 { padding-left: calc(.3rem + 0 * .9rem); }
main td.depth-1 { padding-left: calc(.3rem + 1 * .9rem); }
main td.depth-2 { padding-left: calc(.3rem + 2 * .9rem); }
main td.depth-3 { padding-left: calc(.3rem + 3 * .9rem); }
main td.depth-4 { padding-left: calc(.3rem + 4 * .9rem); }
main td.depth-5 { padding-left: calc(.3rem + 5 * .9rem); }
main td.depth-6 { padding-left: calc(.3rem + 6 * .9rem); }
main td.depth-7 { padding-left: calc(.3rem + 7 * .9rem); }
main td.depth-8 { padding-left: calc(.3rem + 8 * .9rem); }
td .sub, .sub { display: block; color: var(--ink-muted); font-size: .78rem; }
/* a value no record states, its words in its title, one hover away (Desk > Strategies; task-0ac1711b6c) */
abbr.unread { color: var(--ink-muted); text-decoration: underline dotted; cursor: help; }
td.links { white-space: nowrap; }
/* a trade's date and its time, each one line (desk_trades.html; the owner, 2026-11-12) */
td.when { white-space: nowrap; }
/* a path that can be opened must READ as a control: links carry no underline, and a monospace path in a dense
   table looks like data. The owner found a linked unit file on an item page and reported it as not clickable. */
table.paths a { text-decoration: underline; text-underline-offset: 2px; }
table.paths a .open { text-decoration: none; font-size: .82em; color: var(--ink-muted); margin-left: .35rem; white-space: nowrap; }
/* row state as a left edge: the cutover tasklist and its placeholders */
tr.state-done td:first-child, tr.status-done td:first-child { box-shadow: inset 3px 0 0 var(--ok); }
tr.state-in_progress td:first-child, tr.status-ready td:first-child { box-shadow: inset 3px 0 0 var(--warn); }
tr.state-blocked td:first-child, tr.status-blocked td:first-child { box-shadow: inset 3px 0 0 var(--bad); }

/* ------------------------------------------------------------------ 6. small parts: tag, verb, alert, disclosure, forms */
.tag {
  display: inline-block; margin-left: .35rem; padding: .05rem .55rem; border-radius: var(--r-pill);
  background: var(--sunken); color: var(--ink-muted); font-size: .72rem; font-weight: 600; vertical-align: middle;
  max-width: 100%; overflow-wrap: anywhere;   /* a short tag never wraps; a long one (a component's step list) must, on a phone */
}
.tag.ok { background: var(--ok-soft); color: var(--ok); }
.tag.warn { background: var(--warn-soft); color: var(--warn); }
.tag.bad { background: var(--bad-soft); color: var(--bad); }
.tag.ai { background: var(--brand-soft); color: var(--brand); }
.tag.ai.unread { background: var(--sunken); color: var(--ink-muted); }
.tag.rerun { padding-left: .3rem; padding-right: .3rem; }

/* the hover card (task-7e50e7856d; static/cards.js, console_app/cards.py): any mention carrying data-card shows its
   card on hover, focus or a tap. A mention that is no link says it has one with a dotted underline; a pointer cursor
   also makes a phone's browser send the tap. The card is one surface with a hairline, at most 24rem wide, never wider
   or taller than the screen less its 16 px gutters (a longer one scrolls inside itself) */
[data-card]:not(a) { cursor: pointer; text-decoration: underline dotted var(--ink-muted); text-underline-offset: .2em; }
[data-card]:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; border-radius: 2px; }
.cardpop {
  position: absolute; z-index: 60; width: min(24rem, calc(100vw - 32px)); box-sizing: border-box;
  max-height: calc(100vh - 32px); overflow-y: auto;
  padding: .6rem .75rem; background: var(--surface); color: var(--ink); border: 1px solid var(--line-strong);
  border-radius: var(--r-surface); font-size: .8125rem; line-height: 1.4; overflow-wrap: anywhere;
}
.cardpop[hidden] { display: none; }
.cardpop p { margin: 0; }
.cardpop-head { font-size: .875rem; }
.cardpop-lead { margin-top: .3rem !important; }
.cardpop-rows { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: .15rem .6rem; margin: .5rem 0 0; }
.cardpop-rows dt { color: var(--ink-muted); }
.cardpop-rows dd { margin: 0; }
.cardpop-rows dd.bad { font-weight: 600; }
.cardpop-link { margin-top: .5rem !important; padding-top: .4rem; border-top: 1px solid var(--line); }

/* an alert is for what is BROKEN NOW. It is the one surface allowed a fill, and it overrides Basecoat's grid. */
.alert, section.alert, main.page > section.alert {
  display: block; padding: .9rem 1.2rem; border-radius: var(--r-surface);
  background: var(--bad-soft); color: var(--ink); box-shadow: inset 0 0 0 1px var(--bad), inset 4px 0 0 var(--bad);
}
.alert[data-variant="warn"] { background: var(--warn-soft); box-shadow: inset 0 0 0 1px var(--warn), inset 4px 0 0 var(--warn); }
.alert > * + * { margin-top: .4rem; }
.alert h2 { font-size: 1rem; }
.alert ul { margin: .3rem 0 0; }

/* disclosure: detail lives behind a summary that states the count AND the answer */
details > summary { cursor: pointer; color: var(--ink-muted); font-size: .8438rem; padding: .25rem 0; list-style: none; }
details > summary::-webkit-details-marker { display: none; }
details > summary:not(.openrow)::before {
  content: ""; display: inline-block; width: 0; height: 0; margin: 0 .5rem .08rem .1rem;
  border: .28rem solid transparent; border-left-color: currentColor; transition: transform .12s ease-in-out;
}
details[open] > summary:not(.openrow)::before { transform: rotate(90deg) translateX(.1rem); }
details > summary:hover { color: var(--brand); }
details > :not(summary) { margin-top: .5rem; }

/* "About this page": the explanation a page used to open with, kept word for word behind one disclosure */
details.about { max-width: 60rem; }
details.about > :not(summary) { color: var(--ink-muted); font-size: .875rem; }

/* buttons. Basecoat's reset leaves a bare <button> invisible, so the default is drawn here; .btn is Basecoat's. */
.button, main button:not([class]), main.gate .button {
  display: inline-flex; align-items: center; gap: .4rem; padding: .5rem 1rem; border: 0; border-radius: var(--radius);
  background: var(--brand); color: var(--brand-ink); font: inherit; font-size: .875rem; font-weight: 500; cursor: pointer;
}
.button:hover, main button:not([class]):hover { background: var(--brand-hover); text-decoration: none; }
button.quiet {
  padding: .3rem .75rem; border-radius: var(--radius); background: transparent; color: var(--ink-muted);
  border: 1px solid var(--line-strong); font: inherit; font-size: .8125rem; font-weight: 500; cursor: pointer;
}
button.quiet:hover { background: var(--sunken); color: var(--ink); }

form.pick { display: flex; flex-wrap: wrap; align-items: flex-end; gap: .75rem 1rem; }
form.pick label { display: flex; flex-direction: column; gap: .25rem; color: var(--ink-muted); font-size: .75rem; font-weight: 500; letter-spacing: .03em; }
form.pick label.check { flex-direction: row; align-items: center; gap: .4rem; color: inherit; font-size: .875rem; letter-spacing: 0; }
select, input[type="text"], input[type="search"], input[type="date"], input[type="number"] {
  padding: .4rem .6rem; border: 1px solid var(--line-strong); border-radius: var(--r-input);
  background: var(--surface); color: inherit; font: inherit; font-size: .875rem;
}
input[type="text"] { min-width: 12rem; }
/* a select is as wide as its longest option: on a phone that is wider than the page, so it is held to its label */
select { max-width: 100%; }
form.pick label { min-width: 0; max-width: 100%; }
/* a domain ask's answer on Work (task-a9ca877d8d): his words take the row */
form.answer label.words { flex: 1 1 100%; }
form.answer textarea { width: 100%; box-sizing: border-box; font: inherit; }
/* the knowledge base search (search.py): one wide field; each hit a line of Markdown source, the line before it
   muted above it, wrapped anywhere because a source line can be one long path or table row */
form.kbsearch { margin: 0 0 1rem; }
form.kbsearch label.phrase { flex: 1 1 24rem; }
form.kbsearch label.phrase input { width: 100%; box-sizing: border-box; }
ul.kbhits { list-style: none; margin: .2rem 0 .6rem; padding: 0; }
ul.kbhits li { display: grid; gap: .1rem; padding: .3rem 0; border-top: 1px solid var(--line); overflow-wrap: anywhere; font-size: .85rem; }
p.kbhit-where { margin: .6rem 0 0; }
select:focus-visible, input:focus-visible { outline: 2px solid var(--brand); outline-offset: 0; border-color: var(--brand); }

/* the segmented picker: bar sizes and ranges on the Engine page are the SAME control */
.tf-pick, .range-pick { display: inline-flex; flex-wrap: wrap; gap: 0; border-radius: var(--radius); box-shadow: inset 0 0 0 1px var(--line-strong); overflow: hidden; }
.tf-pick button, .range-pick button {
  padding: .35rem .85rem; min-width: 2.9rem; border: 0; border-right: 1px solid var(--line-strong); border-radius: 0;
  background: transparent; color: var(--ink-muted); font: inherit; font-size: .8125rem; font-weight: 600; font-variant-numeric: tabular-nums; cursor: pointer;
}
.tf-pick button:last-child, .range-pick button:last-child { border-right: 0; }
.tf-pick button:hover, .range-pick button:hover { background: var(--sunken); color: var(--ink); }
.tf-pick button.on, .range-pick button.on { background: var(--brand); color: var(--brand-ink); }
/* Desk > Strategies' stage and source filters (task-0052de484f): links in the pick's shape, the chosen one filled */
.filter-pick { display: flex; flex-wrap: wrap; gap: .35rem; margin: .25rem 0 .75rem; }
.filter-pick a { padding: .3rem .75rem; border-radius: var(--r-pill); box-shadow: inset 0 0 0 1px var(--line-strong);
  color: var(--ink-muted); font-size: .8125rem; font-weight: 600; font-variant-numeric: tabular-nums; text-decoration: none; }
.filter-pick a:hover { background: var(--sunken); color: var(--ink); }
.filter-pick a.on { background: var(--brand); color: var(--brand-ink); box-shadow: none; }

/* ------------------------------------------------------------------ 7. logs and documents */
pre {
  margin: 0; padding: .85rem 1rem; border-radius: var(--radius); background: var(--code-bg); color: var(--code-ink);
  font-size: .78rem; line-height: 1.5; white-space: pre; overflow-x: auto;
}
pre.apibody { max-height: 28rem; overflow: auto; }
/* followed log lines: highlighted as they arrive, fading out over four seconds (step 14). An animation in this
   stylesheet, not an inline style, so the site's security policy allows it. */
@keyframes fresh-fade { from { background-color: var(--fresh); } to { background-color: transparent; } }
pre .fresh { animation: fresh-fade 4s ease-out forwards; }

/* break-word, not anywhere: `anywhere` makes every table column in a document as narrow as ONE character, so a
   step page's header labels read 'Wh / en', 'Ch / an / ge / d' (the owner's screenshot of step 150, 2026-09-21) */
article.doc { padding: 1.5rem 2rem 2rem; overflow-wrap: break-word; max-width: 60rem; }
/* a label/value table -- markdown's `| | |` with an empty header row, the head of every step page -- keeps its labels
   on one line at their own width, and gives the rest to the value column */
article.doc table:has(> thead th:first-child:empty) td:first-child { white-space: nowrap; width: 1%; color: var(--ink-muted); }
article.doc > * + * { margin-top: .8rem; }
article.doc h1 { font-size: 1.45rem; }
article.doc h2 { margin-top: 2rem; padding-top: 1.25rem; border-top: 1px solid var(--line); }
article.doc h3 { margin-top: 1.4rem; }
article.doc p, article.doc li { line-height: 1.6; }
article.doc table { display: block; overflow-x: auto; }
article.doc blockquote { margin: 0; padding: .1rem 0 .1rem 1rem; border-left: 3px solid var(--brand); color: var(--ink-muted); }
article.doc :not(pre) > code { padding: .05rem .3rem; border-radius: 3px; background: var(--sunken); }

/* ------------------------------------------------------------------ 8. charts (server-drawn SVG, and the two canvases) */
.windows { margin: 0; }
.chart-box .legend { font-size: .8125rem; color: var(--ink-muted); }
.swatch { display: inline-block; width: .8rem; height: .2rem; margin: 0 .4rem .2rem 0; vertical-align: middle; border-radius: 2px; }
.swatch.s1 { background: var(--s1); } .swatch.s2 { background: var(--s2); } .swatch.s3 { background: var(--s3); }
.swatch.s4 { background: var(--s4); } .swatch.s5 { background: var(--s5); }
svg.chart { display: block; width: 100%; min-width: 30rem; height: auto; }
svg.chart .grid { stroke: var(--line); stroke-width: 1; }
svg.chart .marker { stroke: var(--bad); stroke-width: 1; stroke-dasharray: 4 4; }
svg.chart .axis { fill: var(--ink-muted); font-size: 11px; font-family: var(--font-sans); }
svg.chart .line { fill: none; stroke-width: 1.6; stroke-linejoin: round; }
svg.chart .line.s1 { stroke: var(--s1); } svg.chart .line.s2 { stroke: var(--s2); } svg.chart .line.s3 { stroke: var(--s3); }
svg.chart .dot.s1 { fill: var(--s1); } svg.chart .dot.s2 { fill: var(--s2); } svg.chart .dot.s3 { fill: var(--s3); }

.engine-chart { position: relative; width: 100%; height: 30rem; }
.runs-chart { position: relative; width: 100%; height: 22rem; }
.engine-controls { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem .75rem; }
.engine-controls.centre { justify-content: center; }
/* under the chart (the owner, 2026-09-18): the ranges on the left, the replay controls centred. The outer columns
   are both 1fr, which is what actually centres the middle one however wide the ranges are. */
.chart-foot { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: .5rem; }
.chart-foot .range-pick { grid-column: 1; justify-self: start; }
.chart-foot .engine-controls.centre { grid-column: 2; justify-self: center; }
/* the chart's title IS the pair picker, and the bar sizes are the buttons under it (the owner, 2026-09-18) */
.chart-nav > * + * { margin-top: .5rem; }
.chart-nav h2 { display: flex; flex-wrap: wrap; align-items: baseline; gap: .4rem; }
.chart-nav h2 select { font-weight: 600; padding: .15rem .4rem; }
.chart-nav h2 .rest { font-weight: 400; color: var(--ink-muted); }
.engine-events li.future { color: var(--ink-muted); }
@media (max-width: 720px) {
  .chart-foot { grid-template-columns: 1fr; }
  .chart-foot .range-pick, .chart-foot .engine-controls.centre { grid-column: 1; justify-self: start; justify-content: flex-start; }
}

/* ------------------------------------------------------------------ 9. a row that opens (the shared primitive, 2026-09-19)
   `details` and `summary` do the opening, so no page needs a script for it; a page sets its own columns on
   `.openrow` and its own body inside `.openbody`. Used by APIs and Services; meant to be used rather than copied. */
.openrow { display: grid; align-items: baseline; gap: .3rem .7rem; padding: .5rem .6rem; border-bottom: 1px solid var(--line); font-size: .8438rem; }
.openrow.head { color: var(--ink-muted); font-size: .72rem; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; }
summary.openrow { cursor: pointer; color: inherit; font-size: .8438rem; }
summary.openrow:hover { background: var(--sunken); color: inherit; }
details[open] > summary.openrow { border-bottom-color: transparent; }
.chev { width: 0; height: 0; margin-top: .15rem; border: .3rem solid transparent; border-left-color: var(--ink-muted); transition: transform .12s ease-in-out; }
details[open] .chev { transform: rotate(90deg); }
/* a closed row inside an open one keeps its own chevron closed (the League's family lists its models, task-1202a57a4b) */
details:not([open]) > summary .chev { transform: none; }
.openbody { padding: .3rem .6rem 1rem 1.9rem; border-bottom: 1px solid var(--line); margin-top: 0; }
.openbody > * + * { margin-top: .6rem; }
.openbody > div:empty { display: none; }
.openbody h3 { font-size: .8438rem; }
.rowlinks { margin: 0; font-size: .8125rem; }

/* the APIs page: one row per route -- method, route, what it answers */
.routes .openrow { grid-template-columns: .9rem 3.9rem minmax(8rem, 17rem) minmax(0, 1fr); }
.rpath { overflow-wrap: anywhere; }
.rwhat { color: var(--ink-muted); }
/* the method, coloured by what it does: green reads, blue writes, amber replaces, red removes */
.verb { justify-self: start; padding: .05rem .4rem; border-radius: 4px; background: var(--sunken); color: var(--ink-muted); font-size: .7rem; font-weight: 700; letter-spacing: .03em; }
.verb.get { background: var(--ok-soft); color: var(--ok); }
.verb.post { background: var(--brand-soft); color: var(--brand); }
.verb.put, .verb.patch { background: var(--warn-soft); color: var(--warn); }
.verb.delete { background: var(--bad-soft); color: var(--bad); }
/* rule 10's tag on a Services row: the same chip, coloured by what the checks found (a reader that can write its
   store is red, one the check could not fully read is amber, a mixed unit is amber by its own admission) */
.verb.warn { background: var(--warn-soft); color: var(--warn); }
.verb.bad { background: var(--bad-soft); color: var(--bad); }
.svcsec { margin-top: 1.4rem; }
/* a session's or the coordinator's words as Markdown (task-b31852c7f9): the page's own type, one step down, so a
   heading in a reply never outranks the card it sits in; code on the logs' dark well; a table in the one table style,
   swiped sideways when it is wider than its card; a flowchart drawn in the page's tokens, never a colour of its own */
.md { white-space: normal; overflow-wrap: break-word; }
.md > :first-child { margin-top: 0; }
.md > :last-child { margin-bottom: 0; }
.md p, .md ul, .md ol, .md blockquote, .md pre, .md figure { margin: .35rem 0; }
.md ul, .md ol { padding-left: 1.3rem; }
.md :is(h1, h2, h3, h4, h5, h6) { font-size: 1rem; font-weight: 600; margin: .6rem 0 .25rem; }
.md pre { padding: .5rem .7rem; overflow-x: auto; border-radius: var(--r-input); background: var(--code-bg); color: var(--code-ink); }
.md pre code { background: none; color: inherit; padding: 0; }
.md blockquote { padding-left: .7rem; border-left: 2px solid var(--line-strong); color: var(--ink-muted); }
.md table { display: block; max-width: 100%; overflow-x: auto; }
.md figure.diagram { overflow-x: auto; }
svg.diagram { display: block; max-width: none; font-family: inherit; }
svg.diagram text { font-size: 13px; }
.diagram-node { fill: var(--surface); stroke: var(--brand); stroke-width: 1.5; }
.diagram-node-line { stroke: var(--brand); stroke-width: 1.5; }
.diagram-label { fill: var(--ink); }
.diagram-edge { fill: none; stroke: var(--ink-muted); stroke-width: 1.5; }
.diagram-edge-dotted { stroke-dasharray: 4 3; }
.diagram-edge-thick { stroke-width: 3; }
.diagram-arrowhead { fill: var(--ink-muted); }
.diagram-edge-label-bg { fill: var(--page); }
.diagram-edge-label { fill: var(--ink-muted); }
.svcsec > h2 .note { font-weight: 400; margin-left: .3rem; }
ul.params { list-style: none; margin: 0; padding: 0; }
ul.params li { display: grid; grid-template-columns: minmax(6rem, 9rem) minmax(8rem, 13rem) minmax(0, 18rem); align-items: center; gap: .3rem .7rem; padding: .18rem 0; font-size: .8125rem; }
ul.params input[type="text"] { width: 100%; min-width: 0; box-sizing: border-box; }
p.submitrow { display: flex; align-items: center; gap: .6rem; margin: 0; }
.htmx-indicator { display: none; }
.htmx-request .htmx-indicator, .htmx-request.htmx-indicator { display: inline; }

/* the Services page: one line a row -- service (with its tag), status, state, at boot, last ran -- as the strategy lists
   are (the owner, 2026-11-08 18:23Z); the unit's file, the note and every fault's words are inside the row */
.svcs .openrow { grid-template-columns: .9rem minmax(0, 1fr) 5.5rem 7rem 4rem 7.5rem; }
.svcspan { grid-column: 3 / -1; }
.svcfacts { margin: .3rem .6rem .2rem 1.9rem; font-size: .8125rem; max-width: 60rem; }
.svcfacts p { margin: .15rem 0; }
.svcfacts .k { color: var(--ink-muted); }
.svcfacts code { font-size: .78rem; }
.svcwhen { display: none; }
.svcnote { margin: .5rem 0 0; }
/* the no-service group under Services (step 153): name and how many files; the files open under it */
.nosvc .openrow { grid-template-columns: .9rem minmax(0, 1fr) auto; }
/* a service's instances, under its heading row (task-3a76f809d7) */
.svcgroup > details.files > summary { background: var(--sunken); }
.svcgroup > details.svc .lgname { padding-left: 1.1rem; }
/* Both markets' Leagues and the stage check (`.league`; the owner's line, task-cfe60c14c6): one line a row, and the rest
   of the row opening under it; a League's own columns are `.league.holds`, below. A cell that runs long is cut with an ellipsis and says it whole on hover. A heading is no wider than
   its column, and cut the same way, never run into the next (task-374be3fa92). `.lglong`/`.lgshort` are a cell's words
   on a desktop and on a phone. */
.league .openrow { grid-template-columns: .9rem 2.4rem minmax(0, 1fr) 4.2rem 4.2rem 5.6rem 6.6rem 4.6rem 4.4rem 6rem 8.6rem; }
.league.unranked .openrow { grid-template-columns: .9rem minmax(0, 1fr) 4.2rem 4.2rem 5.6rem 6.6rem 4.6rem 4.4rem 6rem 8.6rem; }
/* a League's line is its now (league_now, task-0584cc5ce4): rank, name, Runs on, In stage since, % since, USD since,
   Closed, Win rate, Orders today, Today USD, Today %, Open, Open P&L, Account; `.lgmid` leaves a narrow desktop, `.lgwide`
   (Account) a desktop under 90rem, its words in the row's Meta. `.lgactive` keeps only the rows with orders today or
   open now (`data-active`), their families and their stages. */
.league.holds .openrow { grid-template-columns: .9rem 2.4rem minmax(0, 1fr) 4.6rem 6.2rem 4.6rem 5.2rem 3.8rem 3.6rem 5.4rem 6.8rem 6.8rem 3.4rem 5rem 6rem; }
@media (max-width: 90rem) {
  .league.holds .openrow > .lgwide { display: none; }
  .league.holds .openrow { grid-template-columns: .9rem 2.4rem minmax(0, 1fr) 4.6rem 6.2rem 4.6rem 5.2rem 3.8rem 3.6rem 5.4rem 6.8rem 6.8rem 3.4rem 5rem; }
}
/* a League heading longer than its column takes a second line rather than being cut ("In stage / since") */
.league.holds .openrow.head > .lgcut { white-space: normal; }
.league.holds .openrow.head > .num .hl { text-align: right; }
.lgactive .lgstage:not([data-active]), .lgactive .lgrow:not([data-active]), .lgactive div.lgplain, .lgactive details.lghunt { display: none; }
tr.lgphone { display: none; }
/* too narrow for every column (task-a4e19a9a5e): Account and Trading period open in the row (`tr.lgphone`, and its trading period) */
@media (max-width: 64rem) {
  .league .openrow > .lgwide { display: none; }
  .league .lgline .tag[data-league="kept-out"] { display: none; }
  tr.lgphone { display: table-row; }
  .league .openrow { grid-template-columns: .9rem 2.4rem minmax(0, 1fr) 4.2rem 4.2rem 4.6rem 5.6rem 4.6rem 4.4rem; }
  .league.unranked .openrow { grid-template-columns: .9rem minmax(0, 1fr) 4.2rem 4.2rem 4.6rem 5.6rem 4.6rem 4.4rem; }
  .league.holds .openrow > .lgmid { display: none; }
  .league.holds .openrow { grid-template-columns: .9rem 2.4rem minmax(0, 1fr) 4.6rem 6.2rem 4.6rem 5.4rem 6.8rem 3.4rem 5rem; }
}
.lgshort { display: none; }
/* a heading that sorts (table_sort, task-d918719cbb): the whole cell the link, its arrow beside a label that is cut first */
.openrow.head a.hs { display: flex; align-items: baseline; min-width: 0; color: inherit; touch-action: manipulation; }
.openrow.head a.hs:hover, .openrow.head a.hs.on { color: var(--ink); }
.openrow.head a.hs:hover { text-decoration: none; }
.openrow.head .num a.hs { justify-content: flex-end; }
.openrow.head a.hs .hl { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.openrow.head a.hs .ha { flex: none; margin-left: .2em; }
/* a row a Strategies link lands on (/desk/league#league-<id>, task-dc5d6fd626) stands below the sticky header */
.lgrow, .league.unranked .openrow, .lgnot .openrow { scroll-margin-top: 4.5rem; }
.league.stagecheck .openrow { grid-template-columns: .9rem minmax(0, 1fr) 4.2rem 4.2rem 4.2rem 4.2rem 4.2rem; }
/* a stage the reading did not check: its word wraps inside the column ("not / checked") */
.league.stagecheck .openrow > .num.state { white-space: normal; overflow-wrap: anywhere; line-height: 1.15; }
/* a row's name: its short name cut first (an overlay row would read as its base), then its overlay, its tags never */
.lgname { min-width: 0; overflow: hidden; }
.lgline { display: flex; align-items: baseline; column-gap: .4rem; min-width: 0; }
.lgline > .lgcut { flex: 0 1000 auto; }
.lgline > :not(.lgcut) { flex: none; white-space: nowrap; }
.lgline > .lgov { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
/* an AI version's name (task-abe6e1e744; the owner, 2026-11-10: "where does it say which ai filters?"): its filter's
   own name, then "on" the strategy it is laid over, onto further lines where it needs them, at most four */
.lgline > .lgwrap { flex: 0 1 auto; min-width: 0; overflow: hidden; white-space: normal; overflow-wrap: break-word;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 4; line-clamp: 4; }
.lgon { color: var(--ink-muted); }
/* a League row's name is read whole (the owner, 2026-11-12: "the title of the startegies cant be rid as its getting cut
   off"): it takes the row's first line from its own column to the end, wrapping where it must (at most three lines), and
   the row's figures stand on the line under it, each in its column; the whole name stays on hover */
.league.holds .openrow:not(.head):not(.lgplain) > .lgname { grid-column: 3 / -1; }
.league.holds .openrow:not(.head):not(.lgplain) > [data-league="runs-on"] { grid-column-start: 4; }
.league.holds .lgname .lgline > .lgcut, .league.holds .lgname .lgline > .lgov, .league.holds .openrow.lgplain > .lgname {
  white-space: normal; overflow-wrap: anywhere; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3;
  line-clamp: 3; }
/* Desk › League's path to live (task-fa17132d0f): one line a card, its label muted beside it */
ul.pathlines { margin: .5rem 0 0; padding: 0; list-style: none; }
ul.pathlines > li { padding: .4rem 0; }
ul.pathlines > li + li { border-top: 1px solid var(--line); }
ul.pathlines .bad a { color: inherit; }
ul.pathlines .k { display: inline-block; min-width: 9.5rem; color: var(--ink-muted); font-size: .8125rem; }
.lgcut { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.league .openrow .note { font-size: inherit; }
.lgfacts th { width: 16rem; white-space: normal; text-transform: none; letter-spacing: 0; font-size: .78rem; }
.lgfold { margin-top: .8rem; }
/* League's rows the engine did not make (task-1f5a33d63a): a name, then "not ran on engine", one line a row */
.lgnot .openrow { grid-template-columns: .9rem minmax(0, 1fr) auto; }
/* One League a market (task-1202a57a4b, the owner's own design): a group a stage; a family's row opens to its best's three
   closed parts (Returns, Latest and open orders, Meta; task-f359164f46), then its other models, each a row of the same
   columns, its name set in, opening to its own three, a Returns part a closed part a record (task-9c6af014a0). So the League alone goes three
   disclosures deep, four to a Returns table, against § 4 rule 5, on his word. A row with no League row is
   its name and a note (`.lgplain`). */
.lgn { flex: none; color: var(--ink-muted); font-size: .78rem; }
.lgmembers { margin-top: 0; border-bottom: 1px solid var(--line-strong); }
/* a member's open/close arrow moves in with its name, a level a step (the owner, 2026-11-10: "can you also indent the
   collapsable icon when we are in the child branches?"; task-f001ff41b7): the arrow's column keeps its width, the arrow
   stands into the gap after it, so nothing widens */
.lgmembers .lgname { padding-left: .9rem; }
.lgmembers .openrow > .chev { margin-left: .9rem; }
.lgmembers .lgmembers .lgname { padding-left: 1.8rem; }
.lgmembers .lgmembers .openrow > .chev { margin-left: 1.8rem; }
.league.holds .openrow.lgplain { grid-template-columns: .9rem minmax(0, 1fr) minmax(0, 22rem); }
details.lgpart { margin-top: .4rem; }
/* a model's Returns table, a block a record and a column a window (task-0931921079), and its orders' three tables
   (task-5d2271b8d4): each swiped sideways on a phone, its first column pinned (§ 4.2) */
h4.lgsub { margin: .7rem 0 .25rem; font-size: .8125rem; font-weight: 600; }
h4.lgsub[data-league="open-now"] { scroll-margin-top: 4.5rem; }
h4.lgsub .sub { display: inline; margin-left: .4rem; color: var(--ink-muted); font-weight: 400; }
/* a Returns block a closed part, its answer on its summary (task-9c6af014a0; the owner, 2026-11-11: "Can you make
   these collapsable as well ?"): a fourth level inside a family's other models, on his word */
details.lgretpart { margin-top: .45rem; }
details.lgretpart > summary { font-size: .8125rem; font-weight: 600; }
details.lgretpart > p.note { margin: .3rem 0 .25rem; }
table.lgret-t th, table.lgret-t td, table.lgorders th, table.lgorders td { white-space: nowrap; }
table.lgret-t tbody th { text-transform: none; letter-spacing: 0; }
details.lgpart > summary { font-size: .8438rem; font-weight: 600; }
/* a hunt family's Hunt rules part under its models (task-374e53617b): its rule keys run past 100 characters and
   differ in the middle, so the pinned first column wraps them whole; its arrow stands level with its family's members'
   arrows (a row's .6rem padding, then the member's .9rem step; task-f001ff41b7) */
.lgmembers > details.lghunt { margin: .4rem 0 .6rem 1.5rem; }
table.lghunt-t tbody th { white-space: normal; overflow-wrap: anywhere; min-width: 12rem; max-width: 24rem; font-size: .75rem; }
@media (max-width: 46rem) { table.lghunt-t tbody th { min-width: 10rem; max-width: 10rem; } }
details.lgpart > table { margin-top: .3rem; }
.lgstage { scroll-margin-top: 4.5rem; }
.lgstage + .lgstage { margin-top: 1.2rem; }
/* a model's flow on its strategy's page (task-2ebef895fb): one column of steps, top to bottom, an arrow between, so it
   reads on a phone; each step a well inside its section, never a card */
ol.flow { list-style: none; margin: .5rem 0 .75rem; padding: 0; }
ol.flow > li { border: 1px solid var(--line-strong); border-radius: .5rem; padding: .5rem .75rem; background: var(--sunken); }
ol.flow > li + li { position: relative; margin-top: 1.6rem; }
ol.flow > li + li::before { content: "\2193"; position: absolute; top: -1.45rem; left: 50%; transform: translateX(-50%);
  color: var(--ink-muted); }
ol.flow .k { display: block; color: var(--ink-muted); font-size: .8125rem; font-weight: 600; }
ol.flow ul { margin: .2rem 0 0; padding: 0; list-style: none; }
ol.flow ul li, ol.rulelist li { overflow-wrap: anywhere; }
ol.rulelist { margin: .5rem 0 0; padding-left: 1.5rem; }
ol.rulelist > li + li { margin-top: .4rem; }
/* Desk > Strategies' and its Statistics' folds: few trades, and not ran on engine (task-1f5a33d63a) */
.poolfold { margin-top: .8rem; }
/* Desk > Strategies: each strategy's closed section, the period it was tested on and what its model uses, as pills
   that wrap inside the row's width (the owner, 2026-10-04 ~03:35Z; task-d1669062e8); Desk > Data > Adapters' model
   pills are the same */
details.uses > summary { font-size: .75rem; padding: .15rem 0; }
details.uses > dl { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: .3rem .6rem; margin: .35rem 0 .2rem;
  font-size: .78rem; }
details.uses dt { color: var(--ink-muted); }
details.uses dd { margin: 0; min-width: 0; overflow-wrap: break-word; }
/* a row's own engine runs, graded readings or replays in its closed section, and the tests over several strategies in
   the page's meta (task-0541d99bc1) */
ul.lines, ul.lines ul { margin: 0; padding-left: 1.1rem; }
ul.pills { display: flex; flex-wrap: wrap; gap: .3rem; margin: 0; padding: 0; list-style: none; }
ul.pills > li { min-width: 0; max-width: 100%; }
.pill { display: inline-block; max-width: 100%; padding: .05rem .55rem; border-radius: var(--r-pill);
  box-shadow: inset 0 0 0 1px var(--line-strong); font-size: .75rem; overflow-wrap: break-word; }
a.pill:hover { box-shadow: inset 0 0 0 1px var(--brand); text-decoration: none; }
.pill.ai { background: var(--brand-soft); }
.pill.nopage { color: var(--ink-muted); box-shadow: inset 0 0 0 1px var(--line); }
.why { color: var(--ink-muted); }
section.adapter table.facts th { width: 7rem; }
/* Desk › Quotes and ideas (task-40f281135d): each item's words large and plain on the page, what came of it a muted
   line under them; no surface, no rule, no quote marks */
ol.quotes { margin: 1.5rem 0 0; padding: 0; list-style: none; }
ol.quotes > li + li { margin-top: 2.25rem; }
ol.quotes blockquote { margin: 0; padding: 0; border: 0; }
ol.quotes blockquote p { margin: 0; color: var(--ink); font-size: 1.45rem; line-height: 1.45; }
ol.quotes p.came { margin: .6rem 0 0; color: var(--ink-muted); font-size: .8125rem; }

@media (max-width: 46rem) {
  ol.quotes blockquote p { font-size: 1.15rem; }
  .routes .openrow { grid-template-columns: .9rem 3.9rem minmax(0, 1fr); }
  .rwhat { grid-column: 2 / -1; }
  .routes .openrow.head span:last-child { display: none; }
  ul.params li { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  ul.params li input[type="text"] { grid-column: 1 / -1; }
  /* Services at 375 px: the name takes what status and state leave, each as wide as its longest word (`inactive`, `standby`;
     a `ch` here measures narrower than the glyphs); at boot and last ran are the row's own line inside it, never a column to swipe to */
  .svcs .openrow { grid-template-columns: .9rem minmax(0, 1fr) 3.7rem 3.7rem; font-size: .66rem; gap: .1rem .3rem; padding-left: .2rem; padding-right: .2rem; }
  .svcs .openrow > :nth-child(n+5) { display: none; }
  .svcs .openrow .note, .svcs .openrow .verb { font-size: inherit; padding: 0 .25rem; }
  .svcspan { grid-column: 2 / -1; }
  .svcwhen { display: block; }
  /* the league's and strategies' rows at 375 px: the name takes what the six columns leave, no rank, every column on
     the one line in its short words, each as wide as its longest value (the face is monospaced, so a `ch` is a
     character), the page never swiped sideways (task-cfe60c14c6; the owner, 2026-09-20, 2026-10-03). The list stands
     out over its section's padding, so the columns have the width */
  .league { margin-left: -1rem; margin-right: -1rem; }
  .league .openrow, .league.unranked .openrow { font-size: .66rem;
    grid-template-columns: .35rem minmax(0, 1fr) 6ch 6ch 6ch 6ch 6ch 7ch; gap: .1rem .18rem; padding: .55rem .2rem; }
  /* the now on a phone, in dollars (the owner, 2026-11-11: "p&l since it went into the stage is better for mobile view",
     "Instead of percent put dollar value"; task-50faa1669d): name, Runs, Since (days), P&L (USD since), Win, Ord, Today
     (USD), Op; `.lgph` comes back from `.lgmid`, `.lgdesk` (% since, Today %, Open P&L) leaves; the rest in the row's
     Returns part */
  .league.holds .openrow > .lgph { display: block; }
  .league.holds .openrow > .lgdesk { display: none; }
  .league.holds .openrow { grid-template-columns: .35rem minmax(0, 1fr) 7ch 5ch 7ch 4ch 3ch 12ch 3ch; }
  .league .openrow.head { font-size: .66rem; letter-spacing: 0; text-transform: none; padding-top: 0; padding-bottom: 0; }
  /* a heading's tap target fills its row: the row's own padding moved onto the link */
  .league .openrow.head a.hs { padding: .55rem 0; }
  .league .openrow.head a.hs .hl { text-overflow: clip; }
  .league .openrow.head a.hs .ha { margin-left: 0; }
  .league .openrow > .lgrank { display: none; }
  .league.holds .openrow.lgplain { grid-template-columns: .35rem minmax(0, 1fr) minmax(0, 45%); }
  .lgmembers .lgname { padding-left: .45rem; }
  .lgmembers .openrow > .chev { margin-left: .45rem; }
  .lgmembers .lgmembers .lgname { padding-left: .9rem; }
  .lgmembers .lgmembers .openrow > .chev { margin-left: .9rem; }
  .lgmembers > details.lghunt { margin-left: .65rem; }
  /* an AI version's name takes its row's first line whole, its figures the second, each in its column (task-abe6e1e744) */
  .league .openrow.lgai > .lgname { grid-column: 2 / -1; }
  .league .openrow.lgai > [data-league="runs-on"] { grid-column-start: 3; }
  /* every League name the same, its first line whole, its figures under it (the owner, 2026-11-12) */
  .league.holds .openrow:not(.head):not(.lgplain) > .lgname { grid-column: 2 / -1; }
  .league.holds .openrow:not(.head):not(.lgplain) > [data-league="runs-on"] { grid-column-start: 3; }
  .league .openrow .note { font-size: inherit; }
  .league .lgcut { text-overflow: clip; }
  .league .lgline > .lgcut { text-overflow: ellipsis; }
  .league .lgline .tag:not(.ai):not(.rerun) { display: none; }
  /* the stage check at 375 px: the name, the four stages' trades, the flag's words; a day's trades in the fold (task-cf85cfa883) */
  .league.stagecheck .openrow { grid-template-columns: .35rem minmax(0, 1fr) 5ch 5ch 7ch 7ch 9ch; }
  main table.stagetrade { display: table; width: 100%; }
  main table.stagetrade tr { display: table-row; }
  main table.stagetrade tr > :first-child { position: static; box-shadow: none; background: transparent; }
  main table.stagetrade th, main table.stagetrade td { display: table-cell; width: auto; min-width: 0; font-size: .66rem; letter-spacing: 0; text-transform: none; padding: .25rem .2rem; white-space: nowrap; }
  .league .lgline .tag.ai, .league .lgline .tag.rerun { margin-left: 0; padding: 0 .3rem; line-height: 1.15; }
  .lglong { display: none; }
  .lgshort { display: inline; }
  ul.pathlines .k { display: block; min-width: 0; }
  .lgfacts th { width: 8rem; }
  main.page > section, main.page > .kbkind > section, main.page > form.sections > section { padding: 1rem 1rem 1.15rem; }
  section .stats { margin-left: -1rem; margin-right: -1rem; }
  /* every table scrolls inside itself on a phone, whether or not its page wrapped it in .scroll */
  main table { display: block; overflow-x: auto; }
  input[type="text"] { min-width: 0; max-width: 100%; }

  /* ---- the phone (the owner, 2026-09-20: "i will be checking it while i am on the road") ---- */
  /* the bar: three things on one line, none of them wrapping */
  header.top { gap: .5rem; padding: .5rem .75rem; }
  /* the nav bar gives way to one Menu button; its panel spans the header, links two to a line under each group */
  header.top .navbar { display: none; }
  header.top .navphone { display: block; flex: 1; }
  header.top .navphone > summary { display: inline-block; padding: .35rem .7rem; }
  header.top:has(> .navphone[open]) > .navpanel { display: block; position: absolute; left: 0; right: 0; top: 100%; z-index: 6; box-sizing: border-box;
    max-height: calc(100vh - 3rem); overflow-y: auto; padding: .5rem .75rem 1rem; background: var(--surface);
    border-bottom: 1px solid var(--line-strong); }
  header.top .navpanel .navhead { margin: .7rem 0 .15rem; font-size: .75rem; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; }
  header.top .navpanel .navhead a { display: inline; padding: 0; color: var(--ink-muted); }
  header.top .navpanel ul { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .1rem .5rem; margin: 0; padding: 0; list-style: none; }
  header.top .navpanel a { padding: .55rem .6rem; }
  header.top button.quiet { white-space: nowrap; padding: .3rem .55rem; }
  main.page { width: calc(100% - 1.5rem); margin-top: 1rem; }
  h1 { font-size: 1.25rem; }
  /* a table on a phone is swiped sideways: a column keeps a readable width instead of folding a date into four
     lines, and the FIRST column stays pinned so the row still says what it is while the rest goes by */
  main td, main th { min-width: 6.5rem; }
  main td.num, main th.num, main td:empty { min-width: 3.5rem; }
  main table tr > :first-child { position: sticky; left: 0; z-index: 1; background: var(--surface); box-shadow: 1px 0 0 var(--line); }
  main tbody tr:hover > :first-child, main table > tr:hover > :first-child { background: var(--sunken); }
  article.doc td, article.doc th { min-width: 5rem; }
  /* filters sit two to a line, the button under them */
  form.pick { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .6rem .75rem; align-items: end; }
  form.pick label.check, form.pick button, form.kbsearch label.phrase { grid-column: 1 / -1; justify-self: start; }
  /* a fieldset (the model editor's lines, gates, portfolio, overlays) and a note take the whole width, never one cell */
  form.pick > fieldset, form.pick > p { grid-column: 1 / -1; min-width: 0; }
  /* a button with a link beside it (the news page's Show and Reset) takes a line of its own, as a lone button does */
  form.pick > .actions { grid-column: 1 / -1; }
  form.kbsearch label.phrase { justify-self: stretch; }
  form.pick select, form.pick input:not([type="checkbox"]) { width: 100%; box-sizing: border-box; }
  /* iOS zooms the whole page when a field under 16px takes focus, and does not zoom back */
  select, input[type="text"], input[type="search"], input[type="date"], input[type="number"], ul.params input[type="text"] { font-size: 16px; }
  /* a finger is wider than a cursor: what opens and what navigates gets a taller target */
  details > summary { padding: .55rem 0; }
  main button.copyid, main a.goto, main button.goto { padding: .35rem .7rem; }
  summary.openrow { padding: .7rem .4rem; }
  .jump a, .jump strong, .jump span { padding: .4rem .75rem; }
  .crumbs { font-size: .875rem; line-height: 2; }
  .tf-pick button, .range-pick button { padding: .55rem .3rem; min-width: 2.35rem; font-size: .78rem; }
  .tf-pick, .range-pick { flex-wrap: nowrap; max-width: 100%; }
  .openbody { padding-left: .6rem; }
  .svcfacts { margin-left: .6rem; }
  .engine-chart { height: 22rem; }
  .runs-chart { height: 16rem; }
  .stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .stat { padding: .7rem .85rem; }
  .tiles { grid-template-columns: 1fr; gap: .6rem; }
  article.doc { padding: 1rem 1rem 1.25rem; }

  /* a table that stacks on a phone (task-6435e13b8e; the owner, 2026-10-03 ~13:11Z, from his phone: "can we improve
     this so that I can see more of the results data on a mobile device ?"): Statistics, Pipelines, the horizon map and
     League's power table. No table swiped sideways: each row is a block, its name (`.name`) on a line of its own,
     then the figures it is decided on (`.key`), then, small, the rest. No cell is hidden but an empty one. A cell's heading is its `data-h`,
     drawn before its value, and a value in words takes a colon ("SE: not measured"); the heading row (`tr.head`) is
     not drawn. The template marks each cell, so a column moved on the desktop moves on the phone with it; each page's
     test pins its cells' headings and which are its figures. */
  main table.stack, main table.stack > :is(thead, tbody) { display: block; overflow-x: visible; }
  main table.stack tr { display: flex; flex-wrap: wrap; align-items: baseline; gap: .2rem .45rem; padding: .6rem 0;
    border-bottom: 1px solid var(--line); }
  main table.stack tr.head { display: none; }
  main table.stack tr.reading { padding-left: 1.2rem; }
  main table.stack tr > :is(th, td) { display: block; order: 3; min-width: 0; padding: 0; border: 0; position: static;
    box-shadow: none; background: none; text-align: left; white-space: normal; overflow-wrap: break-word; }
  /* line 1: the name */
  main table.stack tr > .name { order: 0; flex: 0 0 100%; color: var(--ink); font-size: .875rem; font-weight: 600;
    letter-spacing: 0; text-transform: none; }
  /* line 2: the figures; then, small, the rest */
  main table.stack tr > .key { order: 1; }
  main table.stack tr::after { content: ""; order: 2; flex: 0 0 100%; height: 0; }
  main table.stack tr > :not(.name, .key) { color: var(--ink-muted); font-size: .75rem; }
  main table.stack tr > :is(th, td) span.sub { display: inline; margin-left: .3rem; font-size: inherit; }
  main table.stack tr > [data-h]::before { content: var(--dot, "") attr(data-h) var(--colon, "") "\00a0"; color: var(--ink-muted); }
  main table.stack tr > [data-h=""]::before { content: var(--dot, none); }
  main table.stack tr > .key ~ .key, main table.stack tr > :not(.name, .key) ~ :not(.name, .key) { --dot: "·\00a0"; }
  main table.stack tr > :has(> .note:first-child) { --colon: ":"; }
  main table.stack tr > td:empty { display: none; }
  /* the market labels (task-c022b1f322): each road and the text label a line of its own, their figures under them */
  main table.stack.mlabels tr > td.key { flex: 0 0 100%; color: var(--ink); font-size: .8125rem; --dot: ""; }
  main table.stack.mlabels tr > td.key span.sub { display: block; margin-left: 0; font-size: .75rem; }

  /* a table of label-value pairs stacks on a phone (`table.pairs`: each row one th that names it and one td that holds
     its value; task-9bdd696aa0): each row is its label, small, over its value, the whole width, nothing swiped. Swiped
     with its label pinned and held to one line, a long label (a strategy page's "Is it still being tested?" naming
     B33 B1's version 3 by its title) pushed every value off a 375 px screen, and a long value (a path in Meta) was cut
     at its edge. The strategy page's Is it still being tested? and Its rule carry it, and Meta on every page. */
  main table.pairs, main table.pairs > tbody { display: block; overflow-x: visible; }
  main table.pairs tr { display: block; padding: .5rem 0; border-bottom: 1px solid var(--line); }
  main table.pairs tr > :is(th, td) { display: block; min-width: 0; padding: 0; border: 0; position: static;
    box-shadow: none; background: none; white-space: normal; overflow-wrap: anywhere; }
  main table.pairs tr > th { margin-bottom: .15rem; }
}

/* ------------------------------------------------------------------ 10. the chart library's own tables are not the console's tables
   Lightweight Charts lays a chart out with <table>, <tr> and <td>. "Every table in the page is the one table style" is
   a structural rule, so it reached INSIDE the charts: cell padding and rules on a desktop, and on a phone a minimum
   column width and a pinned first column that squeezed the plot and gave it a scrollbar (seen 2026-09-20 in a phone
   frame). A widget is isolated, not restyled: !important because these must beat every table rule above, whatever
   its specificity becomes. */
main :is(.engine-chart, .runs-chart) table { display: table !important; width: auto !important; overflow: visible !important; font-size: inherit; }
main :is(.engine-chart, .runs-chart) table tr > * {
  padding: 0 !important; border: 0 !important; min-width: 0 !important; position: relative !important; left: auto !important;
  background: none !important; box-shadow: none !important; letter-spacing: normal; text-transform: none; white-space: normal;
}
/* Console > Work (task-0e077aa40c, task-da3b4e5d61): each group of open tasks a card, its heading the disclosure's
   summary; each task under it a heading of its own, its facts in the page's own size and colour, and a question that
   waits on him inside it, one step in behind one hairline, its options a list with what each entails under it */
#work > .taskgroup summary > h2 { display: inline; font-size: 1.25rem; }
#work .task { padding-top: .75rem; border-top: 1px solid var(--line); scroll-margin-top: 4.5rem; }
#work .task > * + * { margin-top: .45rem; }
h3.tasktitle { margin: 0; font-size: 1.05rem; font-weight: 600; }
h3.tasktitle .taskid { margin-left: .35rem; color: var(--ink-muted); font-size: .75rem; font-weight: 400; }
p.taskfacts { margin: 0; }
.taskitems { margin-left: .4rem; padding-left: .9rem; border-left: 1px solid var(--line-strong); }
.question h4 { margin: 0; font-size: 1rem; }
.question > * + * { margin-top: .6rem; }
ul.options { margin: .5rem 0 0; padding-left: 1.1rem; }
ul.options li + li { margin-top: .4rem; }
ul.options .choice-mark { color: var(--brand); font-weight: 600; }
.question:target { outline: 2px solid var(--brand); outline-offset: .4rem; }
/* every task id's Copy button (task-b0d3df05c4, task-3cb77b8841): small and quiet beside the id it copies */
button.copyid { padding: .05rem .45rem; margin-left: .4rem; font-size: .75rem; line-height: 1.4; vertical-align: baseline; }
/* GOTO beside an id (task-b3c0a0bdc3): a link drawn as the Copy button is, opening its holder's terminal in a new tab,
   or the coordinator's, "Ask the coordinator", when that session has no live window (task-d92e0c7203); off (no
   address, dashed) when the coordinator's own window is not live */
a.goto {
  display: inline-block; padding: .05rem .45rem; margin-left: .4rem; border: 1px solid var(--line-strong);
  border-radius: var(--radius); color: var(--ink-muted); font-size: .75rem; font-weight: 500; line-height: 1.4;
  text-decoration: none; vertical-align: baseline;
}
a.goto[href]:hover { background: var(--sunken); color: var(--ink); text-decoration: none; }
a.goto.off { border-style: dashed; cursor: not-allowed; }
details.tasklist > summary { cursor: pointer; }
details.tasklist[open] > summary { margin-bottom: .45rem; }
/* Console > Terminals (task-aa4154b11a): a session's terminal, view-only. xterm draws on a canvas at the window's own
   size, its font scaled so the width fits; its box is the code block's, dark in both themes, and the terminal reads
   the same two tokens for its own background and text */
.terminal-screen { overflow-x: auto; padding: .5rem; background: var(--code-bg); border-radius: var(--r-surface); }
.terminal-loop > * + * { margin-top: var(--gap); }
/* the domain sessions (task-e5d9cd0e82): a row a domain, its Start button beside its state; on a phone each row is its
   button, the whole width and at least 44 px tall, over its state */
.domain-rows { display: grid; gap: .5rem; margin: .75rem 0; padding: 0; list-style: none; }
.domain-rows li { display: flex; flex-wrap: wrap; align-items: center; gap: .35rem .75rem; }
.domain-rows form, .domain-rows .state { margin: 0; }
.domain-rows button, .domain-all button { min-height: 44px; }
@media (max-width: 46rem) {
  .domain-rows li { display: block; }
  .domain-rows button, .domain-all button { width: 100%; }
  .domain-rows .state { margin-top: .25rem; overflow-wrap: anywhere; }
}
/* the terminal that takes the keys: one at a time, the one clicked */
.terminal:focus-within .terminal-screen { outline: 2px solid var(--brand); outline-offset: 2px; }

/* Desk > Data > Central banks > Timeline (task-64fec52653; the owner, 2026-10-08). stance_timeline.js draws the rows on
   one canvas that sticks to the left of its scroll box while a spacer as wide as the axis gives the box its scroll, so
   every row moves together; the names column is outside the box, so it stays. The script places each row where its
   name sits here, measured: these heights are the only place the rows' sizes are set. Colours are the tokens above,
   which the script reads as --stl-*. */
.stl {
  --stl-uncertain: var(--ink-muted); --stl-ink: var(--ink); --stl-muted: var(--ink-muted); --stl-line: var(--line);
  --stl-surface: var(--surface); --stl-today: var(--brand); --stl-gap: var(--line-strong);
}
.stl-bar { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem; }
.stl-zoom { display: inline-flex; flex-wrap: wrap; gap: .25rem; }
.stl-bar button { padding: .2rem .55rem; font-size: .8rem; }
.stl-zoom button[aria-pressed="true"] { background: var(--brand-soft); color: var(--brand); border-color: var(--brand); }
.stl-frame { display: grid; grid-template-columns: 5.5rem minmax(0, 1fr); margin-top: .4rem; }
.stl-names { font-size: .72rem; line-height: 1; }
.stl-axis-pad { height: 22px; }
.stl-bank { height: 18px; padding-top: 6px; font-weight: 600; white-space: nowrap; }
.stl-row { height: 18px; display: flex; align-items: center; color: var(--ink-muted); white-space: nowrap; overflow: hidden; }
.stl-scroll { overflow-x: auto; overflow-y: hidden; overscroll-behavior-x: contain; }
.stl-spacer { position: relative; }
.stl-canvas { position: sticky; left: 0; display: block; cursor: pointer; }
.stl-sheet {
  position: sticky; bottom: .5rem; z-index: 2; margin-top: .5rem; padding: .6rem .8rem; background: var(--surface);
  border: 1px solid var(--line-strong); border-radius: var(--r-surface);
}
.stl-sheet .stl-close { float: right; padding: .1rem .5rem; }
.stl-sheet h3 { font-size: .9rem; margin-bottom: .35rem; }
.stl-sheet table th { width: 6.5rem; }
.stl-opening { color: var(--ink-muted); font-size: .75rem; margin: .4rem 0 0; }
.stl-next, .stl-warn { list-style: none; padding: 0; margin: .6rem 0 0; font-size: .8rem; }
.stl-legend { display: flex; flex-wrap: wrap; gap: .25rem .9rem; margin-top: .6rem; color: var(--ink-muted); font-size: .75rem; }
.stl-legend .sw { display: inline-block; width: .7rem; height: .7rem; margin-right: .3rem; vertical-align: -1px; border-radius: 2px; }
.stl-legend .sw.hawkish { background: var(--stl-hawkish); }
.stl-legend .sw.neutral { background: var(--stl-neutral); }
.stl-legend .sw.dovish { background: var(--stl-dovish); }
.stl-legend .sw.uncertain, .stl-legend .sw.gap {
  background: repeating-linear-gradient(135deg, var(--stl-gap) 0 2px, transparent 2px 5px); border: 1px solid var(--stl-gap);
}
.stl-legend .sw.good { background: var(--stl-good); }
.stl-legend .sw.bad { background: var(--stl-bad); }
.stl-legend .sw.flip { width: 2px; border-radius: 0; background: var(--stl-ink); }
.stl-legend .sw.hindsight { width: 0; border-radius: 0; border-left: 2px dashed var(--stl-muted); }
/* the model editor's run bar and player (task-e424dfcdbe): the controls stick to the screen's foot on a phone, each
   at least 44 px, and the player's orders scroll in their own box with the one at the playhead marked */
.run-bar { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem .75rem; margin: .5rem 0; }
.run-bar input[type="date"], .run-bar select, .run-bar button { min-height: 44px; }
.player { position: sticky; bottom: 0; z-index: 2; display: flex; flex-wrap: wrap; align-items: center; gap: .4rem .6rem;
  margin: .5rem 0; padding: .5rem; background: var(--surface); border-top: 1px solid var(--line); }
.player button, .player select { min-height: 44px; min-width: 44px; }
/* the model editor's five pages (task-492418c391): the steps in each page's header, a step not reached yet said, not
   linked; a row of buttons, a link one as quiet as a quiet button; the Edit page's bar at the screen's foot, its Check
   and Save draft at least 44 px, over the whole page as it scrolls */
.jump span { padding: .15rem .6rem; border-radius: var(--r-pill); color: var(--ink-muted); }
.actions { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem .75rem; }
.actions .button, .actions button, .checkbar button { min-height: 44px; }
a.button.quiet { background: transparent; color: var(--ink-muted); box-shadow: inset 0 0 0 1px var(--line-strong); }
a.button.quiet:hover { background: var(--sunken); color: var(--ink); }
.checkbar { position: sticky; bottom: 0; z-index: 3; display: flex; flex-wrap: wrap; align-items: center; gap: .4rem .75rem;
  padding: .6rem .8rem; background: var(--surface); border-top: 1px solid var(--line-strong); }
.checkbar .line { margin: 0; flex: 1 1 16rem; font-size: .875rem; }
.checkbar form { margin: 0; }
/* the Edit page's form: each fieldset a grid of fields, a label over its input as form.pick draws one, one column on a
   phone; a note, a table or a fieldset inside spans the row */
form.sections fieldset, .group.fields { display: grid; grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr));
  gap: .75rem 1rem; align-items: end; }
form.sections fieldset > :not(label, .field) { grid-column: 1 / -1; }
.field { display: flex; flex-direction: column; gap: .35rem; }
form.sections label, .group.fields label { display: flex; flex-direction: column; gap: .25rem; color: var(--ink-muted);
  font-size: .75rem; font-weight: 500; letter-spacing: .03em; }
form.sections label:has(> input[type="checkbox"]) { flex-direction: row; align-items: center; gap: .4rem; color: inherit;
  font-size: .875rem; letter-spacing: 0; }
form.sections input[type="text"] { min-width: 0; width: 100%; box-sizing: border-box; }
/* a parameter's name carries its card (task-b3cbd6687e; cards.js shows it on a hover, a focus or a tap): marked as one */
.pname { text-decoration: underline dotted; text-underline-offset: .2em; cursor: help; }
.pname::after { content: " \24D8"; font-size: .85em; opacity: .55; }
/* a value is shown whole (the owner, 2026-10-10: "these parameter are in a small input box and hard to read"): a list of
   pairs as a chip a pair, every pair at once; a list, an object or a long text in a box as tall as it, the row's width */
form.sections label.area, .field:has(> label.area), .field:has(> fieldset.chips) { grid-column: 1 / -1; }
form.sections textarea { width: 100%; min-width: 0; box-sizing: border-box; padding: .4rem .6rem; font: inherit;
  font-size: .8125rem; color: var(--ink); border: 1px solid var(--line-strong); border-radius: var(--r-input);
  background: var(--surface); resize: vertical; overflow-wrap: anywhere; field-sizing: content; }
form.sections fieldset.chips { display: flex; flex-direction: row; flex-wrap: wrap; align-items: center;
  justify-content: flex-start; gap: .35rem; }
/* a portfolio field (a .field: its box and its Switch off) reads left to right as a line's params do, its box the
   field's width (basecoat's .field centres a label's children) */
form.sections .field > label:not(:has(> input[type="checkbox"])) { align-items: stretch; text-align: start; }
form.sections fieldset.chips legend { width: 100%; }
form.sections fieldset.chips > p { flex-basis: 100%; margin: 0; }
form.sections label.chip { flex-direction: row; align-items: center; gap: .3rem; padding: .2rem .55rem; color: var(--ink);
  font-size: .8125rem; letter-spacing: 0; border-radius: var(--r-pill); box-shadow: inset 0 0 0 1px var(--line-strong); }
form.sections label.chip:has(> input:checked) { background: var(--brand-soft); box-shadow: inset 0 0 0 1px var(--brand); }
/* the Parameters page: an entry a fold, its facts a two-column list, a value's text broken anywhere */
details.param { border-top: 1px solid var(--line); padding: .5rem 0; scroll-margin-top: 4.5rem; }
details.param > summary { display: list-item; cursor: pointer; }
details.param > summary .meta { display: block; margin-left: 1rem; }
details.param dl.facts { display: grid; grid-template-columns: max-content 1fr; gap: .2rem .8rem; margin: .4rem 0; }
details.param dl.facts dt { color: var(--ink-muted); font-size: .8125rem; }
details.param dl.facts dd { margin: 0; }
details.param .owner { margin-top: .6rem; padding-left: .7rem; border-left: 2px solid var(--line); }
code.wrap { white-space: pre-wrap; overflow-wrap: anywhere; }
/* a button that cannot be pressed (Run as my pick off, the player while it loads) looks it, never like a live one */
.run-bar button:disabled, .player button:disabled { opacity: .5; cursor: not-allowed; }
.player .scrub { position: relative; flex: 1 1 100%; height: 44px; }
.player .scrub canvas { position: absolute; left: 0; right: 0; bottom: 4px; width: 100%; height: 8px; }
.player .scrub input[type="range"] { position: absolute; inset: 0; width: 100%; height: 44px; margin: 0; background: transparent; }
.play-log { max-height: 14rem; overflow-y: auto; }
.play-lanes canvas { display: block; width: 100%; height: 66px; }
/* a row of the player's orders stays one line, the log swiped sideways in its own box (AT pinned) on a phone */
.play-log td, .play-log th { white-space: nowrap; }
@media (max-width: 720px) {
  /* the editor's model and run dropdowns take the whole width, so their text shows rather than being cut at half */
  #pick form.pick { grid-template-columns: minmax(0, 1fr); }
}
.play-log tr.later { opacity: .45; }
.play-log tr.at td { background: var(--brand-soft); font-weight: 600; }
/* a row of the player's orders is a button: clicked, or Enter on it, the chart jumps to its order (task-567e516dd6) */
.play-log tbody tr { cursor: pointer; }
.play-log tbody tr:hover td { background: var(--brand-soft); }
.play-log tbody tr:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }

/* the editor's Past runs (task-71bc283664): what differs from the run below, in a popup over the page (the top layer, so
   the table's scroll box does not cut it), placed under its row's button by run_diff.js, the middle of a phone's screen (margin: auto,
   which Basecoat's reset of every margin to 0 would otherwise take away) */
.rundiff[popover] { max-width: min(36rem, calc(100vw - 2rem)); max-height: min(32rem, calc(100vh - 2rem)); overflow: auto;
  margin: auto; padding: .75rem 1rem; border: 1px solid var(--line-strong); border-radius: var(--radius); background: var(--surface);
  color: var(--ink); font-size: .8125rem; }
.rundiff .rundiff-head { margin: .25rem 0 .5rem; font-weight: 600; }
.rundiff dl { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: .25rem .75rem; margin: .5rem 0; }
.rundiff dt { color: var(--ink-muted); }
.rundiff dd { margin: 0; min-width: 0; overflow-wrap: break-word; }
.rundiff p { margin: .35rem 0 0; }
button.rundiff-open { white-space: normal; text-align: left; }

/* the compare view (task-7be0e9bf93): each change two rows, its figures unbroken, then its reason across the table */
.grid.compare tr.fig td { white-space: nowrap; vertical-align: top; border-bottom: 0; padding-bottom: .15rem; }
.grid.compare tr.why td { white-space: normal; padding-top: 0; font-size: .8125rem; }

/* a run's live view (task-c023a19e1b): the walk's progress stays at the top while the page scrolls, two tiles a row on a
   phone, the cumulative R over its drawdown */
.live-progress { position: sticky; top: 0; z-index: 2; background: var(--page); padding: .5rem 0; }
.live-bar { height: .5rem; border-radius: var(--r-pill); background: var(--sunken); overflow: hidden; }
.live-bar span { display: block; height: 100%; width: 0; background: var(--brand); transition: width .4s ease; }
.live-line { margin: .35rem 0 0; font-variant-numeric: tabular-nums; }
.live .stats { grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); }
.live-chart { height: 20rem; }
@media (max-width: 640px) { .live-chart { height: 15rem; } }

/* a dataset's readings (task-cde5177d8b): each reading a group, its latest values a compact table of tabular figures, a
   selector's cell picker on one line where it fits; on a phone the table drops the fact's own date (its known instant and
   age stay), and the episodes stay folded */
#readings .reading { margin-top: 1.25rem; }
#readings .reading h3 { margin-bottom: .25rem; }
#readings table.compact td { font-variant-numeric: tabular-nums; vertical-align: top; }
#readings .cellpick { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center; margin: .5rem 0; }
#readings .cellpick select { max-width: 100%; }
#readings details.episodes { margin: .5rem 0 1rem; }
#readings details.episodes details { margin-left: .75rem; }
@media (max-width: 46rem) {
  #readings table.latest th:nth-child(4), #readings table.latest td:nth-child(4) { display: none; }
}

/* the busy bar and the error toasts, on every signed-in page (net.js; task-f4d91e6435; the owner, 2026-10-10: "i need a
   spinner to know if something is owrking and an error pop up if something comes in the network tabs"). The bar runs
   along the top edge of the header, in its own ink; the spinner is one of the header's items, just before Sign out, in
   the room its menus leave, so it covers nothing (the coordinator's review, 10-10: under the header it hid the
   breadcrumb at 375 px).
   Neither takes a click. A toast is a failed request; it stays until dismissed. */
.net-busy { position: fixed; top: .5rem; right: .75rem; z-index: 20; display: inline-flex; align-items: center;
  gap: .45rem; padding: .2rem .7rem; border: 1px solid var(--line-strong); border-radius: var(--r-pill); background: var(--surface);
  color: var(--ink); font-size: .75rem; font-weight: 600; white-space: nowrap; pointer-events: none; }
header.top > .net-busy { position: static; padding: 0; border: 0; background: transparent; color: var(--bar-ink); }
.net-busy[hidden] { display: none; }
/* the bar: the header's top edge (the header is sticky, so it is positioned and holds it) */
.net-busy-bar { position: absolute; top: 0; left: 0; right: 0; height: 3px; overflow: hidden; }
.net-busy-bar::before { content: ""; display: block; width: 35%; height: 100%; background: var(--bar-ink);
  animation: net-slide 1.1s ease-in-out infinite; }
.net-spin { width: .8rem; height: .8rem; box-sizing: border-box; border: 2px solid var(--line-strong);
  border-top-color: var(--brand); border-radius: 50%; animation: net-turn .7s linear infinite; }
header.top > .net-busy .net-spin { border-color: rgba(240, 247, 255, .35); border-top-color: var(--bar-ink); }
@keyframes net-slide { from { transform: translateX(-100%); } to { transform: translateX(290%); } }
@keyframes net-turn { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .net-busy-bar::before { width: 100%; animation: none; }
  .net-spin { animation-duration: 2s; }
}
html.net-busy-on body { cursor: progress; }
.net-toasts { position: fixed; right: 1rem; bottom: 1rem; z-index: 20; display: flex; flex-direction: column; gap: .5rem;
  width: min(30rem, calc(100vw - 2rem)); max-height: 70vh; overflow-y: auto; }
.net-toasts[hidden] { display: none; }
.net-toasts .net-toast-all { align-self: flex-end; background: var(--surface); }
.net-toast { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: .15rem .75rem; padding: .6rem .75rem;
  border: 1px solid var(--bad); border-left-width: 4px; border-radius: var(--r-input); background: var(--surface);
  color: var(--ink); font-size: .8125rem; }
.net-toast p { grid-column: 1; margin: 0; overflow-wrap: break-word; }
.net-toast .net-toast-head { color: var(--bad); font-weight: 600; }
.net-toast .net-toast-meta { color: var(--ink-muted); font-size: .75rem; }
.net-toast .net-toast-close { grid-column: 2; grid-row: 1 / span 3; align-self: start; }
@media (max-width: 46rem) {
  .net-toasts { left: 16px; right: 16px; bottom: 16px; width: auto; }
  .net-toast button { min-height: 44px; }
}

/* a button that cannot be pressed is unmistakable, everywhere (task-f4d91e6435: Watch a run live was drawn off yet looked
   live, and "did nothing"; the owner, 2026-10-10, of a dimmed one: "the dim is not very visable"): a grey ground, grey
   text that still reads (4.5:1 and more, in both modes), a dashed edge, a not-allowed cursor, no hover, and an OFF tag
   inside it. Never dimmed: opacity would take the text under reading contrast. Its reason is written under it, never
   only in its hover. The editor's run bar and player are named so their own dimming rule loses. */
button:disabled, main button:not([class]):disabled, .run-bar button:disabled, .player button:disabled {
  opacity: 1; background: var(--sunken); color: var(--ink-muted); border: 1px dashed var(--ink-muted); box-shadow: none;
  cursor: not-allowed; }
button:disabled:hover, button.quiet:disabled:hover, main button:not([class]):disabled:hover {
  background: var(--sunken); color: var(--ink-muted); }
button:disabled::after { content: "off"; margin-left: .45rem; padding: 0 .35rem; border-radius: var(--r-pill);
  background: var(--ink-muted); color: var(--surface); font-size: .6875rem; font-weight: 600; line-height: 1.4;
  letter-spacing: .04em; text-transform: uppercase; vertical-align: middle; }

/* a dataset's source events (task-79a56fc99b): the answer's counts stated above a table that scrolls inside its own box,
   each payload folded in its row; the pickers on one line where they fit */
#source-events .group { margin-top: 1.25rem; }
#source-events .eventpick { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center; margin: .5rem 0; }
#source-events .eventpick select { max-width: 100%; }
#source-events table.compact td { font-variant-numeric: tabular-nums; vertical-align: top; }
#source-events .evbox { max-height: 32rem; overflow: auto; }
#source-events .counts-says { margin: .25rem 0 .75rem; padding-left: 1.1rem; }
#source-events td details pre { max-height: 14rem; overflow: auto; font-size: .72rem; }
