/* widgets/vault-room — THE VAULT (Craig's own room, behind the key).
   Concept of record: docs/mockups/2026-08-08 - The Vault - HQ Concept.html (Craig approved 8/8).

   DAYLIGHT, LIKE EVERY OTHER ROOM. Craig, 8/9: "Don't render The Vault in dark mode. Keep it the
   same as everything else." The concept's "your study after hours" dark ground is retired — this
   room now wears the house palette the Command Desk and the Evidence Gallery wear.

   AND IT CANNOT DRIFT BACK. The palette is ONE block below and nothing under it names a colour:
   every rule in this file reads a var(). The house room tokens are declared once here (identical
   to #portal-room-command-desk / #portal-room-gallery, which is what the room-token contract in
   widgets/portal/styles.css reads through its var(--line, …) fallbacks), and the room's own --v-*
   vocabulary is bound to them — so a re-skin is a rebinding of this block and nothing else, and
   the QA asserts the ground and the ink EQUAL another room's computed values rather than equal a
   hex typed into a test. --canopy and --action are deliberately NOT restated: they are inherited
   from :root so a white-label palette swap (firm.json → shell _PAL_MAP) carries into this room
   the way it carries everywhere else. (--signal is the one exception — see the note on it below.)

   COURT-HONEST COLOUR SURVIVES THE RE-SKIN. Chrome is --canopy, healthy is --signal, and the
   key / needs-GO / calm-alert marks are the house amber trio — the daylight reading of the
   concept's gold, never a red.

   TYPE. The app's --fs-body is 13.5px, which is right for tiles and feed lines and wrong for
   reading a whole blog post. Read surfaces in this room take --fs-read (16px floor, per the
   build spec's "~16px body floor for read surfaces"). Labels/numbers/micro keep the house
   scale so the room still reads as Firmglass. */

#portal-room-vault,
.vlt-blow {                     /* the blowup mounts on <body>, outside the room — same tokens */
  /* the house room palette — the same block the two sibling portal rooms declare */
  --line: #e7e2d4; --line-cool: #e6e9e6; --card: #fff; --bg: #f7f8f7; --sand: #fbfaf6;
  --ink-1: #24332c; --ink-2: #46564d; --ink-3: #8a8f88;
  --warn-ink: #8a5a0f; --warn-line: #ecd9a8; --warn-fill: #fdf6e7;
  --hard-line: #c5dccd; --hard-fill: #eef5f0;
  /* --signal is the ONE token where :root and the portal rooms disagree — :root says #3e7d5c,
     both sibling rooms say #306844. Craig's ask is "the same as everything else", and the rooms
     are the everything-else, so the room value wins here and the divergence is raised rather
     than papered over. --canopy and --action agree, so they are left inherited (above). */
  --signal: #306844;

  /* the room's vocabulary, bound to the house. No hex on this side of the colon, ever. */
  --v-ground: var(--bg);
  --v-card: var(--card);
  --v-card-2: var(--sand);
  --v-line: var(--line);
  --v-line-soft: var(--line-cool);
  --v-ink: var(--ink-1);
  --v-ink-quiet: var(--ink-3);
  --v-ink-mid: var(--ink-2);
  --v-label: var(--ink-2);
  --v-gold: var(--warn-ink);    /* the key / Craig's court / needs-GO */
  --v-gold-line: var(--warn-line);
  --v-gold-fill: var(--warn-fill);
  --v-up: var(--signal);        /* healthy state */
  --v-warm: var(--warn-ink);    /* calm alert. NOT red — Craig-court only, per court law */
  --v-hover: var(--hard-fill);  /* the row/cell wash that was a white scrim on the dark ground */
  --fs-read: 16px;              /* the read-surface floor. See header. */

  /* the debt-free chart's three series. render.js reads these back through getComputedStyle so
     the SVG cannot carry a colour this block has never heard of. */
  --v-chart-debt: var(--warn-ink);
  --v-chart-cash: var(--signal);
  --v-chart-x: var(--action);   /* the owner's own milestone — --action is legal in a Craig-court
                                   room by the same access ruling the Command Desk cites */
}

