/* ============================================================================
   The printable report.

   Loaded on top of tokens.css and using its variables, so a band that is amber
   in the app is amber on the page. What it overrides is the CONTEXT: the app is
   a dark surface holding tiles, and this is a sheet of paper holding a document.

   Two rules run through everything below:

     * On screen it should already look like the printout. A page that rearranges
       itself in the print dialog is a page you have to print twice.
     * Nothing that cannot be pressed on paper survives into it — the toolbar is
       gone, and every heading and table is protected from breaking across a page
       boundary, because a table whose header is on the previous sheet is a table
       nobody can read.
   ============================================================================ */

/* ---------------------------------------------------------------------------
   THE DOCUMENT'S OWN PALETTE — `--doc-*`.

   This file used to pin every colour in the document to ink-on-white, in both
   themes, on the reasoning that the report is a preview of a physical sheet and
   a dark preview of a white printout tells you nothing. That reasoning was about
   the printable URL, and it quietly took the *portfolio page* with it: `/p/<id>`
   renders the same body, so a person who had asked the whole app for dark mode
   got a glaring white sheet in the middle of it. Sam, 2026-09-09.

   So the document now has its own small palette, one layer below the app's. Every
   rule below names a `--doc-*` token rather than a hex, and the tokens are defined
   three times:

     * **dark first**, matching `tokens.css` — dark is this app's default, and the
       two files must agree or the toggle sends them opposite ways;
     * **paper**, when the viewer's OS says light or the nav toggle stamps
       `data-theme="light"` — the same ink-on-white the report has always had, to
       the hex;
     * **paper again, unconditionally, inside `@media print`** (at the foot of this
       file). That is what keeps the original rule true where it actually mattered:
       whatever the screen is doing, what comes out of the printer is black ink on
       white paper. The print preview follows the screen; the print does not.

   The document is NOT the app surface. In dark mode the sheet is one step lighter
   than the page behind it, exactly as a sheet on a desk is — so it still reads as
   a document lying on something, rather than as one more panel.
   --------------------------------------------------------------------------- */
:root {
    /* surfaces: the desk, the sheet on it, and two tints used inside it */
    --doc-desk:          #0f1115;
    --doc-sheet:         #171a21;
    --doc-tint:          #1e222b;
    --doc-tint-2:        #1b1f27;
    --doc-tint-3:        #1e222b;

    /* ink, darkest to faintest */
    --doc-ink:           #e6e9ef;
    --doc-ink-2:         #cdd3dd;
    --doc-ink-3:         #9aa3b2;
    --doc-ink-4:         #8a93a2;
    --doc-ink-5:         #7b8494;

    /* rules and hairlines */
    --doc-rule:          #2a2f3a;
    --doc-rule-soft:     #242832;
    --doc-rule-hair:     #21252e;
    --doc-rule-strong:   #3a4150;

    /* cash is a grey slice in every chart — it is an absence of holding, never a
       colour with an opinion */
    --doc-cash:          #4a5262;

    /* semantic — same meanings as the app's, tuned to sit on the sheet */
    --doc-gain:          #3fb950;
    --doc-loss:          #f85149;
    --doc-loss-ink:      #ff9a94;
    --doc-loss-dim:      #c97b78;
    --doc-loss-bg:       #2b1a1c;
    --doc-warn:          #d29922;
    --doc-warn-ink:      #e5bc5c;
    --doc-warn-line:     #d29922;
    --doc-warn-bright:   #e6c000;
    --doc-warn-bg:       #2a2317;
    --doc-orange:        #f0883e;
    --doc-accent:        #58a6ff;
    --doc-accent-strong: #1f6feb;
    --doc-accent-bg:     #16243a;
    --doc-accent-ink:    #a9cbff;
    --doc-series-2:      #d2a8ff;

    /* text on top of an accent fill — a filled button, a chosen tab. It is NOT the
       sheet colour: on a bright accent the legible ink is dark, in either theme. */
    --doc-on-accent:     #0b1220;
}

/* Paper. Every value here is the hex the document carried before it had tokens, so
   in light mode nothing about the report has moved by a single shade. */
@media (prefers-color-scheme: light) {
    :root:not([data-theme="dark"]) {
        --doc-desk: #f2f3f5; --doc-sheet: #ffffff;
        --doc-tint: #f4f6f9; --doc-tint-2: #f7f9fc; --doc-tint-3: #f0f2f5;
        --doc-ink: #1c2027; --doc-ink-2: #45505f; --doc-ink-3: #5b6472;
        --doc-ink-4: #6b7484; --doc-ink-5: #8a93a2;
        --doc-rule: #d8dce3; --doc-rule-soft: #e3e6eb; --doc-rule-hair: #eef0f4;
        --doc-rule-strong: #b9c0cc; --doc-cash: #c9cfd8;
        --doc-gain: #1a7f37; --doc-loss: #cf222e; --doc-loss-ink: #8a1620;
        --doc-loss-dim: #a8555c; --doc-loss-bg: #fdf6f6;
        --doc-warn: #9a6700; --doc-warn-ink: #7d5e00; --doc-warn-line: #d4a72c;
        --doc-warn-bright: #e6c000; --doc-warn-bg: #fff8e1; --doc-orange: #bc4c00;
        --doc-accent: #0969da; --doc-accent-strong: #0550ae;
        --doc-accent-bg: #eef4ff; --doc-accent-ink: #2c4a7c;
        --doc-series-2: #8250df; --doc-on-accent: #ffffff;
    }
}
:root[data-theme="light"] {
        --doc-desk: #f2f3f5; --doc-sheet: #ffffff;
        --doc-tint: #f4f6f9; --doc-tint-2: #f7f9fc; --doc-tint-3: #f0f2f5;
        --doc-ink: #1c2027; --doc-ink-2: #45505f; --doc-ink-3: #5b6472;
        --doc-ink-4: #6b7484; --doc-ink-5: #8a93a2;
        --doc-rule: #d8dce3; --doc-rule-soft: #e3e6eb; --doc-rule-hair: #eef0f4;
        --doc-rule-strong: #b9c0cc; --doc-cash: #c9cfd8;
        --doc-gain: #1a7f37; --doc-loss: #cf222e; --doc-loss-ink: #8a1620;
        --doc-loss-dim: #a8555c; --doc-loss-bg: #fdf6f6;
        --doc-warn: #9a6700; --doc-warn-ink: #7d5e00; --doc-warn-line: #d4a72c;
        --doc-warn-bright: #e6c000; --doc-warn-bg: #fff8e1; --doc-orange: #bc4c00;
        --doc-accent: #0969da; --doc-accent-strong: #0550ae;
        --doc-accent-bg: #eef4ff; --doc-accent-ink: #2c4a7c;
        --doc-series-2: #8250df; --doc-on-accent: #ffffff;
}

/* The document's surface. In dark mode this is a dark sheet on a darker desk; in
   light it is the white page it has always been. Which one you get is the viewer's
   choice, everywhere except on paper. */
body.report {
    background: var(--doc-desk);
    color: var(--doc-ink);
    margin: 0;
    padding: 0;
}

/* The gutter around the sheet. It sits here rather than on the body because the
   printable view now carries the main nav, and a sticky full-width bar cannot be
   inset by the page's own padding without reading as a floating panel. */
.rshell { padding: var(--sp-4); }

/* **On `.report`, not on `body.report`.** The document is rendered inside the app
   as well, where the body is not `.report` and so inherited the app's own larger
   type — same markup, same stylesheet, visibly different document. A rule that
   describes the document has to live on the document. */
.report {
    font-family: var(--font);
    font-size: 14px;
    line-height: 1.55;
}

.sheet {
    max-width: 8.5in;
    margin: 0 auto;
    background: var(--doc-sheet);
    padding: 0.75in 0.7in;
    box-shadow: 0 2px 18px rgba(0, 0, 0, .12);
    border-radius: 4px;
}

/* ------------------------------------------------------------- the toolbar */

.rtoolbar {
    max-width: 8.5in; margin: 0 auto var(--sp-4);
    background: var(--doc-sheet); border: 1px solid var(--doc-rule); border-radius: var(--r-md);
    padding: var(--sp-3);
}
.rt-line { display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; }
.rt-line + .rt-line { margin-top: var(--sp-3); padding-top: var(--sp-3);
                      border-top: 1px solid var(--doc-rule-hair); }
.rt-back { font-size: var(--fs-sm); color: var(--doc-ink-3); text-decoration: none;
           border: 1px solid var(--doc-rule); border-radius: var(--r-sm);
           padding: 0.3rem 0.7rem; }
.rt-back:hover { border-color: var(--doc-rule-strong); text-decoration: none; }

.rt-presets { display: inline-flex; gap: var(--sp-2); flex-wrap: wrap; }
.rt-presets button {
    font: inherit; font-size: var(--fs-sm); padding: 0.3rem 0.7rem; cursor: pointer;
    border: 1px solid var(--doc-rule); border-radius: 999px; background: var(--doc-sheet); color: var(--doc-ink);
}
.rt-presets button:hover { background: var(--doc-accent-bg); border-color: var(--accent); }

.rt-switch { display: inline-flex; border: 1px solid var(--doc-rule); border-radius: var(--r-sm);
             overflow: hidden; }
.rt-switch a { font-size: var(--fs-sm); padding: 0.3rem 0.75rem; color: var(--doc-ink-3);
               text-decoration: none; border-right: 1px solid var(--doc-rule); }
.rt-switch a:last-child { border-right: none; }
.rt-switch a:hover { background: var(--doc-tint); text-decoration: none; }
.rt-switch a.on { background: var(--doc-accent); color: var(--doc-on-accent); }

/* THE DEMO SWITCH — off is a quiet outline, on is filled amber with its dot lit.
   It reads as a state rather than as an action on purpose: this is the one control on
   the toolbar that changes every figure below it, and it has to be obvious at a glance
   which way it is set from across the room. */
