/* The portal's stylesheet, shared by both surfaces.
 *
 * NFR-27 requires the external surface and sign-in to render without
 * client-side scripting, so those pages are built by Ktor and this file is what
 * makes them look like the product. The staff console's Compose HTML bundle
 * links the same file, so the design has one source rather than two that drift.
 */

    /* Design tokens. This is the one token block: the Ktor pages and the
       Compose console both link this file, and the rules it implements are
       written down in doc/DESIGN-RULES.md.

       Re-value them freely; deleting one leaves a component with an invalid
       colour, because there is no fallback in a var() written without one. */
    :root {
      /* Which of the two palettes below the browser should draw its *own*
         parts in — the calendar an `<input type="datetime-local">` opens, the
         list a `<select>` drops down, the scrollbar of a table. Without it
         those stay light while everything around them turns, because a UA
         control takes no notice of a custom property. Not a colour: it names
         the palette already defined here. */
      color-scheme: light;
      --bg-app: #fcfdfd;
      --bg-primary: #fcfdfd;
      --bg-secondary: #ffffff;
      --bg-tertiary: #f7f7f7;
      --bg-hover: #f5f3f1;
      --accent-wash: #fff7f0;
      --text-primary: #000000;
      --text-secondary: #6b655d;
      --text-tertiary: #777169;
      /* --text-muted is 2.6:1 and is for marks that carry no words. Anything
 a reader has to read takes --text-tertiary, which clears AA at 4.7:1. */
      --text-muted: #a59f97;
      --border-color: #e5e5e5;
      --border-input: #e5e5e5;
      --accent-color: #000000;
      --accent-hover: #ffffff;
      --success-bg: #e7f3ee; --success-text: #14795a;
      --error-bg: #fbeae8;   --error-text: #a8331f;
      --warning-bg: #f9f0dc; --warning-text: #8a6508;
      --history-green: #1a936f;
      --info-bg: #e6ecff;    --info-text: #0447ff;
      --badge-bg: #f2f0ee;   --badge-text: #4a453e;
      --table-header-bg: #ffffff;
      --sidebar-bg: #fcfdfd;
      --sidebar-hover-bg: #ffffff;
      --positive-text: #14795a;
      --negative-text: #a8331f;
      /* Blue is the informational event type in a log, not a link colour:
         links in this product are black. See doc/DESIGN-RULES.md §3. */
      --link-color: #0447ff;
      --brand: #ff4704;
      --chart-orange: #ff7700;
      --chart-teal: #0099b9;
      --chart-mint: #70e4da;
      /* The v3 design's sector palette after orange, teal and mint. */
      --chart-rose: #e9b4a9;
      --chart-graphite: #605f5f;
      --chart-ink: #171717;
      --chart-apricot: #ffb066;
      --ring-inset: rgba(0, 0, 0, 0.075) 0 0 0 0.5px inset;
      --shadow-sm: rgba(0, 0, 0, 0.4) 0 0 1px, rgba(0, 0, 0, 0.04) 0 2px 4px;
      --shadow-md: rgba(0, 0, 0, 0.4) 0 0 1px, rgba(0, 0, 0, 0.08) 0 8px 24px;
      --r-card: 16px; --r-nav: 12px; --r-input: 4px; --r-pill: 9999px;
      --font-mono: 'Geist Mono', ui-monospace, monospace;
    }
    /* Derived rather than copied: the same warm hue turned over, so a page
       reads as the same product at night rather than a different, colder one. */
    body.dark {
      color-scheme: dark;
      --bg-app: #0f0e0d;
      --bg-primary: #141312;
      --bg-secondary: #1c1a18;
      --bg-tertiary: #232120;
      --bg-hover: #2a2725;
      --accent-wash: #2a2017;
      --text-primary: #f6f5f3;
      --text-secondary: #b3aca2;
      --text-tertiary: #9c958b;
      --text-muted: #6f6960;
      --border-color: rgba(255, 255, 255, 0.09);
      --border-input: rgba(255, 255, 255, 0.14);
      --accent-color: #f6f5f3;
      --accent-hover: #1c1a18;
      --success-bg: rgba(26, 147, 111, 0.16); --success-text: #4ec99f;
      --error-bg: rgba(192, 57, 43, 0.16);    --error-text: #e8796a;
      --warning-bg: rgba(184, 134, 11, 0.16); --warning-text: #d8ab41;
      --info-bg: rgba(4, 71, 255, 0.18);      --info-text: #8aa4ff;
      --badge-bg: #2a2725;   --badge-text: #cfc8bf;
      --table-header-bg: #1c1a18;
      --sidebar-bg: #1c1a18;
      --sidebar-hover-bg: #232120;
      --positive-text: #4ec99f;
      --negative-text: #e8796a;
      --link-color: #8aa4ff;
      --ring-inset: rgba(255, 255, 255, 0.10) 0 0 0 0.5px inset;
      --shadow-sm: rgba(0, 0, 0, 0.6) 0 0 1px, rgba(0, 0, 0, 0.30) 0 2px 4px;
      --shadow-md: rgba(0, 0, 0, 0.6) 0 0 1px, rgba(0, 0, 0, 0.45) 0 8px 24px;
    }

    * { margin: 0; padding: 0; box-sizing: border-box; }
    html, body { height: 100%; }
    body {
      font-family: 'Inter', system-ui, -apple-system, sans-serif;
      /* DESIGN-RULES §2: "Body default 14 (the app root sets this and it is
         inherited)". Without it anything that names no size of its own takes
         the browser's 16px. */
      font-size: 14px;
      font-variant-numeric: tabular-nums;
      -webkit-font-smoothing: antialiased;
      color: var(--text-primary);
      background: var(--bg-primary);
    }
    /* Black, with the underline arriving on hover. The reference portals set
       no blue link anywhere, and a blue one inside a table of figures reads as
       another status colour. */
    a { color: var(--text-primary); text-decoration: none; }
    a:hover { color: var(--text-primary); text-decoration: underline; }
    /* The attribute has to win over a class that sets display, or a control
       shipped hidden until its script runs is shown dead with scripting off. */
    [hidden] { display: none !important; }
    #root { min-height: 100%; }

    /* The brand artwork paints only black and white — its one orange fill sits
       inside an alpha mask and is never rendered — so inverting it is safe.
       `on-dark` sits on a panel that is dark in both themes and is always
       inverted; `on-page` follows the theme. */
    .logo-mark { width: 34px; height: 44px; display: block; }
    .logo-full { height: 34px; width: auto; display: block; }
    .on-dark { filter: invert(1); }
    body.dark .on-page { filter: invert(1); }

    /* ---- controls ------------------------------------------------------ */
    .btn {
      display: inline-flex; align-items: center; justify-content: center; gap: 8px;
      padding: 10px 20px; border-radius: var(--r-pill);
      /* A pill with two lines in it is not a pill. The label decides the
         button's width, and a narrow column scrolls rather than folding it. */
      white-space: nowrap;
      font-size: 14px; font-weight: 500; font-family: inherit;
      background: transparent; color: var(--text-primary);
      border: 1px solid var(--border-color); cursor: pointer;
      transition: background .12s ease, color .12s ease, transform .08s ease;
    }
    .btn:hover { background: var(--bg-hover); color: var(--text-primary); }
    /* A button drawn as an anchor, which the server-rendered portal has to do:
       every one of its actions is a GET (NFR-07) and a form button would be a
       post. The base rule underlines a link on hover; a pill with a line under
       its label is not the same control as the one beside it. */
    a.btn:hover { text-decoration: none; }
    .btn:active { transform: scale(0.98); }
    .btn.primary {
      background: var(--accent-color); color: var(--bg-secondary);
      border-color: var(--accent-color);
    }
    body.dark .btn.primary { color: #141312; }
    .btn.primary:hover {
      background: var(--accent-hover); color: var(--text-primary);
      border-color: var(--border-color);
    }
    /* `position: relative` is what `.menu` below is absolutely positioned
       against: `.sel` is deliberately static in the canvas, so without this the
       opened list is placed against the page and lands nowhere near its
       summary. It was missing when the block was first ported. */
    .field { display: flex; flex-direction: column; gap: 6px; position: relative; }
    /* DESIGN-RULES "Input": a form label is 13px, 500, --text-secondary,
       6px above its field, and the section says why the 500 — "it is doing the
       work a column heading does in a table, and the two sit on the same
       screen." This block held 12px/400/--text-tertiary, citing the same
       section against what it says; the canvas never moved. The mark beside it
       is a step down in both, which needs the label to be at the top of that
       step. */
    .field-l { font-size: 13px; font-weight: 500; color: var(--text-secondary); }
    /* DESIGN-RULES "Input", Optional. The marked field is the one that may be
       left blank; required is the default and carries nothing. */
    .field-opt { font-size: 12px; font-weight: 400; color: var(--text-secondary); margin-left: 8px; }
    .input {
      padding: 10px 12px; border: 1px solid var(--border-input);
      border-radius: var(--r-input); font-family: inherit;
      font-size: 14px; background: var(--bg-secondary); color: var(--text-primary);
      transition: border-color .12s ease;
    }
    .input:hover { border-color: var(--text-muted); }
    .input:focus, .input:focus-within { border-color: var(--text-primary); outline: none; }
    .input::placeholder { color: var(--text-tertiary); }
    /* DESIGN-RULES §Input, Disabled: the field on the page's sunken ground, its value in the
       label ink, and no answer to the pointer. */
    .input:disabled { background: var(--bg-tertiary); color: var(--text-tertiary); cursor: default; }
    .input:disabled:hover { border-color: var(--border-input); }
    /* the same box, when what it holds is a choice and a chevron rather than
       something typed: the canvas gives every `<summary class="input select">`
       these three lines, and without them the chevron drops below the value. */
    .input.select { display: flex; align-items: center; justify-content: space-between; }
    .input.ph { color: var(--text-tertiary); }
    /* DESIGN-RULES "Editable cell — Derived": the one control that may sit in
       a table cell and not be a button. The same box as `.input`, at the size
       the artboard drew, right aligned because the column it lives in is, and
       bound to thirteen figures rather than the column's width — a field that
       grows with the column stops looking like one field repeated and starts
       looking like the table has become a form. Thirteen is a billion to the
       cent: the artboard's 110px showed ten and hid the cents of the rest. */
    .cellnum {
      padding: 5px 9px; width: calc(13ch + 20px); text-align: right;
      font-variant-numeric: tabular-nums;
    }
    /* the same box, taller, for the one field on the console that holds a
       paragraph rather than a value: a third-party agreement's economics are
       prose, because nothing computes them. Line height steps up from the
       product's 1.5 for the same reason a callout's does — this is text to be
       read, not a figure to be scanned. Character for character the canvas's. */
    .input.ta { min-height: 74px; line-height: 1.6; }
    /* the same box, holding a file. DESIGN-RULES "Input — file, Derived": the
       prototype draws this field as an ordinary `.input` with a filename in it,
       because an artboard has no file chooser; a real one has the browser's
       button inside the box, and left unstyled it is the one control on the
       console in the browser's font. The button is the ghost `.btn`, minus the
       pill — a pill inside a 6px box does not fit — and the padding above drops
       to 7px so the box keeps its height with a button in it. */
    /* The browser's date field is two pixels taller than a text field for its
       own inner parts: held to the field's height so a row of fields stays level. */
    .input[type="date"], .input[type="datetime-local"], .input[type="month"], .input[type="time"] { height: 39px; }
    /* The file field is a pixel short for the same reason, and is held to it too. */
    .input[type="file"] { padding: 4px; cursor: pointer; height: 39px; }
    .input[type="file"]::file-selector-button {
      margin-right: 12px; padding: 5px 12px; border-radius: var(--r-input);
      font-family: inherit; font-size: 13px; font-weight: 500;
      background: transparent; color: var(--text-primary);
      border: 1px solid var(--border-color); cursor: pointer;
      transition: background .12s ease;
    }
    .input[type="file"]::file-selector-button:hover { background: var(--bg-hover); }

    /* ---- sign-in ------------------------------------------------------- */
    /* One column, centred. There used to be a second half carrying a claim,
       a paragraph and four figures; it said nothing the person signing in
       needed and made the form the smaller half of the screen. */
    /* A column that fills the viewport: the form centres in what is left after
       the footer, which sits on the bottom edge. */
    /* Sign-in shares the v3 reference's application ground. Fields keep
       their card fill and border to distinguish them from the page. */
    .si {
      min-height: 100vh; display: flex; flex-direction: column;
      background: var(--bg-app);
    }
    /* Keep labels, legal text and quiet links one grey step darker on the
       pages that still stand in one column (error, confirm address). */
    .si:not(.si-split) { --text-tertiary: var(--text-secondary); }
    /* Three rows, and the middle one is what centres.

       `1fr auto 1fr` puts `si-body` — the button, the field, the panel — on the
       exact vertical centre of the page whatever its height, and `si-head`
       hangs off the bottom of the row above it. Centring one flat column
       instead counts the mark and the title as part of the mass being centred,
       which pushes the form down and reads as low rather than centred.

       An `1fr` row never shrinks below its own content, so on a viewport too
       short for all three the layout falls back to plain stacking. */
    .si-form {
      flex: 1; padding: 48px 24px 24px; width: 100%;
      display: grid; grid-template-rows: 1fr auto 1fr; justify-items: center;
    }
    .si-form > * { width: 100%; max-width: 400px; }
    .si-head { grid-row: 1; align-self: end; margin-bottom: 32px; }
    .si-body { grid-row: 2; display: flex; flex-direction: column; gap: 24px; }

    /* The mark stands apart from the title under it: 40px, the rhythm table's
       step for one section to the next. */
    .si-top {
      display: flex; justify-content: center; margin-bottom: 40px;
    }
    .si-top .logo-full { height: 56px; width: auto; }

    /* The button is a separate step from the field it submits, so it takes the
       16px the scale gives a field to the block after it, not the 6px that
       binds a label to its own input. */
    .si-form form { display: flex; flex-direction: column; gap: 16px; }

    /* On the bottom edge with a margin, not hung under a form whose height
       changes between the two steps. */
    .si-legal {
      font-size: 12px; color: var(--text-tertiary); text-align: center;
      display: flex; justify-content: center; align-items: center;
      gap: 8px; flex-wrap: wrap; padding: 0 24px 28px;
    }
    .si-legal a {
      color: var(--text-tertiary); text-decoration: underline; text-underline-offset: 3px;
    }
    .si-legal a:hover { color: var(--text-primary); }
    .si-dot { opacity: 0.5; }

    /* 400, not 600. A page title in this design is large and light; weight is
       what a value uses to stand out from its label, not what a heading uses
       to stand out from the page. */
    .si-h { font-size: 24px; font-weight: 400; letter-spacing: -0.02em; }
    .si-p { font-size: 14px; color: var(--text-tertiary); line-height: 1.5; }
    /* The title block only. `.si-p` is used again inside the code step, where
       it sits under a left-aligned form and stays left. */
    .si-intro { text-align: center; display: flex; flex-direction: column; gap: 8px; }

    /* Rendered by SignInPage on a refused attempt and, until now, unstyled —
       the sentence arrived as ordinary body text. Colour on the words, not a
       filled panel behind them. */
    /* On the card fill and not the callout's: the callout fill is this page's
       own ground, so a sunken panel here would have nothing to sink into. */
    .si-error {
      font-size: 13px; color: var(--error-text); line-height: 1.5;
      background: var(--bg-secondary); border-radius: var(--r-nav); padding: 14px 16px;
    }
    .si-google {
      display: flex; align-items: center; justify-content: center; gap: 12px;
      padding: 11px 20px; border: 1px solid var(--border-input); border-radius: var(--r-pill);
      font-size: 14px; font-weight: 500; font-family: inherit;
      background: var(--bg-secondary); color: var(--text-primary); cursor: pointer;
    }
    /* The border darkens and the fill stays. The usual hover fill for a quiet
       control is `--bg-hover`, which on this screen is the page itself, so the
       button would sink into the ground instead of answering the pointer. This
       is the hover a field on the same screen already uses. */
    .si-google:hover { border-color: var(--text-muted); text-decoration: none; }
    .si-or { display: flex; align-items: center; gap: 14px; color: var(--text-tertiary); font-size: 13px; }
    .si-or:before, .si-or:after { content: ""; flex: 1; height: 1px; background: var(--border-color); }
    .si-wide { width: 100%; justify-content: center; padding: 11px 20px; font-size: 14px; }
    /* The code step stands on the page like the address step before it, with no
       fill of its own. It used to be a sunken callout, which put the six cells
       on a surface darker than the page: in the dark theme that made them the
       darkest thing on the screen instead of the lightest, and the sentence and
       the two links read as belonging to a panel rather than to the screen. */
    .si-step2 { display: flex; flex-direction: column; gap: 16px; }
    .si-sent { font-size: 13px; color: var(--text-tertiary); line-height: 1.5; }
    .si-sent strong { color: var(--text-primary); font-weight: 500; }
    /* Resend and Back are peers of each other and subordinate to Sign in, so
       they are quiet text buttons rather than a second pair of pills. */
    .si-alt { display: flex; gap: 18px; align-items: center; }
    .si-link {
      background: none; border: 0; padding: 0; font: inherit; font-size: 13px;
      color: var(--text-tertiary); cursor: pointer; text-decoration: underline;
      text-underline-offset: 3px;
    }
    .si-link:hover { color: var(--text-primary); }
    .btn:disabled { opacity: 0.45; cursor: default; }
    /* Disabled, a button answers nothing: no hover fill, no press. The primary keeps its own
       fill and every other variant its own ground and ink. */
    .btn:disabled:hover { background: transparent; }
    .btn:not(.primary):not(.danger):disabled:hover { color: var(--text-primary); }
    .btn.primary:disabled:hover { background: var(--accent-color); color: var(--bg-secondary); border-color: var(--accent-color); }
    .btn:disabled:active { transform: none; }

    /* Six boxes, one digit each. They work with no script at all — six
       ordinary fields the person tabs between — and the script in SignInPage
       only adds the moving-on, the moving-back and the paste.

       Sized against DESIGN-RULES rather than the first draft of the prototype,
       which drew them at 8px/22px/600: the radius token for a field is 4px, and
       20px/500/-0.01em is the scale's own row for six figures across. */
    /* The row spans the panel, so its ends line up with the label above it
       and the submit below rather than floating centred between them. */
    .si-code { display: flex; gap: 10px; }
    .si-cell {
      flex: 1 1 0; min-width: 0; height: 54px;
      border: 1px solid var(--border-input); border-radius: var(--r-input);
      background: var(--bg-secondary); color: var(--text-primary);
      font-family: inherit; font-size: 20px; font-weight: 500; letter-spacing: -0.01em;
      font-variant-numeric: tabular-nums; text-align: center; padding: 0;
      transition: border-color .12s ease;
    }
    .si-cell:hover { border-color: var(--text-muted); }
    .si-cell:focus { border-color: var(--text-primary); outline: none; }

    /* DESIGN-RULES §Sign-in: the v3 login design. Two halves; the left is the
       orb 0 drawn to its whole rectangle over --chart-orange, which is all it
       is without script; the right centres a 400px panel and keeps help and
       the legal line on its bottom edge. Controls are the design's: 15px,
       14px of padding, the --r-nav radius. */
    .si-split { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
    .si-art { position: relative; min-height: 100vh; background: var(--chart-orange); overflow: hidden; }
    .si-art ff-orb { position: absolute; inset: 0; display: block; }
    .si-art ff-orb canvas { display: block; width: 100%; height: 100%; }
    .si-side { display: flex; flex-direction: column; min-height: 100vh; padding: 40px 32px; min-width: 0; }
    .si-main { flex: 1; display: flex; align-items: center; justify-content: center; padding: 48px 0; }
    .si-split .si-body { width: 100%; max-width: 400px; gap: 0; }
    .si-title { margin: 0 0 32px; font-size: 36px; font-weight: 400; letter-spacing: -0.02em; line-height: 1.1; }
    .si-split .si-error { margin-bottom: 24px; }
    .si-split form { display: flex; flex-direction: column; gap: 16px; }
    .si-split .si-google { padding: 14px 20px; border-radius: var(--r-nav); font-size: 15px; }
    .si-split .si-or { margin: 28px 0; gap: 16px; font-size: 14px; }
    .si-split .field-l { color: var(--text-tertiary); }
    .si-split .input { padding: 14px 16px; font-size: 15px; border-radius: var(--r-nav); }
    .si-split .si-wide { padding: 14px 20px; font-size: 15px; border-radius: var(--r-nav); }
    .si-split .si-cell { border-radius: var(--r-nav); }
    .si-help { text-align: center; font-size: 13px; color: var(--text-tertiary); line-height: 1.6; }
    .si-help a { color: var(--text-primary); text-decoration: underline; text-underline-offset: 3px; }
    .si-split .si-legal { padding: 12px 0 0; }
    /* ---- legal pages --------------------------------------------------- */
    .lg-top {
      border-bottom: 1px solid var(--border-color); background: var(--bg-primary);
      position: sticky; top: 0; z-index: 10;
    }
    .lg-top-in {
      max-width: 880px; margin: 0 auto; padding: 18px 24px;
      display: flex; align-items: center; gap: 14px;
    }
    .lg-top .logo-full { height: 28px; }
    .lg-top-links { margin-left: auto; display: flex; gap: 20px; font-size: 13px; }
    .lg-top-links a { color: var(--text-tertiary); }
    .lg-top-links a.on { color: var(--text-primary); font-weight: 500; }

    /* `lg-page`, not `lg`: the bare class collided with the `lg` modifier a
       Stat puts on `.strip-v` for a large figure (§Stat), so every headline
       figure in the product was taking this page's 56px of padding — pushed
       down and indented away from its own label. The rest of this section is
       already `lg-*`; this one line was the anomaly. */
    .lg-page { max-width: 880px; margin: 0 auto; padding: 56px 24px 96px; }
    /* Sentence case and no added tracking. Nothing in this design is set in
       capitals; an eyebrow is just a small grey line above the title. */
    .lg-eyebrow {
      font-size: 13px; color: var(--text-tertiary); margin-bottom: 8px;
    }
    /* The page title's 36px (21px below the breakpoint) and the body's 14px: DESIGN-RULES §2 Scale has
       no 32, no 16/400 and no 15 for prose. */
    .lg-h1 { font-size: 36px; font-weight: 400; letter-spacing: -0.02em; line-height: 1.1; }
    .lg-meta { font-size: 13px; color: var(--text-tertiary); margin-top: 12px; }
    .lg-lede { font-size: 14px; line-height: 1.6; color: var(--text-tertiary); margin-top: 24px; max-width: 68ch; }

    .lg-toc {
      margin-top: 40px; padding: 22px 24px; border-radius: var(--r-nav);
      background: var(--bg-hover);
    }
    .lg-toc-h { font-size: 12px; color: var(--text-tertiary); }
    .lg-toc ul { margin: 14px 0 0; padding: 0; list-style: none; }
    .lg-toc li { font-size: 14px; line-height: 1.8; }
    .lg-toc a { color: var(--text-primary); }

    .lg-sec { margin-top: 44px; scroll-margin-top: 80px; }
    .lg-sec h2 {
      font-size: 18px; font-weight: 500; letter-spacing: -0.01em;
      padding-bottom: 10px; border-bottom: 1px solid var(--border-color);
    }
    /* 1.6 rather than the 1.5 a portal screen uses: these two pages are the
       only long-form reading in the product, and the rules allow the looser
       leading for exactly that. */
    .lg-sec p { font-size: 14px; line-height: 1.6; color: var(--text-tertiary); margin-top: 16px; max-width: 72ch; }
    .lg-sec ul { margin: 16px 0 0 20px; max-width: 72ch; }
    .lg-sec li { font-size: 14px; line-height: 1.6; color: var(--text-tertiary); margin-bottom: 8px; }
    .lg-sec strong { color: var(--text-primary); font-weight: 500; }

    .lg-foot {
      margin-top: 72px; padding-top: 24px; border-top: 1px solid var(--border-color);
      font-size: 13px; color: var(--text-tertiary); display: flex; gap: 20px; flex-wrap: wrap;
    }

    /* ---- console shell -------------------------------------------------- */
    /* Header, sidebar, page. Values are the reference's, by way of the
       design canvas's artboards: *AdminAccounts* for the staff console and
       *InvestorPortal* and *IntroducerPortal* for the external ones, which share
       this frame and differ only in what the nav lists. */
    .console { min-height: 100vh; display: flex; flex-direction: column; }

    /* v3 design: full-height sidebar, with the sticky bar inside the main column. */
    .hdr {
      display: flex; align-items: center; gap: 24px; height: 56px; padding: 0 40px;
      background: color-mix(in srgb, var(--bg-primary) 90%, transparent);
      backdrop-filter: blur(8px); border-bottom: 1px solid var(--border-color);
      position: sticky; top: 0; z-index: 40;
    }
    .hdr-mid { min-width: 0; margin-right: auto; }
    .search {
      display: flex; align-items: center;
      width: 360px; max-width: min(100%, 45vw); margin-right: auto; padding: 9px 16px 9px 38px;
      border-radius: var(--r-pill);
      border: 1px solid var(--border-color); background: var(--bg-secondary);
      color: var(--text-tertiary); font-size: 13px;
      font-family: inherit; text-align: left; cursor: text; position: relative;
    }
    .search > svg, .search > .ic { position: absolute; left: 16px; }
    .search:hover { border-color: var(--text-muted); color: var(--text-secondary); }
    .search .ic { flex-shrink: 0; }
    /* The ring .iconbtn takes, on the box: the field inside has no border to
       darken, so focused it would otherwise show nothing. */
    .search:focus-within { outline: 2px solid var(--accent-color); outline-offset: 2px; }
    /* The console's panel under the box: §Picker's .menu, its count line
       heading each kind and its rows for the results. The colour is restated
       because the box's hover would otherwise reach every hint in the panel,
       and the cursor because the box's text cursor would reach every row. */
    .search .menu { color: var(--text-tertiary); cursor: default; }
    .search .pcount { padding-top: 7px; }
    .search .popt { cursor: pointer; }
    .search .popt.off { cursor: default; }
    .search input {
      flex: 1; min-width: 0; border: 0; outline: 0; padding: 0;
      background: transparent; color: var(--text-primary);
      font-family: inherit; font-size: 13px; letter-spacing: inherit;
    }
    .search input::placeholder { color: var(--text-tertiary); }
    .iconbtn, .hamburger {
      display: flex; align-items: center; justify-content: center;
      width: 34px; height: 34px; border-radius: var(--r-nav);
      border: 0; background: transparent; color: var(--text-tertiary);
      cursor: pointer; font-family: inherit; flex-shrink: 0;
    }
    .iconbtn:hover, .hamburger:hover { background: var(--bg-hover); color: var(--text-primary); }
    .iconbtn:active, .hamburger:active { transform: scale(0.98); }
    .iconbtn:focus-visible, .hamburger:focus-visible, .history-month:focus-visible {
      outline: 2px solid var(--accent-color); outline-offset: 2px;
    }
    .hamburger { display: none; width: 38px; height: 38px; margin-left: -8px; color: var(--text-primary); }
    .ic { display: flex; }

    html:has(.shell-main) { scrollbar-gutter: stable; }
    .layout { flex: 1; display: flex; align-items: stretch; }
    .shell-main {
      flex: 1; min-width: 0; margin-left: 240px; border-left: 1px solid var(--border-color);
      display: flex; flex-direction: column; background: var(--bg-primary);
    }
    .sidebar {
      width: 240px; flex-shrink: 0; position: fixed; left: 0; top: 0; height: 100vh;
      background: var(--bg-primary); padding: 8px 16px 16px;
      display: flex; flex-direction: column;
      overflow-y: auto; overscroll-behavior: contain;
    }
    .sidebar-brand { display: flex; align-items: center; min-height: 48px; margin-bottom: 32px; flex-shrink: 0; }
    .sidebar-brand .logo-full { height: 41px; max-width: 100%; }
    .shell-nav, .funds-children { display: flex; flex-direction: column; gap: 4px; }
    .content { flex: 1; min-width: 0; padding: 48px 40px 96px; background: var(--bg-primary); }
    .page { min-width: 0; max-width: 1080px; margin: 0 auto; display: flex; flex-direction: column; gap: 20px; }
    /* An active item is literally a small card: it is the one thing in the
       sidebar that is raised, which is what makes it findable at a glance. */
    .navlink {
      display: flex; align-items: center; gap: 12px; width: 100%;
      padding: 10px 14px; border-radius: var(--r-nav);
      font-family: inherit; font-size: 14px; font-weight: 500; text-align: left;
      color: var(--text-tertiary); background: transparent; border: 0; cursor: pointer;
    }
    .navlink:hover { color: var(--text-primary); }
    /* On the server pages the item is a link: the ink is its hover (DESIGN-RULES §Nav item), not a link's underline. */
    a.navlink:hover { text-decoration: none; }
    .navlink.on { background: var(--sidebar-hover-bg); color: var(--text-primary); box-shadow: var(--shadow-sm); }
    .navlink svg { flex-shrink: 0; width: 16px; height: 16px; stroke-width: 1.5; }
    .navlink.navchild { padding: 3px 14px 3px 42px; font-size: 13px; font-weight: 500; letter-spacing: normal; gap: 10px; }
    .navchild .fund-name { min-width: 0; overflow: hidden; white-space: normal; overflow-wrap: anywhere; line-height: 1.3; max-height: 2.6em; }
    .funds-parent { list-style: none; cursor: pointer; }
    .funds-parent::-webkit-details-marker, .acct-chip::-webkit-details-marker { display: none; }
    .funds-label { display: flex; align-items: center; gap: 12px; flex: 1; color: inherit; }
    .funds-chevron { display: flex; margin-left: auto; color: var(--text-secondary); transition: transform .15s ease; }
    .funds-chevron svg { width: 14px; height: 14px; }
    .funds-group:not([open]) .funds-chevron { transform: rotate(-90deg); }
    /* Staff console v2: the More fold. 12px above it; its entries sit under
       the label, where the icons' text starts. */
    .navlink.navmore { margin-top: 12px; }
    .navmore-chevron { display: flex; margin-left: auto; transition: transform .15s ease; }
    .navmore-chevron.open { transform: rotate(180deg); }
    .navlink.navfold { padding-left: 42px; }

    /* Account menu measurements from the v3 design. */
    .acct { position: relative; flex-shrink: 0; }
    .acct-chip {
      display: flex; align-items: center; gap: 10px; background: transparent;
      padding: 4px 8px 4px 4px; border-radius: var(--r-pill); border: 0;
      font-family: inherit; color: var(--text-primary); cursor: pointer; list-style: none;
    }
    .acct-chip:focus-visible, .acct-row:focus-visible, .funds-parent:focus-visible {
      outline: 2px solid var(--accent-color); outline-offset: 2px;
    }
    .acct-label { display: flex; flex-direction: column; text-align: left; }
    .acct-name { font-size: 13px; font-weight: 500; white-space: nowrap; }
    .acct-area { font-size: 12px; color: var(--text-secondary); white-space: nowrap; }
    .acct-chevron { display: flex; color: var(--text-secondary); }
    .acct-menu {
      position: absolute; right: 0; top: calc(100% + 8px);
      width: max-content; min-width: 220px; max-width: calc(100vw - 32px);
      background: var(--bg-secondary); border-radius: var(--r-card); box-shadow: var(--shadow-sm);
      padding: 8px; display: flex; flex-direction: column; gap: 2px;
    }
    .acct-head { font-size: 12px; color: var(--text-secondary); padding: 8px 12px 10px; border-bottom: 1px solid var(--border-color); overflow-wrap: anywhere; }
    .acct-mobile-area { display: none; }
    .acct-row {
      display: block; font: inherit; font-size: 13px; text-align: left; color: var(--text-primary);
      padding: 8px 12px; border-radius: var(--r-nav); background: transparent; border: 0; cursor: pointer;
    }
    .acct-row:hover { color: var(--text-primary); text-decoration: none; background: var(--bg-hover); }
    /* DESIGN-RULES §Bell: the v3 design's *Latest updates*. A disclosure like
       the account menu, its summary a 40px round button with the count of
       unread lines, its panel a card of lines, each one form whose button is
       the whole line. The forms and buttons lose the browser's own boxes. */
    .bell > summary { list-style: none; position: relative; }
    .bell > summary::-webkit-details-marker { display: none; }
    .bell > summary.iconbtn { width: 40px; height: 40px; border-radius: var(--r-pill); color: var(--text-primary); }
    .bell > summary.iconbtn svg { stroke-width: 1.5; }
    .bell[open] > summary.iconbtn { background: var(--bg-hover); }
    .bell-count {
      position: absolute; top: 6px; right: 6px; min-width: 16px; height: 16px; padding: 0 4px;
      border-radius: var(--r-pill); background: var(--chart-orange); color: #ffffff;
      font-size: 10px; font-weight: 600; line-height: 16px; text-align: center;
      box-shadow: 0 0 0 2px var(--bg-primary);
    }
    .acct-menu.bell-menu {
      right: -8px; width: 360px; max-width: calc(100vw - 32px); padding: 0; gap: 0;
      max-height: calc(100vh - 96px); overflow-y: auto;
    }
    .bell-head {
      display: flex; justify-content: space-between; align-items: center;
      padding: 14px 16px; border-bottom: 1px solid var(--border-color);
      font-size: 14px; font-weight: 500;
    }
    .bell-menu form { display: contents; }
    .bell-readall {
      border: 0; padding: 0; background: none; font: inherit; cursor: pointer;
      font-size: 12px; font-weight: 400; color: var(--text-tertiary);
    }
    .bell-readall:hover { color: var(--text-primary); text-decoration: underline; }
    .bell-line {
      display: flex; gap: 12px; width: 100%; padding: 12px 16px; text-align: left;
      border: 0; border-bottom: 1px solid var(--border-color); background: var(--bg-secondary);
      font: inherit; color: var(--text-primary); cursor: pointer; text-decoration: none;
    }
    .bell-line:last-child, .bell-menu form:last-child .bell-line { border-bottom: 0; }
    .bell-line.act.unread { background: var(--accent-wash); }
    .bell-line:hover { background: var(--bg-tertiary); text-decoration: none; color: var(--text-primary); }
    .bell-line:focus-visible { outline: 2px solid var(--accent-color); outline-offset: -2px; }
    .bell-ico {
      display: flex; align-items: center; justify-content: center; flex-shrink: 0;
      width: 32px; height: 32px; border-radius: var(--r-pill);
      background: var(--bg-tertiary); color: var(--text-primary);
    }
    .bell-line.act .bell-ico { background: var(--chart-orange); color: #ffffff; }
    .bell-body { flex: 1; min-width: 0; display: flex; flex-direction: column; }
    .bell-meta { display: flex; justify-content: space-between; gap: 8px; margin-bottom: 2px; }
    .bell-kind { font-size: 12px; font-weight: 500; color: var(--text-tertiary); }
    .bell-line.act .bell-kind { color: var(--chart-orange); }
    .bell-when { font-size: 12px; color: var(--text-muted); white-space: nowrap; }
    .bell-text { font-size: 13px; line-height: 1.45; text-wrap: pretty; }
    .bell-dot { width: 6px; height: 6px; margin-top: 6px; flex-shrink: 0; border-radius: var(--r-pill); background: var(--chart-orange); }
    .avatar {
      display: flex; align-items: center; justify-content: center;
      width: 34px; height: 34px; border-radius: 50%; flex-shrink: 0;
      background: var(--bg-secondary); color: var(--text-tertiary);
      box-shadow: var(--ring-inset), rgba(0,0,0,.4) 0 0 1px; font-size: 12px; font-weight: 500;
    }

    /* `flex-wrap` is what keeps the four figures a block: without it a
       `.pgfigs` too wide for the space left beside the title wraps *inside
       itself* and leaves the fourth alone on a line, which is the shape
       §Page header says the four must never take. Wrapping here drops the
       whole block under the title instead, still four across. */
    .pghead {
      display: flex; align-items: flex-end; justify-content: space-between;
      flex-wrap: wrap; gap: 24px;
    }
    .pgsub { font-size: 14px; color: var(--text-tertiary); margin-top: 8px; }
    .pgtitle { font-size: 36px; font-weight: 400; letter-spacing: -0.02em; line-height: 1.1; }

    /* The console opens its drawer with a click handler and `.nav-open`; the
       external pages have no script and open it with a checkbox, which is the
       treatment DESIGN-RULES 5 Responsive names. Both are here because both
       shells are drawn from this one stylesheet, and the second is a rule
       about a page the first never renders. */
    .navtoggle { position: absolute; width: 0; height: 0; opacity: 0; pointer-events: none; }
    /* Above the breakpoint the hamburger it answers to is not drawn, so the box is no tab stop
       (DESIGN-RULES §8: nothing focusable is invisible). */
    @media (min-width: 901px) { .navtoggle { visibility: hidden; } }
    .navscrim { display: none; }

    /* ---- components ----------------------------------------------------
       Ported from the design canvas's BASE_CSS; their rules are written down
       in doc/DESIGN-RULES.md, which is now their only source. A component
       arrives with the screen that needs it, so that no untested CSS arrives
       ahead of anything rendering it. */

    /* ---- page header -------------------------------------------------- */
    .crumb {
      display: flex; align-items: center; gap: 8px;
      font-size: 13px; color: var(--text-tertiary); margin-bottom: 10px;
    }
    .crumb .sep { color: var(--text-muted); }
    .crumb .up { color: var(--text-tertiary); cursor: pointer; }
    .crumb .up:hover { color: var(--text-primary); text-decoration: underline; }
    /* DESIGN-RULES "Page header": a header may carry figures, and then it
       carries their foot as well. Two rules here already selected `.pgfigs`
       for the definition bubble before the component itself existed in this
       stylesheet; these are the component, ported from the canvas unchanged. */
    .pgfigs { display: flex; gap: 48px; flex-wrap: wrap; }
    .pgfig-k { font-size: 12px; color: var(--text-tertiary); margin-bottom: 4px; }
    .pgfig-v { font-size: 22px; font-weight: 500; letter-spacing: -0.01em; font-variant-numeric: tabular-nums; }
    /* A figure's note, under it, as §Stat's .strip-n: a strip moved into the
       header keeps every note it had. */
    .pgfig-n { font-size: 12px; color: var(--text-tertiary); margin-top: 4px; }
    .pgfigs-ft { margin-top: 12px; font-size: 12px; color: var(--text-tertiary); line-height: 1.5; }
    .pgfigs-ft .dot { color: var(--text-muted); margin: 0 7px; }
    .pgactions { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }
    /* The same row at the foot of a wizard step, where there is no title to
       sit beside and so nothing to push it right. DESIGN-RULES "Wizard action
       bar": a page's actions, at the end of the page rather than beside its
       heading — not a second shape. */
    .pgactions.end { justify-content: flex-end; }
    /* A card head's acts never run past the card: on their own line they shrink to it and wrap. */
    .card-hd > .pgactions { flex-shrink: 1; min-width: 0; }
    .btn.sm { padding: 7px 14px; font-size: 13px; }
    /* DESIGN-RULES "Two actions on one row": the page header's action gap. */
    .tbl td .btn.sm + .btn.sm { margin-left: 10px; }
    /* Inside a row that already sets its gap (.rowacts, .pgactions, .xacts) the gap is the whole distance. */
    .tbl td :is(.rowacts, .pgactions, .xacts, .plat) .btn.sm + .btn.sm { margin-left: 0; }
    .btn.danger { color: var(--error-text); border-color: var(--error-bg); }
    /* No border. The shadow's first layer is a 1px spread at 40% black, which
       draws a sharper edge than a border does and does not double up with the
       rules inside the card. */
    .card {
      background: var(--bg-secondary); border: 0;
      border-radius: var(--r-card); box-shadow: var(--shadow-sm); overflow: hidden;
    }
    /* the card clips so a table's corners follow its radius, but an open
       dropdown is allowed out: a menu whose last options are cut off is worse
       than a corner that is briefly square */
    .card:has(.sel[open]) { overflow: visible; }
    .card-hd {
      display: flex; align-items: center; justify-content: space-between; gap: 12px;
      padding: 18px 24px; border-bottom: 1px solid var(--border-color);
    }
    .card-hd h3 { font-size: 16px; font-weight: 500; letter-spacing: -0.01em; }
    .card-hd .meta { font-size: 13px; color: var(--text-tertiary); }
    .card-bd { padding: 24px; }
    .card-ft {
      padding: 16px 24px; border-top: 1px solid var(--border-color);
      background: var(--bg-tertiary); font-size: 13px; color: var(--text-tertiary);
    }
    /* A foot that carries an action as well as a sentence. Without it the two
       are block-level and touch. */
    .card-ft.row {
      display: flex; align-items: center; justify-content: space-between;
      gap: 16px; flex-wrap: wrap;
    }
    /* The end of the rows, inside the box that scrolls — which is the point: a
       button under the card would sit still while the rows moved past it. It is
       what the reader arrives at rather than something they go looking for, so
       it states what is about to happen instead of asking. */
    .tblmore {
      display: flex; align-items: center; justify-content: center; gap: 10px;
      padding: 16px 24px 18px; font-size: 12px; color: var(--text-tertiary);
      border-top: 1px solid var(--border-color); cursor: pointer;
    }
    .tblmore .dots { display: inline-flex; gap: 4px; }
    .tblmore .dots i {
      width: 5px; height: 5px; border-radius: 50%; background: var(--text-tertiary);
      opacity: 0.45; display: block;
    }
    .tblmore .dots i:nth-child(2) { opacity: 0.7; }
    .tblmore .dots i:nth-child(3) { opacity: 1; }
    .grid2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px; }
    /* Side by side the two cards are one height, so a foot sits at the bottom of
       its card rather than under the shorter one's last row. */
    .grid2 > .card { display: flex; flex-direction: column; }
    .grid2 > .card > .card-ft { margin-top: auto; }
    /* Two cards whose lengths are their own: each as tall as what it holds. */
    .grid2.top { align-items: start; }
    .grid3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px; }
    .grid4 { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 20px; }
    .cols { display: flex; gap: 20px; align-items: flex-start; }
    /* Still a grid — strip() writes its column count inline and the foot spans
       1 / -1 — but no longer a bordered box. The reference states its headline
       figures as bare label-over-number pairs standing on the page, so the card,
       the rules and the shadow all come off and only the spacing separates them. */
    .strip {
      display: grid; gap: 4px 36px;
      background: transparent; border: 0;
      border-radius: 0; box-shadow: none; overflow: visible;
    }
    .strip-cell { padding: 0; border-left: 0; }
    .strip-k {
      font-size: 12px; font-weight: 400; letter-spacing: 0;
      text-transform: none; color: var(--text-tertiary);
    }
    .strip-v { font-size: 22px; font-weight: 500; margin-top: 5px; letter-spacing: -0.01em; }
    .strip-v.lg { font-size: 26px; }
    /* Seven or more across. The figures come down to the body size and the
       strip gains the hairline the reference draws above its eight-cell row. */
    .strip.wide { gap: 4px 12px; padding-top: 20px; border-top: 1px solid var(--border-color); }
    .strip.wide .strip-v { font-size: 14px; margin-top: 4px; }
    .strip.wide .strip-n { font-size: 11px; margin-top: 4px; }
    .strip-v .na { font-style: italic; font-weight: 400; color: var(--text-tertiary); font-size: 14px; }
    .strip-n { font-size: 12px; color: var(--text-tertiary); margin-top: 5px; }
    .strip-foot {
      grid-column: 1 / -1; padding: 12px 0 0; margin-top: 10px;
      border-top: 1px solid var(--border-color); background: transparent;
      font-size: 12px; color: var(--text-tertiary); line-height: 1.55;
    }
    /* ---- tabs --------------------------------------------------------- */
    .tabs {
      display: flex; gap: 2px; align-items: flex-end;
      border-bottom: 1px solid var(--border-color);
    }
    .tab {
      padding: 10px 14px 11px; font-size: 14px; font-weight: 500;
      color: var(--text-tertiary); cursor: pointer;
      border: 0; border-bottom: 2px solid transparent; background: transparent;
      font-family: inherit; margin-bottom: -1px;
    }
    .tab:hover { color: var(--text-primary); }
    /* A tab that is a link (the server pages): §Tabs' hover is the ink and nothing else. */
    a.tab:hover { text-decoration: none; }
    .tab.on { color: var(--text-primary); border-bottom-color: var(--accent-color); }
    /* DESIGN-RULES "Segment": a row of small pills that pick one reading or
       narrow a list to one kind, the chosen one in the primary fill, each a
       link carrying its query. It is the sub-view switch above with a count
       and let out of the tab row; a screen being redrawn takes this one.
       The count is muted in both states — on the black pill the same grey
       stands at 8:1 — so one rule serves and the count does not change
       colour when the choice does. */
    .segment { display: inline-flex; flex-wrap: wrap; gap: 6px; }
    .segment .ct, .morebtn .ct { color: var(--text-muted); font-weight: 400; font-variant-numeric: tabular-nums; }
    /* A tab's count, as the segment's: DESIGN-RULES §Tabs. */
    .tab .ct { color: var(--text-muted); font-weight: 400; }
    /* A section an in-page link lands on stops under the sticky bar rather
       than behind it: 56px of bar and the content's 24px gutter, which is the
       offset .lg-sec already carries for the legal pages. */
    .jump { scroll-margin-top: 80px; }

    /* §7: a calculated zero. A real figure, drawn quieter than a measured
       one, because the test was run and the answer was none. */
    .calc0 { color: var(--text-secondary); }
    /* A table is as tall as its rows and the page scrolls, in the console as
       in the portal (DESIGN-RULES §Table, 7 Oct 2026): no list scrolls inside
       its card, and its headings, sticky to a box that does not scroll down,
       travel with the page. A wide table moves sideways inside the card's
       width. The one table read in a box of its own is the matrix, below. */
    .tblw { overflow: auto; }
    /* The box is the whole of a rounded card, so its scrollbar runs into the card's corners, and
       the wider the bar the more of its ends they cut (§The browser's own parts). The browser's
       thin one is asked for; nothing about it is drawn here. */
    .tblw { scrollbar-width: thin; }
    .tbl { width: 100%; border-collapse: collapse; }
    /* A column heading is a label, not a klaxon: sentence case at 12px on the
       card's own ground, separated by one hairline. The old shouted version —
       uppercase, letterspaced, on a grey band under a 2px rule — competed with
       the figures it was introducing. */
    .tbl th {
      padding: 12px 16px; text-align: left;
      font-size: 12px; font-weight: 500; letter-spacing: 0;
      text-transform: none; color: var(--text-tertiary);
      background: var(--table-header-bg);
      border-bottom: 1px solid var(--border-color); white-space: nowrap;
      position: sticky; top: 0; z-index: 2;
    }
    .tbl td {
      padding: 13px 16px; font-size: 14px;
      border-bottom: 1px solid var(--border-color); vertical-align: middle;
    }
    .tbl.dense th, .tbl.dense td { padding-left: 10px; padding-right: 10px; }
    .tbl.dense .vehicle-name { min-width: 240px; width: 270px; padding-left: 16px; }
    .tbl.dense .vehicle-title { line-height: 1.4; }
    .tbl.dense .num { white-space: nowrap; }
    .tbl.dense td .sub { display: block; }
    .tbl.dense .vehicle-counts { margin-top: 3px; }
    .tbl tbody tr:last-child td { border-bottom: 0; }
    .tbl tbody tr.clickable { cursor: pointer; }
    .tbl tbody tr.clickable:hover td { background: var(--bg-tertiary); }
    .tbl .r { text-align: right; }
    .tbl .c { text-align: center; }
    .tbl .num { text-align: right; font-variant-numeric: tabular-nums; }
    .tbl .strong td, .tbl td.strong { font-weight: 600; }
    .tbl tr.total td {
      font-weight: 600; background: var(--bg-tertiary);
      border-top: 1px solid var(--border-color); border-bottom: 0;
    }
    .tbl tr.sub td {
      font-size: 12.5px; color: var(--text-tertiary);
      padding-top: 0; padding-bottom: 11px; border-bottom: 1px solid var(--border-color);
    }
    /* The row a sentence belongs to carries no rule of its own: the sentence closes it. */
    .tbl tr:has(+ tr.sub > td[colspan]) td { border-bottom: 0; }
    /* A heading row that names the group of rows beneath it. It is a row and not
       a separate table, so one filter bar governs the whole list — but not one
       sort: a list already arranged into sections is arranged, and reordering it
       by a column would dissolve them. */
    .tbl tr.sect td {
      font-size: 12px; font-weight: 500; color: var(--text-tertiary);
      padding: 26px 16px 8px; border-bottom: 1px solid var(--border-color);
    }
    .tbl tbody tr.sect:first-child td { padding-top: 6px; }
    /* A sortable heading is the heading, not a control beside it: the whole
       cell is the target, and the caret only says which way it is going. An
       unsorted column keeps its caret faint rather than hidden, so a header
       row is not a row of arrows. */
    .tbl th.srt { cursor: pointer; user-select: none; }
    .tbl th.srt:hover { color: var(--text-primary); }
    /* Faint but present at rest, not revealed on hover: a touch screen has no
       hover, and an affordance nobody can see is not one. */
    .tbl th.srt .cv { opacity: 0.22; margin-left: 6px; font-size: 9px; font-weight: 400; vertical-align: 1px; }
    .tbl th.srt:hover .cv { opacity: 0.5; }
    .tbl th.srt.on { color: var(--text-primary); }
    .tbl th.srt.on .cv { opacity: 1; }
    /* Right-aligned columns carry the caret on the left of the figure, so the
       figures stay flush with the ones below them. */
    .tbl th.srt.r .cv, .tbl th.srt.num .cv { margin: 0 6px 0 0; }
    /* With scripting off a sort is a link, and the whole cell is still the
       target: the anchor fills its heading rather than sitting inside it, and
       takes no colour and no underline of its own, so a sortable heading and a
       pressable one look the same on both surfaces. */
    .tbl th.srt > a { display: block; color: inherit; text-decoration: none; }
    .tbl th.srt.num > a, .tbl th.srt.r > a { text-align: right; }
    /* The server draws the caret after the words of a right-aligned heading that is not a figure
       (Status); §Table puts it in front, so the words stay flush with the cells under them. */
    .console.portal .tbl th.srt.r > a { display: flex; justify-content: flex-end; align-items: baseline; }
    .console.portal .tbl th.srt.r > a .cv { order: -1; }
    /* A figure a person set is italic and one accepted as proposed is roman —
       never a colour and never a badge, because the distinction is on every
       cell of a hundred-and-twenty-cell grid and anything louder would drown
       the figures it is annotating. It is not .est, which draws nothing:
       that says a figure was derived, this says who put it there.
       A cell that opens the panel behind it is a button drawn as the text it
       replaces, with the affordance only under the pointer, for the same
       reason — and a focus ring, because a control reachable only by pointer is
       not reachable. */
    .tbl .set { font-style: italic; }
    .tbl button.cell, .company-metric-value button.cell {
      background: none; border: 0; padding: 0; font: inherit; color: inherit;
      text-align: inherit;
      font-variant-numeric: tabular-nums; cursor: pointer; border-radius: 4px;
    }
    .tbl button.cell:hover, .company-metric-value button.cell:hover { background: var(--bg-hover); text-decoration: underline; }
    .tbl button.cell:focus-visible { outline: 2px solid var(--accent-color); outline-offset: 2px; }
    /* A row's tick (§Table): the browser's own box, in the product's ink rather than the browser's blue. */
    .tbl input[type="checkbox"] { accent-color: var(--accent-color); }
    /* A row's tick is a control the keyboard reaches: it takes the product's ring and not the
       browser's own (DESIGN-RULES §8, Keyboard focus; §Table, A row's tick). */
    .tbl input[type="checkbox"]:focus-visible { outline: 2px solid var(--accent-color); outline-offset: 2px; }
    /* A reason, without leaving the page and without script: the dash (or the
       nought) is the trigger, hover or focus opens it. It opens downwards because .tblw
       scrolls and would clip anything opening up out of the header. The four
       edge rules below were here without these; a bubble whose base rule lives
       in the other implementation is a bubble that never appears. */
    .def { position: relative; text-decoration: underline dotted; text-underline-offset: 3px; cursor: help; }
    .def > .dfb {
      position: absolute; top: calc(100% + 8px); left: 0; z-index: 30;
      width: 260px; padding: 12px 14px; border-radius: var(--r-nav);
      background: var(--bg-secondary); box-shadow: var(--shadow-md);
      font-size: 12px; font-weight: 400; font-style: normal; line-height: 1.5;
      color: var(--text-tertiary); text-align: left; text-transform: none;
      letter-spacing: 0; white-space: normal; text-decoration: none;
      display: none; opacity: 0; transition: opacity .12s ease, display .12s allow-discrete;
    }
    .def > .dfb b { display: block; color: var(--text-primary); font-weight: 500; margin-bottom: 3px; }
    /* Closed, the bubble is not drawn at all: a hidden one still counted toward
       .tblw's overflow and gave a two-row table a scrollbar. */
    .def:hover > .dfb, .def:focus > .dfb, .def:focus-visible > .dfb { display: block; opacity: 1; }
    @starting-style { .def:hover > .dfb, .def:focus > .dfb, .def:focus-visible > .dfb { opacity: 0; } }
    /* Near the right edge the bubble would run off the card, so it hangs from
       the right instead. Anywhere it could still be too wide for what holds it —
       a phone, a narrow figure column — it takes that width instead of its own. */
    .tbl .r .def > .dfb, .tbl .num .def > .dfb, .tbl .c .def > .dfb,
    .pgfigs > .last .def > .dfb,
      .strip > .last .def > .dfb { left: auto; right: 0; }
    /* A table's last rows have no table under them to open into, and the scroll box cut the
       bubble there: the reason for a dash in the last row could not be read. From the third row
       on, the last two open upwards, into the rows above them. The portal's rule, and the staff
       console's since its tables carry the same dash (DESIGN-RULES §Definition on a label). */
    @media (min-width: 901px) {
      .console .tbl tbody > tr:nth-last-child(-n+2):nth-child(n+3) .def > .dfb { top: auto; bottom: calc(100% + 8px); }
      /* A table of one or two rows has no rows above them either: its scroll box and its card
         let the bubble out, as a card does an open dropdown. */
      .console :is(.card, .tblw):has(.tbl tbody > tr:nth-last-child(-n+2):not(:nth-child(n+3)) .def:is(:hover, :focus)) { overflow: visible; }
    }
    /* A figure in a card and outside a table — a strip, a tile, a field's value — opens its bubble
       over the card's foot and past its edge, which the card clipped. As for an open dropdown
       (.card:has(.sel[open])): the card lets it out. */
    .console .card:has(.def:is(:hover, :focus)):not(:has(.tbl .def:is(:hover, :focus))) { overflow: visible; }
    /* The last fact in a dialog's body has only the body's scroll box under it: its bubble opens
       upwards, as a table's last rows do. */
    .dlg .card-bd > :last-child .kv:last-child .def > .dfb, .dlg .card-bd > .kv:last-child .def > .dfb { top: auto; bottom: calc(100% + 8px); }
    /* The staff console's head figures stand at the right of the title, up to six of them: every
       one of their bubbles hangs from its right edge, not only the last one's. */
    @media (min-width: 901px) { .staff-page .v3-head .pgfigs:not(.under) .def > .dfb { left: auto; right: 0; } }
    .tbl .lead { font-weight: 500; }
    .tbl td .sub { font-weight: 400; font-size: 12px; color: var(--text-tertiary); margin-top: 3px; }
    .tbl .muted { color: var(--text-tertiary); }

    /* Two rows of <th> and not one row of merged cells: the first names the
       groups, the second names the leaves, and a left hairline is the whole of
       the separation between one group and the next. Such a table is never
       sortable — a group cannot be ordered by one of its leaves — which is why
       .grp carries no .srt affordance. */
    .tbl th.grp {
      text-align: center; border-bottom: 1px solid var(--border-color);
      border-left: 1px solid var(--border-color); color: var(--text-secondary);
    }
    .tbl th.gsub { font-weight: 500; }
    .tbl th.bl, .tbl td.bl { border-left: 1px solid var(--border-color); }
    .tbl td.pos { color: var(--positive-text); }
    .tbl td.neg { color: var(--negative-text); }
    /* One row standing for rows that are not drawn, or for a set the table
       names and does not list. Italic on the tinted ground, so it reads as an
       aside rather than as another record. */
    .tbl tr.gap td {
      color: var(--text-tertiary); font-style: italic; background: var(--bg-tertiary);
      /* Never a figure, whatever column it starts in: the text is a heading
         over the rows below it, and a heading reads from the left. */
      text-align: left;
    }
    /* DESIGN-RULES "Figure table", Group row: the total row that opens a
       group, with a chevron in front of its name. The first cell's link is the
       control — it carries the group's key in ?open= and the page comes back
       with that group open, so it works with no script. A closed group is
       that one row; the hairline below it is what separates an open group
       from its first row, since the total above drops its own. The chevron
       is .sel's, turned 90° rather than 180°, over the caret's .15s. */
    .tbl tr.group td { border-bottom: 1px solid var(--border-color); }
    .tbl tr.group > td:first-child a {
      display: flex; align-items: center; gap: 10px; color: inherit; text-decoration: none;
    }
    .tbl tr.group > td:first-child a:hover { text-decoration: underline; }
    .tbl tr.group .chev {
      display: flex; flex-shrink: 0; width: 14px; height: 14px;
      color: var(--text-secondary); transition: transform .15s ease;
    }
    .tbl tr.group.open .chev { transform: rotate(90deg); }
    /* DESIGN-RULES §Group row, the console's year: the count beside the year
       rather than under it, and the row on the tinted ground at 500. */
    .tbl tr.group.yr td { font-weight: 500; background: var(--bg-tertiary); }
    /* DESIGN-RULES §Group row, a batch fund's group (D-65): its funds stand
       under the name, past the chevron and its gap (14 + 10px) from the
       console's 6px cell. */
    .v3-page .tbl tr.inbatch > td:first-child { padding-left: 30px; }
    .tbl tr.group.yr > td:first-child a > div { display: flex; align-items: baseline; gap: 8px; }
    .tbl tr.group.yr > td:first-child .sub { margin-top: 0; }
    /* Three counts in one cell, in a fixed order, under a heading that says
       which is which. Active is the one still at risk, exited the one that
       came back, written off the one that did not — so the three take the
       warning, success and tertiary inks rather than three arbitrary hues. */
    /* A date in a table of many narrow columns. Several columns of dates each
       break over two lines at the browser's own widths, which turns a table
       read across into a table read down; this refuses the break and lets the
       wrapper scroll, which is what it is for. */
    .tbl .dt { white-space: nowrap; }
    /* A short name or token read as one thing — an actor, a role's code — refuses the break too. */
    .tbl .nw { white-space: nowrap; }
    /* The column that takes what the others leave: a short table's columns then stand together
       at the left instead of spreading a figure away from its row's name. */
    .tbl th.rest { width: 100%; }
    /* DESIGN-RULES §2: an event type in a log is a machine token — Geist Mono, at the 12px a
       mono field takes (§Input). */
    .tbl td.evt { font-family: var(--font-mono); font-size: 12px; white-space: nowrap; }
    .tbl .aec { font-variant-numeric: tabular-nums; white-space: nowrap; }
    .tbl .aec b { font-weight: 600; }
    .tbl .aec .a { color: var(--warning-text); }
    .tbl .aec .e { color: var(--success-text); }
    .tbl .aec .z { color: var(--text-tertiary); }
    /* the phone-only half of a group heading, and the line that says how many
       columns a phone is not showing: both absent at this width */
    .tbl th.mo { display: none; }
    .mcols {
      display: none; padding: 10px 14px;
      border-top: 1px solid var(--border-color); background: var(--bg-tertiary);
      font-size: 11.5px; line-height: 1.5; color: var(--text-tertiary);
    }
    /* ---- status dot / fund orb --------------------------------------- */
    /* A vehicle's identity, or a state too small for a word. Never alone: the
       name it belongs to is always beside it. In a table cell it leads that
       name and carries its own gap; in a flex row the row supplies one, so the
       margin is scoped to the cell. A vehicle's is its orb (DESIGN-RULES §Fund
       orb): twelve slots, one per cohort, each a still of the orb
       /assets/orb.js draws live on the fund's own page. A draft has no slot and
       stays the muted grey circle — an orb would say it has an identity it has
       not been given yet. */
    .vdot {
      display: inline-block; width: 12px; height: 12px;
      border-radius: 50%; flex-shrink: 0;
      background: var(--text-muted) center / cover no-repeat;
    }
    .vdot.v0, .vdot.v1, .vdot.v2, .vdot.v3, .vdot.v4, .vdot.v5,
    .vdot.v6, .vdot.v7, .vdot.v8, .vdot.v9, .vdot.v10, .vdot.v11 { background-color: transparent; }
    .vdot.v0 { background-image: url(/assets/orbs/orb-0.png); }
    .vdot.v1 { background-image: url(/assets/orbs/orb-1.png); }
    .vdot.v2 { background-image: url(/assets/orbs/orb-2.png); }
    .vdot.v3 { background-image: url(/assets/orbs/orb-3.png); }
    .vdot.v4 { background-image: url(/assets/orbs/orb-4.png); }
    .vdot.v5 { background-image: url(/assets/orbs/orb-5.png); }
    .vdot.v6 { background-image: url(/assets/orbs/orb-6.png); }
    .vdot.v7 { background-image: url(/assets/orbs/orb-7.png); }
    .vdot.v8 { background-image: url(/assets/orbs/orb-8.png); }
    .vdot.v9 { background-image: url(/assets/orbs/orb-9.png); }
    .vdot.v10 { background-image: url(/assets/orbs/orb-10.png); }
    .vdot.v11 { background-image: url(/assets/orbs/orb-11.png); }
    .tbl td .vdot { margin-right: 8px; vertical-align: -1px; }
    .vdot.fund-orb { display: block; width: 72px; height: 72px; overflow: hidden; }
    ff-orb.fund-orb canvas { display: block; width: 100%; height: 100%; border-radius: 50%; }

    /* A pill in sentence case. Uppercase at 11px is the loudest thing a table
       row can contain, and a status is rarely the most important thing in it. */
    .badge {
      display: inline-block; padding: 3px 10px; border-radius: var(--r-pill);
      font-size: 11.5px; font-weight: 500; text-transform: none;
      letter-spacing: 0; white-space: nowrap;
    }
    .badge.neutral { background: var(--badge-bg); color: var(--badge-text); }
    .badge.ok      { background: var(--success-bg); color: var(--success-text); }
    .badge.warn    { background: var(--warning-bg); color: var(--warning-text); }
    .badge.bad     { background: var(--error-bg); color: var(--error-text); }
    .badge.info    { background: var(--info-bg); color: var(--info-text); }
    /* ---- portal access ------------------------------------------------ */
    /* A badge, the date it is about, and the one thing to do about it. The one
       line on a party's record that staff do not type. */
    .plat { display: inline-flex; align-items: center; gap: 8px; }
    .plat-n { font-size: 12px; color: var(--text-tertiary); white-space: nowrap; }
    /* In a field card's cell the act drops under the state rather than breaking its date. */
    .fg-v .plat { flex-wrap: wrap; row-gap: 6px; }
    /* What a marked value does not fit (*Wrong form*) is that value's own second line: under the
       form and its badge at every width, 2px below, and folding inside the cell — beside the
       badge it fitted a 329px cell and dropped out of a 240px one. */
    .fg-v > .plat-n { display: block; margin-top: 2px; white-space: normal; }
    /* Faded, not absent: it stays in the tab order, so the keyboard reaches it
       and its own :focus brings it back into view. Only inside a table — on a
       detail page there is no row to hover, so the button is simply there.
       And only where there is a pointer that can hover: on a touch screen
       there is no hover state to reveal it with, so it stays visible rather
       than becoming a control nobody can find. */
    @media (hover: hover) and (pointer: fine) {
      .tbl .plat .btn { opacity: 0; transition: opacity .12s ease; }
      .tbl tr:hover .plat .btn,
      .tbl .plat .btn:focus, .tbl .plat .btn:focus-visible { opacity: 1; }
    }
    /* ---- company mark ------------------------------------------------- */
    /* A round mark beside a company name: its logo where the firm holds one, its
       initials on a colour derived from the name where it does not. The inset
       ring keeps a white logo from dissolving into a white card. */
    .cmark {
      display: inline-flex; align-items: center; justify-content: center;
      border-radius: 50%; flex-shrink: 0; overflow: hidden;
      background-size: cover; background-position: center;
      box-shadow: var(--ring-inset);
      color: #ffffff; font-weight: 500; letter-spacing: 0.01em;
    }
    .cname { display: flex; align-items: center; gap: 10px; min-width: 0; }
    .cname .sub { font-weight: 400; font-size: 12px; color: var(--text-tertiary); margin-top: 3px; }
    .pos { color: var(--positive-text); font-weight: 500; }
    .neg { color: var(--negative-text); font-weight: 500; }
    .mono { font-variant-numeric: tabular-nums; }
    .na  { font-style: italic; color: var(--text-tertiary); }
    .muted { color: var(--text-tertiary); }
    .kv { display: flex; flex-direction: column; gap: 5px; }
    .kv-k { font-size: 12px; color: var(--text-tertiary); }
    .kv-v { font-size: 14px; }
    /* DESIGN-RULES "Key/value row", side by side: on a record page the card
       is the list of facts, so the label takes a column and the rows run the
       width of the card with a table's hairline between them. The third
       column is a slot for a badge or a small button, empty otherwise. On a
       phone the column goes and it is the stacked row again. */
    .kvside {
      display: grid; grid-template-columns: 200px minmax(0, 1fr) auto;
      gap: 16px; align-items: center; min-height: 48px; padding: 0 24px;
      border-bottom: 1px solid var(--border-color); font-size: 13.5px;
    }
    .kvside:last-child { border-bottom: 0; }
    .kvside .k { color: var(--text-secondary); }
    /* The portal's record cards: a value that wraps (an agreement's terms) keeps the row's air and
       reads at §2's 1.5; a one-line row is still the 48px it was. */
    @media (min-width: 901px) { .console.portal .kvside { padding-block: 8px; line-height: 1.5; } }
    @media (max-width: 900px) { .console.portal .kvside > :not(.k) { line-height: 1.5; } }
    .fields { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px 24px; }
    .fields.one { grid-template-columns: minmax(0, 1fr); }
    .fields.three { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    /* Field grids that follow one another in a card keep the grid's own row gap between them. */
    .card-bd > .fields + .fields { margin-top: 18px; }
    /* …and so does a single field that stands before or after one. A dialog's body sets its own gap. */
    .card-bd > .field + .field, .card-bd > .field + .fields, .card-bd > .fields + .field { margin-top: 18px; }
    .dlg .card-bd > .field + .field, .dlg .card-bd > .field + .fields, .dlg .card-bd > .fields + .field { margin-top: 0; }
    /* A form's parts down a card — grids, checks, a file field — at the grid's row gap. */
    .formstack { display: flex; flex-direction: column; gap: 18px; }
    /* A field with the one act on it at its right end (Remove): the act is as tall as the field. */
    .field-act { display: flex; align-items: flex-end; gap: 8px; }
    .field-act > .field { flex: 1 1 auto; min-width: 0; }
    .field-act > .btn.sm { height: 39px; padding-top: 0; padding-bottom: 0; flex-shrink: 0; }
    .prose { font-size: 13.5px; line-height: 1.65; color: var(--text-secondary); }
    .prose strong { color: var(--text-primary); font-weight: 600; }
    /* rows of figures that read downward, as in the capital position */
    /* ---- event log ------------------------------------------------------ */
    /* An append-only history down a rail. The ring on the dot is what lets the
       rail pass behind it without touching, and the rail is clipped at the
       first and last row so it begins and ends at an event. */
    .slog { display: flex; flex-direction: column; }
    .slog-row {
      display: grid; grid-template-columns: 96px 22px minmax(0, 1fr) auto;
      gap: 0 4px; align-items: start; font-size: 13.5px;
    }
    .slog-d { color: var(--text-tertiary); font-size: 12.5px; padding: 14px 0; white-space: nowrap; }
    .slog-rail { position: relative; display: flex; justify-content: center; align-self: stretch; }
    .slog-rail::before {
      content: ''; position: absolute; top: 0; bottom: 0;
      width: 1px; background: var(--border-color);
    }
    .slog-row:first-child .slog-rail::before { top: 20px; }
    .slog-row:last-child .slog-rail::before { bottom: calc(100% - 20px); }
    .slog-dot {
      width: 9px; height: 9px; border-radius: 50%; margin-top: 16px;
      position: relative; box-shadow: 0 0 0 3px var(--bg-secondary);
    }
    .slog-b { padding: 13px 0 13px 8px; }
    .slog-t { font-weight: 500; }
    .slog-x { font-size: 12.5px; color: var(--text-tertiary); margin-top: 3px; line-height: 1.55; }
    .slog-r { padding: 13px 0; text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }

    .ladder { display: flex; flex-direction: column; }
    .ladder-row {
      display: grid; grid-template-columns: minmax(0, 1fr) 150px 160px;
      gap: 16px; padding: 9px 0; font-size: 14px; align-items: baseline;
    }
    .ladder-row .amt { text-align: right; font-variant-numeric: tabular-nums; }
    .ladder-row .why { font-size: 12.5px; color: var(--text-tertiary); }
    .ladder-row.rule { border-top: 1px solid var(--border-color); margin-top: 6px; padding-top: 14px; }
    .ladder-row.sum { font-weight: 600; }
    /* A ladder in a narrow card cannot hold three columns: 150 + 160 + two 16px
       gaps is 342px, and a 320px aside gives it 278. Same shape as the phone
       rule below — two columns with the reason on its own line. */
    .ladder.narrow .ladder-row { grid-template-columns: minmax(84px, 1fr) auto; gap: 3px 12px; }
    .ladder.narrow .ladder-row .why { grid-column: 1 / -1; }
    /* Ruled ladder: the breakdown in a field card. A hairline above every line but the first, the
       rule over a total in ink, and the reason after its label instead of under it. */
    .ladder.ruled .ladder-row { display: flex; align-items: baseline; gap: 8px; }
    .ladder.ruled .ladder-row + .ladder-row { border-top: 1px solid var(--border-color); }
    .ladder.ruled .ladder-row.rule { margin-top: 0; padding-top: 9px; }
    .ladder.ruled .ladder-row.rule.sum { border-top-color: var(--text-primary); }
    .ladder.ruled .ladder-row.quiet > :first-child { color: var(--text-tertiary); }
    .ladder.ruled .ladder-row .why { order: 1; flex: 1 1 0; min-width: 0; }
    .ladder.ruled .ladder-row .amt { order: 2; flex: none; }
    .callout {
      border: 1px solid var(--border-color); border-radius: 10px;
      padding: 14px 16px; background: var(--bg-tertiary);
      font-size: 13.5px; line-height: 1.6; color: var(--text-tertiary);
    }
    .callout.warn { background: var(--warning-bg); border-color: transparent; color: var(--warning-text); }
    .callout.info { background: var(--info-bg); border-color: transparent; color: var(--info-text); }
    /* Whose screen this is, on every page of a view-as. DESIGN-RULES "View-as
       banner" — the callout's warn fill and ink, laid out on the header's own
       24px gutter and above it, because a bar that scrolled away would be a
       reminder only for the first screenful. Not sticky and it does not need to
       be: it is the first child of .console and the header below it is what
       sticks, so the bar leaves and comes back with the top of the document. */
    .viewbar {
      margin-left: 240px;
      display: flex; align-items: center; justify-content: space-between; gap: 12px;
      padding: 10px 24px; background: var(--warning-bg); color: var(--warning-text);
      font-size: 13.5px; line-height: 1.6;
    }
    .viewbar-who { font-weight: 600; }
    /* The button borrows the bar's ink rather than the page's, which is the
       one place a .btn does: on a tinted bar the default border and label are
       two shades of somebody else's palette. */
    .viewbar .btn { color: var(--warning-text); border-color: var(--warning-text); }
    /* A short list of named things inside somebody else's card: an icon, the
       name, one note at the right end, no action. DESIGN-RULES "In-card list"
       — and deliberately not the external portal's document list, which has a
       card of its own, a 34px chip and a button on every row. */
    .doclist { display: flex; flex-direction: column; }
    .doc {
      display: flex; align-items: center; gap: 12px; padding: 12px 0;
      border-bottom: 1px solid var(--border-color); font-size: 14px;
    }
    .doc:last-child { border-bottom: 0; }
    .doc .ico { color: var(--text-tertiary); flex-shrink: 0; display: flex; }
    .doc .nm { flex: 1; min-width: 0; }
    /* The line under a name, as a table's lead cell writes it. */
    .doc .nm .sub { font-weight: 400; font-size: 12px; color: var(--text-tertiary); margin-top: 3px; }
    .doc .sz { font-size: 12.5px; color: var(--text-tertiary); }
    /* ---- document list ------------------------------------------------ */
    /* DESIGN-RULES "Document list", and the list the sentence above says the
       one over it is not: a card of its own, a 34px chip, a meta line and an
       action on every row. Not a table — a document has a name, a line of
       provenance and one thing you can do with it, and three of those do not
       want columns. The group heading is outside the card so it is not read as
       a first row, and it is the h2 a step down from a section heading's 18px
       because it divides one list rather than the page. Ported from
       the design canvas unchanged. */
    /* DESIGN-RULES §Card: the section heading between blocks. It stands in the
       page's 20px column gap, and the margin makes that 32px above and 16px
       below (§Rhythm). The portal's capacity heading is this, with a record's
       name. */
    h2.sec { margin: 12px 0 -4px; font-weight: 500; font-size: 18px; letter-spacing: -0.01em; }
    .dlist {
      background: var(--bg-secondary); border-radius: var(--r-card);
      box-shadow: var(--shadow-sm); overflow: hidden;
    }
    /* The hairline is on every row and the card clips the last one against its
       own corner, which survives a row being added in a way :last-child does
       not. */
    .drow {
      display: flex; align-items: center; justify-content: space-between;
      gap: 16px; padding: 16px 24px; border-bottom: 1px solid var(--border-color);
    }
    .drow:hover { background: var(--bg-tertiary); }
    .dl { display: flex; align-items: center; gap: 14px; min-width: 0; }
    .dn { font-weight: 500; }
    .dm { font-size: 12px; color: var(--text-tertiary); margin-top: 2px; }
    /* The name is the only part of the row that can be long, so it is the part
       that gives way. Truncated and not wrapped: a file name that wraps pushes
       the action off its own line at the width where the row has least to
       spare. */
    .dl > div { min-width: 0; }
    .dn, .dm { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .drow > .btn { flex-shrink: 0; }
    /* DESIGN-RULES §Document list, the redesign: the year inside the card,
       on the ground a table's heading row stands on, so it reads as a divider
       of the one list and not as a first document. */
    .dyear {
      display: flex; justify-content: space-between; align-items: center;
      height: 44px; padding: 0 24px; background: var(--bg-tertiary);
      border-bottom: 1px solid var(--border-color);
      font-size: 12px; color: var(--text-tertiary);
    }
    .dyear > span:first-child { font-weight: 500; }
    /* The field on the search screen. The bar's box is a way in; this is the
       thing itself, so it is the width of the page and carries the query. */
    .bigsearch {
      display: flex; align-items: center; gap: 12px;
      padding: 15px 18px; border-radius: var(--r-card);
      background: var(--bg-secondary); box-shadow: var(--shadow-sm);
      font-size: 16px;
    }
    .bigsearch svg { flex-shrink: 0; color: var(--text-tertiary); width: 20px; height: 20px; }
    /* The real control, where the prototype draws a caret and a span. It brings
       no box of its own: the box is .bigsearch, and a second border inside it
       would be two boxes for one field. */
    .bigsearch input {
      flex: 1; min-width: 0; border: 0; outline: 0; padding: 0;
      background: transparent; color: var(--text-primary);
      font-family: inherit; font-size: 16px; letter-spacing: inherit;
    }
    .bigsearch input::placeholder { color: var(--text-tertiary); }
    /* The input drops its own outline above, so the box has to carry it or the
       one field on the screen shows nothing when it is focused. The ring rather
       than a darker border, which is what .input does: there is no border here to
       darken, and the box IS the field. */
    .bigsearch:focus-within { outline: 2px solid var(--accent-color); outline-offset: 2px; }
    /* DESIGN-RULES "Search": the characters the question matched, on the
       palette's tint rather than the browser's yellow, in the row's own ink.
       The 2px is §4's radius for a mark inside a line of text. */
    mark { background: var(--warning-bg); color: inherit; border-radius: 2px; padding: 0 1px; }

    /* The live region is the wrapper and it is always there, empty; the bubble
       is what appears. It spans the viewport and centres its child so that
       whatever the conditional leaves between the two still lands in the middle,
       and it takes no clicks: the page underneath stays usable. */
    .toastw {
      position: fixed; left: 0; right: 0; bottom: 28px; z-index: 90;
      display: flex; justify-content: center; pointer-events: none;
      /* A sentence longer than a phone is wide folds inside the bubble, which keeps
         the page's 16px from the window's edge on each side (DESIGN-RULES §Toast). */
      padding: 0 16px;
    }
    .toast {
      max-width: 560px;
      padding: 12px 20px; border-radius: var(--r-pill);
      background: var(--text-primary); color: var(--bg-secondary);
      font-size: 13.5px; box-shadow: var(--shadow-md);
    }
    body.dark .toast { color: #141312; }
    /* A dialog is a card that has come forward: same ground, same radius, same
       three parts. It is a real <dialog> opened with showModal(), so the page
       behind it is inert and the focus stays inside without any of that being
       written in script. The 440px is the bounded detail column; the backdrop is
       the sidebar drawer's scrim, which is the one veil the language has. */
    .dlg {
      width: 440px; max-width: calc(100vw - 48px);
      max-height: calc(100vh - 48px); overflow: auto;
      /* The reset above sets `* { margin: 0 }`, which beats the `margin: auto`
         the browser gives a modal <dialog> — without this it lands in the
         top-left corner instead of the middle of the window. */
      margin: auto; height: fit-content;
      padding: 0; border: 0; color: var(--text-primary);
      background: var(--bg-secondary);
      border-radius: var(--r-card); box-shadow: var(--shadow-md);
    }
    .dlg::backdrop { background: rgba(10, 11, 13, 0.42); }
    .dlg .card-bd { display: flex; flex-direction: column; gap: 16px; }
    /* The head's meta takes its own line under the title where the two do not fit one. */
    .dlg > .card-hd { flex-wrap: wrap; gap: 4px 12px; }
    /* The buttons sit at the right end together; there is no sentence opposite
       them, as there is in the foot of a card. */
    .dlg .card-ft.row { justify-content: flex-end; gap: 10px; }
    /* DESIGN-RULES §Dialog: the foot's buttons are the small size, whichever the screen wrote. */
    .dlg .card-ft .btn { padding: 7px 14px; font-size: 13px; }
    /* A dialog taller than the window scrolls its body between a head and a foot
       that stay put, so the buttons that answer it are never scrolled away. */
    .dlg[open]:has(> .card-bd) { display: flex; flex-direction: column; overflow: hidden; }
    .dlg[open] > .card-hd, .dlg[open] > .card-ft { flex-shrink: 0; }
    .dlg[open] > .card-bd { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
    /* A table or a one-line empty inside a dialog's body starts at the body's own
       edge: the body already stands 24px in, and a second inset would be two. */
    .dlg .card-bd .tbl :is(th, td):first-child { padding-left: 0; }
    .dlg .card-bd .tbl :is(th, td):last-child { padding-right: 0; }
    .dlg .card-bd > .emptyline:not(:only-child) { padding: 0; border-bottom: 0; }
    /* Several records of facts in one body — a figure's confirmations, newest first — are an
       in-card list: a hairline between one and the next, the body's 16px either side of it.
       A gap alone (34px against the 18px between two facts) did not say where one ended. */
    .dlg .card-bd > .fields:has(> .kv) + .fields:has(> .kv) { margin-top: 0; padding-top: 16px; border-top: 1px solid var(--border-color); }
    /* A dialog whose body carries its own acts has no foot to draw. */
    .dlg .card-ft:empty { display: none; }
    /* DESIGN-RULES §Dialog, in flight: while the act is on its way the dialog is aria-busy; the
       foot answers no press and the filled button pulses as §Updating region does. No caller
       draws its own: the label does not change, so nothing in the foot moves. A wizard's action
       bar is the same two buttons at the end of a page, and waits the same way. */
    .dlg[aria-busy="true"], .pgactions.end[aria-busy="true"] { cursor: progress; }
    .dlg[aria-busy="true"] > .card-ft, .pgactions.end[aria-busy="true"] > * { pointer-events: none; }
    /* The pressed button names itself and pulses (below). A dialog's foot that does not say which
       was pressed has one act, the filled or the danger one, and that is the one that pulses. */
    .dlg[aria-busy="true"] > .card-ft:not(:has([aria-busy="true"])) .btn:is(.primary, .danger) { animation: plot-loading 1.2s ease .15s infinite alternate-reverse; }
    @media (prefers-reduced-motion: reduce) { .dlg[aria-busy="true"] > .card-ft .btn:is(.primary, .danger) { animation: none; } }
    /* DESIGN-RULES §Button, In flight on a page: the pressed button — in a card, a head, a row, a
       cell, a dialog's foot — is the one that is aria-busy, disabled and keeping its words, and it
       pulses whatever its kind. Its siblings are disabled and nothing else. Drawn once, here. */
    :is(.btn, .cellact)[aria-busy="true"], .cellact[aria-busy="true"]:disabled { cursor: progress; animation: plot-loading 1.2s ease .15s infinite alternate-reverse; }
    @media (prefers-reduced-motion: reduce) { :is(.btn, .cellact)[aria-busy="true"], .cellact[aria-busy="true"]:disabled { animation: none; } }
    /* The dialog holds the focus while its own buttons are disabled, and a refusal a wizard's bar
       took the reader to holds it so that it is read out (§Dialog, Focus). Neither is a control,
       so neither draws the ring. Nor does the row, the card heading or the page title the
       focus is given to when the pressed button is left disabled (§Button, In flight on a page). */
    .dlg:focus-visible, .callout[tabindex="-1"]:focus-visible,
    .tbl tr[tabindex="-1"]:focus-visible, :is(h1, h3)[tabindex="-1"]:focus-visible { outline: none; }
    /* A select or a picker opened in a dialog is in the dialog's flow: the body that scrolls
       would clip a list laid over it, so the dialog grows with the list instead. */
    .dlg .sel > .menu { position: static; }
    /* A dialog on a page with no script. showModal() is script, so the same box
       is opened by an address: the opener links to #id, the layer shows at
       :target, and the veil and the cancel are links to an address that names
       nothing, so closing does not scroll the page. Never inside the sidebar —
       below the breakpoint it is a transformed drawer, and a fixed layer inside
       a transformed box is fixed to the box and not to the window. */
    .tdlg {
      display: none; position: fixed; inset: 0; z-index: 60;
      align-items: center; justify-content: center; padding: 24px;
    }
    .tdlg:target { display: flex; }
    .tdlg-veil { position: absolute; inset: 0; background: rgba(10, 11, 13, 0.42); }
    .tdlg .dlg { position: relative; }
    /* The portal's sign-out dialog is drawn outside the page (§Dialog: never inside the drawer), so
       the v3 card head every dialog opened from a page has is given to it here: one head for all.
       The staff console's is a <dialog> beside the shell, outside the page as well, and takes the same. */
    .console.portal > .tdlg .dlg > .card-hd, .console > .dlg > .card-hd { padding: 20px 24px; }
    .console.portal > .tdlg .dlg > .card-hd h3, .console > .dlg > .card-hd h3 { font-size: 20px; letter-spacing: -.02em; }
    @media (max-width: 900px) { .console.portal > .tdlg .dlg > .card-hd, .console > .dlg > .card-hd { padding: 16px; } }
    /* The methodology dialog (v3 design): wider, and it only shows, so it closes from its head. */
    .dlg.wide { width: 704px; }
    .dlg.wide .card-hd { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 32px 32px 0; border-bottom: 0; }
    .dlg.wide .card-hd h3 { font-size: 26px; font-weight: 400; letter-spacing: -.02em; }
    /* Its round close stays at the head's top right where the title takes two lines (a phone):
       the head does not wrap, the title does. */
    .dlg.wide > .card-hd { flex-wrap: nowrap; align-items: flex-start; }
    .dlg.wide > .card-hd h3 { min-width: 0; }
    .dlg-x { display: flex; align-items: center; justify-content: center; width: 32px; height: 32px; flex-shrink: 0; border-radius: var(--r-pill); box-shadow: var(--ring-inset); color: var(--text-secondary); }
    /* The round close answers the pointer as the bar's icon button does (§Button hover: --bg-hover, ink). */
    .dlg-x:hover { background: var(--bg-hover); color: var(--text-primary); text-decoration: none; }
    .methodology { padding: 24px 32px 32px; font-size: 14px; line-height: 1.6; color: var(--text-secondary); }
    .methodology h4 { font-size: 14px; font-weight: 500; color: var(--text-primary); margin-bottom: 4px; }
    .methodology .gloss { font-weight: 400; color: var(--text-tertiary); }
    .methodology section + section { margin-top: 16px; }
    .methodology p + p { margin-top: 8px; }
    /* a dropdown you can actually open. <details> so it works with no script. */
    .sel { position: static; }
    .sel > summary {
      list-style: none; cursor: pointer; user-select: none;
      transition: border-color .12s ease, box-shadow .12s ease;
    }
    .sel > summary::-webkit-details-marker { display: none; }
    .sel > summary::marker { content: ''; }
    .sel > summary:hover { border-color: var(--text-tertiary); }
    .sel[open] > summary { border-color: var(--text-primary); box-shadow: 0 0 0 3px var(--border-color); }
    .sel .chev { display: flex; transition: transform .15s ease; }
    .sel[open] .chev { transform: rotate(180deg); }
    .field:has(.sel[open]) { z-index: 40; }
    /* the opened list */
    .menu {
      position: absolute; top: 100%; left: 0; right: 0; margin-top: 5px; z-index: 30;
      background: var(--bg-secondary); border: 1px solid var(--border-input);
      border-radius: 8px; box-shadow: var(--shadow-md); padding: 5px;
      /* A book of three hundred is searched, not scrolled past the window's foot. */
      max-height: min(360px, 60vh); overflow-y: auto; overflow-x: hidden;
    }
    /* A long option wraps inside the menu; it never gives the menu a sideways scroll. */
    .opt > span:first-child { min-width: 0; overflow-wrap: anywhere; }
    .opt {
      display: flex; align-items: center; justify-content: space-between; gap: 12px;
      padding: 8px 10px; border-radius: 6px; font-size: 14px;
    }
    .opt.on { background: var(--bg-tertiary); font-weight: 500; }
    /* An option answers the pointer as a button does; a refused one does not. */
    .opt, .popt, .pnone { cursor: pointer; }
    .opt:hover, .popt:hover, .pnone:hover { background: var(--bg-hover); }
    .popt.off { cursor: default; }
    .popt.off:hover { background: transparent; }
    .opt .hint { font-size: 12px; color: var(--text-tertiary); font-weight: 400; white-space: nowrap; }
    .opt .tick { color: var(--accent-color); display: flex; }
    /* the note under a selector: annotation, not an option, so it stays visible */
    .field-note { font-size: 12px; line-height: 1.55; color: var(--text-tertiary); margin-top: 1px; }
    /* Picking one out of a book of hundreds. A dropdown cannot do this: the
       list is too long to scan, and each candidate carries more than a name —
       the agreement version, whether it is in force, and whether it can be
       chosen at all. At rest this is a statement of what is recorded, not an
       input: a text box would offer two ways to set a value that divides
       money, and they can disagree. The button is what makes it editable, and
       says so. */
    .picked {
      display: flex; align-items: center; justify-content: space-between; gap: 14px;
      padding: 4px 4px 4px 12px; border: 1px solid var(--border-input);
      border-radius: 6px; background: var(--bg-secondary);
      /* The text field's height (§Input, 39px): beside a field it is the same box. */
      min-height: 39px;
    }
    .picked-t { display: block; }
    .picked-v { display: block; font-size: 14px; color: var(--text-primary); }
    .picked.ph .picked-v { color: var(--text-tertiary); }
    .picked:hover { border-color: var(--text-muted); }
    .sel > summary.picked:focus-visible { border-color: var(--text-primary); outline: none; }
    .picked-s { display: block; font-size: 12px; color: var(--text-tertiary); margin-top: 3px; line-height: 1.45; }
    .picked-go { flex-shrink: 0; display: flex; }
    .picked-go .btn.sm { padding: 5px 12px; }
    /* The search box is the first thing in the panel, because with three
       hundred of them scrolling is not a way of finding one. */
    .psearch {
      display: flex; align-items: center; gap: 9px; margin: 4px 4px 6px;
      padding: 9px 11px; border: 1px solid var(--border-input); border-radius: 7px;
      background: var(--bg-primary); font-size: 13.5px;
    }
    .psearch svg { flex-shrink: 0; color: var(--text-tertiary); }
    /* The real control, where an artboard draws a query and a caret. It brings
       no box of its own: the box is .psearch, and a second border inside it
       would be two boxes for one field. */
    .psearch input {
      flex: 1; min-width: 0; border: 0; outline: 0; padding: 0;
      background: transparent; color: var(--text-primary);
      font-family: inherit; font-size: 13.5px; letter-spacing: inherit;
    }
    .psearch input::placeholder { color: var(--text-tertiary); }
    /* The input drops its outline; the box takes §Input's focus, the darkened border. */
    .psearch:focus-within { border-color: var(--text-primary); }
    .pcount {
      padding: 0 12px 7px; font-size: 11.5px; color: var(--text-tertiary);
      border-bottom: 1px solid var(--border-color); margin-bottom: 5px;
    }
    .popt {
      display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 3px 12px;
      padding: 9px 12px; border-radius: 6px; align-items: baseline;
    }
    .popt.on { background: var(--bg-tertiary); }
    .popt .n { font-size: 14px; font-weight: 500; color: var(--text-primary); }
    .popt.on .n { display: flex; align-items: center; gap: 8px; }
    .popt .r { grid-column: 2; grid-row: 1; justify-self: end; }
    .popt .m { grid-column: 1 / -1; font-size: 12px; color: var(--text-tertiary); line-height: 1.5; }
    /* Listed and refused, never hidden: somebody looking for a terminated
       introducer deserves to be told why, not handed an empty result. */
    .popt.off .n, .popt.off .m { color: var(--text-muted); }
    .popt .tick { color: var(--accent-color); display: flex; }
    /* Not an option in the list. It is the ordinary case and the default, and a
       hundred names would bury it. */
    .pnone {
      display: flex; align-items: center; justify-content: space-between; gap: 12px;
      margin: 0 4px 5px; padding: 8px 12px; border-radius: 6px;
      background: var(--bg-tertiary); font-size: 13.5px;
    }
    .pnone .hint { font-size: 12px; color: var(--text-tertiary); }
    /* DESIGN-RULES "Filter bar", the filter row. One line — the segment at the left,
       and a compact form pushed to the right end: fields the height of the
       header's search box, a typed field with the search glyph inside it, a
       native picker at its own width, and one small button at the same 36px
       so the three read as one line. The label is each control's aria-label;
       the typed field's placeholder says the same words. */
    .filterrow { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
    .filterrow form { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-left: auto; }
    .filterrow .input { height: 36px; padding: 0 12px; font-size: 13px; }
    .filterrow .input.typed {
      display: flex; align-items: center; gap: 8px; width: 280px;
      color: var(--text-tertiary);
    }
    .filterrow .input.typed svg { width: 14px; height: 14px; flex-shrink: 0; }
    /* The box is the field; the input inside it brings no box of its own,
       as the header's .search input does not. */
    .filterrow .input.typed input {
      flex: 1; min-width: 0; border: 0; outline: 0; padding: 0;
      background: transparent; color: var(--text-primary);
      font-family: inherit; font-size: 13px; letter-spacing: inherit;
    }
    .filterrow .input.typed input::placeholder { color: var(--text-tertiary); }
    /* The mark that clears what was typed is the browser's, and it draws it
       in its own blue: the same cross, 12px, in the glyph's tertiary. Every
       search field takes it — a list's typed field, the search line, the bar's
       search box on both surfaces — so there is one cross and not the browser's
       beside ours. */
    input[type="search"]::-webkit-search-cancel-button {
      -webkit-appearance: none; appearance: none; width: 12px; height: 12px; margin: 0 0 0 8px; cursor: pointer;
      background: var(--text-tertiary);
      -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round'%3E%3Cpath d='M2.5 2.5l7 7M9.5 2.5l-7 7'/%3E%3C/svg%3E") center / contain no-repeat;
      mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round'%3E%3Cpath d='M2.5 2.5l7 7M9.5 2.5l-7 7'/%3E%3C/svg%3E") center / contain no-repeat;
    }
    input[type="search"]::-webkit-search-cancel-button:hover { background: var(--text-primary); }
    .filterrow select.input { width: auto; }
    .filterrow .btn.sm { height: 36px; padding-top: 0; padding-bottom: 0; }
    /* Staff console v2: in the console a row's pills keep §Pills' own height; only an act
       — the form's button, or the one closing the row — takes the fields' 36px. */
    .staff-page .filterrow .segment .btn.sm, .staff-page .filterrow > .btn.sm:not(.end) { height: auto; padding: 6px 16px; }
    .check { display: flex; align-items: center; gap: 9px; font-size: 13.5px; cursor: pointer; }
    .check:hover .mark { border-color: var(--text-muted); }
    .check.on:hover .mark { border-color: var(--accent-color); }
    /* What tells two options apart, after the label: the picker option's hint. */
    .check .hint { font-size: 12px; color: var(--text-tertiary); }
    /* The word of a box that carries a hint is one thing: the hint folds, the word does not. */
    .check .mark + span:has(+ .hint) { white-space: nowrap; }
    .check .mark {
      width: 16px; height: 16px; border-radius: 4px;
      border: 1.5px solid var(--border-input); flex-shrink: 0;
      display: flex; align-items: center; justify-content: center;
    }
    /* The mark is filled with the accent, so the tick inside it has to be the
       colour that sits on the accent — the same pairing `.btn.primary` uses.
       The artboards write it as an inline `color:#fff`, which is right in the
       light theme only; the token is right in both. */
    .check.on .mark { background: var(--accent-color); border-color: var(--accent-color); color: var(--accent-hover); }
    /* The timeline: what has happened, dated, with what has not happened
       named. Not the event log — these rows include ones that have not
       occurred, which is what `pending` is for, and there is no rail because
       the rows are a fixed list rather than entries somebody wrote. */
    .timeline { display: flex; flex-direction: column; }
    .tl-row {
      display: grid; grid-template-columns: minmax(0, 1fr) 130px 130px;
      gap: 12px; padding: 10px 0; font-size: 14px; align-items: baseline;
      border-bottom: 1px solid var(--border-color);
    }
    .tl-row:last-child { border-bottom: 0; }
    .tl-row .when { color: var(--text-secondary); text-align: right; }
    .tl-row .amt { text-align: right; font-variant-numeric: tabular-nums; }
    .tl-row.pending { color: var(--text-tertiary); }
    /* On a phone the two 130px columns leave the words a word wide: the
       figure keeps a column as wide as itself and the date goes under the words. */
    @media (max-width: 900px) {
      .tl-row { grid-template-columns: minmax(0, 1fr) auto; gap: 2px 12px; }
      .tl-row .when { grid-column: 1; grid-row: 2; text-align: left; }
      .tl-row .amt { grid-column: 2; grid-row: 1; }
      .tl-row .when:empty, .tl-row .amt:empty { display: none; }
    }

    /* The feed: prose somebody else wrote, newest first, which is why it does
       not look like a table of figures. Ported verbatim from the prototype for
       WP-10's announcements — the same component the company-updates feed is,
       with the mark and the vehicle line left off, because a message from the
       firm is about no company and belongs to no vehicle. */
    .feed { display: flex; flex-direction: column; }
    .feed-it {
      display: flex; gap: 14px; padding: 16px 0;
      border-top: 1px solid var(--border-color);
    }
    .feed-it:first-child { border-top: 0; padding-top: 0; }
    .feed-bd { min-width: 0; flex: 1; }
    .feed-hd { display: flex; align-items: baseline; flex-wrap: wrap; gap: 6px 12px; }
    .feed-nm { font-weight: 500; letter-spacing: -0.01em; }
    .feed-veh {
      display: inline-flex; align-items: center; gap: 6px;
      font-size: 12px; color: var(--text-tertiary);
    }
    .feed-when { font-size: 12px; color: var(--text-tertiary); margin-left: auto; }
    .feed-tx { margin-top: 5px; font-size: 13.5px; color: var(--text-secondary); line-height: 1.6; }

    .steps { display: flex; align-items: center; gap: 10px; font-size: 13px; }
    .step { display: flex; align-items: center; gap: 8px; color: var(--text-tertiary); }
    .step .n {
      width: 22px; height: 22px; border-radius: 50%; font-size: 12px; font-weight: 600;
      display: flex; align-items: center; justify-content: center;
      border: 1px solid var(--border-input); color: var(--text-tertiary);
    }
    .step.on { color: var(--text-primary); font-weight: 500; }
    .step.on .n { background: var(--accent-color); border-color: var(--accent-color); color: var(--bg-secondary); }
    body.dark .step.on .n { color: #121110; }
    .step.done .n { border-color: var(--accent-color); color: var(--text-primary); }
    .steps .bar { width: 26px; height: 1px; background: var(--border-input); }
    /* DESIGN-RULES "One-line empty": a card with nothing to show says so in
       one line where its first row would be — the row's padding, the
       sub-line's ink — and keeps its head. A hairline below it only where rows
       follow, for a card that is empty in one part and not in another. */
    .emptyline { padding: 14px 24px; font-size: 13px; color: var(--text-tertiary); }
    .emptyline:not(:last-child) { border-bottom: 1px solid var(--border-color); }
    /* The console's cards put their one line inside a .card-bd, whose own
       padding would double the row's; the body steps aside for it. */
    .card-bd:has(> .emptyline:only-child) { padding: 0; }
    .tbl td.pos { color: var(--positive-text); }
    .tbl td.neg { color: var(--negative-text); }

    /* ---- narrow -------------------------------------------------------- */
    /* DESIGN-RULES "Metric row": one metric on the review screen — the name,
       the figure, what the act will record, and beneath all three the evidence
       it rests on.

       The middle cell is an ordinary `.input` whether or not it arrived filled
       in. That is PAR-11's whole scope written as CSS: a pre-accepted row that
       rendered as text with an *edit* affordance beside it would let the
       threshold decide whether a person could act, which is the one thing the
       parameter is not allowed to do. */
    .metric-row {
      display: grid; grid-template-columns: minmax(0, 1fr) 110px 92px;
      gap: 12px; padding: 11px 0; border-bottom: 1px solid var(--border-color);
      align-items: baseline; font-size: 14px;
    }
    .metric-row:last-child { border-bottom: 0; }
    .metric-row .amt { text-align: right; font-variant-numeric: tabular-nums; }
    .metric-row .amt .input { width: 100%; text-align: right; font-variant-numeric: tabular-nums; }
    .metric-row .st { text-align: right; font-size: 12px; }
    .metric-row .sub { font-size: 12px; color: var(--text-tertiary); margin-top: 3px; }
    /* The evidence, under all three columns. A flag is a word in it and never
       a tint on the row: a coloured row reads as *refused*, and the whole
       claim of a plausibility flag is *look at this one first*. */
    .metric-src { grid-column: 1 / -1; font-size: 12px; color: var(--text-tertiary); margin-top: -4px; }
    .metric-src .flag { color: var(--warning-text); }

    /* DESIGN-RULES "Chart": one series, or a family of them, over the months a
       company reported.

       The SVG scales and never scrolls, because a chart is read by its shape
       and a shape cut off at the right-hand edge is a shape nobody can read.
       An empty chart keeps its height: a panel that collapsed when it had no
       readings would move everything under it the first time one arrived. */
    .chartbox {
      background: var(--bg-secondary); border: 1px solid var(--border-color);
      border-radius: 10px; padding: 14px 14px 8px;
    }
    .chart-hd { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 2px 12px; margin-bottom: 2px; }
    .chart-t { font-size: 13.5px; font-weight: 600; white-space: nowrap; }
    .chart-lg { display: flex; flex-wrap: wrap; gap: 2px 12px; }
    .chart-lg span { display: flex; align-items: center; gap: 5px; font-size: 11.5px; font-weight: 500; color: var(--text-secondary); white-space: nowrap; }
    .chart-lg i { width: 8px; height: 8px; border-radius: 50%; display: block; }
    .chart svg { display: block; width: 100%; height: auto; }
    .chart text { font-family: inherit; font-variant-numeric: tabular-nums; }
    .chart-empty {
      display: flex; flex-direction: column; align-items: center; justify-content: center;
      gap: 5px; height: 178px; border: 1px dashed var(--border-input); border-radius: 8px;
      color: var(--text-tertiary); font-size: 12.5px; text-align: center;
    }


/* History chart — DESIGN-RULES §Chart: the months, the guide and the tooltip
   under the ink reading below. */
.history-plot { position: relative; }
.history-month { position: absolute; top: 5.454545%; height: 83.636364%; }
.history-guide, .history-dot, .history-tip-shell { visibility: hidden; pointer-events: none; }
.history-month:hover, .history-month:focus-within { z-index: 30; }
.history-month:hover > *, .history-month:focus-within > * { visibility: visible; }
.history-guide { position: absolute; top: 0; bottom: 0; left: var(--month-x); border-left: 1px solid var(--text-tertiary); }
.history-dot { position: absolute; left: var(--month-x); width: 4px; height: 4px; border: 2px solid var(--bg-secondary); box-sizing: content-box; border-radius: 50%; transform: translate(-50%,-50%); }
.history-tip-shell { position: absolute; top: 0; pointer-events: none; }
.history-tip { position: absolute; z-index: 30; top: 0; left: clamp(0px, calc(var(--tip-x) + 14px), calc(100% - 220px)); width: 220px; max-width: 100%; box-sizing: border-box; padding: 10px 12px; border-radius: var(--r-nav); background: var(--bg-secondary); box-shadow: var(--shadow-md); font-size: 12px; line-height: 1.5; color: var(--text-secondary); }
.history-tip b { display: block; color: var(--text-primary); font-weight: 500; margin-bottom: 4px; }
.history-tip div { display: flex; align-items: center; gap: 6px; }
.history-tip i { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
.history-tip span { margin-left: auto; padding-left: 12px; color: var(--text-primary); font-variant-numeric: tabular-nums; }
.history-month.opens-left .history-tip { left: clamp(0px, calc(var(--tip-x) - 234px), calc(100% - 220px)); }
.history-note { font-size: 11.5px; color: var(--text-tertiary); padding: 4px 0 2px; }

/* Ink — DESIGN-RULES §Chart, "Ink". The one reading of the history: the
   value a black line, distributed green under it, committed a dashed grey
   the eye reads as a reference. Paint only; the months, the guide and the
   tooltip are the history chart's above and are not restated. The chart
   sits in an ordinary .card with a .card-hd, and not in .chartbox. */
.ink-plot { padding: 20px 24px 16px; }
.ink-nav { fill: var(--badge-bg); }
.ink-dist { fill: var(--success-bg); }
.ink-distline { fill: none; stroke: var(--history-green); stroke-width: 1.5; }
.ink-value { fill: none; stroke: var(--text-primary); stroke-width: 2; }
.ink-committed { fill: none; stroke: var(--text-muted); stroke-width: 1.5; stroke-dasharray: 4 4; }
/* Multiples: TVPI takes the value's black and DPI the distributed green; RVPI,
   the part still held, is the grey line solid, and par is the dashed one. */
.ink-rvpi { fill: none; stroke: var(--text-muted); stroke-width: 1.5; }

    /* DESIGN-RULES "Quotation": somebody else's sentence, shown where a figure
       is being checked against it.

       A rule down the left rather than quotation marks, so that the stored
       passage stays exactly what arrived. It wraps to as many lines as it
       takes and is never truncated — a passage cut short at the box's width is
       a passage that cannot be checked, which is the only thing it is on the
       screen for. */
    .quote {
      border-left: 2px solid var(--border-input); padding: 2px 0 2px 14px;
      font-size: 13.5px; line-height: 1.65; color: var(--text-secondary);
    }
    .quote em { color: var(--text-primary); font-style: normal; background: var(--warning-bg); padding: 0 2px; }
    body.dark .quote em { background: rgba(230, 81, 0, 0.28); }

    @media (max-width: 1000px) {
      /* Starts at the top rather than centring: on a short viewport with the
         keyboard up, a centred form scrolls its own heading off the screen. */
      /* No spare height to centre in: the rows hug their content and the
         whole column starts at the top. */
      .si-form { grid-template-rows: auto auto; align-content: start; padding: 40px 22px 20px; }
      /* One column: the art goes, and the panel starts at the top. */
      .si-split { grid-template-columns: minmax(0, 1fr); }
      .si-art { display: none; }
      .si-side { padding: 40px 22px 20px; }
      .si-main { align-items: flex-start; padding: 0 0 32px; }
      .si-split .si-body { max-width: none; }
      .si-title { font-size: 21px; margin-bottom: 28px; }
      .si-head { margin-bottom: 28px; }
      .si-body { gap: 20px; }
      .si-top { margin-bottom: 32px; }
      .si-form > * { max-width: none; }
      .si-top .logo-full { height: 44px; }
      .si-legal { padding: 0 22px 22px; }
      .si-h { font-size: 20px; }
      .si-code { gap: 7px; }
      .si-cell { height: 48px; }
      .lg-h1 { font-size: 21px; }
      .lg-page { padding: 36px 22px 72px; }
    }

    /* ---- console, narrow ------------------------------------------------ */
    /* 900px, not the 1000px the sign-in uses: the number is where each layout
       actually runs out of room, and the sidebar runs out sooner. */
    @media (max-width: 900px) {
      .hdr { padding: 0 16px; gap: 12px; }
      .hdr-mid { flex: 1; }
      .search { width: 100%; max-width: none; }
      .shell-main, .viewbar { margin-left: 0; }
      .acct-label, .acct-chevron { display: none; }
      /* The bell is not the bar's last item, so its panel hangs from the bar
         rather than from the bell, 16px in from both edges. */
      .bell { position: static; }
      .acct-menu.bell-menu { left: 16px; right: 16px; width: auto; max-width: none; }
      .acct-mobile-area { display: block; }
      .bigsearch { padding: 13px 15px; font-size: 15px; }
      .bigsearch input { font-size: 15px; }
      .hamburger { display: flex; }

      /* The sidebar becomes a drawer over the page. It keeps its own scroll
         and the scrim closes it, so nothing behind it can be reached by
         accident while it is open. */
      .layout { position: relative; }
      .sidebar {
        z-index: 60; width: 272px; max-width: 82%;
        transform: translateX(-101%); transition: transform .2s ease;
        visibility: hidden;
      }
      .nav-open .sidebar { transform: translateX(0); visibility: visible; box-shadow: var(--shadow-sm); }
      .nav-open .navscrim {
        display: block; position: fixed; inset: 0; z-index: 50;
        background: rgba(10, 11, 13, 0.42); border: 0;
      }
      /* The same drawer, opened without script. The shadow lives on the open
         state alone, or its blur shows as a band down the left edge of a page
         whose menu is shut. */
      /* The keyboard reaches the checkbox, which has no box: its label, the hamburger, shows the ring. */
      .navtoggle:focus-visible ~ .layout .hamburger { outline: 2px solid var(--accent-color); outline-offset: 2px; }
      .navtoggle:checked ~ .layout .sidebar {
        transform: translateX(0); visibility: visible; box-shadow: var(--shadow-sm);
      }
      .navtoggle:checked ~ .layout .navscrim {
        display: block; position: fixed; inset: 0; z-index: 50;
        background: rgba(10, 11, 13, 0.42); border: 0;
      }

      .content { padding: 16px 14px 32px; }
      .page { gap: 16px; max-width: none; }
      .pghead { flex-direction: column; align-items: flex-start; gap: 12px; }
      .pgtitle { font-size: 21px; }
      /* Four figures wrapping as a flex row leave the fourth alone on a line of
         its own. A two-column grid puts them in a square, which is what the
         same four are on a wider screen: a block, not a sentence. */
      .pgfigs {
        display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 18px 28px; width: 100%;
      }
      .pgfig-v { font-size: 18px; }
      .pgactions { padding-top: 0; flex-wrap: wrap; }

      .grid2, .grid3, .grid4 { grid-template-columns: minmax(0, 1fr); gap: 16px; }
      /* the wide column of a two-column screen carries its width inline, so
         this has to shout as well */
      .cols { flex-direction: column; }
      .cols > * { width: 100% !important; max-width: 100%; }
      .fields, .fields.three { grid-template-columns: minmax(0, 1fr); gap: 16px; }
      /* Two columns and not one (§5). Four figures in a column are a list and
         in a square are a block, which is what they are on a wider screen. */
      /* the strip carries its column count inline, so this has to shout */
      .strip { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; gap: 18px 20px; }
      /* Two columns of figures, so the right-hand one is no longer only
         `.last`: a bubble hanging from the left of it runs off the phone. And
         no bubble is ever wider than the screen it is on. */
      .def > .dfb { width: min(260px, calc(100vw - 40px)); }
      .pgfigs > *:nth-child(even) .def > .dfb,
      .strip > .strip-cell:nth-child(even) .def > .dfb { left: auto; right: 0; }
      /* A dash is 13px wide, and a bubble hung from the right edge of one left the window on the
         left. In the portal's strips the bubble hangs from the figure's cell instead: its left
         edge in the left-hand column, its right edge in the right-hand one. */
      .console .strip > .strip-cell { position: relative; }
      .console .strip > .strip-cell .def { position: static; }
      .console .strip > .strip-cell:nth-child(odd) .def > .dfb { left: 0; right: auto; }
      /* The staff console's head figures are the same two columns, and their bubbles hang from
         the figure's cell the same way — the last figure is not always in the right-hand one. */
      .staff-page .pgfigs > * { position: relative; }
      .staff-page .pgfigs > * .def { position: static; }
      .staff-page .pgfigs > *:nth-child(odd) .def > .dfb { left: 0; right: auto; }
      /* A table on a phone moves sideways under the finger, so no edge of a cell is a safe place
         to hang a bubble from: the scroll box cut it on one side or the other. There the bubble
         leaves the table and stands at the foot of the window, across it less the gutter. */
      .console .tbl .def > .dfb { position: fixed; top: auto; bottom: 16px; left: 16px; right: 16px; width: auto; }
      /* No rules between the cells here either. The desktop strip dropped its
         bordered-box look for the reference's plain label-over-figure;
         recreating the boxes at 390px would leave the phone showing the one
         thing the restyle removed. Air separates them instead. */
      .strip-cell { padding: 0; }
      .strip-v { font-size: 18px; }
      .strip-v.lg { font-size: 20px; }
      .strip-foot { border-left: 0; margin-top: 2px; }

      .tabs { overflow-x: auto; }
      .tab { white-space: nowrap; }
      /* A row that scrolls sideways scrolls the other way too, and the tab's 1px step onto the
         row's line was that scroll: a bar beside the portal's tabs. The line is drawn inside the
         row instead and the tab stands on it, its mark over the line as at full width. */
      .console.portal .tabs {
        overflow-y: hidden; border-bottom: 0;
        background: linear-gradient(var(--border-color), var(--border-color)) bottom / 100% 1px no-repeat;
      }
      .console.portal .tab { margin-bottom: 0; }
      .card-hd { flex-wrap: wrap; padding: 13px 16px; }
      .card-bd { padding: 16px; }
      .card-ft { padding: 13px 16px; }
      /* The document list takes the card's own step down, because that is what
         each of its groups is. The row keeps one line: the name truncates and
         the action does not move, which is the opposite way round from letting
         a 13-character button wrap under a file name. */
      .drow { padding: 14px 16px; gap: 12px; }
      .dyear { padding: 0 16px; }

      /* the value is usually money and sometimes a sentence, so it may take
         the width it needs and no more, and never squeezes the label to
         nothing */
      .ladder-row { grid-template-columns: minmax(84px, 1fr) auto; gap: 3px 12px; }
      .ladder-row .why { grid-column: 1 / -1; }

      /* A table shows the columns it was told a phone is for. The others are
         not squeezed and not cropped: they are gone, and the table says so. */
      .tbl .mx, .tbl th.dx { display: none; }
      .tbl th.mo { display: table-cell; }
      .tbl th.mo-nobl { border-left: 0; }
      .tbl th.mo-bl { border-left: 1px solid var(--border-color); }
      .mcols { display: block; }
      .tbl th { padding: 10px 7px; font-size: 10.5px; white-space: normal; }
      .tbl td { padding: 12px 7px; font-size: 13.5px; }
      /* money is the column that cannot wrap, so it is the one that gives
         ground */
      .tbl td.num, .tbl td.c { font-size: 12.5px; }
      .tbl tr.sub td { font-size: 12px; }
      .tbl td .sub { font-size: 11.5px; }

      /* The metric row's three columns become two: label and state share a
         line, the field takes the width beneath them. A 104px word and a
         right-aligned figure cannot share a phone's width without one of them
         wrapping mid-sentence. */
      .metric-row { grid-template-columns: minmax(0, 1fr) auto; gap: 4px 12px; }
      .metric-row .amt { grid-column: 1 / -1; }

      /* The filter row: the form takes the whole line under the segment, the
         typed field the whole line, and the pickers pair at 44%.
         The segment wraps at every width and needs nothing here. */
      .filterrow form { flex: 1 1 100%; margin-left: 0; }
      .filterrow .input.typed { width: auto; flex: 1 1 100%; }
      .filterrow select.input, .filterrow .pick { flex: 1 1 44%; }
      .filterrow .pick > select.input { flex: 1 1 auto; width: 100%; }
      /* The side-by-side row is the stacked row again: the label on its own
         line at the stacked row's 12px tertiary, the value and the slot
         under it. */
      .kvside {
        grid-template-columns: minmax(0, 1fr) auto; gap: 4px 12px;
        min-height: 0; padding: 12px 16px;
      }
      .kvside .k { grid-column: 1 / -1; font-size: 12px; color: var(--text-tertiary); }
      .emptyline { padding: 13px 16px; }
      /* An in-card list row that ends in acts: the acts take a line of their own. */
      .doc:has(> .rowacts) { flex-wrap: wrap; }
      .doc > .rowacts { flex: 1 0 100%; justify-content: flex-start; }
      .ink-plot { padding: 16px 16px 12px; }
      .steps { flex-wrap: wrap; gap: 8px; }
      .steps .bar { display: none; }
      /* an option's reason is as long as it needs to be; it wraps rather than
         running out of the menu and being cut by the card */
      .opt { align-items: flex-start; }
      .opt .hint { white-space: normal; text-align: right; }
    }

    /* Shown until the bundle boots; Main.kt removes it. */
    .loading { display: flex; height: 100vh; align-items: center; justify-content: center; color: var(--text-tertiary); }

/* Fund page — v3 capital, reporting and company status (§Fund capital and reporting). */
/* §Fund orb: the orb left of the title and the cohort under it, 24px between (v3 design). */
.pg-id { display: flex; align-items: center; gap: 24px; min-width: 0; }
.v3-head .pg-id { grid-column: 1; }
.pg-mark { flex-shrink: 0; }
.pg-id:has(> .pg-mark) .pgsub { font-size: 15px; }
.fund-capital .card-bd { padding: 24px; }
.fund-capital .ladder-row { padding-top: 12px; padding-bottom: 12px; }
.fund-latest-report { padding: 24px; }
.fund-latest-report h3 { font-size: 18px; font-weight: 500; letter-spacing: -.01em; margin: 10px 0; }
.fund-latest-report .badge { background: var(--text-primary); color: var(--bg-secondary); }
.fund-earlier-reports { padding: 12px 24px; background: var(--bg-tertiary); border-block: 1px solid var(--border-color); font-size: 12px; color: var(--text-tertiary); }

/* DESIGN-RULES "Split bar": where one sum went, as a bar in parts beside the
   ladder that carries the figures. */
.capital { display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr); gap: 48px; }
.capital > .ladder { border-left: 1px solid var(--border-color); padding-left: 32px; }
.splitbar { display: flex; height: 12px; gap: 2px; }
.splitbar span:first-child { border-radius: var(--r-pill) 0 0 var(--r-pill); }
.splitbar span:last-child { border-radius: 0 var(--r-pill) var(--r-pill) 0; }
.splitbar span:only-child { border-radius: var(--r-pill); }
.split-1 { background: var(--text-primary); }
.split-2 { background: var(--text-muted); }
.split-3 { background: var(--border-color); }
.split-4 { background: var(--badge-bg); }
.splitlg { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px; margin-top: 16px; }
.splitlg > div { display: flex; gap: 8px; align-items: flex-start; min-width: 0; }
.splitlg i { display: block; width: 8px; height: 8px; margin-top: 4px; flex-shrink: 0; border-radius: 2px; box-shadow: inset 0 0 0 1px var(--border-color); }
.splitlg .k { font-size: 12px; color: var(--text-tertiary); }
.splitlg .v { font-size: 13px; font-weight: 500; font-variant-numeric: tabular-nums; }
@media (max-width: 900px) {
  .capital { grid-template-columns: minmax(0, 1fr); gap: 24px; }
  .capital > .ladder { border-left: 0; padding-left: 0; }
  .splitlg { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Company detail: the approved investment and staff overview compositions. */
/* Company head — v3 (DESIGN-RULES): the portal company page's head; the console record draws
   the part under the title with the same classes. */
.co-head { display: flex; gap: 24px; align-items: flex-start; margin: 4px 0 20px; }
.co-id { flex: 1 1 0; min-width: 0; }
.co-title { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin-bottom: 8px; }
.co-title .badge { background: transparent; border: 1px solid var(--border-color); font-size: 12px; white-space: nowrap; }
.co-title .badge.ok { color: var(--text-primary); }
.co-facts { margin: 0 0 12px; font-size: 13px; color: var(--text-tertiary); }
.co-desc { margin: 0 0 16px; font-size: 14px; line-height: 1.6; max-width: 640px; text-wrap: pretty; overflow-wrap: anywhere; }
.pills.co-links a { gap: 6px; color: var(--text-primary); text-decoration: none; }
.pills.co-links a:hover { background: var(--bg-hover); }
.co-id > :last-child { margin-bottom: 0; }
/* Founders card — Derived (DESIGN-RULES): the feed's item with a person where the mark stands. The
   avatar takes the 48px of a mark beside a title and the photograph where one is held; the bio keeps
   the lines its author broke it into. */
.avatar.founder { width: 48px; height: 48px; font-size: 16px; background-size: cover; background-position: center; }
.founders .feed-tx { max-width: 640px; white-space: pre-line; text-wrap: pretty; overflow-wrap: anywhere; }
.founder-in {
  margin-left: auto; display: inline-flex; align-items: center; gap: 6px;
  font-size: 13px; color: var(--text-tertiary); text-decoration: none; white-space: nowrap;
}
.founder-in:hover { text-decoration: underline; }
@media (max-width: 900px) {
  .co-head > .cmark, .pg-id > .cmark { width: 48px !important; height: 48px !important; font-size: 18px !important; }
  .avatar.founder { width: 34px; height: 34px; font-size: 12px; }
}
.company-financials { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr); gap: 24px; align-items: start; }
.company-financials > * { min-width: 0; }
.company-financials > :only-child { grid-column: 1 / -1; }
.company-metrics { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 16px; }
.company-metric { padding: 16px; background: var(--bg-tertiary); border-radius: 10px; min-width: 0; }
.company-metric-label { border-left: 3px solid; padding-left: 8px; color: var(--text-tertiary); font-size: 12px; }
.company-metric .sub { font-size: 12px; color: var(--text-tertiary); }
.company-metric-value { font-size: 20px; font-weight: 600; margin: 8px 0; overflow-wrap: anywhere; }
.company-metric-value .cell { font: inherit; }
.company-history { margin-bottom: 24px; }
.company-history > summary { cursor: pointer; padding: 16px 0; font-size: 13px; font-weight: 500; }
.company-email { border: 1px solid var(--border-color); border-radius: var(--r-nav); padding: 16px; scroll-margin-top: 24px; }
.staff-page .feed-it:last-child { padding-bottom: 0; }
.company-email > summary { cursor: pointer; font-size: 13px; font-weight: 500; }
.company-email-body { white-space: pre-wrap; overflow-wrap: anywhere; margin-top: 16px; }
.company-update-filters { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 24px; }
.company-investment .strip { margin: 0; border-top: 0; padding-top: 0; }
@media (max-width: 1100px) { .company-financials { grid-template-columns: minmax(0, 1fr); } .company-metrics { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 700px) { .company-metrics { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* DESIGN-RULES §Portfolio and company pages v3, the investment card: the design's seven figures. */
.company-investment .strip { grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)) !important; gap: 24px; }
/* A figure wider than its share of the row (a nine-digit valuation at 22px is 151px in a 127px
   column) ran into the figure beside it. The cells flex from the same 120px floor instead, and
   none goes narrower than what it says. */
.company-investment .strip { display: flex; flex-wrap: wrap; }
.company-investment .strip > .strip-cell { flex: 1 1 120px; }
.company-investment .strip.wide .strip-v, .company-investment .strip-v { font-size: 22px; font-weight: 500; }
.company-investment .held-through { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
.company-investment .held-through .vdot { width: 14px; height: 14px; }
.company-investment .held-through a { display: inline-flex; align-items: center; gap: 8px; color: var(--text-primary); font-weight: 500; text-decoration: none; }
.company-investment .held-through a:hover { text-decoration: underline; }
.company-investment .card-ft { display: flex; justify-content: flex-end; gap: 10px; line-height: 1.6; }
.company-investment .card-ft > svg { flex-shrink: 0; margin-top: 2px; }
.company-investment .card-ft a { color: var(--text-primary); text-decoration: underline; text-underline-offset: 2px; }

.figure-decimals { font-size: 0.75em; }

/* v3 page language: opt in as each portal page migrates. */
/* Portfolio: keep the page gap inside the region that refreshes head and rows. */
.portfolio-page { display: flex; flex-direction: column; gap: 20px; min-width: 0; }
.v3-head .pgtitle { font-size: 36px; line-height: 1.1; }
/* Page head v3: the eyebrow spans the head; the title and the figures share the row under it,
   the figures top-aligned to the title's right (as the v3 design). Too narrow for both: the
   figures drop under the title, still one block. */
.v3-head .pghead { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 0 32px; align-items: start; }
.v3-head .pghead > div:first-child { display: contents; }
.v3-head .pgtitle, .v3-head .pgsub, .v3-head .pghead > div:first-child > .pgfig-n { grid-column: 1; }
.v3-head .pgfigs, .v3-head .pgside { grid-column: 2; grid-row: 1 / span 3; }
.v3-head .pgfigs { flex-wrap: nowrap; gap: 32px; }
/* The figures and, under them, the methodology link: one column, 20px apart (v3 design, fund head). */
.pgside { display: flex; flex-direction: column; gap: 20px; min-width: 0; }
@media (max-width: 1280px) {
  .v3-head .pgfigs, .v3-head .pgside { grid-column: 1 / -1; grid-row: auto; margin-top: 16px; }
  .v3-head .pgfigs { flex-wrap: wrap; }
  .v3-head .pgside > .pgfigs { margin-top: 0; }
}
.page-note { display: flex; justify-content: flex-end; gap: 10px; font-size: 13px; line-height: 1.6; color: var(--text-tertiary); }
/* Under figures it takes their width and never sets it. */
.pgfigs + .page-note { width: 0; min-width: 100%; }
.page-note > svg { flex-shrink: 0; margin-top: 2px; }
.page-note a { color: var(--text-primary); text-decoration: underline; text-underline-offset: 2px; }
.v3-page, .performance { display: flex; flex-direction: column; gap: 24px; min-width: 0; }
.v3-page .card-hd { padding: 20px 24px; }
.v3-page .card-hd h3, .performance-head h2 { font-size: 20px; font-weight: 500; letter-spacing: -.02em; }
/* A card's head is the same height with a .btn.sm in it or without (§v3 card: 20 + 24 + 20), so two
   record cards side by side keep their hairlines level — at phone width too (16 + 24 + 16), where acts
   that fold under the title keep the head's 12px from it. The portal and the staff console alike. */
.console.portal .v3-page .card-hd > .pgactions, .staff-page .card-hd > .pgactions { margin-block: -4px; }
@media (max-width: 900px) {
  .console.portal .v3-page .card-hd:has(> .pgactions), .staff-page .card-hd:has(> .pgactions) { row-gap: 16px; }
}
.v3-page .tbl th, .v3-page .tbl td { padding-left: 6px; padding-right: 6px; }
.v3-page .tbl th { padding-top: 12px; padding-bottom: 12px; }
.v3-page .tbl td { padding-top: 14px; padding-bottom: 14px; font-size: 13px; }
.v3-page .tbl th:first-child, .v3-page .tbl td:first-child { padding-left: 24px; }
.v3-page .tbl th:last-child, .v3-page .tbl td:last-child { padding-right: 24px; }
/* Transactions: v3 stat cards and state pills (DESIGN-RULES). */
.transaction-head .pghead { display: block; }
.transaction-head .pgfigs { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; margin-top: 24px; }
@media (max-width: 700px) { .transaction-head .pgfigs { grid-template-columns: 1fr; } }
.transaction-head .pgfigs > div { background: var(--bg-secondary); border-radius: var(--r-card); box-shadow: var(--shadow-sm); padding: 20px 24px; }
.transaction-head .pgfig-k { margin-bottom: 6px; }
.transaction-head .pgfig-v { font-size: 26px; }
.transactions-page .tbl .badge { background: transparent; border: 1px solid var(--border-color); border-radius: var(--r-pill); padding: 3px 10px; font-size: 12px; white-space: nowrap; }
/* Documents: the shared document list, one v3 card per year. */
.documents-page .dyear { height: auto; padding: 14px 24px; font-size: 13px; }
.documents-page .dn, .documents-page .dm { white-space: normal; overflow-wrap: anywhere; }
/* Details: keep the existing responsive record grids inside v3 cards. */
.details-page .grid2 { margin-bottom: 0; }
/* An outcome over a card that shares its grid cell stands the page's block gap over it, as the bank
   account's does; in the half-width addresses list the date stays whole and a row's two acts stack. */
.details-page .grid2 > div > .callout { margin-bottom: 24px; }
.details-page .tbl td.mx { white-space: nowrap; }
.details-page .tbl td .pgactions.end { flex-wrap: wrap; gap: 8px; }
/* An address longer than its column folds inside its cell — at any character, an address has no
   spaces — and the card does not scroll, at any width. The acts' cell is as wide as its widest
   button and no wider, so what room there is is the address's. */
.details-page .tbl td.lead { overflow-wrap: anywhere; }
.details-page .tbl td.r { width: 1%; }
/* Where the card is narrower than its four columns — a phone, and the half-width card until the
   page has its full measure (530px of card, from 1416px of window) — a row is two lines: the
   address across the card, and under it its state, its date where the width draws one, and the
   row's acts at the right. Beside the acts the address had half the card and broke mid-word, and
   between 901px and 1415px the four columns were wider than the card and it scrolled sideways.
   The state stands on the card's left edge, under the address. */
@media (max-width: 600px), (min-width: 901px) and (max-width: 1415px) {
  .details-page .tbl thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .details-page .tbl tbody tr { display: flex; flex-wrap: wrap; align-items: center; column-gap: 12px; border-bottom: 1px solid var(--border-color); }
  .details-page .tbl tbody tr:last-child { border-bottom: 0; }
  .details-page .tbl tbody td { border-bottom: 0; }
  .details-page .tbl tbody td.lead { flex: 1 0 100%; padding-bottom: 0; }
  .details-page .tbl tbody td.lead + td { padding-left: 24px; }
  .details-page .tbl tbody td.r { width: auto; margin-left: auto; }
  .details-page .tbl tbody td .pgactions.end { flex-wrap: nowrap; }
}
@media (max-width: 600px) { .details-page .tbl tbody td.lead + td { padding-left: 16px; } }
/* The Since date is drawn at every width (§Details): under 900px a table hides its .mx columns, and
   this one's is a fact the row has nowhere else — on the phone's two-line row it stands after the
   state, and between 601px and 900px the card is the page's width and holds the four columns. */
@media (max-width: 900px) { .details-page .tbl .mx { display: table-cell; } }
/* A card head in a half-width card folds its act under its title, as every card head does on a
   phone, instead of clipping it or folding the title: 16px between the two lines, the head's own
   12px once the act's -4px is taken off. */
.details-page .card-hd { flex-wrap: wrap; }
.details-page .card-hd:has(> .pgactions) { row-gap: 16px; }
/* A value folds inside its column rather than widening the card — an address has no spaces — and
   where the half-width card cannot give the value a column as wide as the label's 200px (a card
   under 480px: a window of 901px to 1315px) the row is §Key/value row's stacked one, at the card's
   own 24px inset. It follows the card's width, as the addresses' rows do; no card scrolls sideways. */
.details-page .kvside > :not(.k) { min-width: 0; overflow-wrap: anywhere; }
@media (min-width: 901px) and (max-width: 1315px) {
  .details-page .grid2 .kvside { grid-template-columns: minmax(0, 1fr) auto; gap: 4px 12px; min-height: 0; padding: 12px 24px; }
  .details-page .grid2 .kvside .k { grid-column: 1 / -1; font-size: 12px; color: var(--text-tertiary); }
}
.performance-head { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 24px; }
.pills { display: flex; flex-wrap: wrap; gap: 8px; }
.pills a { padding: 6px 16px; font-size: 13px; font-weight: 500; border: 1px solid var(--border-color); border-radius: var(--r-pill); }
.pills a.on { color: var(--bg-secondary); background: var(--text-primary); }
/* A pill is a button wearing a link (§Button: no underline under its label); the one not chosen
   answers the pointer as a ghost button does, as the company head's pills already did. */
.pills a:hover { text-decoration: none; }
.pills a:not(.on):hover { background: var(--bg-hover); }
.performance-card { padding: 24px; }
.performance-card h3 { font-size: 16px; font-weight: 500; letter-spacing: -.01em; }
.chart-caption { font-size: 13px; color: var(--text-tertiary); margin: 4px 0 16px; }
.v3-plot { overflow-x: auto; }
.v3-plot svg { display: block; width: 100%; min-width: 600px; height: auto; }
.v3-plot text { font-size: 12px; fill: var(--text-tertiary); }
.chart-grid { stroke: var(--border-color); }
.chart-axis { stroke: var(--text-muted); }
.v3-plot text.chart-axis-caption { font-size: 11px; }
.v3-legend { display: flex; flex-wrap: wrap; gap: 20px; margin-top: 16px; font-size: 12px; color: var(--text-tertiary); }
.v3-legend span, .sector-grid p { display: flex; align-items: center; gap: 8px; }
.v3-legend i { width: 10px; height: 10px; border-radius: 2px; }
.v3-legend i.line { width: 14px; height: 2px; border-radius: 0; }
.v3-legend i.dot { width: 8px; height: 8px; border-radius: var(--r-pill); }
/* DESIGN-RULES §Loading plot: the plot's box before its history arrives. */
.plot-loading {
  display: flex; align-items: center; justify-content: center;
  aspect-ratio: 1000 / 300; min-height: 180px;
  border: 1px dashed var(--border-input); border-radius: 8px;
  font-size: 13px; color: var(--text-tertiary);
  animation: plot-loading 1.2s ease infinite alternate;
}
@keyframes plot-loading { from { opacity: 1; } to { opacity: .45; } }
@media (prefers-reduced-motion: reduce) { .plot-loading { animation: none; } }
.sector-composition { display: flex; flex-wrap: wrap; align-items: center; gap: 48px; margin-top: 24px; }
.sector-composition svg { width: 240px; max-width: 100%; }
.sector-grid { flex: 1; min-width: min(280px, 100%); display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 16px 24px; }
.sector-grid > div { padding-top: 10px; }
.sector-grid p { font-size: 13px; color: var(--text-tertiary); margin-bottom: 4px; }
.sector-grid i { width: 8px; height: 8px; flex-shrink: 0; border-radius: var(--r-pill); }
.sector-grid strong { font-size: 22px; font-weight: 500; letter-spacing: -.01em; }
/* DESIGN-RULES §Updating region: the drawn view pulses until its replacement arrives. */
[data-partial-region][aria-busy="true"] :is(.card, .callout, .emptyline):not(:is(.card, .callout) *) {
  animation: plot-loading 1.2s ease .15s infinite alternate; cursor: progress;
}
@media (prefers-reduced-motion: reduce) {
  [data-partial-region][aria-busy="true"] :is(.card, .callout, .emptyline):not(:is(.card, .callout) *) {
    animation: plot-loading 0s .15s forwards;
  }
}
/* DESIGN-RULES §Veiled card: a card whose text is being written again keeps it under the dialog's veil, the toast's bubble saying so. */
.card.veiled { position: relative; }
.cardveil { position: absolute; inset: 0; z-index: 1; background: rgba(10, 11, 13, 0.42); cursor: progress; }
.cardveil-say {
  position: absolute; left: 50%; top: min(50%, 40vh); transform: translate(-50%, -50%);
  display: flex; align-items: center; gap: 10px; white-space: nowrap;
  padding: 12px 20px; border-radius: var(--r-pill);
  background: var(--text-primary); color: var(--bg-secondary);
  font-size: 13.5px; box-shadow: var(--shadow-md);
}
body.dark .cardveil-say { color: #141312; }
.cardveil-say .dots { display: inline-flex; gap: 4px; }
.cardveil-say .dots i {
  width: 5px; height: 5px; border-radius: 50%; background: currentColor; display: block;
  animation: plot-loading 1.2s ease infinite alternate;
}
.cardveil-say .dots i:nth-child(2) { animation-delay: .15s; }
.cardveil-say .dots i:nth-child(3) { animation-delay: .3s; }
@media (prefers-reduced-motion: reduce) {
  .cardveil-say .dots i { animation: none; opacity: .45; }
  .cardveil-say .dots i:nth-child(2) { opacity: .7; }
  .cardveil-say .dots i:nth-child(3) { opacity: 1; }
}
.sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
@media (max-width: 900px) {
  .v3-head .pgtitle { font-size: 21px; }
  .v3-page .card-hd, .performance-card { padding: 16px; }
}

/* Fund row (DESIGN-RULES §Fund row, v3 design): "Your investments" on the LP Overview. */
.fundrows { padding: 24px 24px 8px; }
.fundrows h2 { font-size: 20px; font-weight: 500; letter-spacing: -.02em; margin-bottom: 8px; }
.fundrow { display: flex; flex-wrap: wrap; align-items: center; gap: 16px 24px; margin: 0 -24px; padding: 22px 24px; border-top: 1px solid var(--border-color); }
.fundrow.clickable { cursor: pointer; }
.fundrow.clickable:hover { background: var(--bg-tertiary); }
.fr-name { flex: 1 1 200px; min-width: 0; }
.fr-batch, .fr-k { font-size: 12px; color: var(--text-tertiary); margin-bottom: 4px; white-space: nowrap; }
.fr-title .vdot { width: 16px; height: 16px; }
.fr-title { display: flex; align-items: center; gap: 8px; font-size: 16px; font-weight: 500; letter-spacing: -.01em; }
.fr-title a { color: inherit; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fr-figs { flex: 4 1 auto; min-width: 0; display: grid; grid-template-columns: repeat(6, minmax(max-content, 1fr)); gap: 16px 12px; }
.fr-v { font-size: 14px; font-weight: 500; font-variant-numeric: tabular-nums; white-space: nowrap; }
.fr-bar { height: 4px; margin-top: 6px; border-radius: var(--r-pill); background: var(--border-color); overflow: hidden; }
.fr-bar > div { height: 4px; border-radius: var(--r-pill); background: var(--chart-orange); }
@media (max-width: 700px) { .fr-figs { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
/* Chart hover (DESIGN-RULES §Chart, v3 design): the quarter's figures in a card; the other bars recede. */
.v3-plot { position: relative; }
.chart-hit { fill: transparent; cursor: default; }
.v3-plot svg.hovering .bar:not(.on) rect { opacity: .45; }
.chart-guide { stroke: var(--text-muted); stroke-dasharray: 3 3; visibility: hidden; }
.chart-guide.on { visibility: visible; }
.chart-tip { position: absolute; top: 8px; z-index: 2; min-width: 220px; padding: 14px 18px; pointer-events: none; background: var(--bg-secondary); border-radius: var(--r-card); box-shadow: var(--shadow-sm); }
.chart-tip-t { font-size: 14px; font-weight: 500; margin-bottom: 8px; }
.chart-tip-r { display: flex; justify-content: space-between; gap: 24px; padding: 2px 0; font-size: 13px; }
.chart-tip-r span { display: flex; align-items: center; gap: 8px; color: var(--text-tertiary); }
.chart-tip-r i { width: 8px; height: 8px; border-radius: var(--r-pill); }
.chart-tip-r b { font-weight: 500; font-variant-numeric: tabular-nums; }
.chart-tip-r.total span { padding-left: 16px; }
.chart-tip-r.total b, .chart-tip-r.total span { color: var(--text-primary); }
/* ==== v3 docs brief: pill counts and file-type icons (DESIGN-RULES §Pills, §File-type icon) ==== */
/* The count beside a pill's words is grey on every pill, chosen or not (v3 design). */
.pills a { display: inline-flex; align-items: center; gap: 8px; }
.pills a .ct { color: var(--text-muted); font-weight: 400; font-variant-numeric: tabular-nums; }
.ftype { flex-shrink: 0; display: block; }
.ftype .ftype-page { fill: var(--bg-secondary); stroke: var(--text-muted); stroke-width: 1.2; }
.ftype .ftype-fold { stroke: var(--text-muted); stroke-width: 1.2; }
.ftype text { font-size: 6.2px; font-weight: 600; fill: var(--bg-secondary); }
.ftype-pdf .ftype-tag { fill: var(--chart-orange); }
.ftype-sheet .ftype-tag { fill: var(--success-text); }
.ftype-doc .ftype-tag { fill: var(--info-text); }
.ftype-text .ftype-tag { fill: var(--text-tertiary); }
.ftype-other .ftype-tag { fill: var(--badge-text); }
/* ---- v3 fund page (brief "fund") -------------------------------------
   DESIGN-RULES §Fund capital and reporting: each section's heading above
   its card, the latest report beside its open action, the design's orange
   on the capital bars, and the Investments TVPI and status. */
.v3-page.fund-page { gap: 56px; }
/* The Overview's rhythm (DESIGN-RULES §Overview): 48px between sections, 16px
   from a section heading to its first card, 24px between the cards under it. */
.v3-page.overview-page { gap: 48px; }
.overview-page .performance > .performance-head { margin-bottom: -8px; }
/* The console's section with its heading on the page stands as the portal's does: 48px
   from the blocks round it (24px on top of the page's gap), 16px from heading to card. */
.staff-page > .performance { margin: 24px 0; }
.staff-page > .performance:last-child { margin-bottom: 0; }
.staff-page > .performance > .performance-head { margin-bottom: -8px; }
.fund-sec { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.fund-sec .performance-head .meta { font-size: 13px; color: var(--text-tertiary); }
.fund-latest-report { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: 16px 24px; }
.fund-latest-report .meta { font-size: 13px; color: var(--text-tertiary); }
.fund-latest-report h3 { margin: 10px 0 0; }
.fund-latest-open { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; }
.fund-latest-open .sub { font-size: 12px; color: var(--text-tertiary); overflow-wrap: anywhere; }
.fund-sec .dn, .fund-sec .dm { white-space: normal; overflow-wrap: anywhere; }
.fund-capital .split-1 { background: var(--chart-orange); }
.fund-capital .split-2 { background: color-mix(in srgb, var(--chart-orange) 30%, var(--bg-secondary)); }
.fund-capital .split-3 { background: var(--text-secondary); }
.fund-capital .split-4 { background: var(--border-color); }
.fund-investments .tbl td.par { color: var(--text-tertiary); }
/* The console's multiples in a table (DESIGN-RULES §3 Meaning): par is grey, and a loss
   takes the colour alone — the cell's weight is the column's, as `td.neg`'s is. */
.staff-page .tbl td .par { color: var(--text-tertiary); }
/* …but not in an opened row's facts, which are a record's fields and not a column. */
.staff-page .tbl tr.xrow .fgrid .par { color: inherit; }
.staff-page .tbl td .neg { font-weight: inherit; }
/* §Fund row's gain in the investor's fund rows of the console: the colour alone, as the loss. */
.staff-page .tbl td .pos { font-weight: inherit; }
/* A column of words after a column of figures: the figure ends at its cell's right edge and the
   words start at theirs, so the two cells' 6px + 6px would read as one value. The words stand the
   table's outer 24px from the figure. */
.staff-page .tbl :is(th, td).num + :is(th, td):not(.num, .r, .c, .xchev, .end) { padding-left: 24px; }
.fund-investments .tbl .badge { background: transparent; border: 1px solid var(--border-color); font-size: 12px; white-space: nowrap; }
.fund-investments .tbl .badge.ok { color: var(--text-primary); }
/* ── Brief tx: Transactions rows (DESIGN-RULES §Transactions — rows) ──
   The type carries its direction arrow, the fund its 6px dot, a bank reference
   is set in mono under the description. Cell classes, so the Overview's Latest
   transactions draws the same rows. */
.tbl td.tx-type { font-weight: 500; white-space: nowrap; }
.tbl td .ico { display: inline-flex; vertical-align: -3px; margin-right: 8px; }
.tbl td.tx-fund { color: var(--text-tertiary); }
.console.portal .tbl td.tx-fund { white-space: nowrap; }
/* A signed amount never leaves its sign on the line above (−$10,431.82). */
.console.portal .tbl:has(td.tx-type) td.num { white-space: nowrap; }
/* Portfolio: the cohort is a short code (YC W26) and stays on its line. */
.portfolio-page .tbl td:nth-child(2) { white-space: nowrap; }
.tbl td.tx-ref .sub { font-family: var(--font-mono); font-size: 11px; margin-top: 2px; }
/* Below the design's 960px the rows scroll inside their card rather than wrap every account line. */
.tbl:has(td.tx-type) { min-width: 960px; }
/* v3 staff console (DESIGN-RULES §Staff console in v3). The console's page is `.page.v3-page.staff-page`
   and every head is the portal's `.v3-head`; these rules add only what the console has and the
   portal does not: actions in the head, the trail back inside the sub line, and segments as pills. */
/* The console's heads carry up to six figures to the cent, which do not always fit beside the
   title: the head is §Page header's wrapping row, so the whole block of figures drops under the
   title rather than squeezing it, and the actions follow the figures on the right. */
.staff-page .v3-head .pghead { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 16px 32px; }
.staff-page .v3-head .pghead > div:first-child { display: block; flex: 1 1 auto; min-width: 0; }
/* A head with no figures beside its title has only its acts there, and they stay at the right: a
   title too long for the line folds beside them instead of pushing them under itself. The title
   keeps half the head at least; acts wider than the other half drop under it, as figures do. */
@media (min-width: 901px) {
  .staff-page .v3-head .pghead:not(:has(> .pgfigs:not(.under))) > div:first-child { flex-basis: 50%; }
}
.staff-page .v3-head .pgfigs { flex-wrap: wrap; margin-top: 0; }
.staff-page .v3-head .pgactions { padding-bottom: 0; }
/* Staff console v2, Head: a head's acts are small buttons, the filled one included. */
.staff-page .v3-head .pgactions .btn { padding: 7px 14px; font-size: 13px; }
.pgsub .up { color: var(--text-tertiary); }
.pgsub .up:hover { color: var(--text-primary); text-decoration: underline; }
.pgsub .sep { color: var(--text-muted); margin: 0 7px; }
.staff-page .segment { gap: 8px; }
.staff-page .segment .btn.sm { padding: 6px 16px; font-size: 13px; font-weight: 500; }
/* A record's tabs keep each label on one line; where eleven do not fit the column they wrap as whole tabs. */
.staff-page .tabs { flex-wrap: wrap; overflow: visible; }
.staff-page .tab { white-space: nowrap; }
/* Wrapped, every row of tabs stands on a hairline: each tab draws the rule across its own row
   (clipped by the strip), under its own 2px mark, so a chosen tab on the first row still has
   something to sit on. The strip's own border would only be under the last row. */
.staff-page .tabs { position: relative; z-index: 0; overflow: hidden; border-bottom: 0; }
.staff-page .tab { position: relative; margin-bottom: 0; }
.staff-page .tab::after {
  content: ''; position: absolute; z-index: -1; left: -100vw; right: -100vw; bottom: -2px;
  height: 1px; background: var(--border-color);
}
/* DESIGN-RULES §Tabs, Track (staff console v2 design): the two readings of one list, as pills
   on a tinted track, the open one raised onto the card's ground. As wide as its tabs. */
.staff-page .tabs.track {
  align-self: flex-start; flex-wrap: nowrap; align-items: center; gap: 4px; padding: 4px; margin-bottom: -4px;
  overflow: visible; border-radius: var(--r-pill); background: var(--bg-tertiary);
}
.staff-page .tabs.track .tab { padding: 6px 16px; font-size: 13px; border: 0; border-radius: var(--r-pill); }
.staff-page .tabs.track .tab::after { content: none; }
.staff-page .tabs.track .tab.on { background: var(--bg-secondary); box-shadow: var(--shadow-sm); }
/* Brief book-tx. DESIGN-RULES §Scrolling list card: a history of money reads in
   a card a little over half the window tall, at every width, its rows scrolling
   inside it under §Table's sticky headings. */
.tblw.scroller { max-height: 60vh; }
/* DESIGN-RULES §Table: in the external portal no table scrolls on its own, not
   even a history of money; it is as tall as its rows and the page scrolls. A
   wide one still moves sideways inside its card. */
.console.portal .tblw { max-height: none; overflow-y: visible; }
/* The portal's Search page stands outside .v3-page: its results card, its table and the heading
   over its documents are drawn as every other portal page draws them (§v3 card, §v3 table,
   §Document list's group heading). */
.console.portal .page:has(> form > .bigsearch) .card-hd { padding: 20px 24px; }
.console.portal .page:has(> form > .bigsearch) .card-hd h3 { font-size: 20px; font-weight: 500; letter-spacing: -.02em; }
.console.portal .page:has(> form > .bigsearch) .tbl :is(th, td) { padding-left: 6px; padding-right: 6px; }
.console.portal .page:has(> form > .bigsearch) .tbl tr:not(.sect) > td { padding-top: 14px; padding-bottom: 14px; font-size: 13px; }
.console.portal .page:has(> form > .bigsearch) .tbl :is(th, td):first-child { padding-left: 24px; }
.console.portal .page:has(> form > .bigsearch) .tbl :is(th, td):last-child { padding-right: 24px; }
.console.portal .page:has(> form > .bigsearch) > h2 { margin: 12px 0 -4px; font-size: 16px; font-weight: 500; letter-spacing: -0.01em; }
@media (max-width: 900px) {
  .console.portal .page:has(> form > .bigsearch) .card-hd { padding: 16px; }
  .console.portal .page:has(> form > .bigsearch) .tbl :is(th, td):first-child { padding-left: 16px; }
  .console.portal .page:has(> form > .bigsearch) .tbl :is(th, td):last-child { padding-right: 16px; }
}
/* The foot inside the box: the dots and the literal link, which without script
   is the whole mechanism and with it reads "Loading more as you scroll". */
.tblmore a { color: inherit; font-weight: 500; text-decoration: underline; text-underline-offset: 2px; }
/* The row a no-script More lands on (#row-50, #row-100 …) stops clear of the sticky top bar, as
   every jump target does (.jump): at 0 it stood under the bar and the first new row was not read. */
.tbl tr[id^="row-"] { scroll-margin-top: 80px; }
/* DESIGN-RULES §Year divider row: the gap row set roman, the year alone. */
.tbl tr.gap.yr td { font-style: normal; font-size: 13px; font-weight: 500; color: var(--text-tertiary); background: var(--bg-tertiary); }
/* DESIGN-RULES §Introducer and carry-beneficiary transactions: twelve columns
   keep each line on one line and the table moves sideways inside its card. */
.tbl:has(td.tx-rel) td { white-space: nowrap; }

/* Staff console v2 (DESIGN-RULES §Staff console v2). Measurements from the
   staff console v2 design; no colour, size or radius of its own. */
.sdot { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; white-space: nowrap; }
.sdot .d { width: 8px; height: 8px; flex-shrink: 0; border-radius: var(--r-pill); background: var(--text-muted); }
.sdot.action .d { background: var(--chart-orange); }
.sdot.ink .d { background: var(--text-primary); }
.sdot.ok .d { background: var(--chart-teal); }
.sdot.ready .d { background: var(--chart-mint); }
.sdot.quiet .d { background: var(--text-muted); }
.sdot.none .d { background: var(--border-color); }

.attention { padding-bottom: 8px; }
.attention .card-hd { align-items: baseline; padding-bottom: 12px; border-bottom: 0; }
.attention .card-hd .more, .staff-page .card-hd a.more { font-size: 13px; font-weight: 500; text-decoration: none; }
.attention .card-hd .more:hover, .staff-page .card-hd a.more:hover { text-decoration: underline; }
.att-g { margin: 12px 24px 4px; font-size: 12px; color: var(--text-tertiary); }
.att-row {
  display: flex; align-items: center; gap: 16px; width: 100%; padding: 14px 24px;
  border: 0; border-top: 1px solid var(--border-color); background: transparent;
  font: inherit; color: inherit; text-align: left; cursor: pointer;
}
.att-row:hover { background: var(--bg-hover); }
.att-row:focus-visible, .fl-hd:focus-visible, .foldsec:focus-visible { outline: 2px solid var(--accent-color); outline-offset: -2px; }
.att-l { flex: 1; min-width: 0; font-weight: 500; }
.att-n { min-width: 32px; text-align: right; font-weight: 500; font-variant-numeric: tabular-nums; }
.att-a { display: flex; align-items: center; justify-content: flex-end; gap: 4px; min-width: 64px; font-size: 13px; font-weight: 500; white-space: nowrap; }
.att-a .ic { transform: rotate(-90deg); }

.fieldcard { padding: 24px; }
.fc-hd { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 12px; margin-bottom: 16px; }
.fc-hd > :first-child { min-width: 0; }
/* Several acts in a field card's head wrap inside the card rather than run past its edge. */
.fc-hd > .pgactions { flex-shrink: 1; min-width: 0; flex-wrap: wrap; }
.fc-hd h3 { font-size: 16px; font-weight: 500; letter-spacing: -0.01em; }
.fc-note { margin-top: 4px; font-size: 12px; color: var(--text-muted); }
.fc-ft { margin-top: 16px; font-size: 13px; }
.fc-ft .foldsec { font-size: 13px; }
/* Working box: what the card's figures were computed from, behind the foot's fold heading. */
.calcbox { display: flex; flex-direction: column; gap: 8px; margin-top: 12px; padding: 14px 16px; border-radius: var(--r-nav); background: var(--bg-tertiary); font-size: 13px; }
.calcbox > div { display: flex; justify-content: space-between; gap: 16px; }
.calcbox > div > :last-child { text-align: right; }
.calcbox .cb-k { flex: none; color: var(--text-tertiary); }
/* A table in a field card's foot starts and ends at the card's own 24px, not 24px further in. */
.fc-ft .tbl :is(th, td):first-child { padding-left: 0; }
.fc-ft .tbl :is(th, td):last-child { padding-right: 0; }
/* A log in the foot ends at the card's own 24px: its last row gives up the 13px under it. */
.fc-ft .slog-row:last-child > :is(.slog-d, .slog-b, .slog-r) { padding-bottom: 0; }
.fgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 16px 24px; }
.fg-k { margin-bottom: 4px; font-size: 12px; color: var(--text-tertiary); }
.fg-v { font-size: 14px; overflow-wrap: anywhere; }
.fg-n { margin-top: 2px; font-size: 12px; color: var(--text-muted); }
/* A value that carries its own second line (an ownership's as-at and source) draws it as the note. */
.fg-v > .sub { margin-top: 2px; font-size: 12px; color: var(--text-muted); }

.mtiles { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; }
.mt-v { font-size: 18px; font-weight: 500; letter-spacing: -0.01em; font-variant-numeric: tabular-nums; }

.pipeline { display: flex; flex-wrap: wrap; align-items: stretch; gap: 8px; }
.pipeline > div { flex: 1 1 140px; padding: 12px 14px; border-radius: var(--r-nav); background: var(--bg-tertiary); }
.pl-v { font-size: 15px; font-weight: 500; }

.sbars { display: flex; flex-direction: column; gap: 14px; }
.sb-l { display: flex; justify-content: space-between; gap: 12px; margin-bottom: 6px; font-size: 13px; }
.sb-n { color: var(--text-tertiary); font-variant-numeric: tabular-nums; }
.sb-t { height: 6px; border-radius: var(--r-pill); background: var(--bg-tertiary); overflow: hidden; }
.sb-f { height: 6px; border-radius: var(--r-pill); background: var(--chart-orange); }

.xchev { display: inline-flex; color: var(--text-primary); }
td.xchev { display: table-cell; width: 14px; text-align: right; }
.xchev .ic { display: inline-flex; transition: transform .15s ease; }
.xchev.open .ic { transform: rotate(180deg); }
.tbl tr.xrow > td, .v3-page .tbl tr.xrow > td { padding: 0; background: var(--bg-primary); }
.xbody { padding: 20px 24px 24px; display: flex; flex-direction: column; gap: 16px; }
/* Under a row that leads with a company's mark: the cell's 24px, the 28px mark and its 10px gap. */
.xbody.under { padding-left: 62px; }

.foldline { padding: 0; }
.fl-hd {
  display: flex; align-items: center; gap: 10px; width: 100%; padding: 14px 24px;
  border: 0; background: transparent; font: inherit; color: inherit; text-align: left; cursor: pointer;
}
.fl-hd .sdot { font-size: 14px; font-weight: 500; }
.fl-t { font-size: 13px; color: var(--text-tertiary); min-width: 0; }
.fl-hd .xchev { margin-left: auto; }
.fl-bd { padding: 4px 24px 20px; }
.foldsec {
  display: inline-flex; align-items: center; gap: 8px; align-self: flex-start; padding: 0;
  border: 0; background: transparent; font: inherit; font-size: 14px; font-weight: 500;
  color: var(--text-primary); cursor: pointer;
}

.moremenu { position: relative; }
.moremenu > .btn { display: inline-flex; align-items: center; gap: 6px; }
.mm-scrim { position: fixed; inset: 0; z-index: 20; }
.moremenu .acct-menu { z-index: 21; }
/* On a phone a head's acts start at the left, so a panel hung from the button's right edge
   leaves the window: it opens under the button instead, between the page's gutters. */
@media (max-width: 900px) {
  .moremenu { position: static; }
  .moremenu .acct-menu { top: auto; left: 16px; right: 16px; width: auto; max-width: none; margin-top: 8px; }
}

/* Staff console v2: list controls and count. */
/* Staff console v2 — Documents. Folded into app.css by the integrator. */

/* The filter row with nothing on its left: the controls start at the page's
   edge, and the typed field takes what the pickers leave, up to 280px. */
.filterrow.lead .input.typed { flex: 1 1 220px; max-width: 280px; width: auto; }

/* List count: how many rows the filters hold. Alone, at the right over the
   list's card; inside a filter row or a list bar it closes that row. */
.listcount {
  margin: 0 0 12px; font-size: 13px; font-weight: 500;
  color: var(--text-primary); text-align: right; font-variant-numeric: tabular-nums;
}
.filterrow > .listcount, .listbar > .listcount { margin: 0 0 0 auto; white-space: nowrap; }

/* Staff console v2: a list's controls are pills (DESIGN-RULES §Filter bar, The console's
   controls are pills). The typed field and the picker over a list take --r-pill at the
   row's 36px; a form's field (§Input) keeps its 4px. */
.staff-page .filterrow .input { border-radius: var(--r-pill); }
.staff-page .filterrow .input.typed { padding: 0 14px; }
.staff-page .filterrow .input.typed svg { width: 16px; height: 16px; }
/* Picker: the select draws no arrow of its own, and the chevron beside it is the More menu's. */
.pick { position: relative; display: inline-flex; min-width: 0; max-width: 100%; }
.pick > select.input {
  -webkit-appearance: none; appearance: none; min-width: 0; max-width: 100%; height: 36px;
  padding: 0 36px 0 16px; border-radius: var(--r-pill);
  font-size: 13px; font-weight: 500; text-overflow: ellipsis; cursor: pointer;
}
.pick > .ic { position: absolute; right: 14px; top: 50%; transform: translateY(-50%); pointer-events: none; }
.staff-page .filterrow .pick > select.input { max-width: 240px; }

/* More filters: the pill that opens the filters a list is seldom narrowed by — sunken while
   its panel is open, the count of those narrowing after its words as §Pill count draws one. */
.morebtn[aria-expanded="true"] { background: var(--bg-hover); }
/* Filter panel: pickers and fields as pills under a 12px label, on the sunken ground — what
   More filters opens, and the activity log's whole filter. Clear filters closes it as words. */
.filterpanel {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: 16px;
  padding: 16px; border-radius: var(--r-card); background: var(--bg-tertiary);
}
.filterpanel .field { min-width: 0; max-width: 100%; }
.filterpanel .field-l { font-size: 12px; font-weight: 400; color: var(--text-tertiary); }
.filterpanel .input { height: 36px; padding: 0 16px; border-radius: var(--r-pill); font-size: 13px; }
.filterpanel .pick > select.input { max-width: 240px; }
.filterpanel .btn.sm { height: 36px; padding-top: 0; padding-bottom: 0; }
.filterpanel .clear {
  padding: 0 0 9px; border: 0; background: transparent; cursor: pointer;
  font: inherit; font-size: 13px; color: var(--text-tertiary); text-decoration: underline; text-underline-offset: 2px;
}
.filterpanel .clear:hover { color: var(--text-primary); }
/* Controls read together — a range's two ends and the button that sends them — fold as one. */
.filterpanel .fp-keep { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 16px; min-width: 0; }

/* Staff console v2: pill bar. */
/* Pill bar: the row over a list that holds its picker and its qualifying pills.
   §Pills' measurements: 8px gap, 13px/500, --r-pill, the hairline border. */
.pillbar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-bottom: 12px; }
.pillbar select.input {
  width: auto; max-width: 240px; height: 30px; padding: 0 36px 0 16px;
  border-radius: var(--r-pill); font-size: 13px; font-weight: 500;
}
.btn.sm.countpill { display: inline-flex; align-items: center; gap: 6px; padding: 6px 16px; font-weight: 500; }
.countpill .cp-a { font-weight: 400; color: var(--text-tertiary); }

/* Staff console v2: Portfolio and the company record. */

/* A record's status beside its title: §State dot in a hairline pill, 4px 12px. */
.statepill {
  display: inline-flex; align-items: center; padding: 4px 12px; margin-left: 12px; vertical-align: middle;
  border: 1px solid var(--border-color); border-radius: var(--r-pill); letter-spacing: 0; line-height: 1.4;
}
.statepill .sdot { font-weight: 500; }

/* The company's facts under its head: the sub line at the design's 14px. */
.staff-page .co-id { margin-bottom: 0; }
.staff-page .co-id .co-facts { font-size: 14px; }
/* §Company head — v3: the facts, description and links stand beside the mark, 12px under the title's line. */
.pg-id:has(.co-id) { align-items: flex-start; }
.pg-id .co-id { margin-top: 12px; }

/* A head button's count of what is waiting: 18px orange pill, 11px/600. */
.countbtn { display: inline-flex; align-items: center; gap: 8px; }
.countbtn .n { margin: -1px 0; }
.countbtn .n {
  min-width: 18px; height: 18px; padding: 0 5px; border-radius: var(--r-pill);
  background: var(--chart-orange); color: var(--bg-secondary);
  font-size: 11px; font-weight: 600; line-height: 18px; text-align: center; font-variant-numeric: tabular-nums;
}

/* A card heading's one link, and the buttons a tab leads with. */
.fc-hd .fc-more { font-size: 13px; font-weight: 500; text-decoration: none; }
.fc-hd .fc-more:hover { text-decoration: underline; }
.fc-hd .fc-aside { font-size: 13px; color: var(--text-secondary); }
.tabacts { margin-bottom: 12px; }

/* The latest update in a card: its meta line, its text, and the line under a rule. */
.upd-meta { margin-bottom: 8px; font-size: 12px; color: var(--text-tertiary); }
.upd-text { font-size: 14px; line-height: 1.6; text-wrap: pretty; overflow-wrap: anywhere; white-space: pre-line; }
/* A text of many paragraphs — a report read on its page — keeps the legal page's measure. */
.upd-text.long { max-width: 72ch; }
.upd-foot { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--border-color); font-size: 13px; color: var(--text-secondary); }
.upd-foot b { font-weight: 500; color: var(--text-primary); }
.mtiles + .fg-n { margin-top: 12px; }
/* A field card's one-line empty starts where its heading does; a card alone in a pair takes the row. */
.fieldcard > .emptyline { padding: 0; }
.staff-page .grid2 > .fieldcard:only-child { grid-column: 1 / -1; }
/* An extract card with nothing in it is not drawn: the one beside it takes the row, and a row of none is not there. */
.staff-page .grid2 > .card:only-child { grid-column: 1 / -1; }
.staff-page .grid2:empty { display: none; }

/* A holding's tranches under its facts: 13px lines, a rule above each. */
.histlines { margin-top: 20px; }
.histlines .hl { display: flex; justify-content: space-between; gap: 12px; padding: 8px 0; border-top: 1px solid var(--border-color); font-size: 13px; }
.histlines .hl-n { font-variant-numeric: tabular-nums; }
/* A line that ends in an act: the figure and its words stay on one line, the words 12px after it. */
.histlines .hl-n:has(.cellact) { display: inline-flex; align-items: baseline; gap: 12px; flex: none; white-space: nowrap; }
.histlines .hl.sum { font-weight: 600; border-top-color: var(--text-primary); }
/* In an opened row the lines stand under the part's own title, and each part keeps its title 12px over what it heads. */
.xcols > div { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.xcols .histlines { margin-top: 0; }

/* A section a tab folds away sits between cards at the page's rhythm. */
.staff-page .foldsec { margin: 0; }

/* Staff console v2: Administration's list bar, row acts and form in a field card. */
/* List bar: what narrows a list on the left, its count or its act at the right. */
.listbar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; margin-bottom: 12px; }
.listbar .filterrow form { margin-left: 0; }
.listbar > .pgactions { margin-left: auto; }
.filterrow input.input[type="datetime-local"] { width: auto; }

/* Row acts: the small buttons that end a row, in its last cell. */
.rowacts { display: flex; justify-content: flex-end; align-items: center; gap: 8px; white-space: nowrap; }
/* The same line in a column that reads from the left: a state, then its act. */
.rowacts.start { justify-content: flex-start; }

/* Field card holding a form before its facts. */
.fieldcard > .fields { margin-bottom: 16px; }
.fieldcard > .callout { margin-top: 16px; }

/* Staff console v2: Investors and the investor record. */
/* A record's facts on the sub line under its head, and its figures under them.
   The page's 24px gap is too much between the three, so they close up. */
.recfacts {
  display: flex; align-items: center; flex-wrap: wrap; gap: 4px 0;
  margin: -16px 0 0 -20px; font-size: 14px; color: var(--text-tertiary);
  /* Every fact stands 20px after the last with its dot in that space; the row
     starts 20px out, and the dot before the fact that opens a row is cut. */
  clip-path: inset(-4px -4px -4px 16px);
}
.recfacts > .rf { position: relative; padding-left: 20px; }
.recfacts > .rf::before {
  content: "·"; position: absolute; left: 0; width: 20px; text-align: center; color: var(--text-muted);
}
.recfacts .sdot { font-size: 14px; color: var(--text-primary); }
.recstate { display: inline-flex; align-items: center; gap: 6px; }
.recfigs { gap: 16px 40px; flex-wrap: wrap; white-space: nowrap; margin-top: -4px; }

/* Several state dots in one cell: one under another, 4px apart. */
.sdots { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; }

/* The act at the right end of a filter row whose controls start at the left. */
.filterrow > .btn.end { margin-left: auto; }
.filterrow > .btn.sm.end { height: 36px; padding-top: 0; padding-bottom: 0; }

/* A fund named in a row: its 6px mark and its name on one line. */
.tbl td .fundname { display: inline-flex; align-items: center; gap: 8px; white-space: nowrap; }

/* Staff console v2: Funds and a fund's pages. */
/* Head: the figures under the title (the head is a wrapping row; the block of
   figures takes a whole line of it), and the record's facts on the sub line. */
.staff-page .v3-head .pgfigs.under { flex: 0 0 100%; }
.btn.sm.ib { display: inline-flex; align-items: center; gap: 6px; }
.btn.sm.ib[aria-current="page"] { background: var(--bg-tertiary); }

/* The line over a list: search pill left, the list's own acts right. */
.sline { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.sline > .filterrow { flex: 1 1 240px; margin: 0; }
.sline > .filterrow .input.typed { max-width: 360px; }
.sline > .pgactions .btn.sm { height: 36px; padding-top: 0; padding-bottom: 0; }
/* The list count closing the search line, before the list's acts. */
.sline .listcount { margin: 0; white-space: nowrap; }

/* Expanding row whose chevron is its own control. */
.xbtn { display: inline-flex; padding: 4px; border: 0; background: transparent; color: inherit; cursor: pointer; }
.xbtn:focus-visible { outline: 2px solid var(--accent-color); outline-offset: 2px; }
.xtitle { font-size: 14px; font-weight: 500; }
.tbl tr.xrow .xtitle { font-size: 12px; color: var(--text-tertiary); }
/* The columns a phone's table leaves out, in the opened row: absent where the columns say it. */
.mfold-rest { display: none; }
.xacts { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
/* A reader with no act on the row gets no empty line where the acts would be. */
.xacts:empty { display: none; }
.xcols { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 16px 32px; align-items: start; }

/* The matrix of investors and companies: the investor and their total stay
   while the companies scroll sideways, and the headings stay with the fund's
   total under them while the investors scroll. Narrow columns in whole
   dollars; a name folds rather than widens its column. */
/* It is the one table that scrolls inside its card, having two directions to
   scroll in: it reads in what the window has left under a fund's head, so both
   of its scrollbars are on screen at once. 400px is the top bar, that head and
   the page's foot, and 280px the least it is worth scrolling in. */
.tblw:has(> .tbl.matrix) { max-height: max(280px, calc(100vh - 400px)); }
/* Its borders are each cell's own: a collapsed one belongs to the table, and
   stays behind when the cell it closes does not. */
.tbl.matrix { border-collapse: separate; border-spacing: 0; }
.tbl.matrix th, .tbl.matrix td {
  min-width: 88px; padding-left: 10px; padding-right: 10px;
  white-space: nowrap; font-variant-numeric: tabular-nums;
}
.tbl.matrix thead { position: sticky; top: 0; z-index: 3; }
/* The section is what stays, its cells with it: a heading keeps §Table's own
   stickiness for the two columns that stay sideways and nothing else. */
.tbl.matrix thead th { top: auto; max-width: 88px; white-space: normal; vertical-align: bottom; }
.tbl.matrix tr.total td { border-top: 0; }
.tbl.matrix :is(th, td):nth-child(-n+2) { position: sticky; z-index: 1; background: var(--bg-secondary); }
.tbl.matrix :is(th, td):first-child {
  left: 0; width: 176px; min-width: 176px; max-width: 176px; padding-left: 16px;
  white-space: normal; overflow-wrap: anywhere;
}
.tbl.matrix :is(th, td):nth-child(2) { left: 176px; border-right: 1px solid var(--border-color); }
.tbl.matrix thead th:nth-child(-n+2) { z-index: 3; }
.tbl.matrix tr.total td:nth-child(-n+2) { background: var(--bg-tertiary); }
.tbl.matrix th a { color: inherit; text-decoration: none; }
.tbl.matrix th a:hover { text-decoration: underline; }
.tbl.matrix tbody tr.clickable:hover td:nth-child(-n+2) { background: var(--bg-tertiary); }

/* A document or a report as a row: its type icon, then title over "kind · date". */
.docline { display: flex; align-items: center; gap: 12px; min-width: 0; }
.docline .ic { color: var(--text-tertiary); flex-shrink: 0; }
/* The §File-type icon leading a document line (console: `FileTypeIcon`). */
.docline .ftype-ic, .doc .ftype-ic { display: flex; flex-shrink: 0; }

/* Staff console v2: Tasks. Cell act and default value. */

/* Cell act: a cell's words or its state dot as the control that opens the
   record they stand for or changes the value they hold. A bare button; the
   underline is the sign, and a state dot's word takes it for itself. */
.cellact {
  display: inline-block; padding: 0; border: 0; background: transparent;
  font: inherit; color: inherit; text-align: inherit; cursor: pointer;
}
.cellact:hover, .cellact:hover .sdot > span:last-child { text-decoration: underline; }
/* The words form: an act after a value, in the card link's 13px/500 (.fc-more), 8px after it. */
.cellact.more { margin-left: 8px; font-size: 13px; font-weight: 500; }
/* In a field card's value the act wraps under the value it acts on, flush with it, not 8px in. */
.fg-v:has(> .cellact.more) { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 8px; }
.fg-v > .cellact.more { margin-left: 0; }
.cellact:disabled { color: var(--text-tertiary); cursor: default; text-decoration: none; }
/* A state dot among a record's 14px values takes their size. */
.fg-v .sdot, .kv-v .sdot, .kvside .sdot { font-size: inherit; }

/* Default value: what the record supplies where nobody set one — the owning
   role in place of an assignee, the record's date in place of a set one. */
.tbl td .dflt { color: var(--text-tertiary); }

/* A list's state pills under its controls: the pill bar's own 12px between them. */
.filterrow.lead + .pillbar { margin-top: 0; }
/* The page's blocks stand 24px apart (.v3-page's gap). A bar over a list belongs to the
   list: 12px above the next bar or the card, whatever margin it carries elsewhere. */
.staff-page > :is(.filterrow, .filterpanel, .pillbar, .listbar, .listcount, .sline, .tabacts) { margin-top: 0; margin-bottom: -12px; }
/* A lead row is one line that wraps: its form's fields stand in the row itself, 8px from one
   another and from what follows them — the state pills, the More filters pill, the count —
   and the lines it folds into are 12px apart. */
.filterrow.lead { row-gap: 12px; }
.filterrow.lead form { display: contents; }

/* Keyboard focus (DESIGN-RULES §8, §Focus ring). Every control that is not a field shows the
   header's ring — 2px of ink, 2px off — when the keyboard reaches it; a field darkens its
   border (§Input). :where() keeps this at no specificity, so a control that needs the ring
   inside its own box says so below and wins. */
:where(a, button, summary, select, [tabindex], [role="button"]):focus-visible {
  outline: 2px solid var(--accent-color); outline-offset: 2px;
}
/* Inside a box that clips — a card's rows, a table, a menu, the tab strip — the ring is drawn
   inside the control. */
.tab:focus-visible, .tbl tr:focus-visible, .tbl th:focus-visible, .fundrow:focus-visible,
.drow a:focus-visible, .opt:focus-visible, .popt:focus-visible, .pnone:focus-visible,
.acct-menu .acct-row:focus-visible, .tbl td a:focus-visible, .tbl .cellact:focus-visible,
.navlink:focus-visible, .tblmore a:focus-visible { outline-offset: -2px; }
.cellact:focus-visible, .def:focus-visible { border-radius: var(--r-input); }
.check:focus-visible { outline-offset: 4px; border-radius: var(--r-input); }

/* Staff console v2, below the breakpoint (DESIGN-RULES §Staff console v2, Phone). */
@media (max-width: 900px) {
  /* A card's parts share one left edge: the head, a table's first cell, a field card, a row
     that is a button — all on the card's 16px. */
  .v3-page .tbl th:first-child, .v3-page .tbl td:first-child { padding-left: 16px; }
  .v3-page .tbl th:last-child, .v3-page .tbl td:last-child { padding-right: 16px; }
  .mcols { padding: 10px 16px; }
  .fieldcard { padding: 16px; }
  .att-row, .fl-hd { padding-left: 16px; padding-right: 16px; }
  .att-g { margin-left: 16px; margin-right: 16px; }
  .fl-bd { padding: 4px 16px 16px; }
  /* Cards that stood side by side stack a block apart, as every other block of the page does. */
  .staff-page .grid2, .staff-page .cols { gap: 24px; }
  /* A fold line on a phone: its sentence under its state, the chevron beside both. */
  .fl-hd { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 2px 10px; }
  .fl-hd .fl-t { grid-column: 1; grid-row: 2; }
  .fl-hd .xchev { grid-column: 2; grid-row: 1 / span 2; align-self: center; margin-left: 0; }
  .xbody, .xbody.under { padding: 16px; }
  .fundrows { padding: 16px 16px 8px; }
  .fundrow { margin: 0 -16px; padding-left: 16px; padding-right: 16px; }
  .documents-page .dyear { padding: 14px 16px; }
  .fund-capital .card-bd, .fund-latest-report { padding: 16px; }
  .fund-earlier-reports { padding: 12px 16px; }

  /* List controls: the typed field takes the line, the pickers pair, none overruns. */
  .filterrow.lead .input.typed, .sline > .filterrow .input.typed { flex: 1 1 100%; max-width: none; }
  .filterrow select.input, .filterrow input.input { min-width: 0; }
  .pillbar select.input { max-width: 100%; }
  .filterpanel .field { flex: 1 1 44%; }
  .filterpanel .fp-keep { flex: 1 1 100%; }
  .filterpanel .pick, .filterpanel .field > .input { width: 100%; }
  .filterpanel .pick > select.input { width: 100%; max-width: none; }
  .staff-page .filterrow .pick > select.input { max-width: 100%; }
  /* …of a bar that is itself no wider than the page: beside a section's heading the bar is a flex
     item, and a 70-character fund name in the picker widened the bar, and the page with it, to 553px. */
  .pillbar { min-width: 0; max-width: 100%; }
  .pillbar select.input { min-width: 0; }
  .mtiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  /* Phone table, console: every column, at the width its content needs, the table moving
     sideways inside its card and the page carrying the only vertical scroll, the matrix's
     included. Nothing is squeezed, dropped or announced: a cell folds only past 280px. */
  .staff-page .tblw:has(> .tbl.matrix) { max-height: none; }
  .staff-page .tbl { width: max-content; min-width: 100%; }
  .staff-page .tbl th { white-space: nowrap; }
  .staff-page .tbl td { max-width: 280px; }
  .staff-page .tbl .mx, .staff-page .tbl th.dx { display: table-cell; }
  .staff-page .tbl th.mo { display: none; }
  .staff-page .mcols { display: none; }
  /* §Phone columns in the console: a table that names its phone columns shows those alone, at the
     card's width, and what it leaves out stands first in the row's opened cell. */
  .staff-page .tbl.mfold { width: 100%; min-width: 0; }
  .staff-page .tbl.mfold .mx { display: none; }
  .staff-page .tbl.mfold th { white-space: normal; }
  .staff-page .tbl.mfold .xbody { position: static; width: auto; }
  .mfold-rest { display: block; }
  /* What a row opens stays in the window while the table moves under it. */
  .staff-page .tbl tr.xrow > td { max-width: none; }
  .staff-page .xbody { position: sticky; left: 0; width: calc(100vw - 28px); }
  /* …and so does a row's sentence (`tr.sub > td[colspan] > .rowsent`): it folds inside the card's
     width, 16px from its edge as the cell's own padding has it, instead of running on with the table. */
  .staff-page .tbl tr.sub > td[colspan] { max-width: none; }
  .staff-page .tbl tr.sub > td[colspan] > .rowsent { position: sticky; left: 16px; width: calc(100vw - 60px); }
  /* §Event log: the fourth column goes under what happened, at the left, as a §Timeline's when does;
     beside it the text had 126px at 390. */
  .staff-page .slog-row { grid-template-columns: 96px 22px minmax(0, 1fr); }
  .staff-page .slog-rail { grid-row: span 2; }
  .staff-page .slog-b { padding-bottom: 0; }
  .staff-page .slog-r { grid-column: 3; padding: 2px 0 13px 8px; text-align: left; white-space: normal; }
}
