/* PropZilla — single hand-written stylesheet. Light theme, mobile-first.
   Styling mirrors the Daily Report Card (font, palette, surfaces, shadows). */

/* Anton (SIL OFL 1.1, see fonts/Anton-OFL.txt) — the logo wordmark only.
   Self-hosted like Inter rather than pulled from the Google CDN: one less
   third-party request, and it cannot go missing on us. Single weight by
   design, so never ask it for bold — that only triggers faux-bolding. */
@font-face {
  font-family: 'Anton';
  src: url('fonts/Anton-latin-400.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

/* Google Sans (SIL OFL 1.1, see fonts/GoogleSans-OFL.txt) — the UI face, first
   in --sans. Self-hosted since v5.119. It used to come from fonts.googleapis
   .com, which meant every visitor's IP reached Google before they had clicked
   anything: not a cookie question, so no banner would have covered it, and a
   third party philosophy.md §4 already said not to have ("our users' privacy
   should not depend on" a CDN) while Inter and Anton next door were vendored.
   The family is open-licensed, so the fix was to stop asking.

   The weight-axis cut, not the optical-size one: the CDN request clamped
   `opsz` to 17..18 — a one-unit range, i.e. a single optical size — so the
   opsz axis bought nothing and cost 41 KB across the pair. Italic is shipped
   rather than left to the browser, which would otherwise slant the roman by
   hand for the `<em>`s and the few italic rules. */
@font-face {
  font-family: 'Google Sans';
  src: url('fonts/GoogleSans-latin-wght-normal.woff2') format('woff2-variations'),
       url('fonts/GoogleSans-latin-wght-normal.woff2') format('woff2');
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Google Sans';
  src: url('fonts/GoogleSans-latin-wght-italic.woff2') format('woff2-variations'),
       url('fonts/GoogleSans-latin-wght-italic.woff2') format('woff2');
  font-weight: 400 700;
  font-style: italic;
  font-display: swap;
}

@font-face {
  font-family: 'Inter Variable';
  src: url('fonts/InterVariable.woff2') format('woff2-variations'),
       url('fonts/InterVariable.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/* ===========================================================================
   §palette — ONE token block, both themes (v5.17)
   ---------------------------------------------------------------------------
   **[KEY-CONCEPT] LIGHT IS STILL THE DEFAULT.** philosophy.md §3 picks light
   for a tool you read and reason about numbers in, and nothing here changes
   that: an account with no preference renders the first value of every pair,
   which is byte-for-byte the palette this app shipped with. Dark is opt-in,
   per login, from Settings → Appearance.

   **[KEY-CONCEPT] EVERY COLOUR IS A PAIR, AND EVERY COLOUR IS A TOKEN.** The
   second value in `light-dark()` is the dark one. The alternative was a second
   `:root[data-theme="dark"]` block — a copy of this list, forty lines away,
   that silently rots the first time someone adds a token to one and not the
   other. Here a colour cannot exist in one theme and not the other: the pair IS
   the declaration, and you read both by reading one line.

   `light-dark()` resolves against the element's own `color-scheme`, which is
   what the three selectors below set from the `data-theme` PHP wrote onto
   <html>. `auto` is `light dark` — the browser follows the machine and reflows
   the moment the OS flips, with no reload and nothing stored server-side about
   what the OS currently says.

   THE RULE FOR NEW COLOUR: never write a hex below this block. If a component
   needs a shade that isn't here, add the PAIR here and use the token — a raw
   hex is a colour that only works in one theme, and it will be found in the
   other one by the owner, at the screen, mid-session. The only exceptions are
   the firm badges (§firm badges: brand colours, on their own opaque fill, the
   same in both themes) and `--rgc`, which lib/regime.php owns.
   =========================================================================== */
:root            { color-scheme: light; }
:root[data-theme="dark"] { color-scheme: dark; }
:root[data-theme="auto"] { color-scheme: light dark; }

:root {
  /* --- surfaces, ink, edges --- */
  --bg:            light-dark(#fafafa, #10131a);
  --surface:       light-dark(#ffffff, #171b24);
  --surface-2:     light-dark(#f4f5f7, #1e232e);
  --border:        light-dark(#e5e7eb, #2b313d);
  --border-strong: light-dark(#cbd1d9, #414a5a);
  --text:          light-dark(#15171c, #e7eaf0);
  --muted:         light-dark(#6b7280, #99a1b0);
  /* Ink for text sitting ON a solid --accent / --pos / --neg / --warn fill.
     It flips with the theme because the fills do: the light palette's fills are
     dark enough to carry white, the dark palette's are bright enough to carry
     near-black. A literal #fff would have gone unreadable on half of them. */
  --on-solid:      light-dark(#ffffff, #10131a);

  /* --- the four meanings: accent, positive, negative, warning ---
     Each has a FILL value (the token itself — also the ink on a plain surface)
     and a WEAK tint to sit on. `-ink` is the readable text colour on that tint
     where the fill itself is too light (dark theme) or too dark (light theme). */
  --accent:        light-dark(#1f6feb, #5a9bff);
  --accent-weak:   light-dark(#e8f0fe, #17253f);
  --accent-ink:    light-dark(#1d4ed8, #8ab6ff);
  --pos:           light-dark(#15803d, #46c46a);
  --pos-weak:      light-dark(#dcfce7, #14301f);
  --pos-ink:       light-dark(#0f766e, #4fc9b4);   /* the payable teal */
  --pos-faint:     light-dark(#fafffb, #121d16);   /* barely-there verdict wash */
  --neg:           light-dark(#dc2626, #f2635c);
  --neg-weak:      light-dark(#fdecec, #36191b);
  --neg-ink:       light-dark(#b91c1c, #ff8f88);
  --neg-deep:      light-dark(#7f1d1d, #ff6a60);   /* LAST SHOT / reanimation */
  --neg-faint:     light-dark(#fffafa, #201416);
  --warn:          light-dark(#f97316, #f59245);
  --warn-weak:     light-dark(#fff7ed, #33230f);
  --warn-weak-2:   light-dark(#ffedd5, #422c10);   /* one step deeper (THIN) */
  --warn-ink:      light-dark(#b45309, #e0a250);   /* amber text on an amber tint */
  --warn-fill:     light-dark(#b45309, #b45309);   /* solid amber, carries --text */
  --warn-border:   light-dark(#fed7aa, #6d4413);

  /* --- the BV flag's purple: an annotation, never a status --- */
  --biz:           light-dark(#7e22ce, #c58cf5);
  --biz-weak:      light-dark(#f3e8ff, #2b1c3d);
  --biz-edge:      light-dark(#d8b4fe, #6d3fa3);

  /* --- the BV statement's sheet of paper: the same in both themes, because it
         is printed, and a dark sheet on screen would not be what comes out --- */
  --paper:         light-dark(#ffffff, #ffffff);
  --paper-ink:     light-dark(#15171c, #15171c);
  --paper-muted:   light-dark(#5b6270, #5b6270);
  --paper-rule:    light-dark(#d5d9e0, #d5d9e0);
  --paper-band:    light-dark(#f3f4f6, #f3f4f6);
  --paper-void:    light-dark(rgba(220,38,38,.16), rgba(220,38,38,.16));

  /* --- funded rows read as a different class of thing (see §funded) --- */
  --funded-row:    light-dark(#f4fbf7, #14231b);
  --funded-row-2:  light-dark(#f8fbf9, #121b17);   /* the same row, already traded */
  --funded-edge:   light-dark(#10b981, #10b981);

  /* --- session banding on the ATM table --- */
  --sess-a-tint:   light-dark(rgba(249,115,22,.06), rgba(245,146,69,.10));
  --sess-b-tint:   light-dark(rgba(31,111,235,.05), rgba(90,155,255,.10));

  /* --- depth. Dark surfaces get no help from a 4%-black shadow, so the dark
         half is far deeper: on a dark page a raised panel reads by its shade,
         not by its edge. --- */
  /* **[CRITICAL] ONLY THE COLOUR GOES INSIDE light-dark().** It is a <color>
     function — it does not take a shadow, a length or a filter. Wrapping a whole
     `0 1px 2px rgba(…)` in it parses (a custom property swallows almost any
     token sequence) and then fails at SUBSTITUTION, which drops the whole
     `box-shadow` declaration: every card, row and popover in the app silently
     loses its shade, in BOTH themes, with no error anywhere. So the geometry is
     written once, outside, and only the ink is a pair. Same rule for anything
     else non-colour that ever wants the theme — see .brand-mark. */
  --shadow-ink:    light-dark(rgba(15,17,28,0.04), rgba(0,0,0,0.40));
  --shadow-ink-2:  light-dark(rgba(15,17,28,0.03), rgba(0,0,0,0.30));
  --shadow-pop-ink:light-dark(rgba(15,17,28,.10),  rgba(0,0,0,.55));
  --shadow-lg-ink: light-dark(rgba(15,17,28,.16),  rgba(0,0,0,.65));
  --shadow:        0 1px 2px var(--shadow-ink), 0 1px 1px var(--shadow-ink-2);
  --shadow-pop:    0 8px 24px var(--shadow-pop-ink);
  --shadow-lg:     0 6px 24px var(--shadow-lg-ink);
  --track:         light-dark(rgba(15,17,28,.07), rgba(255,255,255,.10));
  --scrim:         light-dark(rgba(21,23,28,.65), rgba(0,0,0,.72));
  /* A hover wash that works on a tinted cell in either theme: darken the light
     one, lift the dark one. (This replaced `filter: brightness(.97)`, which can
     only ever darken — on a dark calendar that reads as the cell going away.) */
  --cell-hover:    light-dark(rgba(0,0,0,.045), rgba(255,255,255,.07));
  /* A hairline that only exists in the dark theme, so a near-black firm badge
     (TopStep) keeps an edge against a near-black surface. Transparent in light:
     the badges are loud enough there and always were. */
  --badge-edge:    light-dark(transparent, rgba(255,255,255,.16));

  --radius: 10px;
  /* Two radii, and only two. --radius is the container tier (cards, panels,
     popovers); --radius-token is EVERY inline token — chip, badge, pill, flag,
     tag, segmented control — and the small blocks they sit in. Before v4.114 the
     EXECUTE cell alone shipped four (999/4/6/8). Data bars, 50% circles and
     micro-decorations (.pip, .dot, .sw, the hamburger) are neither tier and keep
     their own values: a 5px-tall meter is not a pill. */
  --radius-token: 8px;
  --sans: 'Google Sans', 'Inter Variable', 'Inter', ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
/* Phones zoom in when a field under 16px is tapped and stay zoomed, which is what
   makes a page pan sideways after logging a balance (v5.165). Every field is 16px on
   a touch screen; desktop keeps the compact sizes below. */
@media (pointer: coarse) {
  input, select, textarea { font-size: 16px !important; }
}
body {
  margin: 0;
  font-family: var(--sans);
  font-feature-settings: 'cv11', 'ss01';
  -webkit-font-smoothing: antialiased;
  font-size: 16px;
  line-height: 1.5;
  color: var(--text);
  background: var(--bg);
}
h1 { font-size: 22px; margin: 0; }
h2 { font-size: 17px; margin: 0 0 12px; }
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
.muted { color: var(--muted); }
.mono { font-variant-numeric: tabular-nums; }
.pos { color: var(--pos); }
.neg { color: var(--neg); }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }

/* ---------- release bar (v5.63) ---------- */
/* Fixed above the sticky top bar. app.js sets `--updbar-h` to the bar's real
   height once it exists; the body and the top bar move down by that much, so
   nothing hides under it. Default 0: no bar, no effect. */
.updbar {
  position: fixed; top: 0; left: 0; right: 0; z-index: 30;
  display: flex; align-items: center; justify-content: center; flex-wrap: wrap; gap: 8px 16px;
  padding: 8px 16px; font-size: 14px; font-weight: 500;
  /* Amber, like .warnbox (v5.73): a heads-up, not a link. The blue Reload
     button is the one thing on it that acts. */
  background: var(--warn-weak); color: var(--warn-ink);
  border-bottom: 1px solid var(--warn-border);
}
.updbar .btn-primary { padding: 6px 14px; font-size: 14px; }
.updbar a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
body { padding-top: var(--updbar-h, 0px); }

/* ---------- top bar ---------- */
.topbar {
  position: sticky; top: var(--updbar-h, 0px); z-index: 20;
  display: flex; align-items: center; gap: 16px;
  height: 56px; padding: 0 24px;
  background: var(--surface); border-bottom: 1px solid var(--border);
}
.brand { display: flex; align-items: center; gap: 10px; color: var(--text); font-weight: 600; }
.brand:hover { text-decoration: none; }
/* PropZilla mascot (v4.107). Mobile keeps the topbar at 56px and the logo small;
   the >=768px rule grows both, so the logo uses the empty room on the left that
   the nav never occupies. Sized by height — width follows the viewBox. */
.brand-mark { display: block; height: 30px; width: auto; }
/* The mascot needs NO theme rule (v5.52). It is a roundel: every dark shape
   sits on the red disc, never on the page, so the mark reads identically on a
   white topbar and a near-black one. The previous marks were a bare silhouette
   and needed first `filter: invert(1)`, then a whole second file swapped in by
   `content:` — this is the version that deletes the special case instead of
   maintaining it. If a non-colour ever needs the theme again, put it here. */
/* The wordmark alone opts out of --sans, for Anton: a heavy condensed display
   face with one weight only, so it stays at 400 — asking for bold would just
   faux-embolden an already-black face. Anton's cap height runs much larger than
   Inter's, hence the bigger font-size here than the old stack wanted, and a
   little tracking because condensed caps need air (v4.110). */
.brand-text { font-family: 'Anton', var(--sans); font-weight: 400;
  font-size: 22px; text-transform: uppercase; letter-spacing: 0.04em; }
/* Mobile: nav is a dropdown panel toggled by the hamburger (.navtoggle).
   Desktop (>=768px): it becomes the inline tab row — see the desktop block. */
.navtabs {
  display: none; flex-direction: column; gap: 2px;
  position: absolute; top: 56px; left: 0; right: 0; z-index: 19;
  padding: 8px; background: var(--surface); border-bottom: 1px solid var(--border);
  box-shadow: var(--shadow-pop);
  /* The panel scrolls INSIDE itself (v5.112). With More open the list is
     ~950px tall on a 667px phone; before this the panel hung off a sticky bar
     with no height cap, so Help, Settings and Sign out sat below the fold and
     no scroll could reach them (the page scrolled, the bar and its panel did
     not). Cap: the viewport minus the bar and the release bar above it. dvh
     (Safari 15.4+, Chrome 108+) tracks the phone's collapsing URL bar; the vh
     line before it is the fallback. overscroll-behavior keeps a flick at the
     end of the list from scrolling the page behind. Bottom padding clears
     the home indicator on a notched phone. */
  max-height: calc(100vh - 56px - var(--updbar-h, 0px));
  max-height: calc(100dvh - 56px - var(--updbar-h, 0px));
  overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch;
  padding-bottom: calc(8px + env(safe-area-inset-bottom, 0px));
}
.navtabs.open { display: flex; }
/* A short drop-in on open, only where the browser can start a transition from
   display:none (@starting-style) and the user has not asked for less motion. */
@media (prefers-reduced-motion: no-preference) {
  .navtabs.open { transition: opacity .15s ease, translate .15s ease; }
  @starting-style { .navtabs.open { opacity: 0; translate: 0 -6px; } }
}
.navtabs a, .navtabs summary {
  padding: 11px 12px; border-radius: var(--radius-token); color: var(--muted); font-weight: 500;
}
/* Hover only where there is a pointer to hover with: on a touchscreen the
   wash sticks to the last tapped row (More, after opening it). */
@media (hover: hover) {
  .navtabs a:hover, .navtabs summary:hover { background: var(--bg); text-decoration: none; }
}
.navtabs a.active, .navtabs summary.active { color: var(--text); background: var(--surface-2); }
.nav-more-panel a { padding-left: 24px; }         /* mobile: indent under "More" */
.nav-sep { display: none; }                      /* mobile dropdown: no separators */
/* mobile: the words carry it, icons hidden (see .nav-help-icon above) */

/* "More" — groups the less-checked money/reporting pages behind one disclosure
   (v4.36). Native <details>/<summary>: no JS, works nested inside the mobile
   dropdown panel too. */
.nav-more summary { list-style: none; cursor: pointer; user-select: none; }
.nav-more summary::-webkit-details-marker { display: none; }
.nav-more summary::after { content: '▾'; font-size: 10px; margin-left: 5px; opacity: .6; }
.nav-more[open] summary::after { content: '▴'; }
.nav-more-panel { display: flex; flex-direction: column; gap: 2px; }
/* Section labels inside More. Not links — they only tell you which of the two
   questions the group below answers, so the RULE under each one does the
   separating and the words sit back at label size instead of reading as two
   headings stacked into the list they head. */
.nav-group {
  font-size: 12px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--muted);
  padding: 4px 10px 6px; margin-bottom: 4px; user-select: none;
  border-bottom: 1px solid var(--border);
}
/* One per group (see layout.php). Inside the phone's dropdown they stack, which
   is the same shape the flat list had. */
.nav-col { display: flex; flex-direction: column; gap: 2px; }
.nav-col + .nav-col { margin-top: 10px; }

/* Demo ribbon + page ledes (v5.12). Both answer "what am I looking at" without
   a stepped tour: the ribbon says whose data it is, the lede says what the page
   is. Static, server-rendered, no JS, nothing to dismiss. Amber tokens rather
   than literal hex — this has to survive the dark theme, where a hardcoded
   cream band would glare. */
.demo-ribbon {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px;
  padding: 9px 24px; font-size: 13px; line-height: 1.45;
  color: var(--warn-ink); background: var(--warn-weak);
  border-bottom: 1px solid var(--warn-border);
}
.demo-ribbon strong { font-weight: 700; }
/* The impersonation ribbon. Same shape as the demo one, red rather than amber:
   amber says "mind the data", red says "you are not you". It carries its own way
   out, because the ribbon is the only thing on screen that admits the session is
   borrowed. */
.viewas-ribbon {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px;
  padding: 9px 24px; font-size: 13px; line-height: 1.45;
  color: var(--neg-ink); background: var(--neg-weak);
  border-bottom: 1px solid var(--neg);
}
.viewas-ribbon strong { font-weight: 700; }
.viewas-ribbon .viewas-back { display: inline; margin-left: auto; }
.viewas-ribbon .btn-link {
  background: none; border: 0; padding: 0; font: inherit; cursor: pointer;
  color: var(--neg-ink); font-weight: 700; text-decoration: underline;
}
/* The account roster: name on the left, its one action on the right. */
/* The account roster is one grid: name | plan select | profile select | View
   as (v5.140 added the plan). Each row is a subgrid so the action columns
   line up across every row; the owner's own row renders an empty View-as
   cell to hold its column. */
.acct-list { display: grid; grid-template-columns: minmax(0, 1fr) auto auto auto; }
.acct-list li { display: grid; grid-column: 1 / -1; grid-template-columns: subgrid; align-items: center; column-gap: 14px; }
.acct-list li > span:first-child { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 10px; }
.acct-viewas { text-align: right; }
@media (max-width: 560px) {
  /* Phone: the name takes the whole first line, the actions sit under it. */
  .acct-list { grid-template-columns: minmax(0, 1fr) auto auto; row-gap: 0; }
  .acct-list li > span:first-child { grid-column: 1 / -1; }
  .acct-list li > .inline-form { justify-self: start; margin-top: 4px; }
  .acct-list li > .acct-viewas { margin-top: 4px; }
}
@media (max-width: 560px) {
  .viewas-ribbon { padding-left: 16px; padding-right: 16px; }
  .viewas-ribbon .viewas-back { margin-left: 0; }
}
.page-lede { margin: -2px 0 16px; color: var(--muted); font-size: 14px; max-width: 68ch; }
.head-actions { display: inline-flex; align-items: center; gap: 12px; flex-wrap: wrap; }
/* Start here: three links, not three steps. No state, nothing to dismiss. */
.start-here { counter-reset: step; }
.start-here li { counter-increment: step; margin-bottom: 10px; list-style: none; }
.start-here li::before {
  content: counter(step); display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; margin-right: 8px; border-radius: 999px;
  background: var(--accent-weak); color: var(--accent-ink);
  font-size: 12px; font-weight: 700;
}
.start-here b { font-weight: 700; }
.start-here span { color: var(--muted); }
@media (max-width: 560px) { .demo-ribbon { padding-left: 16px; padding-right: 16px; } }
/* Both icon controls are built identically, or they align differently: the
   anchor centres its own content, so neither depends on baseline position. */
.nav-help, .nav-gear { display: inline-flex; align-items: center; gap: 6px; }
/* Help and Settings are drawn as matched inline SVGs (v5.10) rather than the
   "?" glyph and the ⚙ character: at 16px the gear codepoint renders as a spiky
   blob, differently on every platform, and it sat visually smaller than the
   bordered "?" beside it. One box, one stroke weight, one optical size. */
.nav-help-icon, .nav-gear-icon { display: none; opacity: .7; }
.nav-icon { width: 18px; height: 18px; display: block; }
.nav-help:hover .nav-help-icon,
.nav-gear:hover .nav-gear-icon,
.nav-help.active .nav-help-icon,
.nav-gear.active .nav-gear-icon { opacity: 1; }

/* Help page. `scroll-margin-top` clears the sticky topbar so a deep link from
   the "?" doesn't land the heading underneath it. */
.help-list { margin: 12px 0 0; }
.help-list dt {
  font-weight: 700; font-size: 15px; margin-top: 16px; scroll-margin-top: 108px;
}
.help-list dt:first-child { margin-top: 4px; }
.help-list dt:target { color: var(--accent); }
.help-list dd { margin: 4px 0 0; max-width: 68ch; }
.help-when { display: block; margin-top: 3px; font-size: 13px; }
.nav-account {
  /* The chevron is pushed right by its own margin, not by space-between: a
     summary with a label AND a muted hint has three children, and
     space-between would strand the hint in the middle of the row. */
  display: flex; align-items: center; gap: 8px;
  margin-top: 6px; padding: 10px 12px 2px; border-top: 1px solid var(--border);
}

/* Hamburger toggle — mobile only (hidden on desktop). 44px: the smallest
   target a thumb hits reliably (v5.112, was 40). touch-action drops the
   double-tap-to-zoom wait some mobile browsers still put on a tap. */
.navtoggle {
  margin-left: auto; display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; padding: 0; border-radius: var(--radius-token);
  background: none; border: 1px solid var(--border); color: var(--text); cursor: pointer;
  touch-action: manipulation; -webkit-tap-highlight-color: transparent;
}
@media (hover: hover) { .navtoggle:hover { background: var(--surface-2); } }
/* While the phone menu is open (app.js puts .nav-open on <body>): the page
   behind stops scrolling, so a flick on the list never moves the page under
   it, and a wash dims it, so the panel reads as the thing on top and a tap
   on it is a plain "close" (app.js closes on any tap outside the nav). The
   wash sits under the sticky bar (z 20) and so under the panel inside it.
   Phone only: the desktop tab row is never "open". */
@media (max-width: 767px) {
  body.nav-open { overflow: hidden; }
  body.nav-open::after {
    content: ''; position: fixed; inset: 0; z-index: 18;
    background: rgba(0, 0, 0, .35);
  }
}
.navtoggle-bars { display: inline-flex; flex-direction: column; gap: 4px; width: 18px; }
.navtoggle-bars span { height: 2px; border-radius: 2px; background: currentColor; transition: transform .15s, opacity .15s; }
.navtoggle[aria-expanded="true"] .navtoggle-bars span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.navtoggle[aria-expanded="true"] .navtoggle-bars span:nth-child(2) { opacity: 0; }
.navtoggle[aria-expanded="true"] .navtoggle-bars span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

.topbar-right { display: none; margin-left: auto; align-items: center; gap: 12px; }
.whoami { font-size: 13px; color: var(--muted); max-width: 40vw; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.logout-form { margin: 0; }
.linkish { background: none; border: 0; color: var(--accent); cursor: pointer; font: inherit; padding: 0; }

/* ---------- layout ---------- */
/* ONE container for EVERY page, FLUID (v4.25, owner directive after the
   1360px cap of v4.16): content uses the full viewport like a dashboard,
   with only an even gutter at the edges — same gutter as the topbar, so
   every edge lines up. Still no exceptions between tabs; reading-width
   content (journal forms) centers a narrower column INSIDE the fluid page.
   `.dashboard`, `.wide` and `.journal` stay as no-op classes. */
.page { margin: 0; padding: 16px 24px; }
/* A single stacked form doesn't want 1320px of input, so the form column stays
   readable inside the wide page. Multi-column grids (.plan-grid, .two-col) are
   unaffected and use the room. */
.form-page .form-main > label > input:not([type=checkbox]),
.form-page .form-main > label > select,
.form-page .form-main > label > textarea { max-width: 620px; }
/* v4.26 (owner rule: center ALL forms): every standalone form column sits in
   the same centered 760px band the journal uses — one form voice everywhere.
   Inline/filter forms (no .stack/.form-main) are untouched. */
form.stack, form.form-main, form.danger-form,
.card > .filters { max-width: 760px; margin-left: auto; margin-right: auto; }
.page-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 16px; }
.page-head-actions { display: flex; align-items: center; gap: 14px; }
.footer {
  margin: 24px 0 0; padding: 16px 24px;
  display: flex; flex-wrap: wrap; justify-content: center; text-align: center;
  gap: 6px 16px; font-size: 12px; color: var(--muted);
  border-top: 1px solid var(--border);
}

/* ---------- cards / sections ---------- */
.card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 16px; margin-bottom: 16px;
  box-shadow: var(--shadow);
}
/* ONE heading voice (v4.16): every card's title speaks in the same quiet
   small-caps the Book's sections use — no more shouting boxes. */
.card > h2, .jcard-head h2 {
  font-size: 12px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--muted); font-weight: 600; margin: 0 0 12px;
}

/* ---------- buttons ---------- */
.btn-primary, .btn-secondary, .btn-danger, .btn-sm {
  display: inline-block; font: inherit; font-weight: 600; cursor: pointer;
  border-radius: var(--radius-token); padding: 11px 16px; border: 1px solid transparent; text-align: center;
}
.btn-primary { background: var(--accent); color: var(--on-solid); }
.btn-primary:hover { text-decoration: none; filter: brightness(1.05); }
.btn-secondary { background: var(--surface); color: var(--text); border-color: var(--border); }
.btn-secondary:hover { text-decoration: none; background: var(--bg); }
.btn-danger { background: var(--neg-weak); color: var(--neg); }
.btn-sm { padding: 7px 12px; font-size: 14px; background: var(--surface); border-color: var(--border); color: var(--text); }
.btn-link { color: var(--accent); font-weight: 500; }

/* ---------- forms ---------- */
label { display: block; font-size: 14px; color: var(--muted); margin-bottom: 12px; }
.stack > label, .form-main > label { margin-bottom: 14px; }
input[type=text], input[type=email], input[type=password], input[type=date],
input[type=number], input[type=search], input[type=url], select, textarea {
  display: block; width: 100%; margin-top: 4px;
  font: inherit; font-size: 16px; color: var(--text);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-token);
  padding: 11px 12px; min-height: 44px;
}
textarea { min-height: 64px; resize: vertical; }
input:focus, select:focus, textarea:focus { outline: 2px solid var(--accent); outline-offset: 0; border-color: var(--accent); }
.or-new { margin-top: 6px; }
.check { display: flex; align-items: center; gap: 8px; color: var(--text); }
.check input { width: auto; min-height: 0; margin: 0; }
.check.inline { display: inline-flex; margin: 0; }
.two-col { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.form-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 8px; }
/* Add account (v5.59): one row per account number. Two inputs and a ✕ on a
   line at desk width; on a phone the nickname drops under the number. */
.acct-rows { margin-bottom: 14px; }
.acct-rows-head { display: none; font-weight: 600; font-size: 14px; margin-bottom: 4px; }
.acct-row { display: grid; grid-template-columns: 1fr auto; gap: 6px 8px; margin-bottom: 8px; }
.acct-row input { min-width: 0; }
.acct-row input[name="label[]"] { grid-column: 1 / -1; }
.acct-row .acct-row-del { grid-row: 1; grid-column: 2; padding: 7px 10px; }
.acct-rows-foot { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin-top: 6px; }
.acct-rows-foot .muted { flex: 1 1 260px; font-size: 13px; }
.acct-count { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; margin: 0 0 10px; font-size: 14px; }
.acct-count input { width: 72px; padding: 7px 8px; }
.acct-count .muted { flex: 1 1 200px; font-size: 13px; }
@media (min-width: 640px) {
  .acct-rows-head, .acct-row { display: grid; grid-template-columns: 1.4fr 1fr auto; gap: 8px; }
  .acct-rows-head { padding-right: 44px; }
  .acct-row input[name="label[]"] { grid-column: auto; }
  .acct-row .acct-row-del { grid-row: auto; grid-column: auto; }
}
.form-actions .btn-primary, .form-actions .btn-secondary { flex: 1; min-width: 140px; }
/* Add account (v5.77): the plan picked one attribute per row — firm, plan,
   size, eval/funded — each a .seg row of chips, then a summary card with
   the rules the account is about to be registered with. */
.plan-pick { margin-bottom: 16px; }
.plan-pick .pick-row { margin-bottom: 10px; }
.plan-pick-note { display: block; margin-top: 8px; font-size: 13px; }
.pick-msg { margin: 0 0 10px; }
.plan-summary {
  padding: 12px 14px; margin-top: 4px;
  border: 1px solid var(--accent); border-radius: var(--radius-token);
  background: var(--accent-weak); color: var(--text);
}
.plan-summary-head { display: flex; align-items: center; gap: 8px; font-weight: 600; font-size: 15px; }
.plan-facts { display: grid; grid-template-columns: max-content 1fr; gap: 4px 12px; margin: 8px 0 0; font-size: 14px; }
.plan-facts dt { color: var(--muted); }
.plan-facts dd { margin: 0; font-variant-numeric: tabular-nums; }
.plan-summary-notes { margin: 8px 0 0; font-size: 13px; }
/* Plan requests (v5.78): the member's list (plan_request.php, a line on Add
   account) and the owner's queue on admin/plans. One row shape for all three. */
.req-inline { margin: -6px 0 16px; font-size: 14px; }
.req-inline-row { margin-bottom: 4px; }
.req-inline .chip { margin-right: 4px; }
.req-row { display: grid; grid-template-columns: 1fr auto; gap: 4px 12px; padding: 10px 0; border-top: 1px solid var(--border); align-items: center; }
.req-row:first-of-type { border-top: 0; padding-top: 0; }
.req-main { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.req-sub { grid-column: 1; font-size: 13px; }
.req-act { grid-column: 2; grid-row: 1 / span 2; display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 8px; }
.req-act .btn-primary { padding: 7px 12px; font-size: 14px; }
.req-decline { display: flex; align-items: center; gap: 6px; }
.req-decline input { width: 200px; margin-top: 0; min-height: 0; padding: 7px 10px; font-size: 14px; }
.req-foot { margin: 10px 0 0; font-size: 13px; }
@media (max-width: 640px) {
  .req-row { grid-template-columns: 1fr; }
  .req-act { grid-column: 1; grid-row: auto; justify-content: flex-start; }
  .req-decline input { width: 160px; }
}
/* The owner's "requests waiting" count on the gear. */
.nav-badge {
  display: inline-block; min-width: 18px; padding: 0 5px; margin-left: 4px;
  border-radius: 9px; background: var(--accent); color: var(--on-solid);
  font-size: 11px; font-weight: 700; line-height: 18px; text-align: center;
}
.danger-form { margin-top: 24px; }

/* segmented type control */
.seg { border: 0; padding: 0; margin: 0 0 14px; }
.seg legend { font-size: 14px; color: var(--muted); padding: 0; margin-bottom: 6px; }
.seg { display: flex; flex-wrap: wrap; gap: 8px; }
.seg legend { flex-basis: 100%; }
.seg-opt { position: relative; margin: 0; }
.seg-opt input { position: absolute; opacity: 0; inset: 0; cursor: pointer; }
.seg-opt span {
  display: inline-block; padding: 9px 14px; border: 1px solid var(--border);
  /* 8px, not a 999px lozenge: the pills sit next to buttons and inputs that are
     all 8px, and a fully-rounded chip next to them reads as a different system. */
  border-radius: var(--radius-token); background: var(--surface); color: var(--text); font-size: 14px;
  line-height: 1.5;
}
.seg-opt input:checked + span { background: var(--accent); color: var(--on-solid); border-color: var(--accent); }
.seg-opt input:focus-visible + span { outline: 2px solid var(--accent); outline-offset: 2px; }

.fx-line { margin: -6px 0 14px; font-size: 13px; }
.flag-row { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
.flag-row input[type=date] { width: auto; margin-top: 0; }
/* Disclosure rows (v5.27). The native marker is the problem it looks like: a
   bare ▶ next to blue text reads as decoration, not as "this opens". So the
   summary becomes an actual ROW — full width, bordered, hover state, and a
   chevron pinned right that rotates on open. Same shape as a button, because
   that is what it does. */
.more > summary {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  list-style: none; cursor: pointer; user-select: none;
  margin-bottom: 12px; padding: 9px 12px;
  font-weight: 600; color: var(--accent);
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--radius-token);
}
.more > summary::-webkit-details-marker { display: none; }
.more > summary::after {
  content: ''; flex: 0 0 auto; margin-left: auto; width: 8px; height: 8px;
  border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
  /* Translate BEFORE rotate: the other order spins the offset with the glyph
     and the open chevron lands off its own baseline. */
  transform: translateY(-2px) rotate(45deg);
  transition: transform .12s ease;
}
.more[open] > summary::after { transform: translateY(2px) rotate(-135deg); }
.more > summary:hover { background: var(--bg); border-color: var(--accent); }
.more > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.payout-chain label { margin-bottom: 10px; }

/* row-edit (firms/methods/setups) */
.row-edit { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 8px 0; border-top: 1px solid var(--border); }
.row-edit input { margin-top: 0; }
/* A list row READS as its record and opens its editor on click — the same
   <details> disclosure as .riskset on the Book, so a settings list is a list of
   names, not a column of form boxes. The editor underneath is the .row-edit
   form unchanged; it drops its own rule so the row shows one, not two. */
.rowset { border-top: 1px solid var(--border); }
.rowset > summary {
  list-style: none; cursor: pointer; user-select: none;
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px; padding: 11px 0;
}
.rowset > summary::-webkit-details-marker { display: none; }
.rowset > summary strong { border-bottom: 1px dashed var(--border); }
.rowset > summary:hover strong { border-bottom-color: currentColor; }
.rowset[open] > summary strong { border-bottom-color: var(--accent); }
.rowset > summary .muted { font-size: 13px; }
.rowset > .row-edit { border-top: 0; padding-top: 0; }
.ed-name { flex: 2 1 140px; }
.ed-split { flex: 0 1 90px; }
.ed-notes { flex: 3 1 160px; }
.ed-name.static { padding: 8px 0; }
.is-archived { opacity: .55; }

/* plan catalog: edit/delete pair in a table row, and the register-form picker */
.rowacts { display: flex; gap: 10px; align-items: center; white-space: nowrap; }
.planpick { padding: 10px 12px; background: var(--surface-2); border-radius: var(--radius-token); }

/* Plans is a bulk data-entry screen used at a desk: let the form flow into
   columns as width allows instead of one tall stack of pairs. Labels stretch to
   equal row height and the control is pinned to the bottom, so inputs stay on a
   line even when a hint wraps to two lines. */
.plan-grid { display: grid; grid-template-columns: 1fr; gap: 0 16px; }
.plan-grid > label { display: flex; flex-direction: column; }
.plan-grid > label > input, .plan-grid > label > select { margin-top: auto; }
.plan-grid > label > .or-new { margin-top: 6px; }
@media (min-width: 700px)  { .plan-grid { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1040px) { .plan-grid { grid-template-columns: repeat(3, 1fr); } }
/* The catalog table earns its width — keep cells on one line and let the
   existing .table-wrap scroll handle anything narrower. */
.plans-page table.data { min-width: 900px; }
.plans-page table.data th, .plans-page table.data td { white-space: nowrap; }

/* plans_bulk.php: the whole catalog as one editable grid. Nineteen columns of
   inputs never fit a laptop, so the table keeps its own width and hands the
   overflow to .table-wrap's scroll — the alternative (shrinking fields) makes
   every cell unreadable instead of just the far-right ones. */
.plans-bulk .bulk-bar {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: 16px; margin-bottom: 12px;
}
.plans-bulk .bulk-bar > label { display: flex; flex-direction: column; gap: 4px; }
.plans-bulk .bulk-bar input { min-width: 240px; }
.plans-bulk table.data { min-width: 1900px; }
.plans-bulk table.data th, .plans-bulk table.data td { white-space: nowrap; padding: 4px 6px; }
.plans-bulk table.data input[type=text], .plans-bulk table.data select {
  padding: 4px 6px; font-size: 13px; width: 100%;
}
.plans-bulk table.data td.mid { text-align: center; }
.plans-bulk .w-name  { min-width: 130px; }
.plans-bulk .w-money { min-width: 92px; text-align: right; font-variant-numeric: tabular-nums; }
.plans-bulk .w-small { min-width: 64px; text-align: right; font-variant-numeric: tabular-nums; }
.plans-bulk .w-notes { min-width: 200px; }
/* Selects need room for the value itself, not just the caret — a firm column
   that reads "A ⌄" is worse than no column. */
.plans-bulk select { min-width: 128px; }
.plans-bulk td:nth-child(3) select, .plans-bulk td:nth-child(7) select { min-width: 88px; }
/* .form-actions stretches its buttons to fill a narrow form column; under the
   full-width grid that makes a 1500px "Save all". Keep them button-sized. */
.plans-bulk .form-actions .btn-primary, .plans-bulk .form-actions .btn-secondary { flex: 0 0 auto; }
/* Blank rows read as "not yet a plan" without a second colour: a dotted rule
   marks where the catalog ends and the add-area begins. */
.plans-bulk tr.is-new > td { background: var(--surface-2); }
.plans-bulk tr:not(.is-new) + tr.is-new > td { border-top: 2px dashed var(--border); }
.plans-bulk tr.has-err > td { background: var(--neg-weak); }
.plans-bulk .row-err { display: block; font-size: 12px; color: var(--neg-ink); white-space: normal; max-width: 180px; }
/* The list is long; keep Save reachable without scrolling back to the top. */
.plans-bulk .sticky-actions {
  position: sticky; bottom: 0; z-index: 2; margin-top: 0;
  padding: 12px 0; background: var(--bg); border-top: 1px solid var(--border);
}

/* risk plan: the ladder of days to pass, and the ATM sizing table */
.ladder-step {
  display: inline-block; margin: 0 4px 4px 0; padding: 2px 9px; border-radius: var(--radius-token);
  background: var(--accent-weak); color: var(--accent); font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.risk-stop { align-items: center; margin: 14px 0 4px; }
.risk-stop .inline-lbl { display: flex; align-items: center; gap: 8px; margin: 0; }
.risk-stop .inline-lbl input { margin-top: 0; width: 100px; }
.risk-last { margin: 0 0 14px; display: flex; align-items: center; gap: 8px; font-size: 14px; color: var(--muted); }
/* how much drawdown is left, and where the reserve line sits */
.buffer { margin-bottom: 16px; }
.buffer-head { display: flex; justify-content: space-between; gap: 12px; font-size: 14px; margin-bottom: 6px; }
.buffer-bar {
  position: relative; height: 10px; border-radius: 999px;
  background: var(--surface-2); overflow: hidden;
}
.buffer-fill { position: absolute; inset: 0 auto 0 0; background: var(--pos); border-radius: 999px; }
.buffer-fill.low { background: var(--neg); }
.buffer-reserve { position: absolute; top: -3px; bottom: -3px; width: 2px; background: var(--text); opacity: .55; }
.buffer-note { margin: 6px 0 0; font-size: 13px; }
.risk-grid { margin-bottom: 4px; }
.risk-take {
  margin: 12px 0 0; padding: 12px 14px; border-radius: var(--radius-token);
  background: var(--pos-weak); border: 1px solid transparent; font-size: 15px;
}
.risk-take.stop { background: var(--neg-weak); color: var(--neg); }
.risk-take strong.mono { font-size: 17px; }
.risk-foot { margin-top: 12px; font-size: 13px; }

/* the funded playbook block on the account page: the stage, then the trade it
   asks for. Framed rather than tinted — it sits under the preset, not instead of it. */
.playbook { margin-top: 16px; padding: 12px 14px; border: 1px dashed var(--border); border-radius: var(--radius-token); }
.playbook-head { margin: 0 0 6px; font-size: 14px; }
.playbook-head strong { text-transform: uppercase; letter-spacing: .04em; font-size: 12px; color: var(--pos); }
.playbook p { margin: 6px 0 0; }
.playbook .risk-take.play { background: var(--surface-2); }
/* the cash-out call to action: the gate is met, so the instruction is a button
   and not a sentence pointing at the bottom of the page. */
.playbook-cta { margin-top: 10px !important; display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.playbook-cta .muted { font-size: 12px; }
.btn-inline { padding: 8px 14px; font-size: 14px; }

/* ---------- auth ---------- */
.auth { max-width: 380px; margin: 48px auto; padding: 24px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); }
.auth h1 { margin-bottom: 4px; }
/* The brand over a sign-in card. These pages carry no top bar, so this is the
   only thing telling a visitor whose password box this is. Sized between the
   bar's 30px and its 64px desktop form: big enough to read as the brand, not
   so big it outweighs the form under it. Two classes deep so it holds against
   the desktop `.brand-mark { height: 64px }` without needing a media query. */
.auth-brand { justify-content: center; margin: 48px auto 18px; }
.auth-brand .brand-mark { height: 52px; }
.auth-brand .brand-text { font-size: 32px; }
.auth-brand + .auth { margin-top: 0; }
.error { background: var(--neg-weak); color: var(--neg); padding: 10px 12px; border-radius: var(--radius-token); margin-bottom: 14px; font-size: 14px; }
.flash { background: var(--pos-weak); color: var(--pos); padding: 10px 12px; border-radius: var(--radius-token); margin-bottom: 14px; font-size: 14px; }

/* ---------- lists ---------- */
.filters { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 16px; }
.filters select, .filters input { width: auto; flex: 1 1 120px; margin-top: 0; }
/* A filters row whose controls carry a label above them (Settings → Trade card
   defaults): the labels are the flex items, so the row is label + control
   tall, and a button left to stretch became a 79px square. Bottom-align the
   row and drop the label's block margin, so the button lines up with the
   selects at their own height. */
.filters-labeled { align-items: flex-end; }
.filters-labeled > label { display: flex; flex-direction: column; gap: 4px; margin: 0; flex: 1 1 auto; white-space: nowrap; }
/* flex: auto, not the row's `1 1 120px` — inside a column label that basis
   would become the select's HEIGHT. */
.filters-labeled > label > select { width: 100%; flex: 0 0 auto; }
/* The same height the selects have (the unlabelled filters rows get that
   for free by stretching); a natural-height button beside 46px selects
   read as a different control. */
.filters-labeled > .btn-sm { flex: 0 0 auto; align-self: flex-end; padding-top: 10px; padding-bottom: 10px; font-size: 16px; }
.month-head { display: flex; justify-content: space-between; align-items: baseline; margin: 18px 0 8px; font-weight: 600; }
.rows { list-style: none; margin: 0; padding: 0; }
.rows li { margin-bottom: 8px; }
.rowlink {
  display: block; background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 12px 14px; color: var(--text);
  box-shadow: var(--shadow);
}
.rowlink:hover { text-decoration: none; background: var(--surface-2); }
/* expense row + inline "register in book" action for costs not yet on an account */
.exprow { display: flex; align-items: stretch; gap: 8px; }
.exprow .rowlink { flex: 1 1 auto; min-width: 0; }
.exprow-add {
  flex: 0 0 auto; display: flex; align-items: center; padding: 0 14px;
  border: 1px dashed var(--border); border-radius: var(--radius);
  background: var(--surface); color: var(--muted);
  font-size: 13px; font-weight: 600; white-space: nowrap;
}
.exprow-add:hover { text-decoration: none; color: var(--accent); border-color: var(--accent); background: var(--surface-2); }
.row-main { display: flex; align-items: center; gap: 8px; }
.row-date { font-variant-numeric: tabular-nums; font-size: 13px; color: var(--muted); flex: 0 0 auto; }
.row-title { font-weight: 600; flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.row-sub { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-top: 6px; font-size: 14px; }
.badge { font-size: 12px; padding: 2px 8px; border-radius: var(--radius-token); background: var(--bg); border: 1px solid var(--border); color: var(--muted); }
.chip { font-size: 12px; padding: 2px 8px; border-radius: var(--radius-token); background: var(--bg); border: 1px solid var(--border); }
.chip.ok { background: var(--pos-weak); color: var(--pos); border-color: transparent; }
.chip.bad { background: var(--neg-weak); color: var(--neg); border-color: transparent; }
.chip.appr { background: var(--accent-weak); color: var(--accent); border-color: transparent; }
.chip.book { background: var(--accent-weak); color: var(--accent); border-color: transparent; font-variant-numeric: tabular-nums; }
.empty { text-align: center; padding: 32px 16px; color: var(--muted); display: flex; flex-direction: column; gap: 12px; align-items: center; }
.plain { list-style: none; padding: 0; margin: 0; }
.plain li { padding: 6px 0; border-top: 1px solid var(--border); }

/* linked-cost rows (book account ↔ expenses) */
.linkrow { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.linkrow-main { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px; color: var(--text); flex: 1 1 auto; min-width: 0; }
.linkrow-main .mono { color: var(--muted); font-size: 13px; }
.inline-form { margin: 0; flex: 0 0 auto; }
/* Settings → NinjaTrader feed: its options read left, with the card's own text,
   each a bold line over a muted one; the webhook field carries its Save beside it. */
.nt8-opt { max-width: 760px; margin: 0 0 18px; }
.nt8-opt label strong { color: var(--text); }
.nt8-opt-row { display: flex; gap: 10px; align-items: center; }
.nt8-opt-row input { margin-top: 0; flex: 1; min-width: 0; }
.nt8-opt-row button { flex: 0 0 auto; }
.inline-form .btn-link { background: none; border: 0; cursor: pointer; padding: 0; font: inherit; }
.filters .inline-lbl { display: flex; align-items: center; gap: 6px; margin: 0; flex: 0 0 auto; }
.filters .inline-lbl input { flex: 0 0 auto; width: 64px; }
.move-form { display: inline-flex; gap: 2px; }
.move-form .btn-link { font-size: 11px; line-height: 1; padding: 2px 3px; }
.move-form .btn-link:disabled { opacity: .25; cursor: default; }
.seed-note { margin-bottom: 12px; }

/* reset trail (account lineage) */
.trailrail { list-style: none; margin: 8px 0 0; padding: 0; }
.trailrail li { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 8px 0 8px 16px; border-left: 2px solid var(--border); position: relative; }
.trailrail li::before { content: ""; position: absolute; left: -5px; top: 14px; width: 8px; height: 8px; border-radius: 50%; background: var(--border); }
.trailrail li.here { font-weight: 600; }
.trailrail li.here::before { background: var(--accent); }
.trail-num { font-variant-numeric: tabular-nums; }
.trail-meta { font-size: 13px; font-weight: 400; }
.trail-tot { margin-top: 12px; font-size: 14px; }

/* ---------- dashboard ---------- */
.hero {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 24px 16px; text-align: center; margin-bottom: 16px; box-shadow: var(--shadow);
}
.hero.pos { background: var(--pos-weak); border-color: transparent; }
.hero.neg { background: var(--neg-weak); border-color: transparent; }
.hero-label { font-size: 12px; letter-spacing: .08em; color: var(--muted); }
.hero-num { font-variant-numeric: tabular-nums; font-size: 40px; font-weight: 700; line-height: 1.1; margin: 4px 0; }
.hero.pos .hero-num { color: var(--pos); }
.hero.neg .hero-num { color: var(--neg); }
.hero-sub { font-variant-numeric: tabular-nums; font-size: 18px; color: var(--muted); }
.hero-meta, .hero-foot { font-size: 13px; color: var(--muted); margin-top: 6px; }

.stat-grid, .stats { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 16px; }
.stat { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 12px 14px; box-shadow: var(--shadow); }
.stat-k { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; }
.stat-v { font-variant-numeric: tabular-nums; font-size: 22px; font-weight: 700; margin: 2px 0; }
.stat-s, .stat-d { font-size: 12px; color: var(--muted); }
.stat-unit { font-size: 13px; font-weight: 400; color: var(--muted); }

.table-wrap { overflow-x: auto; }
table.data, table.metrics { width: 100%; border-collapse: collapse; font-size: 14px; }
table.data th, table.metrics th { text-align: left; font-size: 12px; color: var(--muted); font-weight: 600; padding: 6px 8px; border-bottom: 1px solid var(--border); }
table.data td, table.metrics td { padding: 8px; border-bottom: 1px solid var(--border); }
table .num, table.data th.num, td.num { text-align: right; font-variant-numeric: tabular-nums; }
table tr:last-child td { border-bottom: 0; }

.chips { display: flex; flex-wrap: wrap; gap: 8px; }
.typechip { background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius-token); padding: 6px 12px; font-size: 14px; }

.months { display: flex; flex-direction: column; gap: 8px; }
.mrow, .bar-row { display: grid; grid-template-columns: 56px 1fr 72px; align-items: center; gap: 10px; }
.mlabel, .bar-label { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
.mbars { display: flex; flex-direction: column; gap: 3px; }
.mbars .bar, .bar-track { height: 9px; border-radius: 4px; }
.bar-track { position: relative; background: var(--bg); display: flex; flex-direction: column; gap: 3px; height: auto; }
.bar { height: 9px; border-radius: 4px; min-width: 2px; }
.bar.spend { background: var(--neg); }
.bar.payout { background: var(--pos); }
.mnet, .bar-net { text-align: right; font-variant-numeric: tabular-nums; font-size: 13px; }
.dot { display: inline-block; width: 9px; height: 9px; border-radius: 2px; vertical-align: middle; }
.dot.spend { background: var(--neg); }
.dot.payout { background: var(--pos); }

/* ---------- eval funnel (bought -> passed -> paid) ---------- */
.funnel-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 6px; }
.funnel-head h2 { margin: 0; }
.funnel-head .chip.book { text-decoration: none; }
.funnel-note { font-size: 12.5px; color: var(--muted); line-height: 1.45; margin: 0 0 16px; }
.funnel-note strong { color: var(--text); font-weight: 600; }
.funnel { display: flex; flex-direction: column; gap: 2px; }
.fstage { display: grid; grid-template-columns: 72px 1fr 48px; align-items: center; gap: 10px; }
.flabel { font-size: 13px; color: var(--muted); }
.ftrack { background: var(--bg); border-radius: 4px; height: 16px; overflow: hidden; }
.fbar { height: 16px; border-radius: 4px; min-width: 3px; }
.fbar.bought { background: var(--accent); }
.fbar.passed { background: var(--accent); opacity: .7; }
.fbar.paid { background: var(--pos); }
.fval { text-align: right; font-variant-numeric: tabular-nums; font-size: 16px; font-weight: 700; }
.frate { padding: 3px 0 3px 82px; font-size: 13px; color: var(--muted); }
.frate .fpct { font-weight: 700; color: var(--text); font-variant-numeric: tabular-nums; }
.funnel-break { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 14px; }
.fbreak-label { font-size: 12px; color: var(--muted); margin-right: 2px; }
.funnel-break .chip { font-variant-numeric: tabular-nums; }
.funnel-foot { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border); font-size: 12px; }

/* ---------- calendar ---------- */
/* cal_head() (v5.63): the one header all three month grids use. The switch or
   title on the left, the arrows on the right, and the lede on its own line
   under them — so switching pages, or Calendar <-> By account, never moves
   the arrows, and no text floats beside them off-centre. */
.cal-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap; margin-bottom: 10px;
}
.cal-head-left { display: flex; align-items: center; gap: 12px; min-height: 38px; }
.cal-head-left h1 { margin: 0; }
.cal-head-left .jtabs { margin-bottom: 0; }
.cal-lede { margin: 0 0 14px; }
.cal-nav { display: flex; align-items: center; gap: 10px; }
.cal-month { font-weight: 600; min-width: 7.5em; text-align: center; }
.nav-arrow {
  display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; border-radius: var(--radius-token);
  background: var(--surface); border: 1px solid var(--border); color: var(--text);
  font-size: 20px; line-height: 1;
}
.nav-arrow:hover { background: var(--surface-2); text-decoration: none; }
.cal-grid { display: grid; grid-template-columns: repeat(5, 1fr) .5fr .5fr; gap: 4px; }
/* Saturday and Sunday are half width (v5.166): nobody trades them. Sunday first is
   a setting; then Sunday leads and Saturday closes the row. */
.cal-grid.wk-sun { grid-template-columns: .5fr repeat(5, 1fr) .5fr; }
/* a narrow weekend cell takes the row's height instead of staying square */
.cal-cell.we { aspect-ratio: auto; }
.cal-dow { text-align: center; font-size: 12px; color: var(--muted); padding-bottom: 4px; }
.cal-cell {
  aspect-ratio: 1 / 1; position: relative; border-radius: var(--radius-token);
  background: var(--surface-2); color: var(--text);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  overflow: hidden; padding: 2px;
}
a.cal-cell:hover { text-decoration: none; }
/* An overlay, not a filter: `brightness()` also dims the text it passes through,
   and it can only go one direction — the dark theme needs the cell to come
   forward, not recede. `.cal-cell` is already positioned. */
a.cal-cell:hover::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  background: var(--cell-hover); pointer-events: none;
}
.cal-cell.out { background: transparent; pointer-events: none; }
.cal-cell.none { background: var(--surface-2); }
.cal-cell.pos { background: var(--pos-weak); }
.cal-cell.neg { background: var(--neg-weak); }
.cal-cell.flat { background: var(--surface-2); }
.cal-cell.today { outline: 2px solid var(--accent); outline-offset: -2px; }
.cal-day { position: absolute; top: 3px; left: 5px; font-size: 12px; font-weight: 600; color: var(--muted); }
/* Mobile: colour-only. A 7-col grid of square cells is too cramped to fit a
   readable number on phones and cover screens, so we lean on the cell tint +
   legend instead. The per-day net returns on desktop (>=768px) — see below. */
.cal-amt { display: none; }
.cal-cell.pos .cal-amt { color: var(--pos); }
.cal-cell.neg .cal-amt { color: var(--neg); }
.cal-legend { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 12px; font-size: 12px; color: var(--muted); }
.cal-legend .legend-label { font-weight: 600; }
.cal-legend .sw { width: 14px; height: 14px; border-radius: 4px; display: inline-block; vertical-align: middle; }
.cal-legend .sw.pos { background: var(--pos-weak); }
.cal-legend .sw.neg { background: var(--neg-weak); }
.cal-legend .sw.none { background: var(--surface-2); }
/* Grid stretches the three columns to equal height; each is a flex column with
   the value pushed to the bottom, so the values stay aligned even when a label
   like "Payouts (paid)" wraps to two lines. The <br> in the markup is the
   no-CSS fallback (keeps label-over-value if this rule ever fails to load);
   it's hidden once flex is doing the stacking. */
.cal-summary { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; text-align: center; }
.cal-summary > div { display: flex; flex-direction: column; gap: 4px; }
.cal-summary > div br { display: none; }
.cal-summary strong { font-size: 18px; margin-top: auto; }
.cal-pop {
  position: absolute; z-index: 50; min-width: 168px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow-lg); padding: 6px;
  display: flex; flex-direction: column; gap: 2px;
}
.cal-pop-title { font-size: 12px; color: var(--muted); padding: 4px 8px 2px; }
.cal-pop a { display: block; padding: 9px 10px; border-radius: var(--radius-token); color: var(--text); font-size: 14px; }
.cal-pop a:hover { background: var(--surface-2); text-decoration: none; }

/* ---------- book ---------- */
/* The explainer card (v5.128, lib/quickstart.php): "What is the Book?", a few
   lines, one Learn more button and a Don't show again link. No steps, no
   state beyond the dismissal. Same card as everything else, an accent rule
   on the left so it reads as "read me", not as data. */
.quickstart { border-left: 3px solid var(--accent); max-width: 72ch; }
.quickstart h2 { margin: 0 0 8px; }
.quickstart p { margin: 0 0 10px; }
.qs-list { margin: 0 0 14px; padding-left: 20px; display: grid; gap: 6px; }
.qs-list b { font-weight: 700; }
.qs-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 18px; }
.warnbox { background: var(--warn-weak); color: var(--warn-ink); border: 1px solid var(--warn-border); padding: 10px 12px; border-radius: var(--radius-token); margin-bottom: 14px; font-size: 14px; }
.book-bar { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 12px; }
.seg-links { display: inline-flex; gap: 2px; background: var(--surface-2); border-radius: var(--radius-token); padding: 3px; }
.seg-links a { padding: 5px 14px; border-radius: var(--radius-token); color: var(--muted); font-size: 14px; font-weight: 500; }
.seg-links a:hover { text-decoration: none; }
.seg-links a.on { background: var(--surface); color: var(--text); box-shadow: var(--shadow); }

.book-list .book-acct { display: block; }
.book-acct .row-sub { gap: 8px; }
.row-spacer { flex: 1 1 auto; }
.idle { font-size: 12px; }
.badge.bad { background: var(--neg-weak); color: var(--neg); border-color: transparent; }
.ochip {
  display: inline-flex; align-items: center; justify-content: center; min-width: 22px;
  padding: 1px 6px; border-radius: var(--radius-token); font-size: 12px; font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.ochip.w    { background: var(--pos-weak); color: var(--pos); }
.ochip.l    { background: var(--neg-weak); color: var(--neg); }
.ochip.be   { background: var(--warn-weak); color: var(--warn); }
.ochip.none { background: var(--surface-2); color: var(--muted); }

.book-state .bs-head { display: flex; justify-content: space-between; align-items: center; gap: 8px; margin-bottom: 12px; }
.bs-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; }
.bs-grid > div { display: flex; flex-direction: column; gap: 2px; }
.bs-grid .stat-k { font-size: 11px; }
.bs-grid .stat-v { font-size: 18px; font-weight: 700; }
.bs-grid .manual { font-size: 11px; font-weight: 500; color: var(--accent); }
/* v4.78: the floor figure IS the editor — same <details> disclosure as the
   History balances. Inside a stat tile the form reads left-to-right like the
   tile does, not right-aligned like a table cell. */
.bs-grid .floorset { display: inline-block; }
.bs-grid .floorset .riskset-form { justify-content: flex-start; margin: 4px 0 0; }
.bs-grid .floorset .riskset-form input[type="text"] { font-size: 15px; }
.bs-rules { margin: 14px 0 0; font-size: 13px; }
/* v5.137: the progress card on the account page — the Book's bar at full width. */
.pcard { margin-top: 14px; padding: 14px 16px; border: 1px solid var(--border); border-radius: 10px; background: var(--surface-2); }
.pcard .stat-k { font-size: 11px; text-transform: uppercase; letter-spacing: .06em; }
.pcard-v { font-size: 22px; font-weight: 700; margin-top: 4px; }
.pcard-sub { font-size: 13px; margin-top: 2px; }
.pbar.full { width: 100%; height: 6px; margin-top: 30px; }
.pcard-ends { display: flex; justify-content: space-between; gap: 12px; margin-top: 10px; }
.pcard-ends > div { display: flex; flex-direction: column; gap: 2px; font-weight: 700; }
.pcard-ends > div:last-child { text-align: right; }
.pbar-lbl { display: none; }
.pbar.full .pbar-lbl { display: block; position: absolute; bottom: calc(100% + 3px); left: 50%; transform: translateX(-50%);
  font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); white-space: nowrap; }

/* book grid: accounts (rows) × days (cols). Stretches to the card so a full month
   fits without horizontal scrolling on a desktop; the min-widths keep the cells
   readable and hand the row back to .table-wrap's scroll on a phone. */
table.book-grid {
  border-collapse: collapse; font-size: 12px;
  table-layout: fixed; width: 100%; min-width: 900px;   /* fixed: the day columns split the leftover evenly */
}
table.book-grid th.bg-day {
  text-align: center; font-size: 11px; color: var(--muted);
  font-weight: 600; padding: 2px 0; border-bottom: 1px solid var(--border);
}
table.book-grid th.bg-day.we { color: var(--border-strong); }
table.book-grid th.bg-day.today { color: var(--accent); }
table.book-grid th.bg-acct {
  position: sticky; left: 0; z-index: 1; background: var(--surface);
  text-align: left; padding: 5px 12px 5px 0; width: 184px;
  border-bottom: 1px solid var(--border); font-weight: 600;
}
table.book-grid th.bg-acct a {
  color: var(--text); display: block;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Rows are near-identical by label ("50k Flex" × 20), so the number leads. */
.bg-num { font-weight: 700; font-variant-numeric: tabular-nums; }
.bg-label { font-weight: 400; color: var(--muted); margin-left: 5px; }
.bg-sub { display: flex; align-items: center; gap: 6px; margin-top: 1px; }
.bg-firm {
  font-size: 11px; font-weight: 400; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.bg-phase {
  flex: 0 0 auto; font-size: 10px; font-weight: 600; letter-spacing: .03em;
  padding: 1px 6px; border-radius: var(--radius-token); background: var(--surface-2); color: var(--muted);
}
.bg-phase.funded { background: var(--accent-weak); color: var(--accent); }
/* Block break between "last traded on" groups; labelled in front of the idle tail. */
table.book-grid tr.bg-break td {
  height: 9px; padding: 0; border-bottom: 1px solid var(--border); background: none;
}
table.book-grid tr.bg-break.labelled td {
  height: auto; padding: 16px 0 5px; border-bottom: 0;
  font-size: 11px; font-weight: 600; text-transform: uppercase;
  letter-spacing: .05em; color: var(--muted);
}
.bcell {
  width: 26px; min-width: 26px; height: 26px; text-align: center; vertical-align: middle;
  border-radius: var(--radius-token); font-size: 11px; font-weight: 700; color: var(--muted);
  border: 2px solid var(--bg);
}
.bcell.none   { background: var(--surface-2); color: transparent; }
.bcell.seed   { background: var(--surface-2); color: var(--muted); }
.bcell.up     { background: var(--pos-weak); color: var(--pos); }
.bcell.down   { background: var(--neg-weak); color: var(--neg); }
.bcell.be     { background: var(--warn-weak); color: var(--warn); }
.bcell.passed { background: var(--accent-weak); color: var(--accent); }
.bcell.blown  { background: var(--neg); color: var(--on-solid); }
.cal-legend .legend-note { margin-left: auto; font-style: italic; }
.cal-legend .sw.up     { background: var(--pos-weak); }
.cal-legend .sw.be     { background: var(--warn-weak); }
.cal-legend .sw.down   { background: var(--neg-weak); }
.cal-legend .sw.passed { background: var(--accent-weak); }
.cal-legend .sw.blown  { background: var(--neg); }

/* ---- History: the DAY calendar (v4.27) ---- */
/* Its header is cal_head() (v5.63), shared with the other two month grids. */
/* Cells are NOT square here: a day carries a record, a bar and a net, so height
   is content-driven and the extra width of the fluid page is welcome (nothing is
   capped — see the layout note at the top). Mobile is seven columns with the
   record only; the week-total column and the bar/net join at >=768px. */
.cal-grid.bcal { grid-template-columns: repeat(5, 1fr) .5fr .5fr; gap: 4px; }
.cal-grid.bcal.wk-sun { grid-template-columns: .5fr repeat(5, 1fr) .5fr; }
.cal-dow.wk { display: none; color: var(--border-strong); }
.bcal-cell {
  aspect-ratio: auto; min-height: 66px;
  align-items: center; justify-content: center; gap: 3px;
  padding: 17px 3px 15px; text-decoration: none;
}
.bcal-cell.none     { background: var(--surface-2); }
.bcal-cell.pay-only { background: var(--surface-2); }
.bcal-cell.w        { background: var(--pos-weak); }
.bcal-cell.l        { background: var(--neg-weak); }
.bcal-cell.e        { background: var(--warn-weak); }
/* The Book calendar shows the whole week (v5.163): a day of the next or previous
   month keeps its colour and its link, a little faded, instead of going blank. */
.cal-cell.bcal-cell.out.w { background: var(--pos-weak); }
.cal-cell.bcal-cell.out.l { background: var(--neg-weak); }
.cal-cell.bcal-cell.out.e { background: var(--warn-weak); }
.cal-cell.bcal-cell.out:not(.none) { pointer-events: auto; opacity: .7; }
.cal-cell.bcal-cell.out.none { background: transparent; }
/* By account: slide the 31 days a week at a time (v5.164). */
.bg-slide { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 10px; }
.bg-day .bg-mon { display: block; font-size: 10px; font-weight: 600; color: var(--muted); text-transform: uppercase; }
/* pass/blow/payout counts: centred under the record on a phone (a 45px cell has
   no free corner), in the top-right corner opposite the day number on desktop */
.bcal-tags {
  position: absolute; bottom: 2px; left: 0; right: 0;
  display: flex; justify-content: center; gap: 3px;
}
.bcal-tag {
  display: inline-flex; align-items: center; border-radius: var(--radius-token);
  padding: 0 4px; font-size: 10px; font-weight: 700; line-height: 16px;
  font-variant-numeric: tabular-nums;
}
.bcal-tag.pass { background: var(--accent-weak); color: var(--accent); }
.bcal-tag.blow { background: var(--neg); color: var(--on-solid); }
/* The payout tag carries the AMOUNT withdrawn, in full — it's cash out of the
   book, not a count worth a glyph. A phone cell can't hold "$1,200.00", so it
   keeps the bare $ and the amount joins at >=768px (the day's net does the same). */
.bcal-tag.pay  {
  background: var(--surface); color: var(--muted); white-space: nowrap;
  border: 1px solid var(--border); line-height: 14px;   /* reads on a grey cell */
}
.bcal-tag.pay .pay-lg { display: none; }
/* The day's record IS the headline — one W/L per account, wrapping on a phone. */
.bcal-rec {
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: center;
  gap: 0 5px; font-size: 12px; font-weight: 700; line-height: 1.15;
  font-variant-numeric: tabular-nums;
}
.bcal-rec .bc-w  { color: var(--pos); }
.bcal-rec .bc-l  { color: var(--neg); }
.bcal-rec .bc-be { color: var(--warn); }
.bcal-bar { display: none; }
.bcal-net { display: none; }
/* week totals column (desktop only — see the media query) */
.bcal-wk {
  display: none; flex-direction: column; align-items: center; justify-content: center;
  gap: 2px; border-radius: var(--radius-token); background: var(--surface-2);
  padding: 6px 4px; font-size: 11px; text-align: center;
}
.bcal-wk.empty { background: transparent; }
.bcal-wk-rec { font-weight: 700; font-variant-numeric: tabular-nums; }
.bcal-wk-rec .bc-w { color: var(--pos); }
.bcal-wk-rec .bc-l { color: var(--neg); }
.bcal-wk-net { font-weight: 700; }
.bcal-wk-sub { font-size: 10px; }
.bcal-card .cal-legend .bcal-tag { line-height: 15px; }

/* ---- PropBook v2 screen ---- */
.book .page-head { margin-bottom: 12px; }
.num { font-variant-numeric: tabular-nums; }
.chip.eval { background: var(--surface-2); color: var(--muted); border-color: transparent; }

/* 1. reminder bar */
.reminder {
  display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 18px 20px; margin-bottom: 14px; box-shadow: var(--shadow);
}
.reminder-line { margin: 0; font-size: 17px; font-weight: 600; }
.bullets { display: flex; align-items: center; gap: 10px; }
.pips { display: inline-flex; gap: 4px; }
.pip { width: 12px; height: 18px; border-radius: 3px; background: var(--surface-2); }
.pip.live { background: var(--accent); }
.pip.spent { background: var(--border); }
.pip.none { background: var(--surface-2); }
.bullets-txt { font-size: 13px; color: var(--muted); }
.bullets-txt strong { color: var(--text); }

/* 2. operational strip */
.opstrip { display: flex; flex-wrap: wrap; gap: 28px; padding: 4px 4px 14px; }
.opstrip > div { display: flex; flex-direction: column; gap: 2px; }
/* Owner only: the whole fleet (manual + Hail Mary) above the manual strip, built to be
   screenshotted and shared. Deliberately the same dark card in both themes, like the
   firm badges: a shared picture should not depend on the theme it was taken in. So its
   colours are its own and live here. */
.fleet-card {
  --fc-bg: #0d1220; --fc-bg-2: #15233d; --fc-ink: #f2f5fa; --fc-dim: #9aa6bb;
  --fc-pos: #4ade80; --fc-neg: #f87171; --fc-hm: #5a9bff; --fc-track: rgba(255,255,255,.10);
  position: relative; overflow: hidden;
  margin: 0 0 18px; padding: 22px 22px 18px;
  border-radius: 16px; color: var(--fc-ink);
  background:
    radial-gradient(120% 90% at 100% 0%, rgba(74,222,128,.16), transparent 55%),
    linear-gradient(135deg, var(--fc-bg), var(--fc-bg-2));
  box-shadow: var(--shadow-lg);
}
.fc-head { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; }
.fc-k { font-size: 12px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--fc-dim); }
.fc-date { font-size: 13px; color: var(--fc-dim); font-variant-numeric: tabular-nums; }
.fc-stats { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; margin: 14px 0 18px; align-items: end; }
@media (min-width: 900px) { .fc-stats { grid-template-columns: 1fr 1fr 1fr 1.3fr; gap: 28px; } }
.fc-graph { grid-column: 1 / -1; display: flex; flex-direction: column; gap: 4px; }
@media (min-width: 900px) { .fc-graph { grid-column: auto; } }
.fc-graph svg { display: block; width: 100%; height: 90px; overflow: visible; }
/* The costs toggle swaps two drawings of the curve (book.php): green alone, or green and
   the red costs line on one shared scale. */
.fleet-card .fc-both, .fleet-card.fc-costs-on .fc-solo { display: none; }
.fleet-card.fc-costs-on .fc-both { display: inline; }
.fc-cap { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 4px 10px; }
.fc-tog { display: inline-flex; align-items: center; gap: 6px; padding: 2px 9px; border: 1px solid var(--fc-track);
  border-radius: 999px; background: none; color: var(--fc-dim); font: inherit; font-size: 12px; cursor: pointer;
  font-variant-numeric: tabular-nums; }
.fc-tog i { width: 8px; height: 8px; border-radius: 50%; border: 1.5px solid var(--fc-neg); }
.fc-tog:hover { color: var(--fc-ink); }
.fc-tog[aria-pressed="true"] { color: var(--fc-ink); border-color: rgba(248,113,113,.45); }
.fc-tog[aria-pressed="true"] i { background: var(--fc-neg); }
.fc-tog-v { display: none; }
.fc-tog[aria-pressed="true"] .fc-tog-v { display: inline; color: var(--fc-neg); }
.fc-stats > div { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.fc-v { font-family: 'Anton', var(--sans); font-size: clamp(32px, 9.5vw, 64px); line-height: 1; letter-spacing: .01em; }
.fc-pos { color: var(--fc-pos); }
.fc-l { font-size: 13px; color: var(--fc-dim); line-height: 1.3; }
.fc-info { display: inline-grid; place-items: center; margin-left: 2px; padding: 2px; border: 0;
  background: none; color: inherit; cursor: pointer; vertical-align: -3px; }
.fc-info svg { display: block; width: 15px; height: 15px; }
.fc-info:hover, .fc-info:focus-visible { color: var(--fc-ink); }
/* The curve's explainer: a popover, so it sits in the top layer and the card's overflow
   cannot clip it. Same dark share-card look; the --fc-* tokens inherit from the card. */
.fc-pop { width: min(380px, calc(100vw - 32px)); margin: auto; padding: 20px 22px 18px;
  border: 1px solid var(--fc-track); border-radius: 14px; color: var(--fc-ink);
  background: linear-gradient(135deg, var(--fc-bg), var(--fc-bg-2)); box-shadow: var(--shadow-lg);
  font-size: 14px; line-height: 1.5; }
.fc-pop:not(:popover-open) { display: none; }   /* closed stays closed, whatever sets display */
.fc-pop::backdrop { background: rgba(8, 12, 22, .35); }
.fc-pop h3 { margin: 0 24px 8px 0; font-size: 12px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--fc-dim); }
.fc-pop p { margin: 0 0 10px; }
.fc-pop ul { margin: 0 0 12px; padding-left: 18px; }
.fc-pop li { margin: 4px 0; }
.fc-pop b { color: var(--fc-pos); font-weight: 600; }
.fc-pop b.fc-red { color: var(--fc-neg); }
.fc-pop .fc-pop-note { margin: 0; padding-top: 10px; border-top: 1px solid var(--fc-track); font-size: 13px; color: var(--fc-dim); }
.fc-pop-x { position: absolute; top: 10px; right: 12px; padding: 2px 6px; border: 0; background: none;
  color: var(--fc-dim); font-size: 20px; line-height: 1; cursor: pointer; }
.fc-pop-x:hover { color: var(--fc-ink); }
.fc-split { height: 8px; border-radius: 999px; background: var(--fc-hm); overflow: hidden; }
.fc-split > span { display: block; height: 100%; background: var(--fc-pos); }
.fc-legend { display: flex; flex-wrap: wrap; gap: 6px 18px; margin-top: 10px; font-size: 14px; font-variant-numeric: tabular-nums; }
.fc-legend i { display: inline-block; width: 9px; height: 9px; border-radius: 50%; margin-right: 7px; vertical-align: 1px; }
.fc-man { background: var(--fc-pos); }
.fc-hm { background: var(--fc-hm); }
.fc-foot { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 8px 16px; margin-top: 18px; padding-top: 14px;
  border-top: 1px solid var(--fc-track); font-size: 14px; color: var(--fc-dim); }
.fc-foot b { color: var(--fc-ink); font-weight: 600; }
.fc-brand { font-weight: 600; color: var(--fc-ink); letter-spacing: .02em; }
.op-k { font-size: 11px; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); }
.op-v { font-size: 22px; font-weight: 700; font-variant-numeric: tabular-nums; }
/* v4.77: the farm tiles carry a second line — the split behind a count, the
   account count behind a capital figure. Muted and small: it qualifies the
   headline number, it never competes with it. (.pos/.neg are the global
   figure colours — nothing extra needed here.) */
.op-sub { font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums; }

.book-alert { margin-bottom: 14px; }
.book-tabs { margin-bottom: 16px; }

/* --- the tab row carries today's red-folder USD releases (v4.104) ---
   The strip rides the tab line rather than taking a band of its own: the
   account table is the page, and a news bar that pushes it down costs more
   than it tells you. Static text — the times are printed once, server-side,
   in New York time. No countdown, no interval, nothing to keep alive.
   Below 900px it drops onto its own line under the tabs (see the media
   block at the bottom of this section) because 3 tabs + 3 events do not
   share a phone width. */
.book-tabrow {
  display: flex; align-items: center; gap: 12px 16px; flex-wrap: wrap;
  margin-bottom: 16px;
}
.book-tabrow .book-tabs { margin-bottom: 0; }
.newsbar {
  display: flex; align-items: center; gap: 6px 14px; flex-wrap: wrap;
  min-width: 0; margin-left: auto;
  font-size: 13px; line-height: 1.35; color: var(--text);
}
.news-ev { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
/* Flat fills, like every other indicator in this sheet (.pip, .cal-legend .sw).
   These were 🔴/🟢/⚪ until v4.113 — the emoji glyphs are drawn with a gradient
   by the system font, and this app has no gradient anywhere else. */
.news-dot { flex: 0 0 auto; width: 7px; height: 7px; border-radius: 50%; background: var(--muted); }
.news-dot.red { background: var(--neg); }
.news-dot.clear { background: var(--pos); }
.news-dot.unknown { background: transparent; box-shadow: inset 0 0 0 1.5px var(--border-strong); }
.news-time { font-weight: 600; color: var(--text); }
.news-title { color: var(--muted); }
/* Truncation is a tooltip away, never a lost event: the title on .newsbar
   always lists the full day. */
.news-more {
  padding: 1px 7px; border-radius: var(--radius-token);
  background: var(--surface-2); color: var(--muted);
  font-size: 12px; font-weight: 600;
}
/* Trump (v5.136): a solid red chip, the loudest thing on the tab row — his
   events are listed whatever their FF impact, see ff_is_trump(). */
.news-ev.trump {
  padding: 2px 8px; border-radius: var(--radius-token);
  background: var(--neg); cursor: help;
}
.newsbar .news-ev.trump .news-time, .newsbar .news-ev.trump .news-title { color: var(--on-solid); font-weight: 700; }
.newsbar.clear .news-txt, .newsbar.unavail .news-txt { color: var(--muted); }
.newsbar.unavail { cursor: help; }
.newsbar.is-stale .news-time { color: var(--muted); }
@media (max-width: 899px) {
  .newsbar { margin-left: 0; width: 100%; }
}

/* 3. ranked listing (Live status): the order to spend the day's bullets */
/* v4.16 (supersedes the v4.10 viewport bleed, which read as a jumping
   container): the ranked tables sit INSIDE the shared page column like every
   other surface — a calm bordered wrap, edge cells padded, internal scroll
   only when the window is genuinely narrower than the table. */
.rankt-bleed {
  overflow-x: auto;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow);
  margin-bottom: 16px;
}
table.rankt { border-collapse: collapse; width: 100%; min-width: 1080px; font-size: 13px; }
/* one uniform gutter for every column — 8px a side since v4.31 (10px before),
   the same on every tab, so the edge insets below still line up. The v4.17
   per-tab 8px 4px squeeze stays gone; it made the gutters uneven. */
table.rankt th, table.rankt td { padding: 9px 8px; border-bottom: 1px solid var(--border); text-align: left; vertical-align: middle; }
/* edge cells carry the inset the card's padding used to provide */
table.rankt th:first-child, table.rankt td:first-child { padding-left: 16px; }
table.rankt th:last-child, table.rankt td:last-child { padding-right: 12px; }
table.rankt thead th { font-size: 11px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); font-weight: 600; white-space: nowrap; }
table.rankt tbody tr:last-child td { border-bottom: 0; }
table.rankt tr.traded { opacity: .55; }
table.rankt th.num, table.rankt td.num { text-align: right; }
.rt-rank { white-space: normal; }
.rt-rank strong { font-size: 17px; font-variant-numeric: tabular-nums; margin-right: 6px; }
/* v4.17: chips stack under the rank number — the row of chips was the widest
   thing in the column */
.rt-rank .rchip { display: block; width: max-content; margin-top: 3px; }
.rchip {
  display: inline-block; padding: 1px 8px; border-radius: var(--radius-token);
  font-size: 11px; font-weight: 600; white-space: nowrap;
}
.rchip.finish  { background: var(--accent-weak); color: var(--accent); }
.rchip.healthy { background: var(--pos-weak); color: var(--pos); }
.rchip.last    { background: var(--neg-weak); color: var(--neg); }
.rchip.done    { background: var(--surface-2); color: var(--muted); }
.rt-acct a { font-weight: 600; color: var(--text); }
/* v4.31 (supersedes the v4.21 uniform width:1%): every column asking for the
   same 1% made the browser hand out the surplus in equal slices REGARDLESS of
   what each column needs — the money columns got squeezed under their content
   and the table pushed past the page, which is what put a horizontal scrollbar
   under the day's plan. Plain auto layout sizes each column to its content and
   spreads what's left in proportion, so the whole row fits the page column —
   no width declarations here at all.
   The account sub-line keeps a cap so Account can't balloon, but as a
   PREFERRED width: it shrinks when the window is tight instead of pushing the
   table past the page. */
.rt-acct .rt-sub { width: auto; max-width: 210px; }
.rt-acct .rt-sub { display: flex; align-items: center; gap: 1px 6px; font-size: 12px; color: var(--muted); margin-top: 2px; white-space: normal; flex-wrap: wrap; }
/* v4.9: the number's last 4 IS the identity mid-session — big, mono, first */
.rt-num { font-size: 20px; font-weight: 700; font-variant-numeric: tabular-nums; letter-spacing: .02em; }
.rt-num:hover { text-decoration: none; color: var(--accent); }
.rt-label { color: var(--text); font-weight: 500; }
/* v4.31: the cell wraps rather than widening the table — the figure and its
   stop count stay glued, the close-drop chip drops to its own line. */
.rt-buf { white-space: normal; }
.rt-buf > strong, .rt-buf > .muted { white-space: nowrap; }
.rt-buf strong { font-variant-numeric: tabular-nums; }
.rt-buf > .chip { display: block; width: max-content; margin-top: 4px; }
.warn-t { color: var(--warn); }
/* v5.183: the balance sits under the account number in every Book table, the
   row's meta tag beside it, and the day's result under it once traded (book.php,
   THE BALANCE LIVES UNDER THE ACCOUNT). It used to move between the buffer cell,
   the result cell, its own column and the end of the row with the row's state. */
.rt-balline { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; margin-top: 3px; }
.rt-balline .rt-meta { margin-top: 0; }
.rt-bal { font-size: 13px; font-weight: 600; color: var(--text); font-variant-numeric: tabular-nums; white-space: nowrap; }
.rt-today { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; margin-top: 4px; font-size: 13px; }
.rt-today strong { white-space: nowrap; font-variant-numeric: tabular-nums; }
/* v5.137: the progress bar — floor on the left, the pass line on the right, a
   START tick between; the fill runs start → balance, green above, red below. */
.pbar { position: relative; display: block; width: 120px; height: 5px; border-radius: 999px; background: var(--border); margin-top: 7px; }
.pbar-fill { position: absolute; top: 0; bottom: 0; border-radius: 999px; }
.pbar-fill.pos { background: var(--pos); }
.pbar-fill.neg { background: var(--neg); }
.pbar-zone { position: absolute; top: 0; bottom: 0; left: 0; border-radius: 999px; background: var(--neg); opacity: .45; }
.pbar-tick { position: absolute; top: -3px; bottom: -3px; width: 2px; margin-left: -1px; border-radius: 1px; background: var(--muted); }
.pbar-tick.orig { background: var(--pos); opacity: .45; }
/* v4.31: same deal — the headline figure never breaks, but the "→ balance",
   "or press", "or finish" and stage lines under it may. */
.rt-loss, .rt-win, .rt-pass { white-space: normal; }
.rt-loss strong, .rt-win strong, .rt-pass strong { white-space: nowrap; font-variant-numeric: tabular-nums; }
.rt-then { display: block; font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
/* a payable account: the stage line doubles as the link that logs the cash-out. */
a.rt-cashout { color: var(--accent); font-weight: 600; }
a.rt-cashout:hover { text-decoration: underline; }
.wpips { display: inline-flex; gap: 3px; }
.wpip { width: 9px; height: 9px; border-radius: 50%; background: var(--surface-2); border: 1px solid var(--border); }
.wpip.on { background: var(--accent); border-color: transparent; }
.rt-atm { font-size: 11.5px; color: var(--muted); }
.rt-atm-row { display: block; white-space: nowrap; }
.rt-atm-row strong { color: var(--text); }
/* v4.59: the loss figure doubles as the PREPLANNING knob — click it, type a
   dollar figure, and that account's whole plan (sizes included) re-derives.
   Native <details>, no JS; the dashed underline is the "this is editable" hint
   and turns accent when a planned figure (not policy) is in force. */
.riskset { display: inline-block; }
.riskset summary { list-style: none; cursor: pointer; user-select: none; }
.riskset summary::-webkit-details-marker { display: none; }
.riskset summary strong { border-bottom: 1px dashed var(--border); }
.riskset summary:hover strong { border-bottom-color: currentColor; }
.riskset.on summary strong { border-bottom: 1px solid var(--accent); }
.riskset-mark {
  display: block; font-size: 10px; font-weight: 700; color: var(--accent);
  text-transform: uppercase; letter-spacing: .04em; text-align: right;
}
.riskset-form {
  display: flex; gap: 6px; align-items: center; justify-content: flex-end;
  flex-wrap: wrap; margin: 6px 0 2px;
}
.riskset-form input[type="text"] { width: 76px; padding: 6px 8px; font-size: 14px; text-align: right; }
/* A full balance (50973.50) needs more room than a risk figure (750.00), and the
   history's balance column reserves the open editor's width so correcting one
   row doesn't shuffle the whole table sideways. */
.riskset-form.wide input[type="text"] { width: 100px; }
.hist-bal { min-width: 192px; }
.riskset-form .btn-sm { white-space: nowrap; }
/* v4.75: settle by hand — the firm's verdict, one click. On the account's state
   card it's a row under the rules line; on every Book row it's the same <details>
   disclosure as the planned figures, kept small and muted so it never competes
   with the day's numbers. Pass reads green on hover, blow red — colour only on
   intent, so neither button shouts from a resting row. */
.settle-cta {
  display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
  margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border);
  font-size: 13px;
}
.settle-cta input[type="date"] { padding: 5px 8px; font-size: 13px; width: auto; }
.settle-pass:hover { border-color: var(--pos); color: var(--pos); }
.settle-blow:hover { border-color: var(--neg); color: var(--neg); }
.settleset { margin-left: 6px; }
.settleset summary {
  font-size: 10px; font-weight: 700; color: var(--muted);
  text-transform: uppercase; letter-spacing: .04em;
}
.settleset summary:hover { color: var(--text); }
.settle-form { justify-content: flex-start; }
.settle-form input[type="date"] { padding: 4px 6px; font-size: 12px; width: auto; }
.settle-lab {
  font-size: 10px; font-weight: 700; color: var(--muted);
  text-transform: uppercase; letter-spacing: .04em; white-space: nowrap;
}
/* **[KEY-CONCEPT]** THE OPEN SETTLE FORM LEAVES THE TOOLBAR. `.rt-tools`
   is anchored to the cell's BOTTOM-right, so a form opening inside it grew
   UPWARDS — out of the row, into `.rankt-bleed`'s `overflow-x: auto`, which
   clips vertically as well and sliced the top off the panel. What survived was
   squeezed to the toolbar's width, so the date and the two verdicts stacked into
   a column sitting on top of the account's own number.

   So the open form is its own panel, anchored to the toolbar and laid out
   ACROSS: `bottom: 0` lines it up with the toolbar and lets it grow up only as
   far as its single row of controls, which no row is short enough to clip, and
   `left: 100%` takes it out of the account column and over the ones beside it.
   Covering EXECUTE is the point — the panel is only up while the disclosure is
   open, and a verdict you are in the middle of recording outranks a size you
   are not about to trade. (The always-visible toolbar still stays inside the
   cell — see .rt-tools. That rule is about the resting state, not this one.) */
.settleset[open] > summary { color: var(--text); }
.settleset[open] .settle-form {
  position: absolute; bottom: 0; left: calc(100% + 8px); z-index: 3;
  flex-wrap: nowrap; white-space: nowrap; margin: 0;
  padding: 7px 9px; border-radius: var(--radius-token);
  background: var(--surface); border: 1px solid var(--border);
  box-shadow: var(--shadow-lg);
}
/* the toolbar fades on hover-out, and it must not take an open panel with it —
   the pointer is over EXECUTE by then, which is a different row's business. */
.rankt tr:has(.settleset[open]) .rt-tools { opacity: 1; pointer-events: auto; z-index: 5; }
.rt-fin { display: block; font-size: 12px; font-weight: 600; color: var(--accent); }
.rt-atm-row.fin, .rt-atm-row.fin strong { color: var(--accent); }
.rt-atm-row.fin em {
  font-style: normal; font-size: 10px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .04em;
}
/* the funded playbook's own rows (press / bank) — the same shape as the
   finisher, in the winning-day green so a funded row reads apart from an eval's. */
.rt-play { display: block; font-size: 12px; font-weight: 600; color: var(--pos); }
.rt-atm-row.play, .rt-atm-row.play strong { color: var(--pos); }
.rt-atm-row.play em, .rt-atm-row.fin em {
  font-style: normal; font-size: 10px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .04em;
}
.rchip.press { background: var(--pos-weak); color: var(--pos); }
.rt-comm { font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
.rt-comm .rt-atm-row { line-height: inherit; }
.rt-comm .rt-atm-row.fin { color: var(--accent); }
.rt-comm .rt-atm-row.play { color: var(--pos); }
.rankt-note { margin: 12px 4px 0; font-size: 12px; }
.rankt-note em { font-style: normal; font-weight: 700; color: var(--accent); font-size: 10px; text-transform: uppercase; }

/* the Update tab's variant: same ranked table, plus a balance-entry column.
   tr.urow keeps the class only for the preview JS hook — undo the flex-card look. */
table.rankt tr.urow {
  display: table-row; padding: 0; background: transparent;
  border: 0; box-shadow: none; border-radius: 0;
}
table.rankt tr.urow.filled { border: 0; box-shadow: none; }
table.rankt tr.urow.filled td { background: var(--accent-weak); }
table.rankt.update .pbar { width: 84px; }
.rt-entry { min-width: 100px; }
.rt-entry .urow-entry { display: block; }
.rt-entry .urow-entry input { width: 96px; padding: 8px 9px; font-size: 15px; }
.rt-entry .urow-preview { display: block; margin-top: 3px; min-width: 0; }

/* ---------- book: quick update (one balance per account, in a list) ---------- */
.update-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 16px; flex-wrap: wrap; margin-bottom: 16px;
}
.upd-progress { display: flex; flex-direction: column; gap: 6px; flex: 1 1 200px; min-width: 160px; }
.upd-count { font-size: 15px; }
.upd-count strong { font-variant-numeric: tabular-nums; }
.upd-track { height: 8px; border-radius: 999px; background: var(--surface-2); overflow: hidden; }
.upd-fill { height: 100%; background: var(--pos); border-radius: 999px; transition: width .2s ease; }
.upd-date { margin: 0; font-size: 13px; display: flex; flex-direction: column; gap: 4px; flex: 0 0 auto; }
.upd-date input { width: auto; padding: 8px 10px; font-size: 15px; }

.usection { margin-bottom: 18px; }
.usection h2 { font-size: 12px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); font-weight: 600; margin: 0 0 8px; }

.ulist { display: flex; flex-direction: column; gap: 8px; }
.urow {
  display: flex; align-items: center; gap: 12px; padding: 11px 14px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow); cursor: text;
}
.urow.filled { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.urow.done { background: var(--surface-2); box-shadow: none; cursor: default; color: var(--text); }
.urow.done:hover { text-decoration: none; background: var(--border); }

.urow-dot {
  flex: 0 0 auto; width: 20px; height: 20px; border-radius: 50%;
  border: 2px solid var(--border-strong); display: inline-flex;
  align-items: center; justify-content: center; font-size: 12px; line-height: 1; color: var(--on-solid);
}
.urow.filled .urow-dot { border-color: var(--accent); background: var(--accent); }
.urow-dot.on { border-color: transparent; background: var(--pos); }

.urow-id { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
/* The name is a link (the only route to an untraded account's page) but must not
   read as one inside the row. */
a.urow-id { color: inherit; }
a.urow-id:hover { text-decoration: none; }
a.urow-id:hover .urow-name { text-decoration: underline; }
.urow-name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.urow-meta { font-size: 12px; color: var(--muted); display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.urow-meta .num { font-variant-numeric: tabular-nums; }
.urow-prev { font-variant-numeric: tabular-nums; white-space: nowrap; }

.urow-entry { flex: 0 0 auto; display: flex; align-items: center; gap: 10px; }
.urow-entry input {
  width: 116px; min-width: 0; margin: 0; padding: 9px 11px; font-size: 16px;
  text-align: right; font-variant-numeric: tabular-nums;
}
.urow-preview { font-size: 13px; font-weight: 600; min-width: 92px; text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.urow-preview.w  { color: var(--pos); }
.urow-preview.l  { color: var(--neg); }
.urow-preview.be { color: var(--warn); }


/* Passed/blown today: still on screen, visibly out of the pool. */
.usection.settled { margin-top: 22px; }
.urow.settled { opacity: .82; }
.urow.settled:hover { opacity: 1; }
.urow-dot.pass { border-color: transparent; background: var(--pos); }
.urow-dot.blow { border-color: transparent; background: var(--neg); }
.settled-actions {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap; margin-top: 10px; font-size: 13px;
}

/* The day's scoreboard. Deliberately the last block on the tab, not the strip. */
.usection.daytally { margin-top: 24px; }
.dtally {
  display: flex; align-items: center; gap: 8px 16px; flex-wrap: wrap;
  padding: 12px 14px; background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow); font-size: 13px; color: var(--muted);
}
.dt-item strong { font-size: 15px; color: var(--text); font-variant-numeric: tabular-nums; margin-right: 2px; }
.dt-item.w strong    { color: var(--pos); }
.dt-item.l strong    { color: var(--neg); }
.dt-item.be strong   { color: var(--warn); }
.dt-item.pass strong { color: var(--pos); }
.dt-item.blow strong { color: var(--neg); }
/* The row carries two units, so it carries two GROUPS. Inside a group the items
   sit tight (they are one thought: a total and its breakdown); between groups a
   rule and the wider row gap keep the account verdicts from reading as another
   term of the trade count. */
.dt-grp { display: inline-flex; align-items: baseline; gap: 4px 10px; flex-wrap: wrap; }
.dt-rec { display: inline-flex; align-items: baseline; gap: 10px; }
.dt-lead strong { font-size: 17px; }
.dt-dot { color: var(--border-strong); }
.dt-sep, .dt-verdict { border-left: 1px solid var(--border); padding-left: 16px; }
/* The month row carries a group more than the day's and runs out of line first;
   below this it stacks, because a left rule on a wrapped group is a stub hanging
   off the start of a line, pointing at nothing. */
@media (max-width: 900px) {
  .dtally.mo .dt-sep, .dtally.mo .dt-verdict {
    width: 100%; border-left: 0; padding-left: 0;
    border-top: 1px solid var(--border); padding-top: 8px;
  }
}
/* Keyed the same way funded/eval is keyed below — the label says what the number
   counts, so "2 blown" can't be misread as two of the trades. */
.dt-grp-k {
  font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted);
}
.dt-net { margin-left: auto; display: inline-flex; align-items: baseline; gap: 8px 12px; flex-wrap: wrap; }
.dt-net strong { font-size: 17px; color: var(--text); font-variant-numeric: tabular-nums; }
.dt-net strong.pos { color: var(--pos); }
.dt-net strong.neg { color: var(--neg); }
/* Funded vs eval P/L. Eval is deliberately grey and a size down — it is a
   scoreboard number, not money, and shouldn't read like a paid day. */
.dt-pl { display: inline-flex; align-items: baseline; gap: 5px; }
.dt-pl-k { font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); }
.dt-pl.ev strong { font-size: 14px; color: var(--muted); font-weight: 600; }

/* ---------- the weekly recap (journal ?view=stats, v5.57) ----------
   Built from vocabulary the app already speaks: the Book calendar's
   proportional W/BE/L bar, the tally's small-caps key, the same W/L/BE inks.
   It leads the Stats tab because "this week" is the read you can still act on;
   the all-time edge tables below are the slow one. Deliberately carries NO
   money — a process recap that printed P/L would be the dopamine board the
   book's own rules forbid. */
.wr-h { font-size: 13px; margin: 22px 0 10px; display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.wr-h:first-of-type { margin-top: 0; }
.wr-h .muted { font-weight: 400; font-size: 12px; }
.wr-card { padding: 14px 16px; }
.wr-hdr {
  display: flex; align-items: center; gap: 8px 16px; flex-wrap: wrap;
  padding-bottom: 12px; border-bottom: 1px solid var(--border);
}
.wr-hdr .wr-bar { flex: 1 1 140px; max-width: 280px; }
.wr-sm { font-size: 12px; }
.wr-rec { font-size: 13px; color: var(--muted); }
.wr-rec strong { font-size: 15px; font-variant-numeric: tabular-nums; margin-right: 2px; color: var(--text); }
.wr-lead strong { font-size: 19px; }
.wr-rec.w strong  { color: var(--pos); }
.wr-rec.l strong  { color: var(--neg); }
.wr-rec.be strong { color: var(--warn); }
/* The record bar: same three inks and same proportional fill as .bcal-bar. */
.wr-bar {
  display: flex; height: 6px; border-radius: 3px; overflow: hidden;
  background: var(--surface-2); min-width: 96px;
}
.wr-bar i { display: block; }
.wr-bar .sw { background: var(--pos); } .wr-bar .sbe { background: var(--warn); } .wr-bar .sl { background: var(--neg); }
/* One "read" per family — key on the left, findings on the right. */
.wr-read { display: flex; gap: 16px; padding: 12px 0; border-bottom: 1px solid var(--border); }
.wr-read:last-of-type { border-bottom: 0; padding-bottom: 2px; }
.wr-k {
  flex: 0 0 104px; padding-top: 3px;
  font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted);
}
.wr-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 7px; }
.wr-line { font-size: 13px; color: var(--muted); }
.wr-line b { color: var(--text); font-variant-numeric: tabular-nums; font-weight: 700; }
.wr-line b.pos { color: var(--pos); } .wr-line b.neg { color: var(--neg); }
/* The conviction pair: two rates stacked so an inversion is visible, not read. */
.wr-cal { display: grid; grid-template-columns: max-content 108px max-content 1fr; gap: 6px 10px; align-items: center; font-size: 13px; }
.wr-cal .wr-bar { min-width: 0; width: 100%; }   /* the grid column sizes it */
.wr-tier { color: var(--muted); font-size: 12px; }
.wr-pct { font-weight: 700; font-variant-numeric: tabular-nums; }
.wr-pct.pos { color: var(--pos); } .wr-pct.neg { color: var(--neg); }
.wr-verdict { font-size: 12px; color: var(--muted); border-left: 2px solid var(--warn); padding-left: 9px; }
.wr-chip {
  display: inline-block; margin: 0 5px 5px 0; padding: 1px 8px;
  border: 1px solid var(--border); border-radius: 99px; font-size: 12px; color: var(--muted);
}
.wr-chip b { color: var(--text); font-variant-numeric: tabular-nums; }
.wr-chip .pos { color: var(--pos); } .wr-chip .neg { color: var(--neg); } .wr-chip .warn { color: var(--warn); }
.wr-note { font-size: 12px; margin: 12px 0 0; padding-top: 10px; border-top: 1px solid var(--border); }
/* Prior weeks read as COLUMNS — scan one metric down the weeks, not four cards. */
.wr-strip { border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); box-shadow: var(--shadow); overflow: hidden; }
.wr-wk { display: flex; align-items: center; gap: 14px; padding: 9px 16px; font-size: 13px; border-top: 1px solid var(--border); }
.wr-wk:first-child { border-top: 0; }
.wr-when { flex: 0 0 96px; color: var(--muted); font-size: 12px; }
.wr-n { flex: 0 0 74px; font-variant-numeric: tabular-nums; }
.wr-wk .wr-bar { flex: 0 0 96px; }
.wr-cell { flex: 0 0 150px; color: var(--muted); font-size: 12px; }
.wr-cell b { color: var(--text); font-variant-numeric: tabular-nums; }
.wr-cell b.pos { color: var(--pos); }
.wr-setups { flex: 1; min-width: 0; color: var(--muted); font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
@media (max-width: 760px) {
  /* The key stops being a column and becomes a label above its findings. */
  .wr-read { flex-direction: column; gap: 6px; }
  .wr-k { flex: none; padding-top: 0; }
  .wr-cal { grid-template-columns: max-content 1fr max-content; }
  .wr-cal .muted { grid-column: 1 / -1; margin-top: -4px; }
  .wr-wk { flex-wrap: wrap; gap: 8px 12px; }
  .wr-setups { flex: 1 0 100%; white-space: normal; }
}

.update-actions {
  position: sticky; bottom: 0; z-index: 2; display: flex; gap: 10px;
  padding: 12px 0 14px; background: linear-gradient(to top, var(--bg) 72%, transparent);
}
.update-actions .btn-primary { flex: 1; }
.all-done { text-align: center; color: var(--pos); font-weight: 600; padding: 14px 0 4px; }

@media (max-width: 560px) {
  /* phones keep the tighter gutter */
  .page, .footer { padding-left: 16px; padding-right: 16px; }
  .topbar { padding: 0 16px; }
  .urow { flex-wrap: wrap; }
  .urow-entry { width: 100%; justify-content: flex-end; }
  .urow-entry input { flex: 1 1 auto; width: auto; }
  .update-head { align-items: stretch; }
  .upd-date { width: 100%; }
  /* Wrapped onto its own line, a left rule points at nothing: rule the top. */
  .dt-sep, .dt-verdict {
    width: 100%; border-left: 0; padding-left: 0;
    border-top: 1px solid var(--border); padding-top: 8px;
  }
}

/* ---------- desktop ---------- */
@media (min-width: 768px) {
  .navtoggle { display: none; }
  /* The logo takes the vertical room next to the nav (v4.107). */
  .topbar { height: 92px; }
  .brand-mark { height: 64px; }
  .brand-text { font-size: 34px; }
  /* DRC-style: the menu sits on the right, clustered next to the user / sign out.
     margin-left:auto pushes it right; topbar-right then follows directly after. */
  .navtabs {
    display: flex; flex-direction: row; align-items: center; gap: 2px; position: static;
    margin-left: auto; padding: 0; background: none; border: 0; box-shadow: none;
    /* Undo the phone panel's self-scroll: an overflow on the row would clip
       the More popover that hangs below it. */
    max-height: none; overflow: visible;
  }
  .navtabs a, .navtabs summary { padding: 6px 12px; font-size: 14px; }
  .nav-sep { display: inline-block; width: 1px; height: 16px; background: var(--border); margin: 0 6px; align-self: center; }
  /* inline-flex, not inline-block: an inline-block sits on the text baseline,
     which drops the icon a couple of px below the labels beside it. */
  .nav-help-icon, .nav-gear-icon { display: inline-flex; align-items: center; }
  .nav-help-word, .nav-gear-word { display: none; }   /* desktop: the icons say it */
  .nav-account { display: none; }
  .topbar-right { display: flex; margin-left: 0; }
  .nav-more { position: relative; }
  .nav-more-panel {
    position: absolute; top: 100%; right: 0; margin-top: 4px; z-index: 21;
    background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-token);
    box-shadow: var(--shadow-pop); padding: 6px; min-width: 150px;
  }
  .nav-more-panel a { padding: 8px 10px; display: block; white-space: nowrap; }
  /* Side by side on the desktop panel: nine links in one column ran most of the
     way down the viewport and read as one wall, and Analysis — three links —
     sat below the fold of the eye. The panel hangs off More's RIGHT edge, so
     the width the second column costs is width into the page, not off it. */
  .nav-more-panel { flex-direction: row; align-items: flex-start; gap: 16px; padding: 8px; }
  .nav-col + .nav-col { margin-top: 0; }
  .cal-amt {
    display: block; margin-top: 12px; font-size: 13px; font-weight: 700; line-height: 1;
    max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  /* History calendar: the phone shows tint + record only; the desktop cell has
     room for the W/BE/L proportion bar, the day's net and a week-total column. */
  .cal-grid.bcal { grid-template-columns: repeat(5, 1fr) .5fr .5fr minmax(84px, 0.8fr); gap: 5px; }
  .cal-grid.bcal.wk-sun { grid-template-columns: .5fr repeat(5, 1fr) .5fr minmax(84px, 0.8fr); }
  .cal-dow.wk { display: block; }
  .bcal-wk { display: flex; }
  .bcal-tags { top: 3px; right: 4px; bottom: auto; left: auto; justify-content: flex-end; }
  .bcal-tag.pay .pay-sm { display: none; }
  .bcal-tag.pay .pay-lg { display: inline; }
  .bcal-cell { min-height: 104px; padding: 22px 10px 10px; }
  .bcal-rec { font-size: 15px; gap: 0 7px; }
  .bcal-bar {
    display: flex; width: 64%; max-width: 104px; height: 4px; margin-top: 3px;
    border-radius: 999px; overflow: hidden; background: var(--track);
  }
  .bcal-bar i { display: block; height: 100%; }
  .bcal-bar i.w  { background: var(--pos); }
  .bcal-bar i.be { background: var(--warn); }
  .bcal-bar i.l  { background: var(--neg); }
  .bcal-net { display: block; margin-top: 2px; font-size: 12px; font-weight: 700; line-height: 1; }
  .stat-grid, .stats { grid-template-columns: repeat(3, 1fr); }
  .tables { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
  .tables .card:first-child { grid-column: 1 / -1; }
  .bs-grid { grid-template-columns: repeat(3, 1fr); }
}
.risk-swap { margin: 6px 0 0; font-size: 13px; }

/* ---------- journal (the DRC's day layer, v4.0) ---------- */
/* Reminder bar doubles as the intent display: goal (or carried focus) + a sub line. */
.reminder-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 320px; }
.reminder-sub { margin: 0; font-size: 13px; }
.reminder-sub strong { color: var(--text); }

/* The journal's reading/writing content centers a 760px column INSIDE the
   shared page width (v4.16) — readable forms, no jumping page edges. */
.journal .jcard-head, .journal .jform, .journal .jtrades, .journal .jday-ctx,
.journal .jorph-h, .journal .shot-grid, .journal .jtradeform,
.journal .error, .journal .warnbox {
  max-width: 760px; margin-left: auto; margin-right: auto;
}
.journal .carried { max-width: 760px; margin: 0 auto 16px; }
.journal .jcard-head { margin-bottom: 14px; }
.jcard-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 14px; }
.jcard-head h2 { margin: 0; }
.jcard-head .muted { font-size: 13px; }
.jcount {
  display: inline-flex; align-items: center; justify-content: center; min-width: 22px;
  padding: 1px 7px; margin-left: 4px; border-radius: var(--radius-token);
  background: var(--surface-2); color: var(--muted); font-size: 12px; font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* Focus carried from the last EOD ("tomorrow's focus" actually read again). */
.carried {
  display: flex; flex-direction: column; gap: 2px;
  background: var(--accent-weak); border-radius: var(--radius-token);
  padding: 10px 14px; margin-bottom: 16px; font-weight: 600;
}
.carried-k { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .05em; color: var(--accent); }

/* 1–10 grade picker and tag chips — radio/checkbox pills (the .seg-opt pattern). */
.jgrade { display: grid; grid-template-columns: repeat(5, 1fr); gap: 8px; margin-bottom: 14px; }
.jgrade .seg-opt span {
  display: block; text-align: center; padding: 10px 0; border-radius: var(--radius-token);
  font-size: 15px; font-weight: 600; font-variant-numeric: tabular-nums;
}
.jgrade-label { margin-bottom: 6px; }
.jgrade-note { margin-bottom: 14px; }
.jtags { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-bottom: 14px; }
/* A free-text field living in a pill row (the stop-size "other" box) has to read
   as one more pill: the global input rule's 44px min-height, 16px text and 4px
   top margin would otherwise sit it a few pixels low and a few taller. */
.jtags input[type=text] {
  margin-top: 0; min-height: 0;
  padding: 9px 12px; font-size: 14px; line-height: 1.5; border-radius: var(--radius-token);
}
/* Specific enough to beat the base `width: 100%` and the rule just above. */
.jtags input[type=text].jstop-other { width: 5.5em; }   /* "12.5" is the widest preset */
/* The open-window hint is a caption for the toggle beside it, not body copy —
   at 16px it out-shouted the 13px pill it explains. */
.jwindow-row .muted { font-size: 13px; }
/* Session row (v5.16): the ⚡ News toggle rides at the end of the session chips
   because it qualifies one of them — it is a second dimension, not a fourth
   session, and the caption under the row is what says so. */
.jsession-row { margin-bottom: 6px; }
/* A rule and a gap, because unseparated the ⚡ chip reads as a FOURTH session —
   which is the one thing it is not. The caption says so; the divider means the
   caption is not the only thing saying so. */
.jnews { margin-left: 10px; padding-left: 14px; border-left: 1px solid var(--border-strong); }
.jnews span { font-size: 13px; }
/* Amber, not the accent blue — news is a condition of the trade, the same
   family as the ⚑ flag's red. --warn itself carries white text at ~2.9:1, so
   the FILL is the darker amber (--warn-fill) and --warn stays the outline.
   --warn-fill is the one token whose two halves are the same colour: it is a
   solid amber under --text, which reads on it as near-black ink in the light
   theme and as near-white ink in the dark one. */
.jnews input:checked + span { background: var(--warn-fill); border-color: var(--warn-fill); }
.jnews input:focus-visible + span { outline-color: var(--warn); }
.jsession-hint { font-size: 13px; margin: 0 0 14px; }
.jday-ctx { margin: -4px 0 14px; font-size: 13px; }
.jform-foot { display: flex; align-items: center; gap: 12px; }
.savestat { font-size: 13px; color: var(--muted); }
.savestat.err { color: var(--neg); font-weight: 600; }
.page-stat { text-align: right; }

/* The day's trades, read off the Book (per-trade journal cards come in phase 2). */
.jtrade { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.jtrade-id { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1 1 auto; }
.jtrade-id > a { font-weight: 600; color: var(--text); }
.jtrade-meta { display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; font-size: 12px; color: var(--muted); }
.jtrade-result { display: inline-flex; align-items: center; gap: 10px; font-size: 13px; font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Inline morning intent on the Book (v5.48: a .more disclosure row like every
   other tucked-away form; the card only centres the form below it). */
.intent-inline:not([open]) > summary { margin-bottom: 0; }
/* centered like journal.php's day view — same column, same calm */
.intent-inline .jform, .eodsec .jform { max-width: 760px; margin-left: auto; margin-right: auto; }
.eodsec { margin-top: 24px; }

/* ---- the trade card (v4.1) + journal links on Book rows ---- */
.rt-jlink { display: inline-block; font-size: 12px; font-weight: 600; white-space: nowrap; }
/* v4.2: the link sits right after the account name — the names are near-identical
   ("50k Flex" × 6), so the name column has the room and the eye is already there. */
.rt-jlink-name { margin-left: 8px; vertical-align: 1px; }

/* balance field inside the trade card: keep the .urow class purely as the
   live-preview JS hook — none of the Book row's card chrome */
.urow.jbal {
  display: block; border: 0; padding: 0; margin-top: 4px;
  background: none; box-shadow: none; cursor: auto;
}
.urow.jbal input { text-align: left; width: 100%; }
.urow.jbal .urow-preview { display: block; margin-top: 4px; text-align: left; }

/* 1–5 star rating: radios in reverse DOM order so earlier stars light up */
.jrate-row { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin: 4px 0 16px; }
.jrate-row .jgrade-label { margin: 0; }
.jstars { display: inline-flex; flex-direction: row-reverse; }
.jstar { margin: 0; position: relative; }
.jstar input { position: absolute; opacity: 0; inset: 0; cursor: pointer; }
.jstar span { font-size: 26px; line-height: 1; color: var(--border-strong); padding: 0 2px; cursor: pointer; }
.jstar:hover span, .jstar:hover ~ .jstar span { color: var(--warn); }
.jstar:has(input:checked) span, .jstar:has(input:checked) ~ .jstar span { color: var(--warn); }
.jstar input:focus-visible + span { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
.jflag span { font-size: 13px; }
/* the flag is a warning, not a choice: red when set, matching the ⚑ chip on Book rows */
.jflag input:checked + span { background: var(--neg); border-color: var(--neg); }
.jflag input:focus-visible + span { outline-color: var(--neg); }
.jstars-ro { color: var(--warn); font-size: 14px; letter-spacing: 1px; white-space: nowrap; }
.jstars-ro .dim { color: var(--border-strong); }

/* journal detail under a trade row on the day view */
.jtrade-journal {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  border-top: 0 !important; padding: 2px 0 8px !important;
  margin-top: -4px; font-size: 13px;
}
.jtrade-note { color: var(--muted); }
.jorph-h { font-size: 12px; text-transform: uppercase; letter-spacing: .05em; margin: 16px 0 4px; }

/* ---- screenshots (v4.3) ---- */
.shot-add {
  display: inline-block; padding: 9px 14px; margin: 4px 0 14px;
  border: 1px dashed var(--border-strong); border-radius: var(--radius-token);
  color: var(--muted); font-size: 13px; cursor: pointer;
}
.shot-add:hover { color: var(--accent); border-color: var(--accent); }
.shot-add input[type=file] { display: none; }
.shot-previews { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: -6px 0 14px; font-size: 12px; }
.shot-preview { height: 52px; border-radius: var(--radius-token); border: 1px solid var(--border); display: block; }
/* a not-yet-saved paste/pick: same ✕ affordance as a stored shot, so a
   doubled paste is removable before the save */
.shot-pending { position: relative; margin: 0; line-height: 0; }
.shot-pending .shot-del { position: absolute; top: 2px; right: 2px; border: 0; cursor: pointer; font: inherit; line-height: 1; padding: 0; }
.shot-grid { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 12px; }
.shot-thumb { position: relative; margin: 0; }
.shot-thumb img { height: 110px; max-width: 220px; object-fit: cover; border-radius: var(--radius-token); border: 1px solid var(--border); display: block; }
.shot-thumb form { position: absolute; top: 4px; right: 4px; margin: 0; }
.shot-del {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: 50%;
  /* #fff, not --on-solid: --scrim is dark in BOTH themes, so the ink over it is too. */
  background: var(--scrim); color: #fff; font-size: 12px; text-decoration: none;
}
.shot-del:hover { background: var(--neg); }
.shot-strip { display: inline-flex; gap: 6px; }
.shot-mini img { height: 40px; border-radius: var(--radius-token); border: 1px solid var(--border); display: block; }
/* ---- trade updates (v5.58): the trade's timeline ---- */
.journal .jupd-wrap { max-width: 760px; margin: 18px auto 0; }
.jupd-hint { max-width: 760px; margin: 14px auto 0; font-size: 13px; }
.jupd { margin: 0 0 10px; padding: 0; display: flex; flex-direction: column; gap: 8px; flex-basis: 100%; }
/* `.jupd .jupd-item`, not `.jupd-item`: the list is `.plain`, and `.plain li`
   (class + element) outranks a lone class — its `padding: 6px 0` silently
   zeroed the left padding here, which is why the stamp touched the rail
   through 5.61's "fix". Same fight the border-top !important was already in. */
.jupd .jupd-item {
  display: flex; align-items: flex-start; gap: 12px;
  /* Left padding = the flex gap, so the stamp sits as far from the rail as
     the body sits from the stamp (v5.75). */
  padding: 8px 0 8px 12px; border-left: 2px solid var(--border-strong);
  border-top: 0; font-size: 13px;
}
/* The stamp sits clear of the rail and names its zone in a smaller face, so
   every body starts on the same column. */
.jupd-time { flex: 0 0 auto; font-size: 12px; padding-top: 1px; white-space: nowrap; }
.jupd-tz { font-size: 10px; letter-spacing: .02em; opacity: .8; }
.jupd-main { display: flex; flex-direction: column; gap: 6px; min-width: 0; flex: 1 1 auto; }
.jupd-body { color: var(--text); white-space: normal; }
.journal .jupd-shots { margin: 0; max-width: none; }
.jupd-del { margin: 0; flex: 0 0 auto; }
.jupd-del .linkish:hover { color: var(--neg); }
.jupd-form { display: flex; flex-direction: column; gap: 6px; margin: 0; }
.jupd-form textarea { width: 100%; box-sizing: border-box; }
.jupd-form-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.jupd-form .shot-add { margin: 0; }
.jupd-form .shot-previews { margin: 0; }
/* the day view folds the form: one line until it is wanted */
.jupd-add { flex-basis: 100%; font-size: 13px; margin-top: 2px; }
.jupd-add summary { cursor: pointer; list-style: none; width: max-content; }
.jupd-add summary::-webkit-details-marker { display: none; }
.jupd-add summary:hover { color: var(--accent); }
.jupd-add[open] summary { margin-bottom: 6px; }
.jtrade-id .jupd, .jtrade-id .jupd-add { margin-top: 4px; }
.jhead-right { display: inline-flex; align-items: center; gap: 14px; }
.jtabs { margin-bottom: 16px; }

/* Journal → Trades (v5.171): every logged trade, filtered and sorted in the browser */
.jt-filters { display: flex; flex-wrap: wrap; gap: 10px 12px; align-items: flex-end; }
.jt-f { display: flex; flex-direction: column; gap: 3px; font-size: 12px; color: var(--muted); min-width: 0; }
.jt-f select, .jt-f input { max-width: 220px; }
.jt-reset { align-self: flex-end; padding: 0 0 8px; background: none; border: 0; color: var(--accent); cursor: pointer; font: inherit; }
.jt-sum { margin: 14px 0 6px; }
.jt-table td.nowrap { white-space: nowrap; }
.jt-table th[data-sort] { cursor: pointer; user-select: none; white-space: nowrap; }
.jt-table th[data-sort]:hover { color: var(--text); }
.jt-table th[aria-sort="ascending"]::after { content: " ▲"; font-size: 10px; }
.jt-table th[aria-sort="descending"]::after { content: " ▼"; font-size: 10px; }
@media (max-width: 640px) {
  .jt-f { flex: 1 1 calc(50% - 6px); }
  .jt-f select, .jt-f input { max-width: none; width: 100%; }
}
.journal .page-head { flex-wrap: wrap; }

/* ---- grade calendar (v4.15): the DRC month view, grade as the focus ---- */
.cal-cell.jg { text-decoration: none; }
.cal-cell.jg.g-low  { background: var(--neg-weak); }
.cal-cell.jg.g-mid  { background: var(--warn-weak); }
.cal-cell.jg.g-good { background: var(--pos-weak); }
.cal-cell.jg.g-top  { background: var(--pos); }
.cal-cell.jg.g-top .jg-grade, .cal-cell.jg.g-top .jg-mind, .cal-cell.jg.g-top .cal-day { color: var(--on-solid); }
.cal-cell.jg.g-note { background: var(--surface-2); }
.jg-grade { font-size: 20px; font-weight: 700; line-height: 1; font-variant-numeric: tabular-nums; }
.cal-cell.jg.g-low .jg-grade  { color: var(--neg); }
.cal-cell.jg.g-mid .jg-grade  { color: var(--warn-ink); }
.cal-cell.jg.g-good .jg-grade { color: var(--pos); }
.jg-mind { font-size: 10px; color: var(--muted); margin-top: 1px; }
.jg-dot { font-size: 18px; color: var(--muted); line-height: 1; }
.jg-tags { position: absolute; bottom: 3px; right: 4px; font-size: 11px; line-height: 1; letter-spacing: -1px; }
.jg-sw { background: var(--surface-2); }
.jg-sw.g-low { background: var(--neg-weak); } .jg-sw.g-mid { background: var(--warn-weak); }
.jg-sw.g-good { background: var(--pos-weak); } .jg-sw.g-top { background: var(--pos); }
/* open-trade badge (journaled at entry, balance pending) */
/* Session chips on the day view (v5.16). The session is neutral — it is a fact
   about the trade, not a verdict on it — so it stays quiet next to the setup's
   accent-blue. ⚡ news is the amber overlay, matching the card's toggle, and
   never appears without a session beside it. */
.chip.sess { background: var(--surface-2); color: var(--text); border-color: transparent; font-weight: 600; white-space: nowrap; }
.chip.news { background: var(--warn-weak); color: var(--warn-ink); border-color: transparent; font-weight: 600; white-space: nowrap; }
.chip.opent { background: var(--warn-weak); color: var(--warn); border-color: transparent; font-weight: 700; white-space: nowrap; }
a.chip.opent:hover { text-decoration: none; background: var(--warn); color: var(--on-solid); }
.jopen-hint { display: block; margin-top: 4px; font-size: 12px; }
/* journal column on the account page's history */
.jhist { white-space: nowrap; }
.jhist .jstars-ro { font-size: 12px; margin: 0 2px; }
.stats-note { margin-top: 10px; font-size: 12px; }
tr.stat-all td { border-top: 2px solid var(--border-strong); font-weight: 600; }
/* The news/clean split under a session row: indented and quieter, so the parent
   session still reads as the row and these read as its breakdown. */
tr.stat-sub td { color: var(--muted); }
tr.stat-sub td:first-child { padding-left: 24px; font-size: 13px; }

/* The fixed ATM column on the Book list: same preset every day, so it reads as a
   label, not a control. `.tight` = cushion is under one full stop of room. */
/* The account page's session table carries the same colour key, so the two screens
   read as one thing: a tinted left edge and the session name in the session colour. */
table.atm tr.atm-s0 td:first-child { box-shadow: inset 3px 0 0 var(--warn); }
table.atm tr.atm-s1 td:first-child { box-shadow: inset 3px 0 0 var(--accent); }
table.atm tr.atm-s0 .atm-sess { color: var(--warn-ink); }
table.atm tr.atm-s1 .atm-sess { color: var(--accent); }
table.atm tr.atm-s0 td { background: var(--sess-a-tint); }
table.atm tr.atm-s1 td { background: var(--sess-b-tint); }
table.atm .atm-sess { text-transform: uppercase; font-size: 11px; letter-spacing: .04em; }

/* --- v4.62: the BV flag. A per-row bookkeeping fact ("this one is invoiced to
   the company"), shown as a quiet purple chip so it reads as an annotation on a
   trading row, never as a status like passed/blown. --- */
.chip.biz { background: var(--biz-weak); color: var(--biz); border-color: transparent; font-weight: 600; letter-spacing: .03em; }
.biz-sub { color: var(--biz); font-weight: 600; }
.exprow.is-biz .rowlink { box-shadow: inset 3px 0 0 var(--biz-edge); }
.biz-check { margin: -4px 0 4px; }

/* Declare mode: the list turned into one form for the retrospective
   "which of these go to the BV" pass. */
.declare-bar { font-size: 13px; margin: 0 0 12px; display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.declare-tick { display: flex; align-items: center; padding: 0 4px 0 2px; }
.declare-tick input { width: 20px; height: 20px; }
.declare-actions { position: sticky; bottom: 0; padding: 12px 0; background: linear-gradient(to top, var(--bg) 70%, transparent); }

/* --- BV statements (bv_statement.php, lib/bv.php). The builder is an ordinary
   page; the saved statement is a sheet of paper that prints onto A4 as it is. --- */
.bv-period .seg-links { flex-wrap: wrap; }
.bv-presets { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; margin-bottom: 10px; }
.bv-presets-k { font-size: 13px; color: var(--muted); min-width: 56px; }
@media (max-width: 600px) { .bv-presets-k { flex-basis: 100%; } }
.bv-qn { display: inline-block; min-width: 18px; padding: 0 5px; margin-left: 2px; border-radius: var(--radius-token);
  background: var(--biz-weak); color: var(--biz); font-size: 11px; font-weight: 700; text-align: center; font-variant-numeric: tabular-nums; }
.bv-period .bv-custom { margin-top: 12px; }
.bv-allbar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; margin: 0 0 12px; font-size: 13px; }
.bv-allbar .btn-link { background: none; border: 0; padding: 0; font: inherit; cursor: pointer; }
.bv-custom { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 8px 12px; }
.bv-custom label { margin: 0; }
.bv-pending { font-size: 13px; margin: 10px 0 0; }
.bv-fx { font-size: 13px; margin: 10px 0 0; font-variant-numeric: tabular-nums; }
.card > h2 + .bv-fx { margin: 0 0 10px; }
.bv-fx.is-warn { color: var(--warn-ink); }
.bv-picks td { vertical-align: top; }
.bv-picks .bv-tick { width: 1%; padding: 6px 2px; }
.bv-picks .bv-date { width: 1%; white-space: nowrap; color: var(--muted); }
.bv-picks tr.is-biz td:first-child { box-shadow: inset 3px 0 0 var(--biz-edge); }
.bv-picks .chip { margin-left: 4px; }
.bv-picks tr.is-declared td, .bv-picks tr.is-declared a { color: var(--muted); }
.bv-picks .bv-allrow th { font-size: 13px; font-weight: 500; color: var(--muted); text-transform: none; letter-spacing: 0; vertical-align: middle; }
.bv-sub { font-size: 12px; white-space: nowrap; }
.bv-older { margin-top: 12px; }
.bv-older summary { cursor: pointer; font-size: 14px; color: var(--accent); }
.bv-older-note { font-size: 13px; margin: 8px 0; }
.bv-names { display: grid; grid-template-columns: 1fr; gap: 0 16px; }
@media (min-width: 640px) { .bv-names { grid-template-columns: 1fr 1fr; } }
.bv-fine-screen { font-size: 12px; margin: 0; }
.bv-picks .bv-date-sub { display: none; }
.bv-sum { align-items: center; flex-wrap: wrap; gap: 8px 16px; background: var(--bg); border-top: 1px solid var(--border); padding: 10px 0; }
.bv-sum-text { flex: 1 1 260px; font-size: 15px; }
.bv-sum .btn-primary { flex: 0 0 auto; }
@media (max-width: 600px) {
  .bv-picks td.bv-date { display: none; }
  .bv-picks .bv-date-sub { display: block; }
  .bv-sum-text { font-size: 14px; }
  .bv-sum .btn-primary { flex: 1 1 100%; }
}
.bv-page .page-head { flex-wrap: wrap; }
.bv-page .page-head h1 { white-space: nowrap; }

/* The sheet. Its own small type scale in pt, so screen and paper agree. */
.bv-sheet {
  position: relative; overflow: hidden;
  max-width: 210mm; margin: 0 auto 16px; padding: 14mm 14mm 12mm;
  background: var(--paper); color: var(--paper-ink);
  border: 1px solid var(--border); border-radius: 4px; box-shadow: var(--shadow-lg);
  font-size: 9.5pt; line-height: 1.45;
}
.bv-sheet a { color: inherit; }
.bv-head { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 12px 24px;
  padding-bottom: 12px; border-bottom: 2px solid var(--paper-ink); margin-bottom: 14px; }
.bv-head-title { flex: 1 1 300px; }
.bv-kicker { font-size: 8.5pt; text-transform: uppercase; letter-spacing: .08em; color: var(--paper-muted); font-weight: 600; }
.bv-head h2 { font-size: 15pt; line-height: 1.25; margin: 4px 0 0; color: var(--paper-ink); text-transform: none; letter-spacing: 0; }
.bv-meta { margin: 0; display: grid; grid-template-columns: auto auto; gap: 2px 14px; align-content: start; }
.bv-meta > div { display: contents; }
.bv-meta dt { color: var(--paper-muted); }
.bv-meta dd { margin: 0; font-weight: 600; }
.bv-meta dd span { display: block; font-weight: 400; color: var(--paper-muted); font-size: 8.5pt; }
.bv-voided { margin: 0 0 12px; font-weight: 700; color: var(--neg); }
.bv-void-mark {
  position: absolute; top: 38%; left: 50%; transform: translate(-50%, -50%) rotate(-24deg);
  font-size: 120pt; font-weight: 800; letter-spacing: .1em; color: var(--paper-void);
  pointer-events: none; user-select: none;
}

.bv-settle { background: var(--paper-band); border-radius: 4px; padding: 10px 14px; margin-bottom: 18px; }
.bv-settle-row { display: flex; justify-content: space-between; gap: 16px; padding: 3px 0; font-variant-numeric: tabular-nums; }
.bv-settle-total { border-top: 1px solid var(--paper-ink); margin-top: 4px; padding-top: 7px; font-size: 12pt; font-weight: 700; }
.bv-settle-ref { margin-top: 6px; color: var(--paper-muted); }
.bv-settle-ref strong { color: var(--paper-ink); }
.bv-settle-ref .num { white-space: nowrap; }

.bv-part { margin-bottom: 16px; }
.bv-part h3 { font-size: 10.5pt; margin: 0 0 6px; }
.bv-part h3 span { font-weight: 400; color: var(--paper-muted); }
.bv-none { margin: 0; color: var(--paper-muted); }
.bv-table { width: 100%; border-collapse: collapse; }
.bv-table th { text-align: left; font-size: 8pt; text-transform: uppercase; letter-spacing: .05em; color: var(--paper-muted);
  font-weight: 600; padding: 4px 6px; border-bottom: 1px solid var(--paper-ink); }
.bv-table td { padding: 4px 6px; border-bottom: 1px solid var(--paper-rule); vertical-align: top; }
.bv-table .num { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.bv-table .bv-no { width: 1%; color: var(--paper-muted); text-align: right; }
.bv-table .bv-date { width: 1%; white-space: nowrap; }
.bv-table tfoot td { border-bottom: 0; border-top: 1px solid var(--paper-ink); font-weight: 700; }
.bv-fxday { display: block; font-size: 7.5pt; color: var(--paper-muted); }
.bv-actual { font-size: 8pt; color: var(--paper-muted); }
.bv-booking .bv-table td:last-child { width: 1%; }
.bv-fine { margin: 6px 0 0; font-size: 8.5pt; color: var(--paper-muted); }
.bv-foot { margin-top: 18px; padding-top: 8px; border-top: 1px solid var(--paper-rule); font-size: 8pt; color: var(--paper-muted); }
.bv-foot p { margin: 0 0 4px; }
.bv-note { color: var(--paper-ink); font-size: 9pt; }
.bv-void { max-width: 210mm; margin: 0 auto; font-size: 13px; }
.bv-void-btn { background: none; border: 0; padding: 0; font: inherit; color: var(--neg); cursor: pointer; }

/* A phone shows the sheet without the USD and rate columns (the paper keeps them). */
@media screen and (max-width: 600px) {
  .bv-sheet { padding: 16px; }
  .bv-sheet .bv-col-usd, .bv-sheet .bv-col-rate { display: none; }
  .bv-void-mark { font-size: 64pt; }
}

@page { size: A4; margin: 14mm 14mm 16mm; }
@media print {
  /* Printing is always light: every token resolves to its light half, whatever
     the screen was showing. */
  :root, :root[data-theme] { color-scheme: light; }
  body { background: var(--paper); }
  body > :not(main), .no-print, .flash { display: none !important; }
  .page { padding: 0; }
  .bv-sheet { max-width: none; margin: 0; padding: 0; border: 0; border-radius: 0; box-shadow: none; }
  .bv-table tr, .bv-settle, .bv-booking, .bv-head { break-inside: avoid; }
  .bv-part h3 { break-after: avoid; }
}

/* --- v4.63: Firm stats — spend/payouts per month per firm. A wide cross-tab,
   so the table keeps its own min-width and hands the overflow to .table-wrap's
   scroll on a phone; the TOTAL row is the sheet's bottom line and reads like
   one. The per-cell .sub lines carry the secondary figures (home currency, the
   buy/paid counts) without a column each. --- */
.firmstats table.firmtab { min-width: 780px; }
.firmstats table.firmtab th, .firmstats table.firmtab td { white-space: nowrap; }
.firmstats .firm-cell a { font-weight: 600; }
.firmstats .sub { display: block; font-size: 11px; font-weight: 400; line-height: 1.4; }
.firmstats tfoot .total-row td { font-weight: 700; border-top: 2px solid var(--border); border-bottom: none; background: var(--surface-2); }
.firmstats .crumbs { margin: 0 0 12px; font-size: 13px; }
.firmstats .chips a.chip { text-decoration: none; font-variant-numeric: tabular-nums; }

/* ---------------------------------------------------------------------------
   The EV optimizer (v4.79) — regime sizing, survival odds, account pricing.
   Each regime gets its own colour so the state is readable at a glance down a
   column: brute is neutral (nothing to protect), reanimation red (the account
   is fighting for its life), transition amber (real profit, still exposed),
   harvest green (the capital is safe, collect).
--------------------------------------------------------------------------- */
.chip.rg-brute       { background: var(--surface-2);  color: var(--muted);  border-color: transparent; }
.chip.rg-survival    { background: var(--neg-weak);           color: var(--warn-ink);       border-color: transparent; }
.chip.rg-reanimate   { background: var(--neg-weak);   color: var(--neg);    border-color: transparent; }
.chip.rg-transition  { background: var(--warn-weak);           color: var(--warn);   border-color: transparent; }
.chip.rg-harvest     { background: var(--pos-weak);   color: var(--pos);    border-color: transparent; }
.chip.warn           { background: var(--warn-weak);           color: var(--warn);   border-color: transparent; }

/* the Book listing's Optimizer column */
.rt-opt { white-space: nowrap; }
.rt-opt .chip { display: inline-block; margin-bottom: 3px; }
.rt-optmoney { display: block; font-variant-numeric: tabular-nums; }
.rt-optmoney.agrees { opacity: .62; }
.rt-optatm { display: block; font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
.rt-optatm strong { color: var(--text); }

/* the account page's optimizer card */
.optimizer h3 { font-size: 13px; text-transform: uppercase; letter-spacing: .04em;
                color: var(--muted); margin: 18px 0 8px; }
/* TODAY'S PLAN — the deterministic decision model on the account page, painted
   in the `color` it returned (same `--rgc` contract as the Book row's block).
   It sits ABOVE the survival DP because it is the one that gets traded. */
.todayplan { border: 1px solid var(--rgc); border-left-width: 3px;
             border-radius: var(--radius-token); padding: 12px 14px; margin-bottom: 14px;
             background: color-mix(in srgb, var(--rgc) 7%, var(--surface-2)); }
.todayplan-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 0 0 6px; }
/* #fff, not --on-solid: --rgc is the model's own colour and does not flip with
   the theme (lib/regime.php), so neither can the ink sitting on it. */
.todayplan-chip { background: var(--rgc); color: #fff; font-weight: 800; letter-spacing: .06em; }
.todayplan-br { margin-left: auto; color: var(--muted); }
/* the action's two halves again (see `.xact-why`) — same split, at this card's
   larger type, so the purpose reads the same way on both pages. */
.todayplan-act { font-weight: 600; }
.todayplan-act .xact-why { padding: 2px 7px; }
.todayplan em { font-style: italic; display: block; margin-top: 4px; }

.opt-regime { border: 1px solid var(--border); border-left-width: 3px; border-radius: var(--radius-token);
              padding: 12px 14px; background: var(--surface-2); }
.opt-regime.rg-brute      { border-left-color: var(--muted); }
.opt-regime.rg-survival   { border-left-color: var(--warn-ink); }
.opt-regime.rg-reanimate  { border-left-color: var(--neg); }
.opt-regime.rg-transition { border-left-color: var(--warn); }
.opt-regime.rg-harvest    { border-left-color: var(--pos); }
.opt-regime-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 0 0 6px; }
.opt-plan { display: flex; flex-wrap: wrap; gap: 22px; margin: 12px 0 4px; }
.opt-k { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; }
.opt-v { font-size: 19px; font-weight: 700; font-variant-numeric: tabular-nums; }
.opt-atms { list-style: none; padding: 0; margin: 10px 0 0; font-variant-numeric: tabular-nums; }
.opt-atms li { padding: 4px 0; border-top: 1px solid var(--border); font-size: 13px; }
.opt-atm-name { display: inline-block; min-width: 82px; color: var(--muted); font-size: 12px; }
.opt-odds { margin-top: 16px; }
.opt-note { font-size: 12px; margin-top: 10px; }
.opt-warn { font-size: 12px; background: var(--warn-weak); border-left: 3px solid var(--warn);
            padding: 8px 12px; border-radius: var(--radius-token); margin: 10px 0 0; }

/* the Masterplan's calibration verdict */
.cal-line { padding: 10px 14px; border-radius: var(--radius-token); border-left: 3px solid var(--border);
            background: var(--surface-2); font-size: 13px; }
.cal-agrees      { border-left-color: var(--pos); background: var(--pos-weak); }
.cal-optimistic  { border-left-color: var(--warn); background: var(--warn-weak); }
.cal-pessimistic { border-left-color: var(--accent); background: var(--accent-weak); }
.optt td, .optt th { vertical-align: top; }
.optt .rt-then { font-size: 11px; }
.opt-exits { font-size: 12px; margin: 10px 0 0; color: var(--muted); }
.opt-exit { display: block; margin-top: 4px; }
.opt-exit.up   { color: var(--pos); }
.opt-exit.down { color: var(--neg); }

/* ===========================================================================
   EXECUTION UI (v4.81) — the Book's ranked tables read during live trading.
   The goal is match-to-NinjaTrader with no arithmetic and no searching: firm
   colour and account number identify the row, one block says what to load.
   =========================================================================== */

/* --- firm badges: colour IS the identifier ------------------------------- */
.firmb {
  display: inline-block; padding: 3px 9px; border-radius: var(--radius-token);
  font-size: 12px; font-weight: 700; letter-spacing: .02em;
  text-transform: uppercase; white-space: nowrap; line-height: 1.35;
  /* The one hairline in the sheet that exists for the dark theme only — inset,
     so it costs the light theme nothing, not even a pixel of box. */
  box-shadow: inset 0 0 0 1px var(--badge-edge);
}
.firmb-lucid        { background: #1d4ed8; color: #fff; }
.firmb-fundednext   { background: #6d28d9; color: #fff; }
.firmb-topstep      { background: #111827; color: #fb923c; }
.firmb-apex         { background: #9f1239; color: #fff; }
.firmb-tpt          { background: #0f766e; color: #fff; }
.firmb-mff          { background: #15803d; color: #fff; }
.firmb-tradeify     { background: #0ff956; color: #0a0a0a; }  /* their favicon green */
.firmb-bulenox      { background: #4338ca; color: #fff; }
.firmb-earn2trade   { background: #b45309; color: #fff; }
.firmb-alpha        { background: #334155; color: #fff; }
.firmb-fundingpips  { background: #047857; color: #fff; }
.firmb-etf          { background: #be123c; color: #fff; }
.firmb-blueguardian { background: #0369a1; color: #fff; }
.firmb-leeloo       { background: #7c2d12; color: #fff; }
.firmb-none         { background: var(--surface-2); color: var(--muted); }
/* stable fallback hues for firms with no hand-picked colour */
.firmb-h0 { background: #b91c1c; color: #fff; }
.firmb-h1 { background: #a16207; color: #fff; }
.firmb-h2 { background: #166534; color: #fff; }
.firmb-h3 { background: #155e75; color: #fff; }
.firmb-h4 { background: #5b21b6; color: #fff; }
.firmb-h5 { background: #9d174d; color: #fff; }
.firmb-h6 { background: #1e40af; color: #fff; }
.firmb-h7 { background: #3f3f46; color: #fff; }

/* --- the NT8 match line: badge + the number as it reads in the dropdown --- */
.rt-idline { display: flex; align-items: center; gap: 8px; margin-bottom: 3px; }
.rt-acct .rt-num {
  font-size: 20px; font-weight: 800; letter-spacing: .01em;
  font-variant-numeric: tabular-nums; color: var(--text); text-decoration: none;
}
.rt-acct .rt-num:hover { text-decoration: underline; }

/* --- the execution block: regime pill + the sizes, and nothing else -------
   Everything that justifies the sizes (risk, target, R:R, breakeven win rate,
   the post-loss balance, the survival exits) is on the pill's tooltip. Printed
   in the row it gets read past forty times a session. Two exception flags stay
   visible — BLOWS and PLANNED — because those are states you must not have to
   hover to discover. */
.rt-exec { min-width: 210px; }
.xblock {
  border-left: 4px solid var(--border); border-radius: var(--radius-token);
  padding: 7px 10px; background: var(--surface-2);
}
.xhead { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.xpill {
  display: inline-block; padding: 3px 9px; border-radius: var(--radius-token);
  font-size: 11px; font-weight: 800; letter-spacing: .07em; cursor: pointer;
  background: var(--bg); border: 1px solid currentColor;
  /* the regime name plus its pencil is one token — wrapping it turns a pill into
     a two-line box and shoves the flags onto their own row */
  white-space: nowrap;
}
.xflag {
  font-size: 10px; font-weight: 800; letter-spacing: .06em;
  padding: 2px 6px; border-radius: var(--radius-token); cursor: help;
}
.xflag.bad  { background: var(--neg); color: var(--on-solid); }
.xflag.plan { background: var(--surface-2); color: var(--muted); border: 1px solid var(--border); }

.xtags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 7px; }
.xtag {
  display: inline-flex; align-items: baseline; gap: 5px;
  padding: 5px 10px; border-radius: var(--radius-token); white-space: nowrap;
  background: var(--bg); border: 1px solid var(--border);
  font-variant-numeric: tabular-nums; font-size: 14px;
}
.xtag em { font-style: normal; font-size: 10px; font-weight: 800; letter-spacing: .06em;
           text-transform: uppercase; color: var(--muted); }
.xtag-stop { font-weight: 700; color: var(--muted); }
.xtag-stop::after { content: ':'; font-weight: 400; }
.xtag-size { font-weight: 800; }
/* the dollar exposure, plainly: a middot, muted, normal weight. It is reference
   beside the instruction, not a second instruction — no border, no accent, no
   stress colour, and it must not compete with the contract count. */
.xtag-amt { color: var(--muted); font-weight: 400; }
.xtag-amt::before { content: '· '; }
.xtag.none { color: var(--muted); font-style: italic; font-size: 12px; }
.xalt { margin-top: 4px; opacity: .6; }
.xalt .xtag { font-size: 12px; padding: 2px 7px; }

/* the ACTION — the decision model's own instruction for this account today.
   Reads under the sizing pill because that is the order it is used in: what to
   put on, then what the trade is for. Small: it is a sentence, and it must not
   compete with the contract count above it.

   It is printed in two halves (see `regime_action_html()`): the VERB half stays
   muted, the PURPOSE half is highlighted. "Protect gains" is the reason the size
   above it was halved, and a reason you read past is a reason you trade past —
   so it gets a band of the regime's own colour rather than the same grey as the
   instruction it qualifies. */
.xact { margin-top: 6px; font-size: 11px; font-weight: 600; letter-spacing: .02em;
        color: var(--muted); cursor: help; }
.xact-do  { color: var(--muted); font-weight: 600; }
.xact-sep { color: var(--muted); opacity: .55; }
/* the highlight is tinted from `--rgc`, so it is the model that colours it — the
   TEXT stays full-contrast ink, because a light regime hex (TRANSITION's grind
   blue) is unreadable as small bold type on its own tint. */
.xact-why {
  font-weight: 800; letter-spacing: .03em; color: var(--text);
  background: color-mix(in srgb, var(--rgc, var(--text)) 30%, transparent);
  padding: 1px 5px; border-radius: var(--radius-token);
  -webkit-box-decoration-break: clone; box-decoration-break: clone;
}
/* in the Book row the line sits at 11px — the purpose half steps up a size so it
   is read before the verb it follows. */
.xact .xact-why { font-size: 12px; }

/* **[KEY-CONCEPT]** REGIME COLOUR IS A FIELD, NOT A STYLESHEET. `--rgc` is the
   `color` hex that `calculateAccountRegime()` returned, set inline on the block,
   so the row is painted by the decision model rather than by a class the CSS and
   the engine both have to remember. Change a colour in lib/regime.php and the
   Book repaints with nothing here to keep in step.

   The classes below survive only as the FALLBACK — the shape (the dashed endgame
   border) and a colour for any block rendered without the property. */
.xblock.x-brute      { border-left-color: var(--neg); background: var(--neg-weak); }
/* The FLAT profile's block (v5.36): no regime colour, because there is no
   regime — the pill carries the two numbers where a state name would be. */
.xblock.x-flat { border-left-color: var(--border); background: var(--surface-2); }
.xpill.xpill-flat { font-variant-numeric: tabular-nums; letter-spacing: 0; }
.xflag.rr { background: var(--surface-2); color: var(--muted); border: 1px solid var(--border); }
.xblock.x-brute      .xpill { color: var(--neg-ink); }
.xblock.x-survival   { border-left-color: var(--warn); background: var(--warn-weak); }
.xblock.x-survival   .xpill { color: var(--warn-ink); }
.xblock.x-transition { border-left-color: var(--accent); background: var(--accent-weak); }
.xblock.x-transition .xpill { color: var(--accent-ink); }
.xblock.x-harvest    { border-left-color: var(--pos); background: var(--pos-weak); }
.xblock.x-harvest    .xpill { color: var(--pos); }
/* reanimation is the endgame — louder than the rest, and marked as a last shot.
   The dashed outline is SHAPE, so it stays with the class while the colour of it
   comes from the model. */
.xblock.x-reanimate  { border-left-color: var(--neg-deep); background: var(--neg-weak);
                       border: 1px dashed var(--neg-deep); border-left-width: 4px; border-left-style: solid; }
.xblock.x-reanimate  .xpill { color: var(--neg-deep); }

/* Last, so the model's own colour beats every fallback above it — same
   specificity, so the cascade is the only thing deciding, and it must decide
   for `--rgc`. */
.xblock.x-regime           { border-left-color: var(--rgc);
                             background: color-mix(in srgb, var(--rgc) 7%, var(--surface-2)); }
.xblock.x-regime .xpill    { color: var(--rgc); }
.xblock.x-regime.x-reanimate { border-color: var(--rgc); border-left-color: var(--rgc); }

/* the planned-risk editor opens off the regime pill itself — and the pill has to
   LOOK editable. Elsewhere the app dashes-underlines an editable figure; a pill
   already has a border, so it carries a small pencil instead. */
.xhead .riskset { display: inline-block; }
.xhead .riskset summary { list-style: none; cursor: pointer; display: inline-flex;
                          align-items: center; gap: 6px; }
.xhead .riskset summary::-webkit-details-marker { display: none; }
.xhead .riskset .riskset-mark { display: none; }   /* the PLANNED flag says it */
.xpill-edit { font-style: normal; font-size: 10px; opacity: .5; margin-left: 5px;
              font-weight: 400; letter-spacing: 0; }
.xhead .riskset summary:hover .xpill { background: var(--surface-2); }
.xhead .riskset summary:hover .xpill-edit { opacity: 1; }
.xhead .riskset[open] .xpill { outline: 2px solid currentColor; outline-offset: 1px; }
.xhead .riskset[open] .xpill-edit { opacity: 1; }
.xhead .riskset-form { margin-top: 7px; }

/* --- FUNDED rows read as a different class of thing ----------------------
   A funded account is the income account; an eval is a lottery ticket. Scanning
   a mixed book, that distinction should land before any text is read — so funded
   rows take a soft emerald tint and a left edge, evals stay neutral. The tint is
   deliberately faint: it marks a whole row, and anything stronger would compete
   with the EXECUTE block's regime colour, which is the thing being read. */
.rankt tr.fundedrow > td { background: var(--funded-row); }
.rankt tr.fundedrow > td:first-child { box-shadow: inset 3px 0 0 var(--funded-edge); }
.rankt tr.fundedrow.traded > td { background: var(--funded-row-2); }

/* --- the account cell: one identity line, one meta tag ------------------- */
.rt-meta {
  display: inline-block; margin-top: 3px;
  font-size: 12px; color: var(--muted); font-weight: 600;
}
.rt-meta.m-paid  { color: var(--pos); }
.rt-meta.m-ready { color: var(--pos-ink); }
.rt-meta.m-met   { color: var(--pos); }
/* The next payout moves the account to the firm's live account: a red pill, the one
   thing on a funded row that says do NOT request. */
.rt-meta.m-live {
  color: var(--neg); background: var(--neg-weak); border: 1px solid var(--neg);
  border-radius: var(--radius-token); padding: 1px 7px;
}
/* THE FINISH LINE (v4.99). Under one preset day's target, so a single trade ends
   the eval — the moment oversizing is most tempting and most expensive. It gets
   the only pill treatment in this cell: amber, bordered, unmissable at a glance
   down the column. Bordered rather than solid so it never competes with the UP
   NEXT row banding, which owns solid amber on this page. */
.rt-meta.m-finish {
  color: var(--warn); background: var(--warn-weak); border: 1px solid var(--warn);
  border-radius: var(--radius-token); padding: 1px 7px;
}
/* The size ceiling, beside the badge — the second half of the answer, so the
   dollars and the biggest legal position are one glance apart instead of four
   columns. Dashed: it is a limit, not a quantity to type. */
.rt-cap {
  display: inline-block; margin-left: 6px; vertical-align: 1px;
  font-size: 10px; font-weight: 800; letter-spacing: .05em; text-transform: uppercase;
  color: var(--warn); border: 1px dashed var(--warn); border-radius: var(--radius-token); padding: 1px 6px;
  white-space: nowrap; cursor: help;
}

/* An OPEN position is the one thing in this cell that is never hidden (v4.98).
   It is not a control you go looking for, it is a state you must be told: money
   is live in this account right now. So it sits in the flow on its own line,
   always — and ONLY when there is one, so a quiet row costs nothing. Every other
   row is exactly as tall as it was. */
.rt-open { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 5px; }

/* Controls and provenance — real functionality, just not first-glance material.
   Revealed on hover or keyboard focus, and ALWAYS shown where there is no hover
   to reveal them with: a touch device would otherwise lose them entirely.

   They are taken OUT OF FLOW rather than merely faded. Fading alone leaves the
   row exactly as tall as before — the clutter goes but none of the height does,
   which is half a fix. Absolute positioning gives back the space AND avoids the
   layout shift that display:none would cause on every hover, which in a table
   you are scanning down is worse than the clutter was.

   **[KEY-CONCEPT] It stays INSIDE the account cell** (v4.103). Two anchors were
   tried and both leaked. The cell's top-right corner sat on the account NUMBER,
   which is a link you click to open the account. `left: 100%` off the identity
   line (v4.100) cleared the number but spilled into the next column — and since
   v4.102 that column is EXECUTE, so it landed on the regime pill, which IS the
   click-to-plan risk control. A card that covers a control is worse than one
   that covers a figure, and out there every neighbour is a control.

   So: the cell's own bottom-right corner, and `right` keeps it inside the column
   whatever the row is doing. The bottom-LEFT belongs to the open chip and the
   card clears it horizontally; nothing else in the cell reaches that corner. */
.rankt .rt-acct { position: relative; }
.rt-tools {
  position: absolute; right: 8px; bottom: 6px; z-index: 2;
  display: flex; flex-wrap: nowrap; align-items: center; gap: 6px;
  padding: 3px 6px; border-radius: var(--radius-token);
  background: var(--surface); border: 1px solid var(--border);
  box-shadow: var(--shadow);
  opacity: 0; pointer-events: none; transition: opacity .12s ease;
}
.rankt tr:hover .rt-tools,
.rankt tr:focus-within .rt-tools { opacity: 1; pointer-events: auto; }
/* Back in the flow, always visible, last in the cell — wherever the floating card
   cannot work:

     (hover: none)       no hover to reveal it with.
     (max-width: 1160px) narrower than the table's own 1080px plus `.page`'s 48px
                         of gutter (and a scrollbar), so `.rankt-bleed`
                         is scrolled and only part of the row is on screen. A card
                         anchored a column to the right of the account then opens
                         outside the visible window — the blow button behind the
                         scrollbar — and one folded narrow enough to stay in it is
                         tall enough for the wrap to clip its top off instead.
                         In the flow there is no overflow to clip and no anchor to
                         reach past: the row simply grows.  */
@media (hover: none), (max-width: 1160px) {
  .rt-tools { position: static; margin-top: 5px; opacity: 1; pointer-events: auto;
              flex-wrap: wrap; background: none; border: 0; box-shadow: none; padding: 0; }
  /* no toolbar to anchor to once it is back in the flow — the form comes with it */
  .settleset[open] .settle-form {
    position: static; flex-wrap: wrap; white-space: normal; margin: 6px 0 2px;
    padding: 0; background: none; border: 0; box-shadow: none;
  }
}

/* a spent row recedes — its execution block is history, not an instruction */
.rankt tr.traded .xblock { opacity: .55; }

/* the NT8 identifier must never wrap — it is matched character by character
   against the Chart Trader dropdown, and a broken line breaks that match */
.rt-idline { flex-wrap: nowrap; }
.rt-acct .rt-num { white-space: nowrap; }
.rankt .rt-acct { min-width: 250px; }

/* ---------------------------------------------------------------------------
   The Audit page (v4.86) — the measured twin of the Masterplan's projection.
   The verdict leads, because it is the answer; everything below is the working.
--------------------------------------------------------------------------- */
.audit-form .audit-presets { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }
.btn-chip {
  display: inline-block; padding: 6px 12px; border-radius: var(--radius-token); font-size: 13px;
  background: var(--surface-2); border: 1px solid var(--border); color: var(--text);
  text-decoration: none;
}
.btn-chip:hover { border-color: var(--accent); }
.btn-chip.on { background: var(--accent-weak); color: var(--accent); border-color: transparent; font-weight: 600; }
.audit-form .check { display: flex; gap: 9px; align-items: flex-start; margin: 10px 0; font-size: 13px; }
.audit-form .check input { margin-top: 3px; }
.audit-window { font-size: 12px; margin-top: 10px; }

.verdict { border-left: 4px solid var(--border); }
.verdict.bad  { border-left-color: var(--neg); background: var(--neg-faint); }
.verdict.good { border-left-color: var(--pos); background: var(--pos-faint); }
.verdict-big { font-size: 40px; font-weight: 800; font-variant-numeric: tabular-nums;
               margin: 4px 0 2px; line-height: 1.1; }
.verdict-sum { font-size: 14px; color: var(--muted); margin: 0 0 12px; }
.verdict-sum strong { color: var(--text); font-variant-numeric: tabular-nums; }
.verdict-band { font-size: 13px; background: var(--surface-2); border-radius: var(--radius-token);
                padding: 10px 12px; margin: 0 0 4px; }
.verdict-band.firm { background: var(--neg-weak); }
.verdict h3 { font-size: 13px; text-transform: uppercase; letter-spacing: .04em;
              color: var(--muted); margin: 18px 0 8px; }
.bkt { width: 100%; }
.bkt th { font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); }
.bkt td, .bkt th { padding: 7px 10px; border-bottom: 1px solid var(--border); text-align: left; }
.bkt td.num, .bkt th.num { text-align: right; font-variant-numeric: tabular-nums; }
.stat-v.band { font-size: 16px; }
.quality-bad { border-left: 4px solid var(--warn); }

/* ---------------------------------------------------------------------------
   Equity comparison chart (v4.95, impact.php)
   Two series, one axis. "What happened" is the recessive reference — grey and
   dashed; the proposal carries the accent. The dash is deliberate secondary
   encoding: identity must survive a colourblind reader and a greyscale print,
   so it is never carried by hue alone.
--------------------------------------------------------------------------- */
.eqchart { position: relative; margin: 6px 0 2px; }
.eqchart svg { width: 100%; height: 320px; display: block; overflow: visible; }
.eq-line { fill: none; stroke-width: 2; vector-effect: non-scaling-stroke;
           stroke-linejoin: round; stroke-linecap: round; }
.eq-actual { stroke: var(--muted); stroke-dasharray: 5 4; }
.eq-cons   { stroke: var(--accent); }
.eq-zero   { stroke: var(--border-strong); stroke-width: 1; vector-effect: non-scaling-stroke; }
/* `hidden` is an HTMLElement property — assigning el.hidden on an SVG child sets
   a JS expando and leaves the content attribute alone, so the crosshair drew a
   stray line down the left edge on every load. Visibility rides a class on the
   CONTAINER, which is real HTML, and both layers read it. */
.eq-cross  { stroke: var(--border-strong); stroke-width: 1; vector-effect: non-scaling-stroke;
             opacity: 0; transition: opacity .08s linear; }
.eqchart.eq-on .eq-cross { opacity: 1; }
.eq-legend { display: flex; gap: 16px; flex-wrap: wrap; margin-bottom: 6px;
             font-size: .82rem; color: var(--muted); }
.eq-key { display: inline-flex; align-items: center; gap: 7px; }
.eq-key::before { content: ""; width: 18px; height: 0; border-top-width: 2px; }
.eq-key-actual::before { border-top: 2px dashed var(--muted); }
.eq-key-cons::before   { border-top: 2px solid var(--accent); }
.eq-axis { display: flex; justify-content: space-between; font-size: .76rem;
           color: var(--muted); margin-top: 2px; }
.eq-tip { display: none; position: absolute; pointer-events: none; z-index: 3; background: var(--surface);
          border: 1px solid var(--border); border-radius: var(--radius-token); box-shadow: var(--shadow);
          padding: 7px 10px; font-size: .8rem; line-height: 1.45; white-space: nowrap;
          transform: translate(-50%, -100%); }
.eqchart.eq-on .eq-tip { display: block; }
.eq-tip b { font-variant-numeric: tabular-nums; }
.eq-tip .k { color: var(--muted); }
.eq-grid { stroke: var(--border); stroke-width: 1; vector-effect: non-scaling-stroke; }
/* Labels sit in HTML, not in the SVG: the plot uses preserveAspectRatio="none"
   to fill its box, which would stretch any text inside it. */
.eq-plot { position: relative; }
.eq-ylabels { position: absolute; inset: 0; pointer-events: none; }
.eq-ylabels span { position: absolute; left: 0; transform: translateY(-50%);
                   font-size: .72rem; color: var(--muted); background: var(--surface);
                   padding: 0 4px; font-variant-numeric: tabular-nums; }

/* ===========================================================================
   §fleet sync — the Quick Sync Fleet overlay on the Book (v5.98)
   ---------------------------------------------------------------------------
   A native <dialog>: the browser owns the backdrop, the focus trap and Escape.
   The body is a four-column register — account, the Book's balance, the field,
   the live diff — that collapses to two columns on a phone. Every colour is a
   token (§palette); the diff reads the same --pos / --neg the tables use.
   =========================================================================== */
.fleet-sync {
  border: 1px solid var(--border); padding: 0; margin: auto;
  width: min(720px, calc(100vw - 32px)); max-height: min(88vh, 900px);
  border-radius: var(--radius); background: var(--surface); color: var(--text);
  box-shadow: 0 24px 64px var(--shadow-lg-ink);
  overflow: hidden;   /* the rows scroll, the head and foot stay put */
}
.fleet-sync::backdrop { background: rgba(10, 12, 18, .45); backdrop-filter: blur(2px); }
.fleet-sync .fs-form { display: flex; flex-direction: column; max-height: min(88vh, 900px); }
.fs-head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 12px;
  padding: 18px 22px 12px; border-bottom: 1px solid var(--border);
}
.fs-head h2 { margin: 0 0 4px; font-size: 18px; }
.fs-head p { margin: 0; font-size: 13px; line-height: 1.45; }
.fs-head kbd {
  font: 600 11px/1 ui-monospace, SFMono-Regular, Menlo, monospace;
  padding: 2px 5px; border-radius: 4px;
  background: var(--surface-2); border: 1px solid var(--border-strong); color: var(--text);
}
.fs-close {
  flex: none; width: 32px; height: 32px; border-radius: var(--radius-token);
  border: 1px solid var(--border); background: var(--surface); color: var(--muted);
  font-size: 20px; line-height: 1; cursor: pointer;
}
.fs-close:hover { background: var(--surface-2); color: var(--text); }

.fs-cols, .fs-row {
  display: grid; grid-template-columns: minmax(0, 1.7fr) minmax(0, 1fr) minmax(0, 1.1fr) minmax(0, .9fr);
  gap: 8px 14px; align-items: center; padding: 8px 22px;
}
.fs-cols {
  font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--muted); border-bottom: 1px solid var(--border); background: var(--surface-2);
}
.fs-rows { overflow: auto; flex: 1 1 auto; min-height: 0; }
.fs-row { border-bottom: 1px solid var(--border); }
.fs-row:last-child { border-bottom: 0; }
.fs-row.funded { background: color-mix(in srgb, var(--pos-weak) 35%, var(--surface)); }
.fs-row.changed { background: color-mix(in srgb, var(--accent-weak) 60%, var(--surface)); }
.fs-row.invalid { background: color-mix(in srgb, var(--neg-weak) 60%, var(--surface)); }
.fs-acct { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.fs-id { font-weight: 600; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.fs-label { font-weight: 400; color: var(--muted); }
.fs-sub { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; font-size: 12px; }
.fs-prev { color: var(--muted); text-align: right; white-space: nowrap; }
.fs-new .sync-balance-input {
  width: 100%; margin: 0; text-align: right; font-variant-numeric: tabular-nums;
  font-weight: 600; padding: 7px 9px;
}
.fs-new .sync-balance-input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-weak); outline: none; }
.fs-diff { text-align: right; font-weight: 700; white-space: nowrap; color: var(--muted); }
.fs-diff.pos { color: var(--pos); }
.fs-diff.neg { color: var(--neg); }
.fs-diff.invalid { color: var(--neg); font-weight: 400; }

.fs-foot {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px;
  padding: 12px 22px 16px; border-top: 1px solid var(--border); background: var(--surface);
}
.fs-summary { font-size: 13px; font-variant-numeric: tabular-nums; }
.fs-err { font-size: 13px; color: var(--neg); flex: 1 1 100%; }
.fs-actions { display: inline-flex; gap: 8px; margin-left: auto; }
.fleet-sync.busy .fs-rows { opacity: .6; }
.fleet-sync.busy .fs-form { cursor: progress; }

/* the moment after a save, before the page reloads: the repainted rows glow */
tr.synced > td { background: var(--accent-weak); transition: background .2s; }

@media (max-width: 640px) {
  .fleet-sync { width: calc(100vw - 16px); max-height: calc(100vh - 16px); }
  .fs-cols { display: none; }
  .fs-row { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); padding: 10px 16px; }
  .fs-acct { grid-column: 1 / -1; }
  .fs-prev { text-align: left; }
  .fs-prev::before { content: 'book '; font-size: 11px; text-transform: uppercase; letter-spacing: .05em; }
  .fs-new { grid-column: 1 / 2; }
  .fs-diff { grid-column: 2 / 3; }
  .fs-prev { grid-column: 1 / -1; }
  .fs-head, .fs-foot { padding-left: 16px; padding-right: 16px; }
}

/* ---------- admin/activity (v5.103): the owner's user-activity page ---------- */
.act-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: var(--border); vertical-align: middle; margin-right: 2px; }
.act-dot.act-hot  { background: var(--pos); }
.act-dot.act-warm { background: var(--accent); }
.act-dot.act-cold { background: var(--warn); }
.act-dot.act-gone { background: var(--border); }
.stat-v.act-hot  { color: var(--pos); }
.stat-v.act-gone { color: var(--muted); }
.act-flag { width: 20px; height: 15px; border-radius: 2px; vertical-align: -2px; margin-right: 5px; box-shadow: inset 0 0 0 1px rgba(0,0,0,.12); }
.act-roster td { vertical-align: top; }
/* The Pages card's share bar: width is the page's views against the busiest page. */
.act-track { height: 6px; border-radius: 999px; background: var(--surface-2); overflow: hidden; }
.act-track i { display: block; height: 100%; background: var(--accent); border-radius: 999px; }
/* One account's last 14 days: a column per day, height against the busiest day. */
.act-bars { display: grid; grid-template-columns: repeat(14, 1fr); gap: 4px; align-items: end; height: 96px; }
.act-day { display: flex; flex-direction: column; align-items: center; height: 100%; }
.act-col { flex: 1; width: 100%; display: flex; align-items: flex-end; }
.act-col i { display: block; width: 100%; background: var(--accent); border-radius: 3px 3px 0 0; }
.act-dl { font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums; margin-top: 3px; }
/* Feature adoption grid: one tinted cell per feature, the tint is recency. */
.act-grid th.num { white-space: nowrap; font-size: 11px; }
.act-grid tr.act-grp th { text-align: center; font-size: 11px; letter-spacing: .06em; text-transform: uppercase; border-bottom: none; padding-bottom: 0; color: var(--muted); }
.act-cell { font-weight: 600; }
.act-cell.act-hot  { background: var(--pos-weak); color: var(--pos); }
.act-cell.act-warm { background: var(--accent-weak); color: var(--accent-ink); }
.act-cell.act-cold { background: var(--warn-weak); color: var(--warn-ink); }
.act-cell.act-gone { background: var(--surface-2); color: var(--muted); }
.act-cell.act-never { font-weight: 400; }
.act-two { display: grid; gap: 16px; }
.tables .card.act-wide { grid-column: 1 / -1; }
@media (min-width: 900px) { .act-two { grid-template-columns: 1fr 1fr; } }

/* ---------- What's new (v5.113) ---------- */
/* One card per release. The anchor the bar and the footer land on scrolls
   clear of the sticky top bar (and the reload bar above it) and is tinted so
   the eye finds the release it was sent to. */
.release { scroll-margin-top: calc(56px + 16px + var(--updbar-h, 0px)); }
@media (min-width: 768px) { .release { scroll-margin-top: calc(92px + 16px + var(--updbar-h, 0px)); } }
.release h2 { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin: 0 0 6px; }
.release h2 a { color: var(--text); }
.release-date { font-size: 13px; font-weight: 500; }
.release:target { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-weak); }
.release .plain li { line-height: 1.5; }
.release .plain li:first-child { border-top: 0; }

/* ---------- Schedule (v5.145, Founding Operator) ----------
   Which bracket to fire at which hour. Bracket colours are fixed roles, each a
   light-dark() pair so the page follows the theme toggle like everything else. */
.sched-page { --sc-hr: light-dark(#b45309, #e0a33a); --sc-r2: light-dark(#6d28d9, #a78bfa);
  --sc-ev: light-dark(#1f6feb, #5a9bff); --sc-h25: light-dark(#0f766e, #34c0a4); --sc-h10: light-dark(#0e7490, #38c6d6); }
.sched-pill { font: 600 11px/1.6 ui-monospace, SFMono-Regular, Menlo, monospace; padding: 0 8px; border-radius: 999px; color: #fff; white-space: nowrap; }
.sched-pill.is-alt { background: transparent !important; color: var(--text); box-shadow: inset 0 0 0 1.5px currentColor; }
.sched-hr { background: var(--sc-hr); } .sched-r2 { background: var(--sc-r2); } .sched-ev { background: var(--sc-ev); }
.sched-h25 { background: var(--sc-h25); } .sched-h10 { background: var(--sc-h10); }
.sched-pill.is-alt.sched-hr { color: var(--sc-hr); } .sched-pill.is-alt.sched-r2 { color: var(--sc-r2); } .sched-pill.is-alt.sched-ev { color: var(--sc-ev); }
.sched-pill.is-alt.sched-h25 { color: var(--sc-h25); } .sched-pill.is-alt.sched-h10 { color: var(--sc-h10); }
.sched-clock { font-size: 28px; font-weight: 700; font-variant-numeric: tabular-nums; margin-bottom: 8px; }
.sched-clock span { font-size: 13px; font-weight: 500; color: var(--muted); margin-left: 8px; }
.sched-block { border: 1px solid var(--border); border-left: 4px solid var(--accent); border-radius: var(--radius); padding: 10px 14px; margin-bottom: 8px; background: var(--surface); }
.sched-block.is-now { border-left-width: 6px; background: var(--surface-2); }
.sched-block.is-skip { border-left-color: var(--neg); }
.sched-block > summary { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; cursor: pointer; list-style: none; }
.sched-block > summary::-webkit-details-marker { display: none; }
.sched-block-body { margin-top: 8px; }
.sched-block-body .sched-when, .sched-block-body .sched-lbl { display: none; }
.sched-when { font-weight: 700; font-variant-numeric: tabular-nums; min-width: 118px; }
.sched-lbl { color: var(--muted); font-size: 13px; }
.sched-is-now .sched-when, .sched-block.is-now .sched-when { font-size: 20px; }
.sched-pills { display: flex; gap: 6px; flex-wrap: wrap; margin-left: auto; }
.sched-skip, .sched-skip-tag { color: var(--neg-ink); font-weight: 600; }
.sched-skip-tag { font-size: 12px; }
.sched-list { list-style: none; margin: 8px 0 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.sched-list li { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.sched-ln { font-weight: 600; } .sched-ln em { font-style: normal; font-weight: 500; color: var(--muted); font-size: 12px; }
.sched-role { color: var(--muted); font-size: 12px; }
.sched-e { margin-left: auto; font-variant-numeric: tabular-nums; font-size: 12px; font-weight: 600; }
.sched-e.pos { color: var(--pos-ink); } .sched-e.neg { color: var(--neg-ink); }
.sched-note { margin: 8px 0 0; color: var(--muted); font-size: 13px; max-width: 70ch; }
.sched-grid-card > summary { cursor: pointer; list-style: none; }
.sched-grid-card > summary h2 { display: inline; font-size: 12px; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); font-weight: 600; margin: 0; }
.sched-grid-wrap { overflow-x: auto; margin-top: 12px; }
.sched-grid { display: grid; grid-template-columns: 150px repeat(20, minmax(34px, 1fr)); gap: 3px; min-width: 860px; }
.sg-lab { display: flex; flex-direction: column; justify-content: center; font-size: 12.5px; padding-right: 6px; }
.sg-lab small { color: var(--muted); font-size: 11px; }
.sg-band { font-size: 11px; color: var(--muted); text-align: center; background: var(--surface-2); border-radius: 4px; padding: 2px 0; }
.sg-hr { font-size: 11px; color: var(--muted); text-align: center; font-variant-numeric: tabular-nums; }
.sg-hr.is-now { color: var(--text); font-weight: 700; }
.sg-c { height: 34px; border-radius: 5px; display: flex; align-items: center; justify-content: center; font: 600 11px ui-monospace, monospace; color: #fff; }
.sg-c.is-alt { opacity: .45; color: var(--text); }
.sg-c.is-pos { background: var(--pos-weak); color: var(--pos-ink); }
.sg-c.is-neg { background: var(--neg-weak); color: var(--neg-ink); }
.sg-c.is-thin { background: var(--surface-2); color: var(--muted); }
.sg-c.is-dead { background: repeating-linear-gradient(135deg, transparent 0 5px, var(--neg-weak) 5px 7px); }
.sched-grid-wrap { position: relative; padding: 4px 0; }
.sched-grid-wrap > :not(.sched-band) { position: relative; z-index: 1; }
.sched-band { position: absolute; z-index: 0; border-radius: 8px; pointer-events: none;
  background: color-mix(in oklab, var(--text) 9%, transparent); }
.sched-legend, .sched-foot { font-size: 12px; color: var(--muted); margin: 10px 0 0; }
/* Book: schedule banner and per-account badge (v5.146) */
.sched-banner { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 14px; margin: 0 0 14px; padding: 9px 14px;
  border: 1px solid var(--border); border-left: 4px solid var(--pos); border-radius: var(--radius); background: var(--surface);
  color: var(--text); text-decoration: none; font-size: 13px; }
.sched-banner.is-skip { border-left-color: var(--neg); }
.sched-banner b { font-variant-numeric: tabular-nums; }
.sched-banner span { color: var(--muted); }
.sched-banner .sb-now { color: var(--text); font-weight: 600; }
.sched-banner .sb-go { margin-left: auto; color: var(--accent-ink); font-weight: 600; }
.xflag.sched-flag { text-decoration: none; }
.xflag.sched-flag:empty { display: none; }
.xflag.sched-flag.is-go { background: var(--pos); color: var(--on-solid); }
.xflag.sched-flag.is-alt { background: var(--warn-weak-2); color: var(--warn-ink); }
.xflag.sched-flag.is-wait { background: var(--surface-2); color: var(--muted); }
/* Schedule: win-rate report (v5.153) */
.sw-verdict { display: flex; flex-wrap: wrap; gap: 12px 28px; margin: 12px 0 4px; }
.sw-vh { display: block; font-size: 11px; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); font-weight: 600; margin-bottom: 6px; }
.sw-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.sw-chip { display: inline-flex; flex-direction: column; padding: 4px 10px; border-radius: 8px; color: #fff; line-height: 1.2; }
.sw-chip b { font-size: 15px; font-variant-numeric: tabular-nums; }
.sw-chip small { font-size: 11px; opacity: .9; }
.sw-chip.is-go { background: var(--pos); } .sw-chip.is-no { background: var(--neg); }
.sw-none { color: var(--muted); font-size: 13px; }
.sw-table { border-collapse: separate; border-spacing: 3px; width: 100%; min-width: 620px; font-variant-numeric: tabular-nums; font-size: 12.5px; }
.sw-table th { font-size: 11px; color: var(--muted); font-weight: 600; text-align: center; padding: 4px; white-space: nowrap; }
.sw-table th small { display: block; font-weight: 500; }
.sw-table th.l, .sw-table td.l { text-align: left; }
.sw-table td { text-align: center; padding: 5px 4px; border-radius: 5px; }
.sw-table td b { display: block; font-weight: 600; }
.sw-table td i { font-style: normal; font-size: 10.5px; opacity: .85; }
.sw-table td.is-thin { opacity: .45; }
.sw-h { font-weight: 700; white-space: nowrap; } .sw-s { color: var(--muted); white-space: nowrap; }
/* Schedule on a phone (v5.153): wide tables scroll inside their card, never widen the page. */
.sched-page { min-width: 0; max-width: 100%; }
.sched-page > .card, .sched-page > details, .sched-page > section { min-width: 0; max-width: 100%; }
.sched-grid-wrap { max-width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }
.sched-block > summary { min-width: 0; }
.sched-pills { flex-wrap: wrap; justify-content: flex-end; min-width: 0; }
@media (max-width: 640px) { .sched-when { min-width: 0; } .sched-pills { margin-left: 0; width: 100%; justify-content: flex-start; } }


/* v5.182: the Passed page — one card per eval waiting for its funded account. */
.passed-card { margin-bottom: 14px; }
.passed-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px; }
.passed-sub { margin: 4px 0 0; font-size: 13px; }
.passed-form { display: grid; grid-template-columns: minmax(180px, 1fr) minmax(200px, 1.2fr) auto; gap: 0 14px; align-items: end; margin-top: 12px; }
.passed-form label { margin-bottom: 0; }
.passed-form .seg { margin: 0; }
.passed-form .pf-actions { grid-column: 1 / -1; align-items: center; margin-top: 12px; }
.passed-form .pf-actions .btn-primary { width: auto; flex: 0 0 auto; }
.passed-mark { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 12px; font-size: 13px; }
@media (max-width: 720px) { .passed-form { grid-template-columns: 1fr; gap: 12px; } }
