/*
 * portfolios.css - the Portfolios surface only.
 *
 * Every selector here is prefixed .pf- so this file can never reach into the
 * $PONBOND or Indexes surfaces, which are being written alongside it. The
 * shared components (.card, .segmented, .tag, .stat-grid, .detail-row,
 * details.disclosure, .scroll-x, .sr-only) come from base.css and are reused
 * untouched; the handful of overrides below are deliberate and each says why.
 *
 * Colour comes from tokens.css. The one exception is the allocation slices and
 * legend dots, whose colours arrive from config.js as data and are set inline
 * in JS, because the chart's palette is a fact about the portfolio rather than
 * a fact about the theme.
 *
 * Both themes have to survive: no colour is defined only inside a media query,
 * and nothing relies on --warning or --danger to carry text meaning, since
 * those two are tuned for a dark page and go thin against white. Where a state
 * has to be loud, the colour is on a border and the text stays ink.
 */

/* --------------------------------------------------------------- layout -- */

/*
 * At narrow widths everything is one column in source order: pick a mix, see
 * the split, then invest. From 940px the allocation explainer and the swap card
 * sit side by side, which keeps the numbers a visitor is comparing on one
 * screen instead of a scroll apart. Source order does not change either way.
 */
.pf-columns {
  display: grid;
  gap: calc(var(--step) * 6);
  align-items: start;
  min-width: 0;
}

@media (min-width: 940px) {
  .pf-columns { grid-template-columns: minmax(0, 1fr) minmax(0, 430px); }
}

.pf-invest {
  display: flex;
  flex-direction: column;
  gap: calc(var(--step) * 6);
  min-width: 0;
}

/* A card head that carries a heading plus a tag or a control on the same line. */
.pf-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(var(--step) * 3);
  flex-wrap: wrap;
}

.pf-lead {
  color: var(--text-muted);
  font-size: 14px;
  line-height: 1.6;
  text-wrap: pretty;
}

/* Classed icons opt out of base.css's `svg:not([class])` sizing rule, so every
 * icon that takes a class has to state its own box. */
.pf-profile-icon,
.pf-tool-icon { width: 1em; height: 1em; flex: none; }

/* --------------------------------------------------------- profile picker - */

.pf-flag { align-self: center; }

/* base.css gives .tag `display: inline-flex`, which outranks the user agent's
 * [hidden] { display: none } on specificity, so the flag would sit there
 * announcing a custom mix nobody has made. Every element in this file that
 * toggles with .hidden and also carries a display rule needs this pairing. */
.pf-flag[hidden] { display: none; }

.pf-profiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: calc(var(--step) * 2);
}

.pf-profile {
  display: flex;
  flex-direction: column;
  gap: calc(var(--step) * 0.5);
  padding: calc(var(--step) * 3);
  border: 1px solid var(--divider);
  border-radius: var(--radius);
  background: var(--bg-white);
  text-align: left;
  transition: border-color 0.15s var(--ease), background 0.15s var(--ease);
}

.pf-profile:hover { border-color: var(--text-subtle); }

/* The selected state is a lime border over a lime tint, never a lime fill:
 * --accent behind body text is 1.1:1 in the light theme. The tint keeps
 * --text-primary as the ink in both themes. */
.pf-profile[aria-pressed="true"] {
  border-color: var(--accent);
  background: var(--accent-soft);
}

.pf-profile-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(var(--step) * 2);
}

.pf-profile-label { font-size: 15px; font-weight: 600; letter-spacing: -0.01em; }
.pf-profile-icon { color: var(--text-subtle); }
.pf-profile[aria-pressed="true"] .pf-profile-icon { color: var(--text-primary); }
.pf-profile-choice { color: var(--text-muted); font-size: 12.5px; line-height: 1.4; }

/* ----------------------------------------------------------------- tools -- */

.pf-tools {
  display: grid;
  grid-template-columns: 1fr;
  gap: calc(var(--step) * 2);
}