.rt-demo {
    display: inline-flex; align-items: center; gap: 0.45rem;
    font-size: var(--fs-sm); font-weight: var(--w-medium); font-family: var(--mono);
    padding: 0.3rem 0.7rem; border-radius: 999px; text-decoration: none;
    border: 1px solid var(--doc-rule); background: var(--doc-sheet); color: var(--doc-ink-3); white-space: nowrap;
}
.rt-demo:hover { text-decoration: none; border-color: var(--doc-warn); color: var(--doc-warn-ink); }
.rt-demo-dot { width: 0.55rem; height: 0.55rem; border-radius: 50%;
               background: var(--doc-rule); flex: none; }
.rt-demo.on { border-color: var(--doc-warn); background: var(--doc-warn-bg); color: var(--doc-warn-ink); }
.rt-demo.on .rt-demo-dot { background: var(--doc-warn-line);
                           box-shadow: 0 0 0 3px rgba(212, 167, 44, 0.25); }

/* The printed banner. Same box as `.runsettled` and deliberately NOT its red: an
   unreconciled ledger is a fault and this is a setting. Amber, and it prints — a
   scaled report that does not say so is indistinguishable from a real one, and the
   person most likely to be caught by that is whoever printed it. */
.demoband { border-color: var(--doc-warn-line); background: var(--doc-warn-bg); color: var(--doc-warn-ink); }

/* The refusal (`_unscalable.html`), on the pages that have no `.card` of their own. */
.unscalable h2 { font-family: var(--font-display); text-transform: none;
                 letter-spacing: 0; font-size: 1.15rem; color: var(--doc-ink);
                 border-bottom: none; }

.rt-print {
    font: inherit; font-size: var(--fs-sm); font-weight: var(--w-semi);
    margin-left: auto; padding: 0.4rem 1rem; cursor: pointer;
    border: 1px solid var(--doc-accent); background: var(--doc-accent); color: var(--doc-on-accent);
    border-radius: var(--r-sm);
}
.rt-print:hover { background: var(--doc-accent-strong); }

.rt-sections { font-size: var(--fs-sm); color: var(--doc-ink-3); }
/* 44px targets on a phone: this is a row of small controls and it is the only
   thing on the page anybody taps. */
.rt-sections label { display: inline-flex; align-items: center; gap: 0.35rem;
                     min-height: var(--tap); cursor: pointer; }
.rt-note { margin: var(--sp-3) 0 0; font-size: var(--fs-sm); color: var(--doc-ink-3); }

/* -------------------------------------------------------------- the sheet */

.rhead { display: flex; justify-content: space-between; align-items: flex-start;
         gap: var(--sp-5); border-bottom: 2px solid var(--doc-ink);
         padding-bottom: var(--sp-3); margin-bottom: var(--sp-5); }
.rhead h1 { margin: 0; font-family: var(--font-display); font-size: 1.6rem;
            letter-spacing: -0.01em; color: var(--doc-ink); }
.rsub { margin: 0.15rem 0 0; font-size: var(--fs-sm); color: var(--doc-ink-3); }
.rmeta { text-align: right; font-size: var(--fs-sm); color: var(--doc-ink-3); line-height: 1.6; }
.rmeta strong { font-family: var(--mono); color: var(--doc-ink); }

.report section { margin-bottom: var(--sp-6); }
.report h2 {
    font-size: 0.78rem; text-transform: uppercase; letter-spacing: .08em;
    color: var(--doc-ink-3); margin: 0 0 var(--sp-3);
    border-bottom: 1px solid var(--doc-rule-soft); padding-bottom: var(--sp-2);
}
.rlabel { margin: 0; font-size: 0.72rem; text-transform: uppercase;
          letter-spacing: .08em; color: var(--doc-ink-3); }
/* The one number somebody reads if they read one number. */
.rbig { margin: 0.1rem 0 0; font-family: var(--mono);
        font-size: clamp(2.4rem, 7vw, 3.4rem); font-weight: var(--w-semi);
        letter-spacing: -0.02em; line-height: 1.05; color: var(--doc-ink); }
.rbig-sub { margin: var(--sp-2) 0 0; font-size: var(--fs-lg); color: var(--doc-ink-3); }
.rlead { margin: 0 0 var(--sp-3); font-size: var(--fs-lg); line-height: 1.5; }
.rnote { margin: var(--sp-2) 0 0; font-size: var(--fs-sm); color: var(--doc-ink-4); }
.rbullets { margin: 0; padding-left: var(--sp-4); }
.rbullets li { margin-bottom: var(--sp-2); color: var(--doc-ink-2); }
.rverdict { margin: var(--sp-3) 0 0; padding: var(--sp-3); background: var(--doc-tint);
            border-radius: var(--r-sm); font-weight: var(--w-medium); }
.rverdict.bad { color: var(--doc-loss); } .rverdict.warn { color: var(--doc-warn); }
.rverdict.good { color: var(--doc-gain); }
.report .gain { color: var(--doc-gain); } .report .loss { color: var(--doc-loss); }
.report .muted { color: var(--doc-ink-4); }

/* A closed short and a holding that fell are the same ticker and the same negative
   number everywhere but here. Amber rather than red: it marks a KIND of trade, not a
   bad one, and the P&L column beside it is already carrying the verdict. */
.rtag { display: inline-block; margin-left: 0.4em; padding: 0.05rem 0.4rem;
        border: 1px solid var(--doc-warn-line); border-radius: var(--r-sm);
        background: var(--doc-warn-bg); color: var(--doc-warn-ink);
        font-size: var(--fs-xs); font-weight: var(--w-medium);
        letter-spacing: 0.02em; vertical-align: 0.08em; }

.runsettled {
    border: 2px solid var(--doc-loss); border-radius: var(--r-sm); color: var(--doc-loss-ink);
    padding: var(--sp-3); margin-bottom: var(--sp-5); font-size: var(--fs-sm);
}

/* "In plain words" is app markup (`.card.plainly`) rendered inside the sheet, and its
   colours come from theme tokens that follow the OS — so a dark-mode browser painted a
   dark card in the middle of a document whose own rule is "ink on white in both
   themes". Every colour it uses is pinned here to the document's palette; the tone
   borders keep their meaning in the print colours. */
.report .card.plainly { background: var(--doc-sheet); border: none; box-shadow: none; padding: 0; }
.report .plainly-block { border-left: 2px solid var(--doc-rule); }
.report .plainly-block h3 { border-bottom: none; padding-bottom: 0;
                            font-size: 0.95rem; margin: 0 0 var(--sp-2); color: var(--doc-ink); }
.report .plainly-block .lead { color: var(--doc-ink); }
.report .plainly-block li { color: var(--doc-ink-2); }
.report .plainly-block .verdict { color: var(--doc-ink); font-weight: var(--w-medium); }
.report .plainly-block.tone-good { border-left-color: var(--doc-gain); }
.report .plainly-block.tone-warn { border-left-color: var(--doc-warn); }
.report .plainly-block.tone-bad  { border-left-color: var(--doc-loss); }
.report .plainly-block.tone-good .verdict { color: var(--doc-gain); }
.report .plainly-block.tone-warn .verdict { color: var(--doc-warn); }
.report .plainly-block.tone-bad  .verdict { color: var(--doc-loss); }
.report .plainly .tiny { color: var(--doc-ink-4); }

.rtable { border-collapse: collapse; width: 100%; font-size: 0.85rem; }
.rtable th { text-align: left; font-size: 0.66rem; text-transform: uppercase;
             letter-spacing: .06em; color: var(--doc-ink-3); padding: 0.35rem 0.5rem;
             border-bottom: 1.5px solid var(--doc-rule); }
.rtable td { padding: 0.35rem 0.5rem; border-bottom: 1px solid var(--doc-rule-hair); }
.rtable td.num, .rtable th.num { text-align: right; font-family: var(--mono);
                                 font-variant-numeric: tabular-nums; }

.rsplit { display: flex; gap: var(--sp-5); align-items: flex-start; flex-wrap: wrap; }
.rsplit .rtable { flex: 1 1 18rem; }
.rdonut-wrap { display: flex; align-items: center; gap: var(--sp-4); }
.rlegend-list { list-style: none; margin: 0; padding: 0; font-size: var(--fs-sm); }
.rlegend-list li { display: flex; align-items: center; gap: 0.4rem;
                   margin-bottom: 0.2rem; color: var(--doc-ink-2); }
.rlegend-list b { margin-left: auto; font-family: var(--mono); color: var(--doc-ink); }

.rk { width: 10px; height: 10px; border-radius: 2px; display: inline-block; }
.rk-port { background: var(--series-1); } .rk-bench { background: var(--doc-ink-5); }
.rk-core { background: var(--band-core); }
.rk-balanced { background: var(--band-balanced); }
.rk-growth { background: var(--band-growth); }
.rk-satellite { background: var(--band-satellite); }
.rk-not-banded { background: var(--band-none); }
/* Cash is a deliberate neutral, NOT an omission. These two classes were simply never
   defined, so on accounts that are half cash the donut showed a bare track and the
   legend an invisible swatch — the largest slice of the book rendered as "no data". */
.rk-cash { background: var(--doc-cash); }
.rlegend { margin: var(--sp-2) 0 0; font-size: var(--fs-sm); color: var(--doc-ink-3);
           display: flex; align-items: center; gap: 0.4rem; flex-wrap: wrap; }

.rfoot { margin-top: var(--sp-6); padding-top: var(--sp-3);
         border-top: 1px solid var(--doc-rule-soft); font-size: 0.72rem; color: var(--doc-ink-4); }

/* ------------------------------------------------------------------ charts */

.rchart { display: block; width: 100%; height: 260px; }
.rchart .rc-base { stroke: var(--doc-rule); stroke-width: 1; stroke-dasharray: 3 3; }
.rchart .rc-port { fill: none; stroke: var(--series-1); stroke-width: 2;
                   stroke-linejoin: round; stroke-linecap: round;
                   vector-effect: non-scaling-stroke; }
