/* budget — page-scoped styles. Owned by this page only.
   Shared primitives live in planner/planner.css and are READ-ONLY from here.
   Scope every rule under [data-view="budget"] so it cannot leak to another page.

   The screen is three blocks that have to read as one:
     1. a money band — four tiles, each carrying its own qualifier
     2. the guests' rooms — a table whose WORKING column has to stay readable
     3. the ledger — an eight-field editable row per line, grouped by category

   Two responsive rules do most of the work:
     · the rooms table folds into cards below 1024px, because the WORKING text
       needs a full-width line and a six-column table cannot give it one;
     · the ledger folds into cards below 768px, because eight editable controls
       in a row is not a phone layout and horizontal scroll is not an answer.
   Both are the same technique — `display:block` on the table parts, then the
   <tr> becomes a grid or flex card. No duplicate markup, no JS.                */

/* ── shared bits ─────────────────────────────────────────────────────────── */

/* words that only exist once a table has folded into cards ("3 nights") */
[data-view="budget"] .unit{display:none}

/* every figure on this screen lines up on the same digit column */
[data-view="budget"] .money,
[data-view="budget"] .num,
[data-view="budget"] input[type="number"]{font-variant-numeric:tabular-nums}

/* ── 1. the money band ───────────────────────────────────────────────────── */

[data-view="budget"] .moneyband{grid-template-columns:repeat(auto-fit,minmax(10.5rem,1fr))}
[data-view="budget"] .moneyband .stat{padding:var(--s4) var(--s4) var(--s3);display:grid;
  align-content:start;gap:.1rem}
[data-view="budget"] .moneyband .stat b{font-size:1.6rem;letter-spacing:-.01em}
[data-view="budget"] .moneyband .stat > span{margin-top:.1rem}
/* the qualifier that used to be its own tile */
[data-view="budget"] .statnote{display:flex;align-items:center;gap:.4rem;margin-top:.35rem;
  font-style:normal;font-size:var(--ft-meta);color:var(--muted);line-height:1.3;
  font-variant-numeric:tabular-nums}
[data-view="budget"] .statnote[data-kind="bad"]{color:var(--bad)}
[data-view="budget"] .statnote[data-kind="good"]{color:var(--good)}
[data-view="budget"] .statnote .bar{flex:1 1 auto;min-width:2.5rem;max-width:5rem}

/* ── panels ──────────────────────────────────────────────────────────────── */

[data-view="budget"] .panel__head{align-items:flex-start;gap:var(--s4) var(--s5)}
[data-view="budget"] .panel__head .tools{align-items:flex-start;gap:var(--s4);
  margin-left:auto;flex:0 0 auto}
/* the panel's own headline figure, so the band doesn't have to carry it */
[data-view="budget"] .headfig{text-align:right}
[data-view="budget"] .headfig b{display:block;font-family:var(--display);font-weight:400;
  font-size:1.25rem;line-height:1.1;color:var(--ink)}
[data-view="budget"] .headfig span{display:block;font-size:var(--ft-label);letter-spacing:.08em;
  text-transform:uppercase;color:var(--muted);margin-top:.15rem}

/* "Priced from: a, b, c" — a list of inputs, set as a list, not as prose */
[data-view="budget"] .inputs{margin:var(--s3) 0 0;display:flex;flex-wrap:wrap;
  align-items:baseline;gap:.3rem var(--s2);font-size:var(--ft-meta);color:var(--muted)}
[data-view="budget"] .inputs dt{font-size:var(--ft-label);letter-spacing:.1em;
  text-transform:uppercase;font-weight:700}
[data-view="budget"] .inputs dd{margin:0;padding:.05rem .45rem;border:1px solid var(--line);
  border-radius:2px;background:var(--surface-2)}

/* empty states name the next action instead of describing the absence */
[data-view="budget"] .empty{display:grid;justify-items:center;gap:var(--s3);
  padding:var(--s7) var(--s5)}