@media (min-width: 520px) {
  .pf-tools { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.pf-tool {
  display: flex;
  align-items: center;
  gap: calc(var(--step) * 3);
  padding: calc(var(--step) * 3);
  border: 1px solid var(--divider-strong);
  border-radius: var(--radius);
  background: var(--bg-sunken);
  text-align: left;
  transition: border-color 0.15s var(--ease), background 0.15s var(--ease);
}

.pf-tool:hover { border-color: var(--text-subtle); }
.pf-tool.is-open { border-color: var(--accent); background: var(--accent-soft); }

.pf-tool-icon { font-size: 20px; color: var(--text-muted); }
.pf-tool.is-open .pf-tool-icon { color: var(--text-primary); }

.pf-tool-body { display: flex; flex-direction: column; min-width: 0; }
.pf-tool-title { font-size: 14px; font-weight: 600; }
.pf-tool-note { color: var(--text-muted); font-size: 12px; }

.pf-panel {
  padding: calc(var(--step) * 4);
  border: 1px solid var(--divider);
  border-radius: var(--radius);
  background: var(--bg-sunken);
}

/* [hidden] loses to a display rule, and .pf-panel does not set one, but the
 * panels sit inside a card whose `> * + *` margin would still reserve space.
 * Stating it here keeps a closed panel out of the layout entirely. */
.pf-panel[hidden] { display: none; }

.pf-panel-lead {
  color: var(--text-muted);
  font-size: 12.5px;
  line-height: 1.6;
  margin-bottom: calc(var(--step) * 3);
}

/* -------------------------------------------------------- model chooser --- */

.pf-models { display: grid; gap: calc(var(--step) * 2); }

.pf-model {
  display: grid;
  gap: calc(var(--step) * 2);
  padding: calc(var(--step) * 3);
  border: 1px solid var(--divider);
  border-radius: var(--radius);
  background: var(--bg-white);
  text-align: left;
  transition: border-color 0.15s var(--ease), background 0.15s var(--ease);
}

.pf-model:hover { border-color: var(--text-subtle); }
.pf-model[aria-pressed="true"] { border-color: var(--accent); background: var(--accent-soft); }

.pf-model-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: calc(var(--step) * 2);
  flex-wrap: wrap;
}

.pf-model-name {
  display: inline-flex;
  align-items: center;
  gap: calc(var(--step) * 1.5);
  font-size: 14px;
  font-weight: 600;
}

.pf-model-choice { color: var(--text-muted); font-size: 12px; }

.pf-model-weights {
  display: flex;
  flex-wrap: wrap;
  gap: var(--step) calc(var(--step) * 3);
  font-family: var(--font-mono);
  font-size: 11.5px;
  color: var(--text-muted);
}

.pf-model-weight { display: inline-flex; align-items: center; gap: calc(var(--step) * 1.5); white-space: nowrap; }

/* ------------------------------------------------------- custom split ----- */

.pf-custom-rows { display: grid; gap: calc(var(--step) * 3); }

.pf-custom-row { display: grid; gap: calc(var(--step) * 1.5); min-width: 0; }

@media (min-width: 520px) {
  .pf-custom-row {
    grid-template-columns: minmax(0, 190px) minmax(0, 1fr);
    align-items: center;
    gap: calc(var(--step) * 3);
  }
}

.pf-custom-name { display: flex; align-items: center; gap: calc(var(--step) * 2); min-width: 0; }
.pf-custom-label { font-size: 13.5px; overflow-wrap: anywhere; }

.pf-custom-controls { display: flex; align-items: center; gap: calc(var(--step) * 3); min-width: 0; }

.pf-range {
  flex: 1 1 auto;
  min-width: 0;
  height: 22px;
  /* One property themes the track and the thumb in every engine that matters,
   * and it takes the token, so the slider follows the accent for free. */
  accent-color: var(--accent);
  cursor: pointer;
}

.pf-percent-wrap {
  display: inline-flex;
  align-items: center;
  gap: 1px;
  flex: none;
  padding: calc(var(--step) * 1) calc(var(--step) * 2);
  border: 1px solid var(--divider-strong);
  border-radius: var(--radius-sm);
  background: var(--bg-white);
  transition: border-color 0.15s var(--ease);
}

/* The ring moves to the wrapper so the field reads as one control. The input's
 * own outline is dropped only because this replaces it. */
.pf-percent-wrap:focus-within { border-color: var(--accent); }
.pf-percent:focus-visible { outline: none; }

.pf-percent {
  width: 34px;
  padding: 0;
  border: 0;
  background: none;
  text-align: right;
  font-family: var(--font-mono);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
}

.pf-percent-sign { color: var(--text-subtle); font-size: 12px; }

.pf-custom-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(var(--step) * 3);
  flex-wrap: wrap;
  margin-top: calc(var(--step) * 4);
  padding-top: calc(var(--step) * 3);
  border-top: 1px solid var(--divider);
}