.rchart .rc-bench { fill: none; stroke: var(--doc-ink-5); stroke-width: 1.5;
                    stroke-dasharray: 4 3; vector-effect: non-scaling-stroke; }

.rdonut .rd-track { fill: none; stroke: var(--doc-rule-hair); stroke-width: 22; }
.rdonut .rd-arc { fill: none; stroke-width: 22; }
.rdonut .rd-core { stroke: var(--band-core); }
.rdonut .rd-balanced { stroke: var(--band-balanced); }
.rdonut .rd-growth { stroke: var(--band-growth); }
.rdonut .rd-satellite { stroke: var(--band-satellite); }
.rdonut .rd-not-banded { stroke: var(--band-none); }
.rdonut .rd-cash { stroke: var(--doc-cash); }
.rdonut .rd-centre { fill: var(--doc-ink); font-family: var(--mono); font-size: 22px;
                     font-weight: 600; text-anchor: middle; }
.rdonut .rd-centre-sub { fill: var(--doc-ink-4); font-size: 9px; text-anchor: middle;
                         text-transform: uppercase; letter-spacing: 0.06em; }

/* Two bars, no axis. The numbers are on the bars; the drawing only has to show
   which is taller, which is the one thing a percentage does not do at a glance. */
.rversus { margin: var(--sp-3) 0 0; }
.rv-row { display: flex; align-items: center; gap: var(--sp-3);
          margin-bottom: var(--sp-2); }
.rv-label { flex: 0 0 11rem; font-size: var(--fs-sm); color: var(--doc-ink-2); }
.rv-bar { flex: 1; height: 26px; background: var(--doc-tint-3); border-radius: 3px;
          overflow: hidden; }
.rv-bar i { display: block; height: 100%; }
.rv-bar .rv-a { background: var(--series-1); }
.rv-bar .rv-b { background: var(--doc-rule-strong); }
/* The second bar in a three-way comparison — darker than the first comparator so the two
   are told apart without a legend, and neither competes with the account's own colour. */
.rv-bar .rv-c { background: var(--doc-ink-4); }
.rv-num { flex: 0 0 7.5rem; text-align: right; font-family: var(--mono);
          font-variant-numeric: tabular-nums; font-weight: var(--w-semi); }

/* ------------------------------------------------------------------- print */

/* **The page's own margin, declared rather than borrowed.** Nothing here ever set one,
   so the printed document relied entirely on whatever the browser's dialog was set to —
   and at "Margins: none", which is what a PDF export often defaults to, the leftmost
   column of every table ran off the edge of the sheet and lost its first characters.

   Belt and braces, because a print dialog can override `@page`: the page box asks for
   half an inch, and the sheet keeps a quarter-inch of its own padding, so even at zero
   page margin nothing touches the paper's edge. */
@page { margin: 0.5in; }

@media print {
    body.report { background: var(--doc-sheet); padding: 0; font-size: 11pt; }
    .sheet { box-shadow: none; max-width: none; padding: 0 0.25in; border-radius: 0; }
    /* The embedded copy carries its own padding at a higher specificity, so it has to be
       told separately or the app page prints with a 1.5rem gutter and the standalone one
       with 0.25in — same document, two margins. */
    .report.embedded .sheet { max-width: none; padding: 0 0.25in; border: none; }
    .rbleed { width: auto; margin-left: 0; }
    /* `header.top` had never been in this list, so the portfolio page has been
       printing the app's own navigation bar since the two views merged — and the
       printable view would now do the same. What gets sent is a document. */
    .rtoolbar, .rdepth, header.top { display: none !important; }
    .rshell { padding: 0; }

    /* A heading stranded at the foot of a page, or a table header on the sheet
       before its rows, is the difference between a report and a printout.

       Long-table sections are the exception: `avoid-page` on a section taller than
       the space left forces a page-feed first, so "Every holding" or the tax table
       arrived after half a blank sheet. Those break naturally — `thead` repeats on
       every page and rows stay whole, which is all the protection a table needs. */
    /* **Sections break naturally; the pieces inside them do not.**
       This was the other way round — every section kept whole, with a short list of
       exceptions — and the exception list is the tell: it had grown to nine entries and
       still stranded paper every time a section grew. `avoid-page` on a section taller
       than the space left forces a feed BEFORE it, so a document of growing sections
       spends more and more of itself on white.

       What actually has to stay together is smaller than a section and is already
       protected: a heading may not be the last thing on a sheet, a table row may not
       split, and a table header repeats on every page it continues onto. With those in
       place a section that runs over a page boundary reads correctly; one that is pushed
       whole just leaves a hole above it.

       Two exceptions remain, and both are pictures rather than prose: a chart split
       across a fold is not a chart, and the headline pair is the one screenful anybody
       reads if they read one. */
    .report section { break-inside: auto; }
    .report section[data-section="big"],
    .report section[data-section="growth"] { break-inside: avoid-page; }
    .report .rchart, .report .rbars, .report .rdeploy,
    .report .rversus, .report .rstats, .report .rdonut-wrap { break-inside: avoid-page; }

    /* **The nested one, which is why the first fix did nothing.** `_summary.html` renders
       its blocks inside a `<section class="card section plainly">` of its own, so
       `.report section` matched it too — relaxing the OUTER section left an inner one
       still marked `avoid-page`, still over half a page tall, and still pushed whole to
       the next sheet. Measured, not reasoned: the printed page-one text was identical
       byte for byte until this line existed.

       The grain that is right: each plain-words block stays whole, and the container
       holding them is free to split between two of them. */
    .report .plainly { break-inside: auto; }
    .report .plainly-block { break-inside: avoid-page; }

    /* Breaking naturally must not break a section apart at its seams: a sub-heading
       stranded at the foot of a sheet, or a table's header on the page before its rows,
       is the failure the whole-section rule was avoiding in the first place. */
    .report h3, .report .rsubhead { break-after: avoid-page; }
    .report .rversus, .report .rstats { break-inside: avoid-page; }
    .report h2 { break-after: avoid-page; }
    thead { display: table-header-group; }
    tr { break-inside: avoid; }

    /* Browsers strip backgrounds by default, which would take the bars, the
       donut and every tone with them — and those ARE the content here. */
    * { -webkit-print-color-adjust: exact; print-color-adjust: exact; }

    .rbig { font-size: 30pt; }
    .rchart { height: 2.4in; }

    /* Every disclosure prints open — `report.js` opens them on `beforeprint` and closes
       them again after, so "what you see is what you print" survives the tables that now
       fold. The triangle is a control that does nothing on paper. */
    .report details > summary { list-style: none; font-weight: var(--w-semi); }
    .report details > summary::-webkit-details-marker { display: none; }
    .report details > summary::after { content: ""; }
}

/* ------------------------------------------------- charts added for v2 */
/* Year rules sit under everything and must read as scaffolding, not data. */
.rchart .rc-tick { stroke: var(--doc-rule-hair); stroke-width: 1; }
.rchart .rc-tick-label { fill: var(--doc-ink-5); font-size: 10px; text-anchor: middle;
                         font-family: var(--mono); }

/* Money crossing the boundary. Deliberately the loudest thing on the chart
   after the two series: a deposit moves the line without anybody having been
   right about anything, and an unmarked one reads as performance. */
.rchart .rc-flow { stroke-width: 1; stroke-dasharray: 2 3; }
.rchart .rc-flow.rc-deposit { stroke: var(--doc-gain); }
.rchart .rc-flow.rc-withdrawal { stroke: var(--doc-loss); }
.rchart .rc-flow.rc-purchase { stroke: var(--doc-ink-5); }
.rchart .rc-flow-mark { stroke: none; }
.rchart .rc-flow-mark.rc-deposit { fill: var(--doc-gain); }
.rchart .rc-flow-mark.rc-withdrawal { fill: var(--doc-loss); }
.rchart .rc-flow-mark.rc-purchase { fill: var(--doc-ink-5); }

.rflows { list-style: none; margin: var(--sp-2) 0 0; padding: 0;
          display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-4);
          font-size: var(--fs-sm); color: var(--doc-ink-3); }
.rflows li { display: flex; align-items: center; gap: 0.4rem; }
.rflows .rf-date { font-family: var(--mono); }
.rflows b { font-family: var(--mono); color: var(--doc-ink); }
/* The legend carries the chart's own shapes, not two squares of different colours: the
   marker under the curve is a triangle pointing the way the money went, and a key that
   does not match it makes the reader learn the picture twice. `clip-path` failing leaves a
   coloured square, which is exactly what these were before. */
.rk-deposit { background: var(--doc-gain); border-radius: 0;
              clip-path: polygon(50% 0, 100% 100%, 0 100%); }
.rk-withdrawal { background: var(--doc-loss); border-radius: 0;
                 clip-path: polygon(0 0, 100% 0, 50% 100%); }

/* Where the money went: one bar, kept first. */
.rstack { margin: var(--sp-3) 0 0; }
.rs-bar { display: flex; height: 34px; border-radius: 3px; overflow: hidden;
          background: var(--doc-tint-3); }
.rs-bar i { display: block; height: 100%; }
.rs-kept { background: var(--doc-gain); }
.rs-tax { background: var(--doc-loss); }
.rs-advisor { background: var(--doc-orange); }
.rs-commissions { background: var(--doc-series-2); }
.rs-margin { background: var(--doc-warn); }
.rs-other { background: var(--doc-ink-5); }
.rk-kept { background: var(--doc-gain); } .rk-tax { background: var(--doc-loss); }
.rk-advisor { background: var(--doc-orange); } .rk-commissions { background: var(--doc-series-2); }
.rk-margin { background: var(--doc-warn); } .rk-other { background: var(--doc-ink-5); }
.rs-key { list-style: none; margin: var(--sp-3) 0 0; padding: 0;
          display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-4);
          font-size: var(--fs-sm); color: var(--doc-ink-2); }
