/* SPACING: reach for a token — `--card-pad`, `--card-gap`, `--sp-1`…`--sp-6` —
   not a raw rem, and not the value in the rule above. Cards on the padding
   contract are enforced by `test/layout-tokens.test.js`; the contract and the
   list of what is on it are in `docs/visual-language.md` → Tokens. Raw values
   still in this file are legacy from a 2px grid, not a precedent to follow. */
/* Forecast, Planner and Budget. */
/* ══ Forecast / Planner / Budget ═══════════════════════════════════════ */
/* The forecast breakdown lives in the 330px rail: keep the committed and
   average columns in the DOM (the renderer emits four cells) but hide them,
   so the rail shows category and the number that matters. */
/* By Category is full width: every column shows, figures right-aligned. */
#panel-forecast .fc-cat-card td:nth-child(n+2),#panel-forecast .fc-cat-card th:nth-child(n+2){
  text-align:end;
  width:16%;
  white-space:nowrap;
}
#panel-forecast .fc-cat-card td.amt{font-weight:600;}
#panel-forecast > .card + .card-head{margin-top:var(--sp-5);}
#panel-forecast #fc-kpis + .card-head{margin-top:0;}
.fc-total-row{
  display:flex;
  justify-content:space-between;
  padding:var(--sp-3) var(--sp-4);
  border-top:1px solid var(--border);
  font-size:var(--fs-body);
  color:var(--muted);
}
.fc-total-row b{color:var(--text);font-variant-numeric:tabular-nums;}
#fc-basis{margin:0 0 var(--sp-5);}
/* Planner: new-trip input sits in the control bar */
.pl-newtrip{display:flex;gap:var(--sp-2);align-items:center;flex:1;min-width:16.25rem;max-width:460px;}
/* Matches the Expenses / Income search box and the month stepper — one corner for
   every control that sits in a `.sec2-bar`. */
.pl-newtrip input{
  flex:1;
  padding:0.625rem 0.875rem;
  border-radius:var(--radius) !important;
  border:1px solid var(--border);
  background:var(--surface);
  font-size:var(--fs-body);
}
#trips-wrap .trip-card{border-radius:var(--radius);}
/* The empty state stands exactly where the first trip card will, rather than in a
   narrower box centred over it. `.empty-state` carries a `--card-wide` cap and
   `auto` margins (03-base-layout.css), which is right for a message inside a
   column but not here: the promise was 1100px and centred, the card it promises
   is the full 1369px and flush left, so naming a trip grew the box 269px and
   slid it 135px left — the one moment the section should look settled. Width,
   edge and corner now match the card; only the height differs, because a card
   with nothing in it yet has no reason to be 745px tall. */
#trips-wrap .empty-state{
  max-width:none;
  margin:0 0 1.25rem;
}
/* Budget: the per-category budget editor as a rail list */
#panel-budget .split-rail .budget-set-list{display:flex;flex-direction:column;padding:0.375rem;gap:var(--sp-1);}
#panel-budget .split-rail .budget-row{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:0.625rem;
  padding:0.6875rem var(--sp-4);
  border-bottom:1px solid var(--border);
}
#panel-budget .split-rail .budget-row:last-child{border-bottom:0;}
/* Set monthly budgets: the rows sit inset inside the card, each with its own smaller
   corners, instead of running edge to edge. Flush rows put their tint and outline
   right against the card's border and rounded corners, which read as two frames
   fighting. A set budget uses the same tile tokens as Overview tiles. */
