/* VP Landscape app surfaces — Sonoran palette (§10a), shared by portal/admin/field/pay */
:root {
  --green: #1e3a2f; --clay: #b4552d; --clay-dark: #93441f;
  --canvas: #faf7f2; --surface: #f0eae0; --ink: #14181a; --muted: #7d9384;
  --ink-soft: #4b5450; --ok: #2e7d4f; --warn: #b48a2d; --bad: #a63d2f;
  --radius: 10px; --shadow: 0 1px 2px rgb(20 24 26 / .06), 0 4px 14px rgb(20 24 26 / .08);
}
* { box-sizing: border-box; }
html { font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif; }
body { margin: 0; background: var(--canvas); color: var(--ink); line-height: 1.55; font-size: 16px; }
h1, h2, h3 { color: var(--green); line-height: 1.15; margin: 0 0 .5em; }
h1 { font-size: 1.7rem; } h2 { font-size: 1.25rem; } h3 { font-size: 1.05rem; }
a { color: var(--clay-dark); }
.app-main { max-width: 64rem; margin: 0 auto; padding: 1.25rem; }
.surface-field .app-main, .surface-portal .app-main { max-width: 34rem; }

.staging-banner {
  background: #7c3aed; color: #fff; text-align: center; font-weight: 700;
  padding: .4rem; font-size: .85rem; position: sticky; top: 0; z-index: 200;
}

.topnav { background: var(--green); color: #fff; padding: .5rem 1rem;
  display: flex; gap: .4rem; align-items: center; flex-wrap: wrap; }