.rs-key li { display: flex; align-items: center; gap: 0.4rem; }
.rs-key b { font-family: var(--mono); color: var(--doc-ink); }
.rs-pct { color: var(--doc-ink-4); font-family: var(--mono); }

.rsubhead { margin: var(--sp-5) 0 var(--sp-2); font-size: 0.82rem;
             text-transform: uppercase; letter-spacing: 0.05em; color: var(--doc-ink-3);
             font-weight: var(--w-semi); }

/* Year bars. */
.rbars { display: block; width: 100%; height: 190px; }
.rbars .rb-zero { stroke: var(--doc-cash); stroke-width: 1; }
.rbars .rb-port { fill: var(--series-1); }
.rbars .rb-bench { fill: var(--doc-rule-strong); }
.rbars .rb-value { fill: var(--doc-ink-2); font-size: 10px; text-anchor: middle;
                   font-family: var(--mono); }
.rbars .rb-label { fill: var(--doc-ink-4); font-size: 11px; text-anchor: middle; }

.rdeploy { display: block; width: 100%; height: 150px; }
.rdeploy .rdp-grid { stroke: var(--doc-rule-hair); stroke-width: 1; }
.rdeploy .rdp-grid-label { fill: var(--doc-rule-strong); font-size: 9px; font-family: var(--mono); }
.rdeploy .rdp-fill { fill: var(--series-1); fill-opacity: 0.16; stroke: none; }
.rdeploy .rdp-line { fill: none; stroke: var(--series-1); stroke-width: 1.75;
                     stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.rdeploy .rdp-axis { stroke: var(--doc-cash); stroke-width: 1; }

/* A number worth reading on its own, in a row of two or three. */
.rstats { display: flex; flex-wrap: wrap; gap: var(--sp-5); margin: var(--sp-3) 0 0; }
.rstat { flex: 1 1 9rem; min-width: 0; }
.rstat .rs-num { font-family: var(--mono); font-size: 1.35rem;
                 font-weight: var(--w-semi); color: var(--doc-ink); display: block; }
.rstat .rs-lab { font-size: var(--fs-sm); color: var(--doc-ink-4); display: block;
                 margin-top: 0.15rem; }
.rstat .rs-num.gain { color: var(--doc-gain); } .rstat .rs-num.loss { color: var(--doc-loss); }

/* Two panels reading as one thought. Falls to a single column under 46rem and
   on paper stays side by side, which is where the width actually exists. */
.rpair { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-5);
         align-items: start; }
.rpair > * { min-width: 0; }
@media (max-width: 46rem) { .rpair { grid-template-columns: 1fr; } }

/* A holding's purchase history, as chips. Reads as a sequence of decisions where a
   comma-separated list reads as one blob of text. */
.rtranches { line-height: 1.9; }
.rtr { display: inline-block; margin: 0 0.3rem 0.15rem 0; padding: 0.05rem 0.4rem;
       border-radius: 3px; font-size: 0.72rem; font-family: var(--mono);
       background: var(--doc-accent-bg); color: var(--doc-accent-ink); white-space: nowrap; }
.rtr b { font-weight: var(--w-semi); }
.rtr em { font-style: normal; color: var(--doc-warn); }
.rtr-reinvested { background: var(--doc-tint-3); color: var(--doc-ink-4); }
.rtr-transferred { background: var(--doc-warn-bg); color: var(--doc-warn); }

/* A wide table must scroll inside itself rather than pushing the sheet.

   **`auto hidden`, never plain `overflow-x`.** Setting one axis to `auto` forces the
   other from `visible` to `auto` — so any absolutely-positioned thing hanging out of the
   box makes a scrollbar appear on an axis nobody asked about. That is where the phantom
   vertical bars came from: `.tip::after` is hidden with `visibility`, which still lays the
   bubble out, so a five-row table that fitted the page perfectly grew a vertical scrollbar
   because one of its headers had a definition attached. The tooltips are inline prose now
   and the axis is nailed shut, which are two independent fixes for the same bug — on
   purpose, because the next person to add a tooltip to a table should not reintroduce it. */
.rscroll { overflow: auto hidden; }

/* **A floor, and it used to be wider than the page.** 44rem is 704px against a text
   column of 682px on paper — so `rwide` guaranteed a sideways drag on any table wearing
   it, whatever its content. It is now under the measure, and the two tables that needed
   the old value (the tax bill, the milestone chips) carry their own. */
.rtable.rwide { min-width: 40rem; }

/* **A table that is wide because it has to be.** The fee schedule is seven money columns,
   because a bill is only checkable when every subtraction in it is on the row — and no
   amount of header trimming got it inside the sheet. So it sets its type one step smaller
   and tightens its cells, which is the same trade the tax table has always made and is
   cheaper than dropping a column or scrolling sideways.

   That is the whole fix, and it was briefly paired with `rbleed` as well — belt and
   braces that cost the document its margins: the period column and the difference column
   landed on the grey outside the sheet on both the app page and the printable one. The
   smaller type is enough on its own, which the same table inside the disclosure below it
   had been demonstrating all along. `rbleed` is for the tax bill, which is thirteen
   columns and genuinely cannot be shrunk into the measure. */
.rtable.rtight { font-size: 0.79rem; }
.rtable.rtight td, .rtable.rtight th { padding: 0.3rem 0.4rem; }
/* Thirteen columns, because the bill is only checkable when every subtraction
   in it is on the row. Wider than the rest and scrolls inside `.rscroll`. */
.rtable.rtax { min-width: 66rem; }

/* **The one table allowed to be wider than the document.** Thirteen columns that have to
   reconcile left to right cannot be trimmed or folded without breaking the only thing the
   table is for, so instead of scrolling inside a 682px box it takes the width the window
   actually has. Screen only: on paper it goes back to the sheet and shrinks to 7pt, and
   `rshell`'s gutter is what stops it touching the window edge. */
@media screen and (min-width: 62rem) {
  .rbleed { width: min(72rem, calc(100vw - 3rem));
            margin-left: calc((100% - min(72rem, calc(100vw - 3rem))) / 2); }
}

/* The disclosures the long tables fold into: the year detail, the quarters that were
   charged nothing, the full holdings list. Same control as the cash-flow legs, so a
   reader learns one gesture. */
.rdetail { margin-top: var(--sp-4); }
.rdetail > summary { font-size: var(--fs-sm); font-weight: var(--w-semi);
                     color: var(--text-dim); }
.rdetail .rtable { margin-top: var(--sp-2); }
.rtable tr.rtotal td { border-top: 2px solid var(--doc-cash); font-weight: var(--w-semi); }
/* A footer that stacks several totals — put in, worth today, profit — needs the
   heavy rule once, where the tally starts. Repeating it under every line turns a
   summary into three separate tables. */
.rtable tfoot tr.rtotal + tr.rtotal td { border-top: 1px solid var(--doc-rule-hair); }
.rtable td.rlead-col { font-family: var(--mono); font-weight: var(--w-semi); }
.rtable tr.rquiet td { color: var(--doc-ink-5); }

/* ---------------------------------------------------- money in and out ----
   This section is read, not skimmed, and it was neither: six columns, 113
   characters of content, and an event heading whose 217-character explanation
   sat in one unconstrained cell and dragged the table past 270. A table that
   scrolls sideways is worse than a narrow one that omits something, because
   the scrolling hides the column the reader was comparing against.

   So the width is now capped in the two places that can blow it: every prose
   cell wraps at a readable measure, and the money columns are the only ones
   allowed to be wide. */

/* Prose inside a table cell. WITHOUT this the browser lays a long sentence out
   on one line and the table inherits its width -- the exact defect above. */
.rtable .rgloss { display: block; max-width: 46ch; font-size: var(--fs-sm);
  color: var(--doc-ink-4); font-weight: var(--w-normal); white-space: normal; }
.rtable tr.revent td[colspan] { max-width: 52ch; white-space: normal; }
.rtable td.rdate { white-space: nowrap; font-variant-numeric: tabular-nums; }
/* The running total is the column a reader checks last and needs least often. */
.rtable td.rrun { color: var(--doc-ink-4); }

/* An EVENT: legs that crossed the account boundary as one transfer. The bracket
   does real work -- three cash tranches of one account transfer, the middle one
   negative, read as a $303,414.37 client withdrawal when listed as three
   ordinary rows. Heading and subtotal carry the emphasis and the legs are
   visibly subordinate, so the eye lands on the total that means something
   before the parts that do not. Every leg stays on the page, indented, never
   hidden: a reader checking against a statement wants the row that is on the
   statement. */
.rtable tr.revent td { border-top: 2px solid var(--doc-cash); padding-top: 0.5rem;
  background: var(--doc-tint-2); }
.rtable tr.rleg td:first-child { padding-left: 1.4rem; }
.rtable tr.rleg td { color: var(--doc-ink-2); }
.rtable tr.reventsum td { border-top: 1px solid var(--doc-cash); border-bottom: 2px solid var(--doc-cash);
  font-weight: var(--w-semi); background: var(--doc-tint-2); }

/* A tally that qualifies the section rather than continuing it. */
.rsub { margin: var(--sp-4) 0 0; padding-left: var(--sp-3);
  border-left: 3px solid var(--doc-rule-hair); }
.rsub h3 { margin: 0 0 var(--sp-1); font-size: var(--fs-sm); text-transform: uppercase;
  letter-spacing: 0.04em; color: var(--doc-ink-4); }

/* The two summary tables -- what the section OPENS with. Narrow on purpose:
   these are meant to be read across in one glance, and a balance sheet that
   spans the full page makes the eye travel for no reason. */
