/* Shared stylesheet for dashboard.html and portfolio.html - extracted from what was
   previously two duplicated ~160KB files so future style changes only need to be made
   once. See claude/roadmap-hedge-fund-level.md ("dashboard.html/portfolio.html
   duplication" entry) for why this exists. */

  /* "Quant Terminal" design system - dark trading-desk palette pulled from
     the ui-ux-pro-max design database's Dark Mode (OLED) + Data-Dense
     Dashboard match for "fintech/trading dashboard": deep navy background,
     green/red signal colors (brightened for on-dark text contrast; both
     verified 4.5:1+ against --card, --line verified 3:1+ non-text contrast),
     Fira Code/Fira Sans typography. See claude/roadmap-hedge-fund-level.md. */
  :root {
    /* Slightly larger base than the browser default (16px) so every rem-based
       size site-wide - especially the long-sentence body copy in footnotes,
       hint boxes and the Learn the terms page - is a little easier to read,
       without needing every individual font-size rule touched by hand. */
    font-size: 17px;
    /* This is the actual remaining cause of the sticky header visibly
       sliding sideways a moment after every page load - a shift that
       survived the earlier .site-account margin-left:auto fix (that fix
       was real and necessary, just not the whole story). Every page here
       paints SHORT at first (most panels start display:none and are only
       populated once app.js's fetches resolve), then grows tall once the
       signal card / DNA card / holdings table / etc. render in - which is
       exactly when the page crosses from "fits in the window" to "needs a
       vertical scrollbar". .site-header-inner is a centered, max-width box
       (margin:auto), so the instant that scrollbar appears, the viewport's
       *usable* width shrinks by the scrollbar's own width and the centered
       header content re-centers into the new, narrower space - sliding
       everything in it sideways by half a scrollbar-width (verified live:
       ~7.5px on a 15px Chrome/Linux scrollbar) on literally every load,
       independent of fonts, login state, or the data-source pill. Reserving
       the scrollbar's gutter up front - whether or not a scrollbar is
       showing yet - keeps the usable width (and so the header's centering)
       constant through that transition instead of only after it. */
    scrollbar-gutter: stable;
    --ink: #F8FAFC;
    --ink-soft: #94A3B8;
    --paper: #020617;
    --card: #0E1223;
    --line: #5B6B85;
    --buy: #22C55E;
    --buy-bg: rgba(34, 197, 94, 0.16);
    --sell: #F87171;
    --sell-bg: rgba(239, 68, 68, 0.16);
    --hold: #94A3B8;
    --hold-bg: rgba(148, 163, 184, 0.16);
    /* --accent is INTERACTIVE, never directional, and must never equal
       --buy. It used to be the identical hex (#22C55E), which meant hovering
       a ticker painted it the exact green that means "this position is up"
       two columns to the right - the reported bug, and only the most visible
       case of green carrying six unrelated meanings at once.

       Blue, for three reasons: maximum separation from both directional
       colours; it is the web's default "you can click this" affordance, so
       it needs no learning; and red-vs-green is the pair the most common
       colour-vision deficiencies confuse, while blue stays distinct from
       both.

       The standing rule, in full: --buy/--sell/--hold describe market
       direction and money ONLY (price up/down, gain/loss, BUY/SELL/HOLD,
       trending up/down, lifting/holding back an axis). --accent describes
       "clickable / selected / you are here" ONLY. Neither borrows the
       other's colour, ever. Anything that is neither - a magnitude bar, a
       radar fill - takes --accent rather than green, because a 90%
       concentration in one holding is not a *good* thing and must not be
       drawn in the same colour as a gain.

       The mint green in the logo and on index.html is a brand mark, on
       pages carrying no price data, and is deliberately left alone. */
    --accent: #3B82F6;
    --accent-bg: rgba(59, 130, 246, 0.16);
    --accent-ring: rgba(59, 130, 246, 0.35);
    --on-accent: #0F172A;
    /* Header + status-pill tokens - the header used to be hardcoded to a
       permanently light "glass" bar regardless of the page's own dark
       theme; it now follows the same toggle (see [data-theme="light"]
       below), which also fixes that pre-existing header/body mismatch. */
    --header-bg: rgba(14, 18, 35, 0.92);
    --brand-mark-bg: #07111f;
    --pill-bg: var(--card);
    --pill-border: var(--line);
    --pill-live-fg: #4ADE80; --pill-live-bg: rgba(34, 197, 94, 0.14); --pill-live-border: rgba(34, 197, 94, 0.4);
    --pill-mock-fg: #F5B759; --pill-mock-bg: rgba(245, 183, 89, 0.14); --pill-mock-border: rgba(245, 183, 89, 0.4);
  }
  /* Light theme - toggled via the header button (see .theme-toggle-btn /
     toggleTheme() in app.js), persisted per-browser in localStorage and
     applied as data-theme="light" on <html>. Every rule elsewhere in this
     file reads colors through the custom properties above, so this block is
     the only place the light palette needs to be defined. */
  :root[data-theme="light"] {
    --ink: #07111F;
    --ink-soft: #56637A;
    --paper: #F4F7F8;
    --card: #FFFFFF;
    --line: #DCE3E7;
    --buy: #15803D;
    --buy-bg: rgba(21, 128, 61, 0.12);
    --sell: #DC2626;
    --sell-bg: rgba(220, 38, 38, 0.12);
    --hold: #64748B;
    --hold-bg: rgba(100, 116, 139, 0.12);
    /* Same split as the dark theme above - this used to be #15803D, the
       identical hex to --buy. Contrast measured, not assumed: white on
       #1D4ED8 is 6.7:1, and #1D4ED8 as link text is 6.7:1 on --card and
       6.2:1 on --paper. The dark theme's equivalents are 4.85:1 and up.
       Every pairing clears AA; none reach AAA's 7:1, so --accent shouldn't
       be used for long body-size prose. */
    --accent: #1D4ED8;
    --accent-bg: rgba(29, 78, 216, 0.12);
    --accent-ring: rgba(29, 78, 216, 0.30);
    --on-accent: #FFFFFF;
    --header-bg: rgba(255, 255, 255, 0.96);
    --pill-bg: #F4F7F8;
    --pill-border: #DCE3E7;
    --pill-live-fg: #176C55; --pill-live-bg: #E7F7F1; --pill-live-border: #B8E5D7;
    --pill-mock-fg: #80551B; --pill-mock-bg: #FFF4E3; --pill-mock-border: #EBD8B6;
  }
  * { box-sizing: border-box; }
  :focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
  body {
    margin: 0;
    /* Fira Sans for UI text - the ui-ux-pro-max database's top match for
       "dashboards, analytics, data visualization" moods. Numbers/tickers
       keep their own monospace elsewhere (.price, .market-tag, the factor
       table, scorecard scores) via Fira Code, which lines figures up and
       reads as "precise data" against the sans-serif UI chrome. */
    font-family: 'Fira Sans', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    background: var(--paper);
    color: var(--ink);
  }
  .shell { max-width: 880px; margin: 0 auto; padding: 2.5rem 1.5rem 5rem; }
  header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 2rem; flex-wrap: wrap; gap: 0.5rem; }
  .brand { display: flex; align-items: center; gap: 0.75rem; }
  .brand-mark { width: 40px; height: 40px; flex-shrink: 0; }
  h1 { font-size: 1.6rem; font-weight: 600; margin: 0; letter-spacing: -0.01em; }
  .sub { color: var(--ink-soft); font-size: 0.85rem; margin: 0.1rem 0 0; }
  .status-pill {
    font-family: var(--num-font);
    font-size: 0.75rem;
    padding: 0.3rem 0.6rem;
    border: 1px solid var(--line);
    border-radius: 3px;
    color: var(--ink-soft);
    background: var(--card);
  }
  .status-pill.mock { color: var(--hold); border-color: var(--hold); }
  .status-pill.live { color: var(--buy); border-color: var(--buy); }

  .panel {
    background: var(--card);
    border: 1px solid var(--line);
    border-radius: 6px;
    padding: 1.25rem 1.4rem;
    margin-bottom: 1.25rem;
  }
  .panel h2 { font-size: 1.1rem; margin: 0 0 1rem; font-weight: 600; }
  .subsection-heading {
    font-size: 0.8rem; font-weight: 700; color: var(--ink-soft); text-transform: uppercase;
    letter-spacing: 0.04em; margin: 1.2rem 0 0.6rem; padding-top: 1rem; border-top: 1px solid var(--line);
  }
  .subsection-heading:first-child { margin-top: 0; padding-top: 0; border-top: none; }
  /* Watchlist subsection headings inside Latest Signals / Factor Rankings /
     Market Conditions are buttons (collapsible - see toggleWatchlistCollapse),
     but keep the exact same look as the plain-div headings above. The
     element+class selector here outweighs .subsection-heading on its own,
     so this wins without needing !important. */
  button.subsection-heading {
    display: flex; align-items: center; gap: 0.4rem; width: 100%;
    font-family: inherit; background: none; border: none; border-top: 1px solid var(--line);
    cursor: pointer; text-align: left;
  }
  /* Each of these buttons is the first (and only) child of its own small
     wrapper <div> (e.g. #factorsWatchlistSection), so the generic
     ":first-child strips its own top spacing" rule above matches it too -
     but that rule assumes "first-child" means "first thing in the panel",
     which isn't true here: the wrapper div always follows the holdings
     content above it. Restore the normal spacing so it doesn't visually
     collide with whatever's above it. */
  button.subsection-heading:first-child {
    margin-top: 1.2rem; padding-top: 1rem; border-top: 1px solid var(--line);
  }
  button.subsection-heading:hover { color: var(--ink); }
  .subsection-chevron { font-size: 0.65rem; }

  .setup-row { display: flex; gap: 0.6rem; flex-wrap: wrap; align-items: center; }
  /* Currency next to the Average price field on the Add-holding form - see
     marketCurrency() / the symbolInput listener in app.js. Fixed width so
     the layout doesn't jump between a 3-letter code (USD) and blank. */
  #avgCostCurrency {
    color: var(--ink-soft); font-size: 0.82rem; font-weight: 600;
    font-family: var(--num-font);
    min-width: 2.6rem; display: inline-block;
  }
  /* The id rule above sets display, which beats the browser's own [hidden]
     rule - so the empty label kept its 2.6rem while the currency choice sat
     beside it, squeezing the price box until "275.852" showed as "5.852"
     (a tester, 24 Sep). */
  #avgCostCurrency[hidden] { display: none; }
  /* The price and the unit it is in, kept together (23 Sep, Sam's review).
     The currency used to sit after the date, right against the Add button,
     where it read as a label for the button rather than for the number it
     qualifies - which is the one thing it exists to tell you. */
  .avg-field { display: inline-flex; align-items: center; gap: 0.4rem; flex: 1; min-width: 190px; max-width: 270px; }
  /* Wide enough to show a price with three decimals in full; the field as
     a whole already keeps 190px, so this only stops the box itself being
     squeezed below what it holds. */
  .avg-field input[type=text] { min-width: 6.5rem; }
  /* The cost-currency choice (23 Sep): same footprint as the label it
     replaces, so the row does not jump when a US code is typed. */
  .avg-ccy-select {
    font-family: var(--num-font); font-size: 0.82rem; font-weight: 600;
    color: var(--ink); background: var(--paper); border: 1px solid var(--line); border-radius: 4px;
    padding: 0.45rem 0.3rem; min-width: 4.2rem; cursor: pointer;
  }
  .avg-ccy-select:focus-visible { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-ring); }
  /* "in AUD" beside a gain worked out in the home currency, and "trades in
     USD" under the currency it replaces - the two facts that explain why a
     row's gain includes the currency move. */
  .gain-ccy {
    font-size: 0.7rem; font-weight: 600; color: var(--ink-soft); white-space: nowrap;
    border: 1px solid var(--line); border-radius: 3px; padding: 0 0.3rem; margin-left: 0.25rem; cursor: help;
  }
  .import-ccy-question { border: 1px solid var(--line); border-radius: 6px; padding: 0.2rem 0.8rem 0.7rem; margin: 0.6rem 0; }
  .import-ccy-choice { display: inline-flex; gap: 0.4rem; align-items: center; margin-right: 1.2rem; font-size: 0.9rem; cursor: pointer; }
  .ccy-trades { display: block; font-size: 0.68rem; color: var(--ink-soft); font-weight: 400; white-space: nowrap; }
  /* Show in AUD (24 Sep 2026): the switch above the holdings table, the
     share-price / exchange-rate line under each overseas gain, and the total. */
  .home-view-toggle { display: inline-flex; align-items: center; gap: 0.4rem; font-size: 0.85rem; margin: 0 0 0.5rem; cursor: pointer; }
  .home-view-toggle input { margin: 0; }
  /* Wraps freely: the holdings table has to fit the page (its scroll box is
     left visible for the pinned headers), and this line is the widest thing
     in it. Share price and currency sit on a line each. */
  .home-split { display: block; font-size: 0.7rem; color: var(--ink-soft); font-family: 'Fira Sans', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; white-space: normal; margin-top: 0.1rem; cursor: help; max-width: 10.5rem; margin-left: auto; }
  .home-split > span { display: block; }
  .home-split.muted { font-style: italic; }
  .home-total { margin: 0.7rem 0 0; font-size: 0.88rem; line-height: 1.6; }
  .home-total-parts { color: var(--ink-soft); }
  /* Wraps the ticker <input> on the Add Holding / Add to watchlist rows so
     the autocomplete dropdown (.ticker-suggestions) below has something
     positioned to anchor to. Takes over the flex:1/min-width the bare
     input used to have directly as a .setup-row child - the input itself
     just fills the wrapper now (see "input[type=text]" below). */
  .ticker-field { position: relative; flex: 1; min-width: 160px; }
  .ticker-field input[type=text] { width: 100%; box-sizing: border-box; }
  input[type=text] {
    font-family: inherit;
    font-size: 0.95rem;
    padding: 0.55rem 0.7rem;
    border: 1px solid var(--line);
    border-radius: 4px;
    background: var(--paper);
    color: var(--ink);
    flex: 1;
    min-width: 160px;
  }
  input[type=text]:focus-visible { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-ring); }
  /* Standalone filter box above a long list/table (holdings, watchlist,
     Factor Rankings, Market Conditions, Latest Signals) - not inside a
     .setup-row, so it needs its own width and spacing rather than relying
     on flex:1 from a row of siblings. */
  .filter-input {
    display: block;
    width: 100%;
    box-sizing: border-box;
    margin: 0.9rem 0 0.7rem;
    font-size: 0.85rem;
    padding: 0.5rem 0.7rem;
    color: var(--ink-soft);
  }
  .filter-input:focus-visible { color: var(--ink); }

  /* Ticker autocomplete dropdown (My Portfolio "Add / Update" and Watchlist
     "Add to watchlist" ticker fields) - anchored to .ticker-field above via
     position:absolute, so it overlays whatever sits below the form rather
     than pushing it down. See attachTickerAutocomplete() in app.js. */
  /* Sized to its content, not to the field (23 Sep). It used to be pinned
     left:0/right:0 to an input that is 160px on the Add row, so a company
     name and "AUSTRALIAN SECURITIES EXCHANGE" were cut to an ellipsis and a
     sideways scrollbar - hiding exactly the words that tell BHP (NYSE) from
     BHP.AX (ASX). Never narrower than the field, never wider than the screen. */
  .ticker-suggestions {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    min-width: 100%;
    width: max-content;
    max-width: min(36rem, calc(100vw - 2rem));
    z-index: 20;
    background: var(--card);
    border: 1px solid var(--line);
    border-radius: 4px;
    max-height: 300px;
    overflow-y: auto;
    overflow-x: hidden;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
  }
  .ticker-suggestion {
    display: flex;
    align-items: baseline;
    gap: 0.6rem;
    padding: 0.5rem 0.7rem;
    cursor: pointer;
    border-bottom: 1px solid var(--line);
  }
  .ticker-suggestion:last-child { border-bottom: none; }
  .ticker-suggestion:hover, .ticker-suggestion.active { background: var(--accent-bg); }
  .ticker-suggestion .ts-symbol {
    font-family: var(--num-font);
    font-weight: 700;
    color: var(--ink);
    font-size: 0.88rem;
    flex-shrink: 0;
  }
  /* Wraps rather than truncates: a name cut to "BHP ..." is the one thing
     that cannot be allowed to happen in a list whose job is telling two BHPs
     apart. */
  .ticker-suggestion .ts-name {
    color: var(--ink-soft);
    font-size: 0.82rem;
    flex: 1;
    white-space: normal;
    overflow-wrap: anywhere;
    min-width: 0;
  }
  .ticker-suggestion .ts-exchange {
    color: var(--ink-soft);
    font-size: 0.68rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    border: 1px solid var(--line);
    border-radius: 3px;
    padding: 0.05rem 0.35rem;
    flex-shrink: 0;
  }
  .ticker-suggestions .ts-empty, .ticker-suggestions .ts-loading {
    padding: 0.6rem 0.7rem;
    color: var(--ink-soft);
    font-size: 0.85rem;
  }
  button {
    font-family: inherit;
    font-size: 0.9rem;
    padding: 0.55rem 1rem;
    border-radius: 4px;
    border: 1px solid var(--accent);
    background: var(--accent);
    color: var(--on-accent);
    font-weight: 600;
    cursor: pointer;
    transition: opacity 0.2s ease, transform 0.15s ease;
  }
  button.secondary { background: transparent; color: var(--ink); border-color: var(--line); font-weight: 400; }
  button:hover { opacity: 0.85; }
  button:active { transform: scale(0.98); }
  button:disabled { opacity: 0.4; cursor: default; transform: none; }
  @media (prefers-reduced-motion: reduce) {
    button { transition: none; }
    button:active { transform: none; }
  }

  .sort-select {
    font-family: inherit; font-size: 0.78rem; padding: 0.3rem 0.5rem;
    border: 1px solid var(--line); border-radius: 4px; background: var(--paper); color: var(--ink);
    max-width: 100%;
  }

  /* Cards/Table view toggle for Latest Signals - same visual weight as the
     sort dropdown next to it, styled as a small segmented control. */
  .view-toggle { display: inline-flex; border: 1px solid var(--line); border-radius: 4px; overflow: hidden; }
  .view-toggle-btn {
    font-family: inherit; font-size: 0.78rem; font-weight: 600; padding: 0.3rem 0.65rem;
    border: none; background: var(--paper); color: var(--ink-soft); cursor: pointer;
  }
  .view-toggle-btn + .view-toggle-btn { border-left: 1px solid var(--line); }
  .view-toggle-btn.selected { background: var(--accent); color: var(--card); }
  .signal-row-detail { padding: 0.5rem 0 0.8rem; }
  .tally { white-space: nowrap; font-size: 0.85rem; }
  /* Who they were (9 Oct 2026): the investor school's three, and a one-line bio in each investor block. */
  .whos-who { margin: 0.4rem 0 1.2rem; }
  .whos-who h3 { margin: 0 0 0.6rem; font-size: 1.05rem; }
  .who-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 0.8rem; }
  .who-card { border: 1px solid var(--line); border-radius: 8px; padding: 0.8rem 0.95rem; background: var(--card); min-width: 0; }
  .who-card h4 { margin: 0 0 0.35rem; font-size: 1rem; }
  .who-years { font-weight: 400; color: var(--ink-soft); font-size: 0.85rem; margin-left: 0.3rem; }
  .who-card p { margin: 0 0 0.4rem; font-size: 0.88rem; line-height: 1.5; }
  .who-books, .who-lessons { color: var(--ink-soft); font-size: 0.82rem !important; }
  .who-lessons { margin-bottom: 0 !important; }
  .iv-bio { font-size: 0.85rem; color: var(--ink-soft); margin: 0 0 0.6rem; line-height: 1.5; }
  .tally-up { color: var(--buy); font-weight: 600; }
  .tally-down { color: var(--sell); font-weight: 600; }
  .tally-none { color: var(--ink-soft); }
  /* An opened table row shows exactly the card the Cards view shows: full width, on the page's own ground -
     no grey cell around it and no inset (9 Oct 2026). */
  .factor-detail-row td.signal-detail-cell { padding: 0; background: transparent; }
  /* Filter, view and order together, directly above the list they change (9 Oct 2026). */
  .signals-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem; margin: 0.9rem 0 0.7rem; }
  .signals-toolbar .filter-input { flex: 1 1 220px; min-width: 0; width: auto; margin: 0; }
  .signals-sort { display: inline-flex; align-items: center; gap: 0.4rem; font-size: 0.85rem; color: var(--ink-soft); }

  .refresh-status { display: flex; align-items: center; gap: 0.4rem; font-weight: 400; }
  #refreshStatusLabel { font-size: 0.75rem; color: var(--ink-soft); white-space: nowrap; }
  .refresh-icon-btn {
    border: none; background: none; padding: 0.2rem; margin: 0;
    font-size: 1rem; line-height: 1; color: var(--ink-soft); cursor: pointer;
    border-radius: 4px; display: inline-flex;
  }
  .refresh-icon-btn:hover { color: var(--ink); background: rgba(255,255,255,0.06); opacity: 1; }
  .refresh-icon-btn.spinning { animation: refresh-spin 0.8s linear infinite; color: var(--accent); }
  @keyframes refresh-spin { to { transform: rotate(360deg); } }
  @media (prefers-reduced-motion: reduce) {
    .refresh-icon-btn.spinning { animation: none; }
  }

  /* Holdings/Watchlist lists (My Portfolio, Watchlist panels) - a table
     rather than a wrapped chip list, so Ticker/Company/Qty/Avg price/
     Gain-loss line up in columns instead of being read one chip at a time.
     Reuses .factor-table's base look (same th/td spacing, uppercase muted
     headers) rather than inventing a second table style. */
  .holdings-list { margin: 1rem 0 0; }
  .holdings-table td.num, .holdings-table th.num { text-align: right; font-family: var(--num-font); }
  .holdings-table td.actions { text-align: right; width: 1%; white-space: nowrap; }
  .holdings-table td.currency-cell { color: var(--ink-soft); font-family: var(--num-font); white-space: nowrap; }
  /* Qty/Avg price cells are directly editable (see updateHoldingField() in
     app.js) - styled to look like plain table text until hovered/focused,
     so the table still reads as a table rather than a form, but the border
     that appears on hover signals it can be typed into. */
  .holdings-table input.cell-edit {
    /* min-width: 0 matters: the page-wide input[type=text] rule sets
       min-width 160px for form rows, and inside the table that minimum is what
       auto layout counts as each column's floor - two short numbers were
       taking 167px each, and the table went past its panel the moment the
       Bought column arrived. */
    width: 5.5rem; max-width: 5.5rem; min-width: 0; box-sizing: border-box; text-align: right;
    font: inherit; font-family: var(--num-font);
    padding: 0.15rem 0.35rem; margin: -0.15rem -0.35rem;
    border: 1px solid transparent; border-radius: 3px;
    background: transparent; color: var(--ink);
  }
  .holdings-table input.cell-edit::placeholder { color: var(--ink-soft); }
  .holdings-table input.cell-edit:hover { border-color: var(--line); }
  .holdings-table input.cell-edit:focus-visible { border-color: var(--accent); background: var(--paper); outline: none; }
  .remove-row-btn {
    border: none; background: none; padding: 0.15rem 0.4rem; font-size: 1rem;
    line-height: 1; color: var(--ink-soft); cursor: pointer; border-radius: 3px;
  }
  .remove-row-btn:hover { color: var(--sell); background: var(--sell-bg); }
  .chip-gain { font-family: var(--num-font); font-size: 0.72rem; }
  .chip-gain.up { color: var(--buy); }
  .chip-gain.down { color: var(--sell); }
  .chip-gain.flat { color: var(--ink-soft); }

  .signals-grid { display: grid; gap: 0.7rem; }
  .signals-grid.signals-grid-table { gap: 0; }
  .signal-card {
    border: 1px solid var(--line);
    border-radius: 6px;
    padding: 0.9rem 1.1rem;
    background: var(--card);
  }
  .signal-top { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
  .symbol { font-size: 1.15rem; font-weight: 600; }
  .price { color: var(--ink-soft); font-size: 0.9rem; margin-left: 0.5rem; font-family: var(--num-font); }
  .price .price-login { color: var(--accent); font-family: inherit; font-size: 0.85rem; text-decoration: underline; text-underline-offset: 2px; }
  .signal-company { color: var(--ink-soft); font-size: 0.85rem; margin-top: 0.15rem; }
  .action-badge {
    font-size: 0.78rem; font-weight: 600; letter-spacing: 0.02em;
    padding: 0.25rem 0.65rem; border-radius: 20px;
  }
  .action-badge.BUY { color: var(--buy); background: var(--buy-bg); }
  .action-badge.SELL { color: var(--sell); background: var(--sell-bg); }
  .action-badge.HOLD { color: var(--hold); background: var(--hold-bg); }
  .strength-badge {
    font-size: 0.68rem; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
    padding: 0.22rem 0.55rem; border-radius: 20px; margin-left: 0.4rem;
    color: var(--accent); background: var(--card); border: 1px solid var(--accent);
  }
  .regime-badge, .vol-badge {
    display: inline-block; font-size: 0.75rem; font-weight: 600; letter-spacing: 0.02em;
    padding: 0.2rem 0.55rem; border-radius: 20px; white-space: nowrap;
  }
  .regime-badge.trending_up, .regime-badge.trending { color: var(--buy); background: var(--buy-bg); }
  .regime-badge.trending_down { color: var(--sell); background: var(--sell-bg); }
  .regime-badge.choppy, .regime-badge.transitioning { color: var(--hold); background: var(--hold-bg); }
  .regime-badge.unknown, .vol-badge.contracting, .vol-badge.normal, .vol-badge.unknown {
    color: var(--ink-soft); background: var(--card); border: 1px solid var(--line);
  }
  .vol-badge.elevated { color: var(--hold); background: var(--hold-bg); }
  .stock-type-badge {
    display: inline-block; font-size: 0.75rem; font-weight: 600; letter-spacing: 0.02em;
    padding: 0.2rem 0.6rem; border-radius: 20px; white-space: nowrap;
  }
  /* "You own this" is not a directional fact - it says nothing about whether
     the position is up or down - so it must not wear the gain/BUY green,
     least of all sitting inches from the gain/loss figures that do. Neutral
     outline instead; the word "Holding" carries the meaning on its own. */
  .stock-type-badge.holding { color: var(--ink-soft); background: transparent; border: 1px solid var(--line); }
  .stock-type-badge.watchlist { color: var(--hold); background: var(--hold-bg); }
  .confidence { font-size: 0.78rem; color: var(--ink-soft); margin-top: 0.3rem; }
  .reasons { margin: 0.7rem 0 0; padding-left: 1.1rem; font-size: 0.88rem; color: var(--ink-soft); }
  .reasons li { margin-bottom: 0.2rem; }
  .indicator-toggle { display: block; margin-top: 0.6rem; }
  .indicator-detail {
    margin-top: 0.5rem; padding: 0.6rem 0.8rem; background: var(--paper);
    border: 1px solid var(--line); border-radius: 4px;
    font-size: 0.82rem; color: var(--ink-soft); line-height: 1.55;
  }
  .indicator-detail ul { margin: 0; padding-left: 1.2rem; }
  .indicator-detail li { margin-bottom: 0.25rem; }

  .signal-card-body { display: flex; gap: 1.1rem; flex-wrap: wrap; }
  .signal-main { flex: 1 1 260px; min-width: 0; }
  .signal-radar-col {
    flex: 0 0 auto; width: 170px;
    display: flex; flex-direction: column; align-items: center;
    padding-top: 0.15rem;
  }
  .radar-caption {
    font-size: 0.72rem; color: var(--ink-soft); text-align: center;
    margin-top: 0.35rem; line-height: 1.4;
  }
  /* The three readings (8 Oct 2026): each with its direction, view or not. */
  .rd-general { margin: 0.6rem 0 0.2rem; font-size: 0.9rem; color: var(--ink); }
  .readings { list-style: none; margin: 0.4rem 0 0; padding: 0; display: grid; gap: 0.45rem; }
  .rd-row { border-left: 3px solid var(--line); padding: 0.15rem 0 0.15rem 0.6rem; }
  .rd-row.rd-up { border-left-color: var(--buy); }
  .rd-row.rd-down { border-left-color: var(--sell); }
  .rd-head { display: flex; align-items: baseline; justify-content: space-between; gap: 0.6rem; flex-wrap: wrap; }
  .rd-name { font-weight: 600; font-size: 0.86rem; color: var(--ink); }
  .rd-dir { font-size: 0.74rem; font-weight: 600; letter-spacing: 0.02em; color: var(--ink-soft); white-space: nowrap; }
  .rd-up .rd-dir { color: var(--buy); }
  .rd-down .rd-dir { color: var(--sell); }
  .rd-text { font-size: 0.84rem; color: var(--ink-soft); line-height: 1.5; margin-top: 0.1rem; }
  .rd-glance { width: 100%; display: grid; gap: 0.3rem; }
  .rdg { display: grid; grid-template-columns: 1.1rem 1fr auto; align-items: center; gap: 0.3rem;
    padding: 0.3rem 0.4rem; border-radius: 6px; border: 1px solid var(--line); font-size: 0.74rem; }
  .rdg-mark { text-align: center; color: var(--ink-soft); }
  .rdg-name { color: var(--ink); line-height: 1.25; }
  .rdg-clock { display: block; color: var(--ink-soft); font-size: 0.66rem; }
  .rdg-word { color: var(--ink-soft); font-weight: 600; }
  .rdg-up { border-color: var(--buy); background: var(--buy-bg); }
  .rdg-up .rdg-mark, .rdg-up .rdg-word { color: var(--buy); }
  .rdg-down { border-color: var(--sell); background: var(--sell-bg); }
  .rdg-down .rdg-mark, .rdg-down .rdg-word { color: var(--sell); }
  .chg-method { margin: 0 0 0.6rem; }
  .radar-grid { fill: none; stroke: var(--line); stroke-width: 1; }
  .radar-grid.mid { stroke-dasharray: 2 2; }
  .radar-axis { stroke: var(--line); stroke-width: 1; }
  .radar-fill { stroke-width: 1.6; stroke-linejoin: round; }
  .radar-fill.BUY { fill: var(--buy); fill-opacity: 0.25; stroke: var(--buy); }
  .radar-fill.SELL { fill: var(--sell); fill-opacity: 0.25; stroke: var(--sell); }
  .radar-fill.HOLD { fill: var(--hold); fill-opacity: 0.25; stroke: var(--hold); }
  .radar-label {
    font-family: 'Fira Sans', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    font-size: 11px; font-weight: 700; letter-spacing: 0.02em; fill: var(--ink-soft);
  }

  /* Signal history timeline (per signal card "View history") - a compact
     Buy/Hold/Sell swimlane built from the existing append-only signal log. */
  .history-toggle { display: block; margin-top: 0.5rem; }
  .signal-history-detail {
    margin-top: 0.5rem; padding: 0.6rem 0.8rem; background: var(--paper);
    border: 1px solid var(--line); border-radius: 4px;
  }
  .history-timeline-wrap svg { display: block; width: 100%; height: auto; }
  .history-caption { font-size: 0.78rem; color: var(--ink-soft); margin: 0 0 0.5rem; line-height: 1.4; }
  .history-lane-ref { stroke: var(--line); stroke-width: 1; }
  .history-line { fill: none; stroke: var(--ink-soft); stroke-width: 1; stroke-opacity: 0.5; }
  .history-point { stroke-width: 1.5; fill-opacity: 0.85; }
  .history-point.BUY { fill: var(--buy); stroke: var(--buy); }
  .history-point.SELL { fill: var(--sell); stroke: var(--sell); }
  .history-point.HOLD { fill: var(--hold); stroke: var(--hold); }
  .history-point.history-strong { stroke-width: 2.5; fill-opacity: 1; }
  .history-axis-label {
    font-family: 'Fira Sans', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    font-size: 10px; fill: var(--ink-soft);
  }
  .history-legend { display: flex; gap: 0.9rem; flex-wrap: wrap; margin-top: 0.4rem; font-size: 0.75rem; color: var(--ink-soft); }
  .history-legend span { display: inline-flex; align-items: center; gap: 0.3rem; }
  .history-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; }
  .history-dot.BUY { background: var(--buy); }
  .history-dot.SELL { background: var(--sell); }
  .history-dot.HOLD { background: var(--hold); }

  /* AI deep-dive research (per signal card "Deep dive") - a plain-language
     synthesis of financials/insider activity/news/technical context, plus
     a "since your last look" status. Reuses the same detail-box look as
     .indicator-detail/.signal-history-detail rather than inventing a new
     visual language for it. */
  .research-toggle { display: block; margin-top: 0.5rem; }
  .research-detail {
    margin-top: 0.5rem; padding: 0.6rem 0.8rem; background: var(--paper);
    border: 1px solid var(--line); border-radius: 4px;
    font-size: 0.85rem; color: var(--ink-soft); line-height: 1.55;
  }
  .research-summary { margin: 0 0 0.6rem; color: var(--ink); }
  .research-summary:last-of-type { margin-bottom: 0; }
  .research-changed-badge {
    display: inline-block; font-size: 0.72rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.03em; padding: 0.2rem 0.5rem; border-radius: 3px; margin-bottom: 0.6rem;
  }
  .research-changed-badge.research-changed { color: var(--hold); background: var(--hold-bg); }
  .research-changed-badge.research-unchanged { color: var(--ink-soft); background: var(--card); border: 1px solid var(--line); }
  .research-changed-badge.research-first { color: var(--accent); background: var(--accent-bg); }
  .research-caveat {
    font-size: 0.78rem; color: var(--ink); background: var(--hold-bg); border: 1px solid var(--hold);
    border-radius: 4px; padding: 0.5rem 0.7rem; margin-bottom: 0.6rem; line-height: 1.45;
  }
  .research-sources { font-size: 0.76rem; margin-top: 0.5rem; }
  .research-sources-label { font-weight: 700; }
  .research-sources a { color: var(--accent); }
  .research-meta { font-size: 0.72rem; margin-top: 0.6rem; color: var(--ink-soft); }

  /* Portfolio Signal Scorecard - a larger 5-axis version of the per-card
     radar above, plus a click-an-axis lifting/holding-back breakdown. */
  .scorecard-body { display: flex; gap: 1.5rem; flex-wrap: wrap; align-items: flex-start; }
  .scorecard-radar-col { flex: 0 0 auto; width: 260px; }
  .scorecard-fill { fill: var(--accent); fill-opacity: 0.22; stroke: var(--accent); stroke-width: 1.8; stroke-linejoin: round; }
  .scorecard-axis-label { cursor: pointer; }
  .scorecard-axis-label.selected { fill: var(--accent); }
  .scorecard-axis-buttons { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.8rem; }
  .scorecard-axis-btn {
    display: flex; align-items: baseline; gap: 0.35rem;
    padding: 0.3rem 0.6rem; border-radius: 4px;
    border: 1px solid var(--line); background: var(--card); color: var(--ink);
    font-family: inherit; font-size: 0.78rem; cursor: pointer;
  }
  .scorecard-axis-btn .axis-btn-score { font-family: var(--num-font); color: var(--ink-soft); }
  .scorecard-axis-btn.selected { border-color: var(--accent); background: var(--accent-bg); }
  .scorecard-axis-btn.selected .axis-btn-score { color: var(--accent); font-weight: 700; }
  .scorecard-breakdown { flex: 1 1 320px; min-width: 0; }
  .scorecard-axis-heading { display: flex; align-items: baseline; gap: 0.5rem; margin-bottom: 0.3rem; }
  .scorecard-axis-name { font-size: 1rem; font-weight: 700; }
  .scorecard-axis-score { font-family: var(--num-font); color: var(--ink-soft); font-size: 0.85rem; }
  .lift-cols { display: flex; gap: 1.5rem; flex-wrap: wrap; margin-top: 0.6rem; }
  .lift-cols > div { flex: 1 1 140px; min-width: 130px; }
  .lift-col-label { display: block; font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em; margin-bottom: 0.35rem; }
  .lift-col-label.up { color: var(--buy); }
  .lift-col-label.down { color: var(--sell); }
  .lift-row { display: flex; justify-content: space-between; gap: 0.6rem; padding: 0.2rem 0; font-size: 0.85rem; }
  .lift-row .sym { font-weight: 600; }
  .lift-row .pct { font-family: var(--num-font); }
  .lift-row .pct.up { color: var(--buy); }
  .lift-row .pct.down { color: var(--sell); }
  .scorecard-nodata { margin-top: 0.7rem; font-size: 0.78rem; color: var(--ink-soft); }

  /* Most .empty elements are <p>, which keeps the browser's default 1em
     top/bottom margin unless told otherwise. Combined with the 1rem padding
     this used to carry, a single line of "nothing to show here" text ended up
     with ~55px of space beneath it INSIDE a panel that already has 21px of
     its own padding - so a panel with nothing to say rendered taller and
     airier than one full of real content. Backwards, and very visible on a
     page where two or three "not available" states can stack (a non-US
     ticker, a quota-exhausted deep dive, a symbol with no filings).
     Margin zeroed, padding cut to a small amount that still separates it
     from the heading above. */
  .empty { color: var(--ink-soft); font-size: 0.9rem; margin: 0; padding: 0.15rem 0 0.35rem; }
  .footnote { color: var(--ink-soft); font-size: 0.875rem; margin-top: 2rem; line-height: 1.55; }
  .footnote code { background: var(--card); border: 1px solid var(--line); padding: 0.05rem 0.35rem; border-radius: 3px; font-size: 0.78rem; }
  .hint-box {
    background: var(--hold-bg); border: 1px solid var(--hold); border-radius: 4px;
    padding: 0.6rem 0.8rem; font-size: 0.82rem; color: var(--ink); line-height: 1.5;
    margin: 0 0 0.9rem;
  }
  .hint-box code { background: var(--card); border: 1px solid var(--line); padding: 0.05rem 0.35rem; border-radius: 3px; font-size: 0.78rem; }
  /* The Add form's market help (23 Sep). The old one was a single 0.82rem
     paragraph of five clauses that testers skipped. Now: body-size text,
     the easy path first, two examples, and the full list one click away
     instead of one page away. */
  .suffix-hint { font-size: 0.92rem; }
  .suffix-hint code { font-size: 0.85rem; }
  .market-list { margin-top: 0.45rem; }
  .market-list summary { cursor: pointer; color: var(--accent); font-weight: 600; font-size: 0.86rem; }
  .market-list summary:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--accent-ring); border-radius: 3px; }
  .market-grid {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(12.5rem, 1fr));
    gap: 0.3rem 1rem; margin: 0.55rem 0 0.1rem; font-size: 0.85rem;
  }
  .market-grid div { display: flex; gap: 0.5rem; align-items: baseline; }
  .market-grid code { min-width: 3.1rem; text-align: center; }
  .market-grid .mg-name { color: var(--ink); }
  .market-grid .mg-cur { color: var(--ink-soft); font-size: 0.78rem; margin-left: auto; font-family: var(--num-font); }
  .market-tag {
    font-family: inherit; font-size: 0.75rem; font-weight: 400;
    color: var(--ink-soft); white-space: nowrap;
  }
  .ticker-code { font-weight: 700; }
  .symbol-label { display: inline-flex; align-items: baseline; gap: 0.4rem; flex-wrap: wrap; }
  .symbol-label .market-tag::before { content: '·'; margin-right: 0.4rem; }
  /* A ticker that links through to its own full page (see stock.html) -
     looks like plain text until hovered, so tables full of tickers don't
     turn into a wall of blue underlines. */
  /* A dotted underline on the ticker itself, by default, is the "this is
     clickable" signal - not just a hover-only change, since a hover cue
     never reaches anyone scanning the table without a mouse over it. Solid
     + accent-colored on hover/focus confirms it. See also the
     .ticker-click-hint line above the holdings table (renderHoldingsList()
     in app.js). */
  a.ticker-link { color: inherit; text-decoration: none; }
  a.ticker-link .ticker-code {
    text-decoration: underline dotted;
    text-decoration-color: var(--ink-soft);
    text-underline-offset: 3px;
  }
  a.ticker-link:hover .ticker-code, a.ticker-link:hover .symbol,
  a.ticker-link:focus-visible .ticker-code, a.ticker-link:focus-visible .symbol {
    text-decoration: underline solid;
    text-decoration-color: var(--accent);
    color: var(--accent);
  }
  .ticker-click-hint { color: var(--ink-soft); font-size: 0.8rem; margin: 0 0 0.6rem; }

  .table-scroll { overflow-x: auto; }
  .factor-table { width: 100%; border-collapse: collapse; font-size: 0.85rem; }
  .factor-table th, .factor-table td { text-align: left; padding: 0.35rem 0.55rem; border-bottom: 1px solid var(--line); }
  .factor-table th { color: var(--ink-soft); font-weight: 600; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.03em; }
  .factor-table td.num, .factor-table th.num { text-align: right; font-family: var(--num-font); }
  .factor-rank { font-family: var(--num-font); color: var(--ink-soft); }
  .factor-row { cursor: pointer; }
  .factor-row:hover { background: rgba(255,255,255,0.04); }
  .factor-chevron { display: inline-block; font-size: 0.7rem; margin-left: 0.3rem; color: var(--ink-soft); }
  /* width:0 on this colspanned cell keeps its (often long, wrapping)
     content out of the browser's auto table-layout column-width
     calculation. Without it, expanding a row made its detail text a
     factor in sizing every column - other rows' Trend/Volatility/etc.
     columns would visibly shift and compress the moment any row opened,
     since the table has to satisfy the detail cell's minimum content
     width by borrowing space from the other columns. The detail content
     still renders at full width either way (a colspan cell always
     stretches to fill its spanned columns) - this only removes it from
     the sizing math, which is exactly what we want since it should wrap
     to fit the table, not dictate the table's shape. */
  .factor-detail-row td { border-bottom: 1px solid var(--line); background: var(--paper); width: 0; }
  .factor-detail { padding: 0.5rem 0.2rem 0.6rem; font-size: 0.82rem; color: var(--ink-soft); line-height: 1.55; }
  .factor-detail ul { margin: 0.5rem 0; padding-left: 1.2rem; }
  .factor-detail li { margin-bottom: 0.25rem; }

  .nav-link { font-size: 0.8rem; color: var(--accent); text-decoration: none; border-bottom: 1px dotted var(--accent); }
  .nav-link:hover { opacity: 0.75; }
  .header-links { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; }

  .user-badge { display: inline-flex; align-items: center; gap: 0.5rem; font-size: 0.8rem; color: var(--ink-soft); }
  .user-badge button { padding: 0.2rem 0.6rem; font-size: 0.75rem; }
  .auth-shell { max-width: 420px; margin: 3rem auto 0; }
  .auth-error {
    background: var(--sell-bg); border: 1px solid var(--sell); color: var(--sell);
    border-radius: 4px; padding: 0.5rem 0.7rem; font-size: 0.82rem; margin-bottom: 0.8rem;
  }
  .auth-field { display: block; width: 100%; margin-bottom: 0.6rem; }
  .auth-actions { display: flex; flex-direction: column; gap: 0.6rem; margin-top: 0.3rem; }
  .auth-forgot { margin: 0.6rem 0 0; font-size: 0.82rem; }
  .auth-forgot a { color: var(--accent); text-decoration: none; border-bottom: 1px dotted var(--accent); }
  .auth-forgot a:hover { opacity: 0.75; }
  input[type=password] {
    font-family: inherit; font-size: 0.95rem; padding: 0.55rem 0.7rem;
    border: 1px solid var(--line); border-radius: 4px; background: var(--paper);
    color: var(--ink); width: 100%;
  }
  input[type=password]:focus-visible { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-ring); }

  .reason-line { display: block; }
  .learn-link {
    display: inline-block; margin-left: 0.35rem; font-size: 0.78rem;
    color: var(--accent); text-decoration: none; border-bottom: 1px dotted var(--accent);
    background: none; border-top: none; border-left: none; border-right: none;
    padding: 0; cursor: pointer; font-family: inherit;
  }
  .learn-link:hover { opacity: 0.75; }

  .learn-panel-intro { color: var(--ink-soft); font-size: 0.9rem; line-height: 1.6; margin: 0 0 1.1rem; }
  .learn-entry {
    border: 1px solid var(--line); border-radius: 6px; padding: 0.2rem 1rem;
    margin-bottom: 0.6rem; background: var(--paper);
  }
  .learn-entry[open] { background: var(--card); }
  .learn-entry summary {
    cursor: pointer; padding: 0.7rem 0; font-weight: 600; font-size: 0.95rem;
    list-style: none;
  }
  .learn-entry summary::-webkit-details-marker { display: none; }
  .learn-entry summary { display: flex; align-items: center; justify-content: space-between; gap: 0.8rem; }
  .learn-entry summary::after { content: "+"; color: var(--accent); font-weight: 700; font-size: 1.1rem; line-height: 1; flex: 0 0 auto; }
  .learn-entry[open] summary::after { content: "\2212"; }
  .learn-entry summary .learn-fullpage-tag { margin-left: auto; }
  .learn-entry p { font-size: 0.88rem; color: var(--ink-soft); line-height: 1.65; margin: 0 0 0.9rem; }

  /* Portfolio Health (see app.portfolio_health on the backend / loadPortfolioHealth()
     in app.js). health-entry reuses the exact same click-to-expand disclosure
     styling as .learn-entry above rather than inventing a second pattern - it's
     the same "closed by default, +/- marker, click the summary line" widget,
     just for a different panel's sub-sections. */
  .health-headline {
    font-size: 1.02rem; font-weight: 650; color: var(--ink); line-height: 1.55;
    margin: 0 0 1rem; padding: 0.85rem 1rem; background: var(--card);
    border: 1px solid var(--line); border-left: 3px solid var(--accent); border-radius: 6px;
  }
  .health-entry {
    border: 1px solid var(--line); border-radius: 6px; padding: 0.2rem 1rem;
    margin-bottom: 0.6rem; background: var(--paper);
  }
  .health-entry[open] { background: var(--card); }
  .health-entry summary {
    cursor: pointer; padding: 0.7rem 0; font-weight: 600; font-size: 0.92rem;
    list-style: none;
  }
  .health-entry summary::-webkit-details-marker { display: none; }
  .health-entry summary::before { content: "+ "; color: var(--accent); font-weight: 700; }
  .health-entry[open] summary::before { content: "\2212 "; }
  .health-entry > p:last-child, .health-entry > .health-bar-row:last-child { margin-bottom: 0.9rem; }
  /* A finding's stated lever ("trimming X would do Y") gets its own quiet
     callout, distinct from the plain-footnote finding text above it - visually
     a step between "just a fact" and the disclaimer-box treatment used for an
     actual compliance warning elsewhere on this site, since a lever is neither. */
  .health-lever {
    font-size: 0.85rem; color: var(--ink-soft); background: var(--pill-bg);
    border: 1px solid var(--pill-border); border-radius: 6px; padding: 0.6rem 0.8rem;
    margin: 0 0 0.9rem;
  }
  .health-bar-row { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.45rem; font-size: 0.84rem; }
  .health-bar-label { width: 128px; flex-shrink: 0; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .health-bar-track { flex: 1; height: 7px; background: var(--line); border-radius: 4px; overflow: hidden; }
  .health-bar-fill { display: block; height: 100%; background: var(--accent); border-radius: 4px; }
  .health-bar-value { width: 48px; flex-shrink: 0; text-align: right; font-family: var(--num-font); color: var(--ink-soft); }
  .disclaimer-box {
    background: var(--sell-bg); border: 1px solid var(--sell); border-radius: 4px;
    padding: 0.8rem 1rem; font-size: 0.85rem; color: var(--ink); line-height: 1.6;
    margin-top: 1.2rem;
  }

/* Shared public-site header identity; account hooks are preserved. Colors
   read through the theme tokens above (see :root / :root[data-theme="light"])
   so the header follows the same dark/light toggle as the rest of the page -
   it used to be hardcoded to always-light regardless of the page's own
   theme, which was its own small inconsistency alongside the nav one below. */
/* font-family here is "Inter, ui-sans-serif, system-ui, ..." rather than
   this site's actual Fira Sans brand stack - a leftover from the imported
   dashboard design system's own defaults (Inter is never linked or
   @font-face'd anywhere on this site, so it always falls through to each
   visitor's system UI font). Cosmetically inconsistent with the rest of the
   page's body text, but deliberately left alone here: switching it to Fira
   Sans was tried and measured to *reintroduce* a version of the exact bug
   this file's scrollbar-gutter fix above exists to kill - every name in the
   current fallback stack resolves to a local, already-available font with
   no network fetch, so the header's width is stable from first paint with
   zero swap risk, where Fira Sans would (measured ~3-4px narrower once it
   loads than the system fallback it briefly shows first). Worth revisiting
   with a reserved min-width if the brand/nav ever need to match the site's
   Fira Sans identity, but not swapped in casually. */
.site-header{position:sticky;top:0;z-index:20;margin:0;padding:0;display:block;background:var(--header-bg);backdrop-filter:blur(16px);border-bottom:1px solid var(--line);color:var(--ink);font:15px/1.5 Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif}
.site-header-inner{min-height:70px;max-width:1320px;margin:auto;padding:12px 24px;display:flex;align-items:center;gap:20px;flex-wrap:wrap}
.site-brand{display:flex;align-items:center;gap:10px;font-size:18px;font-weight:760;letter-spacing:-.02em;color:var(--ink);text-decoration:none;white-space:normal;max-width:15rem}
.site-brand .logo{width:29px;height:29px;border-radius:8px;background:var(--brand-mark-bg);display:grid;place-items:center}
.site-brand svg{width:18px;height:18px}
/* Nav links are now identical, in the same order, on every page that shares
   this header (Home / Dashboard / Portfolio / Company Lookup / Learn the
   terms) and never toggled by login state or page type - previously the
   "Learn the signals" link was display:none by default and only ever shown
   by JS after login on dashboard/portfolio, and stayed permanently hidden
   on stock.html, so the menu had a different number of visible items
   depending on which page and auth state you were on, and visibly
   reflowed. A fixed, always-visible set of links removes that entirely. */
.site-navigation,.site-account{display:flex;align-items:center;gap:16px;flex-wrap:wrap}
.site-navigation a{color:var(--ink-soft);text-decoration:none;font-weight:560;font-size:14px;padding:8px 0}
.site-navigation a:hover{color:var(--ink)}
.site-navigation a[aria-current]{color:var(--accent);box-shadow:0 2px var(--accent)}
/* min-height keeps this row's own box constant regardless of which auth
   element is currently showing - the "Log in" link and the user badge don't
   render at quite the same height (the link has button-like padding the
   badge doesn't), so without this the header would shrink by a few px the
   moment a login/logout swapped one for the other.
   margin-left:auto (not margin-right:auto on .site-brand, which used to do
   this job) is what pushes this cluster to the right edge - moved here so
   nav's own x-position is anchored only to the brand's fixed width, never to
   this cluster's. That matters because this cluster's content keeps
   changing size after first paint with nothing the user did: the status
   pill starts as "checking data source..." and shrinks once that resolves,
   and "Log in" swaps for the user badge once an existing session is
   confirmed - both fire on literally every page load. With the old
   margin-right:auto on .site-brand, nav sat sandwiched between two
   auto-margins, so every one of those resizes visibly slid the whole nav
   left/right a moment after the page had already settled - not just a wrap
   at the responsive breakpoint below, but a continuous shift on any screen
   wide enough for a single row. Anchoring the push here instead means nav
   sits immediately after the brand at a fixed spot, and only this cluster's
   own right-aligned content grows or shrinks in place. */
.site-account{gap:14px;min-height:43px;margin-left:auto}
.site-header .user-badge{color:var(--ink-soft);gap:12px;font:inherit}
/* Bounded at every width, not just the narrow breakpoint below - an email
   used as the display name (no name set at signup) is the single widest
   thing that can land in this header, and its length is outside this site's
   control, so it's truncated everywhere rather than only once the header is
   already stacked. */
.site-header #userBadgeName{max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:inline-block;vertical-align:bottom}
.site-header .secondary,.site-header .header-login-link{color:var(--ink);border:1px solid var(--line);background:transparent;border-radius:10px;padding:9px 14px;font:600 14px/1.5 inherit;cursor:pointer;text-decoration:none;display:inline-block}
/* Paired with the inline head script (see the data-theme one, same file)
   that stamps data-authed="1" on <html> synchronously from a saved
   trendentum_token, before app.js has even loaded, let alone confirmed the
   token is still valid. Without this, a returning logged-in visitor saw
   "Log in" on every single page load (it's static in the HTML) until
   startApp()'s /auth/me round trip finished and swapped in the user badge -
   another sideways shift in this cluster, and the most common case of all
   given most visits are from an already-logged-in session. app.js still
   hides the link itself once it actually confirms the session (see
   startApp()), and un-hides it if the token turns out to be stale (see
   logout()) - this rule only closes the gap before either of those can run. */
html[data-authed="1"] .site-header .header-login-link{display:none}
.site-header .secondary:hover,.site-header .header-login-link:hover{background:var(--card)}
/* min-width fits "checking data source..." (the widest of the pill's 3
   possible strings, ~161px measured in this font stack) so the pill's own
   box - and everything to its right in .site-account (the login link/user
   badge) - doesn't shrink sideways once that resolves to the shorter "live
   data"/"sample data" a moment later. Centered so the shorter, final text
   sits balanced in the reserved box rather than flush left with trailing
   empty space. */
.site-header .status-pill{background:var(--pill-bg);color:var(--ink-soft);border:1px solid var(--pill-border);border-radius:8px;font-size:12px;min-width:162px;text-align:center}
.site-header .status-pill.live{color:var(--pill-live-fg);border-color:var(--pill-live-border);background:var(--pill-live-bg)}
.site-header .status-pill.mock{color:var(--pill-mock-fg);border-color:var(--pill-mock-border);background:var(--pill-mock-bg)}
.site-header a:focus-visible,.site-header button:focus-visible{outline:3px solid var(--accent);outline-offset:4px}
/* Theme toggle button - see toggleTheme()/updateThemeToggleIcon() in app.js.
   Icon is set from JS (a plain unicode glyph, not an image), so this is
   just the button chrome.
   Markup order matters here, not just this rule: the button is placed LAST
   inside .site-account (after the status pill and the login-link/user-badge
   pair) in every page's HTML, not first. .site-account is right-flush via
   margin-left:auto above, so its right edge sits at a fixed x-position and
   only its left edge moves as its content's total width changes - which it
   does, on every page load, both when the status pill's "checking data
   source..." resolves to its shorter final text and when the login link
   swaps for the user badge. A first-position toggle button sat at that
   moving left edge and visibly slid sideways on both of those transitions;
   as the last (rightmost) child it now sits flush against the fixed right
   edge instead, unaffected by how wide its siblings to the left currently
   are. */
.theme-toggle-btn{border:1px solid var(--line);background:transparent;color:var(--ink);border-radius:8px;width:34px;height:34px;padding:0;font-size:1.05rem;line-height:1;cursor:pointer;display:inline-flex;align-items:center;justify-content:center}
.theme-toggle-btn:hover{background:var(--card)}
/* Header theme switch: two buttons, the lit one is the theme in use - so it
   reads as a state, not a guess about what one click would do. Replaces the
   single icon toggle and the duplicate Dark/Light row in the account menu
   (Sam, 20 Sep). */
.theme-switch{display:inline-flex;border:1px solid var(--line);border-radius:8px;overflow:hidden;height:34px}
.theme-switch-btn{border:0;background:transparent;color:var(--ink-soft);width:34px;height:34px;padding:0;font-size:1rem;line-height:1;cursor:pointer;display:inline-flex;align-items:center;justify-content:center}
.theme-switch-btn+.theme-switch-btn{border-left:1px solid var(--line)}
.theme-switch-btn:hover{background:var(--card);color:var(--ink)}
.theme-switch-btn.active{background:var(--accent);color:var(--on-accent)}
/* Below this width, brand + all 5 nav links + the full account cluster
   (toggle + status pill + login link/user badge) genuinely do not fit on one
   line - at 1280px-ish they used to wrap right after the "checking data
   source..." pill resolved to its final text, so the header visibly jumped
   between one and two rows a moment after every page load, and again on
   login/logout as the account cluster's own width changed. Below this
   breakpoint the header instead commits cleanly to a second row for nav,
   which is a stable, predictable layout at any content length - preferable
   to a single row that might silently wrap depending on transient text.
   Raised from a mobile-only 760px to cover that entire "content doesn't fit
   yet" range; the max-width above only needs to comfortably fit the content
   at widths beyond this breakpoint, which it now does. (.site-account's
   margin-left:auto is now a base rule above, not repeated here - it does the
   same job on this row as on the wide single-row layout: pushing the
   cluster to the right of whatever's on its row.) */
@media(max-width:1300px){.site-header-inner{gap:12px 20px;padding:12px 16px}.site-navigation{order:3;width:100%;gap:24px}.site-header .user-badge{flex-wrap:wrap}.site-header{position:relative;backdrop-filter:none}}
@media(max-width:420px){.site-account{width:100%;justify-content:space-between}.site-navigation{gap:18px}}

/* Keep page-specific sections out of layout and accessibility tree, including after refresh. */
body[data-page="dashboard"] #portfolioPanel,body[data-page="dashboard"] #watchlistPanel{display:none!important}
body[data-page="portfolio"] #healthPanel,body[data-page="portfolio"] #sectorsPanel,body[data-page="portfolio"] #comparePanel,body[data-page="portfolio"] #signalsPanel,body[data-page="portfolio"] #regimePanel,body[data-page="portfolio"] #backtestPanel,body[data-page="portfolio"] #quietPanel{display:none!important}
.watchlist-preview-footer{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;margin-top:14px}.watchlist-preview-footer .footnote{margin:0}.watchlist-preview-footer button{min-height:44px;background:rgba(51,208,166,.12);border:1px solid rgba(51,208,166,.55);color:var(--ink);font-weight:600;border-radius:999px;padding:0 1.1rem}.watchlist-preview-footer button:hover,.watchlist-preview-footer button:focus-visible{background:rgba(51,208,166,.22);border-color:#33d0a6}.watchlist-preview-footer button[aria-expanded="true"]{background:transparent}.watchlist-preview-footer button::after{content:" \25BE";font-size:.8em}.watchlist-preview-footer button[aria-expanded="true"]::after{content:" \25B4"}
.row-hint{margin:0 0 .5rem}.signals-table tr.factor-row{cursor:pointer}.signals-table tr.factor-row:hover td{background:rgba(51,208,166,.06)}.row-open-cell{text-align:right;white-space:nowrap}.row-open{display:inline-block;font-size:.78rem;font-weight:600;color:#33d0a6;border:1px solid rgba(51,208,166,.5);border-radius:999px;padding:.1rem .55rem}.row-open .factor-chevron{color:#33d0a6;margin-left:.15rem}.signals-table .row-open-head{width:1%}
.radar-words{margin-top:.45rem;display:flex;flex-wrap:wrap;justify-content:center;gap:.25rem .4rem;font-size:.72rem;line-height:1.3}.radar-words-lead{flex-basis:100%;text-align:center;color:var(--ink-soft);margin-bottom:.1rem}.rw{border:1px solid var(--line);border-radius:999px;padding:.05rem .45rem;color:var(--ink-soft);white-space:nowrap}.rw b{color:var(--ink);font-weight:600}.rw.rw-3{border-color:rgba(51,208,166,.6);background:rgba(51,208,166,.1)}.rw.rw-2{border-color:rgba(51,208,166,.3)}.radar-why{flex-basis:100%;text-align:center;margin-top:.3rem;color:var(--ink);font-size:.72rem;line-height:1.35;border-top:1px dashed var(--line);padding-top:.3rem}

/* Add Portfolio - 4 ways to add holdings (Add manually / Paste holdings /
   Import CSV-Excel / Connect brokerage - see selectAddPortfolioMode() in
   app.js and the onboarding-refresh entry in
   claude/growth-and-product-roadmap.md). A tab row rather than 4 big cards:
   this sits in the same spot on every visit to My Portfolio, not just a
   first-time onboarding moment, so it stays compact for someone who
   already has holdings and just wants the quick single-ticker form (which
   is why "Add manually" - not Connect brokerage - is the default active
   tab, even though brokerage sync is the headline idea; see .coming-soon-badge
   below for why). */
.add-portfolio-tabs{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:0.8rem}
.add-portfolio-tab{font-family:inherit;font-size:0.85rem;font-weight:600;padding:0.5rem 0.85rem;border-radius:20px;border:1px solid var(--line);background:transparent;color:var(--ink-soft);cursor:pointer;display:inline-flex;align-items:center;gap:0.4rem}
.add-portfolio-tab:hover{color:var(--ink);background:var(--card)}
.add-portfolio-tab.active{background:var(--accent);border-color:var(--accent);color:var(--on-accent)}
/* Deliberately understated, not the large/default option a straight SWS
   copy would make it: this build's "Connect brokerage" doesn't actually
   sync anything yet (real broker sync needs a paid aggregator and a
   security review - see routers/portfolio.py's broker_interest()), so
   making it the prominent default would put the least-functional option
   in the most-trusted spot. The badge makes that status legible at a
   glance rather than a surprise after clicking. */
.mg-soon{opacity:0.55}
.coming-soon-badge{font-size:0.68rem;font-weight:700;letter-spacing:0.03em;text-transform:uppercase;padding:0.1rem 0.45rem;border-radius:20px;background:var(--hold-bg);color:var(--hold)}
.add-portfolio-tab.active .coming-soon-badge{background:rgba(255,255,255,0.25);color:var(--on-accent)}
.add-portfolio-panel[hidden]{display:none}
.paste-holdings-textarea{display:block;width:100%;box-sizing:border-box;font-family:inherit;font-size:0.9rem;padding:0.6rem 0.7rem;border:1px solid var(--line);border-radius:4px;background:var(--paper);color:var(--ink);resize:vertical;min-height:7rem}
.paste-holdings-textarea:focus-visible{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-ring)}
input[type=file]{font-family:inherit;font-size:0.85rem;color:var(--ink-soft)}
/* Result summary after a paste/import/broker-interest submit - one line of
   plain feedback (added/updated counts, or the "thanks" message) plus,
   when rows were skipped, the exact per-row reason so nothing silently
   vanishes into a portfolio that's just quietly missing a holding. */
.import-result{margin-top:0.7rem;font-size:0.85rem;color:var(--ink)}
.import-result-summary{font-weight:600}
/* Says, in words, that a paste/import overwrote existing holdings rather
   than adding to them - the one behaviour difference between the bulk paths
   and the single-add form, and the one worth being explicit about. */
.import-result-note{margin:0.4rem 0 0;font-size:0.84rem;color:var(--ink-soft);line-height:1.5}
.import-result-skipped{margin:0.4rem 0 0;padding-left:1.1rem;color:var(--ink-soft)}
/* Same shape as the skipped list, but this is what we DID, not what we
   didn't - so it reads as information rather than a problem. */
.import-result-translated{margin:0.4rem 0 0;padding-left:1.1rem;color:var(--ink-soft)}
.import-result-skipped li{margin:0.15rem 0}
.import-result.error{color:var(--sell)}

/* --- First-run dashboard state (dashboard.html #firstRunPanel) -------------
   Shown instead of the six data panels when a portfolio has no holdings and
   no watchlist items. See the comment on the panel itself in dashboard.html
   for why this replaced six repeated "Add a holding" placeholders. */
.first-run-list{list-style:none;margin:0 0 1.4rem;padding:0;display:grid;gap:0.55rem}
.first-run-list li{display:grid;grid-template-columns:minmax(0,11rem) 1fr;gap:0.2rem 1rem;align-items:baseline;padding:0.6rem 0;border-top:1px solid var(--line)}
.first-run-list li:last-child{border-bottom:1px solid var(--line)}
.first-run-list strong{font-size:0.92rem;color:var(--ink)}
.first-run-list span{font-size:0.86rem;color:var(--ink-soft);line-height:1.45}
.first-run-actions{display:flex;flex-wrap:wrap;gap:0.7rem;align-items:center}
.first-run-cta{display:inline-flex;align-items:center;font-size:0.9rem;font-weight:600;text-decoration:none;padding:0.6rem 1.1rem;border-radius:8px;background:var(--accent);color:var(--on-accent);border:1px solid var(--accent)}
.first-run-cta:hover{filter:brightness(1.08)}
/* Secondary sits at equal weight typographically but without the fill - it's
   a real alternative path, not a dismissal, so it shouldn't read as a
   throwaway link. */
.first-run-cta.secondary{background:transparent;color:var(--accent);border-color:var(--line)}
.first-run-cta.secondary:hover{border-color:var(--accent);filter:none}
@media(max-width:560px){
  .first-run-list li{grid-template-columns:1fr;gap:0.15rem}
  .first-run-actions{flex-direction:column;align-items:stretch}
  .first-run-cta{justify-content:center}
}

/* Data warning. Shown only when the app is running on generated figures
   rather than real market data (see loadDataStatus in app.js) - it replaced a
   permanent green "live data" pill, which used --buy, the same token as a
   price gain. Styled as a real alert rather than a badge: if this is ever on
   screen, nothing else on the page can be trusted. */
.data-warning{
  display:none;
  border:1px solid var(--sell);
  border-left:4px solid var(--sell);
  background:var(--sell-bg,rgba(239,68,68,0.10));
  color:var(--ink);
  border-radius:10px;
  padding:0.85rem 1rem;
  margin:0 0 1.25rem;
  font-size:0.92rem;
  line-height:1.5;
}
.data-warning strong{color:var(--sell)}

/* --- Add-holding feedback -------------------------------------------------
   Confirmation sits directly under the form, where the eyes already are, so
   checking an add never means scrolling the holdings table. */
.add-feedback{
  display:none;
  margin:0.7rem 0 0;
  padding:0.6rem 0.8rem;
  border-radius:8px;
  font-size:0.9rem;
  line-height:1.45;
  border:1px solid var(--line);
}
.add-feedback.ok{border-color:var(--buy);background:var(--buy-bg)}
.add-feedback.warn{border-color:var(--hold);background:var(--hold-bg)}
.add-feedback.error{border-color:var(--sell);background:var(--sell-bg)}
.add-feedback code{font-family:var(--num-font);font-size:0.85em}

/* --- "You already hold this" add-or-replace question ----------------------
   Both buttons carry their own resulting numbers, so neither is the safe
   default you can hit blindly - which is the point. Add-to-it is styled as
   the primary because it is the non-destructive one and the far more common
   intent (buying more of something you own); Replace is deliberately plain
   rather than red, because replacing is a legitimate correction, not an
   error. Cancel is quiet text so the two real answers read as the choice. */
.add-choice-head{margin-bottom:0.45rem}
.add-choice-note{
  margin:0 0 0.5rem;font-size:0.84rem;color:var(--ink-soft);line-height:1.5;
}
.add-choice-actions{display:flex;flex-wrap:wrap;gap:0.5rem;align-items:center}
.add-choice-actions button{
  font-family:inherit;font-size:0.85rem;font-weight:600;
  padding:0.45rem 0.8rem;border-radius:6px;cursor:pointer;
  border:1px solid var(--line);background:var(--card);color:var(--ink);
}
.add-choice-actions button:first-child{
  background:var(--accent);border-color:var(--accent);color:var(--on-accent);
}
.add-choice-actions button:hover{border-color:var(--accent)}
.add-choice-actions button:focus-visible{
  outline:none;box-shadow:0 0 0 3px var(--accent-ring);
}
.add-choice-actions .add-choice-cancel{
  background:transparent;border-color:transparent;color:var(--ink-soft);
  font-weight:500;padding-left:0.4rem;padding-right:0.4rem;
}
.add-choice-actions .add-choice-cancel:hover{color:var(--ink)}

/* --- Named watchlists -----------------------------------------------------
   Same pill language as the Add Portfolio tabs above, deliberately: both are
   "pick which of these you're working in". The count sits inside the tab
   because "Energy 7" answers the question people actually have about a tab
   they aren't looking at. Rename/Delete apply to the OPEN tab rather than
   appearing on every one - a dozen lists each carrying two icons is a worse
   thing to look at than two buttons whose target is unambiguous. */
.watchlist-tabs{display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin:0 0 0.8rem}
.watchlist-tab{
  font-family:inherit;font-size:0.85rem;font-weight:600;
  padding:0.45rem 0.8rem;border-radius:20px;cursor:pointer;
  border:1px solid var(--line);background:transparent;color:var(--ink-soft);
  display:inline-flex;align-items:center;gap:0.4rem;
}
.watchlist-tab:hover{color:var(--ink);background:var(--card)}
.watchlist-tab.active{background:var(--accent);border-color:var(--accent);color:var(--on-accent)}
.watchlist-tab-count{
  font-family:var(--num-font);font-size:0.72rem;font-weight:700;
  opacity:0.75;font-variant-numeric:tabular-nums;
}
.watchlist-tab-new{
  font-family:inherit;font-size:0.82rem;font-weight:600;
  padding:0.45rem 0.7rem;border-radius:20px;cursor:pointer;
  border:1px dashed var(--line);background:transparent;color:var(--ink-soft);
}
.watchlist-tab-new:hover{color:var(--accent);border-color:var(--accent)}
.watchlist-tab-actions{display:inline-flex;align-items:center;gap:0.25rem;margin-left:auto}
.watchlist-tab-actions button{
  font-family:inherit;font-size:0.78rem;font-weight:500;
  padding:0.3rem 0.5rem;border-radius:6px;cursor:pointer;
  border:1px solid transparent;background:transparent;color:var(--ink-soft);
}
.watchlist-tab-actions button:hover{color:var(--ink);border-color:var(--line)}
.watchlist-default-note{
  font-size:0.7rem;text-transform:uppercase;letter-spacing:0.05em;
  color:var(--ink-soft);padding:0.3rem 0.5rem;
}
.watchlist-name-input{
  font-family:inherit;font-size:0.9rem;padding:0.45rem 0.6rem;
  border:1px solid var(--line);border-radius:6px;
  background:var(--paper);color:var(--ink);min-width:min(260px,100%);
}
.watchlist-name-input:focus-visible{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-ring)}

/* One chip per list a stock is in. Clickable, because "also in Dividends" is
   usually followed by wanting to see Dividends. */
.watchlist-chips{max-width:280px}
.watchlist-chip{
  font-family:inherit;font-size:0.72rem;font-weight:600;
  padding:0.15rem 0.5rem;margin:0.1rem 0.25rem 0.1rem 0;border-radius:20px;
  border:1px solid var(--line);background:var(--pill-bg);color:var(--ink-soft);
  cursor:pointer;
}
.watchlist-chip:hover{color:var(--ink);border-color:var(--accent)}
.watchlist-chip.current{color:var(--accent);border-color:var(--accent)}
@media (max-width: 720px){
  /* The tab row is the one thing that must stay usable at phone width; the
     per-row chips are the first thing to go, since the tab you're on already
     tells you the main fact. */
  .watchlist-chips{display:none}
  #watchlistList .holdings-table th.watchlist-lists-col{display:none}
  .watchlist-tab-actions{margin-left:0;width:100%}
}

/* --- "That average price looks wrong" -------------------------------------
   Amber, not red: this is a thing to look at, not a failure. It sits above
   the table because the gain column it invalidates is on the right-hand edge
   and easy to skim past, and each line carries BOTH numbers - the cost basis
   and the share price - because the two side by side are the entire argument
   for the warning. */
.cost-basis-warning{
  margin:0 0 0.9rem;padding:0.7rem 0.9rem;border-radius:8px;
  border:1px solid var(--hold);background:var(--hold-bg);
  font-size:0.88rem;line-height:1.5;
}
/* The currency query: a question, not a verdict, so it keeps the shape and
   drops the alarm. The figures under it are often correct - see case 3 in
   suspectAvgCost - and amber on a right answer is how people learn to ignore
   amber. */
.cost-basis-query{
  border-color:var(--line);background:transparent;
}
.cost-basis-warning ul{list-style:none;margin:0.6rem 0 0;padding:0;display:flex;flex-direction:column;gap:0.5rem}
.cost-basis-warning li{
  display:flex;flex-wrap:wrap;align-items:center;gap:0.5rem 0.75rem;
  justify-content:space-between;
}
.cost-warn-line{flex:1 1 320px;min-width:0}
.cost-warn-actions{display:flex;gap:0.4rem;align-items:center;flex-shrink:0}
.cost-warn-actions button{
  font-family:inherit;font-size:0.82rem;font-weight:600;
  padding:0.35rem 0.7rem;border-radius:6px;cursor:pointer;
  border:1px solid var(--accent);background:var(--accent);color:var(--on-accent);
}
.cost-warn-actions button:focus-visible{outline:none;box-shadow:0 0 0 3px var(--accent-ring)}
.cost-warn-actions .add-choice-cancel{
  background:transparent;border-color:transparent;color:var(--ink-soft);font-weight:500;
}
.cost-warn-actions .add-choice-cancel:hover{color:var(--ink)}
/* the cell you'd actually fix, so the banner and the row agree */
.holdings-table input.cell-edit.suspect{
  border-color:var(--hold);background:var(--hold-bg);
}
/* the queried-not-wrong version: marks the cell without colouring it */
.holdings-table input.cell-edit.queried,
.holdings-table .cell-total.queried{
  border-bottom:1px dashed var(--ink-soft);
}
.gain-unchecked{
  font-size:0.8rem;color:var(--hold);font-family:inherit;white-space:nowrap;
}

.recent-adds{margin:0.7rem 0 0}
.recent-adds-label{
  display:block;font-size:0.72rem;font-weight:700;text-transform:uppercase;
  letter-spacing:0.05em;color:var(--ink-soft);margin-bottom:0.35rem;
}
.recent-adds ul{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:0.25rem}
.recent-adds li{
  display:flex;align-items:baseline;gap:0.5rem;flex-wrap:wrap;
  font-size:0.86rem;color:var(--ink-soft);
  padding:0.25rem 0.5rem;border-radius:6px;background:var(--pill-bg);
}
.recent-adds li strong{font-family:var(--num-font);color:var(--ink)}
.recent-adds li.unknown{border-left:3px solid var(--hold)}
.recent-add-name{flex:1 1 auto;min-width:0}
.recent-add-qty{font-variant-numeric:tabular-nums}

/* --- Sticky holdings table header ----------------------------------------
   Qty and Avg price are adjacent editable cells, so knowing which column is
   which matters while scrolling a long list. 27px, measured - it costs
   essentially nothing.

   top is overridden in the desktop block below; 0 is the fallback for the
   watchlist table and any narrow-width case where nothing else is pinned. */
.holdings-table thead th{
  position:sticky; top:0; z-index:2;
  background:var(--card);
  box-shadow:inset 0 -1px 0 var(--line);
}

/* --- Pinned add row + column headers, DESKTOP ONLY ------------------------
   Measured rather than guessed, on portfolio.html:

     desktop 1280x900 : header 117px + form row  40px = 157px -> 17% of screen
     phone    390x844 : header 213px + form row 188px = 401px -> 48% of screen

   17% is a clear win. 48% is half the screen gone before a single holding is
   visible, because the form stacks vertically at phone width and the site
   header is already 213px. So this applies only above the breakpoint.

   The hint box is deliberately NOT pinned - it is 106px on desktop and 232px
   on mobile, larger than the form itself, and it is reference material you
   read once rather than something you need in view.

   Both offsets come from --sticky-top / --holdings-head-top, which app.js
   MEASURES on load, on resize and whenever the row's own height changes
   (syncStickyOffsets). They are not constants because neither number is one:
   .site-header is position:sticky only above 1300px - a max-width:1300px
   media query switches it to relative - so the correct offset here is the
   header's height on a wide screen and exactly 0 between 900px and 1300px.
   A hardcoded 125px would have left a 125px dead gap across that whole
   range, and the add row's own height changes the moment a confirmation or
   an error message appears inside it. */
@media (min-width: 900px){
  #manualAddArea{
    position:sticky;
    top:var(--sticky-top, 0px);
    z-index:3;
    background:var(--card);
    padding:0.5rem 0;
    margin:0;
    box-shadow:0 1px 0 var(--line);
  }

  /* .table-scroll exists to let a wide table scroll sideways on a narrow
     screen. But a computed overflow-x of auto forces overflow-y to auto as
     well, and that makes the div a scroll container - and a sticky element
     sticks to its nearest scrolling ancestor, not the page. So thead was
     faithfully sticking to a box that never scrolls, and slid away with the
     page exactly as if it were static (measured on a 35-row list at
     1280x900: thead top -261px at scrollY 900, i.e. gone). At >=900px the
     holdings table has the width it needs, so release the container and let
     the page do the scrolling. Scoped to #holdingsList so the factor,
     regime and watchlist tables keep their sideways scroll.
     6 Oct 2026: "has the width it needs" was true at 900px before the Bought
     date, the home-currency gain column and the review-point button joined
     the row; at ~950px the table now runs past the panel's right edge and
     the review-point box (a colspan row, so as wide as the table) with it.
     Below 1100px the container keeps its sideways scroll - the pinned header
     is given up there, an edge that stays inside the panel is not.
     7 Oct 2026: a window width is the wrong test - Sam's ~1120px window still
     ran the table past the panel, because the panel's width depends on the
     layout around it, not the window. Now app.js (fitHoldingsTable) measures
     the table against its container after every render and on resize: it
     scrolls sideways by default and is released (.fits) only when it really
     fits, so the pinned header is kept exactly when it costs nothing. */
  #holdingsList .table-scroll{ overflow-x: auto; }
  #holdingsList .table-scroll.fits{ overflow: visible; }
  /* Inside a sideways-scrolling box a pinned header sticks to the box, not
     the page, and lands on top of the second row (Sam's screenshot, 7 Oct).
     So it is pinned only when the table fits. */
  #holdingsList .table-scroll:not(.fits) .holdings-table thead th{ position: static; }
  /* And the open lots / review-point boxes - rows as wide as the table - are
     held to the visible width and pinned to its left edge while it scrolls. */
  #holdingsList .table-scroll:not(.fits) .review-point-row .review-point-box,
  #holdingsList .table-scroll:not(.fits) .lots-row .lots-box{
    position: sticky; left: 0; box-sizing: border-box;
    max-width: calc(var(--holdings-visible-w, 100%) - 1.2rem);
  }
  #holdingsList .holdings-table thead th{
    top: var(--holdings-head-top, 0px);
    /* a little more room than the 0.35rem the non-pinned tables use: rows
       now slide directly under these cells, and at the default padding the
       label and the row text underneath it nearly touch */
    padding-top: 0.5rem;
    padding-bottom: 0.5rem;
  }
}

