/*
 * Goldmine Option Trading - shared stylesheet.
 *
 * This file is a direct port of the two approved mockups (goldmine_final_v2.html for the
 * dashboard, trade_history_reports_multisource.html for reports) into one stylesheet shared by
 * both pages. The class names, custom properties and rule values below are copied from those
 * mockups; nothing here was redesigned. Where the two mockups defined the same class with a
 * trivially different value (e.g. .card margin-bottom 16px vs 18px), the reports value was kept
 * since it is the newer of the two documents - the difference is not visible enough to matter.
 *
 * Two classes were added that neither mockup needed: .tag-red and .badge-off. Both mockups only
 * ever render bullish/positive states, so they never needed a "bearish" tag colour or a
 * "disarmed" badge colour. Both new rules reuse the existing --red and --border/--text-muted
 * tokens already defined below - no new colours were invented.
 */

:root {
    --bg: #f6f5f2;
    --card: #ffffff;
    --border: #e3e1da;
    --text: #16171a;
    --text-secondary: #6b6a66;
    --text-muted: #9a9890;
    --green: #3b6d11;
    --green-bg: #eaf3de;
    --green-mid: #97c459;
    --red: #a32d2d;
    --red-bg: #fcebeb;
    --blue: #185fa5;
    --blue-bg: #e6f1fb;
    --amber: #854f0b;
    --amber-bg: #faeeda;
    --radius: 10px;

    /*
     * Surface and chart tokens (19 Sep 2026). Until the Solarized Dark and Quiet Light themes were
     * added these were literal light-theme colours scattered through this file and the chart
     * code, which is why the first dark theme left cream patches (the ATM row, neutral chips, the
     * calendar's weekend cells) and black chart lines on a dark card. The values here are the
     * literals they replaced, so the Light theme is unchanged.
     */
    color-scheme: light;
    --accent: var(--green-mid);      /* active edge: activity bar, side panel, report tabs */
    --chip-bg: #f1efe8;              /* neutral chip, segmented-control track */
    --track-bg: #eeece5;             /* empty part of a small progress bar */
    --subtle-bg: #faf9f6;            /* a surface one step quieter than a card */
    --weekend-bg: #eeede7;
    --hatch-alt: #f7f6f1;            /* second stripe of the holiday hatch */
    --mark-holiday-bg: #dddbd3;
    --atm-bg: #faf6e8;               /* the option chain's ATM row */
    --on-strong: #ffffff;            /* text on a control filled with --text */
    --violet: #5d3fd3;               /* hedge overlay events in the activity log */
    --avatar-bg: #cecbf6; --avatar-fg: #26215c;
    /* P&L heat squares (trade diary, reports heat map). THE TWO -1 / -2 LEVELS ARE THE ENDS OF A
       CONTINUOUS RAMP, not two buckets: since 20 Sep 2026 PnlHeat (api.js) mixes between them in
       OKLab by the size of the day's P&L, so a +400 day and a +12,000 day are different squares.
       Both colours are still exactly what they were, and so is the rule behind them.
       ONE RULE FOR EVERY THEME: a calendar's P&L squares are the theme's own brick colours at two
       strengths - the strong level IS --chart-down / --chart-up, the weak level is 45% of it over
       the card - so the calendar always matches the Monitor, and a big loss weighs as much as a
       big win (the first Light palette paired a saturated win green with a pastel loss pink, so
       a -50,000 day looked milder than a +15,000 one). var() here resolves against whichever
       theme block wins, so no theme repeats this; a theme overrides a level only when its
       reference palette supplies the exact swatch (Pastel, Flat). --heat-flat stays per theme.
       A THEME THAT OVERRIDES A LEVEL NOW OWNS A RANGE, NOT A SWATCH, and two are lopsided:
       measured OKLab lightness travel across the ramp is 0.124 for Flat's win arm against 0.193
       for its loss arm, and 0.127 for Solarized Dark's loss arm against 0.221 for its win arm -
       so in those two themes one side of the ramp carries about half the gradation of the other,
       which is the "a big loss weighs as much as a big win" rule bending. Both are the owner's
       own reference swatches, set in the Solarized Dark and Flat theme blocks below, and are left
       as chosen; the fix, if ever wanted, is to take that arm's strong end from --chart-up /
       --chart-down like every other theme does. Every other arm travels 0.175-0.229. */
    --heat-loss-2: var(--chart-down); --heat-loss-1: color-mix(in srgb, var(--chart-down) 45%, var(--card));
    --heat-win-2: var(--chart-up); --heat-win-1: color-mix(in srgb, var(--chart-up) 45%, var(--card));
    --heat-flat: #fac775;
    /* Chart.js and the canvas plugins read these through Theme.color() in api.js.
       --chart-chop is the Choppiness Index pane under the RSI one (20 Sep 2026). ONE RULE FOR
       EVERY THEME: it is a cyan-leaning blue from that theme's own blue/teal family - the
       reference screenshot draws CHOP blue where RSI is purple - one step away from --blue so it
       never matches the payoff card's lines exactly, and checked to be legible on the card and
       distinct from that theme's --chart-rsi, --chart-up and --chart-down. Like the other
       --chart-* tokens it must be a plain hex in EVERY theme, never color-mix(): the pane's band
       plugin passes it to Theme.alpha(), which can only split a #rrggbb into rgba(). */
    --chart-grid: #e1e0d9; --chart-up: #639922; --chart-down: #e24b4a; --chart-rsi: #7f77dd;
    --chart-chop: #0e7c99;
    /*
     * The signal strategies' chart overlays (26 Sep 2026, WP5 - Golden Crossover and Camarilla,
     * signal-strategy.js): an entry / exit segment, a target / stop, the Camarilla resistance
     * and support levels, the pivot, the Golden Crossover's decision candle (a box) and its two
     * moving averages. Each is written here as var() of a palette token so it resolves against
     * whichever theme block wins - the hand-tuned themes below set them literally where their
     * palette wants a different tone. Like every --chart-* token they must resolve to a plain
     * hex (the chart reads them through Theme.color / Theme.alpha), never to color-mix().
     */
    --chart-entry: var(--blue); --chart-exit: var(--text); --chart-target: var(--green); --chart-stop: var(--red);
    --chart-level-r: var(--chart-down); --chart-level-s: var(--chart-up); --chart-pivot: var(--amber);
    --chart-dc: var(--amber); --chart-ema-fast: var(--chart-chop); --chart-ema-slow: var(--chart-rsi);
    --chart-vwap: var(--amber);

    /*
     * Control, chrome and chart-tooltip tokens (19 Sep 2026, when Solarized Dark was matched to
     * VS Code's own theme file and an audit swept the UI for everything a theme could not reach).
     * Each default is written with var() so it resolves against whichever theme block wins and
     * reproduces that theme's previous look; a theme sets one only to depart from it. Tokens
     * that Theme.color() reads for a <canvas> (--chart-*) must resolve to a plain colour, never
     * to color-mix(); none of them may be passed to Theme.alpha() unless it is a #rrggbb hex.
     */
    --text-strong: var(--text);              /* headline figures, the active tab / link */
    --btn-bg: var(--text); --btn-fg: var(--on-strong);   /* the ONE filled (primary) button style */
    --btn-bg-hover: var(--btn-bg); --btn-hover-opacity: 0.85; --btn-disabled-opacity: 0.6;
    --input-bg: var(--card);                 /* every text field, select and date box */
    --hover-bg: var(--border);               /* flat buttons and pills under the pointer */
    --input-hover-bg: var(--border);
    --focus-ring: var(--blue);               /* keyboard focus, and a clicked text field */
    --check-accent: var(--green);            /* every checkbox tick */
    --icon-fg: var(--text-secondary);        /* CSS-drawn icons (the date boxes' calendar) */
    --picker-icon-opacity: 1;                /* the browser's own date / time picker glyph */
    --disabled-opacity: 0.4; --dim-label-opacity: 0.55; --disabled-input-opacity: 0.45;
    --nav-hover-bg: rgba(127,127,127,0.08); --nav-active-bg: rgba(127,127,127,0.10);   /* side panel */
    /* Data rows carry P&L figures, so they get their own, quieter pair: a selection colour that
       suits a plain label can put a loss figure under 3:1. */
    --row-hover-bg: rgba(127,127,127,0.07); --row-open-bg: rgba(127,127,127,0.10); --row-open-edge: transparent;
    --float-bg: var(--card); --float-border: var(--border);   /* account panel, column chooser, tooltips */
    --float-shadow: 0 8px 28px rgba(0,0,0,0.22);
    --selection-bg: color-mix(in srgb, var(--accent) 35%, transparent);
    --scrollbar: auto;
    --fill-good: var(--green); --fill-warn: var(--amber);     /* bar FILLS, as opposed to text */
    --progress-fill: var(--blue); --progress-track: var(--border);
    --pnl-track-stripe: var(--border);
    --logo-plate: #ffffff;                   /* the disc behind the Google logo on the login page */
    --chart-marker: var(--text);             /* the live-spot lines on the brick and payoff charts */
    --chart-tip-bg: var(--tip-bg); --chart-tip-fg: var(--tip-fg); --chart-tip-border: transparent;
    --chart-tip-key-bg: var(--card);         /* painted UNDER a tooltip's colour key */
    --chart-bar-outline: 0;                  /* 1 = outline the Trade analysis bars in their solid colour */
}

/*
 * Themes, opted into via <html data-theme="...">; no attribute (or "light") is the palette
 * above. The account panel's Theme select sets the attribute and remembers the choice in
 * localStorage (Theme in api.js) - it is a purely per-browser display preference, not something
 * the server tracks. Every block reuses the same variable names as the light palette, so no
 * selector anywhere needs a theme-specific override: A NEW COLOUR GOES IN AS A TOKEN, never as
 * a literal in a rule or in chart code - in each of the three hand-tuned blocks below (Dark,
 * Solarized Dark, Quiet Light) and, for the compact themes after them, either derived once in
 * their shared block or set per theme. A theme id lives in two places that must stay in step:
 * its block here and Theme.THEMES in api.js (the early inline script in index.html and
 * login.html applies whatever id was saved; Theme drops one it does not know).
 */
html[data-theme="dark"] {
    color-scheme: dark;
    --bg: #17181a;
    --card: #232426;
    --border: #34353a;
    --text: #eceae4;
    --text-secondary: #a7a59f;
    --text-muted: #7c7a76;
    --green: #7ec850;
    --green-bg: #1e2e17;
    --red: #ef6e6e;
    --red-bg: #34191a;
    --blue: #6db4f0;
    --blue-bg: #17293a;
    --amber: #e0b168;
    --amber-bg: #362a15;
    --chip-bg: #2c2d30; --track-bg: #34353a; --subtle-bg: #1c1d1f; --weekend-bg: #1d1e20;
    --hatch-alt: #232426; --mark-holiday-bg: #3a3b40; --atm-bg: #2e2a1a; --on-strong: #17181a;
    --violet: #a897f5;
    --heat-flat: #a07a2c;
    --chart-grid: #34353a; --chart-up: #6fae3f; --chart-down: #e0605f; --chart-rsi: #9a93ea;
    --chart-chop: #3fb6cf;
    --chart-entry: #6db4f0; --chart-exit: #eceae4; --chart-target: #7ec850; --chart-stop: #ef6e6e;
    --chart-level-r: #e0605f; --chart-level-s: #6fae3f; --chart-pivot: #e0b168;
    --chart-dc: #e0b168; --chart-ema-fast: #3fb6cf; --chart-ema-slow: #9a93ea;
    --chart-vwap: #e0b168;
}

/*
 * Solarized Dark, matched to VS Code's own theme file (theme-solarized-dark, read from the
 * install on the owner's machine, 19 Sep 2026) after he put the two side by side: the page is
 * the #00212b of its side bar and widgets, cards are base03 (#002b36), raised bits base02,
 * fields its input.background #003847, the activity bar #003847 with the active icon on a
 * rounded #005a6f plate (no coloured edge), hover #004454, a selected link #005a6f, the focus
 * ring Solarized cyan, floating panels on #00212b with a cyan-tinted edge, and the primary
 * button its teal. TEXT: nothing is brighter than #d6dbdb, the brightest text VS Code defines
 * (tab.activeForeground) - kept for headline figures and the active tab; running text is a cool
 * grey, labels base1, muted text base0. The first cut used cream base2 #eee8d5 for all text,
 * pure white in the bar and base3 on the avatar - 'bright white', in the owner's words. Two
 * deliberate departures, both for contrast: the button fill is one notch darker than VS Code's
 * #2AA19899 composite (#197271), because a #d6dbdb label is only 4.07:1 on that and 4.6:1 on
 * #166968; and journal rows do NOT take #004454 / #005a6f - loss red drops to 2.5:1 on them -
 * but a fill barely above the card, with a cyan edge as the 'open' cue. Blue
 * and yellow are LIGHTENED from the published palette because the originals are too dim for
 * 11-12px figures on base03; the true yellow is kept where it fills an area (the countdown bar,
 * a flat-day square). GREEN AND RED ARE NOT SOLARIZED'S AT ALL - see the note beside them below:
 * the chrome is VS Code's, the profit-and-loss colours are the owner's emerald board.
 */
html[data-theme="solarized-dark"] {
    color-scheme: dark;
    --bg: #00212b;
    --card: #002b36;
    --border: #0e4656;
    --text: #bac6c7;
    --text-strong: #d6dbdb;
    --text-secondary: #93a1a1;
    --text-muted: #839496;
    /* PROFIT and LOSS are NOT Solarized's olive green and orange-red: the owner found those out of
       place on these teal surfaces (19 Sep 2026) and supplied an emerald brand board instead -
       Caribbean Green #00df81, Mountain Meadow #2cc295, Mint #2fa98c, Frog #17876d, Bangladesh
       Green #03624c, Basil #0b453a - with the instruction to use those shades wherever a green is
       needed and a red family built to match. The reds are a rose-red, the emerald's complement
       (hue ~356), stepped the same way: text / vivid / fill / weak / tint. Text tones are >= 4.5:1
       on a card, on their own tint and on an opened journal row; fills are >= 3.5:1 on a card. */
    --green: #2cc295;        /* Mountain Meadow - every profit figure */
    --green-bg: #093d34;     /* halfway from Pine #06302b to Basil #0b453a: Basil itself puts the P&L panel's
                                captions at 4.1:1 and its 'not yet earned' stripes under 3:1; Pine is 1.05:1
                                against the card, i.e. invisible */
    --green-mid: #2fa98c;    /* Mint - the win-rate bar */
    --red: #f26d76;
    --red-bg: #3e1f2c;
    --blue: #4aa3df;
    --blue-bg: #0a3458;
    --amber: #d0a21a;
    --amber-bg: #3d3a1c;
    --accent: #2aa198;
    --chip-bg: #073642; --track-bg: #0e4656; --subtle-bg: #00252f; --weekend-bg: #00232d;
    --hatch-alt: #002b36; --mark-holiday-bg: #0e4656; --atm-bg: #0a4150; --on-strong: #002b36;
    --violet: #8f94dd;
    --avatar-bg: #03624c; --avatar-fg: #d6dbdb;   /* Bangladesh Green */
    --heat-flat: #b58900;
    --chart-grid: #0e4656; --chart-up: #2fa98c; --chart-down: #d9475a; --chart-rsi: #8086d6;   /* Mint bricks and bars */
    /* Choppiness takes the theme's own (lightened) Solarized BLUE, not its cyan accent #2aa198 -
       that is within a hair of the Mint bricks, and an indicator line must never read as a profit
       colour, the same argument that settled the expiry dot. Well below #d6dbdb in luminance. */
    --chart-chop: #4aa3df;
    /* The signal charts: emerald for a target and a support level, rose for a stop and a
       resistance, Solarized blue for an entry, the brightest text for an exit, yellow pivot. */
    --chart-entry: #4aa3df; --chart-exit: #d6dbdb; --chart-target: #2cc295; --chart-stop: #f26d76;
    --chart-level-r: #d9475a; --chart-level-s: #2fa98c; --chart-pivot: #b58900;
    --chart-dc: #b58900; --chart-ema-fast: #4aa3df; --chart-ema-slow: #8086d6;
    --chart-vwap: #b58900;
    --day-sq: #0a3b49; --weekend-line: #0e4656;
    /* Calendar squares take the board's own steps, not the 45% mix: an idle day here is a dark TEAL
       square, and a teal-green at 45% reads as "a brighter idle day". Small = Frog / weak red,
       big = Caribbean Green / vivid red. */
    --heat-win-1: #17876d; --heat-win-2: #00df81;
    --heat-loss-1: #b83e52; --heat-loss-2: #ff4d67;
    /* Solarized YELLOW. Not the cyan accent: Mint is almost the accent's colour, and a marker must
       never read as a profit colour. Not ink either: #d6dbdb is the brightest tone in the theme,
       and as a dot on dark teal squares it out-shone the P&L fills (the owner: "too bright").
       Yellow is the one Solarized accent still free on the calendar - emerald is profit, rose is
       loss, blue is the special-session ring - and it is 3.8:1 on an idle square at well under
       half the ink's luminance. A flat day's square is the same yellow, but the dot's card-coloured
       halo still rings it. */
    --expiry-dot: #b58900;
    --holiday-sq: #586e75; --holiday-bg: #073642;
    --special-ring: #268bd2;
    --actbar-bg: #003847; --actbar-fg: #6d8a93; --actbar-fg-on: #d6dbdb; --panel-bg: #00252f;
    --actbar-plate: #005a6f; --actbar-plate-hover: #004a5c; --actbar-edge: transparent;
    --tip-bg: #004052; --tip-fg: #d6dbdb;
    --btn-bg: #166968; --btn-fg: #d6dbdb; --btn-bg-hover: #125b5a; --btn-hover-opacity: 1; --btn-disabled-opacity: 0.75;
    --input-bg: #003847; --hover-bg: #004454; --input-hover-bg: #004a5c;
    --focus-ring: #2aa198; --check-accent: #2aa198; --icon-fg: #93a1a1; --picker-icon-opacity: 0.6;
    --disabled-opacity: 0.5; --dim-label-opacity: 0.8; --disabled-input-opacity: 0.7;
    --nav-hover-bg: #004454aa; --nav-active-bg: #005a6f;
    --row-hover-bg: #00313e; --row-open-bg: #00313e; --row-open-edge: #2aa198;
    --float-bg: #00212b; --float-border: #196e6c; --float-shadow: 0 8px 28px rgba(0,0,0,0.5);
    --selection-bg: #2aa19866; --scrollbar: #2a5b69 transparent;
    --fill-good: #2cc295; --fill-warn: #b58900;
    --progress-fill: #047aa6; --progress-track: #00212b; --pnl-track-stripe: #6d8a93;
    --logo-plate: #d6dbdb;
    --chart-marker: #d6dbdb;
    --chart-tip-bg: #00212b; --chart-tip-fg: #d6dbdb; --chart-tip-border: #196e6c;
    --chart-bar-outline: 1;
}

/*
 * Quiet Light, after the VS Code theme: no pure white anywhere (cards are its #f5f5f5 editor
 * grey on a cooler page), #333 text, and its lavender/purple chrome - the activity bar is the
 * title bar's #c4b7d7 with #705697 icons, and #705697 is the active edge. Accents are the
 * theme's own syntax colours (string green, function red, keyword blue, number brown), the
 * green and the brown darkened a step so small figures hold 4.5:1 on a card. This is the one
 * theme whose activity bar is LIGHT, which is why its hover label has its own --tip-* tokens.
 */
html[data-theme="quiet-light"] {
    color-scheme: light;
    --bg: #e9e9ee;
    --card: #f5f5f5;
    --border: #d2d2dc;
    --text: #333333;
    --text-secondary: #62626e;
    --text-muted: #8b8b98;
    --green: #3a7a20;
    --green-bg: #dcebd0;
    --green-mid: #8dbb62;
    --red: #aa3731;
    --red-bg: #f3dcda;
    --blue: #4b69c6;
    --blue-bg: #e0e5f6;
    --amber: #9a5a1f;
    --amber-bg: #f4e6d4;
    --accent: #705697;
    --chip-bg: #e6e6ec; --track-bg: #dfdfe6; --subtle-bg: #efeff2; --weekend-bg: #e6e6eb;
    --hatch-alt: #f5f5f5; --mark-holiday-bg: #d6d6de; --atm-bg: #e8e2f2; --on-strong: #ffffff;
    --violet: #7a3e9d;
    --avatar-bg: #705697; --avatar-fg: #ffffff;
    --heat-flat: #ecc78c;
    --chart-grid: #dcdce4; --chart-up: #5d9b3a; --chart-down: #c8564f; --chart-rsi: #7a3e9d;
    --chart-chop: #1c6f86;
    --chart-entry: #4b69c6; --chart-exit: #333333; --chart-target: #3a7a20; --chart-stop: #aa3731;
    --chart-level-r: #c8564f; --chart-level-s: #5d9b3a; --chart-pivot: #9a5a1f;
    --chart-dc: #9a5a1f; --chart-ema-fast: #1c6f86; --chart-ema-slow: #7a3e9d;
    --chart-vwap: #9a5a1f;
    --day-sq: #d9d9e0; --weekend-line: #cdcdd6;
    --expiry-dot: #705697;
    --holiday-sq: #a9a9b3; --holiday-bg: #e2e2e8;
    --special-ring: #8fa6e0;
    --actbar-bg: #c4b7d7; --actbar-fg: #705697; --actbar-fg-on: #2f2145; --panel-bg: #f0f0f3;
    --tip-bg: #705697; --tip-fg: #ffffff;
    --btn-bg: #705697; --btn-fg: #ffffff; --btn-bg-hover: #5f4883; --btn-hover-opacity: 1;   /* VS Code Quiet Light's button */
    --focus-ring: #9769dc; --check-accent: #705697;
}