.rtable.rbal, .rtable.rcross { max-width: 34rem; }
.rtable.rbal td:first-child, .rtable.rcross td:nth-child(2) { width: 99%; }
.rtable.rbal td, .rtable.rcross td { padding-top: 0.3rem; padding-bottom: 0.3rem; }

/* Every leg, behind a disclosure. Closed by default: the summary above is the
   whole history, and this is the view it is CHECKED in. */
.rlegs { margin-top: var(--sp-4); }
.rlegs > summary { font-size: var(--fs-sm); font-weight: var(--w-semi);
  color: var(--text-dim); }
.rlegs .rtable { margin-top: var(--sp-2); }

@media (max-width: 34rem) {
  /* Narrow screens: the running total is the first thing to go. It is a
     convenience for checking, and the signed amount beside it is the fact. */
  .rtable td.rrun, .rtable th.num:last-child { display: none; }
  .rtable .rgloss { max-width: 100%; }
}

/* Face value against what a cost actually took out of you. The whole table
   exists to make one asymmetry impossible to miss, so the non-deductible rows
   carry a tint and the "really cost" column is the one set in full weight —
   a reader who only ever looks at the bold column still reads it correctly. */
.rcost td.rlead-col { font-family: inherit; }
.rcost .rsub { display: block; font-size: 0.7rem; font-weight: 400; color: var(--doc-ink-5);
               font-family: var(--mono); }
.rcost tr.nondeductible { background: var(--doc-loss-bg); }
.rcost tr.nondeductible .rsub { color: var(--doc-loss-dim); }
.rcost tfoot td { border-top: 2px solid var(--doc-cash); font-weight: var(--w-semi); }

/* One line per rule, not one paragraph per row. */
.rwhy { margin: var(--sp-2) 0 0; padding-left: 1.1rem; font-size: var(--fs-sm);
        color: var(--doc-ink-3); line-height: 1.6; }
.rwhy li { margin: 0.35rem 0; }
.rwhy b { color: var(--doc-ink); }

/* The arithmetic, shown. Sam has to be able to dissect every figure, and a
   formula beside the answer is the difference between a report and a claim. */
.rmath { margin: var(--sp-2) 0 0; font-family: var(--mono); font-size: 0.78rem;
         color: var(--doc-ink-3); line-height: 1.7; }
.rmath b { color: var(--doc-ink); }

/* The share, beside the dollars rather than instead of them. Smaller and lighter, so the
   pair reads as one figure with its proportion attached and not as two headline numbers. */
.rbig-share { font-size: 0.42em; font-weight: var(--w-semi); color: var(--doc-ink-3);
              letter-spacing: 0; margin-left: 0.35rem; vertical-align: 0.35em; }

/* The hurdle, restored under the headline number. A band, not a tile: it reads as the
   sentence the two big figures were building toward. */
.rhurdle { margin: var(--sp-4) 0 0; padding: var(--sp-3);
           border-top: 2px solid var(--doc-ink); background: var(--doc-tint);
           border-radius: 0 0 var(--r-sm) var(--r-sm);
           font-size: var(--fs-md); line-height: 1.6; }
.rhurdle strong { font-family: var(--mono); font-variant-numeric: tabular-nums; }

/* The caveats in footnote type — printed whenever the full section is switched off,
   because the artefact that travels must carry them. */
.rfoot-notes { margin-top: var(--sp-6); padding-top: var(--sp-3);
               border-top: 1px solid var(--doc-rule-soft); }
.rfoot-notes ol { margin: var(--sp-2) 0 0; padding-left: 1.2rem; }
.rfoot-notes li { font-size: 0.72rem; color: var(--doc-ink-4); margin-bottom: 0.25rem;
                  line-height: 1.5; }

/* The count that stands in for the flows the legend does not name. */
.rflows .rf-rest { color: var(--doc-ink-5); }

/* The margin between the two versus bars, stated under them. */
.rv-gap-row { margin-top: -0.25rem; }
.rv-gap { font-family: var(--mono); font-size: 0.74rem; color: var(--doc-ink-4); }
.rv-gap b { color: var(--doc-ink); }

/* Endpoint labels and the price-coverage strip on the growth chart. */
.rchart .rc-end { font-family: var(--mono); font-size: 10px; text-anchor: end; }
.rchart .rc-end-port { fill: var(--series-1); font-weight: 600; }
.rchart .rc-end-bench { fill: var(--doc-ink-5); }
.rchart .rc-cov { fill: var(--doc-warn-line); }
.rk-cov { background: var(--doc-warn-line); opacity: 0.6; }

@media print {
    .rbars { height: 1.7in; }
    .rpair { grid-template-columns: 1fr 1fr; }
    .rscroll { overflow: visible; }
    .rtable.rwide { min-width: 0; font-size: 8.5pt; }
    .rtable.rtax { min-width: 0; font-size: 7pt; }
    /* Seven money columns at reading size do not fit 7.5 inches, and paper has no
       window width to borrow. Same trade the tax table makes one line above — and the
       screen now makes the same one, because a table hanging off both edges of the sheet
       reads as broken however wide the monitor is. */
    .rtable.rtight { font-size: 8pt; }
}


/* ===========================================================================
   The same body, embedded in the app — 2026-08-23.

   `report.css` is loaded on both pages now. Every rule in it is already scoped
   to `.report`, so wrapping the shared body in `<div class="report embedded">`
   makes it render identically inside the app chrome without either stylesheet
   needing to know about the other. `embedded` only undoes the standalone page's
   sheet framing, which base.html already provides.
   =========================================================================== */
/* **The sheet keeps its measure when embedded.** The first version dropped
   `max-width` and `padding` here on the reasoning that base.html already provides
   a container — it does not, and the result was 60-character prose stretched
   across a 2,500px monitor with the text touching both edges. A document is
   defined by its margins; the only thing the app page should take away is the
   drop shadow that made it look like a floating sheet on its own background. */
.report.embedded .sheet {
    box-shadow: none;
    border: 1px solid var(--border);
    padding: var(--sp-6) var(--sp-5);
}
@media (min-width: 60rem) {
    .report.embedded .sheet { padding: var(--sp-6) calc(var(--sp-6) * 1.5); }
}
.report.embedded .rhead { display: none; }   /* base.html has its own page header */

/* A header, not a panel: the same measure as the document it sits on, one row
   tall at rest, with the chips behind a disclosure. */
