/* ═══════════════════════════════════════════════════════════════════════════
   PORTFOLIO — built to the owner's reference screenshot, structurally.

   The screenshot is the specification. Composition, module order, proportions
   and density come from it, not from a reinterpretation of it:

     full-height left rail (232px, flush left, thin border - NOT a floating card)
       logo, vertical nav with line icons, Simulated Account card pinned bottom
     main
       header      title + subtitle left, market state / date / avatar right
       account     ONE full-width card: big value left, four metrics inline
       row 1       Performance Over Time (wide)  |  Allocation (narrow)
       row 2       Holdings (wide)               |  Recent Activity (narrow)

   TWO DEPARTURES, both the owner's own standing instructions rather than design
   choices of mine:
     1. "Deposit Funds" is not built. The card and its position are kept exactly;
        the button is the Pro upgrade. The owner: "we're never gonna make people
        deposit money" and "the add funds button should just say upgrade to
        JagSim Pro."
     2. The site header (.pt-appbar) stays above this page. Removing it makes
        js/app-nav.js:182 mount its #anav "rooms" fallback, which is how the
        discontinued Hub reached a live page during the chart rebuild.
   ═══════════════════════════════════════════════════════════════════════════ */

:root {
  --pf-bg: #f7f8fa;
  --pf-panel: #ffffff;
  --pf-line: #e8eaee;
  --pf-line-2: #f0f2f5;
  --pf-ink: #1a1d21;
  --pf-ink-2: #3d444d;
  --pf-muted: #6b7280;
  --pf-muted-2: #626b7a;
  --pf-green: #1f7a4d;
  --pf-green-soft: #eaf5ef;
  --pf-pos: #14804a;
  --pf-neg: #c0392b;
  --pf-rail-w: 232px;
  --pf-radius: 12px;
  --pf-sans: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

body.pt-body { margin: 0; background: var(--pf-bg); color: var(--pf-ink); font-family: var(--pf-sans); -webkit-font-smoothing: antialiased; }
.pfd *, .pfd *::before, .pfd *::after { box-sizing: border-box; }
.pfd a { color: inherit; text-decoration: none; }
.pfd button, .pfd input { font: inherit; }

.pfd { display: grid; grid-template-columns: var(--pf-rail-w) minmax(0, 1fr); align-items: stretch; min-height: calc(100vh - 96px); }

/* ── Left rail: flush, full height, one hairline border. Not a card. ─────── */
.pfd-rail {
  background: var(--pf-panel); border-right: 1px solid var(--pf-line);
  padding: 20px 16px 18px; display: flex; flex-direction: column; gap: 18px;
  align-self: start;
  /* THE RAIL SCROLLED AWAY WITH THE PAGE. Owner has raised this more than once.
     position:sticky was already here and structurally fine — no overflow ancestor
     breaks it — but it failed for two reasons at once:
       1. top:0 pinned it UNDER the 88px sticky .pt-appbar, so its top was always
          hidden behind the header (his screenshot starts mid-word: "time").
       2. A sticky box TALLER THAN THE VIEWPORT cannot pin usefully — there is no
          room left to stick to, so it just travels with the scroll.
     Pin below the app bar, cap it to the remaining viewport, and let the rail scroll
     INTERNALLY when its own content is too tall. The page no longer drags it. */
  position: sticky;
  top: var(--pf-appbar-h, 88px);
  max-height: calc(100vh - var(--pf-appbar-h, 88px));
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
}
/* Hide the rail's own scrollbar track until it is needed, so a short rail looks flush. */
.pfd-rail::-webkit-scrollbar { width: 6px; }
.pfd-rail::-webkit-scrollbar-thumb { background: var(--pf-line); border-radius: 6px; }
.pfd-rail::-webkit-scrollbar-track { background: transparent; }
.pfd-brand { display: flex; align-items: center; gap: 10px; padding: 0 6px; }
.pfd-brand img { height: 30px; width: auto; display: block; }
.pfd-brand span { font-size: 20px; font-weight: 700; letter-spacing: -.02em; }

.pfd-nav { display: flex; flex-direction: column; gap: 2px; }
.pfd-nav a {
  display: flex; align-items: center; gap: 12px; height: 40px; padding: 0 12px;
  border-radius: 8px; color: var(--pf-ink-2); font-size: 14px; font-weight: 500;
}
.pfd-nav a svg { width: 18px; height: 18px; flex: 0 0 18px; opacity: .75; }
.pfd-nav a:hover { background: var(--pf-line-2); }
.pfd-nav a.on { background: var(--pf-green-soft); color: var(--pf-green); font-weight: 600; }
.pfd-nav a.on svg { opacity: 1; }
.pfd-nav a[hidden] { display: none !important; }

/* No flex spacer. It shoved the Simulated Account card to the bottom of a very
   tall rail, hundreds of pixels below the nav with the Pro upgrade and the
   market countdown down there with it - the owner read them as missing. */
.pfd-rail-spacer { display: none; }
/* The reference's "Simulated Account" card, pinned to the bottom of the rail. */
.pfd-acct {
  border: 1px solid var(--pf-line); border-radius: var(--pf-radius);
  padding: 14px; background: var(--pf-panel);
}
.pfd-acct-hd { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; margin-bottom: 14px; }
.pfd-acct-hd strong { display: block; font-size: 13px; font-weight: 600; }
.pfd-acct-hd span { display: block; font-size: 12px; color: var(--pf-muted); margin-top: 2px; }
.pfd-acct-row { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 12px; font-size: 12.5px; }
.pfd-acct-row .k { color: var(--pf-muted); }
.pfd-acct-row .v { font-weight: 600; color: var(--pf-ink); }
.pfd-acct-row .v.pos { color: var(--pf-pos); }
.pfd-acct-row .v.neg { color: var(--pf-neg); }
.pfd-acct .pfd-btn { width: 100%; margin-top: 4px; }
.pfd-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  height: 38px; padding: 0 14px; border: 1px solid var(--pf-line); border-radius: 8px;
  background: var(--pf-panel); color: var(--pf-ink); font-size: 13px; font-weight: 600; cursor: pointer;
}
.pfd-btn:hover { background: var(--pf-line-2); }
.pfd-btn--pro { background: var(--pf-green); border-color: var(--pf-green); color: #fff; }
.pfd-btn--pro:hover { background: #17603c; }

/* ── Main ────────────────────────────────────────────────────────────────── */
.pfd-main { padding: 26px 30px 34px; min-width: 0; display: flex; flex-direction: column; gap: 18px; }
.pfd-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 20px; flex-wrap: wrap; }
.pfd-head h1 { margin: 0 0 4px; font-size: 26px; font-weight: 600; letter-spacing: -.02em; }
.pfd-head p { margin: 0; font-size: 14px; color: var(--pf-muted); }
.pfd-head-right { display: flex; align-items: center; gap: 14px; }
.pfd-mkt { display: flex; align-items: center; gap: 7px; font-size: 13px; font-weight: 500; color: var(--pf-ink-2); }
.pfd-mkt i { width: 8px; height: 8px; border-radius: 50%; background: #626b7a; display: inline-block; }
.pfd-mkt.is-open i { background: #22c55e; }
.pfd-asof { font-size: 12.5px; color: var(--pf-muted); }
.pfd-avatar { width: 36px; height: 36px; border-radius: 50%; background: #d7dbe0; color: #4b5259; display: grid; place-items: center; font-size: 13px; font-weight: 600; }

/* ── Panels ──────────────────────────────────────────────────────────────── */
.pfd-card { background: var(--pf-panel); border: 1px solid var(--pf-line); border-radius: var(--pf-radius); }
.pfd-card[hidden] { display: none !important; }
.pfd-card-hd { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 16px 20px 0; flex-wrap: wrap; }
.pfd-card-hd h2 { margin: 0; font-size: 15px; font-weight: 800; letter-spacing: -.01em; }
.pfd-card-bd { padding: 16px 20px 20px; }
.pfd-link { font-size: 13px; font-weight: 500; color: var(--pf-green); background: none; border: 0; padding: 0; cursor: pointer; }

/* Account card: big value left, four metrics inline right - one card. */
.pfd-acctcard { padding: 22px 24px; display: flex; align-items: flex-start; gap: 56px; flex-wrap: wrap; }
.pfd-acctcard-lead { flex: 0 0 auto; }
/* ONE LABEL TREATMENT ON THIS STRIP. There were three competing systems here —
   .pfd-acctcard-lead .k at 14px/500, .pfd-metric .k at 13px/500, and the
   10.5px/800 uppercase card-label rule — and which one won depended on how the
   element happened to be nested. That is why the strip read as though five labels
   had been styled by five people. All of them are the same RANK of thing: the
   small word above a number. One treatment, the one eight of ten label sites in
   this codebase already use. */
.pfd-acctcard-lead .k {
  display: block; font-size: 10.5px; font-weight: 800; letter-spacing: .08em;
  text-transform: uppercase; color: var(--pf-muted); margin-bottom: 8px;
}
/* 800, not 600. The hero is the largest number on the page and it was LIGHTER
   than the card titles beside it, which read as unfinished rather than calm. */
.pfd-acctcard-lead .v { display: block; font-size: 30px; font-weight: 800; letter-spacing: -.03em; line-height: 1; }
.pfd-acctcard-lead .d { margin: 10px 0 0; font-size: 13px; font-weight: 700; color: var(--pf-pos); font-variant-numeric: tabular-nums; }
.pfd-acctcard-lead .d.neg { color: var(--pf-neg); }
.pfd-acctcard-lead #portHdrPnlSub {
  display: block; margin: 4px 0 0; font-size: 11.5px; font-weight: 600; color: var(--pf-muted);
}
.pfd-acctcard-cols { flex: 1 1 520px; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 30px; padding-top: 4px; }
/* Same treatment as the hero label above — these sit in the same strip and were
   1px apart at a different weight, which is drift, not hierarchy. */
.pfd-metric .k {
  display: block; font-size: 10.5px; font-weight: 800; letter-spacing: .08em;
  text-transform: uppercase; color: var(--pf-muted); margin-bottom: 7px;
}
/* 20px and 800: 17/600 against a 38/800 hero left a gap with nothing in it, so
   the four columns read as a footnote to the one number rather than as peers. */
.pfd-metric .v {
  display: block; font-size: 20px; font-weight: 800; letter-spacing: -.02em;
  white-space: nowrap; font-variant-numeric: tabular-nums;
}
.pfd-metric .v.pos { color: var(--pf-pos); }
.pfd-metric .v.neg { color: var(--pf-neg); }
.pfd-metric .s { display: block; margin-top: 5px; font-size: 12px; font-weight: 500; color: var(--pf-muted); }

/* The two content rows: wide | narrow, both times. */
.pfd-row { display: grid; grid-template-columns: minmax(0, 1fr) 500px; gap: 18px; align-items: start; }
/* Performance | Allocation: stretch the donut card to the equity chart's bottom
   (owner 2026-08-24). Only on this row, and only while they sit side by side —
   stacking at 1080px must not grow Allocation into empty space. */
@media (min-width: 1081px) {
  .pfd-row--match { align-items: stretch; }
  .pfd-row--match > .pfd-card { display: flex; flex-direction: column; }
  .pfd-row--match > .pfd-card > .pfd-card-bd { flex: 1 1 auto; }
  #analyticsSection > .pfd-card-bd {
    display: flex;
    flex-direction: column;
    justify-content: center;
  }
}

/* Performance */
.pfd-chips { display: flex; gap: 6px; flex-wrap: wrap; }
.pfd-chip {
  height: 28px; padding: 0 11px; border-radius: 6px; border: 1px solid var(--pf-line);
  background: var(--pf-panel); color: var(--pf-ink-2); font-size: 12.5px; font-weight: 500; cursor: pointer;
}
.pfd-chip:hover { border-color: var(--pf-muted-2); }
.pfd-chip.on { background: #2b3138; border-color: #2b3138; color: #fff; }
/* THE CANVAS OWNS ITS OWN HEIGHT. renderEquityChart sets canvas.style.height
   inline (responsive, DPR-scaled) and reads canvas.clientWidth to size the
   backing store. Pinning the box to 300px and the canvas to height:100% fought
   that on both axes - the drawing was scaled to one height and displayed at
   another, which is why the line came out wrong again after it had been fixed.
   min-height only, so the panel still reserves space before the first paint. */
.pfd-chartbox { position: relative; min-height: 260px; }
.pfd-chartbox canvas { width: 100%; display: block; }

/* Allocation */
.pfd-donutwrap { display: grid; place-items: center; padding: 4px 0 16px; }
.alloc-donut { width: 168px; height: 168px; }
.donut-c1 { font-size: 10px; font-weight: 600; fill: var(--pf-ink); }
.donut-c2 { font-size: 5px; font-weight: 500; fill: var(--pf-muted); }
.donut-c3 { font-size: 4.6px; font-weight: 500; fill: var(--pf-muted); }
.legend-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 11px; }
.legend-list li { display: grid; grid-template-columns: 1fr auto auto; align-items: center; column-gap: 22px; font-size: 13px; }
.legend-list .lg-sym { display: flex; align-items: center; gap: 9px; color: var(--pf-ink-2); min-width: 0; }
.legend-list .lg-pct { color: var(--pf-ink-2); font-weight: 500; text-align: right; }
.legend-list .lg-val { color: var(--pf-ink); font-weight: 500; text-align: right; min-width: 88px; }
.lg-dot { width: 9px; height: 9px; border-radius: 50%; flex: 0 0 9px; display: inline-block; }
.alloc-note { font-size: 12.5px; color: var(--pf-muted); line-height: 1.5; margin: 10px 0 0; }

/* Holdings */
/* overflow-x:auto ALONE DOES NOT CONSTRAIN A FLEX OR GRID CHILD. The default
   min-width:auto lets the box grow to fit its contents, so min-width:0 is required
   for the scroller to hold its ground -- it measures 325px with 1214px of scrollable
   content, which is correct.
   CORRECTION (2026-08-19): min-width:0 alone did NOT stop the page scrolling sideways,
   and this comment used to claim it did. With the scroller measuring a correct 325px
   the document still reported scrollWidth 1210. The remaining 835px came from the
   .sr-only spans escaping the scroller -- see the position:relative note below. */
.pfd-tablewrap {
  overflow-x: auto; min-width: 0; max-width: 100%; -webkit-overflow-scrolling: touch;
  /* position:relative is NOT cosmetic here. An overflow scroller only clips
     absolutely-positioned descendants when it is also their CONTAINING BLOCK.
     While this was static, the .sr-only spans inside the table cells were laid
     out against a far ancestor, escaped the scroller entirely, and parked at
     x=1210 -- extending the DOCUMENT scrolling area even though the table
     itself was properly contained at 325px. That is what iOS Safari panned. */
  position: relative;
}
.pfd-card, .pfd-card-bd, .pfd-main, .pfd-row, .pfd-row--full, .pfd-row--pair { min-width: 0; }
.pfd table { width: 100%; border-collapse: collapse; font-size: 13px; }
.pfd thead th {
  text-align: left; color: var(--pf-muted); font-size: 12.5px; font-weight: 500;
  padding: 0 12px 12px; border-bottom: 1px solid var(--pf-line); white-space: nowrap;
}
.pfd tbody td { padding: 14px 12px; border-bottom: 1px solid var(--pf-line-2); color: var(--pf-ink-2); white-space: nowrap; }
.pfd tbody tr:last-child td { border-bottom: 0; }
.pfd tbody td:first-child { color: var(--pf-ink); font-weight: 600; }
.pfd .num { text-align: right; }
.pfd thead th.num { text-align: right; }
.h-sym { display: flex; align-items: center; gap: 10px; }
.h-badge { width: 24px; height: 24px; border-radius: 6px; background: #eef1f4; display: grid; place-items: center; font-size: 10.5px; font-weight: 700; color: #5a626b; flex: 0 0 24px; }
.pos { color: var(--pf-pos); }
.neg { color: var(--pf-neg); }

/* Recent activity */
.activity-list { display: flex; flex-direction: column; }
.activity-item { display: flex; align-items: flex-start; justify-content: space-between; gap: 14px; padding: 13px 0; border-bottom: 1px solid var(--pf-line-2); }
.activity-item:last-child { border-bottom: 0; }
.activity-item__content { display: flex; align-items: flex-start; gap: 12px; min-width: 0; flex: 1 1 auto; }
.activity-item__dot { width: 32px; height: 32px; border-radius: 50%; display: grid; place-items: center; flex: 0 0 32px; }
.activity-item__dot svg { width: 15px; height: 15px; }
.activity-item__dot--buy { background: var(--pf-green-soft); color: var(--pf-green); }
.activity-item__dot--sell { background: #fdeeeb; color: var(--pf-neg); }
.activity-item__dot--note { background: #eef1f4; color: #5a626b; }
.activity-item__text { min-width: 0; }
.activity-item__text strong { display: block; font-size: 13.5px; font-weight: 600; color: var(--pf-ink); margin-bottom: 3px; }
.activity-item__text span { display: block; font-size: 12.5px; color: var(--pf-muted); overflow: hidden; text-overflow: ellipsis; }
.activity-item time { font-size: 12px; color: var(--pf-muted); text-align: right; white-space: nowrap; flex: 0 0 auto; line-height: 1.5; }

/* ── Recent Activity: the right-hand column ────────────────────────────────
   Owner: "recent activities needs to be styled a bit better. Seems like a lot of
   wasted space here." A full-width card held [icon + two short lines] then ~1,300px
   of nothing, then a date. The row was not badly padded - it was missing its most
   useful number, so the amount now stacks above the date and the eye has somewhere
   to land at the end of the row. Tabular figures so the dollar columns line up
   down the list rather than jittering with digit width. */
.activity-item__meta {
  display: flex; flex-direction: column; align-items: flex-end; gap: 2px;
  flex: 0 0 auto; text-align: right;
}
.activity-item__amt {
  font-size: 13.5px; font-weight: 700; color: var(--pf-ink);
  white-space: nowrap; font-variant-numeric: tabular-nums;
}
.activity-item__amt.pos { color: var(--pf-green); }
/* The rows were 13px apart on a card tall enough for far more of them; tightening
   the gap is what puts another event on screen without shrinking any text. */
.activity-item { padding: 11px 0; }

.empty-state { color: var(--pf-muted); font-size: 13px; line-height: 1.6; padding: 26px 4px; text-align: center; }
.empty-state a { color: var(--pf-green); font-weight: 600; }

@media (max-width: 1280px) { .pfd-row { grid-template-columns: minmax(0, 1fr) 400px; } }
@media (max-width: 1080px) {
  .pfd { grid-template-columns: 1fr; }
  /* Stacked layout: the rail is a top strip, not a column — drop the pin and the cap. */
  .pfd-rail { border-right: 0; border-bottom: 1px solid var(--pf-line);
    position: static; max-height: none; overflow-y: visible; }
  .pfd-row { grid-template-columns: 1fr; }
  .pfd-acctcard-cols { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .pfd-main { padding: 20px 16px 28px; }
}
@media (max-width: 620px) {
  .pfd-acctcard { gap: 24px; }
  .pfd-acctcard-lead .v { font-size: 26px; }
  .pfd-acctcard-cols { grid-template-columns: 1fr; }
}


/* ── Holdings column widths ────────────────────────────────────────────────
   Name was unconstrained, so it absorbed every spare pixel and left a canyon
   between it and Type while the numeric columns crowded the right edge. Capped
   with an ellipsis, so a long company name shortens rather than pushing the
   table apart. */
.pfd .holdings-table, .pfd #holdingsTable { table-layout: auto; }
.pfd #holdingsTable th:nth-child(1), .pfd #holdingsTable td:nth-child(1) { width: 1%; white-space: nowrap; }
.pfd #holdingsTable th:nth-child(2), .pfd #holdingsTable td:nth-child(2) {
  max-width: 190px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pfd #holdingsTable th:nth-child(3), .pfd #holdingsTable td:nth-child(3) { width: 1%; white-space: nowrap; }
.pfd #holdingsTable td:nth-child(n+4), .pfd #holdingsTable th:nth-child(n+4) { width: 1%; white-space: nowrap; }

/* The page opens on the numbers. The "Portfolio" heading repeated the nav tab
   already lit above it and pushed the account card down the fold. */
.pfd-head--bare { justify-content: flex-end; margin-bottom: -4px; }
.pfd-chips--right { margin-left: auto; }

/* A full-width row. Holdings has nine columns and was sharing row 2 with Recent
   Activity, which left it ~500px short - Unrealized P&L, P&L % and Weight were
   clipped off the right edge while Activity sat mostly empty beside it. */
.pfd-row--full { grid-template-columns: minmax(0, 1fr) !important; }

/* The stat matrices. portfolio-page.css draws .stats-grid as 4 across; the
   rebuild dropped the class from #tsGrid and #riskGrid, so both rendered as one
   very tall label/value column that ate the page. */
.pfd .stats-grid { border-top: 1px solid var(--pf-line); }
.pfd .st-cell:nth-child(4n) { border-right: 0; }
@media (max-width: 1100px) { .pfd .stats-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 620px) { .pfd .stats-grid { grid-template-columns: 1fr; } }


/* ── Tighter account strip ─────────────────────────────────────────────────
   The reference reads as ONE dashboard strip; 56px gaps and 30px column gutters
   made five floating widgets with a lot of air between them. Pulled in so the
   numbers group, and the lead figure keeps its dominance without the row
   sprawling. */
.pfd-acctcard { padding: 18px 22px; gap: 34px; }
.pfd-acctcard-cols { gap: 18px; flex-basis: 560px; }

/* Denser panels overall - the reference is disciplined, not airy. */
.pfd-main { gap: 14px; padding: 20px 24px 28px; }
.pfd-card-hd { padding: 14px 18px 0; }
.pfd-card-bd { padding: 14px 18px 16px; }
.pfd tbody td { padding: 11px 12px; }
.pfd thead th { padding: 0 12px 10px; }

/* ── Undo the OLD page's grid placement ────────────────────────────────────
   css/portfolio-page.css:333-336 pins #pfPerfPanel/#analyticsSection/
   #holdingsPanel/#pfActivityPanel to explicit grid-column / grid-row values for
   the PREVIOUS two-column layout. That file is loaded again (it styles all the
   JS-rendered rows), and it brought those placements with it - which is why
   Recent Activity stayed 478px wide inside a row that computes one track: being
   placed in column 2 CREATES an implicit second column. The desk lays its own
   rows out; nothing here should be hand-placed. */
.pfd #pfPerfPanel,
.pfd #analyticsSection,
.pfd #holdingsPanel,
.pfd #pfActivityPanel { grid-column: auto !important; grid-row: auto !important; }


/* ══ ACCOUNT VALUE STRIP — match the reference ═════════════════════════════
   The reference puts the whole account on ONE line: the big value on the left
   with its change beneath, and Cash / Buying Power / Day Change / Unrealized
   inline to its right. Ours stacked the four metrics UNDER the value, which is
   what the owner kept pointing at - it doubles the height of the card and
   pushes the chart down the page for no information gained. */
.pfd-acctcard {
  position: relative;
  display: grid !important;
  grid-template-columns: minmax(210px, auto) minmax(0, 1fr) !important;
  align-items: start;
  column-gap: 40px;
  row-gap: 10px;
  padding: 20px 22px;
}
.pfd-acctcard-lead { display: block; }
.pfd-acctcard-lead .k,
.pfd-acctcard-cols .k,
.pfd-acctcard .pfd-metric .k {
  display: block;
  font-size: 10.5px !important;
  font-weight: 800 !important;
  letter-spacing: .08em !important;
  text-transform: uppercase !important;
  color: var(--pf-muted) !important;
  margin-bottom: 6px;
  text-decoration: none !important;
}
.pfd-acctcard .coachjag-cue:not(.coachjag-cue--edge),
.pfd-acctcard .coachjag-cue--edge {
  color: inherit !important;
  text-decoration: none !important;
  box-shadow: none !important;
}
.pfd-acctcard-lead .v {
  display: block;
  font-size: 24px !important;
  line-height: 1.12;
  font-weight: 800;
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
}
.pfd-acctcard-lead .d { margin: 6px 0 0; font-size: 13px; font-weight: 700; }

/* Four metrics: same size as each other, one step under the hero. */
.pfd-acctcard-cols .v,
.pfd-acctcard .pfd-metric .v {
  display: block;
  font-size: 22px !important;
  font-weight: 800;
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
  line-height: 1.15;
  white-space: nowrap;
}
.pfd-acctcard-cols .s,
.pfd-acctcard .pfd-metric .s {
  display: block;
  min-height: 1.25em;
  margin-top: 5px;
  font-size: 12px;
  font-weight: 500;
  color: var(--pf-muted);
}

/* Market state + timestamp, in the card rather than on a row of their own. */
.pfd-acctcard-status {
  grid-column: 1 / -1;
  display: flex; justify-content: flex-end; align-items: center; gap: 12px;
  font-size: 12.5px; color: var(--pf-muted);
  margin-bottom: -4px;
}

@media (max-width: 760px) {
  .pfd-acctcard { grid-template-columns: minmax(0, 1fr) !important; }
  .pfd-acctcard-cols { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; row-gap: 12px; }
}

/* "I already fucking told you use white font for things when you have a dark
   background. I can't read that." - the Pro button is solid green with the
   body's dark text inherited straight through it. */
.pfd-btn--pro,
.pfd-rail .pfd-btn--pro,
a.pfd-btn--pro {
  color: #fff !important;
  font-weight: 800;
}
.pfd-btn--pro:hover, .pfd-btn--pro:focus { color: #fff !important; }


/* TWO PRO PROMPTS ON ONE SCREEN. The rail already carries "Upgrade to JagSim
   Pro"; #holdingsProUpsell put a second, larger one directly beneath the
   holdings table - the owner: "we should not have to unlock with pros next to
   each other, that looks fishy". Worse, it advertised depth that is not on this
   page, so it promised something the page cannot deliver.
   Hidden on the portfolio desk only. js/pro-upsell.js is untouched, so every
   other placement it owns still works. */
.pfd #holdingsProUpsell,
body.pfd-page #holdingsProUpsell { display: none !important; }

/* ══ ALLOCATION LEGEND ═════════════════════════════════════════════════════
   Label, percent and money are three columns in the reference, on one line per
   segment. Ours let the money wrap onto its own line and drift right, so
   "Crypto 0.0%" sat above "$29.86" with no visual relationship. */
#allocLegend { list-style: none; margin: 14px 0 0; padding: 0; display: grid; gap: 8px; }
#allocLegend li {
  display: grid !important;
  grid-template-columns: 12px minmax(0, 1fr) auto auto !important;
  align-items: center;
  column-gap: 12px;
  font-size: 13px;
  white-space: nowrap;
}
#allocLegend .lg-dot { width: 10px; height: 10px; border-radius: 50%; display: block; }
#allocLegend .lg-sym { font-weight: 700; color: var(--pf-text, var(--jag-ink, #1a1f29)); text-align: left; overflow: hidden; text-overflow: ellipsis; }
#allocLegend .lg-pct { font-variant-numeric: tabular-nums; font-weight: 700; text-align: right; min-width: 52px; }
#allocLegend .lg-val { font-variant-numeric: tabular-nums; color: var(--pf-muted); text-align: right; min-width: 92px; }


/* ══ THE YELLOW BANNERS ════════════════════════════════════════════════════
   "Latest session", "Past week - from 2026-08-10", "AMZN is 76% of your
   invested value" were rendering as full-width amber slabs under the charts.
   The owner read them as error styling, and fairly - amber on a trading page
   means something is wrong. They are captions, so they look like captions now:
   plain muted text, no box, no fill. */
.pfd .alloc-note,
.pfd #equityChartSub,
.pfd #allocConcentration {
  background: none !important;
  border: 0 !important;
  border-radius: 0 !important;
  padding: 8px 0 0 !important;
  margin: 6px 0 0 !important;
  color: var(--pf-muted) !important;
  font-size: 12.5px !important;
  font-weight: 500 !important;
}

/* ══ WATCHLIST + DIVIDENDS SHARE A ROW ═════════════════════════════════════
   Both held one short line of content and each spanned the full page width, so
   a single watchlist symbol sat alone in a band the width of the desk. The
   owner's own suggestion: put them side by side, half and half. */
.pfd-row--pair {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 16px;
  /* STRETCH, not start. Watchlist and Upcoming dividends are a matched pair — the
     owner: "why are watchlist and dividends separate if they're the same height?"
     They already sat side by side, but align-items:start let each shrink to its own
     content, so two cards of near-identical height rendered with mismatched bottoms
     and read as unrelated blocks that happened to be adjacent. Equal height makes
     them one row, which is what they are. */
  align-items: stretch;
}
.pfd-row--pair > * { display: flex; flex-direction: column; }
.pfd-row--pair .pfd-card-bd { flex: 1 1 auto; }
/* Dividends starts hidden for a new book. A 2-col grid then leaves Watchlist
   as a half-width strip with a blank column — looks like a layout break. */
.pfd-row--pair.is-single,
.pfd-row--pair:has(#divScheduleCard[style*="display: none"]) {
  grid-template-columns: minmax(0, 1fr);
}
@media (max-width: 900px) { .pfd-row--pair { grid-template-columns: minmax(0, 1fr); } }

/* Watchlist. The rules below used to target #watchlistItems and .wl-chip - NEITHER
   EXISTS. The real container is #watchlistList, and its renderer emits table rows
   (now wrapped in their own <table>, see portfolio-page.js). A selector that
   matches nothing fails silently, which is why every previous pass at this looked
   applied and changed nothing on screen. */
.pfd .pfd-wl-tbl { width: 100%; border-collapse: collapse; margin-top: 10px; }
.pfd .pfd-wl-tbl td {
  padding: 9px 4px; font-size: 13px; vertical-align: middle;
  border-bottom: 1px solid var(--pf-border, #eef1f5);
}
.pfd .pfd-wl-tbl tr:last-child td { border-bottom: 0; }
.pfd .pfd-wl-tbl td.num { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.pfd .pfd-wl-tbl td.wl-x { width: auto; text-align: right; white-space: nowrap; }
.pfd .pfd-wl-tbl .h-symbol { font-weight: 800; text-decoration: none; }
.pfd .pfd-wl-tbl .sub-pct { font-size: 12px; font-weight: 700; margin-left: 6px; font-variant-numeric: tabular-nums; opacity: 1; }  /* .82 from portfolio-page.css:496 put this at 2.75:1 */
.pfd .wl-remove-btn {
  border: 1px solid var(--pf-border, #e4e8ee); background: var(--pf-surface, #fff);
  border-radius: 7px; height: 28px; padding: 0 10px; line-height: 1;
  color: var(--pf-muted, #6b7480); cursor: pointer; font: inherit; font-size: 12px; font-weight: 700;
}
.pfd .wl-remove-btn:hover { color: #d64550; border-color: #f0c9cd; }

/* Watchlist: the add row and the chips were laid out as loose inline text. */
.pfd #watchlistSection .wl-add,
.pfd #watchlistSection form { display: flex; gap: 8px; align-items: center; }
.pfd #watchlistSection input[type="text"] { flex: 1 1 auto; min-width: 0; }
.pfd .wl-chips, .pfd #watchlistItems {
  display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px;
}
.pfd .wl-chip, .pfd #watchlistItems > * {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 10px;
  border: 1px solid var(--pf-border, #e4e8ee);
  border-radius: 999px;
  background: var(--pf-surface, #fff);
  font-size: 13px; white-space: nowrap;
}

/* Upcoming dividends: symbol, detail and amount ran together on one line with
   no spacing, so "AAPL8 shares - $0.27/shareNov 9" read as one word. */
.pfd #divScheduleCard li {
  display: grid;
  /* FOUR columns, not three. The renderer emits four spans - ds-sym, ds-detail,
     ds-when, ds-amt - into a three-column grid, so the amount had nowhere to go
     and wrapped onto a second row underneath the symbol. That is the stray "$0.22"
     hanging below GOOGL in the owner's screenshot. Amount sits right of the detail
     and left of the date, which is also the order you read it in. */
  grid-template-columns: 64px minmax(0, 1fr) auto auto;
  gap: 4px 14px;
  align-items: baseline;
  padding: 8px 0;
  border-top: 1px solid var(--pf-border, #eef1f5);
  list-style: none;
}
.pfd #divScheduleCard li:first-child { border-top: 0; }
.pfd #divScheduleCard .ds-sym { font-weight: 800; font-size: 13px; }
.pfd #divScheduleCard .ds-detail { color: var(--pf-muted, #6b7480); font-size: 12.5px; min-width: 0; }
.pfd #divScheduleCard .ds-amt {
  order: 3; font-weight: 800; font-size: 13px; color: var(--pf-pos, #12805c);
  text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums;
}
.pfd #divScheduleCard .ds-when {
  order: 4; color: var(--pf-muted, #6b7480); font-size: 12.5px;
  text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums;
}
/* An ex-date already passed pays nothing; grey the whole row so it reads as
   informational rather than as money coming. */
.pfd #divScheduleCard li.ds-inelig .ds-amt { color: var(--pf-muted, #6b7480); font-weight: 700; }
.pfd #divScheduleCard ul { margin: 0; padding: 0; }
.pfd #divScheduleCard b, .pfd #divScheduleCard strong:first-child { font-weight: 800; }


/* ══ TYPE + CONTRAST PASS (portfolio) ══════════════════════════════════════
   The page mixed three label treatments - 12px/600 muted, 12.5px/500 muted, and
   11px/800 uppercase - often within one card. One scale now, so a label reads as
   a label everywhere and the eye stops re-learning the hierarchy per panel.

   Numbers get tabular figures throughout: proportional digits change width as
   prices tick, which makes a live column jitter and reads as instability on a
   money screen. */
/* `th` LEFT THIS GROUP. A column header and a card's micro-label are not the
   same rank of thing, but they shared one declaration — so Holdings' header row
   rendered 11.5px/600 sentence case while the Options table two cards below
   rendered 11px/800 letterspaced uppercase, on the same scroll. Headers now match
   the treatment the leaderboard, the chart dock and Options already use; labels
   move to the 10.5px/800 uppercase scale that eight of the ten label sites in
   this codebase were already on. */
.pfd .pfd-card .k,
.pfd .pfd-metric .k,
.pfd .pfd-acct-row .k {
  font-size: 10.5px;
  font-weight: 800;
  color: var(--pf-muted);
  letter-spacing: .08em;
  text-transform: uppercase;
}
.pfd th {
  font-size: 11px;
  font-weight: 800;
  color: var(--pf-muted);
  letter-spacing: .07em;
  text-transform: uppercase;
}
.pfd td, .pfd .pfd-metric .v, .pfd .pfd-acct-row .v,
.pfd .num, .pfd [class*="value"] {
  font-variant-numeric: tabular-nums;
}
.pfd .holdings-group td {
  font-size: 11px; font-weight: 700; letter-spacing: .08em;
  color: var(--pf-muted);
}
/* Positions sub-lines were the lowest-contrast text on the page and carry cost
   basis - the number a trader checks most often after the price. */
.pfd .pos-sub, .pfd .h-co, .pfd .s { color: var(--pf-muted); }


/* ══ PORTFOLIO CONSISTENCY PASS ════════════════════════════════════════════
   Faults visible in the owner's own screenshots, each an inconsistency rather
   than a matter of taste.

   1. RECENT ACTIVITY'S HEADING WAS CENTRED while every other card heading on the
      page is left-aligned. One centred heading in a column of left-aligned ones
      reads as a mistake, because it is one. */
.pfd #pfActivityPanel .pfd-card-hd,
.pfd #activityHead {
  justify-content: space-between;
  text-align: left;
}
.pfd #pfActivityPanel .pfd-card-hd > :first-child { margin-right: auto; }

/* 2. THE NOTEPAD WAS A CARD INSIDE A CARD. The section supplies the "Notepad"
      heading and the card frame; the mounted notebook then drew its own frame,
      its own "Notebook" heading and its own description inside it. Two borders,
      two titles, one feature. The inner chrome stands down - the module is
      shared with Research, so it is hidden here rather than edited there. */
.pfd #notepadSection .nb-card {
  border: 0 !important;
  box-shadow: none !important;
  padding: 0 !important;
  background: transparent !important;
}
/* THE RULE THAT REMOVED THE NOTEPAD'S TITLE. Owner, twice: "you remove the title for
   the notes... make sure you have the title filled back on the notepad for portfolio."
   This hid BOTH the heading and the description line.

   The .sub is restored -- it explained what the notepad is and nothing else on the card
   said it. The <h3> stays hidden for one reason only: it reads "Notebook" while the card
   header two lines above already reads "Notepad", so showing it puts two different names
   for the same thing on one card. The card header IS the title. The per-note title now
   sits on the editor itself, which is the thing that was actually missing: the list
   showed a name for every note and the editor showed none. */
.pfd #notepadSection .nb-card > h3 { display: none; }

/* 3. UPCOMING DIVIDENDS wrapped its amount onto its own line, so the money -
      the reason the row exists - sat orphaned under the date. Three aligned
      columns: symbol, detail, amount. */
.pfd #divScheduleCard li,
.pfd #divScheduleList li {
  display: grid;
  grid-template-columns: 56px minmax(0, 1fr) auto;
  align-items: baseline;
  gap: 2px 12px;
}
.pfd #divScheduleList li > :last-child { justify-self: end; font-variant-numeric: tabular-nums; }

/* 4. DEFINITION UNDERLINES read as errors. Coach Jag marks glossary terms with
      an underline, and on "Buying Power", "Realized P&L" and "Watchlist" it
      landed as a hard orange rule under a heading - which on a money screen
      looks like a validation failure. A dotted underline in the muted colour
      still says "there is a definition here" without shouting. */
.pfd [data-term], .pfd .jag-term, .pfd .coach-term {
  text-decoration: none !important;
  border-bottom: 1px dotted var(--pf-muted);
  cursor: help;
}
.pfd .pfd-card-hd h2,
.pfd .pfd-card-hd h2.coachjag-cue,
.pfd .pfd-card-hd h2 .coachjag-cue {
  text-decoration: none !important;
  border-bottom: 0 !important;
  box-shadow: none !important;
}

/* 5. ONE HEADING SCALE. Card titles were drifting between weights and sizes. */
.pfd .pfd-card-hd h2 {
  font-size: 15px; font-weight: 800; letter-spacing: -.01em; margin: 0;
}
.pfd .pfd-card-hd { align-items: baseline; gap: 12px; }


/* ══ THE TWO RAIL CARDS ════════════════════════════════════════════════════
   What replaced the Simulated Account block. Two cards, each carrying one fact
   that appears nowhere else on the page, sized so the rail reads as navigation
   with a footer rather than as a second dashboard. */
.pfd-rail-cards { display: grid; gap: 10px; margin-top: 18px; }

.pfd-railcard {
  display: block;
  padding: 14px 16px;
  border: 1px solid var(--pf-border, #e4e8ee);
  border-radius: 14px;
  background: var(--pf-surface, #fff);
  text-decoration: none;
}
.pfd-railcard-k {
  display: block; font-size: 11.5px; font-weight: 600;
  color: var(--pf-muted); letter-spacing: .01em;
}
.pfd-railcard-v {
  display: block; margin-top: 3px;
  font-size: 19px; font-weight: 800; letter-spacing: -.01em;
  color: var(--pf-ink, #16202f);
  font-variant-numeric: tabular-nums;
}
.pfd-railcard-s { display: block; margin-top: 2px; font-size: 12px; color: var(--pf-muted); }

/* The upgrade is the one place on this rail that should pull the eye, so it is
   the only filled surface. White on the brand green - the contrast failure the
   owner reported on the old button, which inherited body ink onto a dark fill. */
.pfd-railcard--pro {
  background: linear-gradient(180deg, #0a7a55 0%, #046a49 100%);
  border-color: #046a49;
  color: #fff;
  box-shadow: 0 6px 18px -8px rgba(4, 106, 73, .55);
}
.pfd-railcard--pro:hover { background: linear-gradient(180deg, #0b8a5f 0%, #057753 100%); }
.pfd-railcard-pro-k {
  display: block; font-size: 11.5px; font-weight: 700;
  color: rgba(255, 255, 255, .82); letter-spacing: .02em; text-transform: uppercase;
}
.pfd-railcard-pro-v {
  display: block; margin-top: 2px; font-size: 17px; font-weight: 800; color: #fff;
}

/* The old block's rules are retired with it. */
.pfd-acct, .pfd-acct-hd, .pfd-acct-row { display: none !important; }


/* ══ RECENT ACTIVITY ═══════════════════════════════════════════════════════
   Rebuilt to the owner's spec. The old feed was one flat run of rows with the
   timestamp floating and no grouping, which is why it read as a dump rather
   than a log.

   Date headers first - Today / Yesterday / Aug 10 - because that single change
   is what turns a list into an activity log. Then a strict two-line row:
   action + asset on line one, quantity and price muted beneath it. The
   timestamp gets its own aligned right-hand column so the eye can scan straight
   down it instead of hunting. */
.pfd .pf-act-day {
  position: sticky; top: 0; z-index: 1;
  padding: 10px 0 6px;
  font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: var(--pf-muted);
  background: var(--pf-surface, #fff);
}
.pfd .pf-act-day + .activity-item { border-top: 0; }

.pfd .activity-item {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 12px;
  padding: 11px 0;
  border-top: 1px solid var(--pf-border, #eef1f5);
}
.pfd .activity-item__content { display: flex; align-items: center; gap: 12px; min-width: 0; }
.pfd .activity-item__dot {
  width: 26px; height: 26px; flex: 0 0 auto;
  border-radius: 50%; display: grid; place-items: center;
}
.pfd .activity-item__dot svg { width: 13px; height: 13px; }
.pfd .activity-item__text { display: grid; gap: 1px; min-width: 0; }
.pfd .activity-item__text strong {
  font-size: 13.5px; font-weight: 700; letter-spacing: -.01em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.pfd .activity-item__text span { font-size: 12px; color: var(--pf-muted); font-variant-numeric: tabular-nums; }
.pfd .activity-item time {
  font-size: 12px; color: var(--pf-muted);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}

/* Colour carries action type, consistently: green in, red out, grey neutral. */
.pfd .activity-item__dot--buy  { background: #e7f6ed; color: #0a7a55; }
.pfd .activity-item__dot--sell { background: #fdeceb; color: #b91c1c; }
.pfd .activity-item__dot--note,
.pfd .activity-item__dot--div  { background: #eef1f5; color: #5f6875; }

/* Filter chips in the card header. */
.pfd .pf-act-filters { display: flex; gap: 6px; flex-wrap: wrap; margin-left: auto; }
.pfd .pf-act-filters button {
  padding: 5px 11px; border-radius: 999px;
  border: 1px solid var(--pf-border, #e4e8ee);
  background: var(--pf-surface, #fff);
  font: inherit; font-size: 12px; font-weight: 600;
  color: var(--pf-muted); cursor: pointer;
}
.pfd .pf-act-filters button.on {
  background: #e7f6ed; border-color: #bfe0cd; color: #0a7a55; font-weight: 700;
}
.pfd .pf-act-empty { margin: 14px 0; font-size: 13px; color: var(--pf-muted); }


/* ═══ BEGINNER / INTERMEDIATE PORTFOLIO ════════════════════════════════════
   Owner: "what beginner mode controls the portfolio with the new user sees...
   what is important for a beginner on the portfolio page? What would they need
   to see?"

   THE RULE: a mode changes what is ON SCREEN and what the words say. It never
   changes what the account can do and it never changes a number. Nothing here is
   locked or sold -- switching mode on Coach Jag brings it all straight back.

   WHAT A BEGINNER KEEPS, and why:
     Account value        what am I worth
     Cash you can spend   what can I buy right now
     Holdings             what do I own, and am I up or down on it
     Allocation           the donut is the most intuitive thing on the page
     Recent activity      what have I done
     Open orders          only rendered when some exist
     Watchlist, dividends, notepad

   WHAT IT HIDES, and why these three specifically: Performance Over Time,
   Trading performance and Risk & consistency all describe a TRACK RECORD. On a
   day-one account they are empty axes and zeroes, which reads as a broken page
   rather than a page that is waiting -- and each one demands vocabulary
   (drawdown, win rate, Sharpe) that the site has not taught yet.

   Intermediate keeps performance and trading stats and hides only Risk, which is
   the one that needs the most statistics background to read honestly. */
/* PORTFOLIO NO LONGER HIDES ANYTHING BY MODE. Owner: "why don't we just unlock all
   portfolio features? You literally have everything except the calendar... I think just
   Chart and Coach Jag. I think we're doing too much with portfolio."

   He is right, and the code agrees: Trading performance and Risk were ALREADY gated by
   entitlement -- locked tiles, a blur overlay and their own upgrade prompt -- so hiding
   them by mode was a third rule stacked on top of Pro status and data availability. Three
   overlapping gates on one panel is how a card ends up invisible for a reason nobody can
   name.

   There is also a difference in kind that makes Portfolio the wrong place for this. A
   chart tool you do not understand is noise, and hiding it helps. A panel about YOUR OWN
   MONEY that you cannot see is not simpler, it is opaque -- and the owner's standing rule
   is that transparency comes first.

   Mode now means what its label always said: how busy the Chart is, and how deeply Coach
   Jag explains. The Trading calendar stays Pro-gated, because that is entitlement, not
   mode. */

/* The rail must not point at a card that is not on the page -- a link that
   scrolls nowhere is exactly the dead-button problem the watchlist/dividends
   entry had. Hide the entry with the section. */
/* (rail entry rule removed with the panel hiding above -- the section is visible in
   every mode now, so its link must be too) */


/* ── First landing: welcome, then tour, then level ─────────────────────────
   Green because it is an invitation; no amber. Level chips are secondary so
   Take the tour is the thing you see first. */
#pfExpFork { border-color: var(--pf-green, var(--jag-green)); }
.pf-fork-h { margin: 0 0 6px; font-size: 19px; font-weight: 700; letter-spacing: -.01em; }
.pf-fork-p { margin: 0 0 16px; color: var(--pf-muted); font-size: 14px; line-height: 1.6; max-width: 62ch; }
.pf-fork-actions { display: flex; flex-wrap: wrap; gap: 10px; }
.pf-fork-btn {
  font: inherit; font-size: 14px; font-weight: 700; cursor: pointer;
  padding: 11px 18px; border-radius: 10px; text-decoration: none;
  border: 1px solid var(--pf-line, #dbe1e8); background: #fff; color: var(--pf-ink, #0f1729);
  display: inline-flex; align-items: center; justify-content: center;
}
.pf-fork-btn:hover { border-color: var(--pf-green, var(--jag-green)); }
.pf-fork-btn--go { background: var(--pf-green, var(--jag-green)); border-color: var(--pf-green, var(--jag-green)); color: #fff; }
.pf-fork-btn--go:hover { filter: brightness(1.07); }
.pf-fork-lvl-k {
  margin: 0 0 8px;
  font-size: 11px; font-weight: 800; letter-spacing: .08em;
  text-transform: uppercase; color: var(--pf-muted);
}
.pf-fork-levels { display: flex; flex-wrap: wrap; gap: 8px; }
.pf-fork-lvl {
  flex: 1 1 0; min-width: 0;
  font: inherit; font-size: 13px; font-weight: 800; cursor: pointer;
  padding: 10px 12px; border-radius: 9px;
  border: 2px solid var(--jag-green); background: var(--jag-green-line); color: var(--jag-green-deep);
}
.pf-fork-lvl:hover { border-color: var(--pf-green, var(--jag-green)); background: #d8eee3; }
.pf-fork-lvl.is-on {
  background: var(--pf-green, var(--jag-green));
  border-color: var(--pf-green, var(--jag-green));
  color: #fff;
  box-shadow: 0 0 0 3px rgba(0, 110, 78, .18);
}
.pf-fork-lvl-s { margin: 8px 0 0; font-size: 12.5px; line-height: 1.45; color: var(--pf-muted); max-width: 62ch; }
@media (max-width: 640px) {
  .pf-fork-actions { flex-direction: column; align-items: stretch; }
  .pf-fork-btn { width: 100%; }
  .pf-fork-levels { flex-wrap: nowrap; }
  .pf-fork-lvl { padding: 9px 6px; font-size: 12.5px; }
}


/* ── Watchlist: why you are watching it ────────────────────────────────────
   Step 1 of the research workspace. The reason sits on its own row under the
   symbol so it can run to a readable length instead of fighting the price column
   for space in a 3-column table. */
.pfd-wl-tbl .wl-why-row > td { padding: 0 0 10px 0; border-top: 0; }
.wl-why {
  font: inherit; font-size: 12.5px; line-height: 1.45; text-align: left;
  background: none; border: 0; padding: 0; cursor: text;
  color: var(--pf-muted); max-width: 62ch;
}
/* An empty reason reads as an invitation; a written one reads as the user's own
   words, so it takes the page's text colour rather than the muted prompt grey. */
.wl-why.has-why, .pfd-wl-tbl .wl-why-row td .wl-why:not(:empty).has-why { color: var(--pf-ink); }
.wl-why:hover { color: var(--pf-green, var(--jag-green)); }
.wl-since { display: block; margin-top: 3px; font-size: 11.5px; color: var(--pf-muted); }
.wl-why-edit {
  font: inherit; font-size: 12.5px; line-height: 1.45; width: 100%; max-width: 62ch;
  padding: 8px 10px; border: 1px solid var(--pf-green, var(--jag-green)); border-radius: 8px;
  resize: vertical; background: #fff; color: var(--pf-ink);
}


/* The watchlist reason, carried onto the holding you now own. Quiet and italic so it
   reads as the user's own aside rather than another data column. */
.h-why {
  display: block; margin-top: 3px; font-size: 11.5px; line-height: 1.4;
  color: var(--pf-muted); font-style: italic; max-width: 46ch;
  overflow: hidden; text-overflow: ellipsis;
}


/* ── Trading calendar ──────────────────────────────────────────────────────
   A month of locked-in results. Colour carries the direction, the number carries
   the amount -- colour alone would be unreadable to anyone colour-blind, which is
   why every coloured cell also prints its figure with a sign. */
.cal-nav { display: flex; align-items: center; gap: 12px; margin: 0 0 12px; }
.cal-month { font-size: 15px; font-weight: 700; color: var(--pf-ink); }
.cal-arrow {
  font: inherit; font-size: 15px; line-height: 1; cursor: pointer;
  width: 32px; height: 32px; border-radius: 8px;
  border: 1px solid var(--pf-line, #dbe1e8); background: #fff; color: var(--pf-ink);
}
.cal-arrow:hover { border-color: var(--pf-green, var(--jag-green)); }
.cal-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 8px; }
.cal-hd { font-size: 11px; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; color: var(--pf-muted); text-align: center; padding-bottom: 6px; }
.cal-cell {
  min-height: 78px; border-radius: 12px; padding: 8px 8px 10px;
  border: 1px solid var(--pf-line-2, #eef1f4); background: #fff;
  display: flex; flex-direction: column; align-items: flex-start; gap: 5px;
  font: inherit; text-align: left;
  box-shadow: 0 1px 0 rgba(16, 24, 20, .04);
}
.cal-cell--pad { border: 0; background: transparent; min-height: 0; box-shadow: none; }
.cal-num { font-size: 11px; font-weight: 800; color: var(--pf-muted); }
.cal-amt { font-size: 13.5px; font-weight: 800; font-variant-numeric: tabular-nums; letter-spacing: -.02em; }
.cal-n { font-size: 11px; color: var(--pf-muted); font-weight: 600; }
button.cal-cell { cursor: pointer; }
.cal-cell--up { background: var(--pf-green-soft, #e8f7ef); border-color: #bfe6d2; }
.cal-cell--up .cal-amt { color: var(--pf-green, var(--jag-green)); }
.cal-cell--down { background: #fdeeeb; border-color: #f5cfc7; }
.cal-cell--down .cal-amt { color: var(--pf-neg, #d64550); }
button.cal-cell:hover { outline: 2px solid var(--pf-green, var(--jag-green)); outline-offset: -2px; }
.cal-legend { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; margin: 12px 0 0; font-size: 12px; color: var(--pf-muted); }
.cal-key { width: 12px; height: 12px; border-radius: 3px; display: inline-block; margin-right: 2px; vertical-align: -1px; }
.cal-key--up { background: var(--pf-green-soft, #e8f7ef); border: 1px solid #bfe6d2; }
.cal-key--down { background: #fdeeeb; border: 1px solid #f5cfc7; }
.cal-key--none { background: #fff; border: 1px solid var(--pf-line-2, #eef1f4); }
.cal-day-detail { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--pf-line-2, #eef1f4); }
.cal-day-detail h3 { margin: 0 0 8px; font-size: 14px; font-weight: 700; }
.cal-d-list { list-style: none; margin: 0; padding: 0; }
.cal-d-list li { display: flex; align-items: baseline; gap: 12px; padding: 6px 0; border-bottom: 1px solid var(--pf-line-2, #eef1f4); font-size: 13px; }
.cal-d-list li:last-child { border-bottom: 0; }
.cal-d-sym { font-weight: 800; min-width: 76px; }
.cal-d-qty { color: var(--pf-muted); flex: 1 1 auto; }
.cal-d-pnl { font-weight: 800; font-variant-numeric: tabular-nums; }
.cal-d-pnl.up { color: var(--pf-green, var(--jag-green)); }
.cal-d-pnl.down { color: var(--pf-neg, #d64550); }
/* THE MINUS SIGN WAS ORPHANING ONTO ITS OWN LINE. In a ~38px cell "-$268.91" broke
   after the minus, so a losing day rendered as "-" above "$268.91" and the whole
   grid read as squashed. The amount is one token and must never break; it shrinks to
   fit instead, and the cell gets a little more height so two lines (day number, then
   amount) sit comfortably rather than colliding. */
@media (max-width: 620px) {
  .cal-cell { min-height: 56px; padding: 4px 2px; }
  .cal-amt {
    font-size: 9.5px; white-space: nowrap; letter-spacing: -0.2px;
    display: block; text-align: center; line-height: 1.2;
  }
  .cal-day { font-size: 10px; line-height: 1.1; }
  .cal-grid { gap: 4px; }
}
/* Very narrow phones: drop the cents rather than let the figure wrap or clip. The
   full amount is still exact in the day detail when a cell is tapped. */
@media (max-width: 400px) {
  .cal-amt { font-size: 9px; }
}

.cal-arrow.is-locked { opacity: .45; }
.cal-lock { text-align: left; }
.cal-lock h3 { margin: 0 0 6px; font-size: 15px; font-weight: 700; }
.cal-lock p { margin: 0 0 12px; font-size: 13px; line-height: 1.55; color: var(--pf-muted); max-width: 56ch; }

/* Trade count sits under the amount, quiet: it is context, not a headline. */
.cal-n { font-size: 10px; font-weight: 700; color: var(--pf-muted); margin-top: auto; }
@media (max-width: 620px) { .cal-n { display: none; } }

/* Sell on a holdings row. Outlined, not solid: it is an action you take rarely and
   deliberately, and a row of solid red buttons would read as a page full of warnings. */
.h-sell {
  display: inline-block; font-size: 12px; font-weight: 800; text-decoration: none;
  padding: 5px 12px; border-radius: 7px; white-space: nowrap;
  border: 1px solid var(--pf-neg, #d64550); color: var(--pf-neg, #d64550); background: #fff;
}
.h-sell:hover { background: #fdeeeb; }
td.h-act { text-align: right; }
/* left:0 is load-bearing. Without it an absolutely-positioned .sr-only sits at its
   STATIC position, which inside a 1178px-wide table is ~1210px from the left edge.
   A hidden 1px label was therefore setting the width of the whole document. Pinning
   it to the containing block origin makes that impossible anywhere it is used. */
.sr-only { position: absolute; left: 0; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* Locked calendar. It replaces the grid entirely rather than blurring it: a blurred
   grid of the user's own data is a tease, and a half-shown feature reads as broken. */
.cal-locked { grid-column: 1 / -1; text-align: center; padding: 26px 18px; }
.cal-locked h3 { margin: 0 0 8px; font-size: 17px; font-weight: 700; }
.cal-locked p { margin: 0 auto 16px; font-size: 13.5px; line-height: 1.6; color: var(--pf-muted); max-width: 52ch; }
.cal-arrow:disabled { cursor: not-allowed; }

/* Matches the nav's PRO chips so one word means one thing everywhere on the site. */
.pf-pro-badge {
  display: inline-block; vertical-align: 2px; margin-left: 8px;
  font-size: 10px; font-weight: 800; letter-spacing: .07em;
  color: var(--pf-green, var(--jag-green)); background: var(--pf-green-soft, #e8f7ef);
  border: 1px solid #bfe6d2; border-radius: 999px; padding: 2px 7px;
}

/* Rail PRO chip, matching the card heading badge. */
.pf-nav-pro {
  margin-left: auto; font-size: 9.5px; font-weight: 800; letter-spacing: .06em;
  color: var(--pf-green, var(--jag-green)); background: var(--pf-green-soft, #e8f7ef);
  border: 1px solid #bfe6d2; border-radius: 999px; padding: 1px 6px;
}

/* ACCOUNT VALUE WAS SHOUTING. Owner: "why is account value so big?" At 38px it was
   nearly twice every other number on the strip, so the eye landed there and nowhere
   else -- and it is not the most useful figure on the page. Cash, day change and gain
   or loss are what a trader checks; account value is context. 30px keeps it the
   largest thing in the row without drowning its neighbours. */

/* A running walkthrough outranks mode hiding. The P&L tour points at Trading
   performance, which beginner mode hides -- and a step spotlighting a display:none
   element highlights nothing at all. Reveals only while cj-tour-on is set, so the
   beginner page is unchanged the rest of the time. */
html.cj-tour-on #tradeStatsSection,
html.cj-tour-on #riskCard,
html.cj-tour-on #notepadSection,
html.cj-tour-on #divScheduleCard { display: block !important; }

/* ═══════════════════════════════════════════════════════════════════════════
   PHONE: THE NUMBERS COME FIRST. Added 2026-08-18.

   .pfd is a two-column grid (rail | main). Below 1080px it collapses to one
   column and then stacks in DOM ORDER, so `aside.pfd-rail` -- the section menu,
   the Next Open countdown and the Upgrade banner, 589px of it measured on a
   390px phone -- sat above every number. A user opening their account on a phone
   scrolled past a menu and an ad before seeing whether they had made money.

   Owner: "users should see key shit on mobile ... it should immediately show
   their fucking performance."

   The rail is not removed -- every link in it still works -- it just stops being
   the first thing. Order only; no markup moved, so nothing that queries these
   elements changes.
   ═══════════════════════════════════════════════════════════════════════════ */
@media (max-width: 1080px) {
  .pfd-main { order: 1; }
  .pfd-rail { order: 2; border-bottom: 0; border-top: 1px solid var(--pf-line); }
}

/* ═══════════════════════════════════════════════════════════════════════════
   LOCKED TRADING-CALENDAR EXAMPLE. Added 2026-08-18.
   The lock used to render an empty box. It now renders a real-looking month,
   blurred behind the offer, because "you can't have this" sells nothing and
   "here is what you're missing" does. Every figure is fixed and invented, and
   the card says so twice — a banner above and a caption below — so it can never
   be read as the viewer's own record.
   ═══════════════════════════════════════════════════════════════════════════ */
/* THE EXAMPLE WAS RENDERING INSIDE A 7-COLUMN GRID AND TOOK ONE CELL OF IT.
   #calGrid carries .cal-grid, which is `display:grid; grid-template-columns:
   repeat(7, 1fr)`. Injecting a wrapper into it made that wrapper a single grid
   ITEM, so the whole example was squeezed into one seventh of the card and the
   lock overlay was clipped. Span every column and reset to normal flow inside.

   To answer the question directly: desktop vs mobile here is decided ONLY by
   @media width. This bug was not a breakpoint mistake -- the CSS was width-neutral
   and simply inherited a parent grid I had not accounted for. It looked like a
   desktop-only fault because the card is narrow on mobile anyway. */
.cal-grid > .calx { grid-column: 1 / -1; width: 100%; }
.calx { position: relative; display: block; }
.calx-banner {
  display: inline-block; margin: 0 0 10px;
  padding: 4px 10px; border-radius: 999px;
  background: var(--pf-soft, #eef2f7); color: var(--pf-muted, #5b6a7a);
  font-size: 11.5px; font-weight: 800; letter-spacing: .02em;
}
.calx-dow {
  display: grid; grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 6px; margin-bottom: 6px;
}
.calx-dow span {
  text-align: center; font-size: 11px; font-weight: 800;
  color: var(--pf-muted, #5b6a7a); text-transform: uppercase; letter-spacing: .04em;
}
.calx-grid {
  display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 6px;
  /* Legible, but plainly a sample rather than live data. */
  filter: blur(1.6px); opacity: .92; pointer-events: none; user-select: none;
}
.calx-cell {
  min-height: 72px; border-radius: 10px; border: 1px solid var(--pf-line, #e6ebf2);
  display: flex; align-items: center; justify-content: center; padding: 4px;
}
.calx-cell--off { background: var(--pf-soft, #f6f8fb); border-style: dashed; }
.calx-up   { background: rgba(21,128,61,.10);  border-color: rgba(21,128,61,.30); }
.calx-down { background: rgba(180,35,42,.09);  border-color: rgba(180,35,42,.28); }
.calx-amt  { font-size: 12px; font-weight: 800; }
.calx-up .calx-amt   { color: #15803d; }
.calx-down .calx-amt { color: #b4232a; }
.calx-stats {
  display: flex; flex-wrap: wrap; gap: 14px; margin-top: 12px;
  font-size: 13px; color: var(--pf-muted, #5b6a7a);
  filter: blur(1.2px); opacity: .92;
}
.calx-cap {
  margin: 8px 0 0; font-size: 11.5px; color: var(--pf-muted, #5b6a7a);
}
.calx-lock {
  /* Centred over the grid, but never taller than it -- the button was being cut
     off at the card edge because the overlay was sized before the grid had height. */
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: min(460px, 94%); max-height: 92%; overflow: auto;
  text-align: center; z-index: 2;
  background: var(--pf-card, #fff); border: 1px solid var(--pf-line, #e6ebf2);
  border-radius: 16px; padding: 18px 20px;
  box-shadow: 0 18px 44px rgba(15, 23, 41, .16);
}
.calx-lock h3 { margin: 0 0 6px; font-size: 17px; }
.calx-lock p  { margin: 0 0 14px; font-size: 13px; line-height: 1.5; color: var(--pf-muted, #5b6a7a); }

@media (max-width: 620px) {
  .calx-cell { min-height: 46px; }
  .calx-amt { font-size: 10.5px; }
  .calx-lock { width: 96%; padding: 14px 14px; }
  .calx-stats { gap: 8px; font-size: 12px; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   HOLDINGS GAIN/LOSS COLOUR. Added 2026-08-18 (execution queue, batch 1 #1).
   The markup already sets .pos / .neg on both the Gain-or-loss and the P/L %
   cells, and portfolio-page.css already defines those colours. They never showed
   because `.pfd tbody td { color: var(--pf-ink) }` in THIS file is specificity
   0,0,1,2 and beats a bare `.pos` at 0,0,1,0 — so every cell was repainted ink.
   Matching the table context settles it: 0,0,2,2 wins.
   ═══════════════════════════════════════════════════════════════════════════ */
.pfd tbody td.pos { color: var(--pos, #117a37); font-weight: 700; }
.pfd tbody td.neg { color: var(--neg, #b4232a); font-weight: 700; }
/* first-child gets its own ink rule at the same weight — keep it out of the way
   only when it is genuinely a gain cell (it never is, but be explicit). */
.pfd tbody td:first-child.pos { color: var(--pos, #117a37); }
.pfd tbody td:first-child.neg { color: var(--neg, #b4232a); }

/* The notepad title is now a real input, so it needs to LOOK like the note's title
   rather than a form field — bold, borderless, sitting at the top of the note. */
input.np-editor-t {
  width: 100%; border: 0; background: transparent; padding: 0 0 6px;
  font-size: 17px; font-weight: 800; color: var(--pf-ink, #1a1f29);
  font-family: inherit; letter-spacing: -0.01em;
  border-bottom: 1px solid transparent; transition: border-color .15s ease;
}
input.np-editor-t::placeholder { color: var(--pf-muted, #8a93a0); font-weight: 700; }
input.np-editor-t:focus { outline: none; border-bottom-color: var(--pf-brand, var(--jag-green)); }

/* ═══════════════════════════════════════════════════════════════════════════
   COLLAPSIBLE SECTION RAIL (desktop). Added 2026-08-19.
   Collapsing narrows the rail to icons rather than removing it, so the user never
   loses their place — the standard behaviour for a pinned rail. The choice is
   remembered per device. Mobile is untouched: the rail already collapses there.
   ═══════════════════════════════════════════════════════════════════════════ */
.pfd-rail { position: relative; }
.pfd-rail-toggle {
  position: absolute; top: 8px; right: 8px; z-index: 2;
  width: 26px; height: 26px; border-radius: 8px;
  border: 1px solid var(--pf-line, #e6ebf2); background: #fff;
  color: var(--pf-muted, #6b7480); cursor: pointer;
  font: 700 13px/1 inherit; display: grid; place-items: center;
}
.pfd-rail-toggle:hover { color: var(--pf-ink, #1a1f29); }

/* THE VERTICAL RAIL IS RETIRED ON DESKTOP. Owner: "go horizontal for desktop."
   It cost 220px of ~1456 permanently -- about 15% of the width -- to hold eight links
   used once a visit, while the holdings table underneath fought for room with nine
   columns. Horizontal space is the scarce dimension on a wide page; vertical is nearly
   free because you scroll anyway. The section bar now carries the same list, from the
   same source, for 44px of height.

   Mobile is untouched: the rail still stacks under the numbers there, exactly as it
   did before any of this. */
@media (min-width: 1081px) {
  .pfd { grid-template-columns: minmax(0, 1fr) !important; }
  .pfd-rail { display: none !important; }
  .pfd-rail-toggle { display: none !important; }
}

@media (min-width: 1081px) {
  html.rail-collapsed .pfd { grid-template-columns: 64px minmax(0, 1fr); }
  html.rail-collapsed .pfd-rail { padding-left: 8px; padding-right: 8px; }
  /* Labels go, icons stay — that is what keeps orientation. */
  html.rail-collapsed .pfd-rail a span,
  html.rail-collapsed .pfd-rail .pf-pro-badge,
  html.rail-collapsed .pfd-rail .pfd-rail-foot { display: none; }
  html.rail-collapsed .pfd-rail a { justify-content: center; padding-left: 0; padding-right: 0; }
  html.rail-collapsed .pfd-rail-toggle { right: 50%; transform: translateX(50%); }
}

/* ═══════════════════════════════════════════════════════════════════════════
   TRADING CALENDAR — METRIC STRIP. Added 2026-08-19, from the owner's design.
   Tiles sit above the month grid and summarise the month in facts about what he
   actually did. Deliberately no "average trade duration" (fills carry no hold
   time), no forex or options (neither exists here), and no advice cards.
   ═══════════════════════════════════════════════════════════════════════════ */
/* The owner's supplied palette and card treatment, applied rather than approximated:
   --panel #fff on a #f4f7f5 field, 1px #dbe5de borders, 18px radii and the soft
   0 8px 24px shadow, with each tile a subtle white-to-mint gradient. */
.cal-premium {
  --calp-bg: #f4f7f5; --calp-panel: #fff; --calp-border: #dbe5de;
  --calp-muted: #6d7c76; --calp-green: #2e8b57; --calp-red: #d96b6b;
  --calp-shadow: 0 8px 24px rgba(0,0,0,.06); --calp-radius: 18px;
  background: var(--calp-bg); border-radius: var(--calp-radius); padding: 16px;
}
.calm-strip {
  display: grid; gap: 12px; margin: 0 0 16px;
  grid-template-columns: repeat(auto-fit, minmax(158px, 1fr));
}
.calm-strip:empty { display: none; }
.calm-tile {
  background: linear-gradient(180deg, #ffffff 0%, #f9fcfa 100%);
  border: 1px solid var(--calp-border, #dbe5de);
  border-radius: 16px; padding: 14px 14px 12px; min-width: 0; min-height: 88px;
  box-shadow: var(--calp-shadow, 0 8px 24px rgba(0,0,0,.06));
}
.calm-label {
  color: var(--pf-muted, #6b7480); font-size: 11px; font-weight: 800;
  text-transform: uppercase; letter-spacing: .03em; margin-bottom: 7px;
}
.calm-value {
  font-size: 19px; font-weight: 800; line-height: 1.1;
  font-variant-numeric: tabular-nums; overflow-wrap: anywhere;
}
.calm-value.good { color: var(--pos, #117a37); }
.calm-value.bad  { color: var(--neg, #b4232a); }
.calm-sub { margin-top: 5px; font-size: 11.5px; color: var(--pf-muted, #6b7480); }

@media (max-width: 620px) {
  .calm-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
  .calm-tile { padding: 10px 11px 9px; }
  .calm-value { font-size: 16px; }
}

/* Asset breakdown under the calendar — the owner's donut widget, using the classes
   this product actually has. Inline SVG: the CSP blocks a Chart.js CDN tag. */
.calb-wrap:empty { display: none; }
/* His layout put the breakdown in its own bordered widget to the SIDE of the month,
   not stacked beneath it. On a wide screen it sits alongside; it drops below only
   when there is genuinely no room. */
.cal-split { display: grid; grid-template-columns: minmax(0, 1fr) 360px; gap: 16px; align-items: start; }
/* Owner 2026-08-19 order: account breakdown, then Intraday Activity, then Daily
   Insights. The month keeps the whole left column -- nothing overlaps the grid. */
.cal-rail { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.cal-rail > .calb-wrap:empty { display: none; }   /* kept: harmless once the inner wrapper exists */
.calb-wrap {
  background: var(--calp-panel, #fff); border: 1px solid var(--calp-border, #dbe5de);
  border-radius: var(--calp-radius, 18px); box-shadow: var(--calp-shadow, 0 8px 24px rgba(0,0,0,.06));
  padding: 16px;
}
.calb-wrap-h { margin: 0 0 4px; font-size: 16px; font-weight: 800; }
.calb-wrap-sub { margin: 0 0 12px; font-size: 12px; font-weight: 600; color: var(--calp-muted, #6d7c76); }
.calb { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.calb-donut { width: 120px; height: 120px; flex: 0 0 auto; }
.calb-list { display: flex; flex-direction: column; gap: 7px; flex: 1 1 220px; min-width: 0; }
.calb-row {
  display: grid; grid-template-columns: 10px 1fr auto auto; gap: 10px; align-items: center;
  padding: 8px 10px; background: var(--pf-soft, #f8fbf9);
  border: 1px solid var(--pf-line, #e6ebf2); border-radius: 12px; font-size: 13px;
}
.calb-dot { width: 10px; height: 10px; border-radius: 999px; }
.calb-name { font-weight: 700; }
.calb-pct { color: var(--pf-muted, #6b7480); font-weight: 700; font-variant-numeric: tabular-nums; }
.calb-val { font-weight: 800; font-variant-numeric: tabular-nums; }
.cal-symlist { display: flex; flex-direction: column; gap: 8px; }
.cal-symrow {
  display: grid; grid-template-columns: 64px minmax(0, 1fr) auto;
  gap: 10px; align-items: center; font-size: 13px;
}
.cal-symrow-n { font-weight: 800; letter-spacing: .02em; }
.cal-symrow-track { height: 8px; background: var(--pf-line-2, #f0f2f5); border-radius: 99px; overflow: hidden; }
.cal-symrow-bar { display: block; height: 100%; border-radius: 99px; }
.cal-symrow-bar--up { background: var(--pf-pos); }
.cal-symrow-bar--down { background: var(--pf-neg); }
.cal-symrow-v { font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }
.cal-symrow-v.up, .cal-week-v.up { color: var(--pf-pos); }
.cal-symrow-v.down, .cal-week-v.down { color: var(--pf-neg); }
.cal-wdow {
  display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 5px;
}
.cal-wdow-cell {
  min-width: 0; border-radius: 10px; padding: 7px 3px 6px; text-align: center;
  border: 1px solid var(--pf-line);
  display: flex; flex-direction: column; gap: 2px; min-height: 64px;
}
.cal-wdow-cell--up { background: rgba(20,128,74,.10); border-color: rgba(20,128,74,.28); }
.cal-wdow-cell--down { background: rgba(192,57,43,.08); border-color: rgba(192,57,43,.28); }
.cal-wdow-cell--none { background: var(--pf-line-2); }
.cal-wdow-d { font-size: 9px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: var(--pf-muted); }
.cal-wdow-v { font-size: 10px; font-weight: 800; font-variant-numeric: tabular-nums; line-height: 1.15; }
.cal-wdow-cell--up .cal-wdow-v { color: var(--pf-pos); }
.cal-wdow-cell--down .cal-wdow-v { color: var(--pf-neg); }
.cal-wdow-n { font-size: 8.5px; color: var(--pf-muted); line-height: 1.2; }
.cal-weeks, .cal-sess { display: flex; flex-direction: column; gap: 9px; }
.cal-week, .cal-sess-row {
  display: grid; grid-template-columns: 72px minmax(0, 1fr) auto;
  gap: 8px; align-items: center; font-size: 12.5px;
}
.cal-sess-row { grid-template-columns: 92px minmax(0, 1fr) auto; }
.cal-week-k { font-weight: 800; color: var(--pf-ink-2); }
.cal-sess-lab { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.cal-sess-lab b { font-size: 12.5px; font-weight: 800; }
.cal-sess-lab span { font-size: 10px; color: var(--pf-muted); font-weight: 600; }
.cal-week-track { height: 8px; background: var(--pf-line-2); border-radius: 99px; overflow: hidden; }
.cal-week-bar { display: block; height: 100%; border-radius: 99px; }
.cal-week-bar--up { background: var(--pf-pos); }
.cal-week-bar--down { background: var(--pf-neg); }
.cal-week-bar--none { background: transparent; }
.cal-week-v { font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }
.cal-tape { display: flex; flex-wrap: wrap; gap: 6px; }
.cal-tape-chip {
  display: inline-flex; flex-direction: column; align-items: flex-start; gap: 1px;
  border-radius: 10px; padding: 6px 8px; cursor: pointer;
  border: 1px solid var(--pf-line); background: var(--pf-panel); font: inherit; text-align: left;
}
.cal-tape-chip span { font-size: 10px; font-weight: 800; color: var(--pf-muted); }
.cal-tape-chip b { font-size: 12px; font-variant-numeric: tabular-nums; }
.cal-tape-chip--up { background: rgba(20,128,74,.08); border-color: rgba(20,128,74,.25); }
.cal-tape-chip--down { background: rgba(192,57,43,.07); border-color: rgba(192,57,43,.25); }
.cal-tape-chip--up b { color: var(--pf-pos); }
.cal-tape-chip--down b { color: var(--pf-neg); }
.cal-tape-chip:hover { border-color: var(--pf-muted-2); }
@media (max-width: 620px) {
  .cal-wdow { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
.calb-note { margin: 8px 0 0; font-size: 11.5px; color: var(--pf-muted, #6b7480); }
@media (max-width: 1100px) {
  .cal-split { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 620px) {
  .calb { gap: 12px; }
  .calb-donut { width: 96px; height: 96px; margin: 0 auto; }
  .cal-premium { padding: 10px; }
}

/* ── ASSET CARDS ROW (owner's 2026-08-19 spec) ──────────────────────────────
   His card: symbol top-left, P&L top-right, mini chart, then a footer reading
   "24 hr performance" with the percentage. His tokens: 16px radius, 1px border in
   the panel line colour, the soft green/red tints, and the same 12px gutter as the
   KPI strip directly above it so the two rows read as one block.
   Four across on desktop, two on tablet, one per row on a phone -- the same
   breakpoints his mockup used (1320 / 760), mapped onto this page's grid. */
.cala-row {
  /* THREE across (owner 2026-08-19: "remove the fourth container on the second row"). */
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px; margin: 12px 0 4px;
}
.cala-row:empty { display: none; }
.cala-card {
  border: 1px solid var(--pf-line, #dfe7e1);
  border-radius: 16px; padding: 12px 13px;
  display: grid; gap: 8px; min-width: 0;
  background: #fff; box-shadow: 0 2px 8px rgba(0, 0, 0, .03);
}
.cala-card--up   { background: #eaf6ee; }
.cala-card--down { background: #fdecec; }
.cala-card--flat { background: #f6f8f7; }
.cala-top { display: flex; justify-content: space-between; align-items: center; gap: 10px; }
.cala-sym {
  font-weight: 800; font-size: 14px; letter-spacing: .01em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}
.cala-pnl { font-size: 13px; font-weight: 800; white-space: nowrap; }
.cala-spark { display: block; width: 100%; height: 40px; }
.cala-foot {
  display: flex; justify-content: space-between; gap: 8px;
  color: var(--pf-muted, #6d7c76); font-size: 11px; font-weight: 700;
}
.cala-up   { color: var(--jag-green); }
.cala-down { color: #BB2D2D; }
.cala-flat { color: var(--pf-muted, #6d7c76); }

@media (max-width: 1320px) { .cala-row { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 760px)  { .cala-row { grid-template-columns: 1fr; } }

/* ── CALENDAR RIGHT RAIL + LOCKED STATE (owner's 2026-08-19 spec) ───────────
   His brief: "cleaner spacing, stronger card hierarchy, softer shadows, and better
   typography", and the free-plan calendar should look like the real thing greyed
   back rather than like a weaker placeholder. His tokens, applied to this page. */
.calb-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 10px; }
.calb-tag {
  flex: 0 0 auto; font-size: 11px; font-weight: 800; padding: 5px 9px;
  border-radius: 999px; background: #edf6f0; color: var(--jag-green); white-space: nowrap;
}
.calb-wrap-h { letter-spacing: -0.02em; }
.calb-foot { margin: 10px 0 0; font-size: 11.5px; font-weight: 600; color: var(--pf-muted, #6c7b75); }

/* Session tabs — real filters, not labels: each one re-plots the window below it. */
.cal-tabs { display: flex; gap: 7px; flex-wrap: wrap; margin: 12px 0; }
.cal-tab {
  font: inherit; font-size: 11.5px; font-weight: 800; padding: 7px 12px;
  border-radius: 999px; border: 1px solid var(--pf-line, #dfe7e1);
  background: #fff; color: var(--pf-muted, #6c7b75); cursor: pointer;
  transition: background .16s ease, color .16s ease, border-color .16s ease;
}
.cal-tab:hover { background: #f4f8f6; }
.cal-tab.on { background: #eef7f0; color: var(--jag-green); border-color: #d6eadc; }
.cal-intraday { display: block; width: 100%; height: 120px; }
.cal-axis {
  display: flex; justify-content: space-between; margin-top: 4px;
  font-size: 10.5px; font-weight: 700; color: var(--pf-muted, #6c7b75);
}

.cal-insights { display: flex; flex-direction: column; gap: 10px; }
.cal-insight {
  border-radius: 14px; border: 1px solid var(--pf-line, #dfe7e1);
  background: linear-gradient(180deg, #ffffff 0%, #f9fcfa 100%);
  padding: 12px; box-shadow: 0 4px 14px rgba(15, 23, 20, .04);
}
.cal-insight strong { display: block; margin-bottom: 4px; font-size: 13px; letter-spacing: -0.01em; }
.cal-insight p { margin: 0; color: var(--pf-muted, #6c7b75); font-size: 12px; line-height: 1.45; }

/* LOCKED CALENDAR. Two layers: the example month behind glass, and a crisp card on
   top. The blur is doing the persuasion -- it reads as "the real feature, not yours
   yet". aria-hidden on the stage keeps the invented figures out of screen readers. */
.calx { position: relative; }
.calx-stage {
  filter: blur(1.6px) saturate(.92);
  opacity: .95; pointer-events: none; user-select: none;
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 42%, transparent 88%);
  mask-image: linear-gradient(to bottom, #000 0%, #000 42%, transparent 88%);
}
.calx-cell {
  position: relative; min-height: 78px; border-radius: 13px;
  border: 1px solid var(--pf-line, #dfe7e1); background: #fff;
  padding: 8px; display: flex; flex-direction: column; gap: 6px;
}
.calx-cell--off { background: #fafcfa; opacity: .6; }
.calx-num { font-size: 11.5px; font-weight: 800; color: #42524c; }
.calx-amt {
  align-self: flex-start; font-size: 11.5px; font-weight: 800;
  padding: 4px 8px; border-radius: 10px; line-height: 1.2;
}
.calx-up   .calx-amt { background: #e8f6ec; color: #236644; }
.calx-down .calx-amt { background: #fdecec; color: #a94e4e; }

.calx-lock {
  position: absolute; inset: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 10px;
  text-align: center; padding: 22px; z-index: 2;
}
.calx-lock > * { max-width: 430px; }
.calx-lock::before {
  content: ''; position: absolute; inset: 0; z-index: -1;
  background: radial-gradient(ellipse at center, rgba(255,255,255,.62) 18%, rgba(255,255,255,.22) 70%, transparent 100%);
}
.calx-lock-pill {
  font-size: 10.5px; font-weight: 900; letter-spacing: .08em;
  padding: 4px 10px; border-radius: 999px; background: var(--jag-green); color: #fff;
}
.calx-lock h3 { margin: 0; font-size: 19px; font-weight: 800; letter-spacing: -0.02em; }
.calx-lock p { margin: 0; font-size: 13px; line-height: 1.5; color: #3d4b45; }
.calx-cap { font-size: 11px; font-weight: 600; color: var(--pf-muted, #6c7b75); }

@media (max-width: 1100px) {
  .cal-rail { flex-direction: column; }
  .calx-lock { padding: 16px; }
  .calx-lock h3 { font-size: 17px; }
}

/* ── ONE BLOCK: cards + month on the left, rail full height on the right ────
   Owner 2026-08-19: "What your account is made of moves all the way up right under
   Most traded ... the bottom of the Intraday container is at the bottom right height
   of the calendar." The asset row used to span the full width and push the rail down
   by its own height. It now sits inside the left column, so the rail starts level with
   the cards and the two columns end together. */
.cal-left { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.cal-left .cala-row { margin: 0; }
.cal-split { align-items: stretch; }
.cal-rail { height: 100%; position: relative; min-height: 0; }
/* The inner wrapper is taken OUT of flow so the rail's content can never lengthen the
   grid row. The row is sized by the calendar on the left; this box matches it exactly
   and scrolls. That is what lets side features be added without the month sliding down
   the page, which is the thing the owner objected to on 2026-08-19. */
.cal-rail-inner {
  position: absolute; inset: 0; overflow-y: auto; overscroll-behavior: contain;
  display: flex; flex-direction: column; gap: 14px; padding-right: 2px;
}
.cal-rail-inner > .calb-wrap:empty { display: none; }

/* Patterns rows. A label, the figure, and the evidence under it - the figure is the
   thing being read, so it leads on size and the evidence stays quiet. */
.calp-rows { display: flex; flex-direction: column; gap: 10px; }
.calp-row { display: flex; flex-direction: column; gap: 1px; }
.calp-k {
  font-size: 10.5px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase;
  color: var(--pf-muted, #5b6a63);
}
.calp-v { font-size: 16px; font-weight: 800; letter-spacing: -.01em; color: var(--pf-ink, #10211a); }
.calp-v.up { color: var(--pf-green, #0a7a4d); }
.calp-s { font-size: 11.5px; color: var(--pf-muted, #5b6a63); }
html[data-chart-theme="dark"] .calp-k,
html[data-chart-theme="dark"] .calp-s { color: var(--jag-ink-muted); }
html[data-chart-theme="dark"] .calp-v { color: var(--jag-ink); }
html[data-chart-theme="dark"] .calp-v.up { color: var(--jag-up); }
/* Stacked layout: there is no fixed-height column to match, so the wrapper returns to
   normal flow and the cards simply follow the calendar. */
@media (max-width: 1100px) {
  .cal-rail { height: auto; position: static; }
  .cal-rail-inner { position: static; overflow: visible; }
}
/* Intraday takes the slack so its bottom edge lands with the calendar's. */
/* #calIntraday no longer stretches to eat the leftover space - with more than two
   cards in the rail that pushed the rest out of view. Cards now take their natural
   height and the wrapper scrolls. */
.cal-rail-inner > #calIntraday { display: flex; flex-direction: column; }
.cal-rail > #calIntraday .cal-intraday { flex: 1 1 auto; height: auto; min-height: 120px; }

@media (max-width: 1100px) {
  .cal-rail { height: auto; }
  .cal-rail > #calIntraday { flex: 0 0 auto; }
  .cal-rail > #calIntraday .cal-intraday { height: 120px; }
}

/* ── The free-plan calendar teaser was landing off the page ────────────────
   .calx-lock is position:absolute with left:50%, and it is a descendant of
   .cal-premium — which had no `position`, so it was not the containing block.
   The lock therefore resolved 50% against a distant positioned ancestor and
   rendered half off the left edge of the viewport, over the trade-history
   table, with its own text clipped. An absolutely-positioned overlay is only
   as correct as the box it is measured against. */
.cal-premium { position: relative; }

/* An "empty" card that contains a newline is not :empty, so this rendered as a
   blank white box beside the calendar whenever the rail had nothing to show. */
.calb-wrap:not(:has(*)) { display: none; }

/* ══════════════════════════════════════════════════════════════════════════
   DARK MODE — the portfolio-specific surfaces
   The shared chrome (header, tabs, cards, table headers) is handled in
   css/tokens.css so all 17 pages get it. What remains here is what only this
   page draws: the chips, the holdings cells, the activity strip and the
   trading calendar. Every selector below came from walking the live DOM in
   dark mode and collecting the elements whose COMPUTED background was still
   light — measured, not guessed.
   ══════════════════════════════════════════════════════════════════════════ */
html[data-chart-theme="dark"] .pfd-chip,
html[data-chart-theme="dark"] .pf-act-day,
html[data-chart-theme="dark"] .pfd-card button:not(.pfd-cta):not(.h-sell):not(.pf-fork-btn--go):not(.pf-fork-lvl) {
  background: var(--jag-card-2) !important;
  border-color: transparent !important;
  color: var(--jag-ink-muted) !important;
}
html[data-chart-theme="dark"] .pf-fork-lvl {
  background: #1a322c !important;
  border: 1.5px solid #3d8f72 !important;
  color: #d8f3e8 !important;
  box-shadow: none !important;
}
html[data-chart-theme="dark"] .pf-fork-btn--go,
html[data-chart-theme="dark"] .pf-fork-lvl.is-on {
  background: var(--jag-green, var(--pf-green)) !important;
  border-color: var(--jag-green, var(--pf-green)) !important;
  color: #fff !important;
  box-shadow: 0 0 0 3px rgba(52, 220, 126, .22) !important;
}
html[data-chart-theme="dark"] .pfd-chip.on,
html[data-chart-theme="dark"] .pfd-chip[aria-pressed="true"] {
  background: var(--jag-green-soft) !important;
  color: var(--jag-green) !important;
  border-color: var(--jag-green-line) !important;
}
/* Sell is a destructive action: outlined, never filled, so it cannot be hit by
   accident — and it stays legible on the dark ground. */
html[data-chart-theme="dark"] .h-sell {
  background: transparent !important;
  border: 1px solid var(--jag-down) !important;
  color: var(--jag-down) !important;
}
html[data-chart-theme="dark"] .h-sell:hover { background: var(--jag-down-soft) !important; }

/* Holdings cells. td.num carries the money, so it goes to primary ink, not
   muted — the numbers are the reason the table exists. */
html[data-chart-theme="dark"] td.lft,
html[data-chart-theme="dark"] td.num,
html[data-chart-theme="dark"] td.num.cell-strong {
  background: transparent !important;
  color: var(--jag-ink) !important;
}
html[data-chart-theme="dark"] td.num.muted { color: var(--jag-ink-muted) !important; }

/* ── TRADING CALENDAR ──────────────────────────────────────────────────────
   .cal-premium sets its own --calp-* palette, which is why nothing above
   reaches it. Restating those five variables re-themes the whole calendar in
   one place rather than chasing each cell. */
html[data-chart-theme="dark"] .cal-premium {
  --calp-bg: var(--jag-page);
  --calp-panel: var(--jag-card);
  --calp-border: var(--jag-line);
  --calp-muted: var(--jag-ink-muted);
  --calp-green: var(--jag-up);
  --calp-red: var(--jag-down);
  --calp-shadow: 0 8px 24px rgba(0, 0, 0, .45);
}
html[data-chart-theme="dark"] .cal-cell,
html[data-chart-theme="dark"] .calx-cell,
html[data-chart-theme="dark"] .cala-card {
  background: var(--jag-card) !important;
  border-color: var(--jag-line) !important;
  color: var(--jag-ink);
}
/* A day you finished ahead or behind stays readable as a TINT, not a shout —
   the same rule the chart desk uses for P&L. */
html[data-chart-theme="dark"] .cala-card--up,
html[data-chart-theme="dark"] .calx-up   { background: var(--jag-up-soft) !important;   border-color: var(--jag-up) !important; }
html[data-chart-theme="dark"] .cala-card--down,
html[data-chart-theme="dark"] .calx-down { background: var(--jag-down-soft) !important; border-color: var(--jag-down) !important; }
html[data-chart-theme="dark"] .calx-up .calx-amt   { color: var(--jag-up) !important; }
html[data-chart-theme="dark"] .calx-down .calx-amt { color: var(--jag-down) !important; }
html[data-chart-theme="dark"] .cala-card--flat,
html[data-chart-theme="dark"] .calx-cell--off { background: var(--jag-card-2) !important; }

/* ── TRADING CALENDAR: A GREEN DAY AND A RED DAY LOOKED IDENTICAL IN DARK ──
   Owner 2026-08-22: "make sure that the gains and losses on the trading calendar
   are red and green for profit and loss."

   The dark rule above sets `.cal-cell { background: var(--jag-card) !important }`.
   The tints live on `.cal-cell--up` / `--down`, which are LIGHT-mode rules with
   lower weight than that !important - so in dark every single day painted the same
   neutral card and the whole point of the calendar (see your month at a glance)
   was gone. Its siblings .calx-* and .cala-* already had dark tints; .cal-cell,
   the one actually on screen, was the one that got missed.

   Measured on the tinted grounds, dark:
     up amount   #43D17A on #123C2B = 6.23:1
     down amount #FF6678 on #401C25 = 5.26:1
     day number  #A7B0BE on both    = 5.62 / 6.80:1
   The tint carries the meaning; the border makes it survive a colour-blind read. */
html[data-chart-theme="dark"] .cal-cell--up {
  background: var(--jag-up-soft) !important;
  border-color: var(--jag-up) !important;
}
html[data-chart-theme="dark"] .cal-cell--down {
  background: var(--jag-down-soft) !important;
  border-color: var(--jag-down) !important;
}
html[data-chart-theme="dark"] .cal-cell--up .cal-amt   { color: var(--jag-up) !important; }
html[data-chart-theme="dark"] .cal-cell--down .cal-amt { color: var(--jag-down) !important; }
html[data-chart-theme="dark"] .cal-cell--pad { background: transparent !important; border-color: transparent !important; }

/* The day-detail list and the legend read from the same pair, so they move together
   rather than becoming a third opinion about what "up" looks like. */
html[data-chart-theme="dark"] .cal-d-pnl.up   { color: var(--jag-up); }
html[data-chart-theme="dark"] .cal-d-pnl.down { color: var(--jag-down); }
html[data-chart-theme="dark"] .cal-key--up   { background: var(--jag-up-soft);   border-color: var(--jag-up); }
html[data-chart-theme="dark"] .cal-key--down { background: var(--jag-down-soft); border-color: var(--jag-down); }
html[data-chart-theme="dark"] .cal-key--none { background: var(--jag-card-2);    border-color: var(--jag-line); }

/* THE FONT. Owner: "fixed the fucking font." The amount was 12px/800 and the day
   number 11.5px in a 60px cell - the two competed and neither won. The AMOUNT is
   what the calendar is for, so it leads; the day number steps back to a label. */
.cal-amt { font-size: 13.5px; font-weight: 800; letter-spacing: -.01em; }
.cal-num { font-size: 11px; font-weight: 700; opacity: .8; }
.cal-n   { font-size: 10.5px; }
html[data-chart-theme="dark"] .calb-wrap,
html[data-chart-theme="dark"] .calx-lock { background: var(--jag-card) !important; border-color: var(--jag-line) !important; color: var(--jag-ink); }

/* The last five, measured off the live page: the breakdown rows and their tag,
   the watchlist input, and the notebook's list + editor. Inputs and the editor
   are text-entry surfaces, so they take primary ink rather than muted — you
   have to be able to read what you typed. */
html[data-chart-theme="dark"] .calb-row,
html[data-chart-theme="dark"] .np-list {
  background: var(--jag-card-2) !important;
  border-color: var(--jag-line) !important;
  color: var(--jag-ink);
}
html[data-chart-theme="dark"] .calb-tag {
  background: var(--jag-line-soft) !important;
  border-color: transparent !important;
  color: var(--jag-ink-muted) !important;
}
html[data-chart-theme="dark"] #watchlistInput,
html[data-chart-theme="dark"] .nb-ta,
html[data-chart-theme="dark"] .np-editor,
html[data-chart-theme="dark"] .pfd-card input[type="text"],
html[data-chart-theme="dark"] .pfd-card textarea {
  background: var(--jag-card-2) !important;
  border-color: var(--jag-line) !important;
  color: var(--jag-ink) !important;
}
html[data-chart-theme="dark"] .pfd-card input::placeholder,
html[data-chart-theme="dark"] .pfd-card textarea::placeholder { color: var(--jag-ink-faint) !important; }

/* ── THE CALENDAR PRO TEASER KEPT LANDING OFF-SCREEN ───────────────────────
   Owner, twice: the card hangs off the left edge with its text clipped, and
   the calendar behind it is only partly frosted.

   .calx-lock was centred with left:50% + translate(-50%,-50%). That only works
   if .calx is genuinely its containing block, and it is not reliably — an
   ancestor with a `filter` (and .calx-grid has one) establishes a containing
   block for absolutely-positioned descendants, so the 50% resolved against the
   wrong box and the card walked off the page. I "fixed" this once by adding
   position:relative to .cal-premium, which was the wrong ancestor.

   inset:0 + margin:auto centres without depending on WHICH ancestor won, and
   without a transform. It cannot resolve against the wrong box because it is
   not a percentage of one. */
.calx { position: relative; }
.calx-lock {
  position: absolute;
  inset: 0;                       /* fill the card... */
  margin: auto;                   /* ...then centre inside it, no transform */
  transform: none !important;
  left: 0 !important; top: 0 !important;
  width: min(460px, calc(100% - 32px));
  height: fit-content;
  max-height: calc(100% - 24px);
  overflow: auto;
  text-align: center;
  z-index: 6;
}
.calx-lock h3, .calx-lock p { text-align: center; }
.calx-lock p { margin-left: auto; margin-right: auto; }

/* THE WHOLE CARD FROSTS, NOT JUST THE GRID. Only .calx-grid and .calx-stats
   were blurred, so the month nav, the day-of-week header and the caption stayed
   sharp — it read as a half-finished page rather than a locked feature. Every
   child of .calx frosts except the lock itself. */
.calx > *:not(.calx-lock):not(.calx-preview) {
  filter: blur(1.4px) saturate(.94);
  pointer-events: none;
  user-select: none;
}
.calx-lock { filter: none !important; pointer-events: auto !important; }

/* ── THE PREVIEW STRIP: CRISP LABELS, FROSTED FIGURES ──────────────────────
   Owner 2026-08-22: "users should be able to see what they're missing."
   A filter applies to its whole subtree, so a tile inside the frosted stage can
   never be partly sharp - which is why the six tiles rendered as grey smears and
   taught a free member nothing. The strip now sits outside the stage and frosts
   only the NUMBERS. They read exactly which six things Pro computes from their
   own trades; they cannot read the answers. */
.calx-preview { margin: 0 0 14px; }
.calx-pv-h {
  margin: 0 0 8px; font-size: 11.5px; font-weight: 800; letter-spacing: .06em;
  text-transform: uppercase; color: var(--pf-muted, #5b6a63);
}
.calx-preview .calx-tk { filter: none; }
.calx-preview .calx-tile b,
.calx-preview .calx-tile small {
  filter: blur(4.5px);
  user-select: none;
}
html[data-chart-theme="dark"] .calx-pv-h { color: var(--jag-ink-muted); }
html[data-chart-theme="dark"] .calx-preview .calx-tile {
  background: var(--jag-card-2); border-color: var(--jag-line);
}
html[data-chart-theme="dark"] .calx-preview .calx-tk { color: var(--jag-ink-2); }

/* ── AN EMPTY RAIL CARD IS WORSE THAN NO CARD ──────────────────────────────
   Owner: "why does that look like nothing's there, and it's just a little
   calendar?"

   #calBreakdown and #calIntraday are Pro rails. On a free account they never
   populate, so they rendered as a large empty bordered rectangle beside the
   frosted calendar — which reads as a broken page, not a locked feature. My
   earlier :not(:has(*)) rule only caught cards whose markup was literally
   empty; these have a wrapper inside, so they slipped through.

   Hidden when they have no real content. This is the honest MINIMUM — the
   better version is what the calendar itself does: render EXAMPLE allocations
   frosted, with the same teaser over them, so a free user can see what they
   would get. That needs example data built, and it is in the backlog rather
   than half-done here. */
.calb-wrap:not(:has(.calb)):not(:has(canvas)):not(:has(table)):not(:has(.calb-row)):not(:has(.cal-symlist)):not(:has(.cal-wdow)):not(:has(.cal-weeks)):not(:has(.cal-tape)):not(:has(.cal-sess)):not(:has(.cal-intraday)):not(:has(.calp-rows)) {
  display: none !important;
}
/* With the rail gone the calendar takes the full width rather than leaving the
   gap the rail used to occupy. */
.cal-split:not(:has(.calb-wrap:not([hidden]))) { grid-template-columns: minmax(0, 1fr); }

/* ── THE CALENDAR TEASER CARD IN DARK MODE ────────────────────────────────
   "Your trading, day by day" was invisible: the h3 inherits --jag-ink, which
   is near-WHITE in dark mode, while .calx-lock kept its light --pf-card
   background. White on white. The body copy survived only because it sets its
   own muted colour explicitly.

   Same half-applied signature as the leaderboard: flipping the ink without
   flipping the surface guarantees one of the two ends up invisible. The card
   is a dark surface now, so every child that inherits the ink lands right. */
html[data-chart-theme="dark"] .calx-lock {
  background: #151D29 !important;
  border: 1px solid #263142 !important;
  box-shadow: 0 18px 48px rgba(0, 0, 0, .55) !important;
}
html[data-chart-theme="dark"] .calx-lock h3 { color: #F1F4F7 !important; }
html[data-chart-theme="dark"] .calx-lock p { color: #A7B0BE !important; }
html[data-chart-theme="dark"] .calx-lock .calx-cap { color: #737F90 !important; }
html[data-chart-theme="dark"] .calx-lock-pill { background: #27C96F !important; color: #06140D !important; }
html[data-chart-theme="dark"] .calx-lock .pfd-btn--pro { background: #27C96F !important; color: #06140D !important; border-color: transparent !important; }

/* ── EMPTY BOOK: INVITE, DO NOT BLUR ──────────────────────────────────────
   2026-08-21. The locked calendar used to render an invented "example month",
   blur it, and sell the unblur. If the viewer has never closed a trade there is
   nothing of theirs behind the glass, and a lock over nothing reads as "you
   can't have this" instead of "this is yours". So when there are no closed
   trades we show this instead -- no .calx-stage, therefore no blur (the blur
   lives on .calx-stage, not on .calx), and one action that actually fills it. */
.calx--empty {
  text-align: center;
  padding: 28px 20px 32px;
  border-radius: 12px;
  background: transparent;
  border: 0;
}
.calx--empty h3 {
  margin: 0 0 8px;
  font-size: 16px;
  font-weight: 800;
  color: var(--cdp-ink, var(--jag-ink, #10241c));
}
.calx--empty p {
  margin: 0 auto 16px;
  max-width: 42ch;
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--pf-muted, #5b6a7a);
}
.calx--empty .pfd-btn { display: inline-flex; }

/* Empty book: no mint panel, no 340px empty rail, no day-color legend under a blank. */
#tradeCalendarCard.cal-free-tease .cal-split {
  grid-template-columns: minmax(0, 1fr) 360px;
}
#tradeCalendarCard.cal-is-empty .cal-rail,
#tradeCalendarCard.cal-is-empty .cal-legend { display: none; }

#tradeCalendarCard.cal-free-tease .cal-rail {
  position: relative;
  min-height: 280px;
}
#tradeCalendarCard.cal-free-tease .cal-rail-inner {
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 22%, rgba(0,0,0,.35) 48%, transparent 82%);
  mask-image: linear-gradient(to bottom, #000 0%, #000 22%, rgba(0,0,0,.35) 48%, transparent 82%);
  pointer-events: none;
  user-select: none;
}
#tradeCalendarCard.cal-free-tease .cal-rail::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 58%;
  z-index: 2;
  pointer-events: none;
  backdrop-filter: blur(7px);
  background: linear-gradient(to bottom, transparent, rgba(255,255,255,.55));
}
html[data-chart-theme="dark"] #tradeCalendarCard.cal-free-tease .cal-rail::after {
  background: linear-gradient(to bottom, transparent, rgba(12, 18, 28, .72));
}
#tradeCalendarCard.cal-free-tease .cal-rail-cta {
  position: absolute;
  left: 10px; right: 10px; bottom: 12px;
  z-index: 3;
  text-align: center;
  padding: 12px 10px;
  border-radius: 12px;
  background: rgba(255,255,255,.92);
  border: 1px solid var(--jag-line, #dbe5de);
  box-shadow: 0 10px 28px rgba(16, 32, 24, .12);
}
#tradeCalendarCard.cal-free-tease .cal-rail-cta p {
  margin: 0 0 8px;
  font-size: 12px;
  line-height: 1.4;
  color: var(--pf-muted, #5b6a7a);
}
html[data-chart-theme="dark"] #tradeCalendarCard.cal-free-tease .cal-rail-cta {
  background: rgba(21, 29, 41, .94);
  border-color: #2A3442;
}
#tradeCalendarCard.cal-is-empty .cal-premium {
  background: transparent;
  padding: 0;
  box-shadow: none;
}
#tradeCalendarCard.cal-is-empty .cal-grid { display: block; }

/* The .calx family carries explicit dark overrides rather than relying on tokens
   alone (13 of them above). Matching that pattern here: a dashed card on a light
   surface would otherwise keep a near-white background in dark mode, which is the
   exact "ink flipped, surface didn't" failure that broke the leaderboard. */
html[data-chart-theme="dark"] .calx--empty {
  background: transparent !important;
  border-color: transparent !important;
}
html[data-chart-theme="dark"] .calx--empty h3 { color: #E6EDF3 !important; }
html[data-chart-theme="dark"] .calx--empty p  { color: #97A3B4 !important; }


/* THE TEASER SHOWS THE WHOLE PRODUCT NOW. (2026-08-21)
   Six real stat tiles above the month grid, built from the viewer's own closed
   trades and blurred with the rest. Owner: "it looks just like a regular
   calendar -- it needs to look grayed out where you can see all the features."
   You cannot want what you cannot see the shape of. */
.calx-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 10px;
  margin: 0 0 16px;
}
.calx-tile {
  background: var(--cdp-surface, #fff);
  border: 1px solid var(--jag-line, #dbe5de);
  border-radius: 12px;
  padding: 12px 14px;
  min-width: 0;
}
.calx-tk {
  display: block; font-size: 10px; font-weight: 800; letter-spacing: .1em;
  text-transform: uppercase; color: var(--pf-muted, #5b6a7a);
}
.calx-tile b {
  display: block; margin-top: 6px; font-size: 20px; font-weight: 900;
  font-variant-numeric: tabular-nums; color: var(--cdp-ink, #10241c);
}
.calx-tile b.up { color: var(--jag-up, #067a4e); }
.calx-tile b.dn { color: var(--jag-down, #c0392b); }
.calx-tile small { display: block; margin-top: 3px; font-size: 11px; color: var(--pf-muted, #5b6a7a); }
html[data-chart-theme="dark"] .calx-tile,
html[data-intel-theme="dark"] .calx-tile {
  background: #151D29 !important;
  border-color: #2A3442 !important;
}
html[data-chart-theme="dark"] .calx-tile b,
html[data-intel-theme="dark"] .calx-tile b { color: #E6EDF3 !important; }
html[data-chart-theme="dark"] .calx-tk,
html[data-intel-theme="dark"] .calx-tk,
html[data-chart-theme="dark"] .calx-tile small,
html[data-intel-theme="dark"] .calx-tile small { color: #97A3B4 !important; }
@media (max-width: 720px) { .calx-tiles { grid-template-columns: 1fr 1fr; } }


/* ══ MEASURED DARK FAILURES ON PORTFOLIO. (2026-08-21) ════════════════════
   #14 Recent Activity + Trade history at 1.00:1 -- exactly equal luminance.
   .activity-item__text strong and .activity-item__amt resolve var(--pf-ink)
   #1a1d21 on --jag-card #151D29. Every event title ("Bought AAPL") and every
   dollar amount. Buys and the account-opening row carry no .pos class, so most
   rows are affected. .donut-c1 is the portfolio total in the Allocation donut.
   #17 The trading-calendar PRO metric strip uses a literal gradient, so the
   --calp-* remap cannot reach it. NOTE: .good/.bad use --pos/--neg which are
   never remapped -- flipping the tile dark REQUIRES flipping those too, or you
   trade one defect for another. */
html[data-chart-theme="dark"] .activity-item__text strong,
html[data-intel-theme="dark"] .activity-item__text strong,
html[data-chart-theme="dark"] .activity-item__amt,
html[data-intel-theme="dark"] .activity-item__amt,
html[data-chart-theme="dark"] .donut-c1,
html[data-intel-theme="dark"] .donut-c1 { color: #E6EDF3 !important; }

html[data-chart-theme="dark"] .calm-tile,
html[data-intel-theme="dark"] .calm-tile {
  background: #151D29 !important;
  border-color: #2A3442 !important;
}
html[data-chart-theme="dark"] .calm-value,
html[data-intel-theme="dark"] .calm-value { color: #E6EDF3 !important; }
/* the pair that must move WITH the tile, or green/red become unreadable on it */
html[data-chart-theme="dark"] .calm-value.good,
html[data-intel-theme="dark"] .calm-value.good,
html[data-chart-theme="dark"] .calm-tile .good,
html[data-intel-theme="dark"] .calm-tile .good { color: #4FCB95 !important; }
html[data-chart-theme="dark"] .calm-value.bad,
html[data-intel-theme="dark"] .calm-value.bad,
html[data-chart-theme="dark"] .calm-tile .bad,
html[data-intel-theme="dark"] .calm-tile .bad { color: #F0796B !important; }
html[data-chart-theme="dark"] .calm-label,
html[data-intel-theme="dark"] .calm-label { color: #97A3B4 !important; }

/* ══ DESK LOCK (2026-08-24) ════════════════════════════════════════════════
   Calendar used 16–18px radii, mint fills, and a drop shadow on every tile —
   a different kit from Holdings / Performance (12px, hairline, white). That
   mismatch is what read as “basic” / mockup. One chrome now. */
.pfd-card {
  box-shadow: 0 1px 2px rgba(16, 24, 40, .04);
}
#tradeCalendarCard .calm-strip {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 0;
  margin: 0 0 18px;
  background: #fff;
  border: 1px solid var(--pf-line);
  border-radius: 12px;
  overflow: hidden;
  box-shadow: none;
}
#tradeCalendarCard .calm-tile {
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  border-right: 1px solid var(--pf-line);
  min-height: 0;
  min-width: 0;
  padding: 16px 14px 14px;
}
#tradeCalendarCard .calm-tile:last-child { border-right: 0; }
#tradeCalendarCard .calm-label {
  font-size: 10px;
  letter-spacing: .07em;
  margin-bottom: 8px;
}
#tradeCalendarCard .calm-value {
  font-size: 18px;
  letter-spacing: -.02em;
  overflow-wrap: normal;
  white-space: nowrap;
}
#tradeCalendarCard .calm-sub { margin-top: 6px; font-size: 12px; font-weight: 500; }
#tradeCalendarCard .cal-premium {
  background: #fff;
  border: 1px solid var(--pf-line);
  border-radius: 12px;
  padding: 12px 12px 14px;
  box-shadow: none;
}
#tradeCalendarCard .cal-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin: 0 0 10px;
}
#tradeCalendarCard .cal-month {
  font-size: 18px;
  font-weight: 800;
  letter-spacing: -.03em;
  flex: 1 1 auto;
  text-align: center;
}
#tradeCalendarCard .cal-arrow {
  width: 36px;
  height: 36px;
  border-radius: 10px;
  border: 1px solid var(--pf-line);
  background: #fff;
}
#tradeCalendarCard .cal-hd {
  padding: 0 0 10px;
  border-bottom: 1px solid var(--pf-line-2);
  margin-bottom: 2px;
}
#tradeCalendarCard .cal-cell {
  min-height: 84px;
  border-radius: 10px;
  box-shadow: none;
  background: #fafbfc;
}
#tradeCalendarCard .cal-cell--pad { background: transparent; }
#tradeCalendarCard .cal-amt {
  display: inline-block;
  padding: 3px 7px;
  border-radius: 7px;
  font-size: 12.5px;
  letter-spacing: -.02em;
}
#tradeCalendarCard .cal-cell--up { background: #f3faf6; border-color: #d7eadf; }
#tradeCalendarCard .cal-cell--up .cal-amt { background: #e4f4ea; color: var(--pf-pos); }
#tradeCalendarCard .cal-cell--down { background: #fdf6f5; border-color: #f0d8d4; }
#tradeCalendarCard .cal-cell--down .cal-amt { background: #f8e6e3; color: var(--pf-neg); }
#tradeCalendarCard .cala-card {
  background: #fff !important;
  border: 1px solid var(--pf-line) !important;
  border-radius: 12px;
  box-shadow: none;
  border-left-width: 3px !important;
  border-left-style: solid !important;
}
#tradeCalendarCard .cala-card--up { border-left-color: var(--pf-pos) !important; }
#tradeCalendarCard .cala-card--down { border-left-color: var(--pf-neg) !important; }
#tradeCalendarCard .cala-card--flat { border-left-color: #c5cdd4 !important; }
#tradeCalendarCard .cala-sym { font-size: 13px; letter-spacing: .04em; }
#tradeCalendarCard .cala-pnl { font-size: 15px; }
#tradeCalendarCard .calb-wrap {
  border-radius: 12px;
  box-shadow: none;
  border-color: var(--pf-line);
  padding: 14px 16px 16px;
}
#tradeCalendarCard .calb-wrap-h {
  font-size: 13px;
  font-weight: 800;
  letter-spacing: -.01em;
}
#tradeCalendarCard .calb-wrap-sub { font-size: 12px; font-weight: 500; }
#tradeCalendarCard .cal-week-track,
#tradeCalendarCard .cal-symrow-track { height: 6px; background: var(--pf-line-2); }
@media (max-width: 1180px) {
  #tradeCalendarCard .calm-strip { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  #tradeCalendarCard .calm-tile { border-bottom: 1px solid var(--pf-line); }
  #tradeCalendarCard .calm-tile:nth-child(3n) { border-right: 0; }
  #tradeCalendarCard .calm-tile:nth-last-child(-n+3) { border-bottom: 0; }
}
@media (max-width: 620px) {
  #tradeCalendarCard .calm-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  #tradeCalendarCard .calm-tile:nth-child(3n) { border-right: 1px solid var(--pf-line); }
  #tradeCalendarCard .calm-tile:nth-child(2n) { border-right: 0; }
  #tradeCalendarCard .calm-tile:nth-last-child(-n+2) { border-bottom: 0; }
  #tradeCalendarCard .calm-value { white-space: normal; font-size: 16px; }
  #tradeCalendarCard .cal-cell { min-height: 58px; }
  #tradeCalendarCard .cal-amt { padding: 2px 4px; font-size: 9.5px; }
}