#portal-room-vault {
  background: var(--v-ground);
  color: var(--v-ink);
  font: 15px/1.5 'Inter', -apple-system, 'Helvetica Neue', sans-serif;
  overflow: auto;               /* the room element itself never scrolls (portal law) — this is
                                   the room's OWN declared scroll container, which the engine asks
                                   each room to own. */
}

/* ── header ─────────────────────────────────────────────────────────────────────── */
/* THE TOP-LEFT 128x52 IS NOT OURS. The portal engine's home control — the brand mark that is the
   room's only exit — is absolutely positioned there over every room, and its stylesheet reserves
   that box by contract. Caught in QA: the title rendered underneath it. The header clears it. */
#portal-room-vault .vlt-top { display:flex; align-items:baseline; gap:14px; padding:26px 40px 18px 152px; flex-wrap:wrap; }
#portal-room-vault .vlt-top h1 { font-size:27px; font-weight:800; letter-spacing:.3px; margin:0; }
#portal-room-vault .vlt-key {
  font-size:var(--fs-micro,10px); border:1px solid var(--v-gold-line); color:var(--v-gold);
  background:var(--v-gold-fill);
  border-radius:20px; padding:4px 12px; letter-spacing:.6px; font-weight:700; text-transform:uppercase;
}
#portal-room-vault .vlt-quiet { color:var(--v-ink-quiet); font-size:13px; margin-left:auto; text-align:right; }
#portal-room-vault .vlt-main { padding:0 40px 60px; max-width:1240px; }

/* ── section chrome ─────────────────────────────────────────────────────────────── */
#portal-room-vault .vlt-sec { margin:0 0 34px; }
#portal-room-vault .vlt-sec > h2 {
  font-size:var(--fs-label,11px); letter-spacing:1.6px; text-transform:uppercase;
  color:var(--canopy); margin:0 0 12px; font-weight:700;
  display:flex; align-items:baseline; gap:12px; flex-wrap:wrap;
}
#portal-room-vault .vlt-sec > h2 .vlt-h2note {
  color:var(--v-ink-quiet); font-weight:400; letter-spacing:0; text-transform:none;
  font-size:13px; margin-left:auto;
}
#portal-room-vault .vlt-card { background:var(--v-card-2); border:1px solid var(--v-line); border-radius:16px; }

/* ── toggles / tabs / pills (one control language for the whole room) ───────────── */
#portal-room-vault .vlt-tabs { display:flex; gap:8px; flex-wrap:wrap; margin-bottom:12px; }
#portal-room-vault .vlt-tab {
  font:600 13px 'Inter',sans-serif; border-radius:999px; padding:7px 15px; cursor:pointer;
  border:1px solid var(--v-line); background:var(--v-card); color:var(--v-ink-mid);
  display:inline-flex; align-items:baseline; gap:7px;
}
#portal-room-vault .vlt-tab:hover { border-color:var(--hard-line); color:var(--canopy); }
/* the selected tab is solid canopy with white type — the house's own on-state (.fgr-chip.on,
   .eg-tab.is-on). On the dark ground it was a lifted card; on cream that reads as unselected. */
#portal-room-vault .vlt-tab.on { background:var(--canopy); border-color:var(--canopy); color:#fff; }
#portal-room-vault .vlt-tab .n { font-weight:700; opacity:.7; font-size:12px; }
#portal-room-vault .vlt-tab:focus-visible,
#portal-room-vault button:focus-visible,
#portal-room-vault select:focus-visible,
#portal-room-vault [tabindex]:focus-visible { outline:2px solid var(--action); outline-offset:2px; }

/* ── §1 CONTENT ─────────────────────────────────────────────────────────────────── */
#portal-room-vault .vlt-runway {
  display:flex; gap:10px; flex-wrap:wrap; margin:0 0 14px; font-size:13px; color:var(--v-ink-quiet);
}
#portal-room-vault .vlt-rw {
  background:var(--v-card); border:1px solid var(--v-line); border-radius:12px; padding:9px 14px;
  display:flex; flex-direction:column; gap:2px; min-width:150px;
}
#portal-room-vault .vlt-rw .k { font-size:var(--fs-label,11px); letter-spacing:.8px; text-transform:uppercase; color:var(--v-label); font-weight:600; }
#portal-room-vault .vlt-rw .v { font-size:var(--fs-num,24px); font-weight:800; color:var(--v-ink); line-height:1.1; font-variant-numeric:tabular-nums; }
#portal-room-vault .vlt-rw .s { font-size:12.5px; color:var(--v-ink-quiet); }
#portal-room-vault .vlt-rw.dry .v { color:var(--v-warm); }