[data-view="budget"] .empty h3{font-family:var(--display);font-size:var(--ft-h2);color:var(--ink)}
[data-view="budget"] .empty p{max-width:44ch;color:var(--muted);font-size:var(--ft-meta);
  line-height:var(--lh-ui)}

/* ── 2. the guests' rooms ────────────────────────────────────────────────── */

[data-view="budget"] .roomsum{display:grid;gap:var(--s4) var(--s6);align-items:start;
  grid-template-columns:minmax(0,1fr) minmax(14rem,20rem);
  padding:var(--s4) var(--s5);border-bottom:1px solid var(--line);background:var(--surface-2)}
[data-view="budget"] .roomsum__nights{display:flex;flex-wrap:wrap;gap:var(--s5)}
[data-view="budget"] .roomstat > span{display:block;font-size:var(--ft-label);letter-spacing:.1em;
  text-transform:uppercase;color:var(--muted)}
[data-view="budget"] .roomstat > b{display:block;font-family:var(--display);font-weight:400;
  font-size:1.25rem;line-height:1.2;color:var(--ink);font-variant-numeric:tabular-nums}
[data-view="budget"] .roomstat > em{display:block;font-style:normal;font-size:var(--ft-meta);
  color:var(--muted);font-variant-numeric:tabular-nums}

[data-view="budget"] .roomblock{display:grid;gap:.35rem}
[data-view="budget"] .roomblock__top{display:flex;align-items:baseline;
  justify-content:space-between;gap:var(--s3)}
[data-view="budget"] .roomblock__top span{font-size:var(--ft-label);letter-spacing:.1em;
  text-transform:uppercase;color:var(--muted)}
[data-view="budget"] .roomblock__top b{font-family:var(--display);font-weight:400;font-size:1.25rem;
  line-height:1.2;color:var(--ink)}
[data-view="budget"] .roomblock[data-over="true"] .roomblock__top b{color:var(--bad)}
[data-view="budget"] .roomblock[data-over="true"] .bar i{background:var(--bad)}
/* contract terms are reference data: a key/value list, not a middot run-on */
[data-view="budget"] .terms{margin:.2rem 0 0;display:grid;gap:.15rem}
[data-view="budget"] .terms > div{display:flex;align-items:baseline;gap:var(--s2);
  font-size:var(--ft-meta);line-height:1.35}
[data-view="budget"] .terms dt{flex:0 0 auto;color:var(--muted)}
[data-view="budget"] .terms dd{margin:0;display:flex;align-items:baseline;gap:.4rem;
  min-width:0;color:var(--ink);font-variant-numeric:tabular-nums}
[data-view="budget"] .terms dd em{font-style:normal;color:var(--muted)}
[data-view="budget"] .terms dd em::before{content:"— "}
[data-view="budget"] .terms > div[data-kind="bad"] dd{color:var(--bad)}

/* ── tables, shared between the two blocks ───────────────────────────────── */

/* the table scrolls; the document never does */
[data-view="budget"] .tablewrap{overscroll-behavior-x:contain}
[data-view="budget"] .tablewrap:focus-visible{outline:2px solid var(--terracotta);
  outline-offset:-2px}
/* Not sticky. `.tablewrap{overflow-x:auto}` computes overflow-y:auto, so the
   wrapper was the scroll container for the <thead> and never scrolled
   vertically, so sticky bought nothing and painted over a body row. Fixed
   centrally: .tablewrap is only a scroll container when the table overflows,
   so the page owns the sticky header again and this override is gone. */
[data-view="budget"] .dt th i{font-style:normal;font-weight:400;text-transform:none;
  letter-spacing:0;color:var(--muted)}
/* these rows are not clickable — the shared .dt hand cursor would lie */
[data-view="budget"] .dt tbody tr{cursor:auto}
[data-view="budget"] .dt tfoot td,
[data-view="budget"] .dt tfoot th{background:var(--surface-2);border-top:1px solid var(--line-strong);
  border-bottom:0;height:var(--row-dense);padding:.45rem .75rem;text-align:left}