.rtoolbar { padding: var(--sp-2) var(--sp-3); }
.rt-line { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
.rt-line + .rt-line { margin-top: 0; padding-top: 0; border-top: none; }
.rt-spacer { flex: 1 1 auto; }

.rt-more { position: relative; }
.rt-more > summary {
    list-style: none; cursor: pointer; user-select: none;
    font-size: 0.78rem; color: var(--doc-ink-3); padding: 0.3rem 0.7rem;
    border: 1px solid var(--doc-rule); border-radius: var(--r-sm); white-space: nowrap;
}
.rt-more > summary::-webkit-details-marker { display: none; }
.rt-more > summary::after { content: " \25be"; color: var(--doc-rule-strong); }
.rt-more[open] > summary { background: var(--doc-accent-bg); border-color: var(--accent);
                           color: var(--doc-accent-strong); }
.rt-more > summary:hover { border-color: var(--doc-rule-strong); }
.rt-count { font-family: var(--mono); color: var(--doc-ink-5); margin-left: 0.15rem; }
/* Flows in the toolbar rather than floating over the page: a panel that overlays
   the first paragraph is a panel that hides the thing it is describing. */
.rt-panel { flex-basis: 100%; margin-top: var(--sp-3); padding-top: var(--sp-3);
            border-top: 1px solid var(--doc-rule-hair); }
/* `justify-content: flex-end` so the summary does not jump from the right of the
   row to the left of its own when it opens — the control a person just clicked
   should still be under their cursor. */
.rt-more[open] { flex-basis: 100%; display: flex; flex-wrap: wrap;
                 justify-content: flex-end; align-items: center; gap: var(--sp-2); }

.rt-sections { display: flex; flex-wrap: wrap; gap: 0.3rem; }
.rt-chip { display: inline-flex; align-items: center; gap: 0.3rem;
           padding: 0.15rem 0.55rem; border: 1px solid var(--doc-rule); border-radius: 999px;
           font-size: 0.74rem; color: var(--doc-ink-3); cursor: pointer; user-select: none;
           background: var(--doc-sheet); }
.rt-chip input { margin: 0; width: 0; height: 0; opacity: 0; position: absolute; }
.rt-chip:hover { border-color: var(--accent); }
.rt-chip:has(input:checked) { background: var(--doc-accent-bg); border-color: var(--accent);
                              color: var(--doc-accent-strong); font-weight: var(--w-semi); }
.rt-chip:has(input:focus-visible) { outline: 2px solid var(--accent);
                                    outline-offset: 2px; }
/* No :has() (older Safari): every chip stays legible and the checkbox comes back. */
@supports not selector(:has(*)) {
    .rt-chip input { position: static; width: auto; height: auto; opacity: 1; }
}
.rt-link { text-decoration: none; display: inline-block; }

/* Everything that submits a form. Never printed — which is what keeps
   "what you see is what you print" true on the app page and not only on the
   standalone one. */
.manage { margin-top: var(--sp-6); }
@media print { .manage, .crumbs, .rtoolbar, .controls { display: none !important; } }


/* ---------------------------------------------------------- the manage region */
/* **Wider than the document on purpose.** The sheet is held to 8.5in because that
   is a readable measure for prose; these are forms, and at that width the app's
   `.grid` would fold them into three ~260px columns too narrow for an email field.
   The workshop is allowed to use the screen the document declines to. */
.manage { max-width: min(76rem, 100%); margin: var(--sp-6) auto 0; }
.manage .grid { grid-template-columns: repeat(auto-fit, minmax(21rem, 1fr)); }
.manage-head { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.08em;
               color: var(--text-dim); font-weight: var(--w-semi);
               margin: 0 0 var(--sp-3); }
/* Each block is a few fields wide; stacked full-width they were most of a screen
   of scrolling. The app's own `.grid` puts them two up at 900px and three at 1300. */
.manage .card { margin: 0; }
.manage .card h3, .manage .card strong { font-size: var(--fs-sm); }

/* The document, its header and its step rail share one measure, so the header reads as
   attached to the page rather than floating above a wider one.

   The rail was the exception and looked it: `.wrap` is 1400px and the sheet is 8.5in, so
   eight steps ran a full 275px past the document on either side and read as page
   furniture rather than as this page's contents. Sam, 2026-09-04. Stated here rather than
   beside `.rail` in tokens.css because it is the same fact as the two above it, and this
   sheet is loaded on both pages that draw one. */
.rtoolbar, .rail, .report.embedded .sheet { max-width: 8.5in; margin-left: auto;
                                            margin-right: auto; }

/* ---------------------------------------------------------------- episodes */
/* The divergence line and the periods shaded on it. Green for a stretch the account ran
   ahead, red for one it fell behind — the same two colours `.gain` and `.loss` carry
   everywhere else on the sheet, at a weight a line can be read over. */
.rdiv { display: block; width: 100%; height: 200px; }
.rdiv .rd-band { opacity: 0.13; }
.rdiv .rd-peak { fill: var(--doc-gain); }
.rdiv .rd-dip { fill: var(--doc-loss); }
.rdiv .rd-par { stroke: var(--doc-cash); stroke-width: 1; stroke-dasharray: 3 3; }
.rdiv .rd-line { fill: none; stroke: var(--series-1); stroke-width: 1.6;
                 stroke-linejoin: round; }
.rdiv .rd-tag { fill: var(--doc-ink-4); font-size: 10px; text-anchor: middle;
                font-family: var(--mono); }
.rk-peak { background: var(--doc-gain); } .rk-dip { background: var(--doc-loss); }

/* One episode. The left rule is the only thing separating four or five of these, and it
   carries the direction so a reader scanning the section sees the shape before the
   numbers. */
.repisode { border-left: 3px solid var(--doc-cash); padding-left: 1rem; margin: 1.6rem 0 2rem; }
.repisode.re-peak { border-left-color: var(--doc-gain); }
.repisode.re-dip { border-left-color: var(--doc-loss); }
.repisode h3 { margin: 0 0 0.35rem; font-size: var(--fs-md); }
.repisode h3 .rgloss { display: block; font-weight: var(--w-reg);
                       font-size: var(--fs-sm); color: var(--doc-ink-4); }

/* The three-line split. No header row: each row says what it is in its own first cell,
   and a "what / how much" header over two columns earns nothing. */
/* `rsplit3`, not `rsplit`: that name is step 5's donut-and-table flex layout, and a
   table wearing it became a flex container — fine while it had one tbody, and the day
   it gained a thead (2026-09-04) the header sat beside the rows and the whole thing ran
   off the sheet. Sam's screenshot. */
.rsplit3 { margin: 0.9rem 0 0.5rem; }
.rsplit3 th { text-align: left; font-weight: var(--w-reg); }
.rsplit3 td.num { font-family: var(--mono); white-space: nowrap; }

/* A blank rank between the names that drove the period and the ones that pushed back —
   they are two lists in one table and a rule between them would read as a total. */
.rtable tr.rspacer td { padding: 0.25rem 0; border: 0; }

.rnote.rfee { border-left: 2px solid var(--doc-warn-bright); padding-left: 0.6rem; }

@media print {
  .rdiv { height: 1.8in; }
  .repisode { break-inside: avoid; }
}

/* Exposure through an episode and the weeks before it. */
.rexp { display: block; width: 100%; height: 170px; }
.rexp .rx-gross { fill: none; stroke: var(--series-1); stroke-width: 1.6;
                  stroke-linejoin: round; }
.rexp .rx-net { fill: none; stroke: var(--doc-ink-5); stroke-width: 1.4; stroke-linejoin: round;
                stroke-dasharray: 4 3; }
.rexp .rx-zero { stroke: var(--doc-cash); stroke-width: 1; }
.rexp .rx-full { stroke: var(--doc-cash); stroke-width: 1; stroke-dasharray: 3 3; }
/* Where the episode itself begins. Everything to its left is the lead-in that explains it. */
.rexp .rx-start { stroke: var(--doc-ink-2); stroke-width: 1; stroke-dasharray: 2 3; }
.rexp .rx-repo { fill: var(--doc-warn-bright); opacity: 0.18; }
.rexp .rx-label { fill: var(--doc-ink-4); font-size: 10px; font-family: var(--mono); }
.rexp .rx-mid { text-anchor: middle; }
.rexp .rx-end { text-anchor: end; }
.rk-gross { background: var(--series-1); } .rk-net { background: var(--doc-ink-5); }
.rk-repo { background: var(--doc-warn-bright); }

/* The sentence that names the build. It is the finding on a managed account, so it reads
   as a lead rather than a note. */
.rlead.rrepo { border-left: 2px solid var(--doc-warn-bright); padding-left: 0.6rem; }

@media print { .rexp { height: 1.5in; } }


/* ===========================================================================
   Eight steps — 2026-09-03. docs/tasks/PORTFOLIO_WIZARD.md.

   The body is the same 23 sections, grouped under eight questions. On the app
   page (`.report.stepped`) one step shows at a time and the rail above the sheet
   moves between them; on the printable page and on paper every step shows in
   order under its numbered chapter title, and every section heading carries a
   crumb naming its chapter so a page on its own still says where it belongs.
   =========================================================================== */
.rstep { margin-bottom: var(--sp-8); }
.rstep-head { border-bottom: 3px solid var(--doc-ink); padding-bottom: var(--sp-3);
              margin-bottom: var(--sp-5); }
.rstep-eyebrow { margin: 0; font-family: var(--mono); font-size: 0.68rem;
                 letter-spacing: .1em; text-transform: uppercase; color: var(--doc-ink-4); }
/* Larger than any other type on the sheet: this is the chapter title, and the section
   headings under it keep their small-caps treatment so the two levels read as two. */
.report h2.rstep-title { font-family: var(--font-display); font-size: 1.9rem;
                         font-weight: var(--w-bold); letter-spacing: -.02em;
                         text-transform: none; color: var(--doc-ink); border: 0; padding: 0;
                         margin: 0.15rem 0 0; line-height: 1.15; }
.rstep-q { margin: var(--sp-2) 0 0; font-size: var(--fs-lg); color: var(--doc-ink-3);
           max-width: 68ch; line-height: 1.4; }

/* One step at a time on the app page. `.active` is set by report.js; with no script the
   first step is shown by the template and the rest are reachable by their anchors. */
.report.stepped .rstep { display: none; }
.report.stepped .rstep.active { display: block; }
.report.stepped .rstep[hidden] { display: none; }

/* The crumb over every section heading: "3 · YEAR BY YEAR". Inserted by report.js. On
   the app page the rail already says where you are, so it shows only where the whole
   document is on one page: the printable view and paper. */
.rcrumb { display: block; font-family: var(--mono); font-size: 0.62rem;
          letter-spacing: .1em; text-transform: uppercase; color: var(--accent-dim);
          margin-bottom: 3px; }
.report.stepped .rcrumb { display: none; }

/* The contents list. Screen on the printable page, paper everywhere, never on the app
   page where the rail is the contents. */
.rtoc { margin-bottom: var(--sp-6); padding-bottom: var(--sp-4);
        border-bottom: 1px solid var(--doc-rule-soft); }
.rtoc ol { margin: var(--sp-2) 0 0; padding: 0; list-style: none; columns: 2;
           column-gap: var(--sp-6); }
.rtoc li { break-inside: avoid; padding: var(--sp-2) 0; border-bottom: 1px solid var(--doc-rule-hair);
           font-size: var(--fs-sm); color: var(--doc-ink-3); }
.rtoc li b { display: block; font-family: var(--font-display); color: var(--doc-ink);
             font-size: var(--fs-md); }
.rtoc-n { font-family: var(--mono); color: var(--accent-dim); margin-right: var(--sp-2); }
.report.stepped .rtoc { display: none; }

/* Prev / next under the sheet on the app page. */
.rnav { display: flex; justify-content: space-between; align-items: center;
        gap: var(--sp-3); max-width: 8.5in; margin: var(--sp-4) auto 0; }
.rnav .rnav-where { font-size: var(--fs-xs); color: var(--text-dim); }

/* The arithmetic behind a figure, one click away on screen and open on paper. The
   `.rmath` block inside is unchanged; this only decides when it is seen. */
details.rwork { margin: var(--sp-3) 0 0; }
details.rwork > summary { cursor: pointer; list-style: none; font-size: var(--fs-sm);
                          color: var(--doc-ink-3); font-weight: var(--w-semi); user-select: none; }
details.rwork > summary::-webkit-details-marker { display: none; }
details.rwork > summary::before { content: "+ "; font-family: var(--mono);
                                  color: var(--accent-dim); }
details.rwork[open] > summary::before { content: "\2212 "; }
details.rwork > .rmath { margin-top: var(--sp-2); }

/* Chips grouped by step in the toolbar. */
.rt-group { display: flex; flex-wrap: wrap; align-items: center; gap: 0.3rem;
            padding: 0.2rem 0; }
.rt-group + .rt-group { border-top: 1px solid var(--doc-rule-hair); }
.rt-glabel { font-family: var(--mono); font-size: 0.66rem; letter-spacing: .06em;
             text-transform: uppercase; color: var(--doc-ink-5); min-width: 11rem; }
/* The presets row wants its label narrow, not aligned to the step names' column: at
   11rem the six of them measure 826px against the 780 the panel has, so "Was it worth it"
   dropped to a line of its own for the sake of a gutter. */
.rt-presets .rt-glabel { min-width: 0; margin-right: var(--sp-2); }

@media print {
    .rail, .rnav { display: none !important; }
    .rtoc { display: block; break-after: page; }
    .report.stepped .rtoc, .report.stepped .rcrumb { display: block; }
    .report.stepped .rstep { display: block; }
    .report.stepped .rstep[hidden] { display: none; }
    .rstep { break-before: page; }
    /* THE REGULAR REPORT. Three things, none of which removes a section.
       Measured at each step (06 §11j), because guessing at page counts is how this
       project got a 42-page everyday document in the first place.

       1. The steps run on rather than each taking a fresh sheet. Worth less than it
          looks — the steps are long enough to fill whole pages anyway — but it is free.
       2. The type comes down. This is the everyday document, not the one held beside a
          statement, and 9.5pt is still comfortably readable on paper.
       3. The charts come down with it. A chart's job here is the shape of a line, and
          that survives losing a third of its height; at full size two of them fill a
          page between them. */
    .report.compact .rstep { break-before: auto; margin-bottom: var(--sp-5); }
    .report.compact .rtoc { break-after: auto; }
    .report.compact { font-size: 9pt; }
    .report.compact .rchart { height: 1.25in; }
    .report.compact .rbars { height: 1in; }
    .report.compact .rdiv { height: 1.1in; }
    .report.compact .rexp { height: 1in; }
    /* The chapter titles stay chapter titles and stop being display type: eight of them
       at 1.9rem with their rules and questions is most of a page between them. */
    .report.compact .rstep-q { font-size: 9pt; margin-top: 2pt; }
    .report.compact .rhead { padding-bottom: 6pt; margin-bottom: 10pt; }
    .report.compact .rbig-sub { font-size: 9pt; }
    .report.compact .rbullets li { margin-bottom: 2pt; }
    .report.compact .rverdict { padding: 5pt; margin-top: 6pt; }
    .report.compact .rgist-card { padding: 5pt 0; }
    .report.compact .rbig { font-size: 20pt; }
    .report.compact h2.rstep-title { font-size: 13pt; }
    .report.compact .rstep-head { padding-bottom: 4pt; margin-bottom: 8pt; }
    .report.compact section { margin-bottom: 10pt; }
    .report.compact .rlead { font-size: 10pt; }
    .report.compact .rnote, .report.compact .rgloss { font-size: 7.5pt; }
    .report.compact .rtable { font-size: 8pt; }
    .rstep-head { break-after: avoid; }
    details.rwork > summary { display: none; }
    details.rwork > .rmath { margin-top: 0; }
}

/* ---- three series, three identities — 2026-09-03.
   The account is the first series; VOO is teal and QQQ is purple, by name
   (tokens.css `--series-voo` / `--series-qqq`), on every chart and every key. A
   benchmark is never grey against another benchmark's grey, and never a
   semantic colour. Thicker lines and labelled endpoints, per Sam's review. */
.rchart { height: 280px; }
.rchart .rc-port { stroke-width: 2.4; }
.rchart .rc-bench { stroke: var(--series-voo); stroke-width: 1.8; stroke-dasharray: 5 4; }
.rchart .rc-alt { fill: none; stroke: var(--series-qqq); stroke-width: 1.8;
                  stroke-dasharray: 2 4; stroke-linejoin: round; }
.rchart .rc-end-bench { fill: var(--series-voo); font-weight: 600; }
.rchart .rc-end-alt { fill: var(--series-qqq); font-weight: 600; }
.rk-bench { background: var(--series-voo); }
.rk-alt { background: var(--series-qqq); }
.rbars .rb-bench { fill: var(--series-voo); }
.rbars .rb-alt { fill: var(--series-qqq); }
.rv-bar .rv-b { background: var(--series-voo); }
.rv-bar .rv-c { background: var(--series-qqq); }
.rdiv .rd-line { stroke-width: 2.2; }
.rdiv .rd-alt { fill: none; stroke: var(--series-qqq); stroke-width: 1.6;
                stroke-dasharray: 2 4; stroke-linejoin: round; }

/* ---- one holding — 2026-09-03. `portfolios/holding.html`. ---- */
.rhead-show h1 .rsub-inline { font-size: 1rem; font-weight: var(--w-normal); color: var(--doc-ink-3); }
.rholding .rstats { grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr)); }
.rprice .rp-held { fill: var(--doc-ink-5); opacity: 0.16; }
.rprice .rp-buy { fill: var(--doc-gain); stroke: var(--doc-sheet); stroke-width: 1; }
.rprice .rp-sell { fill: var(--doc-loss); stroke: var(--doc-sheet); stroke-width: 1; }
.rk-held { background: var(--doc-ink-5); opacity: 0.4; }
.rpick input { font: inherit; padding: 0.25rem 0.5rem; border: 1px solid var(--doc-rule);
               border-radius: var(--r-sm); }