#panel-budget .split-rail .budget-row,#panel-budget .split-rail .budget-row.set{
  border:0;
  border-radius:var(--radius-sm);
  padding:0.4375rem var(--sp-3);
  gap:var(--sp-2);
  font-size:var(--fs-label);
  background:transparent;
}
#panel-budget .split-rail .budget-spent-hint{
  font-size:var(--fs-meta);
  color:var(--muted);
  font-weight:500;
  font-variant-numeric:tabular-nums;
  white-space:nowrap;
}
#panel-budget .split-rail .budget-input-wrap input{width:5.25rem;padding-block:0.25rem;}
/* Budget vs spending list (renderBudget). */
.budget-list{display:flex;flex-direction:column;gap:var(--sp-4);}
.bgt-head{display:flex;align-items:center;gap:var(--sp-2);margin-bottom:0.4375rem;font-size:var(--fs-body);min-width:0;}
.bgt-head .cat-mark{flex:1;min-width:0;}
.bgt-fig{font-variant-numeric:tabular-nums;font-weight:600;white-space:nowrap;}
.bgt-fig .of{color:var(--muted);font-weight:400;}
.bgt-status{
  font-size:var(--fs-meta);
  font-weight:600;
  font-variant-numeric:tabular-nums;
  white-space:nowrap;
  min-width:7.5rem;
  text-align:end;
}
.bgt-status.ok{color:var(--pos);}
.bgt-status.tight{color:var(--accent);}
.bgt-status.over{color:var(--neg);}
.bgt-status.free{color:var(--muted);font-weight:500;}
.bgt-split{display:flex;align-items:baseline;gap:var(--sp-2);font-size:var(--fs-meta);color:var(--muted);font-weight:500;}
.bgt-split-note{font-weight:400;}
/* The limit is the track: a flat capsule the width of the budget. Spent and still
   due are one continuous fill — no outline between them. Past the limit the fill
   carries on in solid red, flush with it, and a tick marks where the budget ended. */
.bgt-bar{position:relative;display:flex;}
.bgt-bar::before{
  content:"";
  position:absolute;
  inset-inline-start:0;
  top:0;
  height:100%;
  width:var(--limit,100%);
  background:var(--surface3);
  border-radius:var(--radius-pill);
}
.bgt-bar.meter > i{border-radius:0;}
.bgt-bar i{position:relative;display:block;height:100%;}
.bgt-bar i:first-of-type{border-start-start-radius:var(--radius-pill);border-end-start-radius:var(--radius-pill);}
.bgt-bar i:last-of-type{border-start-end-radius:var(--radius-pill);border-end-end-radius:var(--radius-pill);}
.bgt-bar i:only-of-type{border-radius:var(--radius-pill);}
/* The fill is the row's category colour (`--c`, set from getExpCatColor), so each bar
   reads as that category's spending; still due is the same colour faded. */
.bgt-bar i.spent{background:var(--c,var(--chart-neutral));}
.bgt-bar i.due{background:color-mix(in srgb,var(--c,var(--chart-neutral)) 45%,var(--surface3));}
.bgt-bar i.over{background:var(--chart-neg);}
/* Where the budget ended, on a row that went past it: once the fill covers the track
   the outline no longer shows the limit, so a tick standing just proud of the bar does. */
.bgt-bar.over{overflow:visible;}
.bgt-bar.over::after{
  content:"";
  position:absolute;
  inset-inline-start:var(--limit);
  top:calc(var(--sp-1) * -0.5);
  bottom:calc(var(--sp-1) * -0.5);
  width:2px;
  margin-inline-start:-1px;
  border-radius:1px;
  background:var(--text);
}
/* No limit set, so no track: the absence is the statement. */
.bgt-bar.no-limit::before{display:none;}
#budget-legend{margin-top:1.125rem;}
/* Forecast headline figures: three cards of their own. They were one joined
   `.kpi-strip` laid out on four columns for three figures, so the row stopped a
   quarter short of the section under it and the panes were pushed off the width
   they had. Three cards on three equal columns end on the chart's right edge.
   The cards share a four-row subgrid — label, figure, sub-line, meter — so the
   numbers sit on one line across the row. All three fill the meter track: the
   two next-month cards with how much of the figure is already committed, the
   balance card with today against the year's change. It held a meter on one card
   for a while, which left the other two 43% empty below their sub-line. */
