/* ============================================================
   AC Portfolio Overview — v1
   Matches Claude Design: Portfolio Dashboard.html
   Quicksand for numbers, Marcellus for headings.
   ============================================================ */

/* ── Series palette (categorical) ───────────────────────────
   Chart series colours are a PRESENTATION concern, assigned by fixed slot
   order — never cycled, never taken from the data payload, never derived
   from a value's rank. Every step below passed the six-check validator
   (lightness band, chroma floor, CVD separation, normal-vision floor,
   contrast) in its own mode. Dark is RE-STEPPED, not an automatic flip.

   The previous palette (#1E3A5F/#1A5C45/#4E7A97/#2E5885/#9BB3C5) failed
   three checks: all five sat below the 0.10 chroma floor (they read as
   grey and stopped carrying identity), two fell outside the lightness
   band, and the worst pair scored ΔE 11.1 on the normal-vision floor —
   below 15, i.e. hard to tell apart even with full colour vision.

   The brand navy/blue-greys are deliberately NOT used here: #4E7A97 has
   chroma 0.066 and #161C33 lightness 0.233, so both fail as data colours.
   Brand stays in the chrome (Marcellus headings, navy nav, cream surfaces).
   ─────────────────────────────────────────────────────────── */
.pf-overview {
  --pf-series-1: #2a78d6;  /* blue    */
  --pf-series-2: #008300;  /* green   */
  --pf-series-3: #e87ba4;  /* magenta */
  --pf-series-4: #eda100;  /* yellow  */
  --pf-series-5: #1baf7a;  /* aqua    */
  --pf-series-6: #eb6834;  /* orange  */
  --pf-series-7: #4a3aa7;  /* violet  */
  --pf-series-8: #e34948;  /* red     */
  --pf-surface:  #ffffff;  /* the 2px gap between touching marks */
}

[data-theme="dark"] .pf-overview {
  --pf-series-1: #3987e5;
  --pf-series-2: #008300;
  --pf-series-3: #d55181;
  --pf-series-4: #c98500;
  --pf-series-5: #199e70;
  --pf-series-6: #d95926;
  --pf-series-7: #9085e9;
  --pf-series-8: #e66767;
  --pf-surface:  #0D1B2E;
}

/* ── Container ─────────────────────────────────────────────── */
.pf-overview {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 0 0 32px;
}

.pf-label {
  display: flex;
  align-items: center;
  gap: 7px;
  font-family: 'Quicksand', sans-serif;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--brand, #4E7A97);
  margin-bottom: 6px;
}

.pf-label-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--brand, #4E7A97);
  flex-shrink: 0;
}

.pf-title {
  font-family: 'Marcellus', serif;
  font-size: 40px;
  font-weight: 400;
  color: var(--ink, #0D1B2E);
  line-height: 1.1;
  margin: 0 0 6px;
}

.pf-subtitle {
  font-family: 'Quicksand', sans-serif;
  font-size: 14px;
  color: var(--muted, #526073);
  margin: 0;
}

/* Currency selector, in the header beside the as-at date. The pills themselves
   are .pf-perf-tab — the same control the cash-flow period selector uses — so
   this only has to place them. Right-aligned to match the rest of the meta
   block, and allowed to wrap on a narrow screen rather than squash. */
.pf-ccy-toggle {
  display: flex;
  gap: 4px;
  justify-content: flex-end;
  flex-wrap: wrap;
  margin-top: 6px;
}

/* ── Card base ───────────────────────────────────────────────── */
/* ── Portfolio surfaces ──────────────────────────────────────── */
/* Two fills, and only two: --pf-surface is a card, --pf-surface-inset is a
   shape sitting INSIDE a card. Dark mode pins them to literal values because
   the themed tokens resolved to four slightly different navies across these
   cards, which is what made the tab look patchy. There was a third,
   --pf-surface-alt, which made Scheduled Transactions the one cream card on
   the tab; it was removed rather than restyled, because a single card in its
   own colour reads as a state the reader then goes looking for. */
:root {
  --pf-surface: var(--panel, rgba(255,255,255,0.98));
  --pf-surface-inset: #FAF6EF;
}
:root[data-theme="dark"] {
  --pf-surface: #0F1D30;
  --pf-surface-inset: #192D42;
}

.pf-card {
  background: var(--pf-surface);
  border: 1px solid var(--line, rgba(13,27,46,0.10));
  border-radius: 16px;
  padding: 24px 28px;
}

/* ── Two-column row ─────────────────────────────────────────── */
.pf-row-2col {
  display: grid;
  grid-template-columns: 1.5fr 1fr;
  gap: 16px;
}

@media (max-width: 680px) {
  .pf-row-2col { grid-template-columns: 1fr; }
  .pf-title { font-size: 29px; }
}

/* ── Total Portfolio Value ───────────────────────────────────── */
.pf-card-eyebrow {
  font-family: 'Quicksand', sans-serif;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted, #526073);
  margin: 0 0 12px;
}

/* ── Total value card header ──────────────────────────────────── */
.pf-total-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 10px;
  flex-wrap: wrap;
}

.pf-total-head .pf-card-title {
  margin-bottom: 0;
  flex: 1;
}

/* ── Performance period tabs ──────────────────────────────────── */
.pf-perf-tabs {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
}

.pf-perf-tab {
  appearance: none;
  -webkit-appearance: none;
  font-family: 'Quicksand', sans-serif;
  font-size: 11px;
  font-weight: 600;
  color: #161C33;
  background: transparent;
  border: 1px solid rgba(22,28,51,0.3);
  border-radius: 999px;
  padding: 4px 10px;
  cursor: pointer;
  box-shadow: none;
  transition: color 0.15s, background 0.15s, border-color 0.15s;
  white-space: nowrap;
}

.pf-perf-tab:hover {
  border-color: #161C33;
  color: #161C33;
}

.pf-perf-tab--active {
  background: #161C33;
  color: #fff !important;
  border-color: #161C33;
}

/* ── Dark mode ─────────────────────────────────────────────── */
[data-theme="dark"] .pf-perf-tab {
  color: rgba(197,209,220,0.45);
  border-color: #1B2E43;
}

[data-theme="dark"] .pf-perf-tab:hover {
  color: rgba(197,209,220,0.75);
}

[data-theme="dark"] .pf-perf-tab--active {
  background: #1B2E43;
  color: #8AAFC8;
  border-color: #1B2E43;
}

/* ── Custom cash-flow range ───────────────────────────────────── */
/* Shown only when the Custom period button is selected. Inputs are
   native type="date" so they can be typed into or picked from the
   calendar without shipping a date widget. */
.pf-cf-range {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  align-items: flex-end;
  margin-top: 8px;
}

.pf-cf-range--hidden { display: none; }

.pf-cf-range-field {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.pf-cf-range-label {
  font-family: 'Quicksand', sans-serif;
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: rgba(22,28,51,0.55);
}

.pf-cf-range-input {
  appearance: none;
  -webkit-appearance: none;
  font-family: 'Quicksand', sans-serif;
  font-size: 11px;
  font-weight: 600;
  color: #161C33;
  background: transparent;
  border: 1px solid rgba(22,28,51,0.3);
  border-radius: 8px;
  padding: 4px 8px;
  cursor: text;
  box-shadow: none;
  transition: border-color 0.15s, color 0.15s;
}

/* Hover and focus change colour only — never size or position. */
.pf-cf-range-input:hover,
.pf-cf-range-input:focus {
  border-color: #161C33;
  outline: none;
}

.pf-cf-range-input::-webkit-calendar-picker-indicator {
  cursor: pointer;
  opacity: 0.5;
}

.pf-cf-range-input::-webkit-calendar-picker-indicator:hover { opacity: 1; }

[data-theme="dark"] .pf-cf-range-label { color: rgba(197,209,220,0.45); }

[data-theme="dark"] .pf-cf-range-input {
  color: rgba(197,209,220,0.75);
  border-color: #1B2E43;
}

[data-theme="dark"] .pf-cf-range-input:hover,
[data-theme="dark"] .pf-cf-range-input:focus { border-color: #8AAFC8; }

[data-theme="dark"] .pf-cf-range-input::-webkit-calendar-picker-indicator {
  filter: invert(1);
}

/* ── Period return badge ──────────────────────────────────────── */
.pf-return-badge-slot {
  display: inline-flex;
  align-items: baseline;
  margin-left: 6px;
}

.pf-return-badge {
  font-family: 'Quicksand', sans-serif;
  font-size: 15px;
  font-weight: 700;
  padding: 2px 8px;
  border-radius: 999px;
  line-height: 1.4;
}

.pf-return-badge--pos {
  background: rgba(19, 102, 57, 0.10);
  color: #136639;
}

.pf-return-badge--neg {
  background: rgba(140, 36, 18, 0.10);
  color: #8C2412;
}

/* ── Hero ────────────────────────────────────────────────────── */
/* Themed through local custom properties rather than two full rule sets:
   every rule below reads a --hero-* value, and only the values change between
   light and dark. Adding a colour means adding it in one place. */
.pf-hero {
  --hero-bg: linear-gradient(140deg, #FFFFFF 0%, #FBF8F3 55%, #F6F1E8 100%);
  --hero-fg: #0D1B2E;
  --hero-fg-soft: rgba(13,27,46,0.60);
  --hero-fg-faint: rgba(13,27,46,0.45);
  --hero-rule: rgba(13,27,46,0.12);
  --hero-gold: #9A7B33;
  --hero-chip-bg: rgba(13,27,46,0.04);
  --hero-chip-border: rgba(13,27,46,0.12);
  --hero-pos: #136639;
  --hero-neg: #8C2412;
  --hero-tree: url('./tree-light.svg');
  --hero-tree-opacity: 0.07;

  position: relative;
  overflow: hidden;
  border-radius: 20px;
  padding: 30px 32px 26px;
  /* No margin-bottom. The hero's only two render paths both place it inside
     .pf-overview, a flex column with gap:16px, so a 16px margin here stacked on
     top of that gap: 32px under the hero against 16px everywhere else, and 16px
     between the two cards beside it. The gap owns the spacing. */
  border: 1px solid var(--hero-rule);
  background: var(--hero-bg);
  color: var(--hero-fg);
}

:root[data-theme="dark"] .pf-hero {
  --hero-bg:
    radial-gradient(120% 160% at 78% 8%, #16233A 0%, rgba(22,35,58,0) 60%),
    linear-gradient(140deg, #0F1D30 0%, #12223A 55%, #0D1A2B 100%);
  --hero-fg: #FFFFFF;
  --hero-fg-soft: rgba(244,241,236,0.62);
  --hero-fg-faint: rgba(244,241,236,0.50);
  --hero-rule: rgba(244,241,236,0.12);
  --hero-gold: #C9A961;
  --hero-chip-bg: rgba(244,241,236,0.05);
  --hero-chip-border: rgba(244,241,236,0.16);
  --hero-pos: #7FBF9A;
  --hero-neg: #E08D7E;
  --hero-tree: url('./tree-dark.svg');
  --hero-tree-opacity: 0.10;
}

/* The AC tree, set large and low-contrast behind the date. Its own element so
   it can be positioned and faded without touching the panel's gradient. */
.pf-hero-watermark {
  position: absolute;
  top: 50%;
  right: 2%;
  transform: translateY(-50%);
  width: 300px;
  height: 300px;
  pointer-events: none;
  opacity: var(--hero-tree-opacity);
  background-image: var(--hero-tree);
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
}

.pf-hero-top {
  position: relative;
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 28px;
}

.pf-hero-eyebrow {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 14px;
  font-family: 'Quicksand', sans-serif;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--hero-gold);
}

.pf-hero-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--hero-gold);
  flex-shrink: 0;
}

.pf-hero-label {
  margin: 0 0 8px;
  font-family: 'Quicksand', sans-serif;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--hero-fg-soft);
}

.pf-hero-value {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin: 0 0 18px;
}

.pf-hero-ccy-sym {
  font-family: 'Marcellus', Georgia, serif;
  font-size: 20px;
  color: var(--hero-fg-soft);
}

.pf-hero-number {
  font-family: 'Marcellus', Georgia, serif;
  font-size: 46px;
  line-height: 1;
  letter-spacing: -0.005em;
  color: var(--hero-fg);
}

.pf-hero-meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px 14px;
}

.pf-hero-growth {
  display: inline-flex;
  align-items: baseline;
  gap: 7px;
  padding: 8px 15px;
  border-radius: 999px;
  border: 1px solid var(--hero-chip-border);
  background: var(--hero-chip-bg);
  font-family: 'Quicksand', sans-serif;
  font-size: 13px;
  font-weight: 600;
}

.pf-hero-growth-label {
  font-weight: 500;
  color: var(--hero-fg-soft);
}

.pf-hero-growth--pos { color: var(--hero-pos); }
.pf-hero-growth--neg { color: var(--hero-neg); }

.pf-hero-risk {
  font-family: 'Quicksand', sans-serif;
  font-size: 13px;
  color: var(--hero-fg-soft);
}

.pf-hero-side {
  text-align: right;
  flex-shrink: 0;
}

.pf-hero-asat-label {
  margin: 0 0 8px;
  font-family: 'Quicksand', sans-serif;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--hero-fg-faint);
}