/* The rule grid (app.rule_grid on the backend, loadRuleGrid()/copyRuleGrid()
   in app.js). On screen the squares use the same colour the pasted emoji
   will have - green / amber / red / blank - so what someone sees is what they
   copy. Amber rather than the in-app grey for HOLD, because the emoji
   vocabulary (green/yellow/red/white squares) is fixed by what exists in
   Unicode, and the screen should match the paste. */
.rule-grid{
  margin-top:1rem;padding:0.85rem 1rem;background:var(--card);
  border:1px solid var(--line);border-radius:6px;
}
.rule-grid-head{display:flex;align-items:center;justify-content:space-between;gap:0.6rem;flex-wrap:wrap;margin-bottom:0.6rem}
.rule-grid-title{font-weight:650;font-size:0.95rem;color:var(--ink)}
.rule-grid-copy{padding:0.4rem 0.8rem;font-size:0.85rem}
.rule-grid-copy.copied{border-color:var(--buy);color:var(--buy)}
.rule-grid-body{display:flex;gap:1rem;align-items:flex-start;flex-wrap:wrap}
.rule-grid-squares{display:flex;flex-wrap:wrap;gap:5px;max-width:calc(10 * 26px + 9 * 5px);flex:1 1 320px}
.rule-grid-squares:has(.tile){max-width:none}
.rule-grid-sq{
  width:26px;height:26px;border-radius:4px;display:inline-block;
  border:1px solid transparent;
}
.rule-grid-sq.positive{background:#22C55E}
.rule-grid-sq.mixed{background:#EAB308}
.rule-grid-sq.negative{background:#EF4444}
.rule-grid-sq.no_data{background:transparent;border-color:var(--line)}
.rule-grid-note{margin:0.6rem 0 0;font-size:0.875rem}
.rule-grid-stamp{color:var(--ink-soft);font-size:0.8rem;font-weight:400;margin-left:0.4rem}

/* Trust pages (methodology / about / changelog / privacy / terms) and the
   site footer that links to them from every page. The pages reuse the Learn
   page's .learn-entry disclosure widget so a rule reads like a glossary
   entry; these classes only cover what Learn didn't need. */
.method-list{margin:0.4rem 0 0.9rem 1.2rem;padding:0;font-size:0.9rem;line-height:1.65;color:var(--ink-soft)}
.method-list li{margin-bottom:0.45rem}
.method-list strong,.method-prose strong{color:var(--ink)}
.method-prose{font-size:0.92rem;line-height:1.7;color:var(--ink-soft);margin:0 0 0.9rem}
.method-date{font-size:0.78rem;font-weight:700;text-transform:uppercase;letter-spacing:0.05em;color:var(--ink-soft);margin:1.4rem 0 0.4rem}
.method-date:first-of-type{margin-top:0.4rem}
.site-footer{margin-top:2.5rem;padding-top:1.2rem;border-top:1px solid var(--line);font-size:0.82rem;color:var(--ink-soft)}
.site-footer nav{display:flex;flex-wrap:wrap;gap:0.4rem 1.1rem;margin-bottom:0.5rem}
.site-footer nav a{color:var(--ink-soft);text-decoration:none}
.site-footer nav a:hover{color:var(--ink);text-decoration:underline}
.site-footer p{margin:0}
/* The operating entity, on every page. Registered 22 Sep 2026; before that the
   site could not name one, and the terms said "Trendentum and its operator".
   Quieter than the disclaimer above it - it is an identification, not a claim. */
.site-footer .footer-entity{margin:0.35rem 0 0;font-size:0.76rem;color:var(--ink-soft);opacity:0.8}
/* Inline links inside reference prose were falling back to the browser's
   default blue - unreadable on the dark theme (seen in the methodology page
   screenshot). */
.learn-panel-intro a,.method-prose a,.method-list a,.learn-entry p a,.footnote a,.empty a{color:var(--accent);text-decoration:underline;text-underline-offset:2px}

/* Shared watchlists: the "Shared · link" chip on the tab bar, and the public
   watchlist.html page (initPublicWatchlistPage in app.js). Rows reuse the rule
   grid's square so an outlook reads the same everywhere. */
.watchlist-tab-actions button.watchlist-share-on{color:var(--buy);border-color:var(--buy)}
/* The link mark a shared list carries on its own tab, visible from any tab. */
.watchlist-tab-shared{display:inline-flex;align-items:center;opacity:0.85}
.watchlist-tab.active .watchlist-tab-shared{opacity:1}

/* The share sheet: a small dialog over the page with the channels a link
   usually goes to. Same card/line/accent tokens as everything else so it reads
   as part of the app in both themes; the backdrop is a translucent ink so the
   page underneath is still recognisable. */
.share-sheet-backdrop{
  position:fixed;inset:0;z-index:60;display:flex;align-items:center;justify-content:center;
  padding:16px;background:rgba(2,6,23,0.55);
}
.share-sheet{
  width:min(100%,460px);max-height:calc(100vh - 32px);overflow:auto;
  background:var(--card);color:var(--ink);border:1px solid var(--line);border-radius:12px;
  padding:1rem 1.1rem 1.1rem;box-shadow:0 24px 60px rgba(0,0,0,0.35);
  display:flex;flex-direction:column;gap:0.8rem;
}
.share-sheet-head{display:flex;align-items:center;justify-content:space-between;gap:0.6rem}
.share-sheet-head h3{margin:0;font-size:1.05rem;text-wrap:balance}
.share-sheet-close{
  font-family:inherit;font-size:1.4rem;line-height:1;padding:0.1rem 0.45rem;border-radius:6px;cursor:pointer;
  border:1px solid transparent;background:transparent;color:var(--ink-soft);
}
.share-sheet-close:hover{color:var(--ink);border-color:var(--line)}
.share-sheet-note{margin:0}
.share-sheet-channels{display:grid;grid-template-columns:repeat(auto-fill,minmax(96px,1fr));gap:0.5rem}
.share-sheet-btn{
  font-family:inherit;font-size:0.82rem;font-weight:600;text-decoration:none;cursor:pointer;
  display:flex;flex-direction:column;align-items:center;gap:0.35rem;padding:0.7rem 0.4rem;
  border:1px solid var(--line);border-radius:8px;background:var(--paper);color:var(--ink);
}
.share-sheet-btn:hover{border-color:var(--accent);color:var(--accent)}
.share-sheet-btn:focus-visible,.share-sheet-close:focus-visible,.share-sheet-stop:focus-visible{outline:none;box-shadow:0 0 0 3px var(--accent-ring)}
.share-sheet-link{display:flex;gap:0.5rem;align-items:center;flex-wrap:wrap}
.share-sheet-link .watchlist-name-input{flex:1 1 220px;min-width:0;font-family:var(--num-font);font-size:0.8rem}
/* Multi-line share text (the rule grid's three lines) sits in a textarea so the
   breaks survive the preview and the no-clipboard-API fallback. Aligned to the
   top of the row and not resizable sideways, so it cannot push the button out. */
.share-sheet-link .share-sheet-text{resize:vertical;line-height:1.5;padding:0.45rem 0.6rem;white-space:pre;overflow-x:auto}
.share-sheet-link:has(.share-sheet-text){align-items:flex-start}
.share-sheet-link button{
  font-family:inherit;font-size:0.85rem;font-weight:600;padding:0.45rem 0.8rem;border-radius:6px;cursor:pointer;
  border:1px solid var(--accent);background:var(--accent);color:var(--on-accent);
}
.share-sheet-foot{display:flex;align-items:center;gap:0.6rem;flex-wrap:wrap;border-top:1px solid var(--line);padding-top:0.7rem}
.share-sheet-foot .footnote{margin:0}
.share-sheet-stop{
  font-family:inherit;font-size:0.8rem;font-weight:600;padding:0.35rem 0.6rem;border-radius:6px;cursor:pointer;
  border:1px solid var(--sell);background:transparent;color:var(--sell);
}
.share-sheet-stop:hover{background:var(--sell-bg)}
/* Share on the stock page: a quiet outlined pill in the header (logged in)
   or a right-aligned row above the public signal card (logged out). */
.stock-header-actions{display:flex;align-items:center;gap:0.8rem;flex-wrap:wrap}
.stock-share-row{display:flex;justify-content:flex-end;margin:0 0 0.6rem}
.stock-share-btn{
  font-family:inherit;font-size:0.82rem;font-weight:600;cursor:pointer;
  display:inline-flex;align-items:center;gap:0.35rem;padding:0.35rem 0.75rem;border-radius:20px;
  border:1px solid var(--line);background:transparent;color:var(--ink-soft);
}
.stock-share-btn:hover{color:var(--accent);border-color:var(--accent)}
.stock-share-btn:focus-visible{outline:none;box-shadow:0 0 0 3px var(--accent-ring)}
/* Since your last visit (dashboard). One row per symbol that moved: the
   square then and now, the ticker, one or two plain lines. Same badge and
   square vocabulary as everywhere else, so a flip reads the same here as on
   the card it came from. */
.chg-summary{margin:0 0 0.8rem;font-size:0.95rem}
.chg-summary strong{font-variant-numeric:tabular-nums}
.chg-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:0.5rem}
.chg-item{display:flex;align-items:flex-start;gap:0.7rem;padding:0.55rem 0.7rem;border:1px solid var(--line);border-radius:8px;background:var(--card)}
.chg-squares{display:inline-flex;align-items:center;gap:0.3rem;flex-shrink:0;padding-top:0.15rem}
.chg-sq.rule-grid-sq{width:18px;height:18px}
.chg-arrow{color:var(--ink-soft);font-size:0.85rem}
.chg-body{display:flex;flex-direction:column;gap:0.25rem;min-width:0}
.chg-head{display:flex;align-items:center;gap:0.5rem;flex-wrap:wrap}
.chg-symbol{font-family:var(--num-font);font-weight:700;color:var(--ink);text-decoration:none}
.chg-symbol:hover{color:var(--accent)}
.chg-company{color:var(--ink-soft);font-size:0.85rem}
.chg-tag{font-size:0.68rem;text-transform:uppercase;letter-spacing:0.06em;padding:0.1rem 0.45rem;border-radius:20px;border:1px solid var(--line);color:var(--ink-soft)}
.chg-flipped .chg-tag{color:var(--accent);border-color:var(--accent)}
.chg-lost_data .chg-tag{color:var(--hold);border-color:var(--hold)}
.chg-line{font-size:0.88rem;line-height:1.45;color:var(--ink)}
.chg-line .action-badge{font-size:0.72rem;padding:0.1rem 0.45rem}
.chg-price.up{color:var(--buy)}
.chg-price.down{color:var(--sell)}
@media (max-width:600px){.chg-item{flex-direction:column;gap:0.35rem}}

/* Weekly digest: the control line under Since-your-last-visit, and the
   preview dialog (the exact text that will send, in a monospace block). */
.digest-line{margin:0.8rem 0 0;padding-top:0.6rem;border-top:1px solid var(--line)}
.trial-panel{padding:0.7rem 1rem;border-left:4px solid #33d0a6}
.verify-panel{padding:0.7rem 1rem;border-left:4px solid #e8b34a}
.verify-panel.verify-ok{border-left-color:#33d0a6}
.tf-qr{display:inline-block;padding:.5rem;background:#fff;border-radius:8px}
.tf-qr svg{width:180px;height:180px;display:block}
.tf-secret{font-family:var(--num-font);letter-spacing:.06em;word-break:break-all}
.tf-codes{font-family:var(--num-font);font-size:1rem;line-height:1.7;padding:.7rem 1rem;border:1px solid var(--line);border-radius:8px;background:var(--card);max-width:22rem}
.digest-line.alerts-line{margin-top:0.4rem;padding-top:0;border-top:0}
.digest-line .learn-link{font-size:inherit}
.push-note{color:var(--ink-soft)}
.pro-lock{margin:0.4rem 0;padding:0.55rem 0.8rem;border:1px solid var(--line);border-left:3px solid #33d0a6;border-radius:6px;font-size:0.9rem;color:var(--ink-soft)}
.pro-link{color:#33d0a6;font-weight:600}
.pro-tiers{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:1rem;margin:1rem 0}
.pro-tier{border:1px solid var(--line);border-radius:10px;padding:1rem 1.2rem}
.pro-tier.pro-tier--pro{border-color:#33d0a6}
.pro-tier h3{margin:0 0 0.2rem}
.pro-tier .pro-price{font-size:1.4rem;font-weight:700;margin:0.2rem 0 0.6rem}
.pro-tier ul{margin:0.4rem 0 0 1.1rem;padding:0}
.pro-tier li{margin:0.25rem 0}
.pro-status{margin:0.8rem 0;padding:0.6rem 0.8rem;border:1px solid var(--line);border-radius:6px}
.pro-ladder{margin:1rem 0 1.2rem;padding:1rem 1.2rem;border:1px solid var(--line);border-radius:10px}
.pro-pack{margin:1.2rem 0 0;padding:0.9rem 1.2rem;border:1px dashed var(--line);border-radius:10px}
/* quiet.html - the "not looking" landing page */
.quiet-eyebrow{margin:0 0 0.3rem;font-size:0.78rem;font-weight:700;letter-spacing:0.08em;text-transform:uppercase;color:var(--ink-soft)}
#quietPanel h2{font-size:1.7rem;line-height:1.2;text-wrap:balance;max-width:34ch}
.quiet-h3{margin:1.6rem 0 0.4rem}
.quiet-lines{display:grid;gap:0.6rem}
.quiet-line{display:grid;grid-template-columns:9.5rem minmax(0,1fr);gap:0.3rem 1rem;align-items:baseline;padding:0.7rem 0.9rem;border:1px solid var(--line);border-left-width:4px;border-radius:8px;background:var(--card)}
.quiet-line--calm{border-left-color:var(--line)}
.quiet-line--flip{border-left-color:#e2b04a}
.quiet-line--digest{border-left-color:#33d0a6}
.quiet-when{font-size:0.78rem;font-weight:700;letter-spacing:0.05em;text-transform:uppercase;color:var(--ink-soft)}
.quiet-text{font-size:1.02rem}
.quiet-points{line-height:1.6;padding-left:1.2rem}
.quiet-points li{margin:0.35rem 0}
.quiet-cost{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0.8rem}
.quiet-cost-col{padding:0.95rem 1.05rem;border:1px solid var(--line);border-radius:8px;background:var(--card)}
.quiet-cost-col h4{margin:0 0 0.4rem}
.quiet-cost-col p{margin:0.3rem 0;line-height:1.55}
.quiet-cost-col--pro{border-color:#33d0a6}
.quiet-cta{display:flex;flex-wrap:wrap;gap:0.8rem 1.2rem;align-items:center;margin-top:1.4rem}
.btn-like{display:inline-block;font-size:0.95rem;padding:0.6rem 1.1rem;border-radius:4px;border:1px solid var(--accent);background:var(--accent);color:var(--on-accent);font-weight:600;text-decoration:none}
.btn-like:hover{opacity:0.9}
@media(max-width:700px){.quiet-line{grid-template-columns:1fr}.quiet-cost{grid-template-columns:1fr}#quietPanel h2{font-size:1.4rem}}
.research-credits{margin:0.4rem 0 0;opacity:0.8}
.pro-step{padding:0.6rem 0;border-top:1px solid var(--line);display:grid;grid-template-columns:minmax(0,1fr) auto;gap:0.2rem 1rem;align-items:center}
.pro-step:first-child{border-top:0}
.pro-step-head{display:flex;flex-wrap:wrap;gap:0.4rem;align-items:baseline}
.pro-step-who{opacity:0.8}
.pro-step-state{font-size:0.8rem;letter-spacing:0.02em;text-transform:uppercase;opacity:0.65;margin-left:auto}
.pro-step--current .pro-step-state{color:#33d0a6;opacity:1}
.pro-step--closed{opacity:0.6}
.pro-step-price{font-weight:700;font-size:1.1rem;font-variant-numeric:tabular-nums;grid-column:2;grid-row:1}
.pro-bar{grid-column:1;height:8px;border-radius:4px;background:var(--line);overflow:hidden}
.pro-bar span{display:block;height:100%;background:#33d0a6;border-radius:4px;transition:width .4s}
.pro-step--closed .pro-bar span{background:#7d8a97}
.pro-bar-count{grid-column:2;font-size:0.85rem;opacity:0.8;font-variant-numeric:tabular-nums;text-align:right}
.link-button{background:none;border:0;padding:0;color:#33d0a6;font:inherit;font-weight:600;cursor:pointer;text-decoration:underline}
@media (max-width:480px){.pro-step{grid-template-columns:1fr}.pro-step-price,.pro-bar,.pro-bar-count{grid-column:1;text-align:left}}
.share-sheet.digest-preview{width:min(100%,640px)}
.digest-subject{font-weight:600;font-size:0.95rem}
.digest-subject .so-label{display:block}
.digest-body{margin:0;padding:0.8rem;border:1px solid var(--line);border-radius:8px;background:var(--paper);
  font-family:var(--num-font);font-size:0.8rem;line-height:1.5;white-space:pre-wrap;word-break:break-word;max-height:60vh;overflow:auto}

/* Company snapshot (stock page): five facts in a strip, the 52-week range
   as a bar with today on it, and the earnings line above everything when a
   results day is close. Facts, not a score - no colour beyond the caution. */
.snapshot-panel h2{margin:0}
.snap-head{display:flex;align-items:baseline;justify-content:space-between;gap:0.6rem;flex-wrap:wrap;margin-bottom:0.7rem}
.snap-head .footnote{margin:0}
.snap-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:0.6rem;margin-bottom:0.8rem}
.snap-cell{display:flex;flex-direction:column;gap:0.15rem;padding:0.55rem 0.7rem;border:1px solid var(--line);border-radius:8px;background:var(--paper)}
.snap-label{font-size:0.7rem;text-transform:uppercase;letter-spacing:0.06em;color:var(--ink-soft)}
.snap-value{font-family:var(--num-font);font-size:1.05rem;font-weight:600;font-variant-numeric:tabular-nums;color:var(--ink)}
.snap-value.snap-muted{font-family:inherit;font-size:0.85rem;font-weight:500;color:var(--ink-soft)}
.snap-range{display:flex;flex-direction:column;gap:0.35rem}
.snap-range-bar{position:relative;height:8px;border-radius:4px;background:linear-gradient(90deg,var(--sell-bg),var(--hold-bg),var(--buy-bg));border:1px solid var(--line)}
.snap-range-dot{position:absolute;top:50%;width:14px;height:14px;border-radius:50%;background:var(--accent);border:2px solid var(--card);transform:translate(-50%,-50%);box-shadow:0 0 0 1px var(--accent)}
.snap-range-ends{display:flex;justify-content:space-between;gap:0.6rem;font-family:var(--num-font);font-size:0.8rem;color:var(--ink-soft);font-variant-numeric:tabular-nums}
.snap-range-now{font-family:inherit;color:var(--ink)}
.snap-earnings{font-size:0.9rem;margin-bottom:0.8rem}
.snap-earnings.soon{padding:0.6rem 0.8rem;border:1px solid var(--hold);background:var(--hold-bg);border-radius:8px;line-height:1.45}

/* The market backdrop (Market Conditions panel): one row per series, a
   state chip, the reading, and the rules sentence behind a toggle. Chip
   colours are directional (buy/sell/hold tokens), never the accent. */
.macro{margin:0 0 1rem;padding:0.7rem 0.8rem;border:1px solid var(--line);border-radius:8px;background:var(--paper)}
.macro-head{display:flex;align-items:baseline;justify-content:space-between;gap:0.6rem;flex-wrap:wrap;margin-bottom:0.4rem}
.macro-title{font-weight:600;font-size:0.95rem}
.macro-row{border-top:1px solid var(--line);padding:0.35rem 0}
.macro-row:first-of-type{border-top:0}
.macro-row summary{display:flex;align-items:center;gap:0.6rem;cursor:pointer;list-style:none;font-size:0.9rem}
.macro-row summary::-webkit-details-marker{display:none}
.macro-row summary::after{content:'\25B8';margin-left:auto;color:var(--ink-soft);font-size:0.8rem}
.macro-row[open] summary::after{content:'\25BE'}
.macro-chip{flex-shrink:0;font-size:0.68rem;font-weight:700;text-transform:uppercase;letter-spacing:0.05em;padding:0.15rem 0.5rem;border-radius:20px;min-width:7.5rem;text-align:center}
.macro-chip.up{color:var(--buy);background:var(--buy-bg)}
.macro-chip.down{color:var(--sell);background:var(--sell-bg)}
.macro-chip.flat{color:var(--hold);background:var(--hold-bg)}
.macro-chip.warn{color:var(--hold);background:var(--hold-bg)}
.macro-chip.na{color:var(--ink-soft);border:1px solid var(--line)}
.macro-reading{color:var(--ink)}
.macro-rules{margin:0.4rem 0 0.2rem;padding-left:calc(7.5rem + 1.6rem);font-size:0.85rem;line-height:1.45;color:var(--ink-soft)}
.macro-foot{margin:0.5rem 0 0}
@media (max-width:640px){.macro-rules{padding-left:0}.macro-chip{min-width:0}}

/* Bought date cell + tax notes (Holdings page). */
.holdings-table .date-cell{white-space:nowrap}
.holdings-table input.cell-edit.cell-date{font-family:inherit;font-size:0.8rem;width:8rem;max-width:8rem;min-width:8rem;padding:0.15rem 0.25rem;color-scheme:dark;text-align:left}
:root[data-theme="light"] .cell-edit.cell-date{color-scheme:light}
.au-notes{margin:1rem 0 0;padding:0.7rem 0.85rem;border:1px solid var(--line);border-radius:8px;background:var(--paper)}
.au-head{display:flex;align-items:baseline;justify-content:space-between;gap:0.6rem;flex-wrap:wrap;margin-bottom:0.5rem}
.au-title{font-weight:600;font-size:0.95rem}
.au-approaching{padding:0.55rem 0.7rem;border:1px solid var(--hold);background:var(--hold-bg);border-radius:8px;margin-bottom:0.6rem}
.au-list{margin:0;padding-left:1.1rem;display:flex;flex-direction:column;gap:0.3rem;font-size:0.88rem;line-height:1.45}
.au-tally{margin:0 0 0.4rem;font-size:0.9rem}
.au-tally strong{font-variant-numeric:tabular-nums}
.au-franking,.au-disclaimer,.au-date-help{margin:0.3rem 0 0}
.au-date-help{color:var(--ink)}
.tax-pick{display:flex;flex-wrap:wrap;align-items:center;gap:0.35rem;margin-top:0.6rem}
.tax-pick-label{font-size:0.8rem;color:var(--ink-soft);margin-right:0.2rem}
.tax-chip{font:inherit;font-size:0.8rem;padding:0.2rem 0.6rem;border:1px solid var(--line);border-radius:999px;background:transparent;color:var(--ink);cursor:pointer}
.tax-chip:hover{border-color:var(--ink-soft)}
.tax-chip.on{border-color:var(--accent);background:var(--accent);color:var(--paper);font-weight:600}
.tax-chip:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
/* The Bought date on the add row carries its own label: a bare date box
   read as "today" or "the date I add it". */
.date-field{display:inline-flex;flex-direction:column;gap:0.15rem}
.date-field-label{font-size:0.72rem;color:var(--ink-soft);letter-spacing:0.02em;text-transform:uppercase}
.date-field-label .opt{text-transform:none;letter-spacing:0}
.date-field input[type=date]{color-scheme:dark}
:root[data-theme="light"] .date-field input[type=date]{color-scheme:light}

/* The second-opinion screen after a paste/import. Reuses the sheet chrome;
   wider, because it carries a grid and a list rather than six buttons. */
.share-sheet.second-opinion{width:min(100%,560px)}
.so-lede{margin:0;font-size:0.98rem;line-height:1.45}
.so-lede.so-warn{padding:0.5rem 0.7rem;border:1px solid var(--hold);background:var(--hold-bg);border-radius:8px;font-size:0.9rem}
.so-reading{display:flex;align-items:center;gap:0.6rem;color:var(--ink-soft);font-size:0.9rem;padding:0.4rem 0 0.8rem}
.so-spinner{width:16px;height:16px;border-radius:50%;border:2px solid var(--line);border-top-color:var(--accent);animation:so-spin 0.9s linear infinite;flex-shrink:0}
@keyframes so-spin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion: reduce){.so-spinner{animation:none}}
.so-grid{display:flex;flex-direction:column;gap:0.45rem;padding:0.6rem 0.75rem;border:1px solid var(--line);border-radius:8px;background:var(--paper)}
.so-squares.rule-grid-squares{max-width:none;gap:6px}
.so-squares .rule-grid-sq{width:30px;height:30px}
.so-tally{margin:0;font-size:0.9rem;color:var(--ink-soft)}
.so-tally strong{color:var(--ink);font-variant-numeric:tabular-nums}
.so-foot{margin:0}
.so-label{font-size:0.7rem;text-transform:uppercase;letter-spacing:0.06em;color:var(--ink-soft);margin-bottom:0.3rem}
.so-health .so-headline{margin:0 0 0.3rem}
.so-list{margin:0 0 0.4rem;padding-left:1.1rem;display:flex;flex-direction:column;gap:0.35rem;font-size:0.9rem;line-height:1.4}
.so-fixes.so-ok .so-okline{margin:0;font-size:0.92rem;color:var(--buy)}
.so-skipped summary{cursor:pointer;font-size:0.85rem;color:var(--ink-soft)}
.so-actions{justify-content:flex-start}
.so-actions #soCopyGridBtn{
  font-family:inherit;font-size:0.85rem;font-weight:600;padding:0.45rem 0.8rem;border-radius:6px;cursor:pointer;
  border:1px solid var(--accent);background:var(--accent);color:var(--on-accent);
}
.so-actions .add-choice-cancel{
  font-family:inherit;font-size:0.85rem;padding:0.45rem 0.8rem;border-radius:6px;cursor:pointer;
  border:1px solid var(--line);background:transparent;color:var(--ink-soft);
}
.so-actions .add-choice-cancel:hover{color:var(--ink)}
.so-link{font-size:0.85rem;font-weight:600;color:var(--accent);text-decoration:underline;text-underline-offset:2px}
.watchlist-tab-actions button.watchlist-share-on{display:inline-flex;align-items:center;gap:0.3rem}
@media (prefers-reduced-motion: no-preference){
  .share-sheet{animation:share-sheet-in 140ms ease-out}
  @keyframes share-sheet-in{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
}
.shared-wl-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:0.35rem}
.shared-wl-row{display:flex;align-items:center;gap:0.6rem;flex-wrap:wrap;padding:0.45rem 0.6rem;border:1px solid var(--line);border-radius:6px;background:var(--card);font-size:0.9rem}
.shared-wl-row .rule-grid-sq{width:16px;height:16px;flex-shrink:0}
.shared-wl-symbol{font-family:var(--num-font);font-weight:600;color:var(--ink);text-decoration:none;min-width:5.5rem}
.shared-wl-symbol:hover{text-decoration:underline}
.shared-wl-name{color:var(--ink-soft);flex:1;min-width:8rem}
.shared-wl-outlook{color:var(--ink-soft);font-size:0.82rem}

/* The private backtester (dashboard panel + stock-page section). Counts in
   a small table, misses as a list, caveats folded. */
.bt-lead{margin:0 0 0.7rem;font-size:0.98rem;line-height:1.45}
.bt-table{width:100%;border-collapse:collapse;font-size:0.86rem;margin:0.4rem 0 0.8rem}
.bt-table th,.bt-table td{padding:0.3rem 0.45rem;border-top:1px solid var(--line);text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap}
.bt-table th{font-size:0.7rem;letter-spacing:0.04em;text-transform:uppercase;color:var(--ink-soft);font-weight:600;border-top:0}
.bt-table th:first-child,.bt-table td:first-child{text-align:left;white-space:normal}
/* "Its view" column: the Negative row's cell is that row's first cell (the reading spans both rows), so both are set left explicitly. */
.bt-table .bt-view{text-align:left}
.bt-table td.bt-miss{color:var(--sell,#ef4444)}
.bt-misses{margin:0;padding-left:1.1rem;display:flex;flex-direction:column;gap:0.3rem;font-size:0.88rem;line-height:1.45}
.bt-misses .ticker-link{font-weight:600}
.bt-sub{font-weight:600;font-size:0.9rem;margin:0.8rem 0 0.3rem}
.bt-progress{display:flex;align-items:center;gap:0.6rem;flex-wrap:wrap;margin:0.5rem 0;font-size:0.9rem;color:var(--ink-soft)}
.bt-progress .so-spinner{width:14px;height:14px}
.bt-caveats{margin-top:0.6rem}
.bt-caveats summary{cursor:pointer;font-size:0.82rem;color:var(--ink-soft);list-style:none}
.bt-caveats summary::-webkit-details-marker{display:none}
.bt-caveats summary::before{content:"\25B8  ";font-size:0.75rem}
.bt-caveats[open] summary::before{content:"\25BE  "}
.bt-caveats ul{margin:0.3rem 0 0;padding-left:1.1rem;font-size:0.82rem;color:var(--ink-soft);line-height:1.45}
@media (max-width:640px){.bt-table{display:block;overflow-x:auto}}

/* Parcels: the lots expander under a holding row. */
.holdings-table .cell-total{display:inline-block;padding:0.15rem 0.25rem;font-variant-numeric:tabular-nums}
.holdings-table .cell-total.suspect{color:var(--hold)}
.lots-toggle{font:inherit;font-size:0.8rem;padding:0.15rem 0.5rem;border:1px solid var(--line);border-radius:999px;background:transparent;color:var(--ink);cursor:pointer;white-space:nowrap}
.lots-toggle:hover{border-color:var(--ink-soft)}
.lots-toggle.open{border-color:var(--accent);color:var(--accent)}
.lots-toggle-mini{padding:0.1rem 0.15rem;margin-left:0;border-color:transparent;color:var(--ink-soft)}
.holdings-table .date-cell{white-space:nowrap}
.holdings-table .date-cell input.cell-date{width:7.4rem;max-width:7.4rem;min-width:7.4rem;padding-right:0}
.lots-toggle-mini:hover{border-color:var(--line)}
.lots-caret{display:inline-block;transition:transform 0.15s}
.lots-toggle.open .lots-caret{transform:rotate(180deg)}
@media (prefers-reduced-motion: reduce){.lots-caret{transition:none}}
.holdings-table tr.lots-row>td{padding:0 0 0.6rem;background:transparent}
.lots-box{margin:0.15rem 0 0 0.5rem;padding:0.55rem 0.7rem;border:1px solid var(--line);border-left:3px solid var(--accent);border-radius:8px;background:var(--paper)}
.lots-head{font-size:0.85rem;font-weight:600;margin-bottom:0.35rem}
.lots-head .footnote{font-weight:400}
.lots-table{border-collapse:collapse;font-size:0.85rem}
.lots-table th{font-size:0.68rem;letter-spacing:0.04em;text-transform:uppercase;color:var(--ink-soft);font-weight:600;padding:0.15rem 0.4rem;text-align:left}
.lots-table th.num{text-align:right}
.lots-table td{padding:0.15rem 0.4rem;border-top:1px solid var(--line)}
.lots-table td.num{text-align:right}
.lots-table input.cell-edit{width:6rem;max-width:6rem;min-width:0}
.lots-table input.cell-edit.cell-date{width:8rem;max-width:8rem;min-width:8rem}
.lots-table tr.lot-add td{border-top:1px dashed var(--line)}
.lot-add-btn{font:inherit;font-size:0.78rem;padding:0.2rem 0.55rem;border-radius:6px;border:1px solid var(--accent);background:transparent;color:var(--accent);cursor:pointer;white-space:nowrap}
.lot-add-btn:hover{background:var(--accent);color:var(--paper)}
@media (max-width:640px){.lots-box{margin-left:0}.lots-table{display:block;overflow-x:auto}}

/* "Your own review points" - the per-row toggle and its expander, same shapes as lots above. */
.review-point-toggle{font:inherit;font-size:0.72rem;padding:0.15rem 0.45rem;margin-right:0.35rem;border:1px solid var(--line);border-radius:999px;background:transparent;color:var(--ink-soft);cursor:pointer;white-space:nowrap;font-variant-numeric:tabular-nums}
.review-point-toggle:hover{border-color:var(--ink-soft);color:var(--ink)}
.review-point-toggle.set{border-color:var(--accent);color:var(--accent)}
.review-point-toggle.open{background:var(--accent);color:var(--paper);border-color:var(--accent)}
.holdings-table tr.review-point-row>td{padding:0 0 0.6rem;background:transparent}
.review-point-box{margin:0.15rem 0 0 0.5rem;padding:0.55rem 0.7rem;border:1px solid var(--line);border-left:3px solid var(--accent);border-radius:8px;background:var(--paper)}
.review-point-head{font-size:0.85rem;font-weight:600;margin-bottom:0.35rem}
.review-point-head .footnote{font-weight:400}
.rp-apply-all{font-weight:600}.rp-apply-note{color:var(--ink-soft)}
/* "Close ×" in the corner of an opened review-point / condition box (7 Oct 2026). */
.review-point-box.has-close{position:relative}
.review-point-box.has-close .review-point-head{padding-right:4.8rem}
.rp-close{position:absolute;top:0.4rem;right:0.5rem;border:1px solid var(--line);background:var(--card);color:var(--ink-soft);border-radius:999px;padding:0.1rem 0.6rem;font:inherit;font-size:0.8rem;cursor:pointer}
.rp-close:hover,.rp-close:focus-visible{color:var(--ink);border-color:var(--accent)}
.review-point-fields{display:flex;flex-wrap:wrap;gap:0.5rem 0.9rem;align-items:center;font-size:0.85rem}
.review-point-fields label{display:inline-flex;align-items:center;gap:0.3rem}
.review-point-fields input.cell-edit{text-align:right}
.review-point-fields button{font:inherit;font-size:0.78rem;padding:0.2rem 0.55rem;border-radius:6px;border:1px solid var(--accent);background:transparent;color:var(--accent);cursor:pointer;white-space:nowrap}
.review-point-fields button:hover{background:var(--accent);color:var(--paper)}
.review-point-fields button.add-choice-cancel{border-color:transparent;color:var(--ink-soft)}
.review-point-fields button.add-choice-cancel:hover{background:transparent;color:var(--ink)}
@media (max-width:640px){.review-point-box{margin-left:0}.review-point-fields{flex-direction:column;align-items:flex-start}}

/* Quiet mode: the one-line dashboard. Larger type than a panel - this IS
   the page - and the folded panels are hidden by a body class so a single
   toggle shows everything again for this visit. */
body.quiet-on .panel:not(#quietPanel):not(#authPanel):not(#firstRunPanel){display:none!important}
.quiet-panel{padding:1.3rem 1.4rem}
.quiet-head{display:flex;align-items:baseline;justify-content:space-between;gap:0.8rem;flex-wrap:wrap;margin-bottom:0.6rem}
.quiet-title{font-size:0.72rem;letter-spacing:0.08em;text-transform:uppercase;color:var(--ink-soft);font-weight:600}
.quiet-lead{margin:0;font-size:1.25rem;line-height:1.4;text-wrap:balance}
.quiet-items{list-style:none;margin:0.6rem 0 0;padding:0;display:flex;flex-direction:column;gap:0.55rem}
.quiet-item{display:flex;align-items:flex-start;gap:0.6rem;font-size:1.02rem;line-height:1.45}
.quiet-item .rule-grid-sq{width:14px;height:14px;flex-shrink:0;margin-top:0.35rem}
.quiet-item .ticker-link{font-weight:600}
.quiet-why{font-size:0.85rem;color:var(--ink-soft);margin-left:0.3rem}
.quiet-record{display:block;font-size:0.82rem;color:var(--ink-soft);margin-top:0.15rem}
.quiet-foot{display:flex;align-items:center;justify-content:space-between;gap:0.8rem;flex-wrap:wrap;margin-top:1rem}
.quiet-foot .footnote{margin:0}
.quiet-show{font:inherit;font-size:0.9rem;padding:0.4rem 0.9rem;border-radius:8px;border:1px solid var(--line);background:transparent;color:var(--ink);cursor:pointer}
.quiet-show:hover{border-color:var(--ink-soft)}

/* Plain-English pass (Sam's review, 2026-09-18) */
/* Rule grid tiles carry the ticker; the legend explains the colours. */
.rule-grid-sq.tile{width:auto;min-width:46px;height:28px;padding:0 6px;display:inline-flex;align-items:center;justify-content:center;text-decoration:none;border-radius:5px}
.rule-grid-sq.tile .tile-ticker{font-size:0.7rem;font-weight:700;letter-spacing:0.02em;color:#0B1220;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}
.rule-grid-sq.tile.no_data .tile-ticker{color:var(--ink-soft)}
.rule-grid-sq.tile:hover{outline:2px solid var(--ink);outline-offset:1px}
.rule-grid-legend{display:flex;flex-direction:column;gap:0.3rem;font-size:0.78rem;color:var(--ink-soft);padding:0.4rem 0.6rem;border:1px solid var(--line);border-radius:6px;min-width:160px}
.legend-item{display:flex;align-items:center;gap:0.45rem}
.legend-item .rule-grid-sq{width:14px;height:14px;border-radius:3px}
/* Portfolio Health: the reason, the arithmetic, the principle. */
.health-why{margin:0 0 0.6rem;font-size:0.9rem;line-height:1.5}
.health-why-lead{margin:0.3rem 0 0.9rem;font-size:0.95rem}
.health-stance{margin:0.8rem 0 0}
.principles{margin:0.7rem 0 0}
.principles summary{cursor:pointer;font-size:0.82rem;color:var(--ink-soft);list-style:none}
.principles summary::-webkit-details-marker{display:none}
.principles summary::before{content:"\25B8  ";font-size:0.75rem}
.principles[open] summary::before{content:"\25BE  "}
.principle{margin:0.5rem 0 0;padding:0.5rem 0.75rem;border-left:3px solid var(--accent);background:var(--paper);border-radius:0 6px 6px 0}
.principle p{margin:0;font-size:0.9rem;line-height:1.5;font-style:italic}
.principle footer{margin-top:0.25rem;font-size:0.76rem;color:var(--ink-soft)}
.principle.principle-other{border-left-color:var(--hold)}
.principle-side{text-transform:uppercase;letter-spacing:0.04em;font-size:0.68rem}
.principles-more{margin:0.5rem 0 0;font-size:0.8rem}
/* principles.html - the twelve cards. One card = principle, one verbatim
   quotation with its source (a second, greyer one where investors disagree),
   and where the idea shows up in the app. Same paper/card/line tokens as the
   learn-entry widgets, laid out as a two-column grid that stacks on a phone. */
.pc-theme{margin:1.6rem 0 0.7rem;font-size:0.78rem;font-weight:700;letter-spacing:0.08em;text-transform:uppercase;color:var(--ink-soft)}
.pc-theme:first-of-type{margin-top:0.4rem}
/* Where am I (8 Oct 2026): a topic bar that stays under the site header while the cards scroll, with the
   theme being read highlighted, so a card halfway down the page is never without its heading. */
.pc-jump{position:sticky;top:var(--sticky-top,0px);z-index:5;display:flex;gap:0.4rem;overflow-x:auto;scrollbar-width:none;
  margin:0.6rem -1px 0.4rem;padding:0.55rem 1px;background:var(--card);box-shadow:0 1px 0 var(--line)}
.pc-jump::-webkit-scrollbar{display:none}
.pc-jump a{flex:0 0 auto;display:inline-flex;align-items:center;gap:0.4rem;padding:0.3rem 0.7rem;border:1px solid var(--line);border-radius:999px;
  font-size:0.8rem;font-weight:600;color:var(--ink-soft);text-decoration:none;white-space:nowrap;transition:background 0.15s,color 0.15s,border-color 0.15s}
.pc-jump a:hover{color:var(--ink);border-color:var(--ink-soft)}
.pc-jump a:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.pc-jump a.is-active{background:var(--accent);border-color:var(--accent);color:var(--card)}
.pc-jump-n{font-size:0.7rem;font-weight:700;opacity:0.7;font-variant-numeric:tabular-nums}
.pc-theme{scroll-margin-top:calc(var(--sticky-top,0px) + 3.6rem)}
.pcard{scroll-margin-top:calc(var(--sticky-top,0px) + 3.6rem)}
@media (prefers-reduced-motion:reduce){.pc-jump a{transition:none}}
@media (min-width:721px){.pc-jump{flex-wrap:wrap;overflow-x:visible}}
.pc-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0.8rem}
.pcard{display:flex;flex-direction:column;gap:0.6rem;padding:0.95rem 1.05rem 1rem;border:1px solid var(--line);border-radius:8px;background:var(--card)}
.pcard h4{margin:0;font-size:1.02rem;font-weight:650;line-height:1.35;color:var(--ink);text-wrap:balance}
.pc-principle{margin:0;font-size:0.9rem;line-height:1.55;color:var(--ink)}
.pc-quote{margin:0;padding:0.55rem 0.8rem;border-left:3px solid var(--accent);background:var(--paper);border-radius:0 6px 6px 0}
.pc-quote p{margin:0;font-size:0.9rem;line-height:1.5;font-style:italic;color:var(--ink)}
.pc-quote cite{font-style:normal;font-weight:600}
.pc-quote footer{margin-top:0.3rem;font-size:0.76rem;line-height:1.4;color:var(--ink-soft)}
.pc-quote.pc-other{border-left-color:var(--hold)}
.pc-where{margin:auto 0 0;padding-top:0.55rem;border-top:1px dashed var(--line);font-size:0.85rem;line-height:1.55;color:var(--ink-soft)}
.pc-where .pc-label{display:block;font-size:0.68rem;font-weight:700;letter-spacing:0.08em;text-transform:uppercase;color:var(--accent);margin-bottom:0.2rem}
.pc-where a{color:var(--accent);text-decoration:underline;text-underline-offset:2px}
.pc-where em{color:var(--ink);font-style:normal;font-weight:600}
@media (max-width:720px){.pc-grid{grid-template-columns:1fr}}
/* Sector map (dashboard) and sector.html - app.universe / routers/sectors.py.
   One table, sortable by header, that reads like the rest of the site: the
   rule squares carry the vote, numbers are tabular, and the two personal
   columns (your share, moves with your book) sit beside the market read. */
.sector-tabs{display:inline-flex;flex-wrap:wrap;gap:0.3rem;font-size:0.8rem;font-weight:400}
.sector-tab{padding:0.2rem 0.6rem;font-size:0.78rem}
.sector-tab.active,button.secondary.sector-tab.active{background:var(--accent);border-color:var(--accent);color:var(--on-accent,#fff);font-weight:600}
.sector-table-wrap{overflow-x:auto}
.sector-table{width:100%;border-collapse:collapse;font-size:0.86rem}
.sector-table th,.sector-table td{padding:0.45rem 0.55rem;text-align:left;vertical-align:top;border-bottom:1px solid var(--line);white-space:nowrap}
.sector-table th{font-size:0.72rem;font-weight:700;letter-spacing:0.05em;text-transform:uppercase;color:var(--ink-soft)}
.sector-table th.sortable{cursor:pointer;user-select:none}
.sector-table th.sortable:hover,.sector-table th.sorted{color:var(--accent)}
.sector-table td .num{font-variant-numeric:tabular-nums}
.sector-table .pos{color:var(--buy)}
.sector-table .neg{color:var(--sell)}
.sector-table .muted,.muted{color:var(--ink-soft)}
.sector-link{color:var(--ink);font-weight:600;text-decoration:none;border-bottom:1px dotted var(--accent)}
.sector-link:hover{color:var(--accent)}
.sector-held{font-size:0.72rem;color:var(--ink-soft);margin-top:0.15rem}
.sector-rules{display:inline-flex;align-items:center;gap:0.4rem}
.sector-rules .rule-grid-sq{width:16px;height:16px;flex-shrink:0}
.sector-agree{font-size:0.8rem;color:var(--ink-soft)}
.sector-breadth{display:inline-flex;align-items:center;gap:0.25rem;font-size:0.82rem}
.sector-breadth .rule-grid-sq{width:10px;height:10px;border-radius:2px;margin-left:0.2rem}
.sector-legend .rule-grid-sq{width:11px;height:11px;border-radius:2px;vertical-align:middle}
.sector-market{font-size:0.85rem;font-weight:400;color:var(--ink-soft);margin-left:0.4rem}
.sector-block{margin:1.1rem 0 0;padding:0.9rem 1rem;border:1px solid var(--line);border-radius:8px;background:var(--card)}
.sector-block h3{margin:0 0 0.6rem;font-size:0.95rem}
.sector-index-read{display:flex;gap:0.7rem;align-items:flex-start;margin:0 0 0.6rem}
.sector-index-read .rule-grid-sq{width:26px;height:26px;flex-shrink:0;margin-top:0.15rem}
.sector-reasons{margin:0.3rem 0 0.6rem 1.1rem;padding:0;font-size:0.85rem;line-height:1.5;color:var(--ink-soft)}
.sector-reasons li{margin-bottom:0.3rem}
.sector-reasons li.positive::marker{color:var(--buy)}
.sector-reasons li.negative::marker{color:var(--sell)}
.sector-stats{display:flex;flex-wrap:wrap;gap:0.4rem 1.2rem;font-size:0.85rem;margin:0.2rem 0 0.6rem}
.sector-breadth-line{margin:0.4rem 0 0}
.screen-filters{display:flex;flex-wrap:wrap;gap:0.5rem 0.9rem;align-items:center;margin:0.6rem 0 0.5rem;font-size:0.82rem;color:var(--ink-soft)}
.screen-filters label{display:inline-flex;align-items:center;gap:0.35rem}
.screen-filters select,.screen-filters input[type=text]{font:inherit;font-size:0.82rem;padding:0.25rem 0.4rem;border:1px solid var(--line);border-radius:4px;background:var(--paper);color:var(--ink)}
.screen-filters input[type=text]{width:9rem}
.screen-table td.sc-name{white-space:normal;max-width:16rem;color:var(--ink-soft)}
.sector-badge{display:inline-block;margin-left:0.35rem;padding:0 0.35rem;border:1px solid var(--line);border-radius:999px;font-size:0.66rem;text-transform:uppercase;letter-spacing:0.05em;color:var(--ink-soft);vertical-align:middle}
.sc-watch{padding:0.15rem 0.5rem;font-size:0.76rem}
@media (max-width:720px){.sector-table th,.sector-table td{padding:0.35rem 0.4rem}.screen-filters input[type=text]{width:100%}}
/* Hover glossary */
.term{text-decoration:underline dotted var(--accent);text-decoration-thickness:1.5px;text-underline-offset:3px;cursor:help;border-radius:2px}
.glossary-hint{margin:0 0 0.8rem;padding:0.5rem 0.8rem;border:1px dashed var(--line);border-radius:6px;background:var(--card)}
.term:hover,.term.active,.term:focus-visible{text-decoration-color:var(--accent);background:color-mix(in srgb,var(--accent) 12%,transparent);outline:none}
#termPop{position:absolute;z-index:60;background:var(--card);color:var(--ink);border:1px solid var(--line);border-radius:8px;padding:0.6rem 0.75rem;box-shadow:0 8px 24px rgba(0,0,0,0.25);font-size:0.85rem;line-height:1.45}
#termPop .term-label{font-weight:700;font-size:0.72rem;letter-spacing:0.06em;text-transform:uppercase;color:var(--ink-soft);margin-bottom:0.25rem}
#termPop p{margin:0}
#termPop a{display:inline-block;margin-top:0.4rem;font-size:0.8rem}
@media (prefers-reduced-motion: no-preference){#termPop{animation:term-in 0.12s ease-out}}
@keyframes term-in{from{opacity:0;transform:translateY(-3px)}to{opacity:1;transform:none}}

/* Import review (broker-sync-plan steps 2-4, 6) */
.import-preset{font-size:0.85rem;padding:0.25rem 0.4rem;max-width:100%}
.import-preset-note{color:var(--ink-soft)}
.import-review-table{width:100%;border-collapse:collapse;margin-top:0.6rem;font-size:0.85rem}
.import-review-table th{text-align:left;font-weight:600;color:var(--ink-soft);padding:0.3rem 0.4rem;border-bottom:1px solid var(--line)}
.import-review-table td{padding:0.35rem 0.4rem;border-bottom:1px solid var(--line);vertical-align:top}
.import-review-table tr.rv-change td:nth-child(3){color:var(--hold)}
.import-review-table tr.rv-new td:nth-child(3){color:var(--buy,#33d0a6)}
.import-review-table tr.rv-same td{color:var(--ink-soft)}
.import-review-table select{font-size:0.82rem}
.coverage-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:0.8rem;margin:0.6rem 0}
.coverage-grid h4{margin:0 0 0.3rem;font-size:0.85rem}
.coverage-grid ul{margin:0;padding-left:1.1rem;font-size:0.84rem;color:var(--ink-soft)}
.coverage-grid li{margin:0.15rem 0}
.import-last{color:var(--ink-soft)}
@media (max-width:640px){.import-review-table th:nth-child(4),.import-review-table td:nth-child(4){display:none}}

/* RG 244.30: the factual-information statement "at the outset" of every page */
.factual-line{margin:0;padding:0.35rem 16px;text-align:center;font-size:0.78rem;line-height:1.4;color:var(--ink-soft);background:var(--header-bg);border-bottom:1px solid var(--line)}

/* Admin overview */
.adm-h{margin:1.4rem 0 0.6rem;padding-top:0.8rem;border-top:1px solid var(--line)}
.adm-tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:0.6rem;margin:0.4rem 0 0.8rem}
.adm-tile{border:1px solid var(--line);border-radius:8px;padding:0.6rem 0.8rem}
.adm-tile-v{font-size:1.5rem;font-weight:700;font-variant-numeric:tabular-nums}
.adm-tile-l{font-size:0.78rem;color:var(--ink-soft);text-transform:uppercase;letter-spacing:0.03em}
.adm-tile-s{font-size:0.8rem;color:var(--ink-soft);margin-top:0.15rem}
.adm-grid2{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:1rem;margin:0.4rem 0}
/* A grid column is as wide as its widest unbreakable line unless told
   otherwise, so a long table ran into the next column and past the panel
   (Sam's screenshot, 7 Oct). Each column now keeps its width and scrolls its
   own table sideways if it must. */
.adm-grid2>div,.adm-wide{min-width:0;overflow-x:auto}
.adm-wide{margin:0.4rem 0}
.adm-wide h4{margin:0.4rem 0 0.3rem;font-size:0.9rem}
#admIssues td:last-child{white-space:normal;min-width:14rem;color:var(--ink-soft)}
.adm-grid2 h4{margin:0.4rem 0 0.3rem;font-size:0.9rem}
.adm-table{width:100%;border-collapse:collapse;font-size:0.84rem}
.adm-table th{text-align:left;color:var(--ink-soft);font-weight:600;padding:0.3rem 0.4rem;border-bottom:1px solid var(--line)}
.adm-table td{padding:0.3rem 0.4rem;border-bottom:1px solid var(--line);font-variant-numeric:tabular-nums;white-space:nowrap}
.adm-details{margin:0.6rem 0}
.adm-details summary{cursor:pointer;color:var(--ink-soft);font-size:0.88rem}
.adm-chart{min-height:120px}
.adm-bars{display:flex;align-items:flex-end;gap:3px;height:120px;padding-top:6px}
.adm-bar{flex:1;display:flex;flex-direction:column;justify-content:flex-end;align-items:center;min-width:8px;height:100%}
.adm-bar-fill{width:100%;background:#33d0a6;border-radius:2px 2px 0 0;min-height:2px}
.adm-bar-l{font-size:0.62rem;color:var(--ink-soft);margin-top:2px;transform:rotate(-60deg);transform-origin:top left;height:24px;white-space:nowrap}

/* Destructive action (delete account): red, never the default button colour, never primary-styled. */
button.danger{background:#e25c5c;color:#fff;border-color:#e25c5c}
button.danger:hover{background:#c94a4a;border-color:#c94a4a}
button.danger:disabled{opacity:.6;cursor:default}

/* ---- Account menu (header avatar) and the account settings page --------------
   The avatar button replaces the old "Log out" button. One menu, every page:
   who you are, theme, the settings page's sections, tell a friend, log out.
   Destructive actions never sit in the menu - delete lives at the foot of the
   settings page, past export. */
.site-account{position:relative}
.account-btn{display:inline-flex;align-items:center;gap:8px;background:transparent;border:1px solid var(--line);border-radius:999px;padding:3px 10px 3px 3px;color:var(--ink);font:inherit;font-size:.85rem;cursor:pointer;line-height:1}
.account-btn:hover,.account-btn[aria-expanded="true"]{background:var(--card)}
.account-avatar{width:26px;height:26px;border-radius:50%;background:var(--accent);color:var(--on-accent);display:inline-flex;align-items:center;justify-content:center;font-weight:700;font-size:.72rem;letter-spacing:.02em;flex:none}
.account-avatar.big{width:38px;height:38px;font-size:.95rem}
.account-caret{font-size:.7rem;color:var(--ink-soft)}
.account-menu{position:absolute;right:0;top:calc(100% + 8px);min-width:260px;background:var(--card);border:1px solid var(--line);border-radius:14px;box-shadow:0 12px 32px rgba(0,0,0,.35);padding:6px;z-index:60;display:flex;flex-direction:column;text-align:left}
.account-menu[hidden],.account-menu [role="menuitem"][hidden]{display:none}
.account-menu-head{display:flex;align-items:center;gap:10px;padding:10px 10px 12px;border-bottom:1px solid var(--line);margin-bottom:6px}
.account-menu-who{display:flex;flex-direction:column;min-width:0}
.account-menu-who strong{font-size:.95rem;color:var(--ink)}
.account-menu-who span{font-size:.78rem;color:var(--ink-soft);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:200px}
.account-menu a[role="menuitem"],.account-menu button[role="menuitem"]{display:block;width:100%;text-align:left;padding:9px 10px;border-radius:9px;color:var(--ink);text-decoration:none;font:inherit;font-size:.9rem;background:transparent;border:0;cursor:pointer}
.account-menu a[role="menuitem"]:hover,.account-menu button[role="menuitem"]:hover,.account-menu a[role="menuitem"]:focus-visible,.account-menu button[role="menuitem"]:focus-visible{background:var(--accent-bg);outline:none}
.account-menu-glance{display:block;margin-top:2px;font-size:.78rem;color:var(--ink-soft);font-variant-numeric:tabular-nums}
.account-menu .account-menu-logout{border-top:1px solid var(--line);border-radius:0 0 9px 9px;margin-top:6px;padding-top:11px;color:var(--ink-soft)}
/* Phones (9 Oct 2026): the menu drops down under the avatar, as wide as the screen allows. It used to be a
   sheet fixed to the bottom of the screen, but the header's backdrop blur makes the header, not the screen,
   the box a fixed menu is placed in, so the sheet sat at the header's foot and ran off the top of the screen:
   the name, Account settings and Plan & billing could not be reached (Sam's screenshot). */
@media (max-width:640px){.account-menu{position:absolute;top:calc(100% + 8px);right:0;left:auto;bottom:auto;min-width:0;width:min(340px,calc(100vw - 32px));max-height:min(75vh,560px);overflow-y:auto}.account-btn #userBadgeName{display:none}}
@media (max-width:420px){.account-menu{left:0;right:auto}}

.account-sections{display:flex;flex-wrap:wrap;gap:6px 14px;margin:0 0 1rem;font-size:.85rem}
.account-sections a{color:var(--ink-soft);text-decoration:none;border-bottom:1px solid transparent}
.account-sections a:hover{color:var(--ink);border-bottom-color:var(--ink)}
.account-section{border-top:1px solid var(--line);padding:1.1rem 0 1rem;scroll-margin-top:80px}
.account-section h3{margin:0 0 .6rem;font-size:1.05rem}
.account-section h4{margin:1.2rem 0 .5rem;font-size:.9rem;color:var(--ink-soft);text-transform:uppercase;letter-spacing:.04em}
.account-row{display:grid;grid-template-columns:180px minmax(0,1fr);gap:8px 16px;align-items:start;margin:0 0 .7rem}
.account-row>label{color:var(--ink-soft);font-size:.85rem;padding-top:9px}
.account-field{display:flex;flex-wrap:wrap;gap:8px;align-items:center}
.account-field input[type="text"],.account-field input[type="password"],.account-field select{flex:1 1 220px;max-width:340px}
.account-static{padding:9px 0;color:var(--ink)}
.account-danger{border-top-color:#e25c5c}
.plan-card{display:flex;flex-wrap:wrap;gap:8px 18px;align-items:baseline;margin:0 0 .6rem}
.plan-card .plan-name{font-size:1.15rem;font-weight:700}
.plan-card .plan-meta{color:var(--ink-soft);font-size:.85rem}
@media (max-width:640px){.account-row{grid-template-columns:1fr}.account-row>label{padding-top:0}}

/* Embeddable ticker badge (stock page) */
.badge-embed summary{cursor:pointer;font-weight:600;}
.badge-embed-code{width:100%;box-sizing:border-box;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:0.78rem;line-height:1.35;padding:0.5rem;border-radius:6px;border:1px solid var(--line);background:var(--paper);color:var(--ink);resize:vertical;}
.sector-tab.other{opacity:0.7}
.sector-tab.other.active{opacity:1}

/* Learn articles (/learn/<term>.html) */
.learn-article h1{font-size:1.55rem;line-height:1.25;margin:0.2rem 0 0.9rem;text-wrap:balance}
.learn-article h2{font-size:1.05rem;margin:1.4rem 0 0.5rem}
.learn-article p{font-size:0.93rem;line-height:1.7;color:var(--ink-soft);margin:0 0 0.9rem;max-width:68ch}
.learn-eyebrow{font-size:0.78rem;letter-spacing:0.04em;text-transform:uppercase;color:var(--ink-soft);margin:0 0 0.4rem}
.learn-eyebrow a{color:var(--accent);text-decoration:none}
.learn-one-line{border-left:3px solid var(--accent);background:var(--card);padding:0.7rem 0.9rem;border-radius:4px;margin:0 0 1rem}
.learn-one-line-label{display:block;font-size:0.75rem;letter-spacing:0.04em;text-transform:uppercase;color:var(--accent);margin-bottom:0.25rem}
.learn-one-line p{color:var(--ink);margin:0;font-size:0.95rem}
.learn-where{margin:0 0 1rem;padding-left:1.2rem;font-size:0.9rem;line-height:1.7}
.learn-related{font-size:0.88rem;display:flex;flex-wrap:wrap;gap:0.4rem;align-items:center}
.learn-related span{color:var(--ink-soft)}
.learn-related a{border:1px solid var(--line);border-radius:999px;padding:0.1rem 0.6rem;text-decoration:none}
.learn-fullpage-tag{display:inline-block;white-space:nowrap;font-size:0.68rem;letter-spacing:0.04em;text-transform:uppercase;color:var(--accent);border:1px solid var(--accent);border-radius:999px;padding:0.05rem 0.5rem;margin-left:0.4rem;vertical-align:middle;font-weight:600}
.learn-fullpage-link{margin:0.2rem 0 0.4rem}
.learn-fullpage-link a{color:var(--accent);text-decoration:none;font-weight:600}
.learn-fullpage-link a:hover{text-decoration:underline}

/* Learn page: full-page cards, quick-reference toolbar and groups */
.learn-section-title{display:flex;flex-wrap:wrap;align-items:baseline;gap:0.3rem 0.7rem}
.learn-section-sub{font-size:0.8rem;font-weight:400;color:var(--ink-soft);text-transform:none;letter-spacing:0}
.learn-reads{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:0.6rem;margin:0 0 1.2rem}
.learn-reads a{display:block;border:1px solid var(--line);border-radius:6px;padding:0.7rem 0.85rem;text-decoration:none;color:inherit;background:var(--card)}
.learn-reads a:hover{border-color:var(--accent)}
.learn-reads a strong{display:block;color:var(--accent);font-size:1rem;margin-bottom:0.25rem}
.learn-reads a span{font-size:0.86rem;color:var(--ink-soft);line-height:1.45}
.learn-toolbar{display:flex;gap:0.5rem;align-items:center;margin:0 0 0.6rem}
.learn-toolbar .filter-input{flex:1;margin:0}
.learn-jump{display:flex;flex-wrap:wrap;gap:0.35rem;margin:0 0 1rem}
.learn-jump a{font-size:0.78rem;border:1px solid var(--line);border-radius:999px;padding:0.15rem 0.6rem;text-decoration:none;color:var(--ink-soft)}
.learn-jump a:hover{border-color:var(--accent);color:var(--accent)}
.learn-group{margin:0 0 1.2rem}
.learn-group-title{font-size:0.8rem;letter-spacing:0.05em;text-transform:uppercase;color:var(--ink-soft);margin:0 0 0.5rem;padding-top:0.4rem;border-top:1px solid var(--line)}
.learn-group[hidden],.learn-entry[hidden]{display:none}
.learn-entry mark{background:rgba(51,208,166,0.25);color:inherit;border-radius:2px;padding:0 1px}

#signalsPanel .rule-grid{margin:0 0 0.9rem}



/* Admin: tabs, users, operations, playbooks (20 Sep 2026) */
.adm-tabs{display:flex;gap:0.3rem;border-bottom:1px solid var(--line);margin:0.2rem 0 0.8rem}
.adm-social-btn{font:inherit;font-size:0.85rem;font-weight:600;padding:0.3rem 0.75rem;border-radius:8px;border:1px solid var(--accent);background:var(--accent);color:var(--card);cursor:pointer}
.adm-social-btn:hover{filter:brightness(1.08)}
.adm-social{margin:0 0 0.8rem;padding:0.7rem 0.9rem;border:1px solid var(--line);border-radius:10px;background:var(--card)}
.adm-social-list{list-style:none;margin:0;padding:0;display:grid;gap:0.35rem;font-size:0.9rem}
.adm-social-list a{margin:0 0.15rem;color:var(--accent);font-weight:600}
.adm-tab{border:0;background:transparent;color:var(--ink-soft);padding:0.5rem 0.9rem;font:inherit;font-weight:600;cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1px}
.adm-tab.active{color:var(--accent);border-bottom-color:var(--accent)}
.adm-tab:hover{color:var(--ink)}
.adm-tabpanel[hidden]{display:none}
.adm-users-search{display:flex;gap:0.6rem;align-items:center;margin:0 0 0.6rem}
.adm-users-search .filter-input{flex:1;margin:0}
.adm-users-grid{grid-template-columns:minmax(300px,1fr) minmax(320px,1.2fr)}
#admUserResults td:first-child{white-space:normal;word-break:break-all}
.adm-user-link{padding:0;font-weight:600}
.adm-user-name{display:block;margin:0;font-size:0.75rem}
.adm-user-detail{border:1px solid var(--line);border-radius:8px;padding:0.8rem 1rem;background:var(--card)}
.adm-user-detail h5,.pb h5{font-size:0.78rem;letter-spacing:0.04em;text-transform:uppercase;color:var(--ink-soft);margin:0.9rem 0 0.3rem}
.adm-kv{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:0.3rem 1rem;font-size:0.86rem}
.adm-kv div{display:flex;flex-direction:column}
.adm-kv span{color:var(--ink-soft);font-size:0.75rem}
.adm-kv b{font-weight:500}
.adm-actions{display:flex;flex-wrap:wrap;gap:0.4rem;align-items:center}
.adm-actions button,.adm-btn-link{font-size:0.82rem;padding:0.35rem 0.7rem}
.adm-btn-link{display:inline-block;border:1px solid var(--line);border-radius:6px;text-decoration:none;color:inherit}
.adm-danger{margin-top:0.9rem;border-top:1px solid var(--line);padding-top:0.5rem}
.adm-danger summary{cursor:pointer;color:var(--sell,#e25c5c);font-size:0.86rem}
.adm-state{font-weight:700;font-size:0.8rem}
.adm-state.ok{color:var(--buy,#33d0a6)}.adm-state.bad{color:var(--sell,#e25c5c)}.adm-state.na{color:var(--ink-soft)}
.adm-links{margin:0.3rem 0;padding-left:1.1rem;font-size:0.86rem;line-height:1.6}
.pb-toolbar{display:flex;gap:0.5rem;align-items:center;margin:0 0 0.6rem}
.pb-toolbar .filter-input{flex:1;margin:0}
.pb-group{font-size:0.8rem;letter-spacing:0.05em;text-transform:uppercase;color:var(--ink-soft);margin:1rem 0 0.4rem;padding-top:0.4rem;border-top:1px solid var(--line)}
.pb{border:1px solid var(--line);border-radius:6px;padding:0.2rem 1rem;margin-bottom:0.5rem;background:var(--paper)}
.pb[open]{background:var(--card)}
.pb summary{cursor:pointer;padding:0.6rem 0;font-weight:600;font-size:0.92rem;list-style:none;display:flex;justify-content:space-between;align-items:center;gap:0.6rem}
.pb summary::-webkit-details-marker{display:none}
.pb summary::after{content:"+";color:var(--accent);font-weight:700;flex:0 0 auto}
.pb[open] summary::after{content:"\2212"}
.pb-tags{display:flex;gap:0.3rem;margin-left:auto}
.pb-tag{font-size:0.65rem;letter-spacing:0.04em;text-transform:uppercase;border:1px solid var(--line);border-radius:999px;padding:0.05rem 0.45rem;color:var(--ink-soft)}
.pb-tag-priority{border-color:var(--sell,#e25c5c);color:var(--sell,#e25c5c)}
.pb-tag-compliance{border-color:var(--accent);color:var(--accent)}
.pb p,.pb li{font-size:0.86rem;line-height:1.6;color:var(--ink-soft)}
.pb ul{margin:0 0 0.4rem;padding-left:1.1rem}
.pb-reply{width:100%;box-sizing:border-box;font:inherit;font-size:0.84rem;line-height:1.5;padding:0.5rem 0.6rem;border:1px solid var(--line);border-radius:6px;background:var(--paper);color:var(--ink);resize:vertical}
.pb-reply-row{display:flex;gap:0.6rem;align-items:center;margin:0.3rem 0 0.6rem}
.pb-escalate{border-left:3px solid var(--sell,#e25c5c);padding-left:0.7rem}

/* --- Phone width: give the tables the screen back (21 Sep 2026) -----------
   Reported from a phone: "the screen can move left and right, and at Your
   holdings the right columns can't be seen." Two separate causes, both here.

   First, the page was spending a quarter of a 390px screen on its own
   margins - 1.5rem of shell padding plus 1.4rem of panel padding on each
   side left a 274px column inside a 375px viewport. Desktop-sized breathing
   room on a phone.

   Second, what was left over still wasn't enough for the four-column tables
   (the signals table wanted 421px), so each one scrolled sideways inside its
   own box. That scroll is real and works, but a table that shows Symbol and
   Outlook and hides Price reads as broken rather than scrollable, and a
   sideways swipe over it looks like the whole screen moving.

   So: narrower gutters, smaller type and padding in the table itself, the
   "Why" label reduced to its chevron (the whole row opens anyway), and the
   condition badges allowed to wrap instead of forcing their column to fit
   the longest phrase on one line. The columns themselves all stay - nothing
   is hidden from a phone that a desktop shows. .table-scroll keeps its
   overflow as the backstop for a very long ticker or a 400px screen. */
@media (max-width: 640px) {
  .shell { padding: 1.5rem 0.85rem 3.5rem; }
  .panel { padding: 1rem 0.85rem; }
  .factor-table { font-size: 0.8rem; }
  .factor-table th, .factor-table td { padding: 0.35rem 0.3rem; }
  .factor-table th { letter-spacing: 0; }
  .regime-badge, .vol-badge { white-space: normal; padding: 0.2rem 0.45rem; }
  /* font-size:0 collapses the word and leaves the chevron, which carries the
     same meaning in a fifth of the width. The row's own click target is
     unchanged, and .row-open is aria-hidden, so nothing is lost to a reader. */
  .row-open { font-size: 0; padding: 0.1rem 0.4rem; }
  .row-open .factor-chevron { font-size: 0.8rem; margin-left: 0; }
}

/* Small phones (iPhone SE/mini, 360-400px): the same tables, one more notch
   tighter, so Price still lands on screen rather than one swipe past it. */
@media (max-width: 420px) {
  .factor-table { font-size: 0.76rem; }
  .factor-table th, .factor-table td { padding: 0.32rem 0.22rem; }
  /* The headers, not the figures, were setting several column widths
     ("Indicator agreement" over a 60% reading), so they shrink first. */
  .factor-table th { font-size: 0.66rem; }
  .action-badge { font-size: 0.74rem; padding: 0.22rem 0.45rem; }
  .regime-badge, .vol-badge { font-size: 0.72rem; }
  .market-tag { font-size: 0.68rem; }
  .symbol-label { gap: 0.15rem; }
  .symbol-label .market-tag::before { margin-right: 0.15rem; }
  .row-open { padding: 0.1rem 0.28rem; }
  .signals-table .row-open-cell { padding-left: 0; padding-right: 0.1rem; }
}

/* --- The "which market?" answer (22 Sep 2026) -------------------------------
   Shown when a ticker is listed in more than one market and nothing has told
   us which one the person holds. Buttons, not a dropdown: there are two or
   three of them, the difference between them is the whole question, and a
   dropdown hides the answer behind a click. */
.symbol-choice{display:flex;flex-wrap:wrap;gap:0.5rem;margin:0.6rem 0 0.3rem}
.symbol-choice-btn{display:flex;flex-direction:column;align-items:flex-start;gap:0.1rem;text-align:left;line-height:1.35}
.symbol-choice-name{font-size:0.78rem;font-weight:400;color:var(--ink-soft)}
.symbol-choice-foot{margin-top:0.2rem;font-size:0.82rem}
/* Quieter than the table above it: it explains a difference rather than
   reporting a problem, and it is on screen every time a mixed-currency book
   is shown. */
.gain-currency-note{margin:0.6rem 0 0;line-height:1.5}

/* Price chart on a stock's page (24 Sep 2026). The average colours are the
   chart's own tokens so each line reads on both grounds. */
:root { --ma20: #F5B759; --ma50: #60A5FA; --ma100: #C084FC; --ma200: #F472B6; }
:root[data-theme="light"] { --ma20: #B45309; --ma50: #1D4ED8; --ma100: #7C3AED; --ma200: #BE185D; }
.chart-toolbar { display: flex; flex-wrap: wrap; gap: 0.5rem 1.2rem; align-items: center; margin: 0 0 0.6rem; }
.chart-ranges { display: inline-flex; border: 1px solid var(--line); border-radius: 6px; overflow: hidden; }
.chart-range { background: transparent; color: var(--ink-soft); border: 0; border-right: 1px solid var(--line); padding: 0.3rem 0.65rem; font: 600 0.8rem var(--num-font); cursor: pointer; }
.chart-range:last-child { border-right: 0; }
.chart-range.active { background: var(--accent-bg); color: var(--ink); }
.chart-range:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.chart-chips { display: flex; flex-wrap: wrap; gap: 0.35rem 0.8rem; align-items: center; font-size: 0.8rem; color: var(--ink-soft); }
.chart-chips-label { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.05em; font-weight: 600; }
.chart-chip { display: inline-flex; gap: 0.3rem; align-items: center; cursor: pointer; color: var(--ink); }
.chart-chip input { margin: 0; }
.chart-swatch { display: inline-block; width: 0.9rem; height: 3px; border-radius: 2px; }
.chart-legend { min-height: 2.6rem; font: 0.78rem var(--num-font); color: var(--ink-soft); display: flex; flex-wrap: wrap; gap: 0.2rem 0.8rem; align-items: baseline; margin-bottom: 0.3rem; }
.chart-legend-day { color: var(--ink); font-weight: 600; }
.chart-legend-avg { display: inline-flex; gap: 0.3rem; align-items: center; }
.chart-legend-votes { flex-basis: 100%; display: flex; flex-direction: column; gap: 0.1rem; font-family: 'Fira Sans', -apple-system, 'Segoe UI', Roboto, sans-serif; }
.chart-legend-vote.up { color: var(--buy); }
.chart-legend-vote.down { color: var(--sell); }
.chart-box { width: 100%; height: 380px; }
.chart-status { margin: 0.6rem 0 0; font-size: 0.88rem; }
.chart-foot { margin-top: 0.4rem; }
@media (max-width: 600px) { .chart-box { height: 300px; } .chart-toolbar { gap: 0.5rem; } }

/* Long-term view (24 Sep 2026): folds the daily outlooks, leads with positions. */
body.longterm-on #signalsPanel { display: none !important; }
.lt-title { margin-top: 0; }
.lt-lead { font-size: 1rem; margin: 0 0 0.7rem; }
.lt-table td { vertical-align: middle; }
.lt-side { font-weight: 600; margin-right: 0.45rem; font-family: var(--num-font); font-size: 0.82rem; }
.lt-side.above { color: var(--buy); }
.lt-side.below { color: var(--sell); }
.lt-days { color: var(--ink-soft); font-size: 0.78rem; white-space: nowrap; }
.lt-na { color: var(--ink-soft); font-size: 0.78rem; }
.lt-range { display: inline-flex; flex-direction: column; gap: 0.2rem; min-width: 8rem; }
.lt-range-track { position: relative; height: 4px; border-radius: 2px; background: var(--line); display: block; }
.lt-range-dot { position: absolute; top: 50%; width: 10px; height: 10px; margin: -5px 0 0 -5px; border-radius: 50%; background: var(--accent); }
.lt-range-ends { font: 0.7rem var(--num-font); color: var(--ink-soft); white-space: nowrap; }
.lt-foot { margin-top: 0.6rem; }
.lt-actions { display: flex; flex-wrap: wrap; gap: 0.6rem 1rem; align-items: center; margin-top: 0.4rem; }

/* Backtest: each rule against the base rate (26 Sep 2026) */
.bt-lift td.bt-lift-up { color: var(--buy, #22C55E); }
.bt-lift td.bt-lift-down { color: var(--sell, #F87171); }
.bt-lift td.bt-na { opacity: 0.6; font-style: italic; }
.bt-lift .bt-small { font-size: 0.8em; opacity: 0.75; white-space: nowrap; }

/* Risk picture (26 Sep 2026) */
.risk-table .risk-neg { color: var(--sell, #F87171); }
.risk-table td.num { white-space: nowrap; }
/* The second figure in a cell (when the high was, the multiple, the figure
   leaving a flagged day out, the gap pill) sits on its own line under the
   main number, so six columns fit the panel instead of running off its
   right edge (6 Oct 2026). */
.risk-table td.num .lt-days, .risk-table td.num .risk-flag { display: block; width: fit-content; margin: 0.15rem 0 0 auto; }
.risk-table th { white-space: normal; vertical-align: bottom; }
.risk-table td.num .lt-inline { display: inline; margin: 0; }
/* A flagged one-day gap (app.events, 28 Sep 2026): amber pill beside the last move. Hover for the sentence. */
.risk-table .risk-flag {
  display: inline-block; margin-left: 0.35rem; padding: 0.05rem 0.45rem; border-radius: 999px;
  font-size: 0.72rem; line-height: 1.4; white-space: nowrap; cursor: help;
  color: #e8b34a; border: 1px solid currentColor; opacity: 0.9;
}
.risk-table .risk-flag.muted { color: var(--ink-soft); opacity: 0.75; }

/* Connect your broker - the contract-note inbox (claude/broker-sync-plan.md,
   6 Oct 2026). The address is the one thing on the card that has to be
   copied exactly, so it is set in the mono face at reading size; the health
   line turns amber only when the notes have gone quiet for a fortnight -
   the silent-link failure made visible, never a red alarm for "no trades". */
.inbox-card{border:1px solid var(--line);border-radius:10px;padding:0.8rem 0.9rem;background:var(--card);margin:0.2rem 0 0.6rem}
.inbox-address-row{display:flex;flex-wrap:wrap;align-items:center;gap:0.5rem}
.inbox-address{font-family:var(--num-font);font-size:0.95rem;padding:0.35rem 0.6rem;border-radius:7px;background:var(--accent-bg);color:var(--ink);word-break:break-all;user-select:all}
.inbox-health{color:var(--ink-soft)}
.inbox-health.quiet{color:var(--pill-mock-fg)}
.inbox-banner{margin:0 0 0.7rem;padding:0.55rem 0.8rem;border-radius:9px;background:var(--accent-bg);border:1px solid var(--accent-ring);font-size:0.88rem}
.inbox-banner .link-button{margin-left:0.3rem}
.inbox-howto{margin:0.4rem 0 0.6rem;font-size:0.85rem}
.inbox-howto summary{cursor:pointer;color:var(--ink-soft)}
.inbox-howto h4{margin:0.6rem 0 0.2rem;font-size:0.85rem}
.inbox-howto ol{margin:0;padding-left:1.2rem;color:var(--ink-soft)}
.inbox-howto li{margin:0.15rem 0}
.rv-note{color:var(--pill-mock-fg)}
.add-portfolio-tab .coming-soon-badge:not([hidden]){min-width:1.2rem;text-align:center}
.inbox-why{margin:0 0 0.7rem;font-size:0.85rem}
.inbox-why summary{cursor:pointer;color:var(--accent);font-weight:600}
.inbox-help{margin:0.6rem 0 0.2rem;padding:0.5rem 0.7rem;border-radius:8px;background:var(--pill-mock-bg);border:1px solid var(--pill-mock-border);font-size:0.85rem;color:var(--ink)}
.inbox-help a{color:var(--accent)}

/* --- Where the chart is (6 Oct 2026, app.chart_state) --------------------
   Six fixed states on the stock page and as a column of the dashboard's
   Market Conditions table. Direction states take the same colours the regime
   badges use for trending up/down; a range and an unusual day are neutral,
   because neither says which way. */
.state-badge{display:inline-block;font-size:0.75rem;font-weight:600;letter-spacing:0.02em;padding:0.2rem 0.55rem;border-radius:20px;white-space:nowrap;color:var(--ink-soft);background:var(--card);border:1px solid var(--line)}
.state-badge.up{color:var(--buy);background:var(--buy-bg);border-color:transparent}
.state-badge.down{color:var(--sell);background:var(--sell-bg);border-color:transparent}
.state-badge.watch{color:var(--hold);background:var(--hold-bg);border-color:transparent}
.state-badge.flat{color:var(--ink);background:var(--hold-bg);border-color:transparent}
.state-badge.big{font-size:0.95rem;padding:0.3rem 0.8rem}
.state-badge-btn{background:none;border:0;padding:0;cursor:pointer;font:inherit}
.state-badge-btn:hover .state-badge{filter:brightness(1.12)}
.cs-head{display:flex;align-items:center;gap:0.6rem;flex-wrap:wrap;margin:0 0 0.6rem}
.cs-also{font-size:0.82rem;color:var(--ink-soft)}
.cs-asof{margin:0 0 0 auto}
.cs-sentence{margin:0 0 0.8rem;font-size:1rem;line-height:1.5}
.cs-row-sentence{margin:0 0 0.5rem;color:var(--ink)}
.cs-filter-chip{margin:0 0 0.5rem;font-size:0.85rem;color:var(--ink-soft)}
.cs-all{margin-top:0.6rem}
.cs-all summary{cursor:pointer;font-size:0.86rem;color:var(--ink-soft)}
.cs-table th{text-align:center}
.cs-table th:first-child{text-align:left}
.cs-table td.cs-none{text-align:center;color:var(--ink-soft)}
.cs-last{display:block;font-size:0.72rem;color:var(--ink-soft);font-weight:400}
.cs-pending{font-size:0.72rem;color:var(--ink-soft)}
@media (max-width:640px){.state-badge{white-space:normal}.cs-asof{margin-left:0}}

/* --- Raising cash (6 Oct 2026, app.raising_cash) --------------------------
   The facts table under Holdings and the person's own sort rule. Same frame
   as the Tax notes block beneath it. */
.rc-block{margin:1rem 0 0;padding:0.7rem 0.85rem;border:1px solid var(--line);border-radius:8px;background:var(--paper)}
.rc-btn{font-size:0.82rem;padding:0.3rem 0.7rem}
.rc-rule{display:flex;align-items:center;gap:0.5rem;flex-wrap:wrap;margin:0.4rem 0 0.6rem}
.rc-rule-label{font-weight:600;font-size:0.9rem}
.rc-slot{display:inline-flex;align-items:center;gap:0.3rem}
.rc-slot-n{display:inline-flex;align-items:center;justify-content:center;width:1.3rem;height:1.3rem;border-radius:50%;background:var(--hold-bg);font-size:0.72rem;font-weight:700;color:var(--ink-soft)}
.rc-slot select{font:inherit;font-size:0.84rem;padding:0.25rem 0.4rem;border-radius:6px;border:1px solid var(--line);background:var(--card);color:var(--ink);max-width:min(100%,20rem)}
.rc-rule-saved{flex-basis:100%}
.rc-table td,.rc-table th{vertical-align:top}
.rc-table .rc-sub{display:block;font-size:0.72rem;color:var(--ink-soft);font-weight:400;white-space:nowrap}
.rc-table .up{color:var(--buy)}
.rc-table .down{color:var(--sell)}
.rc-missing{color:var(--ink-soft)}
.rc-tax{font-size:0.78rem;font-weight:600;padding:0.15rem 0.45rem;border-radius:20px;white-space:nowrap;border:1px solid var(--line);color:var(--ink-soft)}
.rc-tax.past{color:var(--ink);background:var(--hold-bg);border-color:transparent}
.rc-tax.soon{color:var(--hold);background:var(--hold-bg);border-color:transparent}
.rc-line{margin:0.6rem 0 0.4rem;font-size:0.9rem;color:var(--ink)}
.rc-card{margin:0.5rem 0 0;padding:0.5rem 0.7rem;border-radius:8px;border:1px solid var(--line);background:var(--card)}
.rc-card summary{cursor:pointer;font-weight:600;font-size:0.88rem}
.rc-card ul{margin:0.4rem 0 0;padding-left:1.1rem;font-size:0.84rem;color:var(--ink-soft);line-height:1.5}
@media (max-width:640px){.rc-rule-saved{flex-basis:auto}}

/* --- Alert types and the two new review points (6 Oct 2026) --------------- */
.alert-types{display:block;margin:0.3rem 0 0.2rem;padding:0.4rem 0.6rem;border:1px solid var(--line);border-radius:8px;background:var(--card)}
.alert-type{display:flex;align-items:baseline;gap:0.4rem;margin:0.25rem 0;font-size:0.88rem;cursor:pointer}
.alert-type input{margin:0;position:relative;top:1px}
/* A watched stock's own levels (9 Oct 2026). */
.review-point-fields.watch-levels{display:grid;grid-template-columns:1fr;gap:0.45rem;justify-items:start}
.watch-levels label{display:flex;align-items:center;gap:0.4rem;flex-wrap:wrap}
.watch-levels input.rp-level{width:6.5rem;min-width:0;max-width:6.5rem;box-sizing:border-box;padding:0.25rem 0.45rem;border:1px solid var(--line);border-radius:6px;background:var(--card);color:var(--ink);font:inherit;text-align:left;font-variant-numeric:tabular-nums}
.watch-levels input.rp-level:focus{outline:2px solid var(--accent);outline-offset:1px;border-color:var(--accent)}
.watch-ctx .rp-own{color:var(--ink-soft)}
.bought-btn{margin-left:0.3rem}
@media (max-width:640px){#watchlistList .holdings-table td.actions{white-space:normal;width:auto;min-width:7.5rem}#watchlistList td.actions > button{margin:2px 0 2px 4px}}
/* Each alert type on two lines (9 Oct 2026): checkbox and name, then what it covers beneath the name, so a
   phone does not squeeze the name into a narrow column beside the description. */
.alert-type{display:grid;grid-template-columns:auto 1fr;column-gap:0.5rem;row-gap:0.1rem;align-items:baseline;margin:0.45rem 0}
.alert-type .alert-type-what{grid-column:2}
.settings-summary strong{font-weight:600}
.rp-note{display:block;margin:0.2rem 0 0;flex-basis:100%}
.rp-state{max-width:min(100%,22rem);font:inherit;font-size:0.85rem}
.rp-stock{margin:0.7rem 0 0}
.rp-stock summary{cursor:pointer;font-size:0.88rem;color:var(--accent);font-weight:600}
.rp-stock .review-point-box{margin-top:0.4rem}
.rp-current{margin:0.4rem 0 0;font-size:0.9rem}

/* --- Holdings table, compact (7 Oct 2026) --------------------------------
   The company name moved under the stock code and the cost currency under
   the average price, so the table fits a laptop-width panel (measured: it
   fits at 724px and up; it was 870-900px with the two extra columns). */
.holdings-table td.code-cell{min-width:7rem;max-width:9.5rem}
.holdings-table .holding-company{display:block;font-size:0.74rem;color:var(--ink-soft);line-height:1.3;margin-top:0.1rem;white-space:normal}
.holdings-table td.qty-cell input.cell-edit{width:4.6rem;max-width:4.6rem}
.holdings-table .avg-ccy{display:block;font-size:0.68rem;color:var(--ink-soft);line-height:1.25;white-space:nowrap;font-family:var(--num-font);margin-top:0.1rem}
.holdings-table .avg-ccy .ccy-trades{display:block}
.holdings-table td.gain-cell .chip-gain{white-space:normal}
.chip-gain .gain-amt{white-space:nowrap}
.holdings-table td.gain-cell .gain-ccy{display:inline-block;margin:0.15rem 0 0}
.holdings-table td.actions .review-point-toggle{white-space:normal;width:5.6rem;text-align:center;line-height:1.25;vertical-align:middle}

/* --- State badges explain themselves (7 Oct 2026) -------------------------
   Every "Where the chart is" badge is a button that opens what the state
   means, the exact rule, and what it does not tell you, in the same popover
   the glossary uses. */
button.state-badge{font:inherit;font-size:0.75rem;font-weight:600;line-height:1.3;cursor:pointer;text-decoration:underline dotted;text-underline-offset:3px;text-decoration-thickness:1px}
button.state-badge.big{font-size:0.95rem}
button.state-badge:hover{filter:brightness(1.1)}
button.state-badge:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
#termPop .sp-rule,#termPop .sp-not{margin-top:0.45rem;font-size:0.8rem;color:var(--ink-soft)}
#termPop .sp-rule strong,#termPop .sp-not strong{color:var(--ink)}
#termPop .sp-actions{display:flex;flex-wrap:wrap;gap:0.3rem 0.9rem;align-items:baseline;margin-top:0.2rem}
#termPop .sp-actions a,#termPop .sp-actions .learn-link{margin:0.45rem 0 0;padding:0;font-size:0.8rem;color:var(--accent);background:none;border:0;text-decoration:underline;text-underline-offset:2px;cursor:pointer;font-weight:600}

/* --- Reading pages, larger type (7 Oct 2026) ------------------------------
   Learn the terms, How the signals are computed (both #learnContentPanel)
   and Investing principles (#principlesPanel) are read through, not
   scanned. Their text was 14px in the soft grey, sources 12px, labels 11px -
   sizes that suit the dashboard and tire a reader. Here: about 17px in the
   full ink colour, lines held to about 68 characters, and the principle cards
   one to a row so a card is a readable column rather than a narrow strip.
   The dashboard, Holdings and stock pages keep their compact sizes. */
#learnContentPanel .learn-panel-intro,
#principlesPanel .learn-panel-intro{font-size:1.02rem;line-height:1.65;max-width:68ch}
#learnContentPanel .learn-entry summary{font-size:1.06rem;padding:0.85rem 0}
#learnContentPanel .learn-entry p,
#learnContentPanel .learn-entry li{font-size:1.0625rem;line-height:1.7;color:var(--ink);max-width:68ch}
#learnContentPanel .learn-entry p strong{color:var(--ink)}
#learnContentPanel .learn-entry{padding:0.25rem 1.25rem}
#learnContentPanel .learn-group-title{font-size:0.88rem}
#learnContentPanel .learn-group > .footnote{font-size:0.95rem;line-height:1.6;max-width:68ch}
#learnContentPanel .method-list,
#learnContentPanel .method-prose{font-size:1.0625rem;line-height:1.7;max-width:68ch}
#learnContentPanel .method-list{color:var(--ink)}
#learnContentPanel .learn-fullpage-link{font-size:1rem}
#learnContentPanel .learn-reads span{font-size:0.95rem;line-height:1.5}

#principlesPanel .pc-grid{grid-template-columns:1fr;gap:1rem}
#principlesPanel .pcard{padding:1.3rem 1.5rem 1.35rem;gap:0.8rem}
#principlesPanel .pcard h4{font-size:1.3rem;line-height:1.3}
#principlesPanel .pc-principle{font-size:1.0625rem;line-height:1.7;max-width:68ch}
#principlesPanel .pc-quote{padding:0.8rem 1.1rem}
#principlesPanel .pc-quote p{font-size:1.0625rem;line-height:1.6;max-width:66ch}
#principlesPanel .pc-quote footer{font-size:0.875rem;line-height:1.5;margin-top:0.45rem}
#principlesPanel .pc-where{font-size:1rem;line-height:1.65;max-width:70ch;padding-top:0.8rem}
#principlesPanel .pc-where .pc-label{font-size:0.75rem;margin-bottom:0.3rem}
#principlesPanel .pc-theme{font-size:0.88rem;margin-top:2rem}
#principlesPanel > .footnote{font-size:0.95rem;line-height:1.6;max-width:68ch}
#principlesPanel .pc-principle a{color:var(--accent);text-decoration:underline;text-underline-offset:2px}
@media (max-width:520px){
  #learnContentPanel .learn-entry{padding:0.2rem 0.9rem}
  #principlesPanel{padding-left:0.75rem;padding-right:0.75rem}
  #principlesPanel .pcard{padding:1rem 0.95rem 1.1rem}
  #principlesPanel .pc-quote{padding:0.7rem 0.85rem}
  #principlesPanel .pcard h4{font-size:1.18rem}
}

/* Review points reached, in Since your last visit (6 Oct 2026 tier review) */
.chg-rp-list{margin-bottom:0.6rem}
.chg-review .chg-tag{color:var(--accent);border-color:var(--accent)}
.chg-rp-mark{flex:0 0 auto;width:1.4rem;text-align:center;color:var(--accent);font-size:1rem;line-height:1.4}

/* How to get the file from your broker (broker_presets.HOWTO) */
.import-howto{margin:.5rem 0 0;padding:.55rem .75rem;border:1px solid var(--line);border-radius:8px;background:var(--card);font-size:.88rem}
.import-howto summary{cursor:pointer;font-weight:600}
.import-howto ol{margin:.45rem 0 .35rem 1.2rem;padding:0}
.import-howto li{margin:.15rem 0}
.import-howto .footnote{margin:.3rem 0 0}
.import-privacy{margin:.45rem 0 0}

/* One chart-state review point for every holding, and what the four mean (6 Oct 2026) */
.rp-default{display:flex;flex-wrap:wrap;align-items:center;gap:.35rem .7rem;margin:.4rem 0 .6rem;padding:.55rem .75rem;border:1px solid var(--line);border-radius:8px;background:var(--card)}
.rp-default label{font-size:.92rem}
.rp-default .footnote{margin:0;flex:1 1 320px}
.rp-default .rp-explain{flex-basis:100%}
.rp-explain{margin:.45rem 0 0;font-size:.88rem}
.rp-explain summary{cursor:pointer;color:var(--accent)}
.rp-explain dl{margin:.4rem 0 0}
.rp-explain dt{font-weight:600;margin-top:.35rem}
.rp-explain dd{margin:.1rem 0 0 0;line-height:1.45}
.rp-explain .rp-rule{display:block;margin-top:.2rem;font-size:.82rem;color:var(--ink-soft)}

/* A review point reached in the last week, on its Holdings row (6 Oct 2026) */
.rp-reached{display:inline-block;margin-top:.25rem;padding:.1rem .45rem;border-radius:6px;font-size:.74rem;line-height:1.35;
  background:color-mix(in srgb, var(--accent) 14%, transparent);color:var(--accent);border:1px solid color-mix(in srgb, var(--accent) 45%, transparent);text-decoration:none;white-space:normal;max-width:15rem}
.rp-reached:hover{text-decoration:underline}
tr.rp-reached-row > td{background:color-mix(in srgb, var(--accent) 5%, transparent)}
.rp-explain .rp-where{margin:.4rem 0 .2rem;font-size:.86rem}
.rp-explain .rp-group{margin:.7rem 0 .1rem;font-size:.72rem;text-transform:uppercase;letter-spacing:.07em;color:var(--ink-soft);border-top:1px solid var(--line);padding-top:.4rem}
.rp-explain dl .rp-group:first-child{border-top:0;margin-top:.2rem;padding-top:0}
.rp-change{margin-left:.35rem;font-size:.8rem;white-space:nowrap}

/* Reading size (6 Oct 2026). The paragraph under each panel's heading says
   what the panel is and how to read it - it is the text people actually
   read, so it is set just under body size (16px against the 17px root)
   instead of footnote size. Every other footnote went from 13.6px to 15px. */
.panel :is(h2, h3) + p.footnote,
.panel .row-hint,
.rule-grid-note { font-size: 0.95rem; line-height: 1.6; }
@media (max-width: 600px) {
  .panel :is(h2, h3) + p.footnote, .panel .row-hint, .rule-grid-note { font-size: 0.92rem; }
}

/* Your portfolio (6 Oct 2026, app.performance). The headline of the
   dashboard: three totals, four period chips, the index funds beside them,
   who moved the book, then one sortable row per stock. Up and down use the
   same green and red as everywhere else; figures are in the mono face so
   columns line up. */
.perf-up { color: var(--buy); }
.perf-down { color: var(--sell); }
.perf-label { display: block; color: var(--ink-soft); font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.04em; margin-bottom: 0.15rem; }
/* Labels on one line across the top (7 Oct 2026): bottom-aligning put VALUE lower than TODAY and GAIN ON COST. */
.perf-head { display: flex; flex-wrap: wrap; gap: 0.8rem 2.2rem; align-items: flex-start; margin: 0.2rem 0 0.9rem; }
.perf-total { display: flex; flex-direction: column; gap: 0.1rem; font-family: var(--num-font); font-variant-numeric: tabular-nums; }
.perf-big { font-size: 1.9rem; font-weight: 600; line-height: 1.1; }
.perf-mid { font-size: 1.25rem; font-weight: 600; line-height: 1.2; }
.perf-wins { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0.5rem; margin-bottom: 0.9rem; }
.perf-win { border: 1px solid var(--line); border-radius: 8px; padding: 0.5rem 0.65rem; font-family: var(--num-font); font-variant-numeric: tabular-nums; display: flex; flex-direction: column; gap: 0.1rem; }
.perf-win-amount { font-size: 1.05rem; font-weight: 600; line-height: 1.2; }
/* The percentage sits under the amount, a touch smaller, in every header box (7 Oct 2026). */
.perf-pct { font-size: 0.85rem; line-height: 1.2; }
.perf-win-note { font-family: 'Fira Sans', sans-serif; font-size: 0.72rem; color: var(--ink-soft); }
.perf-benches { margin: 0 0 0.9rem; font-size: 0.85rem; }
.perf-bench { display: grid; grid-template-columns: minmax(9rem, 2fr) repeat(5, minmax(3.2rem, 1fr)); gap: 0.4rem; padding: 0.25rem 0; border-bottom: 1px solid var(--line); align-items: center; }
.perf-bench-head { color: var(--ink-soft); font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.04em; }
.perf-bench-cell { text-align: right; font-family: var(--num-font); font-variant-numeric: tabular-nums; }
.perf-movers { display: flex; flex-wrap: wrap; gap: 0.2rem 1rem; align-items: baseline; margin: 0 0 0.5rem; font-size: 0.9rem; }
.perf-movers .perf-label { margin: 0; }
.perf-movers-side { font-family: var(--num-font); font-variant-numeric: tabular-nums; }
.perf-mover { font-weight: 600; color: var(--ink); text-decoration: none; }
.perf-mover:hover, .perf-mover:focus-visible { text-decoration: underline; }
.perf-side { color: var(--ink-soft); font-family: 'Fira Sans', sans-serif; font-size: 0.78rem; margin-right: 0.35rem; }
.perf-cell-sub { display: block; font-size: 0.78rem; margin-top: 0.1rem; }
.perf-movers { flex-direction: column; align-items: stretch; }
/* Movers as a grid (7 Oct 2026): arrow, then three columns of code + amount, aligned across both blocks. */
.perf-mv-grid { display: grid; grid-template-columns: 0.8rem repeat(3, minmax(0, 11rem)); gap: 0.2rem 0.9rem; align-items: baseline; font-family: var(--num-font); font-variant-numeric: tabular-nums; }
.perf-mv-arrow { font-size: 0.7rem; }
.perf-mv-cell { white-space: nowrap; min-width: 0; }
.perf-mv-cell .perf-mover { display: inline-block; min-width: 3.9rem; }
.perf-mv-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.perf-sub { margin: 1.3rem 0 0.4rem; }
.perf-tabs { display: flex; gap: 0.4rem; margin: 0 0 0.5rem; flex-wrap: wrap; }
.perf-tab { border: 1px solid var(--line); background: transparent; color: var(--ink-soft); border-radius: 999px; padding: 0.25rem 0.85rem; font: inherit; font-size: 0.85rem; cursor: pointer; }
/* Selected tab filled, like the Holdings/Watchlist tabs; the "Show" buttons under it stay outlined, so the tab reads as the main choice (7 Oct 2026). */
.perf-tab.active { background: var(--accent); border-color: var(--accent); color: var(--on-accent); font-weight: 600; }
.perf-table td.num { white-space: nowrap; font-variant-numeric: tabular-nums; }
.perf-table th.perf-sortable { cursor: pointer; white-space: nowrap; user-select: none; }
/* Headers wrap onto two lines so the Company tab fits the panel instead of running past it (7 Oct 2026). */
.perf-table th.perf-sortable { white-space: normal; line-height: 1.25; vertical-align: bottom; min-width: 4rem; }
.perf-table th.perf-sortable .term { text-underline-offset: 2px; }
.perf-table td.perf-wrap { white-space: normal; min-width: 5.5rem; }
@media (min-width: 601px) { .perf-table th, .perf-table td { padding-left: 0.4rem; padding-right: 0.4rem; } }
.perf-table th.perf-sortable.sorted { color: var(--ink); }
.perf-foot { margin-top: 0.6rem; }
@media (max-width: 600px) {
  .perf-wins { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .perf-big { font-size: 1.5rem; }
  /* Phone (7 Oct 2026, Sam's screenshot): Value across the top, then Today and
     Gain on cost side by side - the wrapped flex row left Gain on its own
     line under an empty half and Today's label floating above Value's. */
  .perf-head { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.8rem 1rem; align-items: start; }
  .perf-head > .perf-total:first-child { grid-column: 1 / -1; }
  .perf-head .perf-mid { font-size: 1.12rem; overflow-wrap: anywhere; }
  .perf-bench { grid-template-columns: minmax(6.5rem, 2fr) repeat(5, minmax(2.6rem, 1fr)); font-size: 0.78rem; }
}
/* Company tab: the 52-week position as a short track with a dot, beside the number. */
.perf-range { position: relative; display: inline-block; width: 3.2rem; height: 4px; border-radius: 2px; background: var(--line); margin-right: 0.4rem; vertical-align: middle; }
.perf-range span { position: absolute; top: 50%; width: 8px; height: 8px; margin: -4px 0 0 -4px; border-radius: 50%; background: var(--accent); }
.perf-table td:not(.num) { white-space: nowrap; }

/* This week on your stocks (6 Oct 2026, app.happenings): one line per fact,
   the stock code first, the date in the mono face, then the sentence. */
.hap-head { font-size: 0.95rem; margin: 0.9rem 0 0.4rem; }
#happenContent .hap-head:first-child { margin-top: 0; }
.hap-list { list-style: none; margin: 0 0 0.4rem; padding: 0; display: flex; flex-direction: column; gap: 0.35rem; }
.hap-item { line-height: 1.5; padding: 0.35rem 0 0.35rem 0.6rem; border-left: 3px solid var(--line); }
.hap-item.hap-gap, .hap-item.hap-move { border-left-color: #e8b34a; }
.hap-item.hap-insider, .hap-item.hap-short { border-left-color: var(--accent); }
.hap-date { font-family: var(--num-font); font-size: 0.8rem; color: var(--ink-soft); margin: 0 0.35rem; }
.hap-foot { margin: 0.2rem 0 0; }
.chg-details { margin-top: 0.4rem; }
.chg-details > summary { cursor: pointer; color: var(--accent); font-size: 0.9rem; margin-bottom: 0.4rem; }
.hap-item .market-tag { margin: 0 0.15rem 0 0.35rem; }

/* Install app (6 Oct 2026): a quiet pill in the top bar, beside the theme
   switch, on every page until Trendentum runs as an installed app. On a
   phone it shrinks to the icon. */
.install-app-btn { display: inline-flex; align-items: center; gap: 0.35rem; border: 1px solid var(--line); background: transparent; color: var(--ink); border-radius: 999px; padding: 0.3rem 0.8rem; font: inherit; font-size: 0.85rem; cursor: pointer; margin-right: 0.5rem; white-space: nowrap; }
.install-app-btn:hover, .install-app-btn:focus-visible { border-color: var(--accent); color: var(--accent); }
@media (max-width: 600px) { .install-app-btn { padding: 0.3rem 0.55rem; } .install-app-label { display: none; } }
.install-dialog { max-width: 30rem; width: calc(100% - 2rem); border: 1px solid var(--line); border-radius: 12px; padding: 1.2rem 1.4rem; background: var(--card, var(--paper)); color: var(--ink); }
.install-dialog::backdrop { background: rgba(0, 0, 0, 0.55); }
.install-dialog h2 { margin: 0 0 0.5rem; font-size: 1.15rem; }
.install-dialog-lead { margin: 0 0 0.6rem; line-height: 1.55; }
.install-dialog ol { margin: 0; padding-left: 1.3rem; display: flex; flex-direction: column; gap: 0.45rem; line-height: 1.55; }
.install-dialog-actions { display: flex; justify-content: flex-end; margin-top: 1rem; }
.install-dialog-close { border: 0; border-radius: 999px; padding: 0.45rem 1.2rem; background: var(--accent); color: #081322; font: inherit; font-weight: 600; cursor: pointer; }

/* Your portfolio on a phone (6 Oct 2026, from Sam's screenshot at ~390px):
   the index-fund grid ran past the panel (YTD cut off), a mover's code and
   its amount split across lines, and the stock code scrolled away with the
   table. */
.perf-mover-item { white-space: nowrap; }
.perf-bench { grid-template-columns: minmax(0, 2fr) repeat(5, minmax(0, 1fr)); }
.perf-bench-name { min-width: 0; overflow-wrap: anywhere; }
.perf-table th:first-child, .perf-table td:first-child { position: sticky; left: 0; z-index: 1; background: var(--card); }
@media (max-width: 600px) {
  .perf-bench { grid-template-columns: minmax(0, 1.5fr) repeat(5, minmax(0, 1fr)); gap: 0.25rem; font-size: 0.72rem; }
  .perf-bench-cell { letter-spacing: -0.02em; }
  .perf-bench-head { font-size: 0.62rem; letter-spacing: 0.02em; }
  .perf-bench-name .market-tag { display: block; }
  .perf-movers { font-size: 0.85rem; }
  .perf-mv-grid { grid-template-columns: 0.9rem repeat(3, minmax(0, 1fr)); gap: 0.35rem 0.6rem; }
  .perf-mv-cell .perf-mover { display: block; min-width: 0; }
  .perf-table td:first-child { box-shadow: 4px 0 6px -4px rgba(0, 0, 0, 0.35); }
}

/* Portfolio page on a phone (6 Oct 2026, Sam's screenshots at ~390px). A
   <select> is as wide as its longest option, so the "Tell me, for every
   holding" menu ran out of its box; it now fills the line and never more.
   The holdings and watchlist tables keep the stock column on screen while
   the rest scrolls sideways. */
.rp-default label { display: flex; flex-wrap: wrap; align-items: center; gap: 0.35rem 0.5rem; min-width: 0; max-width: 100%; }
.rp-default select { flex: 1 1 14rem; min-width: 0; max-width: 100%; width: auto; text-overflow: ellipsis; }
@media (max-width: 600px) {
  .rp-default { padding: 0.55rem 0.6rem; }
  .rp-default label, .rp-default select { width: 100%; }
  .holdings-table th:first-child, .holdings-table td:first-child { position: sticky; left: 0; z-index: 1; background: var(--card); box-shadow: 4px 0 6px -4px rgba(0, 0, 0, 0.25); }
  .holdings-table td:first-child { min-width: 7.5rem; max-width: 9rem; }
}

/* Numbers (6 Oct 2026, Sam: "I prefer CMC fonts"). Figures were set in Fira
   Code, a programmer's monospace: every digit the width of an "M", which read
   like code and pushed tables past a phone screen. They are now Inter - the
   proportional sans most trading apps use - with tabular figures, so digits
   still line up down a column without the monospace width. Body text stays
   Fira Sans. */
:root { --num-font: 'Inter', 'Fira Sans', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif; }
body, table, input, select, button { font-variant-numeric: tabular-nums; }
code { font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace; }
/* "These figures were loaded at ..." - shown instead of an automatic reload when something typed is unsaved (7 Oct 2026). */
#staleBar { position: fixed; left: 50%; bottom: 16px; transform: translateX(-50%); z-index: 70; max-width: calc(100% - 32px); background: var(--card); color: var(--ink); border: 1px solid var(--line); border-radius: 10px; box-shadow: 0 8px 24px rgba(0,0,0,0.25); padding: 0.55rem 0.9rem; font-size: 0.9rem; display: flex; gap: 0.6rem; align-items: center; flex-wrap: wrap; }
/* Phone: one picked column instead of a sideways-scrolling table (7 Oct 2026). */
.perf-pick { display: flex; flex-wrap: wrap; align-items: center; gap: 0.35rem; margin: 0 0 0.5rem; }
.perf-pick-label { font-size: 0.75rem; color: var(--ink-soft); text-transform: uppercase; letter-spacing: 0.04em; margin-right: 0.15rem; }
.perf-pick-btn { border: 1px solid var(--line); background: transparent; color: var(--ink-soft); border-radius: 999px; padding: 0.15rem 0.6rem; font: inherit; font-size: 0.8rem; cursor: pointer; }
.perf-pick-btn.active { border-color: var(--accent); color: var(--ink); font-weight: 600; }
/* "Your stocks" column headers stay in view while its rows scroll (7 Oct 2026),
   under the site header when that is pinned (--sticky-top, measured in app.js).
   Only when the table fits: .fits releases the sideways-scroll box, otherwise
   the header would pin to that box instead of the page. */
#perfStocks .table-scroll.fits { overflow: visible; }
#perfStocks .table-scroll.fits .perf-table thead th { position: sticky; top: var(--sticky-top, 0px); z-index: 3; background: var(--card); box-shadow: inset 0 -1px 0 var(--line); }
/* "Where the chart is", rebuilt 7 Oct 2026: the prices that matter, "tell me when", and the record as a plain comparison. */
.cs-levels { margin: 0.2rem 0 0.8rem; }
.cs-level-list { list-style: none; margin: 0.3rem 0 0; padding: 0; display: grid; gap: 0.45rem; }
.cs-level-list li { display: grid; grid-template-columns: 10rem minmax(0, 1fr); gap: 0.2rem 0.8rem; align-items: baseline; }
.cs-lv { font-family: var(--num-font); font-weight: 600; white-space: nowrap; }
.cs-lv.up { color: var(--buy); } .cs-lv.down { color: var(--sell); } .cs-lv.flat { color: var(--ink); } .cs-lv.vol { color: var(--ink-soft); font-family: inherit; text-transform: uppercase; font-size: 0.78rem; letter-spacing: 0.04em; }
.cs-notify { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem 0.8rem; }
.cs-notify .footnote { margin: 0; }
.cs-notify-btn { background: var(--accent); color: var(--on-accent); border: 1px solid var(--accent); border-radius: 8px; padding: 0.45rem 0.9rem; font: inherit; font-weight: 600; cursor: pointer; }
.cs-notify-btn:hover, .cs-notify-btn:focus-visible { filter: brightness(1.08); }
.cs-notify-on { margin: 0; color: var(--buy); font-weight: 600; }
.cs-lead { margin: 0.2rem 0 0.2rem; }
.cs-followed { margin: 0 0 0.4rem; padding-left: 1.1rem; display: grid; gap: 0.2rem; }
.cs-followed strong { font-family: var(--num-font); }
.cs-sum { margin: 0.1rem 0 0.6rem; font-weight: 600; }
.cs-plan { margin: 0.4rem 0 0.3rem; }
.cs-plan a { font-weight: 600; color: var(--accent); }
@media (max-width: 600px) { .cs-level-list li { grid-template-columns: minmax(0, 1fr); } }
/* "Why these can differ from your broker's figures" under the portfolio header (7 Oct 2026). */
.perf-why { margin: -0.3rem 0 0.9rem; font-size: 0.9rem; }
.perf-why summary { cursor: pointer; color: var(--accent); font-size: 0.88rem; }
.perf-why ul { margin: 0.5rem 0 0; padding-left: 1.1rem; display: grid; gap: 0.35rem; color: var(--ink-soft); }
.perf-why strong { color: var(--ink); font-weight: 600; }
/* Help (7 Oct 2026): the button on every page, the form, the "tell us" links. */
.help-fab { position: fixed; right: 16px; bottom: 16px; z-index: 65; display: inline-flex; align-items: center; gap: 0.4rem; padding: 0.5rem 0.9rem 0.5rem 0.55rem; border-radius: 999px; border: 1px solid var(--line); background: var(--card); color: var(--ink); font: inherit; font-weight: 600; font-size: 0.9rem; box-shadow: 0 6px 20px rgba(0,0,0,0.25); cursor: pointer; }
.help-fab:hover, .help-fab:focus-visible { border-color: var(--accent); }
.help-fab-q { display: inline-grid; place-items: center; width: 1.45rem; height: 1.45rem; border-radius: 50%; background: var(--accent); color: var(--on-accent); font-weight: 700; font-size: 0.85rem; }
@media (max-width: 600px) { .help-fab { padding: 0.45rem; bottom: 12px; right: 12px; } .help-fab-label { display: none; } }
@media print { .help-fab { display: none; } }
.help-dialog { border: 1px solid var(--line); border-radius: 12px; background: var(--card); color: var(--ink); padding: 0; width: min(520px, calc(100vw - 32px)); box-shadow: 0 20px 60px rgba(0,0,0,0.4); }
.help-dialog::backdrop { background: rgba(0,0,0,0.45); }
.help-form { display: grid; gap: 0.7rem; padding: 1rem 1.1rem 1.1rem; }
.help-head { display: flex; justify-content: space-between; align-items: center; gap: 0.5rem; }
.help-head h3 { margin: 0; font-size: 1.1rem; }
.help-x { border: 0; background: transparent; color: var(--ink-soft); font-size: 1.5rem; line-height: 1; cursor: pointer; padding: 0 0.2rem; }
.help-field { display: grid; gap: 0.3rem; font-weight: 600; font-size: 0.9rem; }
.help-field select, .help-field textarea, .help-field input { font: inherit; font-weight: 400; padding: 0.5rem 0.6rem; border: 1px solid var(--line); border-radius: 8px; background: var(--paper); color: var(--ink); }
.help-field textarea { resize: vertical; min-height: 6rem; }
.help-form .help-tech { display: block; margin: 0; font-size: 0.88rem; font-weight: 400; }
.help-tech input { margin: 0 0.4rem 0 0; vertical-align: -2px; }
.help-tech .footnote { display: inline; margin: 0; }
.help-actions { display: flex; align-items: center; gap: 0.8rem; flex-wrap: wrap; }
.help-to, .help-promise { margin: 0; }
.help-link { font-size: inherit; }
.adm-pre { font-size: 0.75rem; max-height: 16rem; overflow: auto; background: var(--paper); border: 1px solid var(--line); border-radius: 6px; padding: 0.5rem; white-space: pre-wrap; }
.adm-ticket { margin: 0.5rem 0; }

.help-optional { font-weight: 400; margin: 0; }

/* "What Trendentum doesn't cover" on the Pro page (8 Oct 2026) - set expectations before checkout */
.pro-limits { margin: 1.4rem 0 0; padding: 1rem 1.2rem; border: 1px solid var(--line); border-radius: 10px; }
.pro-limits h3 { margin: 0 0 0.3rem; }
.pro-limits ul { margin: 0.6rem 0; padding-left: 1.1rem; line-height: 1.55; }
.pro-limits li { margin: 0 0 0.45rem; }
.pro-limits-link { display: block; margin: 0.5rem 0 0; }

/* The company section on the stock page (8 Oct 2026, app.company_profile): one fact, one place, nothing scored */
.co-head { display: flex; align-items: baseline; justify-content: space-between; gap: 0.6rem; flex-wrap: wrap; margin-bottom: 0.6rem; }
.co-head h2 { margin: 0; }
.co-head .footnote { margin: 0; }
.co-about { margin: 0 0 0.8rem; }
.co-desc { margin: 0; line-height: 1.55; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.co-desc.open { display: block; -webkit-line-clamp: unset; }
.co-more { margin: 0.2rem 0 0; font-size: 0.85rem; }
.co-chips { display: flex; flex-wrap: wrap; gap: 0.35rem; margin: 0.5rem 0 0; }
.co-chip { font-size: 0.8rem; padding: 0.15rem 0.55rem; border: 1px solid var(--line); border-radius: 999px; color: var(--ink-soft); text-decoration: none; }
a.co-chip:hover { color: var(--accent); border-color: var(--accent); }
.co-h { margin: 0.9rem 0 0.3rem; font-size: 1rem; }
.co-glance { margin: 0; padding-left: 1.1rem; line-height: 1.6; }
.co-glance li { margin: 0 0 0.25rem; }
.co-wait { margin: 0.5rem 0 0; }
.co-parts { margin: 0.9rem 0 0; display: flex; flex-direction: column; gap: 0.5rem; }
.co-part { border: 1px solid var(--line); border-radius: 10px; padding: 0.55rem 0.8rem; }
.co-part > summary { cursor: pointer; font-weight: 600; }
.co-part[open] > summary { margin-bottom: 0.6rem; }
.co-scroll { overflow-x: auto; }
.co-table { border-collapse: collapse; width: 100%; font-size: 0.9rem; font-variant-numeric: tabular-nums; }
.co-table th, .co-table td { padding: 0.35rem 0.5rem; text-align: right; border-bottom: 1px solid var(--line); white-space: nowrap; }
.co-table th:first-child, .co-table th[scope="row"] { text-align: left; white-space: normal; }
.co-table thead th { font-weight: 600; color: var(--ink-soft); font-size: 0.8rem; }
.co-table .up { color: var(--buy); }
.co-table .down { color: var(--sell); }
.co-table tr.co-self th, .co-table tr.co-self td { background: var(--accent-bg); font-weight: 600; }
.co-svg { width: 100%; height: auto; display: block; margin: 0.2rem 0 0.4rem; }
.co-svg .co-axis { stroke: var(--line); stroke-width: 1; }
.co-svg .co-bar-rev { fill: var(--ink-soft); opacity: 0.45; }
.co-svg .co-bar-ni { fill: var(--buy); }
.co-svg .co-bar-loss { fill: var(--sell); }
.co-svg .co-bar-div { fill: var(--accent); }
.co-svg .co-bar-part { fill: var(--accent); opacity: 0.4; }
.co-svg .co-bar-val { fill: var(--ink-soft); font-size: 11px; font-variant-numeric: tabular-nums; }
.co-svg .co-bar-year { fill: var(--ink-soft); font-size: 11px; }
.co-legend { display: flex; flex-wrap: wrap; align-items: center; gap: 0.35rem 0.8rem; font-size: 0.8rem; color: var(--ink-soft); }
.co-key { display: inline-block; width: 0.8rem; height: 0.8rem; border-radius: 2px; margin-right: -0.4rem; vertical-align: -1px; }
.co-key-rev { background: var(--ink-soft); opacity: 0.45; }
.co-key-ni { background: var(--buy); }
.co-key-loss { background: var(--sell); }
.co-words { margin: 0.3rem 0 0.5rem; line-height: 1.5; }
.co-dl { margin: 0.2rem 0 0.4rem; display: grid; gap: 0.35rem; }
.co-dl > div { display: grid; grid-template-columns: minmax(8rem, 11rem) 1fr; gap: 0.6rem; align-items: baseline; }
.co-dl dt { color: var(--ink-soft); font-size: 0.88rem; }
.co-dl dd { margin: 0; font-variant-numeric: tabular-nums; }
.co-note { margin: 0.7rem 0 0; }
@media (max-width: 600px) {
  .co-dl > div { grid-template-columns: 1fr; gap: 0.1rem; }
}
#stockSnapshotContent:not(:empty) { margin: 0 0 1rem; padding: 0 0 0.9rem; border-bottom: 1px solid var(--line); }
#stockSnapshotContent .snap-earnings:last-child { margin-bottom: 0; }
.co-part .footnote { margin: 0.4rem 0 0; }
@media (max-width: 600px) {
  .co-svg { min-width: 480px; }
  .co-svg .co-bar-val, .co-svg .co-bar-year { font-size: 12px; }
}
/* Company section as one list (8 Oct 2026 review): each line states its figures once; opening it adds only new ones */
.co-rows { display: flex; flex-direction: column; border-top: 1px solid var(--line); margin: 0.4rem 0 0; }
.co-row { border-bottom: 1px solid var(--line); }
.co-row > summary, .co-row-flat { display: grid; grid-template-columns: 7.5rem 1fr auto; gap: 0.7rem; align-items: baseline; padding: 0.6rem 0.2rem; line-height: 1.5; }
.co-row > summary { cursor: pointer; list-style: none; }
.co-row > summary::-webkit-details-marker { display: none; }
.co-row > summary::after { content: "Show"; font-size: 0.78rem; color: var(--accent); white-space: nowrap; }
.co-row[open] > summary::after { content: "Hide"; }
.co-row-flat { grid-template-columns: 7.5rem 1fr; }
.co-row > summary:hover .co-line { color: var(--ink); }
.co-label { font-size: 0.78rem; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: var(--ink-soft); }
.co-line .footnote { margin: 0; }
.co-body { padding: 0 0.2rem 0.8rem calc(7.5rem + 0.9rem); }
.co-sub { margin: 0 0 0.4rem; font-size: 0.88rem; color: var(--ink-soft); }
.stock-notes:not(:empty) { margin: 0 0 1rem; padding: 0.7rem 1rem; border: 1px solid var(--line); border-radius: 12px; background: var(--card); }
.stock-notes .snap-earnings:last-child { margin-bottom: 0; }
#stockRangeContent:not(:empty) { margin: 0.8rem 0 0; }
.stock-regime-line .footnote { margin: 0.8rem 0 0; }
@media (max-width: 600px) {
  .co-row > summary, .co-row-flat { grid-template-columns: 1fr auto; gap: 0.15rem 0.6rem; }
  .co-row-flat { grid-template-columns: 1fr; }
  .co-label { grid-column: 1 / -1; }
  .co-body { padding-left: 0.2rem; }
}
.co-body .footnote { margin: 0.4rem 0 0; }
/* The stock page's title section (8 Oct 2026, Sam's order): last close, the day's change, market value, market conditions, dated notes */
.stock-quote:not(:empty) { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.4rem 1.4rem; margin: 0.8rem 0 0; }
.stock-quote-price { font-size: 1.6rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.stock-quote-change { font-weight: 600; font-variant-numeric: tabular-nums; margin-left: 0.35rem; }
.stock-quote-change.up { color: var(--buy); }
.stock-quote-change.down { color: var(--sell); }
.stock-quote .footnote { margin: 0 0 0 0.35rem; }
.stock-quote-cap .footnote { margin: 0; }
.stock-quote-cap strong { font-variant-numeric: tabular-nums; }
#stockHeaderPanel .stock-regime-line .footnote { margin: 0.6rem 0 0; }
#stockHeaderPanel .stock-notes:not(:empty) { margin: 0.8rem 0 0; padding: 0.7rem 0 0; border: 0; border-top: 1px solid var(--line); border-radius: 0; background: none; }
/* Past outlooks as stretches (8 Oct 2026) */
.op-list { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--line); }
.op-row { display: grid; grid-template-columns: 6.5rem minmax(11rem, 1fr) auto; gap: 0.3rem 0.8rem; align-items: baseline; padding: 0.5rem 0.2rem; border-bottom: 1px solid var(--line); font-variant-numeric: tabular-nums; }
.op-badge { font-size: 0.8rem; font-weight: 600; padding: 0.1rem 0.55rem; border-radius: 999px; justify-self: start; border: 1px solid var(--line); }
.op-badge.pos { color: var(--buy); background: var(--buy-bg); border-color: var(--buy); }
.op-badge.neg { color: var(--sell); background: var(--sell-bg); border-color: var(--sell); }
.op-badge.mix { color: var(--hold); background: var(--hold-bg); border-color: var(--hold); }
.op-current .op-when { font-weight: 600; }
.op-what { text-align: right; }
.op-what .footnote { margin: 0; }
.op-move.up { color: var(--buy); }
.op-move.down { color: var(--sell); }
@media (max-width: 600px) {
  .op-row { grid-template-columns: auto 1fr; }
  .op-what { grid-column: 1 / -1; text-align: left; }
}

  /* On a phone the three reading boxes would repeat the list just above them (8 Oct 2026). */
  @media (max-width: 560px) {
    .signal-radar-col:has(.rd-glance) { display: none; }
  }

/* Your reasons (8 Oct 2026): the person's own record - investment or speculation, Lynch's kind of company,
   why it is here and what would make them sell. Their words lead; everything else is quiet. */
.reasons-panel .rs-intro{margin:0 0 0.9rem;max-width:62ch;color:var(--ink-soft);line-height:1.55}
.rs-edit{display:grid;gap:0.9rem;max-width:720px}
.rs-field{display:grid;gap:0.35rem}
.rs-label{font-size:0.72rem;font-weight:700;letter-spacing:0.07em;text-transform:uppercase;color:var(--ink-soft)}
.rs-radios{display:flex;flex-wrap:wrap;gap:0.4rem 1.1rem}
.rs-radio{display:inline-flex;align-items:center;gap:0.35rem;font-size:0.92rem;color:var(--ink)}
.rs-field .footnote{margin:0;max-width:66ch}
.rs-field select.cell-edit{max-width:240px}
.rs-text{width:100%;box-sizing:border-box;font:inherit;font-size:0.94rem;line-height:1.5;padding:0.55rem 0.65rem;border:1px solid var(--line);border-radius:6px;background:var(--card);color:var(--ink);resize:vertical}
.rs-text:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
/* Lynch's six kinds as described choices (Sam, 8 Oct 2026: a dropdown hid what each one means). */
.rs-kinds{border:0;margin:0;padding:0;min-width:0}
.rs-kinds legend{padding:0;margin-bottom:0.35rem}
.rs-kind-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0.5rem;margin-top:0.2rem}
.rs-kind{display:flex;align-items:flex-start;gap:0.55rem;padding:0.55rem 0.7rem;border:1px solid var(--line);border-radius:8px;cursor:pointer;color:var(--ink)}
.rs-kind:hover{border-color:var(--ink-soft)}
.rs-kind:has(input:checked){border-color:var(--accent);box-shadow:inset 0 0 0 1px var(--accent)}
.rs-kind:has(input:focus-visible){outline:2px solid var(--accent);outline-offset:2px}
.rs-kind input{margin:0.2rem 0 0;flex:none;accent-color:var(--accent)}
.rs-kind strong{display:block;font-size:0.92rem}
.rs-kind-about{display:block;margin-top:0.1rem;font-size:0.82rem;line-height:1.45;color:var(--ink-soft)}
@media (max-width:560px){.rs-kind-grid{grid-template-columns:1fr}}
.rs-actions{display:flex;align-items:center;gap:0.6rem;flex-wrap:wrap}
.rs-view{display:grid;gap:0.75rem;max-width:720px}
.rs-chips{display:flex;flex-wrap:wrap;gap:0.4rem}
.rs-chip{display:inline-block;padding:0.2rem 0.6rem;border:1px solid var(--line);border-radius:999px;font-size:0.78rem;font-weight:600;color:var(--ink)}
.rs-chip.rs-speculation{border-color:#d97706;color:#d97706}
.rs-chip.rs-investment{border-color:var(--accent);color:var(--accent)}
.rs-block p{margin:0.2rem 0 0;font-size:1rem;line-height:1.6;color:var(--ink);white-space:pre-line}
.rs-reread{margin:0;padding:0.5rem 0.7rem;border-left:3px solid #d97706;font-size:0.9rem;color:var(--ink)}
.rs-foot{margin:0}
.spec-tag{display:inline-block;margin-left:0.35rem;padding:0 0.4rem;border:1px solid #d97706;border-radius:999px;font-size:0.66rem;font-weight:700;letter-spacing:0.04em;text-transform:uppercase;color:#d97706;vertical-align:middle}
.spec-line{margin:0.7rem 0 0;font-size:0.9rem;color:var(--ink)}
.spec-line.over strong{color:#d97706}
.spec-cap-label{margin-left:0.4rem;font-size:0.85rem;color:var(--ink-soft);white-space:nowrap}
.spec-cap-label input.cell-edit{width:56px;min-width:0;max-width:56px;padding:0.15rem 0.35rem;font-size:0.85rem;margin:0 0.15rem}

/* Through Graham's, Fisher's and Lynch's eyes (8 Oct 2026). Neutral markers - within / outside a published
   line, or can't tell - never a tick, a cross or a total. */
.iv-lede{margin:0 0 0.35rem;max-width:72ch;font-size:0.94rem;line-height:1.55;color:var(--ink)}
.iv-years{margin:0 0 0.8rem}
.iv-blocks{display:flex;flex-direction:column;border-top:1px solid var(--line)}
.iv-block{border-bottom:1px solid var(--line)}
.iv-block>summary{display:flex;align-items:baseline;gap:0.75rem;padding:0.75rem 0.2rem;cursor:pointer;list-style:none}
.iv-block>summary::-webkit-details-marker{display:none}
.iv-block>summary::after{content:"Show";margin-left:auto;font-size:0.78rem;color:var(--accent);white-space:nowrap}
.iv-block[open]>summary::after{content:"Hide"}
.iv-block>summary:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.iv-who{font-weight:700;font-size:1.02rem;color:var(--ink);min-width:4.2rem}
.iv-what{font-size:0.9rem;color:var(--ink-soft)}
.iv-inner{padding:0 0.2rem 0.9rem}
.iv-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:0.85rem}
.iv-item{display:grid;grid-template-columns:8.2rem 1fr;gap:0.8rem;align-items:start}
.iv-list:not(:has(.iv-mark)) .iv-item{grid-template-columns:1fr}
.iv-mark{display:inline-block;justify-self:start;padding:0.15rem 0.55rem;border-radius:999px;font-size:0.72rem;font-weight:600;white-space:nowrap;border:1px solid var(--line);color:var(--ink-soft)}
.iv-mark.iv-in{border-color:var(--accent);color:var(--accent)}
.iv-mark.iv-out{border-color:var(--ink-soft);color:var(--ink)}
.iv-mark.iv-na{border-style:dashed}
.iv-body{display:grid;gap:0.15rem;min-width:0}
.iv-title{font-weight:600;font-size:0.94rem;color:var(--ink)}
.iv-value{font-size:0.94rem;line-height:1.5;color:var(--ink);font-variant-numeric:tabular-nums}
.iv-rule{font-size:0.82rem;line-height:1.45;color:var(--ink-soft)}
.iv-note{font-size:0.82rem;line-height:1.45;color:var(--ink-soft);font-style:italic}
.iv-src{margin:0.8rem 0 0}
.iv-sub{margin-top:1.1rem;padding-top:0.9rem;border-top:1px dashed var(--line);display:grid;gap:0.45rem}
.iv-intro{margin:0;font-size:0.88rem;line-height:1.5;color:var(--ink-soft);max-width:70ch}
.iv-qs{margin:0.2rem 0 0;padding-left:1.8rem;display:flex;flex-direction:column;gap:0.6rem}
.iv-qs li{font-size:0.92rem;line-height:1.45;color:var(--ink)}
.iv-qs li::marker{color:var(--ink-soft);font-variant-numeric:tabular-nums}
.iv-q{display:block}
.iv-mine{margin-top:0.25rem;display:flex;flex-wrap:wrap;align-items:baseline;gap:0.4rem;font-size:0.88rem;color:var(--ink-soft)}
.iv-answer{display:flex;flex-wrap:wrap;gap:0.4rem;margin-top:0.3rem}
.iv-answer select.cell-edit{width:auto;min-width:9rem}
.iv-answer .iv-note-in{flex:1 1 14rem;min-width:0;width:auto}
.iv-watch{margin-top:1rem;padding:0.55rem 0.75rem;border-left:3px solid var(--accent)}
.iv-watch p{margin:0.2rem 0 0;font-size:0.92rem;line-height:1.5;color:var(--ink)}
.iv-more{margin:0.8rem 0 0}
@media (max-width:560px){
  .iv-item{grid-template-columns:1fr;gap:0.3rem}
  .iv-block>summary{flex-wrap:wrap;gap:0.2rem 0.6rem}
}

/* The sector screen's investors' tests (8 Oct 2026): a tab beside the price readings, Graham's lines as
   tick-boxes the person sets. No column adds anything up. */
.sc-tabs{display:flex;gap:0.3rem;margin:0.4rem 0 0.7rem;border-bottom:1px solid var(--line)}
.sc-tab{font:inherit;font-size:0.88rem;padding:0.45rem 0.8rem;border:0;border-bottom:2px solid transparent;background:transparent;color:var(--ink-soft);cursor:pointer;margin-bottom:-1px}
.sc-tab.on{color:var(--ink);font-weight:600;border-bottom-color:var(--accent)}
.sc-tab:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.sc-graham{border:1px solid var(--line);border-radius:8px;padding:0.5rem 0.75rem 0.6rem;margin:0.5rem 0;display:flex;flex-wrap:wrap;gap:0.35rem 1rem;align-items:center;font-size:0.84rem;color:var(--ink)}
.sc-graham legend{padding:0 0.3rem;font-size:0.72rem;font-weight:700;letter-spacing:0.07em;text-transform:uppercase;color:var(--ink-soft)}
.sc-line{display:inline-flex;align-items:center;gap:0.35rem;white-space:nowrap}
.sc-line input{accent-color:var(--accent)}
.screen-filters input.sc-num{width:4.5rem}
.sc-sub{display:block;font-size:0.72rem;color:var(--ink-soft);margin-top:0.1rem}
.sc-site{white-space:nowrap;font-size:0.82rem}
.stock-quote-site{font-size:0.86rem;white-space:nowrap}
#screenTable .sc-name{min-width:11rem}
.iv-compare{margin:0 0 0.9rem;padding:0.55rem 0.75rem;border:1px solid var(--line);border-radius:8px;font-size:0.92rem}
.iv-compare a{font-weight:600}
.sector-index-tabs{display:flex;flex-wrap:wrap;gap:0.4rem;margin:0.4rem 0 0.9rem}

/* The stock page's sticky bar (9 Oct 2026): look up another stock, jump to a section, and - once the title
   section has scrolled away - which stock this is. One slim bar instead of a lookup box at the top and bottom. */
.stock-bar{position:sticky;top:var(--sticky-top,0px);z-index:6;margin:0 0 1rem;padding:0.6rem 0.9rem 0.45rem;background:var(--card);border:1px solid var(--line);border-radius:12px;box-shadow:0 6px 18px -14px rgba(0,0,0,0.5)}
.sb-row{display:flex;align-items:center;gap:0.6rem 0.8rem;flex-wrap:wrap}
.sb-id{display:flex;align-items:baseline;gap:0.55rem;min-width:0;flex:1 1 auto;overflow:hidden;white-space:nowrap}
.sb-id[hidden]{display:none}
.sb-id .ticker-code{font-size:1.02rem}
.sb-name{color:var(--ink-soft);font-size:0.86rem;overflow:hidden;text-overflow:ellipsis;min-width:0}
.sb-price{font-weight:650;font-variant-numeric:tabular-nums}
.sb-chg{font-size:0.86rem;font-variant-numeric:tabular-nums}
.sb-chg.up{color:var(--buy)}
.sb-chg.down{color:var(--sell)}
.sb-search{flex:1 1 14rem;max-width:26rem;margin-left:auto}
.sb-search input{width:100%;box-sizing:border-box}
.sb-go{flex:none}
.sb-jump{display:flex;gap:0.35rem;overflow-x:auto;scrollbar-width:none;margin:0.5rem -0.2rem 0;padding:0.1rem 0.2rem 0.15rem}
.sb-jump::-webkit-scrollbar{display:none}
.sb-jump:empty{display:none}
.sb-jump a{flex:0 0 auto;padding:0.22rem 0.65rem;border:1px solid var(--line);border-radius:999px;font-size:0.78rem;color:var(--ink-soft);text-decoration:none;white-space:nowrap}
.sb-jump a:hover{color:var(--ink);border-color:var(--ink-soft)}
.sb-jump a:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.sb-jump a.is-active{background:var(--accent);border-color:var(--accent);color:var(--card)}
#stockBody section.panel,#stockHeaderPanel{scroll-margin-top:calc(var(--sticky-top,0px) + var(--stock-bar-h,96px) + 12px)}
@media (max-width:640px){
  .stock-bar{padding:0.5rem 0.6rem 0.4rem;border-radius:10px}
  .sb-name{display:none}
  .sb-id{flex:1 1 100%}
  .sb-search{flex:1 1 0;max-width:none;margin-left:0}
}
@media (max-width:640px){
  .stock-bar .sb-search input{padding-top:0.45rem;padding-bottom:0.45rem;font-size:0.92rem}
  .stock-bar .sb-go{padding:0.45rem 0.85rem;font-size:0.9rem}
  .stock-bar .sb-jump{margin-top:0.4rem}
}
#screenTable tr.sc-pending td{color:var(--ink-soft)}

/* Market and sector picker on a sector's page (9 Oct 2026) */
.sector-picker{display:grid;gap:0.45rem;margin:0 0 1.1rem;padding:0 0 0.9rem;border-bottom:1px solid var(--line)}
.sp-row{display:flex;align-items:flex-start;gap:0.6rem}
.sp-label{flex:0 0 3.6rem;padding-top:0.28rem;font-size:0.72rem;font-weight:700;letter-spacing:0.07em;text-transform:uppercase;color:var(--ink-soft)}
.sp-chips{display:flex;flex-wrap:wrap;gap:0.3rem;min-width:0}
a.sector-tab.sp-link{display:inline-block;border:1px solid var(--line);border-radius:4px;color:var(--ink);text-decoration:none;white-space:nowrap}
a.sector-tab.sp-link:hover{border-color:var(--ink-soft)}
a.sector-tab.sp-link:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
a.sector-tab.sp-link.active{background:var(--accent);border-color:var(--accent);color:var(--on-accent,#fff);font-weight:600}
@media (max-width:640px){
  .sp-row{flex-direction:column;gap:0.25rem}
  .sp-label{padding-top:0;flex:none}
  .sp-chips{flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none;max-width:100%;padding-bottom:0.15rem}
  .sp-chips::-webkit-scrollbar{display:none}
}

/* Speculative checks (9 Oct 2026): a highlighted figure gets an amber rule, never a mark or a score. */
.iv-item.iv-spec{grid-template-columns:1fr;padding-left:0.75rem;border-left:3px solid transparent}
.iv-item.iv-spec.iv-flag{border-left-color:#d97706}
#screenTable .sc-short{color:#b45309;font-weight:600}
.sector-picker{grid-template-columns:minmax(0,1fr)}.sp-row{min-width:0}
.stock-follow p{margin:0 0 0.6rem;max-width:72ch;line-height:1.55}.stock-follow p:last-child{margin:0}

/* Investor school (9 Oct 2026) */
.lesson{margin:1.2rem 0 0;padding:1.1rem 1.2rem 1rem;border:1px solid var(--line);border-radius:12px;background:var(--card);display:grid;gap:0.7rem;max-width:820px;scroll-margin-top:calc(var(--sticky-top,0px) + 3.6rem)}
.lesson h3{margin:0;font-size:1.25rem;line-height:1.3}
.lesson > p{margin:0;font-size:0.97rem;line-height:1.65;color:var(--ink);max-width:70ch}
.ls-kicker{font-size:0.72rem !important;font-weight:700;letter-spacing:0.08em;text-transform:uppercase;color:var(--ink-soft) !important}
.ls-try{padding:0.7rem 0.85rem;border-radius:8px;background:var(--paper);border:1px dashed var(--accent);font-size:0.92rem;line-height:1.55;color:var(--ink)}
.ls-try .pc-label{display:block;font-size:0.68rem;font-weight:700;letter-spacing:0.08em;text-transform:uppercase;color:var(--accent);margin-bottom:0.25rem}
.ls-done{display:inline-flex;align-items:center;gap:0.45rem;font-size:0.86rem;color:var(--ink-soft);cursor:pointer;justify-self:start}
.ls-done input{accent-color:var(--accent)}
.lesson.is-done{border-color:var(--accent)}
#pcJump a.is-done:not(.is-active){border-color:var(--accent)}
#pcJump a .pc-jump-n{margin-right:0.1rem}
.sc-progress{margin:0 0 0.4rem}
#schoolPanel .pc-jump{flex-wrap:nowrap;overflow-x:auto}
@media (min-width:721px){#schoolPanel .pc-jump{flex-wrap:nowrap;overflow-x:auto}}
/* Lesson bar arrows (9 Oct 2026): app.js wraps the bar in a shell that takes over the sticky position, and adds
   an arrow with a fade at whichever end has more chips hidden. */
.pc-jump-shell{position:sticky;top:var(--sticky-top,0px);z-index:5}
.pc-jump-shell > .pc-jump{position:relative;top:auto;z-index:auto}
.pc-jump-arrow{position:absolute;top:0;bottom:0;z-index:1;width:3.2rem;display:flex;align-items:center;padding:0;border:0;cursor:pointer;color:var(--ink);background:transparent;font:inherit}
.pc-jump-arrow[hidden]{display:none}
.pc-jump-arrow.is-prev{left:0;justify-content:flex-start;background:linear-gradient(to right,var(--card) 55%,transparent)}
.pc-jump-arrow.is-next{right:0;justify-content:flex-end;background:linear-gradient(to left,var(--card) 55%,transparent)}
.pc-jump-arrow span{display:inline-flex;align-items:center;justify-content:center;width:1.75rem;height:1.75rem;border:1px solid var(--line);border-radius:50%;background:var(--card);font-size:1.15rem;line-height:1;box-shadow:0 1px 3px rgba(0,0,0,0.08)}
.pc-jump-arrow:hover span{border-color:var(--ink-soft)}
.pc-jump-arrow:focus-visible{outline:none}
.pc-jump-arrow:focus-visible span{outline:2px solid var(--accent);outline-offset:2px}
/* Part 2 of the school (9 Oct 2026): part headings, part labels in the lesson bar and the who's who. */
.ls-part{margin:2rem 0 0;font-size:1.15rem;padding-top:0.9rem;border-top:2px solid var(--line);max-width:820px;scroll-margin-top:calc(var(--sticky-top,0px) + 3.6rem)}
#part-1{margin-top:1.2rem}
.ls-part-intro{margin:0.4rem 0 0;max-width:70ch;color:var(--ink-soft);font-size:0.95rem;line-height:1.6}
.ls-list{margin:0;padding-left:1.2rem;display:grid;gap:0.35rem;font-size:0.95rem;line-height:1.55;max-width:70ch}
.pc-jump-part{flex:0 0 auto;align-self:center;font-size:0.68rem;font-weight:700;letter-spacing:0.08em;text-transform:uppercase;color:var(--ink-soft);padding:0 0.2rem 0 0.4rem}
/* Who they were, folded (9 Oct 2026): the summary line is the whole section once read. */
.who-fold > summary{list-style:none;cursor:pointer;display:flex;flex-wrap:wrap;align-items:baseline;gap:0.2rem 0.7rem;padding:0.65rem 0.85rem;border:1px solid var(--line);border-radius:8px;background:var(--card)}
.who-fold > summary::-webkit-details-marker{display:none}
.who-fold > summary:hover{border-color:var(--ink-soft)}
.who-fold > summary:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.whos-who .who-fold > summary h3{margin:0;font-size:1.05rem}
.who-fold-names{flex:1 1 16rem;min-width:0;font-size:0.85rem;color:var(--ink-soft);line-height:1.45}
.who-fold-hint{margin-left:auto;font-size:0.82rem;font-weight:600;color:var(--accent);white-space:nowrap}
.who-fold-hint::after{content:"";display:inline-block;width:0.42em;height:0.42em;margin-left:0.4em;border-right:2px solid currentColor;border-bottom:2px solid currentColor;transform:translateY(-0.18em) rotate(45deg);transition:transform 0.15s}
.who-fold[open] .who-fold-hint::after{transform:translateY(0.05em) rotate(-135deg)}
.who-fold .when-open{display:none}
.who-fold[open] .when-open{display:inline}
.who-fold[open] .when-closed{display:none}
.who-fold[open] > summary{margin-bottom:0.2rem}
@media (prefers-reduced-motion:reduce){.who-fold-hint::after{transition:none}}
.who-part{margin:0.9rem 0 0.45rem;font-size:0.72rem;font-weight:700;letter-spacing:0.08em;text-transform:uppercase;color:var(--ink-soft)}

/* The Learn section (9 Oct 2026): one menu item, three pages behind these tabs. */
.learn-tabs{display:flex;flex-wrap:wrap;gap:0.3rem;margin:0 0 1rem;border-bottom:1px solid var(--line)}
.learn-tabs a{padding:0.45rem 0.8rem;border-bottom:2px solid transparent;margin-bottom:-1px;font-size:0.9rem;color:var(--ink-soft);text-decoration:none;white-space:nowrap}
.learn-tabs a:hover{color:var(--ink)}
.learn-tabs a.on{color:var(--ink);font-weight:600;border-bottom-color:var(--accent)}
.learn-tabs a:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
/* Research tabs sit above the page's panels rather than inside one (9 Oct 2026). */
.research-tabs{margin:0.2rem 0 0.9rem}
#schoolPanel{min-width:0}

/* Your mind and money (9 Oct 2026, behaviour.html): the bias cards reuse the school's lesson cards. */
.mind-gap{margin:0.6rem 0 1rem;padding:0.9rem 1.05rem;border:1px solid var(--line);border-left:4px solid var(--accent);border-radius:10px;background:var(--card);max-width:820px}
.mind-gap h3{margin:0 0 0.4rem;font-size:1.05rem}
.mind-gap p{margin:0 0 0.5rem;font-size:0.95rem;line-height:1.6;max-width:70ch}
.mind-src{margin:0 !important;font-size:0.8rem !important;color:var(--ink-soft) !important;line-height:1.5}
.mind-ask{margin:0.6rem 0 0;padding-left:1.4rem;display:grid;gap:0.55rem;max-width:760px;font-size:0.95rem;line-height:1.55}
.mind-ask-ref{color:var(--ink-soft);font-size:0.82rem}
.mind-books{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:0.8rem;margin-top:0.6rem}
.mind-books .who-card h4{font-size:0.98rem;line-height:1.35}
.mind-papers-h{margin:1.4rem 0 0.4rem;font-size:1rem}
.mind-papers{margin:0;padding-left:1.2rem;display:grid;gap:0.35rem;font-size:0.88rem;line-height:1.5;max-width:900px}

/* Tax on shares (9 Oct 2026, tax.html). */
.tax-note{margin:0.4rem 0 1rem;padding:0.75rem 0.95rem;border:1px solid var(--line);border-left:4px solid #d99b39;border-radius:10px;background:var(--card);font-size:0.9rem;line-height:1.55;max-width:820px}
.tax-countries{display:flex;flex-wrap:wrap;gap:0.4rem;margin:0 0 1rem;position:sticky;top:var(--sticky-top,0px);z-index:4;background:var(--card);padding:0.5rem 0;box-shadow:0 1px 0 var(--line);scroll-margin-top:var(--sticky-top,0px)}
.tax-countries a{padding:0.35rem 0.85rem;border:1px solid var(--line);border-radius:999px;font-size:0.85rem;font-weight:600;color:var(--ink-soft);text-decoration:none}
.tax-countries a:hover{color:var(--ink);border-color:var(--ink-soft)}
.tax-countries a.on{background:var(--accent);border-color:var(--accent);color:var(--card)}
.tax-countries a:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.tax-country{max-width:860px;scroll-margin-top:calc(var(--sticky-top,0px) + 3.6rem)}
@media (max-width:640px){.tax-countries{position:static;box-shadow:none;padding:0}.tax-country{scroll-margin-top:0.5rem}}
.tax-country h3{margin:0.4rem 0 0.6rem;font-size:1.3rem;display:flex;flex-wrap:wrap;align-items:baseline;gap:0.3rem 0.7rem}
.tax-asof{font-size:0.78rem;font-weight:600;letter-spacing:0.04em;text-transform:uppercase;color:var(--ink-soft)}
.tax-country h4{margin:1.3rem 0 0.35rem;font-size:1rem}
.tax-country p{margin:0 0 0.6rem;font-size:0.95rem;line-height:1.65;max-width:72ch}
.tax-table-wrap{overflow-x:auto;margin:0.6rem 0 0.4rem}
.tax-table{border-collapse:collapse;font-size:0.88rem;min-width:100%;font-variant-numeric:tabular-nums}
.tax-table caption{text-align:left;font-size:0.82rem;color:var(--ink-soft);padding-bottom:0.35rem}
.tax-table th,.tax-table td{padding:0.45rem 0.6rem;border-bottom:1px solid var(--line);text-align:left;vertical-align:top}
.tax-table thead th{font-size:0.75rem;text-transform:uppercase;letter-spacing:0.04em;color:var(--ink-soft);font-weight:600}
.tax-compare tbody th{font-weight:600;white-space:nowrap}
.tax-in-app{margin-top:1rem !important;padding:0.6rem 0.8rem;border-radius:8px;background:var(--paper);border:1px dashed var(--accent)}
.tax-sources{font-size:0.8rem !important;color:var(--ink-soft);line-height:1.6 !important}
.tax-sources a{color:inherit}

/* The standing rule above Holdings / Watchlist (10 Oct 2026): tinted and edged in --accent so it reads as the
   reader's own setting that applies to every stock. Not green: green on these pages means a price went up. */
.rp-default{background:var(--card);background:color-mix(in srgb,var(--accent) 7%,var(--card));border-color:var(--accent-ring);border-left:3px solid var(--accent)}
@media (min-width:601px){.rp-default{padding:.65rem .85rem}.rp-default label{flex:0 1 auto;flex-wrap:nowrap}.rp-default label select{flex:0 1 auto}}
.rp-default .rp-eyebrow{flex-basis:100%;font-size:.68rem;font-weight:700;letter-spacing:.09em;text-transform:uppercase;color:var(--accent)}
.rp-default label{font-weight:600}
.rp-default .footnote strong{color:var(--ink)}
.ticker-click-hint .holdings-help{display:inline}
.ticker-click-hint .holdings-help summary{display:inline;cursor:pointer;color:var(--accent);list-style:none;margin-left:.25rem}
.ticker-click-hint .holdings-help summary::-webkit-details-marker{display:none}
.ticker-click-hint .holdings-help summary::after{content:" \25B8"}
.ticker-click-hint .holdings-help[open] summary::after{content:" \25BE"}
.ticker-click-hint .holdings-help[open]{display:block;margin-top:.35rem}
.ticker-click-hint .holdings-help p{margin:.3rem 0 0}

/* Reached chip, two lines (10 Oct 2026, Sam): what happened, then when. */
.rp-reached .rp-what,.rp-reached .rp-when{display:block}
.rp-reached .rp-when{font-size:.68rem;opacity:.85}

/* Long, wide tables (10 Oct 2026, Sam): the sideways scrollbar sat at the very bottom of the list, out of reach,
   and the column names scrolled away. The box is now held to the screen's height - so its sideways scrollbar is
   always on screen - and the column names stay pinned at its top while the rows scroll under them. A table
   that fits its panel (.fits, measured in app.js) is left to the page as before. Not on phones, where a
   sideways swipe needs no scrollbar and a box inside the page would trap the thumb. */
@media (min-width:601px){
  .table-scroll.tall{max-height:calc(100vh - var(--sticky-top,0px) - 1.5rem);overflow:auto}
  .table-scroll.tall thead th{position:sticky;top:0;z-index:3;background:var(--card);box-shadow:inset 0 -1px 0 var(--line)}
  .table-scroll.tall.fits{max-height:none;overflow:visible}
  #holdingsList .table-scroll.tall:not(.fits){max-height:calc(100vh - var(--holdings-head-top,var(--sticky-top,0px)) - 1.5rem)}
  #holdingsList .table-scroll.tall:not(.fits) .holdings-table thead th{position:sticky;top:0}
}

/* --- Loading, said plainly (10 Oct 2026, Sam) ----------------------------------------------------------
   The Dashboard and Holdings & Watchlist pages take a while on a first open, and nothing said so. Two signs:
   a pill with a spinner at the bottom of the screen while the opening loads run (app.js pageLoader), and a
   small spinner beside every "Loading..." / "Gathering..." / "Reading..." line inside a panel. */
.page-loader{position:fixed;left:50%;bottom:22px;transform:translateX(-50%);z-index:60;display:flex;align-items:center;gap:.8rem;
  max-width:calc(100vw - 32px);padding:.75rem 1.15rem .75rem .9rem;border-radius:14px;background:var(--card);color:var(--ink);
  border:1px solid var(--accent-ring);box-shadow:0 12px 32px -12px rgba(0,0,0,.45);transition:opacity .3s ease,transform .3s ease}
.page-loader.pl-done{opacity:0;transform:translateX(-50%) translateY(10px)}
.page-loader .pl-spin{width:26px;height:26px;flex-shrink:0;border-radius:50%;border:3px solid var(--accent-bg);border-top-color:var(--accent);animation:so-spin .8s linear infinite}
.page-loader .pl-text{display:flex;flex-direction:column;gap:.1rem;font-size:.95rem;line-height:1.3}
.page-loader .pl-sub{font-size:.8rem;color:var(--ink-soft)}
.empty.loading{display:flex;align-items:center;gap:.55rem}
.empty.loading::before{content:"";width:16px;height:16px;flex-shrink:0;border-radius:50%;border:2px solid var(--accent-bg);border-top-color:var(--accent);animation:so-spin .8s linear infinite}
@media (prefers-reduced-motion: reduce){.page-loader .pl-spin,.empty.loading::before{animation-duration:2.4s}}