/*
 * COMPACT THEMES (19 Sep 2026, second batch). The four themes above set every token by hand.
 * Every theme below sets only its ~25 BASE colours - surfaces, text, the four accents, chart
 * fills, activity bar - and this block derives the rest from them with color-mix(): the accent
 * tints, neutral chips and tracks, calendar day markers, the side panel. (The calendars' P&L
 * squares need nothing here: :root derives them from --chart-up/down for every theme.) So a new
 * theme is one short block plus a line in Theme.THEMES (api.js); nothing else.
 *
 * How the selector works: it matches any data-theme EXCEPT the four hand-tuned ones. :where()
 * contributes no specificity, so this is html:root = (0,1,1): it beats every plain :root block
 * wherever that sits in the file, and it TIES with html[data-theme="x"], so a theme block -
 * which comes later - can still override any derived token (Pastel sets its own heat squares).
 *
 * --tint is how much accent goes into an accent's background: 12% reads on a light card, a dark
 * card needs 20%. Tokens that JavaScript reads for a <canvas> (Theme.color in api.js: --text*,
 * --green, --red, --blue, --chart-*) must resolve to a plain hex colour, never to color-mix() -
 * that is why --chart-grid is var(--border) and the themes give --chart-up/down/rsi literally.
 * Text accents were checked for contrast on the card (>= 4.5:1) and on their own tint (>= 4:1);
 * where a reference palette's colour was too light to be text (every pastel, Flat UI's Grass and
 * Sunflower) the theme uses a darkened version for text and keeps the original for fills.
 */
html:root:where([data-theme]:not([data-theme="light"]):not([data-theme="dark"]):not([data-theme="solarized-dark"]):not([data-theme="quiet-light"])) {
    --tint: 12%;
    --green-bg: color-mix(in srgb, var(--green) var(--tint), var(--card));
    --red-bg: color-mix(in srgb, var(--red) var(--tint), var(--card));
    --blue-bg: color-mix(in srgb, var(--blue) var(--tint), var(--card));
    --amber-bg: color-mix(in srgb, var(--amber) var(--tint), var(--card));
    --green-mid: var(--chart-up);
    --chip-bg: color-mix(in srgb, var(--text) 7%, var(--card));
    --track-bg: color-mix(in srgb, var(--text) 11%, var(--card));
    --subtle-bg: color-mix(in srgb, var(--bg) 55%, var(--card));
    --weekend-bg: color-mix(in srgb, var(--text) 6%, var(--card));
    --hatch-alt: var(--card);
    --mark-holiday-bg: color-mix(in srgb, var(--text) 14%, var(--card));
    --atm-bg: color-mix(in srgb, var(--amber) 14%, var(--card));
    --on-strong: var(--card);
    --avatar-bg: var(--accent);
    --heat-flat: color-mix(in srgb, var(--amber) 45%, var(--card));
    --chart-grid: var(--border);
    --day-sq: color-mix(in srgb, var(--text) 13%, var(--card));
    --weekend-line: color-mix(in srgb, var(--text) 17%, var(--card));
    --expiry-dot: var(--accent);
    --holiday-sq: color-mix(in srgb, var(--text) 38%, var(--card));
    --holiday-bg: color-mix(in srgb, var(--text) 9%, var(--card));
    --special-ring: color-mix(in srgb, var(--blue) 60%, var(--card));
    --panel-bg: color-mix(in srgb, var(--bg) 50%, var(--card));
    --tip-bg: var(--actbar-bg); --tip-fg: var(--actbar-fg-on);
    /* The signal charts' overlays, from the theme's own accents (all plain hex in every compact
       theme, so Theme.alpha can split them). */
    --chart-entry: var(--blue); --chart-exit: var(--text); --chart-target: var(--green); --chart-stop: var(--red);
    --chart-level-r: var(--chart-down); --chart-level-s: var(--chart-up); --chart-pivot: var(--amber);
    --chart-dc: var(--amber); --chart-ema-fast: var(--chart-chop); --chart-ema-slow: var(--chart-rsi);
    --chart-vwap: var(--amber);
}

/* Claude: Anthropic's warm neutrals - ivory #faf9f5 cards on an oat page, near-black #141413
   text and chrome, the coral #d97757 as the accent edge. Green and blue are the brand's
   #788c5d and #6a9bcc, darkened for text; the loss red is kept cooler than the coral so a loss
   never reads as "just the accent". */
html[data-theme="claude"] {
    color-scheme: light;
    --bg: #f0eee6; --card: #faf9f5; --border: #dedcd1;
    --text: #141413; --text-secondary: #5e5d59; --text-muted: #87867f;
    --green: #4d6a32; --red: #b23a33; --blue: #3d6c9e; --amber: #96601a;
    --accent: #d97757; --violet: #6f5fa8;
    --chart-up: #788c5d; --chart-down: #c9584c; --chart-rsi: #8577c0; --chart-chop: #2e7d92;
    --avatar-bg: #c96442; --avatar-fg: #ffffff;
    --actbar-bg: #1f1e1d; --actbar-fg: #9c9a92; --actbar-fg-on: #faf9f5;
}
html[data-theme="claude-dark"] {
    color-scheme: dark; --tint: 20%;
    --bg: #1f1e1d; --card: #262624; --border: #3d3c38;
    --text: #faf9f5; --text-secondary: #c2c0b6; --text-muted: #918f86;
    --green: #a9bf8a; --red: #f0857c; --blue: #8fb8e2; --amber: #e0b36a;
    --accent: #d97757; --violet: #b3a7ea;
    --chart-up: #8ca36c; --chart-down: #d9645a; --chart-rsi: #a99de3; --chart-chop: #5fc3d4;
    --avatar-fg: #141413;
    --actbar-bg: #141413; --actbar-fg: #87867f; --actbar-fg-on: #faf9f5;
}

/* Pastel and Pastel Night: the 18-step pastel strip (yellows, peaches, pinks, sages, blues,
   lavenders, ending in navy). Pastel is white cards on a lavender-grey page with the navy as
   text and chrome; Pastel Night turns it over - navy cards, the pastels themselves as text.
   The heat squares are the strip's own pinks and sages. */
html[data-theme="pastel"] {
    color-scheme: light;
    --bg: #f3f1f8; --card: #ffffff; --border: #e0dbea;
    --text: #1e2136; --text-secondary: #64557b; --text-muted: #8c7da8;
    --green: #4c7058; --red: #ad514f; --blue: #32769b; --amber: #b4521e;
    --accent: #bba6dd; --violet: #64557b;
    --chart-up: #62866c; --chart-down: #cb7876; --chart-rsi: #8c7da8; --chart-chop: #1e8296;
    --green-mid: #8ba47c;
    --heat-loss-2: #cb7876; --heat-loss-1: #fbc2c2; --heat-flat: #f4d35e;
    --heat-win-1: #b4cfa4; --heat-win-2: #62866c;
    --expiry-dot: #f67b45;
    --avatar-fg: #1e2136;
    --actbar-bg: #1e2136; --actbar-fg: #8c7da8; --actbar-fg-on: #ffffff;
}
html[data-theme="pastel-night"] {
    color-scheme: dark; --tint: 20%;
    --bg: #161828; --card: #1e2136; --border: #353957;
    --text: #eeebf6; --text-secondary: #b9b3cf; --text-muted: #9788b3;
    --green: #b4cfa4; --red: #e39b99; --blue: #a0c5e3; --amber: #f4d35e;
    --accent: #bba6dd; --violet: #bba6dd;
    --chart-up: #8ba47c; --chart-down: #cb7876; --chart-rsi: #bba6dd; --chart-chop: #7fcfe0;
    --heat-flat: #f4d35e;
    --expiry-dot: #ffb88a;
    --avatar-fg: #1e2136;
    --actbar-bg: #10121e; --actbar-fg: #8c7da8; --actbar-fg-on: #ffffff;
}

/* Forest: the soft-UI mock-up in deep green and orange - pale grey-green surfaces, a deep
   green activity bar, orange as the accent edge and the warning colour. */
html[data-theme="forest"] {
    color-scheme: light;
    --bg: #e8ece7; --card: #f7f9f5; --border: #d3dad2;
    --text: #12261e; --text-secondary: #4a6156; --text-muted: #7c8f85;
    --green: #1f6b4a; --red: #b23e2c; --blue: #2c6c8c; --amber: #b3560f;
    --accent: #f08a3c; --violet: #6c5fa6;
    /* A true blue, not a cyan: Forest's bricks are already a teal-green (#2e8b62). */
    --chart-up: #2e8b62; --chart-down: #d2553f; --chart-rsi: #7a6fb0; --chart-chop: #2f6bb0;
    --avatar-fg: #2a1608;
    --actbar-bg: #0f3d2e; --actbar-fg: #7faf98; --actbar-fg-on: #ffffff;
}

/* Ocean: the teal / cyan / navy arrow infographic on pale blue-grey. */
html[data-theme="ocean"] {
    color-scheme: light;
    --bg: #e4ebef; --card: #f5f9fb; --border: #ccd9e0;
    --text: #0f2233; --text-secondary: #436073; --text-muted: #748e9f;
    --green: #1a7565; --red: #b5433d; --blue: #1f6f9c; --amber: #94610f;
    --accent: #1fa5c8; --violet: #5a63ad;
    /* Ocean is blue and teal throughout, so Choppiness goes DARKER than both the blue-violet RSI
       line and the teal-green bricks rather than trying to find a free hue. */
    --chart-up: #27917b; --chart-down: #d2605a; --chart-rsi: #5f7fbf; --chart-chop: #0b5e86;
    --avatar-fg: #06202b;
    --actbar-bg: #0f2233; --actbar-fg: #6f93a8; --actbar-fg-on: #ffffff;
}

/* Sage: the sage-and-dark-green infographic - the quietest theme, nearly monochrome, with
   muted sage / terracotta bricks and a mint accent edge. */
html[data-theme="sage"] {
    color-scheme: light;
    --bg: #ecefe5; --card: #f9faf4; --border: #d8ddcd;
    --text: #14352a; --text-secondary: #4f6353; --text-muted: #84937f;
    --green: #356b42; --red: #a6463d; --blue: #3b6c87; --amber: #8a651b;
    --accent: #7fb894; --violet: #6e6a9e;
    --chart-up: #6b8a66; --chart-down: #c4705f; --chart-rsi: #8a8fb8; --chart-chop: #1f6d87;
    --green-mid: #a3b49b;
    --expiry-dot: var(--text);
    --avatar-bg: #a3b49b; --avatar-fg: #14352a;
    --actbar-bg: #14352a; --actbar-fg: #8fa38c; --actbar-fg-on: #f2f4ea;
}

/* Flat: the Flat UI swatch card - Light Gray surfaces, Dark Gray text and chrome, Mint as the
   accent edge, Grapefruit / Grass / Blue Jeans / Sunflower as the accents (darkened for text;
   the swatch colours themselves fill the bricks and the heat squares). */
html[data-theme="flat"] {
    color-scheme: light;
    --bg: #e6e9ed; --card: #f5f7fa; --border: #ccd1d9;
    --text: #434a54; --text-secondary: #656d78; --text-muted: #808895;
    --green: #4b7722; --red: #be3445; --blue: #3468b2; --amber: #8a5f08;
    --accent: #37bc9b; --violet: #7d5fd0;
    /* Flat UI's Aqua #3bafda, darkened one step for a line on a light card. */
    --chart-up: #679b2a; --chart-down: #e04b5c; --chart-rsi: #967adc; --chart-chop: #1d7b9c;
    --green-mid: #8cc152;
    --heat-loss-2: #da4453; --heat-loss-1: #f5a9b1; --heat-flat: #ffce54;
    --heat-win-1: #c5e59f; --heat-win-2: #8cc152;
    --expiry-dot: var(--text);
    --avatar-bg: #ac92ec; --avatar-fg: #2b2140;
    --actbar-bg: #434a54; --actbar-fg: #aab2bd; --actbar-fg-on: #ffffff;
}

/* Earth: the pill palette on near-black - cream text, sage for profit, dusty rose for loss,
   mustard for warnings, terracotta as the accent edge, plum for the avatar and hedge events. */
html[data-theme="earth"] {
    color-scheme: dark; --tint: 20%;
    --bg: #141414; --card: #1e1e1e; --border: #343330;
    --text: #f2e9d8; --text-secondary: #bbb3a3; --text-muted: #8c8679;
    --green: #8fa88f; --red: #d47c8a; --blue: #8fa9c4; --amber: #d4a12c;
    --accent: #e07a47; --violet: #b58dc2;
    --chart-up: #8fa88f; --chart-down: #d47c8a; --chart-rsi: #b58dc2; --chart-chop: #6fb5c9;
    --heat-flat: #d4a12c;
    --avatar-bg: #5b3a62; --avatar-fg: #f2e9d8;
    --actbar-bg: #0c0c0c; --actbar-fg: #8c8679; --actbar-fg-on: #f2e9d8;
}

* { box-sizing: border-box; }

body {
    margin: 0;
    background: var(--bg);
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    color: var(--text);
}
/* Headline figures take the theme's strongest text tone. :where() gives this rule NO specificity
   on purpose: most of these elements also carry .pl-pos / .pl-neg, which are single-class rules
   (0,1,0). An ordinary rule here - '.payoff-stat .val' is (0,2,0), '.stats-row span.value' (0,2,1)
   - would out-rank them and turn every headline P&L figure grey in every theme. Source order has
   nothing to do with it (the .pl-* rules come later in the file); specificity does. */
:where(.tb-value, .clock-time, .payoff-stat .val, .snapshot-value, .summary-value, .stat-value, .stats-row span.value, .strategy-name) { color: var(--text-strong); }
html { scrollbar-color: var(--scrollbar); }
::selection { background: var(--selection-bg); }
/* One themed focus ring for every control, replacing the browser's own (near-white under a dark
   colour scheme). 'solid', not 'auto': Chromium adds a white companion edge only to 'auto'.
   :where() keeps it below .act:focus-visible, which shows focus with its plate instead. */
:where(button, select, input, textarea, a, [role=button], [tabindex]):focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 1px; }

.hidden { display: none !important; }
.wrap { max-width: 920px; margin: 0 auto; padding: 20px; }

h1 { font-size: 20px; font-weight: 700; margin: 0 0 4px; }
.subtitle { font-size: 13px; color: var(--text-secondary); margin: 0 0 18px; }

/* ------------------------------------------------------------------ */
/* Top bar                                                              */
/* ------------------------------------------------------------------ */

.topbar {
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    padding: 14px 20px; background: var(--card); border-bottom: 0.5px solid var(--border);
    position: sticky; top: 0; z-index: 5; flex-wrap: wrap;
}
.topbar-left { display: flex; align-items: center; gap: 12px; }
.burger {
    background: none; border: 1px solid var(--border); border-radius: 8px;
    width: 40px; height: 40px; display: flex; align-items: center; justify-content: center;
    cursor: pointer; flex-shrink: 0;
}
.burger span { display: block; width: 18px; height: 2px; background: var(--text); position: relative; }
.burger span::before, .burger span::after {
    content: ''; position: absolute; width: 18px; height: 2px; background: var(--text); left: 0;
}
.burger span::before { top: -6px; }
.burger span::after { top: 6px; }
.strategy-name { font-size: 16px; font-weight: 700; margin: 0; }
.strategy-sub { font-size: 12px; color: var(--text-secondary); margin: 1px 0 0; }
/* The current trading mode, inline in the subtitle: upper-case on the mode's colour. */
.mode-chip {
    display: inline-block; padding: 1px 7px; border-radius: 6px; font-size: 11px; font-weight: 700;
    letter-spacing: 0.04em; text-transform: uppercase; vertical-align: 1px;
    background: var(--chip-bg); color: var(--text-secondary);
}
.mode-chip-backtest { background: var(--blue-bg); color: var(--blue); }
.mode-chip-paper { background: var(--amber-bg); color: var(--amber); }
.mode-chip-live { background: var(--green-bg); color: var(--green); }

.mode-switch { display: flex; gap: 4px; background: var(--chip-bg); border-radius: 10px; padding: 4px; }
.mode-pill {
    font-size: 12px; font-weight: 700; padding: 7px 12px; border-radius: 7px;
    border: none; background: transparent; color: var(--text-secondary); cursor: pointer;
}
.mode-pill.active-backtest { background: var(--card); color: var(--blue); box-shadow: 0 0 0 1px var(--border); }
.mode-pill.active-paper { background: var(--card); color: var(--amber); box-shadow: 0 0 0 1px var(--border); }
.mode-pill.active-live { background: var(--card); color: var(--green); box-shadow: 0 0 0 1px var(--border); }

.topbar-right { display: flex; align-items: center; gap: 10px; }
.clock-time { font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums; }
.clock-label { font-size: 10px; color: var(--text-muted); text-align: right; }
.avatar {
    width: 34px; height: 34px; border-radius: 50%; background: var(--avatar-bg); color: var(--avatar-fg);
    display: flex; align-items: center; justify-content: center; font-size: 13px; font-weight: 700;
    cursor: pointer; flex-shrink: 0; letter-spacing: 0.02em; user-select: none;
}
/* The drawer's Account block: the same badge, larger and not a control, beside the signed-in
   user's name and email. min-width:0 on the text lets a long email ellipsize inside the 320px
   drawer instead of pushing it wider. */
.avatar.avatar-lg { width: 44px; height: 44px; font-size: 16px; cursor: default; }
.avatar.avatar-lg:hover { filter: none; }
.profile-card { display: flex; align-items: center; gap: 12px; padding: 2px 0 10px; }
.profile-text { min-width: 0; }
.profile-name, .profile-email { margin: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.profile-name { font-size: 14px; font-weight: 700; }
.profile-email { font-size: 12px; color: var(--text-secondary); margin-top: 2px; }
.profile-email:empty { display: none; }
.mode-banner {
    display: flex; align-items: center; gap: 8px; font-size: 12px; font-weight: 700;
    padding: 8px 14px; border-radius: var(--radius); margin-bottom: 14px;
}
.mode-banner.backtest { background: var(--blue-bg); color: var(--blue); }
.mode-banner.paper { background: var(--amber-bg); color: var(--amber); }
.mode-banner.live { background: var(--green-bg); color: var(--green); }
/* The kill switch is not a mode: until 19 Sep 2026 its banner borrowed .live and read GREEN. */
.mode-banner.kill { background: var(--red-bg); color: var(--red); }
.mode-dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; }

/* ------------------------------------------------------------------ */
/* Cards                                                                */
/* ------------------------------------------------------------------ */

.card {
    background: var(--card); border: 0.5px solid var(--border); border-radius: 12px;
    padding: 16px 18px; margin-bottom: 18px;
}
.card-title { font-size: 15px; font-weight: 700; margin: 0 0 4px; }
.card-sub { font-size: 12px; color: var(--text-muted); margin: 0 0 12px; }
.card-header-row {
    display: flex; justify-content: space-between; align-items: center; gap: 8px;
    flex-wrap: wrap; margin-bottom: 4px;
}
/* A packed card grid (27 Sep 2026): a card moves up into the gap a shorter card above it left,
   instead of every row being as tall as its tallest card. shell.js (Masonry) adds .masonry-on to
   every grid carrying .masonry and sets each card's grid-row-end to "span N" of these 2px rows -
   its height plus the grid's column gap - so the gap between cards is the same down a column as
   across a row. The cards' own bottom margin would double it, so it goes. Until the script runs
   (or without ResizeObserver) the grid is the ordinary one. */
.masonry.masonry-on { grid-auto-rows: 2px; row-gap: 0; align-items: start; }
.masonry.masonry-on > * { margin-bottom: 0; }

select {
    font-size: 13px; padding: 8px 12px; border: 1px solid var(--border); border-radius: 8px;
    background: var(--input-bg); min-height: 38px;
}
/* Every text-like control takes the theme's surface and text colour. Without this a field kept
   the browser's own white box and black text on a dark card (color-scheme on the theme block
   covers what is left to the browser: the picker pop-ups, the scrollbars, the checkboxes).
   :where() keeps this at element specificity, so any class rule still overrides it. */