.pf-custom-total { display: flex; align-items: baseline; gap: calc(var(--step) * 2); flex-wrap: wrap; }
.pf-custom-total-label { color: var(--text-muted); font-size: 12.5px; }

.pf-custom-total-value {
  font-size: 16px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  padding: 1px calc(var(--step) * 1.5);
  border-radius: var(--radius-sm);
}

/* An unbalanced total is loud, but the loudness is a ring rather than red type:
 * --danger as text measures about 3.7:1 on the light page, which is under AA
 * for a 16px weight. The ink stays --text-primary. */
.pf-custom-total-value.is-off {
  color: var(--text-primary);
  box-shadow: inset 0 0 0 1px var(--danger);
}

.pf-custom-remainder { color: var(--text-muted); font-size: 12.5px; }
.pf-custom-remainder.is-off { color: var(--text-primary); font-weight: 500; }

.pf-custom-actions { display: flex; gap: calc(var(--step) * 2); flex-wrap: wrap; }

.pf-quiet-button {
  padding: calc(var(--step) * 1.75) calc(var(--step) * 3);
  border: 1px solid var(--divider-strong);
  border-radius: var(--radius-pill);
  color: var(--text-muted);
  font-size: 12.5px;
  font-weight: 600;
  white-space: nowrap;
  transition: color 0.15s var(--ease), border-color 0.15s var(--ease);
}

.pf-quiet-button:hover { color: var(--text-primary); border-color: var(--accent); }

/* ------------------------------------------------------------ allocation -- */

.pf-bar {
  display: flex;
  width: 100%;
  height: 16px;
  border-radius: var(--radius-pill);
  overflow: hidden;
  background: var(--bg-sunken);
  border: 1px solid var(--divider);
}

.pf-slice {
  height: 100%;
  min-width: 0;
  /* A hairline in the card's own colour separates two adjacent steps of the
   * same lime ramp. Drawn as an inset shadow rather than a border so it costs
   * no width and cannot push the last slice out of the bar. */
  box-shadow: inset -1.5px 0 0 var(--bg-white);
  transition: width 0.3s var(--ease);
}

.pf-slice:last-child { box-shadow: none; }

.pf-bar-mini { height: 8px; border-radius: var(--radius-pill); }

.pf-legend { display: grid; gap: calc(var(--step) * 2); min-width: 0; }

@media (min-width: 620px) {
  .pf-legend { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: calc(var(--step) * 2) calc(var(--step) * 5); }
}

.pf-legend-item {
  display: flex;
  align-items: baseline;
  gap: calc(var(--step) * 2);
  font-size: 13.5px;
  min-width: 0;
}

/* A slice at 0% is still listed, because a reader comparing two mixes needs to
 * see that the row exists and holds nothing. */
.pf-legend-item.is-empty { opacity: 0.5; }

.pf-legend-dot {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 3px;
  flex: none;
  align-self: center;
  vertical-align: middle;
}

.pf-legend-amount {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  min-width: 58px;
  flex: none;
}

.pf-legend-name { color: var(--text-muted); flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }

.pf-legend-symbol {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-subtle);
  flex: none;
}

.pf-warning {
  padding: calc(var(--step) * 2.5) calc(var(--step) * 3);
  border-left: 3px solid var(--warning);
  border-radius: var(--radius-sm);
  background: var(--bg-sunken);
  color: var(--text-primary);
  font-size: 13px;
  line-height: 1.55;
  text-wrap: pretty;
}

.pf-warning[hidden] { display: none; }

/* ------------------------------------------------------------------ swap -- */

.pf-sides { width: 100%; }