#panel-forecast .fc-tiles{
  display:grid;
  grid-template-columns:repeat(3,minmax(0,1fr));
  grid-template-rows:repeat(4,auto);
  gap:var(--card-gap);
  margin-bottom:var(--sp-5);
}
#panel-forecast .fc-tiles > .kpi{
  display:grid;
  grid-row:span 4;
  grid-template-rows:subgrid;
  grid-template-columns:minmax(0,1fr);
  row-gap:0;
  align-content:start;
}
#panel-forecast .fc-tiles > .kpi > .k{grid-row:1;align-self:end;min-width:0;max-width:100%;}
#panel-forecast .fc-tiles > .kpi > .v{grid-row:2;align-self:last baseline;min-width:0;max-width:100%;}
#panel-forecast .fc-tiles > .kpi > .s{grid-row:3;align-self:start;min-width:0;max-width:100%;}
#panel-forecast .fc-tiles .ov-meter{grid-row:4;align-self:end;padding-top:var(--sp-2);min-width:0;max-width:100%;}
/* Two columns leave a third card with nowhere to sit, so the balance — the one
   that carries the meter — takes the second row whole rather than half of it. */
@media (max-width:1150px){
  #panel-forecast .fc-tiles{grid-template-columns:1fr 1fr;}
  #panel-forecast .fc-tiles > .kpi:last-child{grid-column:1/-1;}
}
@media (max-width:760px){
  #panel-forecast .fc-tiles{grid-template-columns:1fr;}
}
/* Budget lists: categories are marked by their badge. A set budget no longer gets a
   violet stripe and wash — its row is a step lighter and shows the amount instead of
   an input, which is the difference that matters. */
#panel-budget .split-rail .budget-row .cat-mark{flex:1;min-width:0;}
/* Two columns: KPI + spending vs budget editor. The editor card stretches to the
   full height of the left stack and grows with every category row — no short cap. */
#panel-budget .bg-layout{align-items:stretch;}
#panel-budget .bg-col-main{display:flex;flex-direction:column;gap:0;min-width:0;}
#panel-budget .bg-col-main > .bg-kpis{margin-bottom:1.375rem;}
#panel-budget .bg-col-main > .card-head{margin-top:0;}
#panel-budget .bg-set-rail{
  display:flex;
  flex-direction:column;
  min-height:0;
  align-self:stretch;
}
#panel-budget .bg-set-rail > .card-head{flex:0 0 auto;}
#panel-budget .bg-set-card{
  flex:1 1 auto;
  display:flex;
  flex-direction:column;
  min-height:0;
}
#panel-budget .bg-set-card .budget-set-list{flex:1 1 auto;}
@media (max-width:1150px){
  #panel-budget .bg-set-card{flex:none;min-height:auto;}
}
/* A set budget's row on the same tile tokens as the Overview's tiles. */
#panel-budget .split-rail .budget-row.set{background:var(--tile);box-shadow:inset 0 0 0 1px var(--tile-edge);}
.start-bal-form{display:flex;gap:var(--sp-3);flex-wrap:wrap;align-items:flex-end;}
.field--stack{flex-direction:column;display:flex;gap:var(--sp-2);}
#sb-amount{width:9.375rem;}
.budget-row--gap{margin-bottom:var(--sp-2);}
.plan-section-label{margin:0 0 var(--sp-2);margin-inline-start:var(--sp-1);}
.plan-section-label--lg{margin:0 0 var(--sp-3);margin-inline-start:var(--sp-1);}
.plan-buffer-meta{font-size:var(--fs-meta);color:var(--muted);margin-bottom:var(--sp-3);}
.plan-buffer-edit{display:flex;align-items:center;gap:var(--sp-2);margin-bottom:var(--sp-3);flex-wrap:wrap;}
.plan-buffer-input-wrap{display:inline-flex;align-items:center;gap:var(--sp-2);}
.plan-buffer-input{width:7.5rem;}
.plan-footnote{margin:var(--sp-3) 0 0;margin-inline-start:var(--sp-1);font-size:var(--fs-micro);color:var(--muted);}
.plan-chart-head{margin:var(--sp-5) 0 var(--sp-2);margin-inline-start:var(--sp-1);}
.trip-chart .chart-wrap{height:14rem;}
.plan-tile .v.accent{color:var(--accent);}