input:where(:not([type=checkbox]):not([type=radio]):not([type=range])), select, textarea {
    background-color: var(--input-bg); color: var(--text);
}
/* The hairline every field gets unless a class rule says otherwise - without it a bare field (the
   journal's export dates) kept the browser's two-tone bevel. select is left out: it has its own
   8px corner above, and this rule comes later at the same specificity. */
input:where(:not([type=checkbox]):not([type=radio]):not([type=range])), textarea {
    border: 1px solid var(--border); border-radius: 6px; padding: 5px 8px;
}
input[type=checkbox], input[type=radio] { accent-color: var(--check-accent); }
/* Browser-drawn parts of a date / time field: the picker glyph is pure white under a dark colour
   scheme, and the focused dd / mm / yyyy segment is white text on the OS highlight. */
input::-webkit-calendar-picker-indicator { opacity: var(--picker-icon-opacity); }
input::-webkit-datetime-edit-day-field:focus, input::-webkit-datetime-edit-month-field:focus,
input::-webkit-datetime-edit-year-field:focus, input::-webkit-datetime-edit-hour-field:focus,
input::-webkit-datetime-edit-minute-field:focus, input::-webkit-datetime-edit-ampm-field:focus {
    background-color: var(--selection-bg); color: var(--text-strong);
}

/* ------------------------------------------------------------------ */
/* Replay transport                                                     */
/* ------------------------------------------------------------------ */

.transport { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }
button.tbtn {
    font-size: 13px; font-weight: 600; padding: 9px 14px; border-radius: 8px;
    border: 1px solid var(--border); background: var(--card); color: var(--text);
    cursor: pointer; min-height: 40px;
}
button.play { min-width: 92px; }   /* painted by the primary-button rule, after button.plain */
/* Hover feedback via theme tokens, so it reads as a tint in dark mode too; .play is excluded
   because its filled style needs its own treatment rather than the flat-button tint. */
button.tbtn:not(.play):not(.btn-primary):not(.danger):hover:not(:disabled) { background: var(--hover-bg); }

/* One consistent hover affordance for EVERY clickable control, matching the entry buttons'
   tint: if it can be clicked, it lights up the same way. Filled/colored controls (Play, the
   avatar, an ON toggle, the active mode pill) instead dim slightly, because a grey tint would
   fight their own fill color. */
.burger:hover, .close-btn:hover,
button.plain:not(.btn-primary):not(.danger):hover:not(:disabled),
.mode-pill:hover:not(.active-backtest):not(.active-paper):not(.active-live),
.toggle:hover:not(.disabled):not(.on) { background: var(--hover-bg); }
/* A pill or tab under the pointer also takes full text colour: its resting tone is a muted one,
   which falls under 3:1 on a hover fill. A .tab has no padding, so it gets the colour only. */
.mode-pill:hover:not(.active-backtest):not(.active-paper):not(.active-live), .tab:hover:not(.active) { color: var(--text); }
.date-display-wrap:hover input[type=text]:not(:disabled),
select:hover:not(:disabled) { background: var(--input-hover-bg); color: var(--text); }
.avatar:hover, .toggle.on:hover:not(.disabled),
.mode-pill.active-backtest:hover, .mode-pill.active-paper:hover, .mode-pill.active-live:hover {
    filter: brightness(0.93);
}
select { cursor: pointer; }
button.tbtn:disabled { opacity: var(--disabled-opacity); cursor: not-allowed; }
.progress-track { background: var(--border); height: 6px; border-radius: 4px; overflow: hidden; margin-bottom: 6px; }
.progress-fill { background: var(--progress-fill); height: 100%; width: 0%; }
/* Only the replay bar's groove: .progress-track is shared with the top bar's countdown, whose
   track must keep its step against the card. */
#backtestControls .progress-track { background: var(--progress-track); }

/* ------------------------------------------------------------------ */
/* Metrics                                                              */
/* ------------------------------------------------------------------ */

.metric { background: var(--card); border: 0.5px solid var(--border); border-radius: var(--radius); padding: 12px 14px; }
.metric-label { font-size: 12px; color: var(--text-secondary); margin: 0 0 4px; }
.metric-value { font-size: 20px; font-weight: 700; margin: 0; font-variant-numeric: tabular-nums; }

/* ------------------------------------------------------------------ */
/* Badges and tags                                                      */
/* ------------------------------------------------------------------ */

.badge { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 700; padding: 4px 10px; border-radius: 20px; }
.badge-armed { background: var(--green-bg); color: var(--green); }
/* Added: neither mockup ever showed a disarmed badge, so this state had no colour defined. */
.badge-off { background: var(--chip-bg); color: var(--text-secondary); }
.badge-dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; }

.tag-row { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 10px; }
.tag { font-size: 12px; font-weight: 600; padding: 4px 10px; border-radius: 20px; }
.tag-green { background: var(--green-bg); color: var(--green); }
.tag-blue { background: var(--blue-bg); color: var(--blue); }
.tag-gray { background: var(--chip-bg); color: var(--text-secondary); }
/* Added: the mockup's example screen never showed a bearish setup, so it never needed this. */
.tag-red { background: var(--red-bg); color: var(--red); }
.tag-amber { background: var(--amber-bg); color: var(--amber); }

.btn-row { display: flex; flex-direction: column; gap: 8px; }

/* Rule boards (entry / exit panels): one row per rule, verdict glyph on the left. */
.rule-verdict { font-size: 12px; font-weight: 700; margin: 0 0 8px; padding: 6px 8px; border-radius: 6px; background: var(--chip-bg); color: var(--text-secondary); }
.rule-verdict.ready { background: var(--green-bg); color: var(--green); }
.rule-verdict.blocked { background: var(--red-bg); color: var(--red); }
.rule-verdict.holding { background: var(--blue-bg); color: var(--blue); }
.rule-board { display: flex; flex-direction: column; gap: 8px; overflow-y: auto; }
.rule-group-title { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); margin: 2px 0 3px; }
.rule-row { display: flex; align-items: flex-start; gap: 7px; padding: 3px 0; border-bottom: 0.5px solid var(--border); font-size: 12px; }
.rule-row:last-child { border-bottom: none; }
.rule-icon { flex: 0 0 16px; width: 16px; height: 16px; border-radius: 50%; font-size: 10px; font-weight: 700; display: inline-flex; align-items: center; justify-content: center; margin-top: 1px; }
.rule-icon.pass, .rule-icon.met { background: var(--green-bg); color: var(--green); }
.rule-icon.fail { background: var(--red-bg); color: var(--red); }
.rule-icon.wait { background: var(--amber-bg); color: var(--amber); }
.rule-icon.na { background: var(--chip-bg); color: var(--text-muted); }
.rule-icon.info { background: var(--blue-bg); color: var(--blue); font-style: italic; }
.rule-text { display: flex; flex-direction: column; min-width: 0; flex: 1 1 auto; }
.rule-name { font-weight: 600; }
.rule-row.na .rule-name { color: var(--text-muted); font-weight: 500; }
.rule-detail { font-size: 11px; color: var(--text-secondary); overflow-wrap: anywhere; }
.rule-bar { height: 4px; background: var(--track-bg); border-radius: 2px; margin-top: 3px; overflow: hidden; }
.rule-bar-fill { height: 100%; background: var(--fill-warn); }
.rule-bar-fill.met { background: var(--fill-good); }

/* Entry / Exit rule tabs (dashboard rules card). */
.rule-tabs { display: inline-flex; gap: 2px; background: var(--chip-bg); border-radius: 8px; padding: 2px; }
.rule-tab {
    border: none; background: transparent; font: inherit; font-size: 12px; font-weight: 600;
    color: var(--text-secondary); padding: 4px 12px; border-radius: 6px; cursor: pointer;
}
.rule-tab:hover { color: var(--text); }
.rule-tab.active { background: var(--card); color: var(--text-strong); box-shadow: 0 0 0 1px var(--border); }

/*
 * Two-column rule board: CSS columns rather than a grid so the groups flow and balance on their
 * own whatever their row counts. Rows never split across a column break, and a group title
 * never ends a column with its rows on the other side.
 */
.rule-pane { flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden; }
.rule-board.two-col { display: block; column-count: 2; column-gap: 22px; overflow: visible; }
/* Entry groups stay whole across the column break (all gates together); the exit board is one
   group, so it keeps breaking freely or it would collapse into a single column. */
.rule-board.inline-rows .rule-group { break-inside: avoid; }
.rule-text.inline { display: block; }
.rule-text.inline .rule-name, .rule-text.inline .rule-detail, .rule-text.inline .rule-sep { display: inline; }
.rule-text.inline .rule-detail { font-size: 12px; }
.rule-text.inline .rule-sep { color: var(--text-muted); }
.rule-board.two-col .rule-group { margin-bottom: 8px; }
.rule-board.two-col .rule-row { break-inside: avoid; }
.rule-board.two-col .rule-group-title { break-after: avoid; }
@media (max-width: 1099px) { .rule-board.two-col { column-count: 1; } }

button.entry-btn {
    width: 100%; text-align: left; padding: 11px 14px; border: 1px solid var(--border);
    border-radius: 8px; background: var(--card); font-size: 13px; font-weight: 600;
    color: var(--text); cursor: pointer; min-height: 44px;
}
button.entry-btn:hover:not(:disabled) { background: var(--border); }
button.entry-btn:disabled { opacity: 0.5; cursor: not-allowed; }

/* ------------------------------------------------------------------ */
/* Position table                                                       */
/* ------------------------------------------------------------------ */

table.legs { width: 100%; border-collapse: collapse; font-size: 13px; margin-bottom: 4px; }
table.legs th {
    text-align: right; font-size: 11px; color: var(--text-muted); font-weight: 600;
    padding: 6px 4px; border-bottom: 1px solid var(--border); text-transform: uppercase;
    /* Sticky only matters inside a scrolling ancestor (.chain-scroll) - harmless no-op on the
       position/journal tables, which never scroll internally. */
    position: sticky; top: 0; background: var(--card);
}
table.legs th:first-child, table.legs td:first-child { text-align: left; }
table.legs td { text-align: right; padding: 8px 4px; border-bottom: 1px solid var(--border); }
table.legs tr:last-child td { border-bottom: none; font-weight: 700; }
/* A list, not a ledger: the last row is just another row (the settings page's special sessions). */
table.legs.plain-rows tr:last-child td { font-weight: 400; }
.pl-pos { color: var(--green); }
.pl-neg { color: var(--red); }
.pl-flat { color: var(--text-secondary); }
.no-position { font-size: 13px; color: var(--text-muted); padding: 6px 0; }

.legend { display: flex; gap: 16px; flex-wrap: wrap; font-size: 12px; color: var(--text-secondary); margin-top: 8px; }
.legend span { display: inline-flex; align-items: center; gap: 6px; }
.swatch { width: 14px; height: 3px; border-radius: 2px; display: inline-block; }

/* ------------------------------------------------------------------ */
/* Exit control                                                         */
/* ------------------------------------------------------------------ */

.countdown-time { font-size: 22px; font-weight: 700; font-variant-numeric: tabular-nums; margin: 4px 0 8px; }
.exit-btns { display: flex; flex-direction: column; gap: 8px; }
button.plain {
    font-size: 13px; font-weight: 600; padding: 10px 14px; border-radius: 8px;
    border: 1px solid var(--border); background: var(--card); color: var(--text);
    cursor: pointer; min-height: 40px;
}
button.plain.danger, button.tbtn.danger { border-color: var(--red); color: var(--red); }
/* The flat hover fill would put a red label (the kill switch, 'Resume algo') near 3:1 exactly
   while the pointer is on it; a danger button hovers onto the red tint instead. The flat hover
   rules carry :not(.danger) for this: 'button.tbtn:not(.play):not(.btn-primary):hover:not(:disabled)'
   is (0,5,1) and would otherwise out-rank this rule's (0,4,1) whatever the order. */
button.plain.danger:hover:not(:disabled), button.tbtn.danger:hover:not(:disabled) { background: var(--red-bg); }
button.plain:disabled, .mode-pill:disabled { color: var(--text-secondary); cursor: default; }
/*
 * The PRIMARY button: one filled button per surface - Play, 'Save changes', sign-in. Declared
 * here, after button.tbtn and button.plain, because all three are (0,1,1) and the later rule
 * wins; the flat hover rules above exclude .play / .btn-primary for the same reason. :is(button, a)
 * because the sign-in button is a link. Its colours are tokens (--btn-*): ink-filled by default,
 * VS Code's teal in Solarized Dark, its purple in Quiet Light.
 */
button.play, :is(button, a).btn-primary { background: var(--btn-bg); color: var(--btn-fg); border: 1px solid var(--btn-bg); }
button.play:hover:not(:disabled), :is(button, a).btn-primary:hover:not(:disabled) {
    background: var(--btn-bg-hover); border-color: var(--btn-bg-hover); opacity: var(--btn-hover-opacity);
}
:is(button, a).btn-primary:disabled { color: var(--btn-fg); opacity: var(--btn-disabled-opacity); cursor: default; }
.note { font-size: 12px; color: var(--text-muted); margin-top: 10px; }

/* Payoff card's headline strip: P&L, margin, POP, max profit/loss. */
.payoff-stats { display: flex; gap: 18px; flex-wrap: wrap; margin: 2px 0 8px; }
.payoff-stat .lbl { font-size: 10px; color: var(--text-muted); margin: 0; text-transform: uppercase; letter-spacing: 0.03em; }
.payoff-stat .val { font-size: 14px; font-weight: 700; margin: 1px 0 0; font-variant-numeric: tabular-nums; }

/* ------------------------------------------------------------------ */
/* Activity log                                                         */
/* ------------------------------------------------------------------ */

.log-row { display: flex; gap: 10px; padding: 8px 0; border-top: 0.5px solid var(--border); font-size: 13px; }
.log-row:first-child { border-top: none; }

/* Eye-catching treatment for the handful of row types worth scanning for at a glance in an
   otherwise long, plain activity log - see dashboard.js's classifyLogRow. */
.log-badge {
    display: inline-block; font-size: 10px; font-weight: 700; padding: 1px 7px;
    border-radius: 10px; margin-right: 6px; vertical-align: middle;
}
.log-hl-entry.log-badge { background: var(--blue-bg); color: var(--blue); }
.log-hl-exit-partial.log-badge { background: var(--amber-bg); color: var(--amber); }
.log-hl-exit-all.log-badge { background: var(--red-bg); color: var(--red); }
/* Hedge overlays (overnight / temporary attach and remove) are position-changing events too -
   they alter real exposure - so they get the same standout treatment, in their own violet. */
.log-hl-hedge.log-badge { background: color-mix(in srgb, var(--violet) 14%, transparent); color: var(--violet); }
.log-row.log-hl-hedge { background: color-mix(in srgb, var(--violet) 6%, transparent); }
.log-row.log-hl-entry, .log-row.log-hl-exit-partial, .log-row.log-hl-exit-all, .log-row.log-hl-hedge {
    border-radius: 6px; padding-left: 6px; padding-right: 6px; border-top-color: transparent;
}
.log-row.log-hl-entry { background: color-mix(in srgb, var(--blue) 7%, transparent); }
.log-row.log-hl-exit-partial { background: color-mix(in srgb, var(--amber) 8%, transparent); }
.log-row.log-hl-exit-all { background: color-mix(in srgb, var(--red) 7%, transparent); }
.log-time { color: var(--text-muted); min-width: 80px; font-variant-numeric: tabular-nums; display: flex; flex-direction: column; }
.log-date { font-size: 11px; color: var(--text-secondary); white-space: nowrap; }

/* ------------------------------------------------------------------ */
/* Settings drawer                                                      */
/* ------------------------------------------------------------------ */

#overlay {
    position: fixed; inset: 0; background: rgba(0,0,0,0.35); opacity: 0; pointer-events: none;
    transition: opacity 0.2s; z-index: 10;
}
#overlay.open { opacity: 1; pointer-events: auto; }
#drawer {
    position: fixed; top: 0; right: -340px; width: 320px; height: 100%; background: var(--card);
    box-shadow: -2px 0 12px rgba(0,0,0,0.08); transition: right 0.25s ease; z-index: 11;
    overflow-y: auto; padding: 20px;
}
/* The drawer is quick info only; every editable number lives on settings.html, where cards lay
   out in a responsive grid and long labels have room to wrap instead of truncating. */
.settings-row.dimmed > span { color: var(--text-muted); opacity: var(--dim-label-opacity); }
.settings-row input:disabled, .settings-row select:disabled { opacity: var(--disabled-input-opacity); cursor: not-allowed; }
.spage-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(430px, 1fr)); gap: 16px; align-items: start; }
.spage-actions { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin: 0 0 10px; }
.spage .settings-row { gap: 14px; }
.spage .settings-row > span:first-child { flex: 1 1 auto; }
.spage .settings-row input[type=number], .spage .settings-row input[type=text] { width: 110px; flex-shrink: 0; }
.spage .settings-row select { max-width: 60%; }
.spage .settings-row input[type=checkbox] { width: 18px; height: 18px; flex-shrink: 0; }
.save-banner { min-height: 20px; margin: 0 0 14px; font-size: 13px; font-weight: 600; border-radius: 8px; }
.save-banner:not(:empty) { padding: 10px 14px; }
.save-banner.ok { background: var(--green-bg); color: var(--green); }
.save-banner.err { background: var(--red-bg); color: var(--red); }
.save-banner.info { background: var(--chip-bg); color: var(--text-secondary); }
.save-banner.running { background: var(--amber-bg); color: var(--amber); }
@media (max-width: 500px) { .spage-grid { grid-template-columns: 1fr; } }
#drawer.open { right: 0; }
.drawer-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; }
.drawer-title { font-size: 16px; font-weight: 700; margin: 0; }
.close-btn { background: none; border: none; font-size: 18px; cursor: pointer; color: var(--text-secondary); }
.settings-section { margin-bottom: 18px; }
.settings-label { font-size: 11px; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.03em; margin: 0 0 8px; }
.settings-row {
    display: flex; justify-content: space-between; align-items: center; padding: 7px 0;
    border-bottom: 0.5px solid var(--border); font-size: 13px; gap: 10px;
}
.settings-row:last-child { border-bottom: none; }
.settings-row input[type=number], .settings-row input[type=text] {
    width: 100px; padding: 6px 8px; border: 1px solid var(--border); border-radius: 6px;
    font-size: 13px; text-align: right;
}
/* Date and time fields had no rule of their own and kept the browser's bevelled border, which
   is a bright two-tone edge on a dark card. Same hairline as the number fields above. */