.pf-field {
  padding: calc(var(--step) * 3) calc(var(--step) * 3.5);
  border: 1px solid var(--divider);
  border-radius: var(--radius);
  background: var(--bg-sunken);
  min-width: 0;
  transition: border-color 0.15s var(--ease);
}

.pf-field:focus-within { border-color: var(--divider-strong); }
.pf-field.is-quiet { background: transparent; }

.pf-field-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: calc(var(--step) * 3);
  font-size: 12.5px;
}

.pf-field-label { color: var(--text-muted); }
.pf-field-side { color: var(--text-subtle); font-size: 11.5px; text-align: right; overflow-wrap: anywhere; }

.pf-field-body {
  display: flex;
  align-items: center;
  gap: calc(var(--step) * 2);
  margin-top: calc(var(--step) * 1.5);
  min-width: 0;
}

.pf-field-right { display: flex; align-items: center; gap: calc(var(--step) * 2); flex: none; }

.pf-amount,
.pf-quote {
  flex: 1 1 auto;
  min-width: 0;
  width: 100%;
  font-size: clamp(20px, 6vw, 26px);
  font-weight: 600;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}

.pf-amount { border: 0; background: none; padding: 0; }
.pf-amount::placeholder { color: var(--text-subtle); }
.pf-quote.is-empty { color: var(--text-subtle); }

.pf-max {
  padding: calc(var(--step) * 1) calc(var(--step) * 2.5);
  border: 1px solid var(--divider-strong);
  border-radius: var(--radius-pill);
  color: var(--text-muted);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  transition: color 0.15s var(--ease), border-color 0.15s var(--ease);
}

.pf-max:hover:not(:disabled) { color: var(--text-primary); border-color: var(--accent); }
.pf-max:disabled { opacity: 0.45; }

.pf-chip {
  display: inline-flex;
  align-items: center;
  gap: calc(var(--step) * 1.5);
  padding: calc(var(--step) * 1.5) calc(var(--step) * 2.5);
  border: 1px solid var(--divider-strong);
  border-radius: var(--radius-pill);
  background: var(--bg-elevated);
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
}

.pf-chip-dot { width: 8px; height: 8px; border-radius: 50%; flex: none; background: var(--text-subtle); }
.pf-chip-dot-share { background: var(--accent); }

/* The rail pulls in against .card's `> * + *` spacing so the arrow reads as
 * sitting between the two boxes rather than as a third row. */
.pf-swap > .pf-flip-rail {
  display: flex;
  justify-content: center;
  margin-top: calc(var(--step) * -1);
  margin-bottom: calc(var(--step) * -1);
}

.pf-flip {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border: 1px solid var(--divider-strong);
  border-radius: 50%;
  background: var(--bg-elevated);
  color: var(--text-muted);
  font-size: 17px;
  transition: color 0.15s var(--ease), border-color 0.15s var(--ease);
}

.pf-flip:hover { color: var(--text-primary); border-color: var(--accent); }
.pf-flip svg { transition: transform 0.25s var(--ease); }
.pf-flip.is-up svg { transform: rotate(180deg); }

.pf-action-icon { display: inline-flex; font-size: 16px; }
.pf-action-icon[hidden] { display: none; }

.pf-status {
  color: var(--text-muted);
  font-size: 12.5px;
  line-height: 1.55;
  /* Reserve a line so the card does not jump every time the reason changes
   * length or clears entirely. */
  min-height: 1.55em;
  text-wrap: pretty;
}

/* ----------------------------------------------------------------- stats -- */

.pf-chain { display: flex; align-items: center; gap: calc(var(--step) * 2); font-size: 12px; color: var(--text-muted); }

.pf-chain-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex: none;
  background: var(--text-subtle);
}

.pf-chain-dot.is-ok { background: var(--live-dot); }
.pf-chain-dot.is-bad { background: var(--danger); }

/* --------------------------------------------------------------- history -- */

.pf-horizons { flex: 0 0 auto; width: auto; }

.pf-outcome {
  display: flex;
  align-items: baseline;
  gap: calc(var(--step) * 2.5);
  flex-wrap: wrap;
  font-variant-numeric: tabular-nums;
}