.topnav .brand { font-weight: 800; color: #fff; text-decoration: none; margin-right: .6rem; }
/* .6rem vertical padding puts these at ~44px — thumb-sized, same rule the
   field app follows. They were ~34px, on the nav phone clients use most. */
.topnav a { color: #dfe8e2; text-decoration: none; padding: .6rem .6rem; border-radius: 6px; font-size: .95rem; }
.topnav a:hover, .topnav a.active { background: rgb(255 255 255 / .12); color: #fff; }
.topnav .spacer { flex: 1; }
.topnav-scroll { display: flex; gap: .4rem; align-items: center; flex: 1; min-width: 0; }

.card { background: #fff; border-radius: var(--radius); box-shadow: var(--shadow);
  padding: 1.1rem 1.25rem; margin-bottom: 1rem; }
.card h2:first-child, .card h3:first-child { margin-top: 0; }
.muted { color: var(--ink-soft); font-size: .92rem; }
.pill { display: inline-block; padding: .1rem .55rem; border-radius: 99px; font-size: .8rem;
  font-weight: 600; background: var(--surface); color: var(--ink-soft); }
.pill.ok { background: #e2f0e7; color: var(--ok); }
.pill.warn { background: #f6ecd7; color: var(--warn); }
.pill.bad { background: #f6ded8; color: var(--bad); }
.pill.info { background: #e3e9f2; color: #3d5a80; }

.btn { display: inline-block; padding: .65rem 1.1rem; border-radius: var(--radius); border: 2px solid transparent;
  background: var(--clay); color: #fff; font-weight: 700; font-size: 1rem; cursor: pointer; text-decoration: none; text-align: center; }
.btn:hover { background: #c4643a; }
.btn.secondary { background: transparent; border-color: var(--green); color: var(--green); }
.btn.secondary:hover { background: var(--green); color: #fff; }
.btn.subtle { background: var(--surface); color: var(--ink); font-weight: 600; }
.btn.danger { background: var(--bad); }
.btn.big { width: 100%; padding: 1rem; font-size: 1.15rem; }
.btn:disabled { opacity: .5; cursor: default; }
.btn-row { display: flex; gap: .6rem; flex-wrap: wrap; margin: .75rem 0; }
.btn-row .btn { flex: 1; min-width: 8rem; }

label { display: block; font-weight: 600; font-size: .92rem; margin: .8rem 0 .25rem; }
/* font-size is pinned to 16px, not inherited: a select inside a .93rem table
   inherits ~14.9px, and anything under 16px makes iOS zoom the page on tap. */
input, select, textarea { width: 100%; max-width: 100%; min-width: 0; padding: .6rem .7rem; border: 1px solid #cfc8ba; border-radius: 8px;
  font: inherit; font-size: 16px; background: #fff; }
input[type="date"] { display: block; -webkit-appearance: none; appearance: none; color: var(--ink); }
input[type="date"]::-webkit-date-and-time-value { color: var(--ink); }
input:focus, select:focus, textarea:focus { outline: 2px solid var(--green); border-color: var(--green); }
.field-note { font-size: .82rem; color: var(--ink-soft); margin-top: .25rem; }
.error-box { background: #f6ded8; border: 1px solid var(--bad); color: #6d2a1f; padding: .7rem 1rem; border-radius: 8px; margin: .75rem 0; }
.ok-box { background: #e2f0e7; border: 1px solid var(--ok); color: #1d5236; padding: .7rem 1rem; border-radius: 8px; margin: .75rem 0; }

table.data { width: 100%; border-collapse: collapse; font-size: .93rem; background: #fff;
  border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow); }
table.data th { background: var(--surface); text-align: left; padding: .55rem .7rem; font-size: .82rem;
  text-transform: uppercase; letter-spacing: .03em; color: var(--ink-soft); }
table.data td { padding: .55rem .7rem; border-top: 1px solid #eee7db; vertical-align: top; }
table.data tr:hover td { background: #faf7f0; }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }

.feed-item { display: flex; gap: .7rem; padding: .55rem 0; border-bottom: 1px solid #eee7db; font-size: .95rem; }
.feed-item .when { color: var(--ink-soft); font-size: .82rem; white-space: nowrap; min-width: 7.5rem; }
.feed-item .cat { min-width: 1.4rem; text-align: center; }

/* Field app — thumb-sized targets (§15.2) */
.surface-field .visit-header { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: .5rem; margin-bottom: .75rem; }
.surface-field .visit-header a { padding: .9rem .25rem; text-align: center; background: var(--green); color: #fff;
  border-radius: var(--radius); text-decoration: none; font-weight: 700; font-size: 1rem; }
/* No phone on file: visibly inert, not a green button that does nothing. */
.surface-field .visit-header .dead { padding: .9rem .25rem; text-align: center; background: var(--surface);
  color: var(--muted); border-radius: var(--radius); font-weight: 700; font-size: 1rem; }
.onmyway { display: block; width: 100%; padding: 1rem; margin: .5rem 0; background: var(--clay); color: #fff;
  border-radius: var(--radius); text-align: center; font-weight: 800; font-size: 1.1rem; text-decoration: none; }
.gate-code { font-size: 1.6rem; font-weight: 800; color: var(--clay-dark); letter-spacing: .1em; }
.offline-note { display: none; background: #f6ecd7; color: #6d5312; padding: .5rem .8rem; border-radius: 8px;
  font-weight: 600; margin-bottom: .6rem; }
body.is-offline .offline-note { display: block; }

/* Expense preset buttons (§23.1: built for standing at a gas pump) */
.preset-grid { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: .55rem; margin: .75rem 0; }
.preset-grid button { padding: 1rem .3rem; font-size: .95rem; font-weight: 700; background: #fff;
  border: 2px solid var(--surface); border-radius: var(--radius); cursor: pointer; }
.preset-grid button.selected { border-color: var(--clay); background: #fbeee6; }
.amount-input { font-size: 2rem; text-align: center; font-weight: 800; padding: .8rem; }

.day-stop { display: flex; gap: .75rem; align-items: center; padding: .7rem 0; border-bottom: 1px solid #eee7db; }
.day-stop .pos { background: var(--green); color: #fff; min-width: 2rem; height: 2rem; border-radius: 50%;
  display: flex; align-items: center; justify-content: center; font-weight: 800; }
.day-stop .body { flex: 1; } .day-stop a { text-decoration: none; }

.kpi-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); gap: .75rem; margin-bottom: 1rem; }
.kpi { background: #fff; border-radius: var(--radius); box-shadow: var(--shadow); padding: .8rem 1rem; }
.kpi .v { font-size: 1.5rem; font-weight: 800; color: var(--green); font-variant-numeric: tabular-nums; }
.kpi .l { font-size: .8rem; color: var(--ink-soft); text-transform: uppercase; letter-spacing: .03em; }

.locked { background: #f4f1ea !important; color: #8a857a !important; }
@media (max-width: 40rem) { .app-main { padding: .8rem; } h1 { font-size: 1.35rem; } }

/* Installed to the home screen (§15.4): there is no browser chrome left, so
   the page itself has to clear the status bar at the top and the home
   indicator at the bottom. Whichever bar comes first gets the top inset. */
/* Hidden by default; the standalone block below turns it on. Declared BEFORE
   that block on purpose — same specificity, so source order decides. */
.pdf-download-note { display: none; }

@media (display-mode: standalone) {
  .staging-banner { padding-top: calc(.4rem + env(safe-area-inset-top)); }
  body:not(.is-staging) > .topnav:first-child { padding-top: calc(.5rem + env(safe-area-inset-top)); }
  body:not(.is-staging) > .app-main:first-child { padding-top: calc(1.25rem + env(safe-area-inset-top)); }
  .app-main { padding-bottom: calc(1.25rem + env(safe-area-inset-bottom)); }

  /* The invoice PDF is a one-way door here and there is no fixing it from
     this side. The URL sits inside the manifest scope, so iOS opens it in
     this webview, which has no chrome; it ignores Content-Disposition and
     renders the PDF anyway; and target="_blank" is not honoured for in-scope
     URLs. Every exit belongs to the OS and none of them are offered. So the
     link is not shown here — only in a real browser, where Back exists. */
  .pdf-download { display: none; }
  .pdf-download-note { display: block; }
}

/* Field navigation (§15.2): every screen below the day list has a way back out,
   and finishing a stop hands off to the next one. Big targets — this is used
   one-handed, standing in a yard, in the sun. */
.field-topbar { display: flex; align-items: center; justify-content: space-between;
  gap: .75rem; margin-bottom: .6rem; }
.field-topbar .back { display: inline-block; padding: .55rem .9rem .55rem .6rem;
  background: var(--surface); border-radius: 99px; color: var(--green);
  font-weight: 700; text-decoration: none; font-size: 1rem; }
.field-topbar .muted { font-size: .9rem; white-space: nowrap; }

.day-progress { margin: -.35rem 0 .6rem; color: var(--ink-soft); }

/* Day navigation and the two side errands. These were inline text links —
   roughly 20px of tappable height, which is well under the 44px a thumb can
   hit reliably, and they sat close enough together to catch the wrong one.
   Buttons instead: arrows keep a fixed width, the two named actions share
   whatever is left and wrap to their own row on a phone. Kept `subtle` so
   they do not compete with the On-my-way call to action below them. */
.day-nav { display: flex; flex-wrap: wrap; gap: .5rem; margin: .5rem 0 .9rem; }
.day-nav .btn { min-height: 3rem; display: inline-flex; align-items: center; justify-content: center; }
.day-nav .btn:not(.day-nav-arrow) { flex: 1 1 8rem; }
.day-nav .day-nav-arrow { flex: 0 0 3.75rem; font-size: 1.35rem; line-height: 1; padding: .65rem .5rem; }

/* The whole stop row is the tap target, not just the words. */
a.day-stop { display: flex; gap: .75rem; align-items: center; padding: .85rem .2rem;
  border-bottom: 1px solid #eee7db; color: inherit; text-decoration: none; }
a.day-stop .body { flex: 1; display: block; }
a.day-stop .body strong { display: block; font-size: 1.05rem; }
a.day-stop .body .muted { display: block; }
a.day-stop .chev { color: var(--muted); font-size: 1.6rem; line-height: 1; }
a.day-stop.is-finished .body { opacity: .55; }
a.day-stop.is-finished .pos { background: var(--ok); }

.btn.block { display: block; width: 100%; text-align: center; margin: .5rem 0; }
.onmyway.next-stop { background: var(--green); }
.field-nav { display: flex; justify-content: space-between; gap: .6rem; margin: 1.25rem 0 .5rem; }
.field-nav .btn { flex: 1; text-align: center; }

/* Queued work that could not be sent — loud on purpose. Silence here means
   he believes the office knows something it does not (§15.4). */
.outbox-banner { background: #f6ded8; border: 2px solid var(--bad); color: #5d1c13;
  border-radius: var(--radius); padding: .8rem .9rem; margin-bottom: .8rem; font-weight: 600; }
.outbox-banner .btn-row { margin-bottom: 0; }

/* ==========================================================================
   Responsive behaviour — phone, tablet, desktop
   ========================================================================== */

/* Nothing should push the page itself sideways. Wide content (data tables,
   most often) scrolls inside its own card instead of stretching the document
   and leaving every other section short of the right edge. */
.card { overflow-x: auto; }

/* Prose content wraps instead of scrolling its card sideways: one long pasted
   URL or gate instruction in a note used to put a horizontal scrollbar on the
   whole card. Tables keep their own rules above. */
.card p, .card li, .day-stop .body, .feed-item { overflow-wrap: anywhere; }

/* Squeezing eight columns into a phone makes every cell wrap to three lines,
   which is harder to read than a sideways scroll. Below this width the card
   above takes over and scrolls.

   Only for genuinely wide tables — four columns or more. A two-column
   label/amount table like the P&L has room on any phone, and forcing a floor
   on it pushed the amounts (the entire point of the table) off the right edge
   and made the reader scroll to see a number that had been fitting fine.

   A table can opt out with `.fit` when its wide column is prose that can wrap
   instead. The `:not(.fit)` here is load-bearing, not decoration:
   `:has(th:nth-child(4))` outscores a plain `table.data.fit`, so an opt-out
   written as its own rule silently loses and the floor stays on. Excluding it
   in this selector settles it by specificity rather than by source order. */
table.data:not(.fit):has(th:nth-child(4)) { min-width: 32rem; }

/* Money never wraps: "$130.00" split across two lines is unreadable, and the
   column is only as wide as the longest figure anyway. */
td.num, th.num { white-space: nowrap; }

/* `anywhere` rather than `break-word`, because only `anywhere` lowers the
   column's min-content width — which is what decides whether the table fits
   at all. Without it a single long word holds the whole table open. */
table.data.fit td:first-child, table.data.fit th:first-child { overflow-wrap: anywhere; }

.invoice-list-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  gap: .8rem;
  align-items: center;
  border-bottom: 0;
}

.invoice-summary-link {
  display: grid;
  gap: .25rem;
  color: inherit;
  text-decoration: none;
}

.invoice-summary-link strong {
  font-size: 1.05rem;
}

.invoice-summary-link:hover strong {
  text-decoration: underline;
}

.invoice-actions {
  display: flex;
  gap: .5rem;
  align-items: center;
}

.invoice-actions .btn {
  flex: 0 0 auto;
  min-width: 5.25rem;
  text-align: center;
}

.invoice-lines {
  display: grid;
  gap: .35rem;
  margin-bottom: .85rem;
}

.invoice-line {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: .75rem;
  align-items: start;
  padding: .65rem 0;
  border-bottom: 1px solid #eee7db;
}

.invoice-line > :first-child {
  overflow-wrap: anywhere;
}

.invoice-line > strong {
  color: var(--green);
  font-variant-numeric: tabular-nums;
  text-align: right;
  white-space: nowrap;
}

.invoice-total {
  font-size: 1.05rem;
}

.invoice-open {
  margin-top: .15rem;
  padding: .75rem .85rem;
  border-bottom: 0;
  border-radius: var(--radius);
  background: #f6ecd7;
}

.payment-breakdown {
  display: grid;
  gap: .35rem;
  margin: 1rem 0 0;
  padding: .8rem .9rem;
  border: 1px solid #eadfce;
  border-radius: var(--radius);
  background: var(--surface);
}

.payment-breakdown > div {
  display: flex;
  justify-content: space-between;
  gap: .75rem;
  align-items: baseline;
}

.payment-breakdown span {
  color: var(--ink-soft);
}

.payment-breakdown strong {
  color: var(--green);
  font-variant-numeric: tabular-nums;
  text-align: right;
  white-space: nowrap;
}

.payment-card-total {
  margin-top: .25rem;
  padding-top: .45rem;
  border-top: 1px solid #eadfce;
  font-weight: 700;
}

@media (max-width: 40rem) {
  /* On a phone the cell padding is competing with the figures for room. */
  table.data th, table.data td { padding-left: .5rem; padding-right: .5rem; }
  .card { padding-left: .9rem; padding-right: .9rem; }
  .invoice-list-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: .7rem;
  }
  .invoice-actions {
    grid-column: 1 / -1;
    width: 100%;
  }
  .invoice-actions .btn {
    flex: 1 1 0;
    width: 100%;
  }
  .invoice-line {
    grid-template-columns: 1fr;
    gap: .2rem;
  }
  .invoice-line > strong {
    text-align: left;
  }
  .payment-breakdown > div {
    align-items: flex-start;
  }
}

/* Rows that pair a description with a small form — confirm a payment, move a
   visit, mark an invoice paid. The form is a flex ITEM here, so without an
   explicit basis its inline children overflow the row and print on top of the
   neighbouring text. */
/* "Ask for a different day", inside a visit row. It sits INSIDE .body rather
   than beside it: .day-stop is a flex row and .body has flex:1 (basis 0), so a
   sibling form carrying a label, an input, a hint and a button shrank the date
   and service down to a three-line sliver. A form belongs under the thing it
   is about, not next to it. */
.ask-day { margin-top: .55rem; }
.ask-day label { font-size: .85rem; font-weight: 600; margin: 0 0 .3rem; }
.ask-day .row-form { gap: .5rem; }
.ask-day input[type="date"] { flex: 0 1 10rem; }
.ask-day .field-note { margin: .3rem 0 0; }

/* The three close-out buttons sit under the move box, not beside it: they are
   a different decision from rescheduling and must not be mis-tapped for one. */
.close-out { margin-top: .4rem; }
.close-out .btn { flex: 0 1 auto; }

/* Run-order arrows. Stacked and narrow so they take a column rather than a
   row, and tall enough to hit with a thumb in the truck. */
.reorder { display: flex; flex-direction: column; gap: .25rem; flex: 0 0 auto; }
.reorder .btn { min-height: 2.6rem; width: 3rem; padding: .2rem; font-size: 1rem; line-height: 1; }

/* The field day row: the stop itself takes the width, the arrows sit beside
   it. The anchor cannot contain them — a form inside a link is invalid. */
.day-stop-row { display: flex; align-items: center; gap: .5rem; }
.day-stop-row .day-stop { flex: 1; min-width: 0; border-bottom: none; }
.day-stop-row { border-bottom: 1px solid #eee7db; }

.row-form { display: flex; flex-wrap: wrap; gap: .4rem; align-items: center; }
.row-form input, .row-form select { width: auto; min-width: 0; flex: 0 1 auto; }
.row-form .btn { flex: 0 0 auto; }
.row-form label { margin: 0; display: inline-flex; align-items: center; gap: .3rem; font-weight: 400; }
.row-form label input[type="checkbox"] { width: auto; }

/* Date-range / export controls above a report. */
.filter-bar { display: flex; flex-wrap: wrap; gap: .5rem; align-items: end; margin-bottom: 1rem; }
.filter-bar label { margin: 0 0 .25rem; }
.filter-bar input, .filter-bar select { width: auto; min-width: 0; }

/* Each form in a button row is a flex item and needs a basis of its own,
   otherwise a form containing a label + input + button collapses. */
.btn-row > form { flex: 1 1 12rem; }
.bulk-actions > form { display: flex; flex-direction: column; align-items: flex-start; gap: .55rem; }
.bulk-actions label { margin: 0; }
.bulk-actions input, .bulk-actions select { width: 100%; }
.bulk-actions .btn { flex: 0 0 auto; }
.quote-status-cell .pill { vertical-align: top; }
.quote-aging-pill { display: block; width: max-content; max-width: 100%; margin-top: .35rem; border-radius: 8px; line-height: 1.25; white-space: normal; }

@media (max-width: 52rem) {
  /* Nine admin links wrapped onto three stacked rows, eating a third of a
     phone screen before any content. Keep the home link fixed and scroll only
     the tabs, so the active tab can be brought into view without overlap. */
  .topnav { flex-wrap: nowrap; overflow: hidden; padding-right: 0; }
  .topnav-scroll { overflow-x: auto; scrollbar-width: none; padding-right: 1rem; }
  .topnav-scroll::-webkit-scrollbar { display: none; }
  .topnav a, .topnav .brand { white-space: nowrap; }
  .topnav .spacer { display: none; }
  /* The scrollbar is hidden, so this fade is the only hint that Cuenta /
     Settings exist past the right edge. The nav script adds .scrollable when
     the strip actually overflows and .at-end once it is scrolled to the end. */
  .topnav.scrollable { position: relative; }
  .topnav.scrollable::after {
    content: ''; position: absolute; top: 0; right: 0; bottom: 0; width: 2.4rem;
    background: linear-gradient(to right, rgb(30 58 47 / 0), var(--green)); pointer-events: none;
  }
  .topnav.scrollable.at-end::after { display: none; }
}

@media (max-width: 40rem) {
  /* Admin list rows: the description takes the first line, then the controls
     sit under it in TWO lines — [▲▼][date][Move], then the three outcomes.
     Nine separate lines is what this looked like before.

     `> form` is load-bearing. As a descendant selector it also caught the
     individual forms wrapping each arrow and each outcome button — one form
     per button — and stretched every one of them to 100%, which is why each
     landed on a line of its own. Only the row's OWN form (Move / Approve)
     should claim width here. */
  .day-stop:not(a) { flex-wrap: wrap; align-items: center; }
  /* Basis leaves room for the number circle beside it but not for the controls
     after it, so the stop reads as one line and the controls wrap below —
     rather than the circle stranded alone on a line of its own. */
  .day-stop:not(a) > .body { flex: 1 1 calc(100% - 3rem); min-width: 0; }
  /* An explicit basis, not `auto`: flexbox decides where to wrap from the
     basis BEFORE it shrinks anything, so a form measured at its natural
     content width jumped to its own line the moment a row carried both
     arrows. Sized to fit the two-arrow case, then it grows to fill. */
  .day-stop:not(a) > form { flex: 1 1 12rem; }
  .day-stop:not(a) > .reorder { flex: 0 0 auto; flex-direction: row; }
  /* 2.75rem still clears the 44px tap target, and the two together buy back
     the width the date box needs on the tightest row. */
  .reorder .btn { width: 2.75rem; }
  .day-stop:not(a) > .close-out { flex: 1 1 100%; margin-top: 0; gap: .35rem; }
  /* Trimmed horizontally so all three outcomes sit on one line at 375px
     instead of "Skipped" dropping to a line of its own — it missed by 2px.
     Vertical padding is untouched, so the 44px tap height stands. */
  .close-out .btn { padding-left: .5rem; padding-right: .5rem; }
  .row-form input[type="date"], .row-form input[name="ref"] { flex: 1 1 7rem; }
  .filter-bar > span { flex: 1 1 9rem; }
  .filter-bar .btn { flex: 1 1 auto; }
}

/* Tablets and up: the field and portal column is sized for a phone held in
   one hand. On an iPad that leaves most of the screen empty, so let it grow —
   still short of full width, because a 1000px line length is unreadable. */
@media (min-width: 48rem) {
  .surface-field .app-main, .surface-portal .app-main { max-width: 46rem; }
  .surface-field .visit-header a { font-size: 1.05rem; }
}

/* Large desktop: admin reports and grids get the extra room. */
@media (min-width: 90rem) {
  .surface-admin .app-main { max-width: 80rem; }
}

/* Note edit/remove panel. A <details> rather than always-visible controls:
   the common case is reading your notes, not changing them, and a bare
   "Remove" button beside every note is one mis-tap from losing one. Expanding
   first makes the destructive action deliberate without needing a dialog. */
.card > details > summary {
  cursor: pointer; color: var(--clay-dark); font-size: .92rem;
  padding: .2rem 0; width: max-content;
}
.card > details > summary:hover { text-decoration: underline; }
/* A collapsed SECTION (the client timeline) — reads as its h2 would, so
   collapsing it doesn't demote it to a link. Overrides the note-edit summary
   styling above. */
.card > details > summary.card-section-toggle {
  color: var(--green); font-size: 1.25rem; font-weight: 700; padding: .1rem 0 .4rem;
}
.card > details form + form { margin-top: .5rem; }

/* Account page notification grid. The portal column is 34rem, so the two
   checkbox columns are pinned narrow and the label takes what is left —
   otherwise a three-column auto layout gives "Schedule changes and
   confirmations" one word per line. Checkboxes need the width reset: inputs
   are 100%-wide globally, which renders each one as a bar. */
.prefs { width: 100%; border-collapse: collapse; margin: .5rem 0 .75rem; }
.prefs th, .prefs td { padding: .5rem .4rem; text-align: left; }
.prefs tbody td { border-top: 1px solid #eee7db; }
.prefs thead th:not(:first-child), .prefs tbody td:not(:first-child) {
  width: 4.25rem; text-align: center;
}
.prefs thead th { font-size: .82rem; color: var(--ink-soft); text-transform: uppercase; letter-spacing: .04em; }
.prefs input[type="checkbox"] { width: auto; margin: 0; }
.prefs input[type="checkbox"]:disabled { opacity: .55; }
.prefs-group th {
  padding-top: 1.1rem; border-top: none; font-size: .82rem; color: var(--green);
  text-transform: uppercase; letter-spacing: .04em;
}


/* The monthly statement — a screen that is also a document. It gets printed or
   saved to PDF and handed to an accountant, so the print view has to lose the
   furniture (nav, buttons, the app's own chrome) and keep the numbers. */
.statement-bar { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center; margin-bottom: 1rem; }
.statement-bar .spacer { flex: 1; }

@media print {
  .topnav, .staging-banner, .no-print, .field-topbar { display: none !important; }
  .app-main { max-width: none; padding: 0; }
  .card { box-shadow: none; border: 1px solid #ddd; break-inside: avoid; }
  .kpi { box-shadow: none; border: 1px solid #ddd; }
  table.data { box-shadow: none; font-size: 11pt; }
  /* Repeat the header when a long expense list spills onto a second sheet. */
  table.data thead { display: table-header-group; }
  tr { break-inside: avoid; }
  a { color: inherit; text-decoration: none; }
  body { background: #fff; }
}