[data-view="budget"] .dt tfoot .num{text-align:right}

/* the working column: the reason this page is trustworthy. It is never
   truncated, never nowrap, and never squeezed below a readable measure. */
[data-view="budget"] .c-working{white-space:normal}
[data-view="budget"] .c-working .working{display:inline;line-height:1.45;
  overflow-wrap:break-word}
[data-view="budget"] .assumed{display:inline-block;line-height:1.35;
  border:1px solid rgba(201,162,39,.5);border-radius:2px;padding:0 .35rem;
  background:#FDFAF0;margin:.1rem .25rem .1rem 0}
/* a state, not a control: no box, no fill — those read as a button */
[data-view="budget"] .flag{font-size:var(--ft-label);letter-spacing:.08em;
  text-transform:uppercase;font-weight:700;color:var(--bad)}

[data-view="budget"] .rooms{table-layout:auto}
[data-view="budget"] .rooms .c-party{min-width:11rem}
[data-view="budget"] .rooms .c-party b{font-family:var(--display);font-weight:400;
  font-size:var(--ft-name);line-height:1.2}
[data-view="budget"] .rooms .c-people,
[data-view="budget"] .rooms .c-rooms,
[data-view="budget"] .rooms .c-nights{width:1%;white-space:nowrap;color:var(--muted)}
[data-view="budget"] .rooms .c-people i{font-style:normal;color:var(--muted)}
/* 17rem is the narrowest the arithmetic stays readable at, and it is exactly
   what lets the rooms table fit a 1024px window without a scrollbar */
[data-view="budget"] .rooms .c-working{min-width:17rem}
[data-view="budget"] .rooms .c-cost{width:1%;white-space:nowrap}
[data-view="budget"] .rooms td.c-cost{font-size:var(--ft-name);font-family:var(--display);
  font-weight:400}
[data-view="budget"] .rooms tr[data-priced="false"] .c-party b{color:var(--muted)}
[data-view="budget"] .rooms tfoot .c-cost b{font-family:var(--display);font-weight:400;
  font-size:var(--ft-name)}

/* ── 3. the ledger ───────────────────────────────────────────────────────── */

/* wireRecords needs `.rec` on the row; planner.css styles `.rec` as a wrapping
   flex form, which would destroy a table row. Put it back to a table row. */
[data-view="budget"] .ledger tr.rec{display:table-row;padding:0;gap:0;
  flex-wrap:nowrap;align-items:stretch;border-bottom:0}

/* Nine columns need 56rem before the money starts getting clipped. Below that
   the wrapper scrolls — squeezing "12000" down to "120(" is not a layout. */
[data-view="budget"] .ledger{table-layout:fixed;width:100%;min-width:56rem}
[data-view="budget"] .ledger td{padding:.2rem .5rem;height:var(--row-dense)}
[data-view="budget"] .ledger th{padding:.5rem}
/* Percentages sum to ~71%; Paid + Due + delete take the remaining ~284px.
   Notes is declared, not left to `auto` — auto gets whatever is left over,
   which at 1280 was 56px and clipped every note to two characters. */
[data-view="budget"] .ledger .c-line{width:20%;min-width:11rem}
[data-view="budget"] .ledger .c-cat{width:10%;min-width:7.5rem}
[data-view="budget"] .ledger .c-vendor{width:13%;min-width:8rem}
[data-view="budget"] .ledger .c-est,
[data-view="budget"] .ledger .c-act{width:8%;min-width:6.5rem}
/* centred, so a column of ticks reads as one and the box stops crowding the
   right-aligned Actual figure sitting immediately to its left */
[data-view="budget"] .ledger .c-paid{width:5.5rem;text-align:center}
[data-view="budget"] .ledger .c-due{width:9.5rem}
[data-view="budget"] .ledger .c-notes{width:12%;min-width:8rem}
[data-view="budget"] .ledger .c-del{width:2.75rem;text-align:right}

/* category band: its subtotal sits directly above the lines it totals */
[data-view="budget"] .ledger tr.grp th,
[data-view="budget"] .ledger tr.grp td{position:static;background:var(--sand);
  border-bottom:1px solid var(--line-strong);height:auto;padding:.35rem .5rem;
  font-size:var(--ft-meta);color:var(--ink);text-transform:none;letter-spacing:0}
[data-view="budget"] .ledger tr.grp th{font-family:var(--display);font-weight:400;
  font-size:var(--ft-body);text-align:left}
[data-view="budget"] .ledger tr.grp th em{font-style:normal;font-family:var(--ui);
  font-size:var(--ft-label);letter-spacing:.1em;text-transform:uppercase;color:var(--muted);
  margin-left:.5rem}
[data-view="budget"] .ledger tr.grp .money{font-weight:700}
[data-view="budget"] .ledger tr.grp .c-est{color:var(--muted);font-weight:400}

/* Controls are quiet until touched — a resting ledger reads as data, not as a
   form. planner.css already does most of this for `.dt td input/select`; here
   it only has to fill the cell and right-align the money. */
/* `tr.rec` is load-bearing specificity, not decoration: planner.css's
   `.dt tbody tr:not(.detail) td input:not([type=checkbox])` sets
   `width:auto;min-width:5rem`, which scores (0,3,4) and beats a selector
   without it — leaving each input at its intrinsic ~167px and painting the
   Estimate and Actual figures on top of the next column. */
[data-view="budget"] .ledger tr.rec td input:not([type="checkbox"]),
[data-view="budget"] .ledger tr.rec td select{width:100%;min-width:0}
[data-view="budget"] .ledger td input[type="number"]{text-align:right;
  font-variant-numeric:tabular-nums;-moz-appearance:textfield}
[data-view="budget"] .ledger td input[type="number"]::-webkit-outer-spin-button,
[data-view="budget"] .ledger td input[type="number"]::-webkit-inner-spin-button{
  -webkit-appearance:none;margin:0}
/* an estimate is a guess and reads like one; a committed actual is the fact */
[data-view="budget"] .ledger td.c-est input{color:var(--muted)}
[data-view="budget"] .ledger td.c-act input{color:var(--ink);font-weight:700}
[data-view="budget"] .ledger td.c-act[data-vs="over"] input{color:var(--bad)}
[data-view="budget"] .ledger td.c-act[data-vs="under"] input{color:var(--good)}
[data-view="budget"] .ledger td.c-act[data-vs="over"]{box-shadow:inset 2px 0 0 var(--bad-line)}
[data-view="budget"] .ledger td.c-act[data-vs="under"]{box-shadow:inset 2px 0 0 var(--good-line)}

/* planner.css sizes every control in a .dt row to --h-ctl × min 5rem, which
   turns a checkbox into a 44×80 slab on a phone. It is a checkbox: 18px box,
   with the wrapping <label> providing the touch target. */
[data-view="budget"] .ledger td input[type="checkbox"]{width:1.125rem;height:1.125rem;
  min-width:0;flex:none}
[data-view="budget"] .paidbox{display:inline-flex;align-items:center;gap:.35rem;
  min-height:var(--h-ctl);padding:0 .2rem;cursor:pointer;font-size:var(--ft-meta);
  color:var(--muted)}
[data-view="budget"] .paidbox span{display:none}
/* The placeholders are the card layout's field labels. While the <thead> is
   doing that job they would just read as values in a borderless cell. */
[data-view="budget"] .ledger td input::placeholder{color:transparent}
[data-view="budget"] .ledger tr.rec[data-paid="true"] .c-line input{color:var(--muted)}

[data-view="budget"] .ledger .x{margin:0;padding:.25rem .4rem}
[data-view="budget"] .ledger tfoot th{font-family:var(--ui);font-size:var(--ft-label);
  letter-spacing:.1em;text-transform:uppercase;color:var(--muted);font-weight:700}
[data-view="budget"] .footnote{font-size:var(--ft-meta);color:var(--muted);
  font-variant-numeric:tabular-nums}
[data-view="budget"] .footnote b[data-kind="bad"]{color:var(--bad)}
[data-view="budget"] .footnote b[data-kind="good"]{color:var(--good)}

/* ── ≤1439: the ledger scrolls, so the line name is pinned ───────────────── */
@media (min-width:768px) and (max-width:1439px){
  [data-view="budget"] .ledger .c-line{position:sticky;left:0;z-index:1;
    background:var(--surface);box-shadow:1px 0 0 var(--line)}
  [data-view="budget"] .ledger thead .c-line{z-index:4;background:var(--sand)}
  [data-view="budget"] .ledger tr.grp .c-line,
  [data-view="budget"] .ledger tfoot .c-line{z-index:2;background:var(--sand)}
  [data-view="budget"] .ledger tfoot .c-line{background:var(--surface-2)}
}

/* ── ≤1023: the rooms table becomes one card per party ───────────────────── */
@media (max-width:1023px){
  [data-view="budget"] .roomsum{grid-template-columns:minmax(0,1fr)}
  [data-view="budget"] .unit{display:inline}

  [data-view="budget"] .rooms,
  [data-view="budget"] .rooms thead,
  [data-view="budget"] .rooms tbody,
  [data-view="budget"] .rooms tfoot,
  [data-view="budget"] .rooms tr,
  [data-view="budget"] .rooms td,
  [data-view="budget"] .rooms th{display:block}
  [data-view="budget"] .rooms thead{position:absolute;width:1px;height:1px;overflow:hidden;
    clip-path:inset(50%)}
  [data-view="budget"] .rooms tr{display:flex;flex-wrap:wrap;align-items:baseline;
    gap:0 .55rem;padding:var(--s3) var(--s5);border-bottom:1px solid var(--line)}
  [data-view="budget"] .rooms tbody tr:last-child{border-bottom:0}
  [data-view="budget"] .rooms td,
  [data-view="budget"] .rooms tfoot td{height:auto;padding:0;border:0;width:auto;
    background:none}
  /* the name claims enough of line 1 that the meta run always wraps below it —
     otherwise a short name lets "3 rooms · 4 nights" ride up beside the money
     and no two rows align */
  [data-view="budget"] .rooms .c-party{order:1;flex:1 1 auto;min-width:calc(100% - 5.5rem)}
  /* width:1% is a table-layout trick; as a flex item it becomes flex-basis:1% */
  [data-view="budget"] .rooms .c-cost{order:2;flex:0 0 auto;width:auto;margin-left:auto;
    text-align:right}
  [data-view="budget"] .rooms .c-resort{order:3}
  [data-view="budget"] .rooms .c-people{order:4}
  [data-view="budget"] .rooms .c-rooms{order:5}
  [data-view="budget"] .rooms .c-nights{order:6}
  /* the meta run gets its separators from CSS, so the markup stays a table */
  [data-view="budget"] .rooms .c-resort,
  [data-view="budget"] .rooms .c-people,
  [data-view="budget"] .rooms .c-rooms,
  [data-view="budget"] .rooms .c-nights{font-size:var(--ft-meta);color:var(--muted);
    text-align:left;width:auto}
  [data-view="budget"] .rooms tbody .c-rooms::before,
  [data-view="budget"] .rooms tbody .c-nights::before{content:"· ";color:var(--muted)}
  /* the working gets what it always needed: a line of its own, full width */
  [data-view="budget"] .rooms .c-working{order:7;flex:1 0 100%;margin-top:.3rem;
    min-width:0;white-space:normal}
  [data-view="budget"] .rooms tfoot tr{background:var(--surface-2);
    border-top:1px solid var(--line-strong)}
  [data-view="budget"] .rooms tfoot td:empty{display:none}
}

/* ── ≤767: the ledger becomes one card per line ──────────────────────────── */
@media (max-width:767px){
  [data-view="budget"] .moneyband{grid-template-columns:repeat(2,minmax(0,1fr))}
  [data-view="budget"] .moneyband .stat b{font-size:1.35rem}
  [data-view="budget"] .panel__head .tools{margin-left:0;width:100%;align-items:center}
  [data-view="budget"] .headfig{text-align:left;margin-right:auto}

  [data-view="budget"] .ledger,
  [data-view="budget"] .ledger thead,
  [data-view="budget"] .ledger tbody,
  [data-view="budget"] .ledger tfoot,
  [data-view="budget"] .ledger tr,
  [data-view="budget"] .ledger td,
  [data-view="budget"] .ledger th{display:block;width:auto}
  [data-view="budget"] .ledger thead{position:absolute;width:1px;height:1px;overflow:hidden;
    clip-path:inset(50%)}
  [data-view="budget"] .ledger{table-layout:auto;min-width:0}

  /* not sticky: a sticky <tr> that is also a flex container renders 1 topbar
     height below its own flow box in Chrome and lands on top of the first card */
  [data-view="budget"] .ledger tr.grp{
    display:flex;flex-wrap:nowrap;align-items:baseline;gap:0 var(--s3);
    padding:.4rem var(--s4);background:var(--sand);
    border-block:1px solid var(--line-strong)}
  [data-view="budget"] .ledger tr.grp th,
  [data-view="budget"] .ledger tr.grp td{padding:0;border:0;background:none}
  [data-view="budget"] .ledger tr.grp th{flex:1 1 auto;min-width:0;overflow:hidden;
    text-overflow:ellipsis;white-space:nowrap}
  /* the two subtotals earn the width here; the line count does not */
  [data-view="budget"] .ledger tr.grp th em{display:none}
  [data-view="budget"] .ledger tr.grp .c-est{flex:0 0 auto;margin-left:auto}
  [data-view="budget"] .ledger tr.grp .c-est::before{content:"est ";color:var(--muted)}
  [data-view="budget"] .ledger tr.grp .c-act{flex:0 0 auto}
  [data-view="budget"] .ledger tr.grp .c-paid,
  [data-view="budget"] .ledger tr.grp .c-due,
  [data-view="budget"] .ledger tr.grp .c-notes,
  [data-view="budget"] .ledger tr.grp .c-del{display:none}

  [data-view="budget"] .ledger tr.rec{display:grid;
    grid-template-columns:repeat(6,minmax(0,1fr));gap:var(--s2);
    padding:var(--s3) var(--s4);border-bottom:1px solid var(--line);align-items:end}
  /* the desktop column widths are grid-item widths here, and would win */
  [data-view="budget"] .ledger tr.rec td{height:auto;padding:0;border:0;
    width:auto;min-width:0}
  /* the row is placed explicitly: the delete button is last in the DOM, and
     sparse auto-placement would otherwise drop it onto a fifth line */
  [data-view="budget"] .ledger tr.rec .c-line{grid-row:1;grid-column:1/6}
  [data-view="budget"] .ledger tr.rec .c-del{grid-row:1;grid-column:6/-1;text-align:right}
  [data-view="budget"] .ledger tr.rec .c-cat{grid-row:2;grid-column:1/4}
  [data-view="budget"] .ledger tr.rec .c-vendor{grid-row:2;grid-column:4/-1}
  [data-view="budget"] .ledger tr.rec .c-est{grid-row:3;grid-column:1/3}
  [data-view="budget"] .ledger tr.rec .c-act{grid-row:3;grid-column:3/5}
  [data-view="budget"] .ledger tr.rec .c-paid{grid-row:3;grid-column:5/-1}
  [data-view="budget"] .ledger tr.rec .c-due{grid-row:4;grid-column:1/4}
  [data-view="budget"] .ledger tr.rec .c-notes{grid-row:4;grid-column:4/-1}

  /* bare numbers side by side need their names back */
  [data-view="budget"] .ledger tr.rec td[data-label]::before{content:attr(data-label);
    display:block;font-size:var(--ft-label);letter-spacing:.1em;text-transform:uppercase;
    color:var(--muted);margin-bottom:.15rem}
  /* except Paid, whose control already says so */
  [data-view="budget"] .ledger tr.rec td.c-paid::before{content:none}
  /* on a phone a control has to look like one, and be 44px. background-color,
     not background — the shared select rule draws its arrow with a gradient */
  [data-view="budget"] .ledger tr.rec input:not([type="checkbox"]),
  [data-view="budget"] .ledger tr.rec select{height:var(--h-ctl);font-size:var(--ft-body);
    border-color:var(--line-strong);background-color:#fff}
  [data-view="budget"] .ledger tr.rec .c-line input,
  [data-view="budget"] .ledger tr.rec .c-act input{font-size:1rem}
  [data-view="budget"] .ledger td input::placeholder{color:var(--muted)}
  [data-view="budget"] .ledger tr.rec .c-act[data-vs]{box-shadow:none}
  [data-view="budget"] .paidbox{display:flex;min-height:var(--h-ctl);width:100%;
    justify-content:flex-start;border:1px solid var(--line-strong);background:#fff;
    border-radius:2px;padding:0 .5rem;color:var(--ink);font-size:var(--ft-body)}
  [data-view="budget"] .paidbox span{display:inline;min-width:0;overflow:hidden;
    text-overflow:ellipsis;white-space:nowrap}
  [data-view="budget"] .ledger .x{min-width:var(--h-ctl);min-height:var(--h-ctl);
    border:1px solid var(--line);border-radius:2px}
  [data-view="budget"] .ledger tfoot tr{display:flex;flex-wrap:wrap;align-items:baseline;
    gap:.2rem var(--s3);padding:var(--s3) var(--s4);background:var(--surface-2);
    border-top:1px solid var(--line-strong)}
  [data-view="budget"] .ledger tfoot th,
  [data-view="budget"] .ledger tfoot td{padding:0;border:0;background:none;height:auto}
  [data-view="budget"] .ledger tfoot .c-line{flex:0 0 auto}
  [data-view="budget"] .ledger tfoot .c-est::before{content:"est ";color:var(--muted)}
  [data-view="budget"] .ledger tfoot .c-paid{flex:1 0 100%}
}

/* ── ≤639: panels run edge to edge; every control is a touch target ──────── */
@media (max-width:639px){
  [data-view="budget"] .panel{margin-inline:calc(var(--gutter) * -1);
    border-inline:0;border-radius:0}
  [data-view="budget"] .panel__head,
  [data-view="budget"] .roomsum,
  [data-view="budget"] .rooms tr,
  [data-view="budget"] .ledger tr.grp,
  [data-view="budget"] .ledger tr.rec,
  [data-view="budget"] .ledger tfoot tr{padding-inline:var(--gutter)}
  [data-view="budget"] .moneyband{grid-template-columns:repeat(2,minmax(0,1fr))}
  [data-view="budget"] .moneyband .stat{padding:var(--s3)}
  [data-view="budget"] .moneyband .stat b{font-size:1.25rem}
  [data-view="budget"] .roomsum__nights{gap:var(--s4)}
  /* --h-ctl is already 44px here; give the row grid room for it */
  [data-view="budget"] .ledger tr.rec{row-gap:var(--s3)}
}

@media print{
  [data-view="budget"] .ledger .c-del{display:none}
  [data-view="budget"] .dt th{position:static}
}