@media print { .rpick { display: none !important; } }

/* ---- the bottom line under each step's question, and the gist's cards ---- */
.rstep-bottom { margin: var(--sp-3) 0 0; max-width: 68ch; padding: var(--sp-2) var(--sp-3);
                border-left: 3px solid var(--accent-dim); background: var(--doc-accent-bg);
                border-radius: 0 var(--r-sm) var(--r-sm) 0; font-size: var(--fs-md); }
.rstep-bottom b { font-weight: var(--w-semi); }
.rgist-verdict { font-family: var(--font-display); font-size: 1.25rem; line-height: 1.35;
                 font-weight: var(--w-semi); max-width: 68ch; margin: 0 0 var(--sp-4);
                 text-wrap: balance; }
.rgist { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-3); }
@media (max-width: 640px) { .rgist { grid-template-columns: 1fr; } }
.rgist-card { border: 1px solid var(--doc-rule); border-top: 3px solid var(--doc-rule);
              border-radius: var(--r-md); padding: var(--sp-3) var(--sp-4);
              display: flex; flex-direction: column; gap: var(--sp-2);
              break-inside: avoid; }
.rgist-card.tone-good { border-top-color: var(--doc-gain); }
.rgist-card.tone-warn { border-top-color: var(--doc-warn); }
.rgist-card.tone-bad  { border-top-color: var(--doc-loss); }
.rgist-card h3 { margin: 0; font-size: var(--fs-md); border: 0; padding: 0; }
.rgist-card p, .rgist-card li { font-size: var(--fs-sm); margin: 0; color: var(--doc-ink-2); }
.rgist-card ul { margin: 0; padding-left: 1.1em; }
.rgist-card .lead { color: var(--doc-ink); }
.rgist-card .verdict { font-weight: var(--w-medium); color: var(--doc-ink); }
.rgist-card.tone-good .verdict { color: var(--doc-gain); }
.rgist-card.tone-warn .verdict { color: var(--doc-warn); }
.rgist-card.tone-bad  .verdict { color: var(--doc-loss); }
.rgist-go { font-size: var(--fs-xs); margin-top: auto; text-decoration: none; }
@media print { .rgist-go { display: none; } .rgist { grid-template-columns: 1fr 1fr; } }

/* ---- the episode charts, with axes — 2026-09-03. Sam: "label the axis, lines, and
   make things clearer... adding dates on the horizontal is better." ---- */
.rdiv { height: 220px; }
.rdiv .rd-grid { stroke: var(--doc-rule-hair); stroke-width: 1; }
.rdiv .rd-grid.rd-par { stroke: var(--doc-ink-5); stroke-dasharray: 3 3; }
.rdiv .rd-tick { stroke: var(--doc-rule-hair); stroke-width: 1; }
.rdiv .rd-ylab { fill: var(--doc-ink-4); font-size: 10px; text-anchor: end; font-family: var(--mono); }
.rdiv .rd-xlab { fill: var(--doc-ink-5); font-size: 10px; text-anchor: middle; }
.rdiv .rd-axis { fill: var(--doc-ink-5); font-size: 9px; font-family: var(--mono); }
.rdiv .rd-axis-end { text-anchor: end; }
.rdiv .rd-end { font-size: 10px; font-family: var(--mono); font-weight: 600; }
.rdiv .rd-end-main { fill: var(--series-1); }
.rdiv .rd-end-alt { fill: var(--series-qqq); }
.rexp { height: 190px; }
.rexp .rx-grid { stroke: var(--doc-rule-hair); stroke-width: 1; }
.rexp .rx-tick { stroke: var(--doc-rule-hair); stroke-width: 1; }
.rexp .rx-ylab { fill: var(--doc-ink-4); font-size: 10px; text-anchor: end; font-family: var(--mono); }
.rexp .rx-xlab { fill: var(--doc-ink-5); font-size: 10px; text-anchor: middle; }
.rexp .rx-end { font-size: 10px; font-family: var(--mono); font-weight: 600; }
.rexp .rx-end-gross { fill: var(--series-1); }
.rexp .rx-end-net { fill: var(--doc-ink-4); }
.rexp .rx-end-lab { text-anchor: end; }
@media print { .rdiv { height: 2in; } .rexp { height: 1.7in; } }

/* The split table's labels are sentences now, and a sentence does not wear small caps
   or a nowrap. Sam's screenshot, 2026-09-04: the table ran off the page. */
.rsplit3 tbody th { white-space: normal; text-transform: none; letter-spacing: 0;
                    font-size: var(--fs-sm); color: var(--doc-ink); line-height: 1.4;
                    padding-right: var(--sp-3); }
.rsplit3 thead th { white-space: normal; }

/* The holdings-history table stays inside the sheet. It used to bleed to the window's
   width on screen (§10w) because its purchase chips are the content; stepped, that read
   as a table off the page. The chips wrap inside their cell instead. */
.rtranches { white-space: normal; min-width: 16rem; }

/* Label cells wrap; the app's global `td { white-space: nowrap }` is right for a figure
   and wrong for a sentence. The cost table's first column carried a label and its gloss
   on one unbreakable line and pushed the table past the sheet, so the printable page
   grew a scrollbar under "what each cost really cost". Sam, 2026-09-04. */