#portal-room-vault .vlt-rows { padding:2px 20px; }
#portal-room-vault .vlt-row {
  display:flex; gap:14px; align-items:baseline; padding:12px 0;
  border-bottom:1px dashed var(--v-line-soft); font-size:14.5px; cursor:pointer;
}
#portal-room-vault .vlt-row:last-child { border-bottom:none; }
#portal-room-vault .vlt-row:hover { background:var(--v-card); }
#portal-room-vault .vlt-row .d { width:104px; flex:none; color:var(--v-ink-quiet); font-size:13px; }
/* ONE BOLD ANCHOR PER ROW (the readability baseline): the title carries the weight and the
   date, the pill and the hint are all subordinate to it. Before this the row had no anchor at
   all — five items in a line at the same weight, which is a row you scan twice. */
#portal-room-vault .vlt-row .t { color:var(--v-ink); flex:1 1 auto; font-weight:650; }
/* the court mark is a CHIP, not a second bold sentence competing with the title */
#portal-room-vault .vlt-row .go {
  color:var(--v-gold); background:var(--v-gold-fill); border:1px solid var(--v-gold-line);
  border-radius:999px; padding:3px 9px; flex:none;
  font-size:var(--fs-micro,10px); font-weight:700; letter-spacing:.5px;
}
#portal-room-vault .vlt-row .sp {
  font-size:var(--fs-micro,10px); font-weight:700; letter-spacing:.7px; text-transform:uppercase;
  border-radius:999px; padding:3px 9px; border:1px solid var(--v-line); color:var(--v-ink-quiet); flex:none;
}
#portal-room-vault .vlt-row .sp.live { color:var(--v-up); border-color:var(--v-up); }
#portal-room-vault .vlt-row .sp.staged { color:var(--v-gold); border-color:var(--v-gold-line); }
#portal-room-vault .vlt-row .sp.failed { color:var(--v-warm); border-color:var(--v-warm); }
#portal-room-vault .vlt-row .hint { color:var(--v-ink-quiet); font-size:12px; flex:none; }
#portal-room-vault .vlt-row.open { background:var(--v-hover); }

/* THE READER, IN PLACE. No drawer, no popout — the body opens under the row it belongs to.
   The markup comes from window.csReaderHTML (the content widget's own component, escape-first),
   so the words and the escaping are shared with the Content drawer and cannot drift. Its csp-*
   styles are #ops-modal-scoped, which this room is NOT inside — so the presentation is restated
   here, at the read floor. Shared HTML, local ink: the fork is deliberate and is only ever
   about colour and size. */