.settings-row input[type=date], .settings-row input[type=time] {
    padding: 5px 8px; border: 1px solid var(--border); border-radius: 6px; font-size: 13px;
}
.toggle { width: 38px; height: 22px; border-radius: 12px; background: var(--border); position: relative; cursor: pointer; flex-shrink: 0; }
.toggle.on { background: var(--green); }
.toggle.disabled { cursor: not-allowed; opacity: 0.55; }
.toggle-knob { width: 18px; height: 18px; border-radius: 50%; background: #fff; position: absolute; top: 2px; left: 2px; transition: left 0.15s; }
.toggle.on .toggle-knob { left: 18px; }

@media (min-width: 900px) {
    .wrap { max-width: 1500px; }
}
.save-toast { font-size: 12px; color: var(--green); text-align: center; margin-top: 8px; height: 16px; }

/* ==================================================================== */
/* Live views (Monitor, Rules, Option chain, Activity) - fill the viewport */
/* ==================================================================== */

/*
 * .live-view scopes the compact card/metric sizing to the views that fill the viewport exactly
 * (their own internal scroll regions: .chain-scroll, #logList, the rule panes), so it cannot
 * affect the Reports / Settings / Schedulers views, which are ordinary scrolling documents
 * (.doc-view). The workbench frame itself - activity bar, side panel, top bar - is styled at
 * the end of this file.
 */
.live-view .card { margin-bottom: 0; padding: 12px 14px; }
.live-view .card-sub { margin: 0 0 8px; }

/* The Backtest view's month monitor (26 Sep 2026): a row per segment, its own progress bar. Tokens only. */
.bt-months { width: 100%; border-collapse: collapse; font-size: 12px; }
.bt-months th { text-align: left; font-weight: 600; color: var(--text-secondary); padding: 4px 8px 6px 0; border-bottom: 0.5px solid var(--border); }
.bt-months td { padding: 5px 8px 5px 0; border-bottom: 0.5px solid var(--border); vertical-align: middle; }
.bt-months tr.bt-done .bt-state { color: var(--green); font-weight: 600; }
.bt-months tr.bt-running .bt-state { color: var(--blue); font-weight: 600; }
.bt-months tr.bt-failed .bt-state { color: var(--red); font-weight: 700; }
.bt-months tr.bt-aborted .bt-state { color: var(--amber); font-weight: 600; }
.bt-months tr.bt-pending .bt-state { color: var(--text-muted); }
.bt-months tr.bt-running .progress-fill { background: var(--blue); }
.bt-months tr.bt-done .progress-fill { background: var(--green); }
#backtestControls .replay-top { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
/* A parallel run's segment strip (26 Sep 2026): one block per segment, filled to its own progress.
   Tokens only, so every theme colours it. */
.parallel-strip { display: flex; gap: 2px; height: 7px; margin-top: 5px; }
.parallel-strip .seg { display: block; flex: 1 1 0; min-width: 2px; height: 100%; background: var(--track-bg); border-radius: 2px; overflow: hidden; }
.parallel-strip .seg i { display: block; height: 100%; width: 0; background: var(--progress-fill); }
.parallel-strip .seg-running i { background: var(--blue); }
.parallel-strip .seg-done i { background: var(--green); }
.parallel-strip .seg-failed { background: var(--red); }
.parallel-strip .seg-aborted i { background: var(--fill-warn); }
#backtestControls .jump-row { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; margin-top: 6px; }
#backtestControls .jump-sep { width: 1px; height: 22px; background: var(--border); margin: 0 4px; }
#backtestControls #seekTime:disabled,
#backtestControls #btnSeekGo:disabled { opacity: var(--disabled-opacity); cursor: not-allowed; }

/*
 * A native <input type="date"> always renders its selected value in the browser/OS's own format,
 * with no CSS or JS override - the actual reason a "dd Mon yyyy" request against it kept not
 * sticking. The fix used here (#seekDate, #logDateFilter) is to let the real date input keep doing
 * all the work - opening the native picker, handling keyboard/accessibility - but make it
 * invisible and lay it exactly over a plain read-only text box that this dashboard fully controls
 * and always renders as dd Mon yyyy (see the change handlers in dashboard.js).
 */
.date-display-wrap { position: relative; display: inline-block; }
.date-display-wrap input[type=text] {
    cursor: pointer; width: 100px; font-size: 12px; padding: 6px 22px 6px 8px;
    border: 1px solid var(--border); border-radius: 7px; background: var(--input-bg);
    color: var(--text); min-height: 34px;
}
.date-display-wrap input[type=text]:disabled { opacity: 0.5; cursor: not-allowed; }
/* The browser's default placeholder gray otherwise reads as "disabled" even when the field is
   perfectly clickable and just has no date chosen yet - only the :disabled rule above should ever
   look muted. */
.date-display-wrap input[type=text]::placeholder { color: var(--text-secondary); opacity: 1; }
/*
 * A visible calendar icon standing in for the real date input's own icon, which is invisible
 * (opacity:0, see below) along with the rest of that input. Purely decorative - pointer-events:
 * none lets every click pass straight through to the real, invisible input underneath, which is
 * what actually opens the picker (see the click handler in dashboard.js that calls showPicker()).
 */
/* Drawn as a MASK filled with a token, not as the calendar emoji it used to be: an emoji comes
   from the OS colour font, ignores 'color' and every token, and was a white sticker inside the
   field on every dark theme. The SVG carries shape only - no colour enters the stylesheet. */
.date-display-wrap::after {
    content: ''; position: absolute; right: 7px; top: 50%; transform: translateY(-50%);
    width: 12px; height: 12px; pointer-events: none; background-color: var(--icon-fg);
    -webkit-mask: 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") center / contain no-repeat;
    mask: 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") center / contain no-repeat;
}
.date-display-wrap:has(input:disabled)::after { opacity: 0.5; }
.date-display-wrap input[type=date] {
    position: absolute; inset: 0; width: 100%; height: 100%;
    opacity: 0; cursor: pointer; border: none; padding: 0;
}
.date-display-wrap input[type=date]:disabled { cursor: not-allowed; }

/*
 * Custom scrollbar for the Renko/RSI card - see wireBrickScrollbar in dashboard.js. The zoom
 * plugin's drag-to-pan and ctrl+wheel zoom have no visible position indicator on their own; this
 * is a plain draggable track standing in for one, kept in sync with whatever the chart's own
 * pan/zoom does and vice versa.
 */
.chart-scrollbar { position: relative; height: 8px; margin-top: 4px; background: var(--border); border-radius: 4px; cursor: pointer; }
.chart-scrollbar-thumb {
    position: absolute; top: 0; left: 0; height: 100%; min-width: 16px;
    background: var(--text-muted); border-radius: 4px; cursor: grab;
}
.chart-scrollbar-thumb:hover, .chart-scrollbar-thumb.dragging { background: var(--text-secondary); }
.chart-scrollbar-thumb.dragging { cursor: grabbing; }

/* Two metric rows, sized to sit directly above the grid columns they describe. */
.metric-reserved { border-style: dashed; background: var(--subtle-bg); }
.metric-reserved .metric-value { color: var(--text-muted); }
.live-view .metric { padding: 7px 10px; }
.live-view .metric-label { font-size: 10px; margin: 0 0 3px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.live-view .metric-value { font-size: 14px; }

.chain-card { flex: 1 1 55%; min-height: 0; display: flex; flex-direction: column; }
.log-card { flex: 1 1 35%; min-height: 0; display: flex; flex-direction: column; }
.log-card #logList { flex: 1 1 auto; overflow-y: auto; min-height: 0; }
.log-row > span:last-child { min-width: 0; white-space: normal; overflow-wrap: anywhere; }
.chain-scroll { overflow-x: auto; }
.progress-fill-amber { background: var(--fill-warn); }

/*
 * Live P&L headline (first card in .col-a). 70px is five times the 14px the dashboard renders a
 * .metric-value at, which is the size the operator asked for; the clamp's middle term is in vw
 * because .col-a is a fixed 3.2/13 fraction of the grid, so ~3.6vw tracks the column's own width
 * and reaches 70px on a 1920px screen. nowrap + overflow:hidden because the shell is height:100vh:
 * a six-figure loss must shrink out of sight rather than wrap and push the Renko card off-screen.
 */
.pnl-panel { flex: 0 0 auto; transition: background 240ms ease; }
.pnl-panel.pnl-profit { background: var(--green-bg); }
.pnl-panel.pnl-loss { background: var(--red-bg); }
.pnl-value {
    /* 2px smaller than the original clamp(24px, 3.2vw, 60px) at every viewport width. */
    font-size: clamp(22px, calc(3.2vw - 2px), 58px); font-weight: 700; line-height: 1.02;
    letter-spacing: -0.02em; margin: 0 0 6px; font-variant-numeric: tabular-nums;
    white-space: nowrap; overflow: hidden;
}
/*
 * The unfilled remainder is a stripe pattern rather than a second flat colour: a paler tint of
 * --border is nearly invisible against --card in the dark theme, and stripes read as "not yet
 * earned" at a glance from across the room, which is the whole point of this panel.
 */
.pnl-target-track {
    height: 10px; border-radius: 5px; overflow: hidden; border: 0.5px solid var(--border);
    background: repeating-linear-gradient(135deg, var(--pnl-track-stripe) 0 5px, transparent 5px 10px);
}
/* Always the profit colour: a losing position reads 0% width, so this never paints during a loss. */
.pnl-target-fill { height: 100%; width: 0%; background: var(--fill-good); transition: width 240ms ease; }
/* A target the position can no longer reach (a stopped condor side, a temporary hedge): the bar
   still shows how far along it is, hatched so it cannot be read as "on its way" - the caption
   beside it says what closes the trade instead. Both tokens are already themed. */
.pnl-target-fill.pnl-target-capped {
    background: repeating-linear-gradient(135deg,
        var(--fill-warn) 0 5px, var(--pnl-track-stripe) 5px 10px);
}
.pnl-target-note { font-size: 11px; color: var(--text-secondary); margin: 6px 0 0; }

/* Trade diary mini-calendars - same day-by-day P&L data as reports.html's .day-grid heatmap
   (see Api.periods), just smaller and inline in the dashboard's side column. */
.mini-month-label { font-size: 12px; font-weight: 700; margin: 0 0 6px; text-align: center; color: var(--blue); }
.mini-day-grid { display: grid; grid-template-columns: repeat(7, 13px); gap: 3px; margin-bottom: 6px; justify-content: center; }
/* --day-sq (idle working day) is defined with the day markers further down, light and dark. */
.mini-day-sq { width: 13px; height: 13px; border-radius: 3px; background: var(--day-sq); }
.mini-day-sq[data-pnl] { cursor: pointer; }
.mini-month-total { font-size: 11px; font-weight: 700; padding: 2px 7px; border-radius: 20px; display: inline-block; }
.diary-reserved {
    flex: 1 1 auto; border: 1px dashed var(--border); border-radius: 10px; display: flex;
    align-items: center; justify-content: center; color: var(--text-muted); font-size: 11px; min-height: 40px;
}
.mini-tooltip {
    position: fixed; background: var(--float-bg); border: 1px solid var(--float-border); border-radius: 8px;
    padding: 7px 10px; font-size: 12px; box-shadow: 0 4px 14px rgba(0,0,0,0.15); pointer-events: none; z-index: 50;
}

@media (max-width: 1099px) {
    .chain-scroll { max-height: 360px; }
    .log-card #logList { max-height: 220px; }
    #diaryMonths { max-height: 300px; }
}

/* ==================================================================== */
/* Reports page - trade_history_reports_multisource.html                */
/* ==================================================================== */

.source-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 16px; }
.source-label { font-size: 12px; color: var(--text-muted); }
.source-note { font-size: 12px; color: var(--text-muted); }

.tabs { display: flex; gap: 20px; border-bottom: 1px solid var(--border); margin-bottom: 20px; }
.tab { font-size: 14px; font-weight: 600; color: var(--text-muted); padding: 0 0 10px; cursor: pointer; border-bottom: 2px solid transparent; }
.tab.active { color: var(--text-strong); border-bottom-color: var(--accent); }

.selector-row { display: flex; justify-content: flex-end; align-items: center; gap: 6px; margin-bottom: 14px; }
.selector-row.week-nav { justify-content: flex-start; gap: 10px; }
.arrow-btn { padding: 5px 9px; font-size: 11px; line-height: 1; }
.arrow-btn:disabled { opacity: 0.35; cursor: default; }

.snapshot-row {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 0;
    border: 1px solid var(--border); border-radius: 12px; margin-bottom: 18px; overflow: hidden;
}
.snapshot-item { padding: 16px 18px; border-right: 1px solid var(--border); background: var(--card); }
.snapshot-item:last-child { border-right: none; }
.snapshot-label { font-size: 12px; color: var(--text-secondary); margin: 0 0 6px; }
.snapshot-value { font-size: 20px; font-weight: 700; margin: 0; }
.snapshot-value .date { font-size: 12px; font-weight: 400; color: var(--text-secondary); margin-left: 6px; }

.stats-row {
    display: flex; flex-wrap: wrap; gap: 24px; padding: 14px 0 20px;
    border-bottom: 1px solid var(--border); margin-bottom: 20px; font-size: 13px;
}
.stats-row span.label { color: var(--text-secondary); margin-right: 6px; }
.stats-row span.value { font-weight: 700; }

.month-scroll { display: block; padding-bottom: 8px; margin-bottom: 6px; }
.year-block { margin-bottom: 18px; }
.year-head { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.year-label { font-size: 14px; font-weight: 700; }
.year-note { font-size: 12px; color: var(--text-muted); }
.year-months { display: flex; flex-wrap: wrap; gap: 14px 18px; }
.day-wd { width: 12px; height: 10px; font-size: 8px; line-height: 10px; text-align: center; color: var(--text-muted); }
.day-sq.blank { background: transparent; }
.month-total.month-empty { background: transparent; color: var(--text-muted); font-weight: 400; padding-left: 0; }
.month-block { min-width: 100px; flex-shrink: 0; }
.month-label { font-size: 12px; font-weight: 600; margin: 0 0 8px; }
.day-grid { display: grid; grid-template-columns: repeat(7, 12px); gap: 3px; margin-bottom: 8px; }
.day-sq { width: 12px; height: 12px; border-radius: 3px; background: var(--day-sq); }
.month-total { font-size: 11px; font-weight: 700; padding: 3px 8px; border-radius: 20px; display: inline-block; }

.streak-note { font-size: 13px; color: var(--text-secondary); margin: 8px 0 24px; }

.summary-row {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 0;
    border: 1px solid var(--border); border-radius: 12px; overflow: hidden;
}
.summary-item { padding: 14px 16px; border-right: 1px solid var(--border); background: var(--card); }
.summary-item:last-child { border-right: none; }
.summary-label { font-size: 12px; color: var(--text-secondary); margin: 0 0 6px; }
.summary-value { font-size: 17px; font-weight: 700; margin: 0; }
.returns-row { margin-bottom: 20px; }
.returns-row:empty { display: none; }

.cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); border: 1px solid var(--border); border-radius: 10px; overflow: hidden; }
.cal-head {
    font-size: 11px; font-weight: 700; color: var(--text-secondary); text-transform: uppercase;
    padding: 8px 10px; background: var(--subtle-bg); border-bottom: 1px solid var(--border);
}
.cal-cell { min-height: 68px; padding: 8px 10px; border-right: 1px solid var(--border); border-bottom: 1px solid var(--border); font-size: 12px; position: relative; }
.cal-cell.blank { background: var(--subtle-bg); }
.cal-date { font-weight: 600; }
.cal-trades { position: absolute; top: 8px; right: 10px; font-size: 10px; color: var(--text-muted); }
.cal-pnl { margin-top: 18px; font-weight: 700; font-size: 12px; }

.week-row { display: grid; grid-template-columns: repeat(7, 1fr); gap: 10px; margin-bottom: 18px; }
/* Working days are white cards on the page; a weekend is tinted and muted so the two read apart. */
.week-card { border: 1px solid var(--border); border-radius: 10px; padding: 12px; text-align: center; background: var(--card); }
.week-card.weekend { background: var(--weekend-bg); }
.week-card.weekend .week-date, .week-card.weekend .week-day { color: var(--text-muted); }
.week-day { font-size: 11px; color: var(--text-muted); text-transform: uppercase; margin: 0 0 4px; }
.week-date { font-size: 13px; font-weight: 600; margin: 0 0 8px; }
.week-pnl { font-size: 14px; font-weight: 700; }
.week-trades { font-size: 10px; color: var(--text-muted); margin-top: 2px; }

.stat-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 10px; margin-bottom: 18px; }
.stat-card { background: var(--card); border: 0.5px solid var(--border); border-radius: var(--radius); padding: 12px 14px; }
.stat-label { font-size: 12px; color: var(--text-secondary); margin: 0 0 4px; }
.stat-value { font-size: 18px; font-weight: 700; margin: 0; }
.stat-sub { font-size: 11px; color: var(--text-muted); margin: 3px 0 0; }
.stat-sub-inline { font-size: 11px; font-weight: 400; color: var(--text-muted); }
.day-sq[data-pnl] { cursor: pointer; }
.day-sq[data-pnl]:hover { outline: 2px solid var(--blue); outline-offset: 1px; }
.cal-cell.has-trades { cursor: pointer; }
.cal-cell.has-trades:hover { filter: brightness(0.96); }

.bg-green { background: var(--green-bg); }
.bg-red { background: var(--red-bg); }
.bg-amber { background: var(--amber-bg); }

/*
 * Day markers - weekend, market holiday, expiry day - shared by every calendar in the UI: the
 * dashboard's trade-diary squares (.mini-day-sq), and on reports.html the heat-map squares
 * (.day-sq), the month calendar (.cal-cell) and the week cards (.week-card). The classes are set
 * by MarketDays.classify() in api.js from /api/calendar; nothing here decides what a day IS.
 *
 * EVERY DAY KIND DIFFERS IN KIND, NEVER BY A SHADE: an idle working day is a solid square
 * (--day-sq), a weekend is hollow, a holiday is a darker solid grey, a traded day is filled with
 * its P&L colour (inline, so it always wins over a marker's background), EXPIRY IS A CENTRED DOT
 * (--expiry-dot) and a special session is the one RING (--special-ring).
 *
 * Expiry was a pastel violet ring until 19 Sep 2026. Two things were wrong with it: it was the
 * same lavender in every theme, and it was the same SHAPE as the special-session ring in a
 * neighbouring pastel - Sunday 8 Nov 2026 (Diwali Muhurat trading, a PARTIAL special session)
 * read as "a Sunday expiry" to the owner. Hence the rule above. The dot's colour is the theme's
 * own: its --accent where that cannot be mistaken for a P&L fill (Claude coral, Solarized cyan,
 * Forest orange, Ocean cyan, Earth terracotta, Quiet Light purple; Pastel takes the strip's
 * orange), and the theme's ink (--text) where the accent is a green (Light, Dark, Sage, Flat) -
 * on these calendars a green mark would read as profit. Expiry is never a FILL for that reason.
 *
 * Tones (owner's review, 17 Sep 2026): markers stay quiet beside the P&L fills - every calendar
 * sits on a card, and weekends must not sink into the page colour.
 * (Themes other than Light and Dark set these tokens in their blocks at the top of the file.)
 */
:root {
    --day-sq: #e2e0d6; --weekend-line: #d6d4ca;
    --expiry-dot: var(--text);
    --holiday-sq: #b4b2a9; --holiday-bg: #eceae4;
    --special-ring: #8fbbe8;
}
html[data-theme="dark"] {
    --day-sq: #3a3b40; --weekend-line: #3a3b40;
    --holiday-sq: #6a6963; --holiday-bg: #2a2b2e;
    --special-ring: #5d8fc2;
}

.mini-day-sq.day-weekend, .day-sq.day-weekend, .day-legend-sq.day-weekend {
    background: transparent; box-shadow: inset 0 0 0 1px var(--weekend-line);
}
.mini-day-sq.day-holiday, .day-sq.day-holiday, .day-legend-sq.day-holiday { background: var(--holiday-sq); }
/* Expiry: a centred dot. Its 1px halo is the card colour, so the dot separates from whatever
   fills the square - idle grey, a pastel loss, a saturated win - without a second colour. Sizes
   keep the dot on whole pixels: 4px in a 12px square, 5px in the 13px and 11px ones. */
.mini-day-sq, .day-sq, .day-legend-sq { position: relative; }
.mini-day-sq.day-expiry::after, .day-sq.day-expiry::after, .day-legend-sq.day-expiry::after {
    content: ''; position: absolute; left: 50%; top: 50%; width: 5px; height: 5px; margin: -2.5px 0 0 -2.5px;
    border-radius: 50%; background: var(--expiry-dot); box-shadow: 0 0 0 1px var(--card); pointer-events: none;
}
.day-sq.day-expiry::after { width: 4px; height: 4px; margin: -2px 0 0 -2px; }
/* A special trading session (Budget day on a Sunday = FULL, Muhurat trading = PARTIAL): a blue
   ring - the ONLY ring on these calendars since expiry became a dot. The square underneath still says what the day otherwise is - a FULL session is a
   solid trading-day square (it is no longer a "weekend"), a Muhurat day keeps its grey holiday
   or hollow weekend look. Declared after the weekend/expiry rules so its ring wins. */
.mini-day-sq.day-special, .day-sq.day-special, .day-legend-sq.day-special {
    box-shadow: inset 0 0 0 2px var(--special-ring);
}
/* A TRADED special-session day - Budget Sunday 1 Feb 2026, a Muhurat day that books an exit - is
   the one case where that ring sits on a P&L fill, and since 20 Sep 2026 that fill is a
   continuous ramp: the ring's luminance lies BETWEEN the ramp's two ends, so some day was certain
   to land on it exactly. Measured across all 13 themes the ring against the fill falls to
   1.00-1.04:1 (it was an already-poor 1.03-1.48:1 when only the two endpoint colours existed).
   So those squares, AND ONLY THOSE, get a 1px well of card colour between ring and fill - the
   separation the expiry dot has had all along. Ring-vs-card is theme-fixed at 2.01:1 (Light) to
   4.57:1 (Dark) and nothing the ramp does can reach it.
   Scoped to [data-pnl] because the well is not free: it costs a pixel each side, and on a 12px
   square that is a third of the coloured core. An untraded special session has no fill to be
   confused with and keeps the plain ring.
   ORDER MATTERS AND READS BACKWARDS: the FIRST shadow paints on top, so ring-then-card leaves the
   ring at the square's edge and puts the card band inside it. Card-then-ring would put the band
   in the grid gap - which is already card colour - and leave the ring touching the fill, i.e. no
   change at all. Not `outline`: [data-pnl]:hover already uses one and the two would fight. */