.report .rtable td.rlead-col, .report .rtable tbody th, .rcost .rsub,
.report .rtable td.wrap, .report .rtable th.wrap { white-space: normal; }
.rcost td.rlead-col { max-width: 18rem; }
@media print { .rcost .rsub { font-size: 0.62rem; } }

/* The toolbar sits directly under the page header on the app page: the controls row and
   the header's duplicate print link that used to sit between them are gone. */
.report-page .rtoolbar, .phead + .rtoolbar { margin-top: 0; }
.rt-course { background: transparent; color: var(--accent); border-color: var(--doc-rule); }

/* The board's button: the one control on the toolbar with a face, because balancing is
   a big part of the app and it should show (Sam, 2026-09-07). */
.rt-board { display: inline-flex; align-items: center; gap: .6rem; padding: .4rem .95rem .4rem .7rem;
            border-radius: var(--r-md); text-decoration: none; color: var(--doc-on-accent);
            background: linear-gradient(135deg, var(--accent, var(--doc-accent)), var(--doc-accent-strong));
            box-shadow: 0 2px 8px rgba(9, 105, 218, .35); border: 1px solid transparent; }
.rt-board:hover { filter: brightness(1.08); box-shadow: 0 4px 14px rgba(9, 105, 218, .45); color: var(--doc-on-accent); }
.rt-board svg { flex: none; }
.rt-board span { display: grid; line-height: 1.15; }
.rt-board b { font-size: var(--fs-sm); font-weight: var(--w-semi); }
.rt-board small { font-size: .68rem; opacity: .92; }
@media print { .rt-board { display: none !important; } }


/* ===========================================================================
   The three documents — 2026-09-04. docs/06 §11j.

   A row of links above the sheet, one per depth, the current one filled. Screen only:
   the print rule above hides it with the rest of the chrome.
   =========================================================================== */
.rdepth { display: flex; gap: var(--sp-2); max-width: 8.5in; margin: 0 auto var(--sp-3); }
.rdepth a { font-size: var(--fs-sm); font-weight: var(--w-medium); padding: 0.3rem 0.9rem;
            border: 1px solid var(--doc-rule); border-radius: 999px; background: var(--doc-sheet);
            color: var(--doc-ink-3); text-decoration: none; }
.rdepth a:hover { border-color: var(--accent); color: var(--accent);
                  text-decoration: none; }
.rdepth a.on { background: var(--doc-accent); border-color: var(--doc-accent); color: var(--doc-on-accent); }

/* ---- the one-page report ------------------------------------------------
   Eight blocks, each a figure you can read at arm's length and a sentence saying what
   it means. Sized so eight fit a page and a half without the reader ever meeting a
   table. `equifolio/brief.py` decides what goes in them. */
.rbrief { margin-top: var(--sp-5); }
.rb-block { display: grid; grid-template-columns: 2.2in 1fr; gap: var(--sp-5);
            padding: var(--sp-4) 0; border-top: 1px solid var(--doc-rule-soft); break-inside: avoid; }
.rb-block:first-child { border-top: 2px solid var(--doc-ink); }
.rb-n { font-family: var(--mono); font-size: 0.66rem; letter-spacing: .1em;
        text-transform: uppercase; color: var(--doc-ink-5); margin: 0 0 var(--sp-1); }
.rb-title { font-family: var(--font-display); font-size: 1.05rem; font-weight: var(--w-semi);
            color: var(--doc-ink); margin: 0; line-height: 1.2; }
.rb-figure { font-family: var(--mono); font-size: 1.9rem; font-weight: var(--w-semi);
             letter-spacing: -0.02em; color: var(--doc-ink); margin: var(--sp-2) 0 0;
             line-height: 1.05; }
.rb-unit { font-size: var(--fs-sm); color: var(--doc-ink-3); margin: 2px 0 0; }
.rb-line { margin: 0 0 var(--sp-2); font-size: var(--fs-lg); line-height: 1.45;
           color: var(--doc-ink); }
.rb-figure.good { color: var(--doc-gain); } .rb-figure.bad { color: var(--doc-loss); }

/* The bullets. A dash rather than a disc, and a coloured one where the point carries a
   verdict — Sam asked for the page to "reflect style, success/failure, big indicators",
   and a bullet that is green or red does that before a word is read. */
.rb-points { margin: 0; padding: 0; list-style: none; }
.rb-points li { position: relative; padding-left: 1rem; margin-bottom: 0.3rem;
                line-height: 1.4; color: var(--doc-ink); }
.rb-points li::before { content: "–"; position: absolute; left: 0; color: var(--doc-rule-strong); }
.rb-points li.good::before { content: "▲"; color: var(--doc-gain); font-size: 0.62em; top: 0.3em; }
.rb-points li.bad::before { content: "▼"; color: var(--doc-loss); font-size: 0.62em; top: 0.3em; }

/* The grids. Sam: "if you get a table: 22, 23, 24, 25, 26 and % vs VOO and dollar
   figures... another table: 5 episodes grid". Tight, no zebra, the verdict column tinted
   rather than the whole row shouted. */
.rb-table { width: 100%; border-collapse: collapse; margin: var(--sp-3) 0 0;
            font-size: var(--fs-sm); }
.rb-table th { text-align: left; font-size: 0.66rem; text-transform: uppercase;
               letter-spacing: .06em; color: var(--doc-ink-4); font-weight: var(--w-semi);
               border-bottom: 1px solid var(--doc-ink); padding: 0 0.5rem 3px 0; }
.rb-table th.num, .rb-table td.num { text-align: right; padding-right: 0; }
.rb-table td { padding: 3px 0.5rem 3px 0; border-bottom: 1px solid var(--doc-rule-hair);
               font-family: var(--mono); font-size: 0.78rem; white-space: nowrap; }
.rb-table td:first-child { font-family: var(--font); }
.rb-table tr.good td:last-child { color: var(--doc-gain); }
.rb-table tr.bad td:last-child { color: var(--doc-loss); }
.rb-tnote { margin: var(--sp-2) 0 0; font-size: var(--fs-xs); color: var(--doc-ink-4);
            line-height: 1.35; }

@media print {
    /* Two pages is the brief. Eight blocks fit the first comfortably; what pushed it to
       three was the caveats — eleven of them on the Pension, in full, because they are
       the one thing the print shell forbids configuring out of a document. So they are
       kept in full and set small, which is what a footnote is for. */
    .report.brief { font-size: 10pt; }
    .report.brief .rb-block { padding: 7pt 0; }
    .report.brief .rb-figure { font-size: 16pt; }
    .report.brief .rb-line { font-size: 10pt; }
    .report.brief .rb-points li { margin-bottom: 2pt; }
    .report.brief .rb-table { font-size: 8pt; }
    .report.brief .rb-table td { font-size: 8pt; }
    .report.brief .rb-tnote { font-size: 7pt; }
    .report.brief .rhead { padding-bottom: 6pt; margin-bottom: 8pt; }
    .report.brief .runsettled { padding: 5pt; margin-bottom: 8pt; font-size: 8.5pt; }
    .report.brief .rfoot-notes { font-size: 7pt; line-height: 1.35; }
    .report.brief .rfoot-notes li { margin-bottom: 2pt; }
    .report.brief .rbrief { margin-top: 6pt; }
}

@media (max-width: 719px) {
    .rb-block { grid-template-columns: 1fr; gap: var(--sp-2); }
}


/* ===========================================================================
   ON PAPER, ALWAYS INK ON WHITE — 2026-09-09.

   The screen follows the viewer; the printer does not. This block restates the
   paper palette inside `@media print`, so a report printed from a dark-mode
   window comes out identical to one printed from a light-mode window: black ink,
   white sheet, no field of toner where the background used to be.

   It sits at the foot of the file so it wins over both definitions above without
   needing `!important` on a single declaration — custom properties resolve at use,
   so overriding the twenty-nine tokens here re-colours every rule in the document
   at once.
   =========================================================================== */
@media print {
    :root {
        --doc-desk: #ffffff; --doc-sheet: #ffffff;
        --doc-tint: #f4f6f9; --doc-tint-2: #f7f9fc; --doc-tint-3: #f0f2f5;
        --doc-ink: #1c2027; --doc-ink-2: #45505f; --doc-ink-3: #5b6472;
        --doc-ink-4: #6b7484; --doc-ink-5: #8a93a2;
        --doc-rule: #d8dce3; --doc-rule-soft: #e3e6eb; --doc-rule-hair: #eef0f4;
        --doc-rule-strong: #b9c0cc; --doc-cash: #c9cfd8;
        --doc-gain: #1a7f37; --doc-loss: #cf222e; --doc-loss-ink: #8a1620;
        --doc-loss-dim: #a8555c; --doc-loss-bg: #fdf6f6;
        --doc-warn: #9a6700; --doc-warn-ink: #7d5e00; --doc-warn-line: #d4a72c;
        --doc-warn-bright: #e6c000; --doc-warn-bg: #fff8e1; --doc-orange: #bc4c00;
        --doc-accent: #0969da; --doc-accent-strong: #0550ae;
        --doc-accent-bg: #eef4ff; --doc-accent-ink: #2c4a7c;
        --doc-series-2: #8250df; --doc-on-accent: #ffffff;
    }
    /* The app's own tokens paint anything inside the sheet that is app markup —
       `.card.plainly` is the one that reaches the page. Pinned to paper here for the
       same reason. */
    :root {
        --bg: #ffffff; --surface: #ffffff; --surface-2: #f4f6f9;
        --border: #d8dce3; --text: #1c2027; --text-dim: #5b6472; --text-faint: #6b7484;
        --gain: #1a7f37; --loss: #cf222e; --warn: #9a6700;
        --accent: #0969da; --accent-dim: #0550ae; --shadow: none;
    }
}