#portal-room-vault .vlt-read { padding:4px 0 22px; max-width:76ch; }
#portal-room-vault .vlt-read .csp-meta { display:flex; gap:10px; align-items:center; flex-wrap:wrap; margin-bottom:10px; font-size:12.5px; color:var(--v-ink-quiet); }
#portal-room-vault .vlt-read .csp-title { font:800 22px/1.3 'Inter',sans-serif; color:var(--v-ink); margin:0 0 12px; }
#portal-room-vault .vlt-read .csp-body { font-size:var(--fs-read); line-height:1.65; color:var(--v-ink); }
#portal-room-vault .vlt-read .csp-body p { margin:0 0 14px; }
#portal-room-vault .vlt-read .csp-body h2,
#portal-room-vault .vlt-read .csp-body h3,
#portal-room-vault .vlt-read .csp-body h4 { color:var(--v-ink); margin:22px 0 8px; line-height:1.3; }
#portal-room-vault .vlt-read .csp-body h2 { font-size:19px; }
#portal-room-vault .vlt-read .csp-body h3 { font-size:17px; }
#portal-room-vault .vlt-read .csp-body h4 { font-size:var(--fs-read); }
#portal-room-vault .vlt-read .csp-body ul,
#portal-room-vault .vlt-read .csp-body ol { margin:0 0 14px; padding-left:22px; }
#portal-room-vault .vlt-read .csp-body li { margin:0 0 6px; }
#portal-room-vault .vlt-read .csp-body a { color:var(--v-gold); }
#portal-room-vault .vlt-read .csp-body code { background:var(--v-hover); border-radius:4px; padding:1px 5px; font-size:14px; }
#portal-room-vault .vlt-read .csp-hero { display:block; width:100%; height:auto; border-radius:12px; margin:0 0 16px; }
#portal-room-vault .vlt-read .csp-frame { width:100%; height:60vh; border:1px solid var(--v-line); border-radius:12px; background:var(--v-card); }
/* the honest-absence box: the house calm-amber wash, which is what a "waiting on X" is —
   never a red, never a silent omission. */
#portal-room-vault .vlt-read .csp-pending,
#portal-room-vault .vlt-gap {
  background:var(--warn-fill); border:1px solid var(--warn-line); color:var(--v-ink-mid);
  border-radius:12px; padding:12px 16px; font-size:13.5px; line-height:1.55;
}
#portal-room-vault .vlt-read .csp-live-link,
#portal-room-vault .vlt-live-link { color:var(--v-gold); font-size:13px; font-weight:600; }
#portal-room-vault .vlt-gap b { color:var(--v-gold); }
#portal-room-vault .vlt-gap .k {
  display:block; font-size:var(--fs-micro,10px); letter-spacing:1.2px; font-weight:700;
  color:var(--v-gold); margin-bottom:5px; text-transform:uppercase;
}

/* ── §2 PIPELINE ────────────────────────────────────────────────────────────────── */
#portal-room-vault .vlt-kan { display:flex; gap:12px; overflow-x:auto; padding:2px 2px 12px; align-items:flex-start; }
#portal-room-vault .vlt-col {
  flex:0 0 232px; background:var(--v-card-2); border:1px solid var(--v-line);
  border-radius:14px; padding:12px 11px; display:flex; flex-direction:column; gap:9px;
}
#portal-room-vault .vlt-col.empty { opacity:.45; }
#portal-room-vault .vlt-col.dragover { border-color:var(--v-gold); background:var(--v-gold-fill); }
#portal-room-vault .vlt-col > .ch {
  font-size:var(--fs-label,11px); letter-spacing:.9px; text-transform:uppercase;
  color:var(--v-label); font-weight:700; display:flex; justify-content:space-between; gap:8px;
}
#portal-room-vault .vlt-deal {
  background:var(--v-card); border:1px solid var(--v-line); border-radius:12px;
  padding:11px 12px; font-size:13.5px; cursor:grab;
}
#portal-room-vault .vlt-deal:active { cursor:grabbing; }
/* ONE BOLD ANCHOR PER CARD. The card used to run three of them — the name, the value and the
   "Next:" label — so nothing on it led. The name is the anchor; the value keeps its own colour
   and steps down a weight, and the "Next:" label drops to a quiet eyebrow. */
#portal-room-vault .vlt-deal .nm { font-weight:700; color:var(--v-ink); display:block; margin-bottom:3px; }
#portal-room-vault .vlt-deal .vv { color:var(--v-up); font-weight:600; font-variant-numeric:tabular-nums; float:right; margin-left:8px; }
/* Three lines on a card, whatever the board carries — see the clamp note in render.js. The list
   view and the tooltip carry the full text; this only folds it. */
#portal-room-vault .vlt-deal .nx {
  color:var(--v-ink-mid); font-size:12.5px; margin-top:5px; line-height:1.45;
  display:-webkit-box; -webkit-line-clamp:3; -webkit-box-orient:vertical; overflow:hidden;
}
#portal-room-vault .vlt-deal .nx b { color:var(--v-ink-quiet); font-weight:600; }
#portal-room-vault .vlt-deal .rot { color:var(--v-warm); font-size:12px; margin-top:5px; }
#portal-room-vault select.vlt-stage {
  margin-top:8px; width:100%; font:600 12px 'Inter',sans-serif; padding:5px 7px; border-radius:8px;
  border:1px solid var(--v-line); background:var(--v-card); color:var(--v-ink); cursor:pointer;
}
#portal-room-vault select.vlt-stage:disabled { opacity:.5; cursor:progress; }