.pf-hero-asat-date {
  margin: 0 0 14px;
  font-family: 'Marcellus', Georgia, serif;
  font-size: 24px;
  line-height: 1;
  color: var(--hero-fg);
}

.pf-hero-ccy-toggle {
  display: inline-flex;
  gap: 8px;
}

.pf-hero-ccy-btn {
  padding: 7px 17px;
  border-radius: 999px;
  border: 1px solid var(--hero-chip-border);
  background: transparent;
  color: var(--hero-fg-soft);
  font-family: 'Quicksand', sans-serif;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.pf-hero-ccy-btn:hover { border-color: var(--hero-gold); }

.pf-hero-ccy-btn:focus-visible {
  outline: 2px solid var(--hero-gold);
  outline-offset: 2px;
}

.pf-hero-ccy--active {
  background: var(--hero-gold);
  border-color: var(--hero-gold);
  color: #0D1B2E;
}

.pf-hero-products {
  position: relative;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 24px;
  margin-top: 22px;
  padding-top: 20px;
  border-top: 1px solid var(--hero-rule);
}

.pf-hero-product {
  /* A button, restyled flat: the affordance is the ↗ cue and the hover lift,
     not chrome. text-align matches the old div so nothing shifts.

     display:block is load-bearing, not tidiness. This is a real <button>, and
     the client portal's global button rule sets inline-flex + centred content,
     which laid the name and the value side by side in the middle of each column
     instead of stacked at its left edge. The staff portal's global rule sets no
     display, so the same markup stacked correctly there and the two portals
     disagreed on a shared component. Stated here so the component does not
     depend on which page's button styles happen to reach it. */
  display: block;
  border: none;
  background: transparent;
  padding: 6px 8px;
  margin: -6px -8px;
  border-radius: 10px;
  text-align: left;
  font: inherit;
  color: inherit;
  cursor: pointer;
  transition: background 0.14s ease;
}

.pf-hero-product:hover,
.pf-hero-product:focus-visible {
  background: var(--hero-chip-bg);
}

.pf-hero-product:focus-visible {
  outline: 2px solid var(--hero-gold);
  outline-offset: 2px;
}

/* Always visible, never hover-only: it is the only thing telling a client the
   account row opens, and a cue that appears once you are already pointing at
   the row has arrived too late to invite the click. Faint at rest, and it
   firms up on hover — colour change, which is this portal's affordance. */
.pf-hero-product-cue {
  margin-left: 6px;
  font-size: 11px;
  color: var(--hero-fg-faint);
  opacity: 1;
  transition: color 0.14s ease;
  display: inline-flex;
  align-items: center;
  vertical-align: -2px;
}

.pf-hero-cue-icon {
  width: 14px;
  height: 14px;
  display: block;
}

.pf-hero-product:hover .pf-hero-product-cue,
.pf-hero-product:focus-visible .pf-hero-product-cue {
  color: var(--hero-fg-soft);
}

.pf-hero-product + .pf-hero-product {
  padding-left: 24px;
  margin-left: 0;
  border-left: 1px solid var(--hero-rule);
  border-radius: 0 10px 10px 0;
}

.pf-hero-product-name {
  margin: 0 0 6px;
  font-family: 'Quicksand', sans-serif;
  font-size: 13px;
  color: var(--hero-fg-soft);
}

.pf-hero-product-value {
  margin: 0;
  font-family: 'Quicksand', sans-serif;
  font-size: 17px;
  font-weight: 600;
  color: var(--hero-fg);
}

/* Who the account is with, alongside the product name — quieter than the
   name, because the product is what the client is looking for and the
   institution is how they confirm they have found it. */
.pf-hero-product-inst {
  color: var(--hero-fg-faint);
  font-weight: 500;
}

/* The account number. Small, monospaced-by-tracking rather than by font: a
   real monospace face next to Quicksand looks like a bug, but a number read
   off a statement needs its digits to sit still. */
.pf-hero-product-acct {
  margin: 0 0 6px;
  font-family: 'Quicksand', sans-serif;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--hero-fg-faint);
}

/* Past three accounts the strip stops being a row and becomes a grid — three
   across, wrapping. Left as one row, each extra account just made every
   column narrower, and six accounts came out as six unreadable slivers.
   The vertical dividers go with it: a lattice of rules through a wrapped grid
   reads as a table, and these are not table rows. */
@media (min-width: 861px) {
  .pf-hero-products--grid {
    grid-auto-flow: row;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    row-gap: 18px;
  }
  .pf-hero-products--grid .pf-hero-product + .pf-hero-product {
    padding-left: 8px;
    margin-left: -8px;
    border-left: none;
    border-radius: 10px;
  }
}

@media (max-width: 860px) {
  .pf-hero { padding: 24px 22px 20px; }
  .pf-hero-top { flex-direction: column; gap: 20px; }
  .pf-hero-side { text-align: left; }
  .pf-hero-number { font-size: 36px; }
  .pf-hero-asat-date { font-size: 21px; }
  .pf-hero-watermark { width: 190px; height: 190px; right: -20px; }
  /* Columns become rows: three side-by-side products are unreadable narrow. */
  .pf-hero-products { grid-auto-flow: row; gap: 16px; }
  .pf-hero-product + .pf-hero-product {
    padding-left: 0;
    padding-top: 16px;
    border-left: none;
    border-top: 1px solid var(--hero-rule);
    /* The divider is this element's own top border, so any radius on the top
       corners bends the line's ends. Stacked, the rule sits along the top, so
       the top corners go square and the line runs straight across; the bottom
       corners keep their radius for the hover fill. (Desktop keeps
       0 10px 10px 0 — there the divider is on the LEFT, and the same logic
       squares that edge instead.) */
    border-radius: 0 0 10px 10px;
  }
}