.mini-day-sq.day-special[data-pnl], .day-sq.day-special[data-pnl] {
    box-shadow: inset 0 0 0 2px var(--special-ring), inset 0 0 0 3px var(--card);
}
.mini-day-sq[data-mark] { cursor: default; }
.mini-day-sq[data-pnl] { cursor: pointer; }
/* The diary square's hover affordance is the heat map's (see .day-sq[data-pnl]:hover above), and
   it has to be an OUTLINE, not a fill: every traded square carries an inline background, so a
   hover FILL either loses to it or - worse, if it ever won - erases the day's P&L colour. This
   replaces exactly that, a --hover-bg entry in the shared flat-hover rule that an inline
   background had made unreachable since the day the squares were built. It matters more now that
   the colours are a continuous ramp: neighbouring days look more alike, so "which square am I
   on?" is a question the pointer has to answer. */
.mini-day-sq[data-pnl]:hover { outline: 2px solid var(--blue); outline-offset: 1px; }

/* :not(.has-trades) - a day that holds a trade keeps its P&L colour even if the holiday list is
   wrong about it (it was, for four 2026 dates, until 17 Sep 2026); the tag still shows. */
.cal-grid { background: var(--card); }
.cal-cell.day-weekend:not(.has-trades) { background: var(--weekend-bg); }
.cal-cell.day-weekend .cal-date { color: var(--text-muted); }
.cal-cell.day-holiday:not(.has-trades) { background: repeating-linear-gradient(135deg, var(--holiday-bg) 0 6px, var(--hatch-alt) 6px 12px); }
.cal-cell.day-holiday .cal-date { color: var(--text-secondary); }
.cal-mark {
    display: inline-block; margin-left: 6px; padding: 1px 6px; border-radius: 8px; vertical-align: 1px;
    font-size: 9px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; white-space: nowrap;
}
/* In the cell views expiry is the same dot, leading its tag; the cell keeps no coloured edge. */
.cal-mark.expiry { background: var(--chip-bg); color: var(--text-secondary); }
.cal-mark.expiry::before {
    content: ''; display: inline-block; width: 5px; height: 5px; border-radius: 50%; margin-right: 4px;
    vertical-align: 1px; background: var(--expiry-dot);
}
.cal-mark.holiday { background: var(--mark-holiday-bg); color: var(--text-secondary); }
.cal-mark.special { background: var(--blue-bg); color: var(--blue); }
.cal-cell.day-special, .week-card.day-special { box-shadow: inset 0 3px 0 var(--special-ring); }
.day-legend-cells .day-legend-sq.day-special {
    background: var(--card); box-shadow: inset 0 3px 0 var(--special-ring), inset 0 0 0 1px var(--border);
}

.week-card.day-holiday { background: repeating-linear-gradient(135deg, var(--holiday-bg) 0 6px, var(--hatch-alt) 6px 12px); }
.week-card.day-holiday .week-date { color: var(--text-secondary); }
.week-card .cal-mark { margin-left: 5px; }

.day-legend { display: flex; flex-wrap: wrap; gap: 4px 14px; font-size: 11px; color: var(--text-muted); margin: 0 0 8px; }
.day-legend-stacked { flex-direction: column; gap: 3px; margin: 8px 0 0; align-items: flex-start; }
.day-legend-item { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
.day-legend-sq { width: 11px; height: 11px; border-radius: 3px; background: var(--day-sq); flex: 0 0 auto; }
/* The month calendar and the week cards draw days as CELLS, not squares - white working day,
   tinted weekend, hatched holiday, a dot for expiry - so their key shows those. */
.day-legend-cells .day-legend-sq { background: var(--card); box-shadow: inset 0 0 0 1px var(--border); }
.day-legend-cells .day-legend-sq.day-weekend { background: var(--weekend-bg); box-shadow: inset 0 0 0 1px var(--border); }
.day-legend-cells .day-legend-sq.day-holiday {
    background: repeating-linear-gradient(135deg, var(--holiday-sq) 0 2px, var(--hatch-alt) 2px 4px);
    box-shadow: inset 0 0 0 1px var(--border);
}

/*
 * The P&L colour scale's key, built by the legendHtml() that PnlHeat.scale() returns (api.js,
 * 20 Sep 2026; it is a method on the scale, not on the module). A calendar square's
 * colour is continuous now - it moves with the money from the palest tint at a near-flat day up
 * to the theme's full brick colour at the largest single day in view - so the key has to be
 * continuous too. Its bar is not a decoration and not a hand-drawn approximation: THE GRADIENT
 * STOPS ARE EMITTED BY THE VERY FUNCTION THAT COLOURS A SQUARE and the two figures either side
 * are the real ends of the scale, so the bar IS the mapping, curve and all. No colour appears
 * here: the gradient arrives as an inline color-mix() over the same var() tokens the squares
 * carry, so the key follows a live theme switch exactly as they do.
 */
.pnl-scale { display: flex; align-items: center; gap: 7px; margin: 2px 0 6px; }
.pnl-scale-bar {
    flex: 1 1 auto; min-width: 48px; max-width: 260px; height: 9px; border-radius: 5px;
    box-shadow: inset 0 0 0 1px var(--border);
}
.pnl-scale-end { font-size: 11px; font-weight: 600; white-space: nowrap; }
.pnl-scale-note { margin: 0 0 8px; font-size: 11px; color: var(--text-muted); }
/* The dashboard's trade diary is a narrow side column: the bar, the two figures, and only the
   SCOPE of the sentence the wide key prints in full (the rest is the bar's title). That much has
   to be visible rather than hovered - the diary draws three months while its figures come from
   the source's whole history, so without it the key labels itself with days that are not on the
   calendar beneath it. */
.pnl-scale-compact { gap: 5px; margin: 6px 0 2px; }
.pnl-scale-compact .pnl-scale-end { font-size: 10px; font-weight: 600; }
.pnl-scale-compact .pnl-scale-bar { min-width: 34px; height: 8px; }
.pnl-scale-note-compact { font-size: 10px; margin: 0 0 4px; }

/*
 * Option chain widget.
 *
 * The mockup (goldmine_final_v2.html, "Option chain" card) styled this almost entirely with
 * classes that already exist above - .card, .card-header-row, .mode-pill for the expiry tabs,
 * table.legs for the grid and .tag-* for the SELL/HEDGE/ATM badges - and set the few remaining
 * bits with inline styles on generated rows. Those inline styles are lifted into real classes
 * here rather than re-emitted from JavaScript on every render, and no new colours are introduced:
 * every value below reuses a token already defined at the top of this file.
 */
/* Fixed height with a sticky header (see table.legs th above), matching goldmine_final_v2.1.html's
   updated Option chain card - the strategy trades ~20 strikes each side of ATM, more than any
   card should show uncropped, so the table scrolls internally rather than growing the page. */
/* position:relative is load-bearing, not decorative: without it, atmRow.offsetTop in
   scrollAtmIntoView() resolves against whatever ancestor IS positioned (or the document, if none
   is), not this container - the auto-center math would use the wrong reference frame entirely. */
.chain-scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; position: relative; }
.chain-side { text-align: center; color: var(--text-muted); font-size: 11px; }
/* table.legs td sets text-align:right at higher specificity (element+class+element beats a bare
   class) - td.chain-strike matches that specificity so this override actually takes effect. */
table.legs td.chain-strike { text-align: center; font-weight: 700; }
.chain-atm { background: var(--atm-bg); }
/* In-the-money cells (27 Sep 2026): shown on a quieter surface, no longer blanked - the chain is
   common to every strategy now, and the Golden Crossover and the Camarilla buy ITM options. */
table.legs td.chain-itm { background: var(--subtle-bg); }
.tag-mini { padding: 1px 6px; font-size: 10px; margin-left: 4px; }
/* Distinct from .note: this is a refusal the engine acted on, not a caption. */
.chain-warning { font-size: 12px; margin-top: 10px; padding: 8px 10px; border-radius: 8px;
    background: var(--red-bg); color: var(--red); font-weight: 600; }
.chain-warning.soft { background: var(--amber-bg); color: var(--amber); }
.chain-empty { font-size: 13px; color: var(--text-muted); padding: 10px 0; }

/* ==================================================================== */
/* Workbench frame - activity bar, side panel, top strip (19 Sep 2026)  */
/* ==================================================================== */

/*
 * index.html is one document laid out like an editor: an icon-only activity bar down the left
 * edge, a side panel beside it for areas with sections, then the main column (top bar, mode
 * banner, backtest transport, routed view). shell.js puts has-panel / panel-collapsed on <body>
 * and data-area on it; everything below keys off those. The bar is chrome, and it has to read
 * as separate from the cards: dark in Light, Dark and Solarized Dark, lavender in Quiet Light -
 * with quiet icons that strengthen on hover and carry the theme's --accent edge (the same one
 * the report tabs underline with) when active. The hover label has its own --tip-* colours
 * because it cannot borrow the bar's once a bar is light. Solarized Dark and Quiet Light set
 * these four tokens in their own blocks at the top of this file.
 */
:root { --actbar-bg: #26282c; --actbar-fg: #8e939b; --actbar-fg-on: #ffffff; --panel-bg: #fbfaf7; --tip-bg: #26282c; --tip-fg: #ffffff;
        /* the active icon's marker: an --accent edge by default; a theme may swap it for a rounded plate */
        --actbar-plate: transparent; --actbar-plate-hover: transparent; --actbar-edge: var(--accent); }
html[data-theme="dark"] { --actbar-bg: #0f1011; --actbar-fg: #7c7a76; --actbar-fg-on: #eceae4; --panel-bg: #1d1e20; --tip-bg: #0f1011; --tip-fg: #eceae4; }

body.wb { height: 100vh; overflow: hidden; display: flex; }

.actbar {
    flex: 0 0 50px; background: var(--actbar-bg); display: flex; flex-direction: column;
    align-items: center; padding: 8px 0 10px; gap: 2px; z-index: 40;
}
.act {
    width: 50px; height: 46px; display: flex; align-items: center; justify-content: center;
    background: none; border: none; border-left: 2px solid transparent; border-right: 2px solid transparent;
    color: var(--actbar-fg); cursor: pointer; position: relative; padding: 0;
}
/* position: relative keeps the icon ABOVE the plate, which is an absolutely positioned ::before. */
.act svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; position: relative; }
/* The plate is ::before because ::after is the hover label. Transparent unless a theme sets it. */
.act::before { content: ''; position: absolute; inset: 4px 7px; border-radius: 8px; background: transparent; }
.act:hover::before, .act:focus-visible::before { background: var(--actbar-plate-hover); }
.act.active::before { background: var(--actbar-plate); }
.act:hover, .act:focus-visible { color: var(--actbar-fg-on); outline: none; }
.act.active { color: var(--actbar-fg-on); border-left-color: var(--actbar-edge); }
/* The label an icon-only bar needs: appears beside the icon on hover, never takes layout space. */
.act::after {
    content: attr(data-title); position: absolute; left: 54px; top: 50%; transform: translateY(-50%);
    background: var(--tip-bg); color: var(--tip-fg); font-size: 12px; font-weight: 600; white-space: nowrap;
    padding: 5px 9px; border-radius: 6px; opacity: 0; pointer-events: none; transition: opacity 120ms ease;
    box-shadow: 0 2px 8px rgba(0,0,0,0.25);
}
.act:hover::after, .act:focus-visible::after { opacity: 1; }
.act-spacer { flex: 1 1 auto; }
.actbar .avatar { margin-top: 8px; width: 32px; height: 32px; font-size: 12px; }

.sidepanel {
    flex: 0 0 218px; background: var(--panel-bg); border-right: 0.5px solid var(--border);
    padding: 16px 0; overflow-y: auto; display: none;
}
body.has-panel:not(.panel-collapsed) .sidepanel { display: block; }
.sp-title { font-size: 11px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-muted); margin: 0 0 10px; padding: 0 16px; }
.sp-group { font-size: 10px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-muted); margin: 14px 0 4px; padding: 0 16px; }
.sp-section a {
    display: block; padding: 7px 16px 7px 14px; font-size: 13px; color: var(--text-secondary);
    text-decoration: none; border-left: 2px solid transparent;
}
.sp-section a:hover { color: var(--text); background: var(--nav-hover-bg); }
.sp-section a.active { color: var(--text-strong); font-weight: 700; border-left-color: var(--accent); background: var(--nav-active-bg); }
.sp-hint { font-size: 11px; color: var(--text-muted); margin: 16px 16px 0; line-height: 1.45; }
.sp-inline-link { font-size: 12px; font-weight: 600; color: var(--blue); text-decoration: none; }
.sp-inline-link:hover { text-decoration: underline; }
/* A link inside a side-panel hint is running text, not a section link (2 Oct 2026). */
.sp-section .sp-hint a { display: inline; padding: 0; border: 0; font-size: inherit; color: var(--blue); background: none; }

/*
 * The Strategies section is a TREE (27 Sep 2026; the owner found the flat list - strategy names
 * styled like the links under them, "Live / Trades / Backtest / Settings" four times over - hard
 * to read). A strategy is a header button - chevron, its name in ordinary case, a badge in its
 * mode's colour (the top bar's .mode-chip colours) - with its tabs indented beneath, each with an
 * icon, along an indent guide under the chevron. strategies.js keeps one strategy open at a time
 * (.open) and marks the one on screen (.current), which shows on the header while it is folded.
 * The icons are CSS masks filled with currentColor, chosen from the tab in data-sub, so a link
 * strategies.js builds for a new strategy gets its icon with no markup of its own.
 */