#portal-room-vault table.vlt-list { width:100%; border-collapse:collapse; font-size:13.5px; }
#portal-room-vault table.vlt-list th {
  text-align:left; font-size:var(--fs-label,11px); letter-spacing:.9px; text-transform:uppercase;
  color:var(--v-label); font-weight:700; padding:9px 12px; border-bottom:1px solid var(--v-line);
  cursor:pointer; white-space:nowrap;
}
#portal-room-vault table.vlt-list td { padding:10px 12px; border-bottom:1px dashed var(--v-line-soft); vertical-align:top; }
#portal-room-vault table.vlt-list tr:last-child td { border-bottom:none; }
/* the deal NAME is the row's anchor (rendered <b> in render.js); the value carries colour, not
   a competing weight — same one-anchor rule the kanban card follows. */
#portal-room-vault table.vlt-list td.num { text-align:right; font-variant-numeric:tabular-nums; color:var(--v-up); font-weight:600; white-space:nowrap; }
#portal-room-vault table.vlt-list tr:hover td { background:var(--v-card); }
#portal-room-vault .vlt-foot { font-size:13px; color:var(--v-ink-quiet); margin-top:10px; line-height:1.55; }

/* ── §3 MONEY ───────────────────────────────────────────────────────────────────── */
#portal-room-vault .vlt-ents { display:grid; grid-template-columns:repeat(auto-fit,minmax(232px,1fr)); gap:14px; }
#portal-room-vault .vlt-ent { background:var(--v-card); border:1px solid var(--v-line); border-radius:16px; padding:18px 22px; }
#portal-room-vault .vlt-ent .n {
  font-size:var(--fs-label,11px); letter-spacing:1.4px; text-transform:uppercase; color:var(--v-label);
  margin-bottom:6px; display:flex; justify-content:space-between; gap:10px; font-weight:600;
}
#portal-room-vault .vlt-ent .cash { font-size:30px; font-weight:800; font-variant-numeric:tabular-nums; line-height:1.1; }
#portal-room-vault .vlt-ent .sub { font-size:13.5px; margin-top:3px; color:var(--v-ink-quiet); }
#portal-room-vault .vlt-ent .beat { margin-top:11px; padding-top:10px; border-top:1px dashed var(--v-line); font-size:13px; color:var(--v-ink-mid); }
#portal-room-vault .vlt-ent.pw .n span:last-child { color:var(--v-gold); }
#portal-room-vault .vlt-total { display:flex; gap:18px; align-items:baseline; margin:16px 2px 22px; font-size:14.5px; color:var(--v-label); flex-wrap:wrap; }
/* three figures on one line, and the entity CARDS above are the section's anchors — so these
   step down rather than shouting over them. */
#portal-room-vault .vlt-total b { color:var(--v-ink); font-size:17px; font-weight:650; font-variant-numeric:tabular-nums; }