/* ── Contributions & Withdrawals ──────────────────────────────── */
/* Two inset tiles, label above a large figure, then the net flow on its own
   line in the display serif. The tile tint is a token so dark mode has a real
   value — a hard-coded cream turns into a glowing block on the dark panel. */
.pf-cashflow-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 18px;
}

.pf-cashflow-tile {
  /* Neutral, not cream. An inset still has to read as inset, so this is a
     tint of the ink rather than no fill at all. Dark mode keeps the shared
     inset navy, which was never the problem. */
  background: rgba(13, 27, 46, 0.04);
  border-radius: 12px;
  padding: 14px 16px 16px;
}

:root[data-theme="dark"] .pf-cashflow-tile {
  background: var(--pf-surface-inset);
}

.pf-cashflow-tile-label {
  margin: 0 0 6px;
  font-family: 'Quicksand', sans-serif;
  font-size: 13px;
  font-weight: 500;
  color: var(--muted, #526073);
}

.pf-cashflow-tile-amount {
  margin: 0;
  font-family: 'Quicksand', sans-serif;
  font-size: 28px;
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -0.01em;
}

.pf-cashflow-amount--pos { color: var(--success, #136639); }
.pf-cashflow-amount--neg { color: var(--danger, #8C2412); }

.pf-cashflow-netflow {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  padding: 16px 0 0;
  border-top: 1px solid var(--line, rgba(13,27,46,0.10));
}

.pf-cashflow-netlabel {
  font-family: 'Quicksand', sans-serif;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted, #526073);
}

.pf-cashflow-netamount {
  font-family: 'Marcellus', Georgia, serif;
  font-size: 30px;
  line-height: 1;
  color: var(--ink, #0D1B2E);
}

@media (max-width: 560px) {
  .pf-cashflow-tile-amount { font-size: 24px; }
  .pf-cashflow-netamount { font-size: 26px; }
}

/* ── Consolidated Returns chart ─────────────────────────────── */
.pf-returns-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 28px;
  flex-wrap: wrap;
}

/* The section's own name, in the heading face. Title case rather than the
   all-caps this line used to carry: Marcellus at heading size with 0.16em
   tracking reads as a wordmark stamped on the card, not as a heading. */
.pf-returns-title {
  font-family: 'Marcellus', serif;
  font-size: 22px;
  font-weight: 400;
  color: var(--ink, #0D1B2E);
  letter-spacing: -0.01em;
  line-height: 1.1;
  margin: 0 0 4px;
}

/* What this particular card shows, under the heading and quieter than it. */
.pf-returns-sub {
  font-family: 'Quicksand', sans-serif;
  font-size: 13px;
  font-weight: 600;
  color: var(--muted, #526073);
  line-height: 1.3;
  margin: 0;
}

/* Why a bar is missing. Quiet, under the chart, and never coloured like a
   warning — a period we cannot measure is a fact about the records, not an
   alarm about the money. */
.pf-returns-note {
  margin: 14px 0 0;
  font-family: 'Quicksand', sans-serif;
  font-size: 11px;
  line-height: 1.6;
  color: var(--muted, #526073);
  max-width: 62ch;
}

/* This card sits beside Contributions & Withdrawals and is stretched to its
   height. With a chart in it that is right; with one sentence in it the
   sentence hung off the heading above a pool of empty card. The card becomes
   a column and the explanation takes the space and centres in it — the same
   treatment the Asset Allocation bars got on 2026-09-07. */
.pf-returns-card {
  display: flex;
  flex-direction: column;
}

.pf-returns-review {
  margin: 0;
  padding: 8px 0;
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  font-family: 'Quicksand', sans-serif;
  font-size: 13px;
  font-weight: 500;
  line-height: 1.6;
  color: var(--pf-muted, #526073);
  max-width: 54ch;
}
.pf-returns-meta {
  font-family: 'Quicksand', sans-serif;
  font-size: 12px;
  color: var(--muted, #526073);
  white-space: nowrap;
  margin: 4px 0 0;
}

.pf-returns-chart-wrap {
  width: 100%;
  overflow-x: auto;
  margin-top: 8px;
}

.pf-returns-grid {
  position: relative;
  display: grid;
  gap: 16px;
  min-width: 420px;
}

.pf-returns-baseline {
  position: absolute;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--line, rgba(13,27,46,0.14));
  pointer-events: none;
}

.pf-returns-col {
  display: flex;
  flex-direction: column;
  align-items: center;
  opacity: 0.6;
  transition: opacity 200ms ease;
}

.pf-returns-col--active {
  opacity: 1;
}

.pf-returns-pos-area {
  height: 140px;
  width: 100%;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: center;
}

.pf-returns-neg-area {
  height: 72px;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
}

.pf-returns-value {
  font-family: 'Quicksand', sans-serif;
  font-size: 13px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Value colours live in CSS, not in a render-time inline style, so a theme
   toggle after render re-themes them. (Previously baked in as inline colour:
   positives stayed dark navy on the dark surface and went invisible.) */
.pf-returns-value--pos { margin-bottom: 8px; color: #101830; }
.pf-returns-value--neg { margin-top: 8px;    color: #8C2412; }

[data-theme="dark"] .pf-returns-value--pos { color: #F3EEE4; }
[data-theme="dark"] .pf-returns-value--neg { color: #F0A090; }

.pf-returns-bar {
  width: 38px;
  max-width: 68%;
  box-sizing: border-box;
  border: 1px solid transparent;
  transition: height 700ms cubic-bezier(0.22,0.61,0.36,1), filter 200ms cubic-bezier(0.22,0.61,0.36,1);
}

.pf-returns-bar:hover { filter: brightness(0.95); }

/* 4px rounded data-end, square at the baseline (mark spec + radius canon;
   6px was off-canon and the baseline end should not be rounded at all). */
.pf-returns-bar--pos { border-radius: 4px 4px 0 0; }
.pf-returns-bar--neg { border-radius: 0 0 4px 4px; }

.pf-returns-label {
  margin-top: 12px;
  font-family: 'Quicksand', sans-serif;
  font-size: 12px;
  font-weight: 700;
  color: var(--muted, #526073);
  text-align: center;
  line-height: 1.35;
  letter-spacing: 0.01em;
}

.pf-returns-col--active .pf-returns-label { color: var(--ink, #0D1B2E); }

@media (max-width: 680px) {
  .pf-returns-head { flex-direction: column; }
}

/* ── Debit Orders & Income ───────────────────────────────────── */
/* One column of sections rather than two side-by-side columns: the two sides
   are read as one list of what leaves and enters each month, and the split
   forced both into half the width for no gain. Per-side subtotals are gone —
   the net monthly flow is the figure people act on. */
.pf-debit-header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  margin-bottom: 22px;
}

.pf-debit-meta {
  font-family: 'Quicksand', sans-serif;
  font-size: 14px;
  color: var(--muted, #526073);
  flex-shrink: 0;
}

.pf-debit-section + .pf-debit-section {
  margin-top: 26px;
}

.pf-debit-section-title {
  margin: 0 0 4px;
  font-family: 'Quicksand', sans-serif;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted, #526073);
}

.pf-debit-list {
  display: flex;
  flex-direction: column;
}

.pf-debit-item {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  padding: 13px 0;
  border-top: 1px solid var(--line, rgba(13,27,46,0.09));
}

.pf-debit-item-copy {
  min-width: 0;
  font-family: 'Quicksand', sans-serif;
  line-height: 1.35;
}

/* What it is, on its own line and in the ink colour — it is the thing being
   read. The account and the day sit beneath as supporting detail, because
   they qualify the item rather than compete with it. */
.pf-debit-item-name {
  margin: 0;
  font-size: 15px;
  font-weight: 600;
  color: var(--ink, #0D1B2E);
}

.pf-debit-item-meta {
  margin: 2px 0 0;
  font-size: 12px;
  color: var(--muted, #526073);
}

/* Account numbers get read digit by digit, so tabular figures and a little
   tracking. */
.pf-debit-item-account {
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
}

.pf-debit-item-sep { color: var(--muted, #526073); }

.pf-debit-item-amount {
  flex-shrink: 0;
  font-family: 'Quicksand', sans-serif;
  font-size: 15px;
  font-weight: 600;
  color: var(--ink, #0D1B2E);
  font-variant-numeric: tabular-nums;
}

.pf-debit-netflow {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  margin-top: 26px;
  padding-top: 18px;
  border-top: 1px solid var(--line, rgba(13,27,46,0.10));
}

/* Sits under the Net Monthly Flow row and says what that figure leaves out.
   A caption jammed against the number it qualifies reads as broken, so it
   takes real room above it — the net row already opens with a rule and 18px,
   and this clears the amount by 10 and the card's bottom edge by its own
   line-height. 12px because it qualifies the total rather than competing
   with it, and the muted ink for the same reason. */
.pf-debit-note {
  margin: 10px 0 0;
  font-size: 12px;
  line-height: 1.5;
  color: var(--muted, #526073);
}

.pf-debit-netlabel {
  font-family: 'Quicksand', sans-serif;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted, #526073);
}

.pf-debit-netamount {
  font-family: 'Marcellus', Georgia, serif;
  font-size: 30px;
  line-height: 1;
}

.pf-debit-netamount--pos { color: var(--success, #136639); }
.pf-debit-netamount--neg { color: var(--danger, #8C2412); }

@media (max-width: 560px) {
  .pf-debit-netamount { font-size: 26px; }
  .pf-debit-item { gap: 10px; }
}

/* ── Asset Allocation ────────────────────────────────────────── */
.pf-card-title {
  font-family: 'Marcellus', serif;
  font-size: 18px;
  font-weight: 400;
  color: var(--ink, #0D1B2E);
  margin: 0 0 18px;
}

.pf-alloc-bar-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

/* This card sits in a row that stretches all three to the tallest, and the
   bars are the shortest content of the three — so they hung off the title
   with a pool of empty card underneath. Let the bar list take the leftover
   height and sit in the middle of it. */
.pf-alloc-card {
  display: flex;
  flex-direction: column;
}

.pf-alloc-card .pf-alloc-bar-list {
  flex: 1 1 auto;
  justify-content: center;
}

.pf-alloc-row {
  display: grid;
  grid-template-columns: 140px 1fr 64px;
  align-items: center;
  gap: 12px;
}

.pf-alloc-label {
  font-family: 'Quicksand', sans-serif;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink, #0D1B2E);
  white-space: nowrap;
}

.pf-alloc-track {
  height: 10px;
  background: rgba(13,27,46,0.06);
  border-radius: 999px;
  overflow: hidden;
}

.pf-alloc-fill {
  height: 100%;
  border-radius: 999px;
  transition: width 0.6s ease;
}

.pf-alloc-pct {
  font-family: 'Quicksand', sans-serif;
  font-size: 13px;
  font-weight: 600;
  color: var(--muted, #526073);
  text-align: right;
}

/* Asset class colour palette — SA = blue-navy family, Non-SA = teal-green family */
/* SA (local) is the GREEN ramp and non-SA (offshore) the NAVY ramp, anchored
   on the same #195C45/#1F395F the Local vs Offshore donut uses — the two cards
   describe the same split and must not colour it opposite ways. */
.pf-alloc-fill--sa-equity    { background: #195C45; }
.pf-alloc-fill--sa-bond      { background: #2E7A60; }
.pf-alloc-fill--sa-property  { background: #4A9A7E; }
.pf-alloc-fill--sa-cash      { background: #6AB898; }
.pf-alloc-fill--sa-other     { background: #9ACFBB; }
.pf-alloc-fill--nonsa-equity { background: #1F395F; }
.pf-alloc-fill--nonsa-bond   { background: #2E5885; }
.pf-alloc-fill--nonsa-prop   { background: #4E7A97; }
.pf-alloc-fill--nonsa-cash   { background: #698DAA; }
.pf-alloc-fill--nonsa-other  { background: #9BB3C5; }
/* Money we hold but cannot see inside — deliberately a neutral grey so it
   reads as "unknown" rather than as another asset class. */
.pf-alloc-fill--unclassified { background: #AEB4BC; }

/* ── Holdings ────────────────────────────────────────────────── */
.pf-hold-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}
.pf-hold-head .pf-card-title { margin-bottom: 18px; }

.pf-hold-count {
  font-family: 'Quicksand', sans-serif;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted, #526073);
}

/* A long security name plus five columns will not fit a phone. The table
   scrolls inside its own box rather than pushing the page sideways. */
.pf-hold-scroll { overflow-x: auto; }

.pf-hold-table {
  width: 100%;
  border-collapse: collapse;
}

/* Sortable headers. The clickable cue is the hover colour change — no
   chevrons. The arrow appears only on the column actually being sorted by,
   where it reports state rather than advertising the control. */
.pf-hold-th {
  cursor: pointer;
  user-select: none;
  transition: color 0.12s ease;
}
.pf-hold-th:hover { color: var(--ink, #0D1B2E); }
.pf-hold-th--active { color: var(--ink, #0D1B2E); }
.pf-hold-sort { margin-left: 4px; font-weight: 700; }
@media (prefers-reduced-motion: reduce) { .pf-hold-th { transition: none; } }

/* The asset class reads as a label, not a value — quieter than the name it
   sits beside, but not as faint as the ISIN below it. */
.pf-hold-class {
  font-size: 12px;
  font-weight: 600;
  color: var(--muted, #526073);
  white-space: nowrap;
}

.pf-hold-table th {
  font-family: 'Quicksand', sans-serif;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.01em;
  text-transform: capitalize;
  color: var(--muted, #526073);
  text-align: left;
  white-space: nowrap;
  padding: 0 0 10px 16px;
  border-bottom: 1px solid var(--line, rgba(13,27,46,0.10));
}
.pf-hold-table th:first-child, .pf-hold-table td:first-child { padding-left: 0; }
.pf-hold-table th.pf-hold-num, .pf-hold-table td.pf-hold-num { text-align: right; }

.pf-hold-table td {
  font-family: 'Quicksand', sans-serif;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink, #0D1B2E);
  white-space: nowrap;
  padding: 11px 0 11px 16px;
  border-bottom: 1px solid rgba(13,27,46,0.06);
}

/* Hover is a background change only — no lift, no movement. */
.pf-hold-table tbody tr { transition: background 0.12s ease; }
.pf-hold-table tbody tr:hover { background: rgba(13,27,46,0.03); }
@media (prefers-reduced-motion: reduce) {
  .pf-hold-table tbody tr { transition: none; }
}

/* inline, not block: the (i) that follows must sit at the top right of the
   name's last letter, not drop onto its own line. The subtitle below is the
   block that starts the second line. */
/* Company mark. The initials sit underneath and the logo covers them, so a
   security without a logo still looks intentional and nothing reflows when an
   image loads late. No shadow — the ring is a hairline border. */
.pf-hold-idcell {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}
.pf-hold-idtext { min-width: 0; }

.pf-hold-mark {
  position: relative;
  flex: 0 0 auto;
  width: 28px;
  height: 28px;
  border-radius: 8px;
  overflow: hidden;
  background: rgba(13,27,46,0.05);
  border: 1px solid var(--line, rgba(13,27,46,0.10));
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.pf-hold-initials {
  font-family: 'Quicksand', sans-serif;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--muted, #526073);
}

.pf-hold-logo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  /* Most marks are square on white; a touch of padding stops them touching
     the border, and the white keeps a transparent PNG legible in dark mode. */
  padding: 2px;
  background: #fff;
}

.pf-hold-name { display: inline; }

/* The name is the control that opens the holding. It must look like the
   text it replaced — a button element otherwise arrives with the global
   button padding, border and background — and signal itself on hover the
   way everything else does: colour only, no caret, nothing that moves. */
.pf-hold-name-btn {
  display: inline;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}
.pf-hold-name-btn:hover { color: var(--brand, #4E7A97); }
.pf-hold-name-btn:focus-visible {
  outline: 2px solid var(--brand, #4E7A97);
  outline-offset: 2px;
  border-radius: 2px;
}

/* ── The accounts behind a holding ───────────────────────────────
   Opened from the name. Everything here had to fit on one cramped line
   before; with room, each account can carry its value too. */
.pf-hold-detail > td {
  padding: 4px 0 16px 44px;
  background: var(--pf-surface-inset, rgba(82, 96, 115, 0.05));
}

.pf-hold-detail-title {
  margin: 0 0 8px;
  font-family: 'Quicksand', sans-serif;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted, #526073);
}

.pf-hold-detail-list {
  /* Held to a readable measure. Left to fill the table's full width the
     product ended up at the far left and its account number and value at
     the far right, with a hand's width of nothing between them — three
     facts about one account, reading as three unrelated columns. */
  max-width: 560px;
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.pf-hold-detail-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: baseline;
  gap: 14px;
  font-family: 'Quicksand', sans-serif;
  font-size: 13px;
}

.pf-hold-detail-prod { overflow-wrap: anywhere; }

.pf-hold-detail-acct {
  font-size: 12px;
  color: var(--muted, #526073);
  white-space: nowrap;
}

.pf-hold-detail-val {
  min-width: 96px;
  text-align: right;
  font-weight: 600;
  white-space: nowrap;
}

/* No narrow-screen variant on purpose. This row lives inside
   .pf-hold-scroll, which scrolls the whole table sideways rather than
   letting it narrow, so the detail always has the table's full width to
   work with however small the phone is. A viewport media query here
   looked sensible and did nothing at all — it is the container that never
   narrows, not the screen. */

/* ── Holding identifiers popover ─────────────────────────────── */
.pf-hold-info {
  position: relative;
  display: inline-block;
  margin-left: 5px;
  vertical-align: super;
  line-height: 0;
}

.pf-hold-info-btn {
  width: 14px;
  height: 14px;
  padding: 0;
  border-radius: 50%;
  border: 1px solid var(--line, rgba(13,27,46,0.28));
  background: transparent;
  color: var(--muted, #526073);
  font-family: 'Quicksand', sans-serif;
  font-size: 9px;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
}

.pf-hold-info-btn:hover,
.pf-hold-info:focus-within .pf-hold-info-btn {
  border-color: var(--brand, #4E7A97);
  color: var(--brand, #4E7A97);
}

/* Shown on hover OR focus-within, so it is reachable by keyboard and not only
   by mouse. Positioned above the row: these sit low in a long table and a
   popover below would fall off the card. */
.pf-hold-pop {
  /* Base position is a fallback; portfolio.js re-places the popover with
     position:fixed on open, because .pf-hold-scroll clips absolute children. */
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%) translateY(4px);
  z-index: 20;
  min-width: 190px;
  padding: 10px 12px;
  border-radius: 10px;
  border: 1px solid var(--line, rgba(13,27,46,0.12));
  background: var(--pf-surface);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.12s ease, transform 0.12s ease, visibility 0.12s;
  line-height: 1.4;
  text-align: left;
}

.pf-hold-info:hover .pf-hold-pop,
.pf-hold-info:focus-within .pf-hold-pop {
  opacity: 1;
  visibility: visible;
  transform: translateX(-50%) translateY(0);
}

.pf-hold-pop-row {
  display: flex;
  justify-content: space-between;
  gap: 14px;
  font-family: 'Quicksand', sans-serif;
  font-size: 12px;
  color: var(--ink, #0D1B2E);
  white-space: nowrap;
}

.pf-hold-pop-key {
  font-weight: 600;
  color: var(--muted, #526073);
}

.pf-hold-pop-more {
  display: block;
  width: 100%;
  margin-top: 9px;
  padding: 6px 10px;
  border-radius: 7px;
  border: 1px solid var(--line, rgba(13,27,46,0.14));
  background: var(--pf-surface-inset);
  color: var(--ink, #0D1B2E);
  font-family: 'Quicksand', sans-serif;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}

.pf-hold-pop-more:hover {
  border-color: var(--brand, #4E7A97);
  color: var(--brand, #4E7A97);
}

/* ── Product breakdown dialog ────────────────────────────────── */
.pf-proddlg-backdrop {
  position: fixed;
  inset: 0;
  z-index: 900;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(13,27,46,0.45);
}

.pf-proddlg {
  /* Wide enough to show a whole product at once. At 560px a portfolio of
     fifteen holdings was a scroll through a letterbox; the lists below run
     in two columns at this width, so most products fit without scrolling
     at all. It still scrolls when it must — that is a fallback, not the
     normal case. */
  width: min(1040px, 94vw);
  max-height: 92vh;
  overflow-y: auto;
  border-radius: 20px;
  padding: 26px 30px 30px;
  background: var(--pf-surface);
  /* No shadow. The backdrop separates the panel from the page. */
  border: 1px solid var(--line, rgba(13,27,46,0.10));
}

/* ── Purchases in the product dialog ─────────────────────────── */
.pf-proddlg-note {
  margin: -4px 0 12px;
  font-family: 'Quicksand', sans-serif;
  font-size: 12px;
  line-height: 1.45;
  color: var(--muted, #526073);
}

.pf-proddlg-count {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  color: var(--muted, #526073);
}

.pf-trade-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 14px;
  padding: 9px 0;
  border-top: 1px solid var(--line, rgba(13,27,46,0.08));
}

.pf-trade-copy { min-width: 0; }

.pf-trade-name {
  margin: 0;
  font-family: 'Quicksand', sans-serif;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink, #0D1B2E);
}

.pf-trade-meta {
  margin: 2px 0 0;
  font-family: 'Quicksand', sans-serif;
  font-size: 11px;
  color: var(--muted, #526073);
}

/* Bought / Sold reads first — it is the one word that changes the meaning
   of every number beside it. */
.pf-trade-side { font-weight: 700; color: var(--ink, #0D1B2E); }

.pf-trade-nums {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 1px;
}

.pf-trade-value {
  font-family: 'Quicksand', sans-serif;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink, #0D1B2E);
  font-variant-numeric: tabular-nums;
}

.pf-trade-gain { font-size: 11px; font-variant-numeric: tabular-nums; }
.pf-proddlg-gain { color: var(--success, #136639); font-weight: 600; }
.pf-proddlg-gain--neg { color: var(--danger, #8C2412); }

/* Two columns once there is room for them. The rows are self-contained, so
   they reflow to one column on a narrow screen without losing anything. */
.pf-proddlg-list {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 32px;
}
@media (max-width: 760px) {
  .pf-proddlg-list { grid-template-columns: 1fr; }
}

/* Debit orders are statements, not comparable bars — two of them side by side
   in the two-column grid read as a comparison that is not being made. */
.pf-proddlg-list--single { grid-template-columns: 1fr; }

.pf-proddlg-head {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  margin-bottom: 18px;
}

.pf-proddlg-eyebrow {
  margin: 0 0 4px;
  font-family: 'Quicksand', sans-serif;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted, #526073);
}

.pf-proddlg-title {
  margin: 0;
  font-family: 'Marcellus', Georgia, serif;
  font-size: 22px;
  font-weight: 400;
  line-height: 1.15;
  color: var(--ink, #0D1B2E);
}

.pf-proddlg-total {
  margin-left: auto;
  font-family: 'Marcellus', Georgia, serif;
  font-size: 20px;
  color: var(--ink, #0D1B2E);
  white-space: nowrap;
}

/* A PERFECT CIRCLE with the X dead centre. Every property here is load
   bearing and none of it is decoration:
     box-sizing + padding:0  — the global `button` padding is horizontal, so
                               without these the box grows wider than tall and
                               you get an oval. This is what went wrong.
     min/max-width           — flex refuses to squeeze it out of round.
     inline-grid + place-items — centres the glyph optically and vertically,
                               which line-height alone does not do.
   Matches .ca-modal-close in admin.css; if that changes, change this. */
.pf-proddlg-x {
  flex: 0 0 32px;
  box-sizing: border-box;
  width: 32px;
  height: 32px;
  min-width: 32px;
  max-width: 32px;
  padding: 0;
  display: inline-grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid var(--line, rgba(13,27,46,0.14));
  background: transparent;
  color: var(--muted, #526073);
  font-size: 17px;
  line-height: 1;
  cursor: pointer;
}

.pf-proddlg-x:hover { color: var(--ink, #0D1B2E); border-color: var(--ink, #0D1B2E); }

.pf-proddlg-section {
  margin: 20px 0 8px;
  font-family: 'Quicksand', sans-serif;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted, #526073);
}

.pf-proddlg-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  padding: 9px 0;
  border-top: 1px solid var(--line, rgba(13,27,46,0.08));
}

.pf-proddlg-row-copy { flex: 1; min-width: 0; }

.pf-proddlg-sec {
  margin: 0 0 5px;
  font-family: 'Quicksand', sans-serif;
  font-size: 14px;
  color: var(--ink, #0D1B2E);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.pf-proddlg-track {
  height: 4px;
  border-radius: 2px;
  background: var(--pf-surface-inset);
  overflow: hidden;
}

.pf-proddlg-fill {
  height: 100%;
  border-radius: 2px;
  background: var(--brand, #4E7A97);
}

.pf-proddlg-fill--alloc { background: var(--accent, #7FA3BC); }

.pf-proddlg-row-nums {
  flex-shrink: 0;
  text-align: right;
  font-family: 'Quicksand', sans-serif;
}

.pf-proddlg-val {
  display: block;
  font-size: 14px;
  font-weight: 600;
  color: var(--ink, #0D1B2E);
}

.pf-proddlg-pct {
  display: block;
  font-size: 12px;
  color: var(--muted, #526073);
}

.pf-proddlg-empty {
  margin: 8px 0 0;
  font-family: 'Quicksand', sans-serif;
  font-size: 14px;
  line-height: 1.5;
  color: var(--muted, #526073);
}
.pf-hold-muted { color: var(--muted, #526073); font-weight: 500; }
.pf-hold-gain { color: var(--success, #136639); }
.pf-hold-gain--neg { color: var(--danger, #8C2412); }

.pf-hold-total td {
  border-bottom: none;
  padding-top: 14px;
  font-weight: 700;
}
.pf-hold-total tr:hover { background: none; }

/* ── Donut Charts ────────────────────────────────────────────── */
.pf-row-2col-charts {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}

/* Asset Allocation, Local vs Offshore and Discretionary vs Compulsory read as
   peers, so they sit in one row. The bars need more width than a donut, hence
   the wider first column. Two-up then one-up as the screen narrows — three
   donuts on a phone are three unreadable donuts. */
.pf-row-alloc-donuts {
  display: grid;
  grid-template-columns: 1.3fr 1fr 1fr;
  gap: 16px;
  /* Equal heights: three cards of three different depths read as an accident.
     They were start-aligned when the third sat in a stacked column. */
  align-items: stretch;
}

@media (max-width: 1100px) {
  .pf-row-alloc-donuts { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 680px) {
  .pf-row-alloc-donuts { grid-template-columns: 1fr; }
}

.pf-donut-stack {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

@media (max-width: 680px) {
  .pf-row-2col-charts { grid-template-columns: 1fr; }
  .pf-row-alloc-donuts { grid-template-columns: 1fr; }
}

/* ── Account panel ───────────────────────────────────────────
   The dialog behind one account: what it is, what has gone into it, what is
   inside it and how it has done. */
.pf-proddlg-inst {
  color: var(--muted, #526073);
  font-weight: 400;
}

.pf-proddlg-acct {
  margin: 4px 0 0;
  font-family: 'Quicksand', sans-serif;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--muted, #526073);
}

/* Single figures — when the account started, what has been paid in. Wraps,
   because the honest labels are long ("Contributions since Jun 2021") and a
   truncated label is worse than a second line. */
.pf-proddlg-facts {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 32px;
  margin: 18px 0 4px;
  padding-bottom: 18px;
  border-bottom: 1px solid var(--line, #E8EDF2);
}

.pf-fact {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.pf-fact-label {
  font-family: 'Quicksand', sans-serif;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted, #526073);
}

.pf-fact-value {
  font-family: 'Marcellus', Georgia, serif;
  font-size: 20px;
  line-height: 1;
  color: var(--ink, #0D1B2E);
}

/* Returns, the same periods as the consolidated card. A period we cannot
   compute is absent, never a zero — "0.00%" is a claim that it made nothing. */
.pf-ret-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(104px, 1fr));
  gap: 12px 20px;
  margin-top: 12px;
}

.pf-ret-cell {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.pf-ret-label {
  font-family: 'Quicksand', sans-serif;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted, #526073);
}

.pf-ret-value {
  font-family: 'Marcellus', Georgia, serif;
  font-size: 19px;
  line-height: 1;
  color: var(--success, #136639);
}

.pf-ret-value--neg { color: var(--danger, #8C2412); }

/* ── Loading / empty / error states ──────────────────────────
   The skeleton matches the final layout's shape rather than showing a
   spinner, so nothing reflows when the data lands. */
.pf-sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.pf-skel {
  background: var(--line, #E8EDF2);
  border-radius: 4px;
}
[data-theme="dark"] .pf-skel { background: rgba(255,255,255,0.07); }

.pf-skel--label { width: 34%; height: 12px; margin-bottom: 14px; }
.pf-skel--hero  { width: 52%; height: 32px; }
.pf-skel--bar   { width: 100%; height: 20px; margin-bottom: 16px; }
.pf-skel--row   { width: 100%; height: 12px; margin-top: 10px; }

@media (prefers-reduced-motion: no-preference) {
  .pf-skeleton .pf-skel { animation: pf-skel-pulse 1.4s ease-in-out infinite; }
  @keyframes pf-skel-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.55; } }
}

.pf-empty {
  font-family: 'Quicksand', sans-serif;
  font-size: 13px;
  line-height: 1.6;
  color: var(--muted, #526073);
  margin: 0;
  max-width: 62ch;
}
.pf-empty--detail {
  margin-top: 8px;
  font-size: 11px;
  opacity: 0.75;
}

/* ── Part-to-whole: horizontal stacked bar ───────────────────
   Replaces the donut. A donut is "part-to-whole at a glance only" and is
   the wrong form when a reader compares close values — advisors do exactly
   that across allocation slices, and arc lengths are far harder to compare
   than aligned lengths.

   Mark spec: ≤24px thick, 4px rounded OUTER data-ends (square where
   segments meet), and a 2px gap in the surface colour separating touching
   segments. The gap is what separates marks — never a border, which would
   add ink that isn't data. */
.pf-stack-wrap {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.pf-stack-track {
  display: flex;
  width: 100%;
  height: 20px;
  gap: 2px;                       /* the surface gap — 2px, consistent */
  border-radius: 4px;
  overflow: hidden;
  background: transparent;
}

.pf-stack-seg {
  min-width: 3px;                 /* a sliver stays visible/hoverable */
  transition: filter 140ms ease;
}

/* Square where segments meet; 4px only on the outer data-ends */
.pf-stack-seg:first-child { border-radius: 4px 0 0 4px; }
.pf-stack-seg:last-child  { border-radius: 0 4px 4px 0; }
.pf-stack-seg:only-child  { border-radius: 4px; }

/* Hover = the interactive signal (no chevrons anywhere in this portal) */
.pf-stack-seg:hover { filter: brightness(1.12); }

.pf-donut-wrap {
  display: flex;
  align-items: center;
  gap: 24px;
}

.pf-donut-svg-wrap {
  flex-shrink: 0;
}

.pf-donut-legend {
  display: flex;
  flex-direction: column;
  gap: 10px;
  flex: 1;
}

.pf-donut-legend-item {
  display: flex;
  align-items: center;
  gap: 8px;
}

.pf-donut-legend-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  flex-shrink: 0;
}

.pf-donut-legend-name {
  font-family: 'Quicksand', sans-serif;
  font-size: 13px;
  color: var(--muted, #526073);
  flex: 1;
}

/* tabular-nums ONLY where numbers form a vertical column that must align
   (legend values, table rows, axis ticks). Deliberately NOT on the hero
   AUM figure — tabular gives every digit the width of a '0', which reads
   loose at display sizes. */
.pf-donut-legend-pct {
  font-family: 'Quicksand', sans-serif;
  font-size: 13px;
  font-weight: 700;
  color: var(--ink, #0D1B2E);
  font-variant-numeric: tabular-nums;
  min-width: 48px;
  text-align: right;
}

.pf-donut-legend-val {
  font-family: 'Quicksand', sans-serif;
  font-size: 11px;
  color: var(--muted, #526073);
  min-width: 84px;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* ── Donut tooltip ───────────────────────────────────────────
   ApexCharts ships its tooltip with `box-shadow: 2px 2px 6px -4px #999`,
   which this portal does not allow anywhere. The chip below brings its own
   surface, so the library's shell is stripped back to a bare positioner. */
.apexcharts-tooltip.apexcharts-theme-light,
.apexcharts-tooltip.apexcharts-theme-dark,
.apexcharts-tooltip {
  box-shadow: none;
  border: 0;
  background: transparent;
  border-radius: 8px;
  overflow: visible;
}
.pf-apex-tip {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 7px 11px;
  border-radius: 8px;
  font-family: 'Quicksand', sans-serif;
  font-size: 12px;
  white-space: nowrap;
}
.pf-apex-tip-name { font-weight: 600; }
.pf-apex-tip-val {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* ── Coming Soon overlay ─────────────────────────────────────── */
.pf-coming-soon-wrap {
  position: relative;
  min-height: 480px;
  overflow: hidden;
}

.pf-coming-soon-blur {
  filter: blur(6px);
  pointer-events: none;
  user-select: none;
  opacity: 0.45;
}

.pf-coming-soon-card {
  position: absolute;
  top: 35%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 10;
  background: var(--panel, rgba(13,20,36,0.90));
  border: 1px solid rgba(105, 141, 170, 0.22);
  border-radius: 20px;
  padding: 40px 44px;
  text-align: center;
  width: min(360px, calc(100vw - 48px));
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
}

[data-theme="light"] .pf-coming-soon-card {
  background: rgba(255,255,255,0.95);
}

.pf-coming-soon-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 16px;
  color: var(--muted, #526073);
}

.pf-coming-soon-eyebrow {
  font-family: 'Quicksand', sans-serif;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted, #526073);
  margin: 0 0 10px;
}

.pf-coming-soon-title {
  font-family: 'Marcellus', serif;
  font-size: 29px;
  font-weight: 400;
  color: var(--ink, #EEE8DF);
  margin: 0 0 14px;
  line-height: 1.15;
}

[data-theme="light"] .pf-coming-soon-title {
  color: var(--ink, #0D1B2E);
}

.pf-coming-soon-body {
  font-family: 'Quicksand', sans-serif;
  font-size: 13px;
  color: var(--muted, #8A9DAF);
  margin: 0;
  line-height: 1.6;
}

[data-theme="light"] .pf-coming-soon-body {
  color: var(--muted, #526073);
}

/* ── Empty / Loading state ──────────────────────────────────── */
.pf-empty {
  text-align: center;
  padding: 48px 24px;
  color: var(--muted, #526073);
  font-family: 'Quicksand', sans-serif;
  font-size: 14px;
}

.pf-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 200px;
  color: var(--muted, #526073);
  font-family: 'Quicksand', sans-serif;
  font-size: 13px;
  gap: 10px;
}

/* ── Admin portal context — tighter padding inside panel-body ── */
.panel-body .pf-overview {
  padding: 0;
}

/* ── Allowances collapsible ─────────────────────────────────── */
.pf-allowances-details {
  margin-top: 8px;
}

.pf-allowances-summary {
  list-style: none;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 20px;
  background: var(--panel, rgba(255,255,255,0.98));
  border: 1px solid var(--line, rgba(13,27,46,0.10));
  border-radius: 16px;
  cursor: pointer;
  user-select: none;
  transition: background 0.15s ease;
}

.pf-allowances-details[open] .pf-allowances-summary {
  border-radius: 16px 16px 0 0;
  border-bottom-color: transparent;
}

.pf-allowances-summary::-webkit-details-marker { display: none; }
.pf-allowances-summary:hover { background: rgba(78,122,151,0.04); }

.pf-allowances-summary-label {
  font-family: 'Marcellus', serif;
  font-size: 17px;
  font-weight: 400;
  color: var(--ink, #0D1B2E);
  flex-shrink: 0;
}

.pf-allowances-summary-sub {
  font-family: 'Quicksand', sans-serif;
  font-size: 11px;
  color: var(--muted, #526073);
  flex: 1;
}

.pf-allowances-chev {
  color: var(--muted, #526073);
  flex-shrink: 0;
  transition: transform 200ms ease;
  display: flex;
}

.pf-allowances-details[open] .pf-allowances-chev {
  transform: rotate(180deg);
}

.pf-allowances-details .al-grid {
  background: var(--panel, rgba(255,255,255,0.98));
  border: 1px solid var(--line, rgba(13,27,46,0.10));
  border-top: none;
  border-radius: 0 0 16px 16px;
  padding: 16px;
}

/* ── Allowance card ──────────────────────────────────────────── */
.al-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 10px;
}

.al-card {
  background: var(--panel-inset, rgba(13,27,46,0.03));
  border: 1px solid var(--line, rgba(13,27,46,0.08));
  border-radius: 12px;
  padding: 16px 18px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

[data-theme="dark"] .al-card {
  background: rgba(255,255,255,0.03);
  border-color: rgba(197,209,220,0.10);
}

.al-card-head {
  display: flex;
  align-items: flex-start;
  gap: 8px;
}

.al-card-title-group {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.al-card-title {
  font-family: 'Marcellus', serif;
  font-size: 16px;
  color: var(--ink, #0D1B2E);
  font-weight: 400;
  line-height: 1.2;
}

.al-card-subtitle {
  font-family: 'Quicksand', sans-serif;
  font-size: 10px;
  font-weight: 600;
  color: var(--muted, #526073);
  text-transform: uppercase;
  letter-spacing: 0.07em;
}

.al-card-head-right {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
  padding-top: 2px;
}

.al-tone-pill {
  font-family: 'Quicksand', sans-serif;
  font-size: 10px;
  font-weight: 700;
  padding: 3px 9px;
  border-radius: 999px;
  white-space: nowrap;
}

.al-tone--ok     { background: rgba(46,125,82,0.15); color: #2e7d52; }
.al-tone--warn   { background: rgba(217,119,6,0.12);  color: #b45309; }
.al-tone--danger { background: rgba(185,28,28,0.12);  color: #b91c1c; }

[data-theme="dark"] .al-tone--ok     { background: rgba(56,142,96,0.20); color: #5dba82; }
[data-theme="dark"] .al-tone--warn   { background: rgba(217,119,6,0.20);  color: #f59e0b; }
[data-theme="dark"] .al-tone--danger { background: rgba(185,28,28,0.20);  color: #f87171; }

.al-info-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  border: 1px solid var(--line, rgba(13,27,46,0.12));
  background: transparent;
  color: var(--muted, #526073);
  cursor: pointer;
  padding: 0;
  transition: background 0.15s, color 0.15s;
}

.al-info-btn:hover,
.al-info-btn.is-active {
  background: rgba(78,122,151,0.12);
  color: var(--ink, #0D1B2E);
}

/* ── Progress bar ────────────────────────────────────────────── */
.al-bar-track {
  height: 5px;
  background: rgba(13,27,46,0.08);
  border-radius: 999px;
  overflow: hidden;
  display: flex;
}

[data-theme="dark"] .al-bar-track { background: rgba(255,255,255,0.08); }

.al-bar-used {
  height: 100%;
  border-radius: 999px 0 0 999px;
  transition: width 0.4s ease;
}

.al-bar-proj {
  height: 100%;
  opacity: 0.35;
}

.al-bar--ok          { background: #2e7d52; }
.al-bar--ok-proj     { background: #2e7d52; }
.al-bar--warn        { background: #d97706; }
.al-bar--warn-proj   { background: #d97706; }
.al-bar--danger      { background: #b91c1c; }
.al-bar--danger-proj { background: #b91c1c; }

/* ── Stat rows ───────────────────────────────────────────────── */
.al-stat-row {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 8px;
}

.al-stat-col {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.al-stat-col--r {
  text-align: right;
  align-items: flex-end;
}

.al-stat-lbl {
  font-family: 'Quicksand', sans-serif;
  font-size: 10px;
  font-weight: 600;
  color: var(--muted, #526073);
  text-transform: none;
  letter-spacing: 0;
}

.al-stat-num {
  font-family: 'Quicksand', sans-serif;
  font-size: 15px;
  font-weight: 700;
  color: var(--ink, #0D1B2E);
  line-height: 1.2;
}

.al-stat-num--rem { color: #2e7d52; }
[data-theme="dark"] .al-stat-num--rem { color: #5dba82; }

.al-info-row {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

/* ── Info/detail panel ───────────────────────────────────────── */
.al-detail-panel {
  border-top: 1px solid var(--line, rgba(13,27,46,0.08));
  padding-top: 10px;
}

.al-detail-panel p {
  font-family: 'Quicksand', sans-serif;
  font-size: 11px;
  color: var(--muted, #526073);
  margin: 0;
  line-height: 1.55;
}

@media (max-width: 600px) {
  .al-grid { grid-template-columns: 1fr; }
  .pf-allowances-summary-sub { display: none; }
}

/* ── Mobile: prevent horizontal overflow ─────────────────────── */
@media (max-width: 640px) {
  /* Lock the portfolio section — no sideways scroll */
  [data-section="portfolio"] {
    overflow-x: hidden;
  }

  /* Period buttons WRAP. They were forced onto one line and the section hides
     its overflow, so the last chip — Custom — was cut in half and could not be
     tapped at all. Two lines of reachable buttons beats one line with a
     control amputated off the end. */
  .pf-perf-tabs {
    flex-wrap: wrap;
    gap: 4px;
  }
  .pf-perf-tab {
    font-size: 10px;
    padding: 3px 7px;
  }

  /* ── Consolidated Returns: fit the screen instead of scrolling off it ──────
     The grid carried min-width:420px and the wrapper scrolls, so on a 375px
     phone a third of the chart sat off-screen to the right — including the
     tallest bar and the Since Inception figure. Worse, it read as empty space:
     the only bar you could see was the small negative one, so the chart looked
     like it had nothing in it. It fits now, and the space fills itself. */
  .pf-returns-grid {
    min-width: 0;
    gap: 6px;
  }
  .pf-returns-value {
    font-size: 10px;
  }
  .pf-returns-label {
    margin-top: 8px;
    font-size: 9.5px;
    line-height: 1.25;
    letter-spacing: 0;
    overflow-wrap: break-word;
  }

  /* ── Holdings on a phone: name on top, figures beneath ───────────────────
     Seven columns cannot sit in 375px, so the table scrolled sideways inside
     its own wrapper and the phone showed the security name and nothing else —
     no value, no gain, no weight, which is most of the reason to open it.
     Hiding three columns was not enough: a company name and three figures
     still cannot share 297px without the name being squeezed to a couple of
     characters per line. So the row stacks — name and accounts across the top,
     the three figures as a strip underneath, each labelled because once the
     header row is gone nothing else says which is which.

     Asset class, Units and the rand P/L are the ones dropped: the first two
     are context rather than answers, and the rand gain is the percentage in
     another form — the percentage is the one people read.

     No orientation query is needed. Turning the phone sideways takes the
     viewport past 640px — the narrowest modern phone is 667px in landscape —
     so rotating restores the full seven-column table on its own. */
  /* No sideways scrolling on a phone. .pf-hold-scroll sets overflow-x:auto for
     the desktop table, and per spec a non-visible value on one axis promotes
     the OTHER axis to auto too — so the card became a nested scroll container
     in both directions. Once the row stacks there is nothing to scroll
     horizontally, and a nested scroller only competes with the page for
     vertical drags. The page scrolls up and down; the card scrolls neither way. */
  .pf-hold-scroll { overflow: visible; }

  .pf-hold-table, .pf-hold-table tbody { display: block; width: 100%; }
  .pf-hold-table thead { display: none; }

  .pf-hold-table tbody tr {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    column-gap: 8px;
    row-gap: 10px;
    padding: 13px 0;
    border-bottom: 1px solid rgba(13,27,46,0.06);
  }
  [data-theme="dark"] .pf-hold-table tbody tr {
    border-bottom-color: rgba(139,175,200,0.10);
  }
  .pf-hold-table td { border: none; padding: 0; }

  /* Name, logo and accounts take the full width above the figures. */
  .pf-hold-table td:first-child {
    grid-column: 1 / -1;
    white-space: normal;
  }
  .pf-hold-mark { width: 26px; height: 26px; }
  .pf-hold-idcell { gap: 9px; }
  .pf-hold-name { font-size: 13px; overflow-wrap: anywhere; }

  /* Columns that do not earn their place on a phone. */
  .pf-hold-table td:nth-child(2),   /* Asset class */
  .pf-hold-table td:nth-child(3),   /* Units */
  .pf-hold-table td:nth-child(5) {  /* P/L in rand */
    display: none;
  }

  /* Value, gain and weight as three labelled figures. Left-aligned, not right:
     right-aligning three columns of different widths leaves them drifting
     apart with nothing to line up against once the table grid is gone. */
  .pf-hold-table td:nth-child(4),
  .pf-hold-table td:nth-child(6),
  .pf-hold-table td:nth-child(7) {
    text-align: left;
    font-size: 12.5px;
    line-height: 1.25;
    min-width: 0;
    overflow-wrap: anywhere;
  }
  .pf-hold-table tbody tr:not(.pf-hold-total) td:nth-child(4)::after,
  .pf-hold-table tbody tr:not(.pf-hold-total) td:nth-child(6)::after,
  .pf-hold-table tbody tr:not(.pf-hold-total) td:nth-child(7)::after {
    display: block;
    margin-top: 2px;
    font-size: 8.5px;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--muted, #526073);
  }
  .pf-hold-table tbody tr:not(.pf-hold-total) td:nth-child(4)::after { content: 'Value'; }
  .pf-hold-table tbody tr:not(.pf-hold-total) td:nth-child(6)::after { content: 'Gain'; }
  .pf-hold-table tbody tr:not(.pf-hold-total) td:nth-child(7)::after { content: 'Weight'; }

  /* The total row has only two figures and needs no labels — "Total" already
     says what it is. */
  .pf-hold-table tbody tr.pf-hold-total td:first-child { margin-bottom: 0; }

  /* Asset allocation rows: the fixed columns tighten, the TEXT does not.

     Both of these used to drop to 11px here and Marz asked for them bigger.
     11 is the ladder's `small` step — captions, hints, chart labels — and an
     allocation row is none of those: it is a list row, so it reads at body
     size like every other list row in the app. Shrinking it was the exact
     move the type ladder exists to stop, making something quieter by making
     it smaller instead of by making it lighter.

     The columns grow with the text rather than clipping it: 118px holds
     "Non-SA Property" (the longest class name) at 13px with room, and 50px
     holds "100.0%". The bar gives up the difference and still has ~180px,
     which is far more than a bar needs to be read. */
  .pf-alloc-row {
    grid-template-columns: 118px 1fr 50px;
    gap: 8px;
  }

  /* Donut charts: shrink SVG, drop the R-value column */
  .pf-donut-wrap {
    gap: 16px;
  }

  .pf-donut-svg-wrap svg {
    width: 90px !important;
    height: 90px !important;
  }

  .pf-donut-legend-val {
    display: none;
  }

  /* Same reasoning for the donut legend beside it — it is a list of holdings
     with their shares, not a chart label. 12px was not on the ladder at all;
     it was a size someone reached for to sit between two others. */
  .pf-donut-legend-name {
    font-size: 13px;
  }

  .pf-donut-legend-pct {
    font-size: 13px;
  }

  /* "Coming Soon" overlay: the blurred mock content behind it stacks into
     one tall column on mobile (vs. desktop's side-by-side grid), so the
     card's top:35% was resolving against a much taller box and landing far
     below the fold. Cap the wrap to a fixed height so the card sits near
     the top regardless of how tall the blurred content grows. */
  .pf-coming-soon-wrap {
    height: 440px;
    min-height: 0;
  }

  .pf-coming-soon-card {
    padding: 32px 28px;
  }
}

/* "Sample data" marker on the Allowances section while the cards are demo-only
   (real allowances not yet computed by the portfolio API). */
.pf-allowances-sample {
  font-family: 'Quicksand', sans-serif;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #8A5C0A;
  background: rgba(217,148,6,0.14);
  border-radius: 999px;
  padding: 3px 9px;
  margin-left: 8px;
  vertical-align: middle;
  white-space: nowrap;
}
[data-theme="dark"] .pf-allowances-sample { color: #F0B24E; background: rgba(240,178,78,0.16); }


/* ═══════════════════════════════════════════════════════════════════════════
   SCREEN REAL ESTATE — staff portfolio section
   ───────────────────────────────────────────────────────────────────────────
   The portfolio page sat inside three nested paddings: the portal's right
   column, the section panel, and then each .pf-card. On a 375px phone that
   added up to 104px — 27.7% of the screen given over to margin, which is why
   holdings sub-lines truncated and the returns labels collided.

   The middle layer is the redundant one: every .pf-card already carries its
   own inset, so the panel was insetting an inset. And .pf-card's 28px sides
   were a desktop measure that never got a mobile value.

   BOTH portals get this treatment. portfolio.css is shared, and the two used
   to differ because only the staff panel was named: the client portal kept the
   base .pf-card (24px 28px, radius 16px) while staff had 14px and radius 20px.
   On a 375px screen that left the client's cards with 28px of inner padding a
   side, which is what pushed the range pills onto a second row. The two hosts
   are therefore listed together on every rule below — add a third portal and it
   joins the list rather than inheriting the untouched base.
   ═══════════════════════════════════════════════════════════════════════════ */

/* The wrapping panel stops double-insetting the cards it contains. (Only the
   staff panel needs this: the client's .content-panel is already stripped to
   padding 0 in portal.css.) */
#portfolioPanel {
  padding-left: 8px;
  padding-right: 8px;
}

#portfolioPanel .pf-card,
#portalApp .content-panel[data-section="portfolio"] .pf-card {
  padding: 20px 22px;
  /* Softer than the 16px house default. These cards now sit directly on the
     page ground rather than inside a panel, and a card on a ground carries a
     rounder corner than one nested in a box. Still on the radius canon. */
  border-radius: 20px;
}

@media (max-width: 640px) {
  /* The panel keeps a little side padding on a phone. With the outline gone
     the cards are the only edge left, and they need air between themselves and
     the screen.

     10px here plus the portal column's 6px puts the cards 16px off each edge —
     the same figure the client portal reaches through `.content`'s own padding,
     so the two portals match.

     DO NOT "correct" this to account for `.shell`'s `calc(100vw - 32px)`. I did
     exactly that on 2026-09-09 and shipped a panel that hung 6px off the left of
     the screen with its heading sliced in half. The signed-in staff portal is
     FULL BLEED: `body:has(#adminPortalLayout:not(.hidden)) .admin-auth-shell`
     sets `width: 100%; margin: 0`, so the shell contributes nothing and 10 + 6
     is the whole gutter.

     The measurement that misled me was taken after forcing the app visible with
     `classList.remove("admin-auth-shell")`, which drops that very rule and hands
     back a 16px shell margin that no real session has. To measure this panel,
     leave the class alone and only unhide #adminPortalLayout / #adminWorkspace. */
  #portfolioPanel {
    padding-left: 10px;
    padding-right: 10px;
  }

  /* 16, and the house card surface with it. 14 was this card's own answer to
     an inset every other card on the phone gives as 16, and --pf-surface was
     its own answer to a fill --ac-card now gives once for both portals. */
  #portfolioPanel .pf-card,
  #portalApp .content-panel[data-section="portfolio"] .pf-card {
    padding: 16px;
    background: var(--ac-card);
    border-color: var(--ac-card-line);
  }

  /* Same reasoning inside the cards: the hero and the holdings rows were
     carrying desktop insets on a 375px screen. */
  #portfolioPanel .pf-hero,
  #portalApp .content-panel[data-section="portfolio"] .pf-hero { padding: 16px; }
  #portfolioPanel .pf-hold-table td,
  #portfolioPanel .pf-hold-table th,
  #portalApp .content-panel[data-section="portfolio"] .pf-hold-table td,
  #portalApp .content-panel[data-section="portfolio"] .pf-hold-table th { padding-left: 0; }
}

/* The section panel was a white, bordered, rounded box holding white, bordered,
   rounded cards — the same surface drawn twice, so the page read as a box
   inside a box. The panel has no content of its own, so it gives up its
   surface entirely and becomes pure structure: the cards now sit on the page
   ground, which is what makes them read as cards. */
#portfolioPanel {
  background: transparent;
  border: 0;
  border-radius: 0;
}

/* ── The product dialog on a phone ──────────────────────────────────────────
   At 375px the desktop geometry left 267px of usable content: 24px of backdrop
   padding each side, then 30px of dialog padding each side. The value column
   ("R 1 234 567", nowrap) was the first thing squeezed out, and the 22px
   Marcellus title broke across three lines.

   It becomes a sheet against the bottom edge — full width, so the numbers fit,
   and anchored where the thumb already is. Deliberately NOT the full-screen
   treatment .ca-modal takes on mobile: that one is a multi-step form and owns
   the screen, whereas this is a read-only drill-down that is often four rows
   long, and a whole empty screen for four rows reads as heavier than it is. */
@media (max-width: 640px) {
  .pf-proddlg-backdrop {
    padding: 0;
    align-items: flex-end;
  }

  .pf-proddlg {
    width: 100%;
    max-width: none;
    max-height: 92vh;
    padding: 18px 16px calc(20px + env(safe-area-inset-bottom, 0px));
    border-radius: 20px 20px 0 0;
    border-bottom: 0;
  }

  /* The head wraps into two lines: name and close button, then the total
     beneath on its own. The total keeps its weight — it is the number the
     client opened the dialog to see — so it grows rather than shrinks. */
  .pf-proddlg-head {
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 10px 12px;
    margin-bottom: 14px;
  }
  /* basis 0, not auto: on `auto` the wrapped title's content width is taken
     as the basis, the 32px close button no longer fits beside it, and the X
     drops onto a line of its own. */
  .pf-proddlg-head > div { order: 1; flex: 1 1 0; min-width: 0; }
  .pf-proddlg-x { order: 2; }
  .pf-proddlg-total {
    order: 3;
    flex: 1 0 100%;
    margin-left: 0;
    font-size: 22px;
  }
  .pf-proddlg-title { font-size: 19px; }

  /* Two lines of a fund's real name beat one line of "Coronation Global Op…".
     The row is a flex pair, so the label wrapping just makes the row taller —
     it does not push the value column anywhere. */
  .pf-proddlg-row { gap: 12px; }
  .pf-proddlg-sec { white-space: normal; overflow: visible; }
}