.pf-outcome-start { font-size: 18px; font-weight: 600; color: var(--text-muted); }
.pf-outcome-arrow { align-self: center; color: var(--text-subtle); font-size: 16px; }

.pf-outcome-end {
  font-size: clamp(26px, 5.6vw, 34px);
  font-weight: 700;
  letter-spacing: -0.025em;
}

.pf-outcome-delta {
  padding: calc(var(--step) * 0.5) calc(var(--step) * 2);
  border: 1px solid var(--accent-mid);
  border-radius: var(--radius-pill);
  background: var(--accent-soft);
  color: var(--text-primary);
  font-size: 13px;
  font-weight: 600;
}

.pf-outcome-delta.is-down { border-color: var(--danger); background: transparent; }

.pf-spark-wrap { min-width: 0; }

.pf-spark {
  display: block;
  width: 100%;
  height: 84px;
}

/*
 * Two paths, in the order sparkline() appends them: the area under the line,
 * then the line. Positional selectors rather than classes because dom.js's
 * svg() helper builds unclassed paths, and the order is fixed by the code that
 * writes them.
 */
.pf-spark path:nth-child(1) { fill: var(--accent-soft); stroke: none; }

.pf-spark path:nth-child(2) {
  fill: none;
  stroke: var(--chart-line);
  stroke-width: 2;
  /* The viewBox is stretched to the card width with preserveAspectRatio="none",
   * which would smear the stroke horizontally without this. */
  vector-effect: non-scaling-stroke;
}

.pf-spark-empty { color: var(--text-subtle); font-size: 13px; }

.pf-spark-years {
  display: flex;
  justify-content: space-between;
  margin-top: calc(var(--step) * 1);
  font-size: 11px;
  color: var(--text-subtle);
  font-variant-numeric: tabular-nums;
}

.pf-context { display: grid; gap: calc(var(--step) * 3); }

@media (min-width: 560px) {
  .pf-context { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.pf-context dt { color: var(--text-muted); font-size: 12px; }

.pf-context dd {
  font-size: 14px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  text-wrap: pretty;
}

.pf-notes {
  display: grid;
  gap: calc(var(--step) * 2);
  margin-top: calc(var(--step) * 4);
  color: var(--text-muted);
  font-size: 12.5px;
  line-height: 1.6;
}

.pf-notes li { position: relative; padding-left: calc(var(--step) * 3.5); }

.pf-notes li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--text-subtle);
}

/* The returns table lives inside .scroll-x, so these only colour the figures. */
.pf-history td.is-up { color: var(--success); }
.pf-history td.is-down { color: var(--danger); }
.pf-history td.is-empty { color: var(--text-subtle); }

.pf-link {
  display: inline-flex;
  align-items: center;
  gap: calc(var(--step) * 1.25);
  color: var(--text-muted);
  border-bottom: 1px solid var(--divider-strong);
  font-size: 12.5px;
  transition: color 0.15s var(--ease), border-color 0.15s var(--ease);
}

.pf-link:hover { color: var(--text-primary); border-color: var(--accent); }
.pf-muted { color: var(--text-subtle); font-size: 12.5px; }

/* ---------------------------------------------------------- how it works -- */

/* Inside a card the disclosure's own top border would double the card edge. */
.pf-how > .pf-disclosure { border-top: 0; padding-top: 0; }

.pf-how-body { display: grid; gap: calc(var(--step) * 3); }
.pf-how-body h3 { color: var(--text-primary); font-size: 13px; letter-spacing: 0.01em; }

.pf-split { display: grid; }

.pf-split-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: calc(var(--step) * 3);
  padding-block: calc(var(--step) * 2);
  border-bottom: 1px solid var(--divider);
  font-size: 13.5px;
}

.pf-split-row:last-child { border-bottom: 0; }

.pf-split-row dt { display: flex; align-items: center; gap: calc(var(--step) * 2); color: var(--text-muted); min-width: 0; }
.pf-split-row dd { font-weight: 600; font-variant-numeric: tabular-nums; flex: none; }

.pf-contract { display: inline-flex; align-items: center; gap: calc(var(--step) * 2); }