#portal-room-vault .vlt-df { background:var(--v-card-2); border:1px solid var(--v-line); border-radius:16px; padding:16px 20px 12px; }
#portal-room-vault .vlt-df-head { display:flex; align-items:baseline; gap:14px; flex-wrap:wrap; margin-bottom:8px; }
#portal-room-vault .vlt-df-head .hl { font-size:20px; font-weight:800; color:var(--v-ink); }
#portal-room-vault .vlt-df-head .hl b { color:var(--v-gold); }
#portal-room-vault .vlt-btn {
  font:700 12.5px 'Inter',sans-serif; border-radius:999px; padding:7px 15px; cursor:pointer;
  border:1px solid var(--v-gold-line); background:transparent; color:var(--v-gold);
}
#portal-room-vault .vlt-btn { background:var(--v-gold-fill); }
#portal-room-vault .vlt-btn:hover { background:var(--v-gold); color:var(--v-card); }
#portal-room-vault .vlt-df-src { font-size:12.5px; color:var(--v-ink-quiet); margin-top:8px; line-height:1.55; }
#portal-room-vault .vlt-payoffs { display:grid; grid-template-columns:repeat(auto-fit,minmax(210px,1fr)); gap:10px; margin-top:12px; }
#portal-room-vault .vlt-payoff { background:var(--v-card); border:1px solid var(--v-line); border-radius:12px; padding:10px 13px; font-size:13px; }
#portal-room-vault .vlt-payoff .nm { font-weight:700; color:var(--v-ink); }
#portal-room-vault .vlt-payoff .dt { color:var(--v-gold); font-weight:700; font-variant-numeric:tabular-nums; }
#portal-room-vault .vlt-payoff .bal { color:var(--v-ink-quiet); font-variant-numeric:tabular-nums; }

/* THE BLOWUP. Craig: "see exactly when I'm going to be debt free." Full viewport, every month
   label drawn — the inline hero has room for a label every few months, this one has room for all
   of them, which is the entire reason it exists. */
#portal-room-vault .vlt-blow,
.vlt-blow {
  position:fixed; inset:0; z-index:9600; background:var(--v-ground);
  display:flex; flex-direction:column; padding:22px 30px 26px; color:var(--v-ink);
  font:15px/1.5 'Inter',-apple-system,sans-serif;
}
.vlt-blow[hidden] { display:none; }
.vlt-blow .bh { display:flex; align-items:baseline; gap:16px; margin-bottom:10px; flex-wrap:wrap; }
.vlt-blow .bh h2 { font-size:22px; font-weight:800; margin:0; color:var(--canopy); }
.vlt-blow .bh .hl b { color:var(--v-gold); }
.vlt-blow .bh .x {
  margin-left:auto; background:var(--v-card); border:1px solid var(--v-line); color:var(--v-ink-mid);
  border-radius:999px; padding:6px 14px; cursor:pointer; font:700 12.5px 'Inter',sans-serif;
}
.vlt-blow .bh .x:hover { border-color:var(--v-gold); color:var(--v-gold); }
.vlt-blow .bwrap { flex:1 1 auto; min-height:0; overflow:auto; }
.vlt-blow svg { width:100%; height:auto; display:block; }
.vlt-blow .bfoot { font-size:12.5px; color:var(--v-ink-quiet); margin-top:10px; line-height:1.55; }

/* ── the YNAB slot: a marked hole, not a stub feature ───────────────────────────── */
#portal-room-vault .vlt-slot {
  border:1px dashed var(--v-line); border-radius:14px; padding:16px 20px; margin-top:14px;
  color:var(--v-ink-quiet); font-size:13.5px; line-height:1.6; background:transparent;
}
#portal-room-vault .vlt-slot .k {
  display:block; font-size:var(--fs-micro,10px); letter-spacing:1.2px; font-weight:700;
  color:var(--v-label); margin-bottom:6px; text-transform:uppercase;
}

/* ── doors back into the surfaces this room does not re-implement ───────────────── */
#portal-room-vault .vlt-doors { display:flex; gap:10px; flex-wrap:wrap; margin-top:14px; }
#portal-room-vault .vlt-door {
  font:600 13px 'Inter',sans-serif; border-radius:12px; padding:9px 15px; cursor:pointer;
  border:1px solid var(--v-line); background:var(--v-card); color:var(--v-ink-mid); text-align:left;
}
#portal-room-vault .vlt-door:hover { border-color:var(--v-gold-line); color:var(--v-ink); }
#portal-room-vault .vlt-door b { color:var(--v-ink); display:block; font-size:13.5px; }
#portal-room-vault .vlt-door span { font-size:12px; color:var(--v-ink-quiet); }

@media (max-width: 860px) {
  #portal-room-vault .vlt-top { padding:20px 18px 14px; }
  #portal-room-vault .vlt-main { padding:0 18px 50px; }
  #portal-room-vault .vlt-quiet { margin-left:0; text-align:left; width:100%; }
}