.sp-strategy + .sp-strategy { border-top: 0.5px solid var(--border); }
.sp-strategy-head {
    display: flex; align-items: center; gap: 6px; width: 100%; margin: 0;
    padding: 9px 10px 9px 8px; border: none; border-left: 2px solid transparent; background: none;
    font: inherit; font-size: 13px; font-weight: 600; color: var(--text); text-align: left; cursor: pointer;
}
.sp-strategy-head::before {
    content: ''; flex: 0 0 12px; height: 12px; background-color: var(--icon-fg);
    transform: rotate(-90deg); transition: transform 120ms ease;
    -webkit-mask: 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.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E") center / contain no-repeat;
    mask: 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.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E") center / contain no-repeat;
}
.sp-strategy.open > .sp-strategy-head::before { transform: none; }
.sp-strategy-head:hover { background: var(--nav-hover-bg); }
.sp-strategy.current > .sp-strategy-head { color: var(--text-strong); }
.sp-strategy.current:not(.open) > .sp-strategy-head { border-left-color: var(--accent); background: var(--nav-active-bg); }
.sp-strategy-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sp-mode {
    flex: none; padding: 2px 6px; border-radius: 5px; font-size: 9.5px; font-weight: 700; line-height: 1.3;
    letter-spacing: 0.05em; text-transform: uppercase; background: var(--chip-bg); color: var(--text-muted);
}
.sp-mode[data-mode="backtest"] { background: var(--blue-bg); color: var(--blue); }
.sp-mode[data-mode="paper"] { background: var(--amber-bg); color: var(--amber); }
.sp-mode[data-mode="live"] { background: var(--green-bg); color: var(--green); }
.sp-strategy-tabs { display: none; position: relative; padding: 0 0 8px; }
.sp-strategy.open > .sp-strategy-tabs { display: block; }
/* The indent guide, under the chevron. */
.sp-strategy-tabs::before { content: ''; position: absolute; left: 16px; top: 0; bottom: 10px; border-left: 1px solid var(--border); }
.sp-section .sp-strategy-tabs a { display: flex; align-items: center; gap: 8px; padding: 6px 12px 6px 26px; font-size: 12.5px; }
.sp-strategy-tabs a::before {
    content: ''; flex: 0 0 14px; height: 14px; background-color: currentColor; opacity: 0.7;
    -webkit-mask: var(--sp-icon) center / contain no-repeat; mask: var(--sp-icon) center / contain no-repeat;
}
.sp-strategy-tabs a.active::before, .sp-strategy-tabs a:hover::before { opacity: 1; }
.sp-strategy-tabs a { --sp-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='3'/%3E%3C/svg%3E"); }
.sp-strategy-tabs a[data-sub$="/live"] { --sp-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='M22 12h-4l-3 9L9 3l-3 9H2'/%3E%3C/svg%3E"); }
.sp-strategy-tabs a[data-sub$="/payoff"] { --sp-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 20h18'/%3E%3Cpath d='M3 15h5l4-8 4 8h5'/%3E%3C/svg%3E"); }
.sp-strategy-tabs a[data-sub$="/trade"] { --sp-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='9'/%3E%3Cpath d='M12 8v8M8 12h8'/%3E%3C/svg%3E"); }
.sp-strategy-tabs a[data-sub$="/rules"] { --sp-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 6l2 2 4-4M3 17l2 2 4-4M13 6h8M13 12h8M13 18h8'/%3E%3C/svg%3E"); }
.sp-strategy-tabs a[data-sub$="/chain"] { --sp-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='18' rx='2'/%3E%3Cpath d='M3 9h18M3 15h18M12 3v18'/%3E%3C/svg%3E"); }
.sp-strategy-tabs a[data-sub$="/backtest"] { --sp-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 3v5h5M12 7v5l4 2'/%3E%3C/svg%3E"); }
.sp-strategy-tabs a[data-sub$="/profiles"] { --sp-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='9' cy='7' r='4'/%3E%3Cpath d='M2 21v-2a4 4 0 0 1 4-4h6a4 4 0 0 1 4 4v2M16 3.1a4 4 0 0 1 0 7.8M22 21v-2a4 4 0 0 0-3-3.9'/%3E%3C/svg%3E"); }
.sp-strategy-tabs a[data-sub$="/trades"] { --sp-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 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z'/%3E%3Cpath d='M14 2v6h6M16 13H8M16 17H8'/%3E%3C/svg%3E"); }
.sp-strategy-tabs a[data-sub$="/settings"] { --sp-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='M4 21v-7M4 10V3M12 21v-9M12 8V3M20 21v-5M20 12V3M1 14h6M9 8h6M17 16h6'/%3E%3C/svg%3E"); }

.wb-main { flex: 1 1 auto; min-width: 0; height: 100vh; display: flex; flex-direction: column; }
.wb-main .topbar { position: static; padding: 8px 18px; flex: 0 0 auto; }
.wb-main .mode-banner { flex: 0 0 auto; margin: 0; border-radius: 0; padding: 6px 18px; }
#views { flex: 1 1 auto; min-height: 0; overflow: auto; }

/* The live strip in the top bar: the same figures in every view. */
.tb-stats { display: flex; align-items: center; gap: 22px; flex-wrap: wrap; }
.tb-stat { display: flex; flex-direction: column; line-height: 1.2; min-width: 0; }
.tb-label { font-size: 10px; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.04em; white-space: nowrap; }
.tb-value { font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }
.tb-countdown { min-width: 190px; }
.tb-countline { display: flex; align-items: center; gap: 8px; }
.tb-countline .progress-track { flex: 1 1 auto; height: 6px; margin: 0; display: block; min-width: 90px; }
.tb-countline .progress-fill { display: block; height: 100%; }

/* The backtest transport belongs to the live views; a report or a setting has no use for it. */
body[data-area="reports"] #backtestControls,
body[data-area="settings"] #backtestControls,
body[data-area="schedulers"] #backtestControls { display: none; }

section.view.live-view { height: 100%; display: flex; flex-direction: column; gap: 10px; padding: 10px 16px 12px; min-height: 0; }
/* A document view takes the whole width the window gives it (27 Sep 2026, the owner: "there is
   space at right side. the panels should adjust the size based on browser size and screen
   resolution"). It was capped at 1560px, which left an empty strip beside Home, Settings and
   every other document view on a wide screen; the card grids inside size their columns to the
   width instead. */
section.view.doc-view { padding: 18px 22px 40px; }

/* Monitor (27 Sep 2026): two columns - the charts, and beside them the P&L headline with the
   engine status, the day's live P&L graph across the column's full width, and the open
   positions. Until then a third column squeezed the live P&L graph to ~180px; the payoff card
   that took the middle column's height is Goldmine's Payoff tab now (.payoff-page-card). */
.monitor-grid {
    flex: 1 1 auto; min-height: 0; display: grid; gap: 10px;
    grid-template-columns: minmax(0, 5fr) minmax(0, 4fr);
}
.mon-col { display: flex; flex-direction: column; gap: 10px; min-height: 0; min-width: 0; }
.mon-col > * { min-width: 0; }
.mon-top { flex: 0 0 auto; display: grid; gap: 10px; grid-template-columns: minmax(0, 1fr) minmax(190px, 0.6fr); }
.mon-top > .card { min-width: 0; }
.live-pnl-card { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0; }
.live-pnl-wrap { position: relative; flex: 1 1 0; min-height: 160px; }
.chart-card { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0; }
/* Three stacked panes sharing one brick-index axis: price, RSI, Choppiness (20 Sep 2026). The
   ratios follow the reference screenshot - roughly 56% price, 20% RSI, 24% Choppiness - and the
   bottom pane is the taller of the two oscillators because it carries the card's only visible
   time labels (~20px of the box is axis, not plot). */
.chart-main { position: relative; width: 100%; flex: 3.2 1 0; min-height: 150px; margin-bottom: 4px; }
.chart-rsi { position: relative; width: 100%; flex: 1.15 1 0; min-height: 74px; margin-bottom: 4px; }
.chart-ci { position: relative; width: 100%; flex: 1.35 1 0; min-height: 86px; }
.payoff-card { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0; }
/* Every strategy's Payoff tab (27 Sep 2026): the one card, filling the view. Goldmine's plot
   keeps its #payoffChartWrap id (dashboard.js hides it by id while flat); the others' plots are
   .payoff-page-wrap, hidden by attribute while flat. */
.payoff-page-card { flex: 1 1 auto; }
#payoffChartWrap, .payoff-page-wrap { position: relative; width: 100%; flex: 1 1 0; min-height: 260px; }
.payoff-page-wrap[hidden] { display: none; }
.pos-card { flex: 0 0 auto; max-height: 36%; overflow-y: auto; }

/* Rules and the option chain have a whole view each now, so they use its width. */
#view-rules > .card { flex: 1 1 auto; }
#view-rules .rule-pane { overflow-y: auto; min-height: 0; }
@media (min-width: 1500px) { #view-rules .rule-board.two-col { column-count: 3; } }
/* The Rules board of every other strategy (3 Oct 2026, strategy-rules.js): Goldmine's card, built
   per strategy, so it is sized by class where Goldmine's is sized by id. Its rows carry the rule's
   id as a chip, and its verdict has a fourth state - waiting for a time, neither ready nor blocked. */
.rules-view > .card { flex: 1 1 auto; }
.rules-view .rule-pane { overflow-y: auto; min-height: 0; }
@media (min-width: 1500px) { .rules-view .rule-board.two-col { column-count: 3; } }
/* Its groups may break across columns (rows never split, a title never ends a column): a strategy's
   rails or its unjudged "as configured" list is one long group, and kept whole it would leave the
   other columns empty. Goldmine's entry groups are short and stay whole. */
.rules-view .rule-board.inline-rows .rule-group { break-inside: auto; }
.rule-verdict.waiting { background: var(--amber-bg); color: var(--amber); }
.rule-id {
    display: inline-block; margin-right: 6px; padding: 0 5px; border-radius: 4px; background: var(--chip-bg);
    color: var(--text-secondary); font-size: 10px; font-weight: 700; letter-spacing: 0.02em; vertical-align: 1px;
}
.rule-row.na .rule-id { color: var(--text-muted); }
.rules-asof { margin: 8px 0 0; }
.chain-card-full { flex: 1 1 auto; max-width: 1100px; width: 100%; margin: 0 auto; }
.chain-card-full .chain-scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
#view-activity .log-card { flex: 1 1 auto; }

.account-panel {
    position: fixed; left: 58px; bottom: 10px; width: 300px; max-height: calc(100vh - 20px); overflow-y: auto;
    background: var(--float-bg); border: 1px solid var(--float-border); border-radius: var(--radius);
    box-shadow: var(--float-shadow); padding: 16px; display: none; z-index: 60;
}
.account-panel.open { display: block; }

/* Reports toolbar and two-up breakdown cards. */
.rep-toolbar { margin-bottom: 18px; }
.rep-toolbar .source-row { margin-bottom: 10px; }
.rep-period { display: flex; align-items: center; gap: 22px; flex-wrap: wrap; border-bottom: 1px solid var(--border); }
.rep-period .tab { padding-top: 6px; }
.rep-two-col { display: grid; grid-template-columns: repeat(auto-fit, minmax(440px, 1fr)); gap: 0 16px; }

@media (max-width: 1099px) {
    body.wb { height: auto; overflow: visible; }
    .actbar { position: sticky; top: 0; height: 100vh; }
    .wb-main { height: auto; }
    #views { overflow: visible; }
    section.view.live-view { height: auto; }
    .monitor-grid { display: block; }
    .mon-col { display: block; }
    .mon-col > * { margin-bottom: 10px; }
    .chart-main { height: 220px; flex: none; }
    .chart-rsi { height: 96px; flex: none; }
    .chart-ci { height: 112px; flex: none; }
    .live-pnl-wrap { height: 220px; flex: none; }
    #payoffChartWrap, .payoff-page-wrap { height: 340px; flex: none; }
    .pos-card { max-height: none; }
    .sidepanel { flex-basis: 180px; }
}

/* ==================================================================== */
/* Trade journal and trade analysis (journal.js)                        */
/* ==================================================================== */

.jr-filterbar { padding: 12px 14px; }
.jr-filter-row, .jr-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.jr-head { margin-bottom: 12px; }
.jr-addfilter { display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.jr-addfilter select, .jr-addfilter input, .jr-head select, .jr-head input {
    min-height: 32px; padding: 4px 8px; font-size: 12px; border: 1px solid var(--border);
    border-radius: 7px; background: var(--input-bg); color: var(--text);
}
.jr-chips { display: inline-flex; gap: 6px; flex-wrap: wrap; }
.jr-chip {
    display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600;
    background: var(--blue-bg); color: var(--blue); border-radius: 14px; padding: 4px 6px 4px 10px;
}
.jr-chip button { border: none; background: none; color: inherit; cursor: pointer; font-size: 14px; line-height: 1; padding: 0 3px; }
.jr-summary { margin: 0 0 12px; }
.jr-scroll { overflow: auto; max-height: 74vh; border: 0.5px solid var(--border); border-radius: 8px; }
.jr-table { margin: 0; white-space: nowrap; }
.jr-table thead th { position: sticky; top: 0; background: var(--card); z-index: 2; cursor: pointer; user-select: none; }
.jr-table thead th.sorted { color: var(--text); }
.jr-table td, .jr-table th { padding-left: 10px; padding-right: 10px; }
.jr-table td.txt, .jr-table th.txt { text-align: left; }
.jr-table tbody tr.jr-row { cursor: pointer; }
.jr-table tbody tr.jr-row:hover td { background: var(--row-hover-bg); }
.jr-table tbody tr.jr-row.open td { background: var(--row-open-bg); }
.jr-table tbody tr.jr-row.open td:first-child { box-shadow: inset 2px 0 0 var(--row-open-edge); }
/* Tables nested in an opened row: no card-coloured patch on the detail panel's surface, and NOT
   sticky - they live inside .jr-scroll too, and would pin at top:0 over the journal's own header. */
.jr-detail table.legs th { position: static; background: transparent; cursor: default; user-select: auto; }
.jr-caret { display: inline-block; width: 12px; color: var(--text-muted); transition: transform 120ms ease; }
tr.jr-row.open .jr-caret { transform: rotate(90deg); }
.jr-detail td { white-space: normal; text-align: left; background: var(--panel-bg); padding: 14px 16px 16px; }
.jr-detail h4 { font-size: 11px; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase; color: var(--text-muted); margin: 14px 0 6px; }
.jr-detail h4:first-child { margin-top: 0; }
.jr-detail table.legs { width: auto; min-width: 60%; white-space: nowrap; margin: 0; }
.jr-kv { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 2px 22px; }
.jr-kv div { display: flex; justify-content: space-between; gap: 10px; font-size: 12px; padding: 3px 0; border-bottom: 0.5px solid var(--border); }
.jr-kv div span:first-child { color: var(--text-secondary); }
.jr-kv div span:last-child { font-weight: 600; text-align: right; overflow-wrap: anywhere; }
.jr-detail details { margin-top: 12px; font-size: 12px; }
.jr-detail details summary { cursor: pointer; color: var(--blue); font-weight: 600; }

.jr-colwrap { position: relative; }
.jr-colpanel {
    position: absolute; right: 0; top: 38px; width: min(720px, 80vw); max-height: 60vh; overflow-y: auto; z-index: 30;
    background: var(--float-bg); border: 1px solid var(--float-border); border-radius: var(--radius);
    box-shadow: var(--float-shadow); padding: 14px 16px;
}
.jr-colpanel h4 { font-size: 11px; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase; color: var(--text-muted); margin: 12px 0 6px; }
.jr-colpanel h4:first-of-type { margin-top: 4px; }
.jr-colgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 3px 14px; }
.jr-colgrid label { font-size: 12px; display: flex; align-items: center; gap: 6px; cursor: pointer; }
.jr-colactions { display: flex; gap: 8px; align-items: center; margin-bottom: 6px; }

/* Win-rate bar in the analysis table: green share of a neutral track, the figure beside it. */
.an-bar { display: flex; align-items: center; gap: 8px; }
.an-bar-track { flex: 1 1 auto; height: 8px; border-radius: 4px; background: var(--red-bg); overflow: hidden; min-width: 70px; }
.an-bar-fill { height: 100%; background: var(--green-mid); }
.an-total td { font-weight: 700; border-top: 1px solid var(--border); }

/* A closed leg of the open position: only its plain cells are muted. It used to be the whole row
   at opacity 0.5, which put a booked LOSS at about 2:1 in every theme. The :not() list is
   required: this selector outranks the single-class .pl-* rules. */
table.legs tr.leg-closed td:not(.pl-pos):not(.pl-neg):not(.pl-flat) { color: var(--text-secondary); }

/* Toasts (Toast in api.js). They had NO rule until 19 Sep 2026: the container is appended to
   body.wb, a flex row, so each toast became a bare unstyled column that squeezed the workbench
   for a few seconds. A floating stack now, with the kind on its left edge. */
.toasts { position: fixed; right: 16px; bottom: 16px; z-index: 70; display: flex; flex-direction: column; gap: 8px; pointer-events: none; max-width: 420px; }
.toast {
    background: var(--float-bg); color: var(--text); border: 1px solid var(--float-border); border-left: 3px solid var(--text-muted);
    border-radius: 8px; padding: 10px 14px; font-size: 13px; font-weight: 600; box-shadow: var(--float-shadow);
}
.toast.ok { border-left-color: var(--green); }
.toast.err { border-left-color: var(--red); }
.toast.info { border-left-color: var(--blue); }

/* ==========================================================================
   Settings > Rules on / off (20 Sep 2026)

   The owner's "list all the entry rules and exit rules with checkbox". The rows are built by
   settings.js from RuleCatalog, so nothing here may assume a fixed set of rules - only the
   shapes: a switchable row (text + checkbox), a locked row (text + padlock, no input) and the
   two heading levels. Every colour is a token, as everywhere else, so all thirteen themes get
   this for free; the dimming reuses the same two opacity tokens .settings-row.dimmed does, so a
   field dimmed by its rule looks exactly like one dimmed by a mode dropdown.
   ========================================================================== */
.rules-actions { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; margin: 0 0 10px; }
.rules-actions input[type=search] {
    flex: 0 0 200px; padding: 6px 10px; border: 1px solid var(--border); border-radius: 6px;
    font-size: 13px; background: var(--input-bg); color: var(--text);
}
.rules-actions .note { margin-top: 0; flex: 1 1 200px; }
.rules-actions .rules-off { color: var(--amber); font-weight: 600; }

/* Tabs and panels (27 Sep 2026) replaced the one list that scrolled inside a 460px box: the
   owner asked for the switches grouped into panels and tabs. The card takes the whole row of the
   settings grid, and a tab's panels (one per RuleCatalog group) flow into as many columns as fit
   - CSS columns rather than a grid, as on the rule board, so panels of different lengths pack
   without gaps; a panel never splits across a column break. Nothing scrolls inside the card. */
/* order: -1 (27 Sep 2026): in All settings the full-width card came third, after Trading mode and
   the Backtest window, and every column those two did not fill was left empty above it. Placed
   first, it heads the page and the packed cards (.masonry) fill everything below it. */
.spage-grid > .rules-card { grid-column: 1 / -1; order: -1; }
.rules-tabs { flex: 0 0 auto; }
.rules-tab-badge { margin-left: 6px; font-size: 11px; font-weight: 600; color: var(--text-muted); }
.rules-tab-badge:empty { display: none; }
.rules-tabs .rules-tab-badge.rules-off { color: var(--amber); }
.rules-panels { columns: 3 320px; column-gap: 14px; }
.rules-panel {
    break-inside: avoid; margin: 0 0 14px; padding: 2px 12px 0;
    border: 1px solid var(--border); border-radius: 8px;
}
.rules-panel-head {
    display: flex; justify-content: space-between; align-items: baseline; gap: 8px;
    padding: 8px 0 6px; border-bottom: 1px solid var(--border);
}
.rules-panel-title {
    font-size: 11px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
    color: var(--text-strong);
}
.rules-panel-count { font-size: 11px; color: var(--text-muted); white-space: nowrap; }
.rules-panel-count.rules-off { color: var(--amber); font-weight: 600; }
.rules-nomatch { margin: 0; }

.rule-row {
    display: flex; justify-content: space-between; align-items: flex-start; gap: 12px;
    padding: 8px 0; border-bottom: 0.5px solid var(--border); font-size: 13px;
}
.rule-row:last-child { border-bottom: none; }
.rule-text { display: flex; flex-direction: column; gap: 2px; flex: 1 1 auto; min-width: 0; }
.rule-text > b { font-weight: 600; color: var(--text); }
.rule-desc { font-size: 12px; color: var(--text-muted); }
/* The consequence of switching a rule OFF - the same sentence the confirmation repeats. Amber
   rather than red: it is a caution about a choice, not an error. */
.rule-warn { font-size: 12px; color: var(--amber); }
.rule-row input[type=checkbox] {
    width: 18px; height: 18px; flex-shrink: 0; margin-top: 2px; accent-color: var(--check-accent);
}
/* A rule the operator cannot switch off: the padlock is the whole control, so it must read as
   a statement rather than as a disabled input. */
.rule-lock {
    flex-shrink: 0; font-size: 11px; color: var(--text-muted); white-space: nowrap;
    padding: 2px 8px; border-radius: 10px; background: var(--chip-bg); cursor: help;
}
.rule-row.dimmed > .rule-text > b, .rule-row.dimmed > .rule-text > .rule-desc {
    opacity: var(--dim-label-opacity);
}
.rule-row input:disabled { opacity: var(--disabled-input-opacity); cursor: not-allowed; }

/* The card left behind where the Trade direction and Trade types switches used to be. */
.rules-pointer .card-sub { margin-bottom: 0; }
.rules-pointer a, .settings-row a, .card-sub a { color: var(--blue); }

/* Trading profiles on the Settings page (25 Sep 2026). A profile edits its own copy of the
   profile keys through the same [data-key] inputs; a GLOBAL key is shared by every profile and
   is dimmed (the same two opacity tokens .dimmed uses) with the sentence that says why. The
   row-level controls take .profile-hidden while another profile is on screen - NOT the shell's
   .hidden, which shell.js rewrites on every route change. */
.spage-actions .profile-pick { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-muted); }
.spage-actions .profile-pick select { max-width: 220px; }
.profile-note { margin: 0; font-size: 12px; color: var(--text-muted); flex: 1 1 100%; }
.settings-row.global-locked > span:first-child::after,
.rule-row.global-locked > .rule-text > b::after {
    content: " \00b7 shared by every profile"; font-size: 11px; font-weight: 400; color: var(--text-muted);
}
.profile-hidden { display: none !important; }

/* Open positions as blocks (25 Sep 2026): one per position, drawn by position-card.js and shared
   by the Monitor, the Manual trade page and the Profiles page. The profile tag is the blue chip;
   a quarantined block takes a red left edge so it is found at a glance. */
.pos-block { padding: 6px 0 8px; border-bottom: 1px solid var(--border); }
.pos-block:last-child { border-bottom: none; }
.pos-block-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; flex-wrap: wrap; margin-bottom: 4px; }
.pos-block-title { display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.pos-block-actions { display: inline-flex; gap: 6px; }
.pos-block.pos-quarantined { border-left: 3px solid var(--red); padding-left: 8px; }
.pos-profile { font-weight: 600; }
/* The rule board's profile tabs sit under the Entry / Exit tabs, smaller, one per profile. */
.profile-tabs { margin: 4px 0 6px; gap: 6px; }
.profile-tabs .profile-tab { font-size: 12px; }

/* The Manual trade page (25 Sep 2026): two cards side by side, the preview as label/value rows. */
.trade-grid { display: grid; grid-template-columns: minmax(360px, 1fr) minmax(360px, 1.1fr); gap: 16px; align-items: start; }
@media (max-width: 900px) { .trade-grid { grid-template-columns: 1fr; } }
.tr-types { display: inline-flex; flex-wrap: wrap; gap: 4px 14px; font-size: 13px; }
.tr-types label { display: inline-flex; align-items: center; gap: 4px; }
.tr-types small { color: var(--text-muted); }
.tr-types-row { align-items: flex-start; }
.tr-warn { margin: 4px 0 0; font-size: 12px; color: var(--amber); }
.tr-kv { display: flex; flex-direction: column; gap: 2px; margin-bottom: 8px; }
.tr-kv-row { display: flex; gap: 10px; font-size: 13px; padding: 3px 0; border-bottom: 0.5px solid var(--border); }
.tr-kv-row:last-child { border-bottom: none; }
.tr-kv-label { flex: 0 0 130px; color: var(--text-muted); }
.tr-kv-value { flex: 1 1 auto; min-width: 0; }
.tr-guards td { font-size: 12px; text-align: center; }
.tr-guards td:first-child, .tr-guards td:last-child { text-align: left; }
.tr-guards tr:last-child td { font-weight: 400; }

/* The Profiles page (25 Sep 2026): one card per profile. */
.pf-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(360px, 1fr)); gap: 14px; align-items: start; }
.pf-card.pf-archived { opacity: 0.85; }
.pf-section { margin: 10px 0 4px; font-size: 11px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: var(--text-muted); }
.pf-flags { font-size: 12px; display: flex; flex-wrap: wrap; gap: 4px 12px; align-items: center; }
.pf-flags-label { color: var(--text-muted); }
.pf-flags label { display: inline-flex; align-items: center; gap: 4px; }
.pf-flags input[type=checkbox] { accent-color: var(--check-accent); }
.pf-stats { display: grid; grid-template-columns: 1fr 1fr; gap: 4px 14px; font-size: 12px; }
.pf-stat { display: flex; flex-direction: column; }
.pf-stat-label { color: var(--text-muted); font-size: 11px; }
.pf-stat-value { font-weight: 600; }
.pf-actions { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
/* The Manual trade tab of every strategy but Goldmine (27 Sep 2026, strategy-manual.js): one block
   per profile holding a position, separated by a rule like the Monitor's position blocks. */
.mt-pos { padding: 10px 0; border-top: 0.5px solid var(--border); }
.mt-pos:first-child { border-top: none; padding-top: 0; }
.mt-pos-title { margin: 0; font-size: 13px; font-weight: 600; }
.mt-pos .legs td, .mt-pos .legs th { font-size: 12px; }

/* ------------------------------------------------------------------ */
/* Home and the strategy sub-pages (26 Sep 2026)                        */
/* ------------------------------------------------------------------ */
/* The Home view's account strip and strategy cards, and the Rolling Straddle tabs. Tokens only. */
.home-strip { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; margin-top: 8px; }
/* auto-fit, not auto-fill (27 Sep 2026): the columns no card uses collapse, so the strategy cards
   share the whole row whatever the window's width, rather than leaving empty tracks on the right. */
.home-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); gap: 14px; align-items: start; }
.strategy-card .sc-row { display: flex; align-items: center; gap: 10px; margin: 6px 0 10px; font-size: 12px; color: var(--text-secondary); }
.strategy-card .sc-stats { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 6px 14px; font-size: 12px; }
.strategy-card .sc-stat { display: flex; flex-direction: column; }
.strategy-card .sc-stat span { color: var(--text-muted); font-size: 11px; }
.strategy-card .sc-stat b { font-variant-numeric: tabular-nums; font-size: 14px; }
.strategy-card .sc-actions { display: flex; align-items: center; gap: 8px; margin-top: 12px; flex-wrap: wrap; }
.strategy-card .sc-mode { font-size: 12px; color: var(--text-secondary); display: inline-flex; align-items: center; gap: 6px; }
.strategy-card .sc-error { color: var(--red); }
/* "Open" is navigation, so it is a link - no fill, no border (27 Sep 2026, the owner) - pushed to
   the right end of the action row. */
.strategy-card .sc-open { margin-left: auto; font-size: 13px; font-weight: 600; color: var(--blue); text-decoration: none; padding: 4px 2px; }
.strategy-card .sc-open:hover { text-decoration: underline; }
/* The outcome of a mode change or Stop, kept across polls by home.js. */
.strategy-card .sc-msg { margin: 8px 0 0; }
.strategy-card .sc-msg-busy { color: var(--text-secondary); }
.strategy-card .sc-msg-ok { color: var(--green); }
.strategy-card .sc-msg-err { color: var(--red); }
.log-strategy { display: inline-block; font-size: 10px; font-weight: 700; padding: 1px 6px; border-radius: 10px; background: var(--blue-bg); color: var(--blue); vertical-align: middle; }
.log-strategy-sys { background: var(--chip-bg); color: var(--text-secondary); }
.rs-live-grid { display: grid; grid-template-columns: minmax(0, 2fr) minmax(300px, 1fr); gap: 10px; height: 100%; min-height: 0; }
.rs-live-grid .mon-col { display: flex; flex-direction: column; gap: 10px; min-height: 0; }
.rs-live-grid .chart-card { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 280px; }
.rs-chart-wrap { position: relative; flex: 1 1 auto; min-height: 240px; }
.rs-chart-wrap canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
.rs-chart-wrap-doc { height: 320px; flex: none; margin-bottom: 12px; }
.rs-timeline { max-height: 220px; overflow: auto; font-size: 12px; }
.rs-timeline .rs-ev { display: grid; grid-template-columns: 62px 82px 1fr; gap: 8px; padding: 4px 0; border-bottom: 1px solid var(--border); }
.rs-timeline .rs-ev:last-child { border-bottom: none; }
.rs-timeline .rs-ev-kind { font-weight: 700; }
.rs-state { font-size: 13px; display: grid; grid-template-columns: 1fr 1fr; gap: 4px 12px; }
.rs-state .rs-kv span { display: block; font-size: 11px; color: var(--text-muted); }
.rs-state .rs-kv b { font-variant-numeric: tabular-nums; }
.rs-form-row { display: flex; flex-wrap: wrap; gap: 10px 14px; align-items: flex-end; margin: 8px 0; font-size: 12px; }
.rs-form-row label { display: inline-flex; flex-direction: column; gap: 3px; color: var(--text-secondary); }
.rs-settings-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 4px 24px; }
.rs-settings-grid .settings-row input, .rs-settings-grid .settings-row select { max-width: 150px; }
.rs-run-row { cursor: pointer; }
.rs-run-row:hover td { background: var(--hover-bg); }
.rs-progress { height: 8px; border-radius: 4px; background: var(--track-bg); overflow: hidden; margin: 6px 0; }
.rs-progress > span { display: block; height: 100%; background: var(--fill-good); }
.rs-profile { display: grid; grid-template-columns: 1fr auto; gap: 6px 12px; padding: 8px 0; border-bottom: 1px solid var(--border); font-size: 12px; align-items: start; }
.rs-profile:last-child { border-bottom: none; }
.rs-profile .pf-flags label { margin-right: 10px; }
.rs-profile textarea { width: 100%; min-height: 70px; font-family: ui-monospace, monospace; font-size: 11px; }
@media (max-width: 1100px) {
    .rs-live-grid { grid-template-columns: 1fr; height: auto; }
}

/* ------------------------------------------------------------------ */
/* UI restructure (26 Sep 2026, WP5): sub-tabs, the neutral banner,     */
/* the shared payoff card and the signal strategies' pages. Tokens only. */
/* ------------------------------------------------------------------ */

/* The Settings view's section strip - one row of pills for the context on screen (settings.js). */
.subtabs {
    display: flex; flex-wrap: wrap; align-items: center; gap: 4px;
    margin: 0 0 12px; padding: 6px 8px; background: var(--chip-bg); border-radius: 10px;
}
.subtabs:empty { display: none; }
.subtabs-label {
    font-size: 11px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
    color: var(--text-muted); margin-right: 8px; padding-left: 4px;
}
.subtab {
    font-size: 12px; font-weight: 600; color: var(--text-secondary); text-decoration: none;
    padding: 6px 11px; border-radius: 7px; white-space: nowrap;
}
.subtab:hover { color: var(--text); background: var(--hover-bg); }
.subtab.active { background: var(--card); color: var(--text-strong); box-shadow: 0 0 0 1px var(--border); }
.subtab.subtab-other { margin-left: auto; color: var(--blue); }

/* A common view's banner: no mode of its own, so the neutral chip colours. */
.mode-banner.neutral { background: var(--chip-bg); color: var(--text-secondary); }

/* The payoff card on a strategy page (RS, the signal strategies): a fixed-height plot. */
/* The payoff card left the Live tabs for a Payoff tab of its own on 27 Sep 2026
   (.payoff-page-card); the signal strategies' position card takes the height it had. */
.sig-position-card { flex: 1 0 auto; }

/* The signal chart's key: one swatch per overlay style actually drawn. */
.sig-legend { display: flex; flex-wrap: wrap; gap: 4px 12px; font-size: 11px; color: var(--text-muted); margin-top: 4px; }
.sig-legend .sw { display: inline-block; width: 14px; height: 0; border-top: 2px solid var(--text-muted); vertical-align: middle; margin-right: 4px; }
.sig-legend .sw.dashed { border-top-style: dashed; }
.sig-legend .sw.dotted { border-top-style: dotted; }
.sig-legend .sw.box { height: 8px; border: 1px solid; opacity: 0.8; }
.sig-live-grid .chart-card { min-height: 320px; }
.sig-events .rs-ev { grid-template-columns: 62px 120px 1fr; }
.sig-ev-rules { font-size: 10px; font-weight: 700; color: var(--blue); }
.sig-state .sig-kv-wide { grid-column: 1 / -1; }

/* The settings form generated from the strategy's parameter spec, grouped. */
.sig-group {
    font-size: 11px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
    color: var(--text-muted); margin: 14px 0 4px; padding-top: 8px; border-top: 1px solid var(--border);
}
.sig-settings > .sig-group:first-child { margin-top: 0; padding-top: 0; border-top: none; }
.sig-rows { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 4px 24px; }
.sig-rows .settings-row input, .sig-rows .settings-row select { max-width: 170px; }
.sig-rows .settings-row input[type=text] { width: 170px; }
.sig-rows .settings-row > span:first-child { display: flex; flex-direction: column; gap: 1px; }
.sig-desc { font-size: 11px; color: var(--text-muted); font-weight: 400; }
/* 28 Sep 2026: a rule switched off in the Rules list of a strategy that lists its rules. */
.sig-rules tr.dimmed td { color: var(--text-muted); opacity: var(--dim-label-opacity); }
.sig-rules th:nth-child(-n+2), .sig-rules td:nth-child(-n+2) { text-align: left; }
.sig-rules td:first-child { white-space: nowrap; font-weight: 600; }
/* 28 Sep 2026: a position's recorded readings in the signal strategies' positions tables. */
.sig-tags { font-size: 11px; color: var(--text-muted); max-width: 460px; white-space: normal; }
.sig-override { display: inline-flex; flex-direction: column; gap: 3px; color: var(--text-secondary); }
/* 3 Oct 2026: an override select left on "what the settings say" reads faded, like the number
   boxes' placeholders beside it; its drop-down list keeps the ordinary text colour. */
.sig-override select.sig-unset { color: var(--text-muted); }
.sig-override select.sig-unset option { color: var(--text); }

/* A backtest report's breakdown tables, side by side. */
.sig-breakdowns { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 10px 18px; margin: 10px 0; }
.sig-breakdown h4 {
    font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em;
    color: var(--text-muted); margin: 6px 0 4px;
}
.sig-breakdown table.legs { font-size: 12px; }
.sig-report-section {
    font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em;
    color: var(--text-muted); margin: 14px 0 4px;
}

/* Reports > Backtest runs (27 Sep 2026, backtest-runs.js) and the toolbar's "Combine runs..."
   pop-over (reports.js). Tokens only, so every theme draws them. */
.source-pick { display: inline-flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.combine-panel { left: 0; right: auto; width: min(560px, 86vw); }
.combine-list { display: flex; flex-direction: column; gap: 6px; max-height: 42vh; overflow-y: auto; }
.combine-list label { display: grid; grid-template-columns: auto 1fr; column-gap: 8px; font-size: 13px; cursor: pointer; align-items: baseline; }
.combine-list label .note { grid-column: 2; margin: 0; }
.btr-actions { flex-wrap: wrap; gap: 8px; margin-bottom: 10px; }
.btr-table td { vertical-align: top; }
/* Text cells wrap so the row fits the card; the numbers and the actions stay on one line. */
.btr-table td.txt { white-space: normal; min-width: 70px; }
.btr-table td.txt .btr-name { overflow-wrap: anywhere; }
.btr-table tbody tr.btr-picked td { background: var(--row-open-bg); }
.btr-table tbody tr.btr-picked td:first-child { box-shadow: inset 2px 0 0 var(--row-open-edge); }
.btr-name { font-weight: 600; color: var(--text); }
/* The links from a backtest run to its report views (5 Oct 2026; ReportLinks in api.js): one
   unbroken "Calendar · Performance · Journal" - on its own line above Abort / Delete in the runs
   list, a cell of its own in a strategy's Runs table. */
.btr-report-links { display: block; margin: 0 0 6px; white-space: nowrap; }
td.bt-report-links { white-space: nowrap; }
p.bt-report-links .sp-inline-link, span.bt-report-links .sp-inline-link { font-size: inherit; }
.btr-id { margin: 2px 0 0; font-size: 11px; }
.btr-details { white-space: normal; max-width: 260px; font-size: 12px; color: var(--text-secondary); }
.btr-icon { border: none; background: none; color: var(--text-muted); cursor: pointer; font-size: 13px; padding: 0 3px; }
.btr-icon:hover:not(:disabled) { color: var(--blue); }
.btr-icon:disabled { cursor: default; opacity: 0.4; }
.btr-rename { display: inline-flex; gap: 6px; align-items: center; }
.btr-rename input { width: 220px; }
.btr-chip {
    display: inline-block; font-size: 11px; font-weight: 600; white-space: nowrap;
    background: var(--blue-bg); color: var(--blue); border-radius: 10px; padding: 2px 8px; margin: 1px 0;
}
.btr-doomed { font-size: 12px; font-weight: 600; color: var(--red); }
.btr-state { font-size: 11px; font-weight: 700; letter-spacing: 0.03em; color: var(--text-secondary); }
.btr-state-running, .btr-state-merging { color: var(--amber); }
.btr-state-failed, .btr-state-aborted, .btr-state-incomplete { color: var(--red); }
.btr-actions-cell { white-space: nowrap; }
.btr-actions-cell .btr-delete, .btr-actions-cell .btr-abort { margin-left: 8px; padding: 2px 10px; font-size: 12px; min-height: 0; }
.btr-actions-cell .btr-abort { font-weight: 700; }

/* The Delta Shield Condor (28 Sep 2026): a cycle spans days, so its timeline's first column carries the date too. */
.dsc-events .rs-ev { grid-template-columns: 118px 96px 1fr; }
/* A "global" tag in a strategy settings form sits beside its label, not stretched across the column. */
.sig-rows .settings-row .tag-mini { align-self: flex-start; margin-left: 0; }

/* System health view (1 Oct 2026, health.js): gauge cards, the hour charts, the disk bars. A level
   colours the FILL and the card's left edge; the figure itself stays ink so it reads in every theme. */
.hl-gauges { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
.hl-gauges .stat-card { border-left: 3px solid var(--fill-good); }
.hl-gauges .stat-card.hl-warn { border-left-color: var(--fill-warn); }
.hl-gauges .stat-card.hl-critical { border-left-color: var(--red); }
.hl-gauges .stat-card.hl-none { border-left-color: var(--border); }
.hl-bar { background: var(--track-bg); height: 6px; border-radius: 4px; overflow: hidden; margin-top: 8px; }
.hl-bar > span { display: block; height: 100%; background: var(--fill-good); }
.hl-bar.hl-warn > span { background: var(--fill-warn); }
.hl-bar.hl-critical > span { background: var(--red); }
.hl-charts { display: grid; grid-template-columns: repeat(auto-fit, minmax(380px, 1fr)); gap: 16px; }
.hl-chart-wrap { position: relative; height: 220px; }
table.hl-kv td:first-child { text-align: left; color: var(--text-secondary); white-space: nowrap; width: 1%; padding-right: 18px; }
table.hl-kv td:last-child { text-align: left; word-break: break-word; }
.save-banner.warn { background: var(--amber-bg); color: var(--amber); }
/* The speedometer dials: rim zones from the server's limits, a needle turned in place. */
.hl-gauges .hl-dial-card { text-align: center; }
.hl-dial { display: block; width: 100%; max-width: 190px; margin: 0 auto 2px; overflow: visible; }
.hl-dial path { fill: none; stroke-width: 7; }
.hl-zone-ok { stroke: var(--fill-good); }
.hl-zone-warn { stroke: var(--fill-warn); }
.hl-zone-critical { stroke: var(--red); }
.hl-ticks line { stroke: var(--text-muted); stroke-width: 1; }
.hl-needle { stroke: var(--text); stroke-width: 2; stroke-linecap: round; transform-box: view-box;
    transform-origin: 50px 54px; transform: rotate(-90deg); transition: transform 0.9s cubic-bezier(.3, 1.3, .5, 1); }
.hl-hub { fill: var(--text); }
@media (prefers-reduced-motion: reduce) { .hl-needle { transition: none; } }

/* Data load view (2 Oct 2026, dataload.js): the ingestion job's progress. The timeline places one
   bar per series on a shared date axis - its range as a track, the loaded part filled, the chunk
   in flight pulsing. Fills are theme tokens; a state never changes the ink of a figure. */
.dl-hidden { display: none; }
.dl-cards { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
.dl-cards .stat-card.dl-live { border-left: 3px solid var(--blue); }
.dl-cards .stat-value { font-size: 16px; }
.dl-timeline { margin-top: 10px; }
.dl-row { display: grid; grid-template-columns: minmax(120px, 220px) 1fr; gap: 12px; align-items: center; margin: 5px 0; }
.dl-row-label { font-size: 12px; color: var(--text-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dl-row.dl-running .dl-row-label { color: var(--text-strong); font-weight: 600; }
.dl-track { position: relative; height: 12px; }
.dl-track i { position: absolute; top: 0; height: 100%; border-radius: 3px; min-width: 2px; }
.dl-track .dl-range { background: var(--track-bg); }
.dl-track .dl-range.dl-failed { background: var(--red-bg); outline: 1px solid var(--red); outline-offset: -1px; }
.dl-track .dl-done { background: var(--fill-good); }
.dl-track .dl-now { background: var(--blue); animation: dl-pulse 1.2s ease-in-out infinite; }
.dl-axis { margin-bottom: 8px; }
.dl-axis .dl-row-label { color: var(--text-muted); }
.dl-ticks { height: 16px; border-bottom: 1px solid var(--border); overflow: hidden; }
.dl-ticks span { position: absolute; top: 0; padding-left: 4px; border-left: 1px solid var(--border); height: 100%;
    font-size: 10px; line-height: 14px; color: var(--text-muted); white-space: nowrap; }
.dl-key { display: inline-block; width: 14px; height: 8px; border-radius: 2px; vertical-align: baseline; }
.dl-key-done { background: var(--fill-good); }
.dl-key-now { background: var(--blue); }
.dl-key-todo { background: var(--track-bg); }
.dl-key-failed { background: var(--red-bg); outline: 1px solid var(--red); outline-offset: -1px; }
.dl-bar { background: var(--track-bg); height: 6px; border-radius: 4px; overflow: hidden; margin-bottom: 3px; min-width: 90px; }
.dl-bar > span { display: block; height: 100%; background: var(--fill-good); transition: width 400ms ease; }
tr.dl-running .dl-bar > span { background: var(--blue); }
tr.dl-failed .dl-bar > span { background: var(--red); }
tr.dl-running .dl-state { color: var(--blue); font-weight: 700; }
tr.dl-done .dl-state { color: var(--green); font-weight: 700; }
tr.dl-failed .dl-state { color: var(--red); font-weight: 700; }
tr.dl-stopped .dl-state { color: var(--amber); font-weight: 700; }
.dl-notes { margin: 6px 0 0; padding-left: 18px; font-size: 13px; color: var(--text-secondary); }
.dl-notes li { margin: 3px 0; }
.dl-notes li.dl-note-failed { color: var(--red); font-weight: 600; }
@keyframes dl-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.45; } }
@media (prefers-reduced-motion: reduce) { .dl-track .dl-now { animation: none; } .dl-bar > span { transition: none; } }
@media (max-width: 700px) { .dl-row { grid-template-columns: 1fr; gap: 2px; } }
a.dl-link { color: var(--blue); }
/* Settings > Account: the credentials card (2 Oct 2026). */
.cred-head { font-size: 13px; font-weight: 700; color: var(--text-strong); margin: 14px 0 4px; }
.cred-actions { display: flex; flex-wrap: wrap; gap: 8px; margin: 10px 0 6px; }
.cred-detail { white-space: pre-line; margin: 4px 0 0; }
/* The data calendar (2 Oct 2026): one square per day, coloured by what is STORED for it. Status is
   never colour alone - "no data" is a hollow square with a red edge, "closed" a faint hollow one,
   "not available yet" is hatched - and the clicked day's figures are printed under the calendar. */
.dlc-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; margin: 6px 0 10px; font-size: 13px; }
.dlc-bar label { display: inline-flex; align-items: center; gap: 6px; color: var(--text-secondary); }
.dlc-legend { display: flex; flex-wrap: wrap; gap: 4px 16px; font-size: 12px; color: var(--text-muted); margin: 0 0 8px; }
.dlc-legend span { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.dlc-summary { font-size: 13px; color: var(--text-secondary); margin: 0 0 12px; }
.dlc-summary b { color: var(--text-strong); }
.dlc-months .day-grid { grid-template-columns: repeat(7, 14px); }
.dlc-months .day-wd { width: 14px; }
.dlc-sq { display: inline-block; width: 14px; height: 14px; border-radius: 3px; box-sizing: border-box; background: transparent; flex: 0 0 auto; }
.dlc-sq.dlc-full { background: var(--fill-good); }
.dlc-sq.dlc-partial { background: var(--fill-warn); }
.dlc-sq.dlc-none { background: var(--card); border: 2px solid var(--red); }
.dlc-sq.dlc-failed { background: var(--red); }
.dlc-sq.dlc-pending { background: repeating-linear-gradient(135deg, var(--blue) 0 2px, var(--card) 2px 4px); border: 1px solid var(--blue); }
.dlc-sq.dlc-closed { border: 1px solid var(--weekend-line); }
.dlc-sq.dlc-out { background: var(--day-sq); opacity: 0.55; }
.dlc-sq.dlc-future, .dlc-sq.dlc-blank { background: transparent; }
.dlc-sq.dlc-unknown { background: var(--day-sq); }
.dlc-months .dlc-sq[data-day] { cursor: pointer; }
.dlc-months .dlc-sq[data-day]:hover, .dlc-months .dlc-sq.dlc-picked { outline: 2px solid var(--blue); outline-offset: 1px; }
/* Days selected for a reload (2 Oct 2026): an ink ring, a different mark from the blue ring of the
   day under the pointer and of the day whose figures are shown, and never a fill - the fill is
   the day's status and stays readable under the ring. Declared after the hover rule and at its
   specificity plus one class, so a selected day keeps its ring while the pointer is on it. With
   the grid's 3px gap the rings of neighbouring days meet and a range reads as one band. A drag
   selects days, not text. */
.dlc-months { user-select: none; -webkit-user-select: none; }
.dlc-months .dlc-sq.dlc-selected[data-day], .dlc-months .dlc-sq.dlc-selected[data-day]:hover { outline: 2px solid var(--text-strong); outline-offset: 1px; }
.dlc-selbar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin: 0 0 12px; min-height: 30px; font-size: 13px; }
.dlc-seltext { color: var(--text-strong); font-weight: 600; }
.dlc-months.dlc-computing { opacity: 0.55; }
.dlc-count { font-size: 11px; color: var(--text-muted); }
.dlc-detail { margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--border); }
.dlc-detail .dlc-word { font-weight: 700; }
.dlc-word.dlc-full { color: var(--green); }
.dlc-word.dlc-partial { color: var(--amber); }
.dlc-word.dlc-none, .dlc-word.dlc-failed { color: var(--red); }
.dlc-word.dlc-pending { color: var(--blue); }

/* Database view (2 Oct 2026, database.js): the journal's tables on the left, one table's rows on
   the right. Everything in it is built from the database's own catalogue, so no rule here may
   name a table or a column. The grid borrows the journal's .jr-scroll / .jr-table. */
.db-layout { display: grid; grid-template-columns: minmax(190px, 250px) minmax(0, 1fr); gap: 16px; align-items: start; }
.db-side input[type="search"] {
    width: 100%; min-height: 32px; margin-top: 6px; padding: 4px 8px; font-size: 12px; box-sizing: border-box;
    border: 1px solid var(--border); border-radius: 7px; background: var(--input-bg); color: var(--text);
}
.db-table-list { margin-top: 8px; max-height: 66vh; overflow-y: auto; }
button.db-table {
    display: flex; justify-content: space-between; align-items: baseline; gap: 10px; width: 100%;
    border: none; border-left: 2px solid transparent; background: none; color: var(--text-secondary);
    font: inherit; font-size: 12px; text-align: left; padding: 5px 8px; border-radius: 0 6px 6px 0; cursor: pointer;
}
button.db-table:hover { background: var(--nav-hover-bg); color: var(--text); }
button.db-table.active { color: var(--text-strong); font-weight: 700; border-left-color: var(--accent); background: var(--nav-active-bg); }
.db-table-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.db-table-rows { flex: none; font-size: 11px; font-weight: 400; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.db-title { font-size: 15px; }
.db-filters { margin-bottom: 10px; }
.db-hint { margin: 0 0 10px; color: var(--amber); }
.db-scroll { max-height: 64vh; }
.db-grid th { white-space: nowrap; }
.db-grid th.db-nosort { cursor: default; }
.db-grid td { max-width: 340px; overflow: hidden; text-overflow: ellipsis; }
.db-grid td.db-null { color: var(--text-muted); font-style: italic; }
.db-grid td.db-masked { color: var(--text-muted); }
.db-flag { font-size: 9px; font-weight: 700; letter-spacing: 0.04em; color: var(--text-muted); border: 1px solid var(--border); border-radius: 4px; padding: 0 3px; margin-left: 4px; vertical-align: 1px; }
.db-arrow { margin-left: 4px; font-size: 9px; }
/* An opened row: every column of it, in full. The cell spans a table that may be thousands of
   pixels wide, so its content is pinned to the visible left edge at the scroller's own width. */
.db-grid tr.jr-detail td { max-width: none; overflow: visible; }
.db-detail { position: sticky; left: 16px; width: var(--db-detail-width, 640px); box-sizing: border-box; }
.db-kv { display: grid; grid-template-columns: minmax(140px, max-content) minmax(0, 1fr); gap: 0 18px; font-size: 12px; }
.db-kv > div { padding: 4px 0; border-bottom: 0.5px solid var(--border); min-width: 0; }
.db-kv .db-k { color: var(--text-secondary); white-space: nowrap; }
.db-kv .db-k small { color: var(--text-muted); margin-left: 6px; }
.db-kv .db-v { font-weight: 600; white-space: pre-wrap; overflow-wrap: anywhere; }
.db-kv .db-v.db-null { font-weight: 400; color: var(--text-muted); font-style: italic; }
.db-kv pre { margin: 0; font: inherit; font-weight: 400; font-family: ui-monospace, Consolas, monospace; font-size: 11.5px; white-space: pre-wrap; overflow-wrap: anywhere; max-height: 320px; overflow-y: auto; }
.db-pager { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 12px; }
.db-pager select {
    min-height: 30px; padding: 3px 6px; font-size: 12px; margin-left: 4px;
    border: 1px solid var(--border); border-radius: 7px; background: var(--input-bg); color: var(--text);
}
.db-page { font-size: 12px; font-weight: 600; color: var(--text-secondary); font-variant-numeric: tabular-nums; }
@media (max-width: 900px) {
    .db-layout { grid-template-columns: minmax(0, 1fr); }
    .db-table-list { max-height: 180px; }
}

.db-scroll.db-loading { opacity: 0.55; }
#dbTableMeta b { color: var(--text-strong); font-variant-numeric: tabular-nums; }

/* ------------------------------------------------------------------ */
/* Documentation area (2 Oct 2026) - docs.js, docs-strategies.js,       */
/* docs-figures.js. A page is a header card and section cards; a figure  */
/* is an inline SVG whose every colour is a class over the theme tokens  */
/* below, so it follows a theme switch without being redrawn.            */
/* ------------------------------------------------------------------ */
.docs-head-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.docs-title { font-size: 22px; font-weight: 700; margin: 0; color: var(--text-strong); }
.docs-lede { font-size: 14.5px; line-height: 1.55; color: var(--text-secondary); margin: 8px 0 12px; max-width: 120ch; }
.docs-lede b, .docs-lede i { color: var(--text); }
.docs-facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 10px 22px; margin-bottom: 12px; }
.docs-fact span { display: block; font-size: 10.5px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-muted); }
.docs-fact b { font-size: 13px; font-weight: 600; line-height: 1.4; }
.docs-links { display: flex; gap: 14px; align-items: center; font-size: 13px; }
.docs-links a, .docs-section a, .docs-source a { color: var(--blue); text-decoration: none; font-weight: 600; }
.docs-links a:hover, .docs-section a:hover { text-decoration: underline; }
.docs-toc { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin: 0 0 14px; }
.docs-toc .tbtn { min-height: 28px; padding: 3px 10px; font-size: 12px; }
.docs-h { font-size: 16px; font-weight: 700; margin: 0 0 12px; color: var(--text-strong); }
.docs-section p { font-size: 13.5px; line-height: 1.58; margin: 0 0 10px; }
.docs-section > p, .docs-section > .docs-list { max-width: 125ch; }
.docs-section code, .docs-source code { font-family: ui-monospace, Consolas, monospace; font-size: 12px; background: var(--chip-bg); border-radius: 4px; padding: 1px 5px; }
.docs-list { margin: 0 0 10px; padding-left: 20px; font-size: 13.5px; line-height: 1.55; }
.docs-list li { margin: 5px 0; }
.docs-muted { color: var(--text-muted); font-weight: 400; font-size: 12px; }
.docs-section p.docs-illus { font-size: 12px; color: var(--text-muted); margin: 12px 0 0; }
.docs-rule {
    display: inline-block; font-family: ui-monospace, Consolas, monospace; font-size: 11px; font-weight: 700;
    background: var(--chip-bg); color: var(--text-secondary); border-radius: 4px; padding: 0 5px; white-space: nowrap; line-height: 1.5;
}
.docs-split { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 26px; align-items: start; }
.docs-split.docs-split-fig { grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr); }
.docs-pair { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 26px; align-items: start; margin-bottom: 6px; }
.docs-quad { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px 28px; margin: 6px 0 12px; max-width: 940px; }
@media (max-width: 760px) { .docs-quad { grid-template-columns: minmax(0, 1fr); } }
@media (max-width: 1100px) { .docs-split, .docs-split.docs-split-fig { grid-template-columns: minmax(0, 1fr); } }
.docs-table-wrap { overflow-x: auto; margin: 0 0 12px; }
.docs-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.docs-table th {
    text-align: left; font-size: 10.5px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
    color: var(--text-muted); padding: 6px 12px 6px 0; border-bottom: 1px solid var(--border);
}
.docs-table td { padding: 7px 12px 7px 0; border-bottom: 0.5px solid var(--border); vertical-align: top; line-height: 1.45; }
.docs-table tr:last-child td { border-bottom: none; }
.docs-table td:last-child, .docs-table th:last-child { padding-right: 0; }
.docs-table.docs-num td:not(:first-child), .docs-table.docs-num th:not(:first-child) { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.docs-table.docs-legs td:nth-child(n+3), .docs-table.docs-legs th:nth-child(n+3) { text-align: right; font-variant-numeric: tabular-nums; }
.docs-table.docs-compact td { padding-top: 4px; padding-bottom: 4px; }
.docs-table.docs-compact td:nth-child(2), .docs-table.docs-compact th:nth-child(2) { font-variant-numeric: tabular-nums; }
.docs-table.docs-terms td:first-child { font-weight: 700; white-space: nowrap; width: 1%; padding-right: 22px; }
.docs-table.docs-matrix td { vertical-align: middle; }
.docs-table.docs-matrix td:first-child { width: 1%; white-space: nowrap; padding-right: 22px; }
.docs-table.docs-catalog td:first-child { white-space: nowrap; }
.docs-section a.docs-chip {
    display: inline-block; margin: 2px 6px 2px 0; padding: 4px 11px; border-radius: 14px; background: var(--chip-bg);
    color: var(--text); font-size: 12.5px; font-weight: 600; text-decoration: none;
}
.docs-section a.docs-chip:hover { background: var(--hover-bg); text-decoration: none; }
.docs-callout { border-left: 3px solid var(--blue); background: var(--subtle-bg); border-radius: 8px; padding: 10px 14px; margin: 0 0 12px; }
.docs-callout > b { display: block; margin-bottom: 4px; font-size: 13.5px; }
.docs-callout p:last-child { margin-bottom: 0; }
.docs-callout-warn { border-left-color: var(--fill-warn); }
.docs-days { display: grid; grid-template-columns: repeat(auto-fit, minmax(128px, 1fr)); gap: 8px; margin: 0 0 14px; }
.docs-day { border: 0.5px solid var(--border); border-radius: 8px; padding: 9px 11px; background: var(--subtle-bg); font-size: 12px; line-height: 1.4; }
.docs-day b { display: block; font-size: 13px; }
.docs-day span { display: block; color: var(--text-muted); font-size: 11px; margin-bottom: 4px; }
.docs-day em { font-style: normal; color: var(--text-secondary); }
.docs-day.on { border-left: 3px solid var(--blue); }
.docs-day.off { background: transparent; border-style: dashed; }
.docs-source { margin-top: 0; }

.dfig-wrap { margin: 0 0 4px; max-width: 860px; }
.dfig-wrap.dfig-wide { max-width: 1020px; }
.docs-quad .dfig-wrap { max-width: 440px; }
svg.dfig { display: block; width: 100%; height: auto; overflow: visible; font-family: inherit; }
.dfig text { fill: var(--text-secondary); font-size: 11.5px; }
.dfig .dfig-tick { fill: var(--text-muted); font-size: 10.5px; font-variant-numeric: tabular-nums; }
.dfig .dfig-axis-title { fill: var(--text-muted); font-size: 10px; }
.dfig-grid { stroke: var(--chart-grid); stroke-width: 1; }
.dfig-axis { stroke: var(--border); stroke-width: 1; }
.dfig-zero { stroke: var(--text-secondary); stroke-width: 1; }
/* One custom property carries the colour of a mark, so the same class colours a line, a level,
   a mark and the legend swatch beside the figure. Scoped, because several of the names are short. */
.dfig .ln-fast, .dfig-swatch.ln-fast { --c: var(--chart-ema-fast); }
.dfig .ln-slow, .dfig-swatch.ln-slow { --c: var(--chart-ema-slow); }
.dfig .ln-vwap, .dfig-swatch.ln-vwap { --c: var(--chart-vwap); }
.dfig .ln-a, .dfig-swatch.ln-a { --c: var(--blue); }
.dfig .ln-b, .dfig-swatch.ln-b { --c: var(--chart-rsi); }
.dfig .st-up, .dfig-swatch.st-up, .dfig .up, .dfig-swatch.up { --c: var(--chart-up); }
.dfig .st-down, .dfig-swatch.st-down, .dfig .down, .dfig-swatch.down { --c: var(--chart-down); }
.dfig .k, .dfig-swatch.k { --c: var(--blue); }
.dfig .entry { --c: var(--chart-entry); }
.dfig .exit { --c: var(--chart-exit); }
.dfig .target { --c: var(--chart-target); }
.dfig .stop { --c: var(--chart-stop); }
.dfig .note { --c: var(--text-muted); }
.dfig .lv-r { --c: var(--chart-level-r); }
.dfig .lv-s { --c: var(--chart-level-s); }
.dfig .lv-p { --c: var(--chart-pivot); }
.dfig .dc { --c: var(--chart-dc); }
.dfig .pf-main, .dfig-swatch.pf-main { --c: var(--text); }
.dfig .pf-before, .dfig-swatch.pf-before { --c: var(--text-muted); }
.dfig .dashed { stroke-dasharray: 5 4; }
.dfig-wick { stroke: var(--c); stroke-width: 1.2; }
.dfig-body { fill: var(--c); }
.dfig-line { fill: none; stroke: var(--c, var(--text-secondary)); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.dfig-dot { fill: var(--c, var(--text)); stroke: var(--card); stroke-width: 2; }
.dfig-level { stroke: var(--c, var(--text-muted)); stroke-width: 1.5; }
.dfig-box { fill: var(--c, var(--text-muted)); fill-opacity: 0.16; stroke: var(--c, var(--text-muted)); stroke-width: 1; }
.dfig-zone { fill: var(--text-muted); fill-opacity: 0.07; }
.dfig-zone.zone-a { fill-opacity: 0.04; }
.dfig-zone.zone-b { fill-opacity: 0.10; }
.dfig-zone.zone-d { fill-opacity: 0.17; }
.dfig-zone.zone-good { fill: var(--chart-up); fill-opacity: 0.10; }
.dfig-zone.zone-bad { fill: var(--chart-down); fill-opacity: 0.10; }
.dfig-span { fill: var(--text-muted); fill-opacity: 0.08; }
.dfig .dfig-span-label, .dfig .dfig-zone-label { fill: var(--text-muted); font-size: 10px; }
.dfig-mark { fill: var(--c, var(--text-secondary)); }
.dfig .dfig-mark-label, .dfig .dfig-level-label, .dfig .dfig-plateau, .dfig .dfig-edge-label {
    paint-order: stroke; stroke: var(--card); stroke-width: 3px; stroke-linejoin: round;
}
.dfig .dfig-mark-label { fill: var(--text); font-weight: 600; }
.dfig .dfig-plateau { fill: var(--text); font-weight: 700; font-size: 12px; font-variant-numeric: tabular-nums; }
.dfig-profit { fill: var(--chart-up); fill-opacity: 0.22; }
.dfig-loss { fill: var(--chart-down); fill-opacity: 0.22; }
.dfig-payoff { fill: none; stroke: var(--c, var(--text)); stroke-width: 2; stroke-linejoin: round; }
.dfig-strike { stroke: var(--chart-grid); stroke-width: 1; stroke-dasharray: 2 3; }
.dfig-spot { stroke: var(--text-muted); stroke-width: 1; stroke-dasharray: 4 3; }
.dfig-be { fill: var(--card); stroke: var(--text); stroke-width: 2; }
.dfig-be-drop { stroke: var(--text-muted); stroke-width: 1; stroke-dasharray: 2 3; }
.dfig .dfig-be-label { fill: var(--text); font-weight: 600; font-variant-numeric: tabular-nums; }
.dfig-cross { stroke: var(--text-muted); stroke-width: 1; opacity: 0; pointer-events: none; }
.dfig-cross.on { opacity: 0.7; }
.dfig-bar { fill: var(--chip-bg); }
.dfig-bar.good { fill: var(--green-bg); }
.dfig-bar.warn { fill: var(--amber-bg); }
.dfig .dfig-bar-label { fill: var(--text); font-weight: 600; }
.dfig .dfig-row-label { fill: var(--text); font-size: 11px; font-weight: 600; font-variant-numeric: tabular-nums; }
.dfig-point { fill: var(--c, var(--text)); stroke: var(--card); stroke-width: 2; }
.dfig-node { fill: var(--subtle-bg); stroke: var(--text-muted); stroke-width: 1.2; }
.dfig-node.end { stroke: var(--text); stroke-width: 1.8; }
.dfig-node.ghost { fill: none; stroke-dasharray: 4 3; }
.dfig .dfig-node-title { fill: var(--text); font-weight: 700; font-size: 11px; letter-spacing: 0.03em; }
.dfig .dfig-node-sub { fill: var(--text-secondary); font-size: 10px; }
.dfig-edge { fill: none; stroke: var(--text-secondary); stroke-width: 1.3; }
.dfig-arrow { stroke: var(--text-muted); stroke-width: 2; }
.dfig-arrow-head { fill: var(--text-secondary); }
.dfig-band { fill: var(--blue); }
.dfig-band.b0 { fill-opacity: 0.10; } .dfig-band.b1 { fill-opacity: 0.16; } .dfig-band.b2 { fill-opacity: 0.22; }
.dfig-band.b3 { fill-opacity: 0.28; } .dfig-band.b4 { fill-opacity: 0.34; }
.dfig .dfig-band-label { fill: var(--text); font-weight: 700; font-size: 11.5px; }
.dfig-legend { display: flex; flex-wrap: wrap; gap: 4px 16px; margin-top: 6px; font-size: 11.5px; color: var(--text-secondary); }
.dfig-key { display: inline-flex; align-items: center; gap: 6px; }
.dfig-swatch { display: inline-block; width: 18px; height: 0; border-top: 2px solid var(--c, var(--text-secondary)); }
.dfig-swatch.dashed { border-top-style: dashed; }
.dfig-swatch.block { width: 10px; height: 10px; border: 0; border-radius: 2px; background: var(--c); }
.dfig-wrap figcaption { font-size: 12px; line-height: 1.45; color: var(--text-muted); margin-top: 6px; }
.dfig-tip {
    position: fixed; z-index: 60; pointer-events: none; min-width: 130px; background: var(--float-bg); color: var(--text);
    border: 1px solid var(--float-border); border-radius: 8px; padding: 7px 10px; font-size: 12px; box-shadow: var(--float-shadow);
}
.dfig-tip > b { display: block; margin-bottom: 3px; }
.dfig-tip div { display: flex; justify-content: space-between; gap: 16px; }
.dfig-tip span { color: var(--text-secondary); }
.dfig-tip div b { font-variant-numeric: tabular-nums; }

/* ---- Portfolios (6 Oct 2026) ---- */
.pfo-layout { display: grid; grid-template-columns: minmax(220px, 300px) minmax(0, 1fr); gap: 14px; align-items: start; }
@media (max-width: 1000px) { .pfo-layout { grid-template-columns: 1fr; } }
.pfo-item { display: block; padding: 8px 10px; border-radius: 6px; cursor: pointer; border: 1px solid transparent; }
.pfo-item:hover { background: var(--hover-bg); }
.pfo-item.active { background: var(--subtle-bg); border-color: var(--border); }
.pfo-item b { display: block; font-size: 13px; }
.pfo-item span { font-size: 11px; color: var(--text-muted); }
.pfo-main .card { margin-bottom: 14px; }
.pfo-members td input, .pfo-members td select { width: 100%; box-sizing: border-box; }
.pfo-members td.pfo-num input { width: 80px; }
.pfo-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-top: 10px; }
.pfo-form { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 8px 14px; }
.pfo-form label { display: flex; flex-direction: column; gap: 3px; font-size: 12px; color: var(--text-secondary); }
.pfo-form input, .pfo-form select { padding: 5px 7px; }
.pfo-progress { height: 8px; background: var(--track-bg); border-radius: 4px; overflow: hidden; margin: 6px 0; }
.pfo-progress span { display: block; height: 100%; background: var(--fill-good); }
.pfo-seg { display: inline-block; width: 14px; height: 10px; margin: 1px; border-radius: 2px; background: var(--track-bg); }
.pfo-seg.RUNNING { background: var(--blue); } .pfo-seg.DONE { background: var(--fill-good); }
.pfo-seg.FAILED { background: var(--red); } .pfo-seg.ABORTED { background: var(--fill-warn); }

/* ---- Entry-day chips (6 Oct 2026): the portfolio members' entry days and the Reports filter bar's
   entry-day pick share one look. A lit chip is a day entries are taken on; "own" (dashed) means
   the profile's own rule stands and nothing is laid over it. Colours are tokens only. */
.day-chips, .jr-days { display: inline-flex; gap: 4px; flex-wrap: wrap; align-items: center; }
/* A chip is a flex column of its own, so the weekday line under the day sits INSIDE the pill whatever
   box it is placed in - as a plain inline span with a block child it broke the line mid-chip, which
   is what the Reports filter bar showed on 6 Oct 2026 (its box is .jr-days, not .day-chips). */
.day-chip { display: inline-flex; flex-direction: column; align-items: center; justify-content: center;
  border: 1px solid var(--border); border-radius: 12px; padding: 2px 8px; font-size: 11px; line-height: 1.25;
  cursor: pointer; background: var(--chip-bg); color: var(--text-muted); user-select: none; text-align: center; white-space: nowrap; }
.day-chip:hover { border-color: var(--blue); }
.day-chip.on { background: color-mix(in srgb, var(--blue) 16%, transparent); color: var(--blue); border-color: var(--blue); }
.day-chip.own { border-style: dashed; }
.day-chip small { display: block; font-size: 9px; line-height: 1; opacity: .8; }
.day-chip.day-all { font-weight: 600; }
.pfo-members td.pfo-days-cell { min-width: 300px; }
.pfo-members td.pfo-num input, .pfo-members td.pfo-num select { width: 80px; }
.pfo-members td.pfo-fit { white-space: nowrap; font-size: 12px; }
.pfo-members td.pfo-fit-bad { color: var(--red); font-weight: 600; }
.pfo-members td.pfo-fit small { font-weight: 400; color: var(--text-muted); }
.pfo-warnings { color: var(--red); margin-top: 8px; line-height: 1.5; }
.pfo-deployed { font-size: 11px; padding: 2px 8px; border-radius: 10px; background: color-mix(in srgb, var(--green) 18%, transparent); color: var(--green); margin-left: 8px; }
.btr-star { background: none; border: 0; cursor: pointer; font-size: 16px; line-height: 1; color: var(--text-muted); padding: 0 4px; vertical-align: middle; }
.btr-star:hover { color: var(--fill-warn); }
.btr-star.on { color: var(--fill-warn); }
.btr-favonly input { vertical-align: middle; margin-right: 3px; }
.jr-days-row { margin-top: 6px; }
