:root {
  --bg: #eaeeeb;
  --surface: #ffffff;
  --surface-soft: #eef4f2;
  --ink: #16201d;
  --muted: #566159;
  --line: #d2ddd8;
  --teal: #087f7a;
  --teal-dark: #075d59;
  --green: #198754;
  --amber: #b7791f;
  --red: #c24135;
  --blue: #3b67b0;
  --violet: #6c55b8;
  /* Soft semantic tints (chips / row highlights / small accents) */
  --tint-green: #e6f5ec;
  --tint-red: #fdece9;
  --tint-amber: #fdf2e0;
  --tint-blue: #e8f1fb;
  --tint-teal: #e2f1ef;
  /* Solid summary-card fills — three shades of grey, no colour. White text
     on all (AA-safe). Money-in cards (Income, Ready) share the light grey;
     Waiting = mid grey; Spending = dark grey. */
  --card-income: #676c6a;  /* light grey */
  --card-ready:  #676c6a;  /* light grey */
  --card-wait:   #565c5a;  /* mid grey   */
  --card-spend:  #3a3f3e;  /* dark grey  */
  --shadow: 0 10px 26px rgba(24, 33, 31, 0.10);
  /* Project colour tags (v4.22) - a fixed palette so a card is always
     readable; every pair is redefined for dark mode below. */
  --pc-teal: #087f7a;   --pct-teal: #e2f1ef;
  --pc-blue: #3b67b0;   --pct-blue: #e8f1fb;
  --pc-violet: #6c55b8; --pct-violet: #ede9f8;
  --pc-green: #198754;  --pct-green: #e6f5ec;
  --pc-amber: #b7791f;  --pct-amber: #fdf2e0;
  --pc-red: #c24135;    --pct-red: #fdece9;
  --pc-clay: #a05a2c;   --pct-clay: #f7ebe1;
  --pc-slate: #5b6b7a;  --pct-slate: #eaeef2;
}

body.dark {
  --bg: #0e1217;
  --surface: #1b212a;
  --surface-soft: #222a35;
  --ink: #e7ecf2;
  --muted: #a4b0bc;
  --line: #2c3743;
  --tint-green: #163027;
  --tint-red: #33211f;
  --tint-amber: #33291a;
  --tint-blue: #1c2838;
  --tint-teal: #16302e;
  --shadow: 0 12px 30px rgba(0, 0, 0, 0.45);
  --pc-teal: #2fb3ab;   --pct-teal: #16302e;
  --pc-blue: #6d97e0;   --pct-blue: #1c2838;
  --pc-violet: #9c88e8; --pct-violet: #241f38;
  --pc-green: #4cc38a;  --pct-green: #163027;
  --pc-amber: #e0a343;  --pct-amber: #33291a;
  --pc-red: #e3695c;    --pct-red: #33211f;
  --pc-clay: #cd8b57;   --pct-clay: #33241a;
  --pc-slate: #93a5b5;  --pct-slate: #212a33;
}
body.dark .report-table tbody tr:nth-child(even) { background: var(--surface-soft); }
body.dark .report-table tfoot th { background: var(--surface-soft); }
body.dark .bar { background: #2c3743; }
body.dark .tag.cat { background: #2c3743; color: #cdd6e0; }
body.dark .state.pending { background: #3a3320; }
body.dark input, body.dark select, body.dark textarea { background: var(--surface-soft); color: var(--ink); }

/* Password show/hide toggle */
.pw-wrap { position: relative; }
.pw-wrap input { width: 100%; padding-right: 44px !important; }
.pw-toggle {
  position: absolute;
  right: 6px;
  top: 50%;
  transform: translateY(-50%);
  background: none;
  border: none;
  cursor: pointer;
  font-size: 17px;
  line-height: 1;
  opacity: 0.65;
  padding: 4px 6px;
}
.pw-toggle:hover { opacity: 1; }

/* Search box */
.search-box {
  width: 100%;
  min-height: 38px;
  border-radius: 10px;
  border: 1px solid var(--line);
  padding: 8px 12px;
  font-family: inherit;
  margin-bottom: 10px;
  background: var(--surface);
  color: var(--ink);
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  min-height: 100vh;
  color: var(--ink);
  background: var(--bg);
  font-family: Inter, Segoe UI, Arial, sans-serif;
}

button,
select {
  font: inherit;
}

button {
  cursor: pointer;
}

button:disabled {
  cursor: not-allowed;
  opacity: 0.55;
}

.app-shell {
  display: grid;
  grid-template-columns: 260px minmax(0, 1fr);
  min-height: 100vh;
}

/* Let every level of the layout shrink to the window; wide children (tables,
   chip rows) then scroll inside their own `overflow-x:auto` box as intended. */
.workspace,
.main-grid,
.queue-panel,
.detail-panel {
  min-width: 0;
}

.sidebar {
  position: sticky;
  top: 0;
  height: 100vh;
  padding: 24px 18px;
  background: #102320;
  color: #eef7f4;
}

.brand {
  display: flex;
  gap: 12px;
  align-items: center;
  margin-bottom: 28px;
}

.brand-mark {
  display: grid;
  width: 44px;
  height: 44px;
  place-items: center;
  border-radius: 8px;
  background: #f0b84c;
  color: #17211f;
  font-weight: 800;
}

.brand strong,
.brand span {
  display: block;
}

.brand span,
.sync-box {
  color: #a8bbb5;
  font-size: 13px;
}

.nav-list {
  display: grid;
  gap: 6px;
}

.nav-divider {
  border: 0;
  border-top: 1px solid rgba(255, 255, 255, 0.12);
  margin: 6px 4px;
}

.overhead-filter-bar { margin-bottom: 14px; }

.nav-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-height: 44px;
  padding: 10px 12px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: #dfe9e5;
  text-align: left;
}

.nav-item:hover {
  background: #1d3a35;
  color: #ffffff;
}

.nav-item.active {
  background: #1d3a35;
  color: #ffffff;
  box-shadow: inset 3px 0 0 var(--brand-accent, #f0b84c);
}

.nav-item.active .nav-icon {
  background: #f0b84c;
  color: #17211f;
}

.nav-icon {
  display: grid;
  width: 26px;
  height: 26px;
  place-items: center;
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.1);
  font-size: 12px;
  font-weight: 800;
}

.sync-box {
  position: absolute;
  right: 18px;
  bottom: 22px;
  left: 18px;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 8px;
}

.status-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: #4ade80;
}

.workspace {
  padding: 28px;
}

.topbar,
.section-head,
.row-title,
.detail-actions,
.topbar-actions,
.filter-row {
  display: flex;
  align-items: center;
}

.topbar-actions { flex-wrap: wrap; }
.topbar-title { display: flex; align-items: center; gap: 12px; min-width: 0; }
.nav-toggle {
  display: none;
  min-height: 42px;
  min-width: 42px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--surface);
  color: var(--ink);
  font-size: 20px;
  line-height: 1;
}
.nav-backdrop {
  position: fixed;
  inset: 0;
  z-index: 11;
  background: rgba(9, 18, 16, 0.45);
}
.nav-backdrop[hidden] { display: none; }
#site-selector { max-width: 220px; }

.topbar {
  justify-content: space-between;
  gap: 20px;
  margin-bottom: 18px;
}

.eyebrow {
  margin: 0 0 4px;
  color: var(--muted);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0;
  text-transform: uppercase;
}

h1,
h2 {
  margin: 0;
}

h1 {
  font-size: 30px;
}

h2 {
  font-size: 20px;
}

.topbar-actions {
  gap: 10px;
}

select,
.ghost-button,
.primary-button,
.danger-button,
.chip {
  min-height: 40px;
  border-radius: 8px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink);
}

select {
  padding: 0 14px;
}

.ghost-button,
.primary-button,
.danger-button,
.chip {
  padding: 0 14px;
  font-weight: 800;
}

.primary-button {
  border-color: var(--teal);
  background: var(--teal);
  color: #ffffff;
}

.primary-button:hover {
  background: var(--teal-dark);
}

.danger-button {
  border-color: #f3c7c3;
  color: var(--red);
}

.ghost-button.full {
  width: 100%;
}

/* Split button: the big half does the everyday action (download the backup),
   the narrow chevron holds the rare ones (restore / folder / switch database).
   They read as one control, so the corner gains no visual clutter. */
.split-btn {
  display: inline-flex;
  align-items: stretch;
}

.split-btn .split-main {
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
}

.split-btn .split-more {
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
  border-left: 0;
  padding: 0 9px;
  font-size: 12px;
  color: var(--muted);
}

.split-btn .split-more:hover {
  color: var(--ink);
}

.metrics {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 180px), 1fr));
  gap: 12px;
  margin-bottom: 16px;
}

.metric,
.queue-panel,
.detail-panel,
.site-card {
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface);
  box-shadow: var(--shadow);
}

.metric {
  padding: 16px;
  border: 0;
  color: #ffffff;
  background: var(--card-ready);
}

.metric.good    { background: var(--card-income); }
.metric.spend   { background: var(--card-spend); }
.metric.warning { background: var(--card-wait); }
.metric.info    { background: var(--card-ready); }

.metric span,
.metric small {
  display: block;
  color: rgba(255, 255, 255, 0.85);
}

.metric strong {
  display: block;
  margin: 8px 0 4px;
  font-size: 22px;
  color: #ffffff;
}

.main-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.45fr) minmax(340px, 0.8fr);
  gap: 16px;
}

.queue-panel,
.detail-panel {
  padding: 18px;
}

.detail-panel {
  border-top: 3px solid var(--teal);
}

.section-head {
  justify-content: space-between;
  gap: 14px;
  margin-bottom: 14px;
}

.filter-row {
  gap: 8px;
  overflow-x: auto;
}

.chip {
  min-height: 34px;
  padding: 0 12px;
  color: var(--muted);
  white-space: nowrap;
}

.chip.active {
  border-color: var(--teal);
  background: var(--tint-teal);
  color: var(--teal-dark);
  box-shadow: inset 0 0 0 1px var(--teal);
}

/* Entry rows are TWO lines at every width (v4.28):
     line 1 = what it was + its chips      |  amount
     line 2 = who/where . when . note      |  status
   This layout was written for the phone in v4.26 and proved there; it is now
   the layout everywhere. The old 3-column grid also left its last 150px track
   empty (a row has only two children), which is why the amount used to stop
   short of the right edge. */
.payment-row {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 10px 0;
  border-top: 1px solid var(--line);
}

.payment-row.selected {
  margin: 0 -12px;
  padding-right: 12px;
  padding-left: 9px;
  border-radius: 8px;
  background: var(--tint-teal);
  box-shadow: inset 3px 0 0 var(--teal);
}

.row-main {
  display: flex;
  flex: 1 1 auto;
  min-width: 0;
  flex-wrap: wrap;
  align-items: baseline;
  column-gap: 6px;
  row-gap: 2px;
}

.row-title {
  flex: 1 1 100%;
  min-width: 0;
  gap: 8px;
  /* never wrap: when space runs out the DESCRIPTION ellipsises rather than the
     chips dropping onto a third line */
  flex-wrap: nowrap;
  overflow: hidden;
}

.row-title .tag { flex: 0 0 auto; }

.row-title strong {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.row-main p,
.row-main small,
.row-status span {
  margin: 0;
}

/* one size for both halves of line 2, or a 14px party name beside an 11px date
   reads as two different things stuck together */
.row-main p,
.row-main small {
  margin: 0;
  color: var(--muted);
  font-size: 12.5px;
  line-height: 1.35;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.row-main p { max-width: 60%; }

/* The chips set the height of line 1. Trimming them is the last of the
   moderate pass - it shortens every row without touching any text size. */
.payment-row .tag,
.payment-row .state {
  min-height: 20px;
  padding: 1px 8px;
  font-size: 11.5px;
}
.row-main p::after { content: " ·"; }

.row-status {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: flex-start;
  text-align: right;
  gap: 3px;
}

.tag,
.state,
.approval-steps span {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 26px;
  border-radius: 999px;
  padding: 0 9px;
  font-size: 12px;
  font-weight: 800;
  white-space: nowrap;
}

.tag.material {
  background: #ede9fe;
  color: var(--violet);
}

.tag.labour {
  background: #fff4d5;
  color: #8a5a09;
}

.tag.vendor {
  background: #e9f5ff;
  color: var(--blue);
}

.tag.client {
  background: #def7ec;
  color: var(--green);
}

.state.blocked {
  background: #ffe9e7;
  color: var(--red);
}

.state.pending {
  background: #fff4d5;
  color: var(--amber);
}

.state.ready {
  background: #def7ec;
  color: var(--green);
}

.state.verify {
  background: #e9f5ff;
  color: var(--blue);
}

/* Money-flow kind tags */
.tag.kind-funding { background: #e9f5ff; color: var(--blue); }
.tag.kind-advance { background: #ede9fe; color: var(--violet); }
.tag.kind-return  { background: #e6f6ec; color: var(--green); }
.tag.kind-spend   { background: #ffe9e7; color: var(--red); }
.tag.kind-income  { background: #def7ec; color: var(--green); }
.tag.kind-overhead { background: #fff4e0; color: #9a6a1b; }
.tag.cat  { background: #f1f3f9; color: #495267; text-transform: capitalize; }
.tag.mode { background: #fff4d5; color: #8a5a09; }
.tag.via  { background: #e7f7f0; color: var(--teal); }
.tag.grp  { background: #ede9fe; color: var(--violet); }
.tag.void { background: #ffe9e7; color: var(--red); font-weight: 700; }

/* Deleted (voided) entries: dimmed + struck through, still visible to the Owner */
.voided-row { opacity: 0.6; }
.voided-row .row-title strong { text-decoration: line-through; }

/* Pay list (group payment) */
.paylist-table { border: 1px solid var(--line); border-radius: 10px; overflow: hidden; }
.paylist-head, .paylist-row { display: grid; grid-template-columns: 2.4fr 1.2fr 1.2fr 36px; gap: 8px; align-items: center; padding: 8px; }
.paylist-head { background: var(--surface-soft); font-size: 12px; font-weight: 700; color: var(--muted); }
.paylist-row { border-top: 1px solid var(--line); }
.paylist-row input, .paylist-row select { width: 100%; min-height: 36px; border-radius: 8px; border: 1px solid var(--line); padding: 6px 8px; font-family: inherit; background: var(--surface); color: var(--ink); }
.paylist-row .pl-del { background: none; border: none; color: var(--red); font-size: 18px; cursor: pointer; }
.paylist-total { display: flex; justify-content: space-between; align-items: center; margin-top: 12px; padding: 10px 12px; background: var(--surface-soft); border-radius: 10px; font-size: 15px; }

/* Signed amounts */
.amt-in   { color: var(--green); }
.amt-out  { color: var(--red); }
.amt-move { color: var(--blue); }

/* ---- Projects page ---- */
.balance-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr));
  gap: 14px;
}
.project-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
  gap: 14px;
  /* Cards keep their own height - a collapsed card must not be stretched
     tall just because a neighbour in the same row is expanded. */
  align-items: start;
}
.project-card {
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 16px;
  background: var(--surface);
}
.project-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 8px;
  margin-bottom: 12px;
}
.project-head strong { display: block; font-size: 15px; }
.project-head span { color: var(--muted); font-size: 12px; }
.project-bars { margin-bottom: 12px; }
.bar-label {
  display: flex;
  justify-content: space-between;
  font-size: 12px;
  font-weight: 700;
  margin: 8px 0 4px;
}
.bar {
  height: 8px;
  border-radius: 999px;
  background: #eef0f5;
  overflow: hidden;
}
.bar-fill { height: 100%; border-radius: 999px; }
.bar-fill.prog  { background: var(--blue); }
.bar-fill.spend { background: var(--green); }
.bar-fill.over  { background: var(--red); }
.project-nums { margin: 0; }
.project-nums > div {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 5px 0;
  border-bottom: 1px dashed var(--line);
}
.project-nums > div:last-child { border-bottom: 0; }
.project-nums dt { color: var(--muted); font-size: 12px; }
.project-nums dd { margin: 0; font-weight: 800; font-size: 14px; text-align: right; }

/* Collapsible card (v4.29): the bars + headline money always show, the rest
   slides down on "More details". The hidden half stays in the DOM - its Add /
   Edit / Delete buttons keep their listeners - it is just a grid row animated
   from 0fr up to its real height. */
.project-more {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 240ms cubic-bezier(0.4, 0, 0.2, 1);
}
.project-card.open .project-more { grid-template-rows: 1fr; }
.project-more-inner { overflow: hidden; min-height: 0; }
.project-more-toggle {
  width: 100%;
  margin-top: 10px;
  min-height: 32px;
  padding: 7px 10px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--surface-soft);
  color: var(--muted);
  font: inherit;
  font-size: 12px;
  font-weight: 700;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
}
.project-more-toggle:hover { background: var(--surface); color: var(--ink); }
.pmt-arrow { font-size: 10px; transition: transform 240ms ease; }
.project-card.open .pmt-arrow { transform: rotate(180deg); }
@media (prefers-reduced-motion: reduce) {
  .project-more, .pmt-arrow { transition: none; }
}

/* Colour-tagged card: a stripe down the left plus a tinted title band. */
.project-card.has-color { border-left: 4px solid var(--pc); }
.project-card.has-color .project-head {
  background: var(--pct);
  border-radius: 10px;
  padding: 8px 10px;
  margin: -4px -4px 12px;
}

/* Archived projects: collapsed section at the bottom of the Projects page. */
.archived-block { margin-top: 20px; border-top: 1px solid var(--line); padding-top: 12px; }
.archived-block > summary {
  cursor: pointer;
  font-weight: 800;
  font-size: 14px;
  color: var(--muted);
  padding: 6px 2px;
  list-style: none;
  display: flex;
  align-items: center;
  gap: 8px;
}
.archived-block > summary::-webkit-details-marker { display: none; }
.archived-block > summary::before { content: "B8"; font-size: 12px; }
.archived-block[open] > summary::before { content: "BE"; }
.archived-block .project-grid { margin-top: 12px; }
.project-card.archived { opacity: 0.72; background: var(--surface-soft); }

/* Colour picker in the Add/Edit Project window. */
.swatch-row { display: flex; gap: 8px; flex-wrap: wrap; }
.swatch {
  width: 30px;
  height: 30px;
  min-height: 30px;
  padding: 0;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: var(--sw, var(--surface));
  cursor: pointer;
}
.swatch.active { box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px var(--ink); }
.swatch.none {
  background:
    linear-gradient(to top right, transparent calc(50% - 1px), var(--red) calc(50% - 1px), var(--red) calc(50% + 1px), transparent calc(50% + 1px)),
    var(--surface);
}

/* Month chips on Office Costs carry their own total (v4.22). */
.chip.has-sub { line-height: 1.2; padding-top: 5px; padding-bottom: 5px; }
.chip .chip-sub { display: block; font-size: 11px; font-weight: 700; opacity: 0.85; }
.overhead-totals {
  display: flex;
  align-items: center;
  gap: 18px;
  flex-wrap: wrap;
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 10px 14px;
  margin-bottom: 14px;
  background: var(--surface);
}
.overhead-totals .ot-label { font-size: 12px; color: var(--muted); display: block; }
.overhead-totals .ot-value { font-size: 17px; font-weight: 800; }

.project-contracts { margin-top: 14px; border-top: 1px solid var(--line); padding-top: 10px; }
.contract-row {
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 8px 10px;
  margin-top: 8px;
  background: var(--bg, transparent);
}
.contract-row-top { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.contract-row-top strong { font-size: 13px; margin-right: auto; }
.contract-row-nums { display: flex; gap: 14px; font-size: 12px; color: var(--muted); margin-top: 4px; flex-wrap: wrap; }

/* ---- Attached bill papers (one chip per file, several per bill) ---- */
.bill-files { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.bill-file {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  max-width: 100%;
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 2px 4px 2px 9px;
  font-size: 11px;
  background: var(--surface);
}
.bill-file a {
  color: var(--ink);
  text-decoration: none;
  max-width: 190px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.bill-file a:hover { text-decoration: underline; }
.bill-file-x {
  border: 0;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
  padding: 2px 5px;
  border-radius: 999px;
  min-height: 0;
}
.bill-file-x:hover { color: var(--red); background: var(--line); }
.bill-files-empty { font-size: 11px; color: var(--muted); margin-top: 6px; }

/* ---- Cash position cards ---- */
.balance-card {
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 16px;
  background: var(--surface);
}
.balance-card header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 8px;
}
.balance-net { font-size: 24px; font-weight: 800; }
.balance-card small { color: var(--muted); }
.balance-modes {
  display: flex;
  gap: 10px;
  margin-top: 12px;
  border-top: 1px solid var(--line);
  padding-top: 10px;
}
.balance-modes span {
  flex: 1;
  display: flex;
  flex-direction: column;
  font-size: 11px;
  color: var(--muted);
}
.balance-modes b { color: var(--ink, #1d2230); font-size: 13px; margin-top: 2px; }

/* ---- Reports ---- */
.report-controls {
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 14px;
  margin-bottom: 12px;
  background: var(--surface);
}
.report-controls select, .report-controls input[type="date"] {
  min-height: 34px;
  border-radius: 8px;
  border: 1px solid var(--line);
  padding: 4px 8px;
  font-family: inherit;
}
/* A <select> sizes itself to its longest option, so one long project name
   stretched this control to ~380px and dragged the whole page sideways on a
   phone. Same fix as #site-selector got in v4.22. Applies to Reports and the
   Cash Book, which share this control. */
.report-controls select { max-width: 220px; }
.report-period { color: var(--muted); font-size: 13px; margin: 0 0 10px; }
.report-table-wrap { overflow-x: auto; border: 1px solid var(--line); border-radius: 12px; }
.report-table { border-collapse: collapse; width: 100%; font-size: 13px; min-width: 720px; }
.report-table th, .report-table td { padding: 8px 10px; text-align: right; border-bottom: 1px solid var(--line); white-space: nowrap; }
.report-table th:first-child, .report-table td:first-child { text-align: left; }
.report-table thead th { background: var(--blue); color: #fff; font-weight: 800; }
.report-table tfoot th { background: #f1f3f9; font-weight: 800; }
.report-table tbody tr:nth-child(even) { background: #fafbfd; }

/* A Paid figure you can open: it is a number that hides a list of real
   payments, so it reads as a link and says so on hover. */
.report-table .paid-cell {
  cursor: pointer;
  text-decoration: underline;
  text-decoration-style: dotted;
  text-underline-offset: 3px;
}

.report-table .paid-cell:hover { background: var(--tint-teal); }

/* The breakdown drops in as a full-width row under the figure it belongs to. */
.vpay-drill > td {
  background: var(--surface-soft, #f7f8fb);
  padding: 12px 14px;
  white-space: normal;
}

.vpay-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 8px;
}

.vpay-head .ghost-button { min-height: 30px; padding: 0 12px; font-size: 12px; }

.vpay-table { min-width: 0; }
.vpay-table tbody tr:hover { background: var(--tint-teal); }

.approval-steps {
  display: flex;
  justify-content: flex-end;
  gap: 6px;
  min-width: 0;
}

.approval-steps span {
  border: 1px solid var(--line);
  color: var(--muted);
}

.approval-steps span.done {
  border-color: #b7e5cd;
  background: #def7ec;
  color: var(--green);
}

.bill-preview {
  display: grid;
  gap: 10px;
}

.paper {
  display: grid;
  min-height: 150px;
  place-items: center;
  border: 1px dashed #b9c5c0;
  border-radius: 8px;
  background: linear-gradient(135deg, #ffffff 0%, #ffffff 55%, #edf3f0 55%, #edf3f0 100%);
  text-align: center;
}

.paper span,
.paper small {
  color: var(--muted);
}

.paper strong {
  color: var(--red);
}

.detail-list {
  display: grid;
  gap: 10px;
  margin: 16px 0;
}

.detail-list div {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 0;
  border-bottom: 1px solid var(--line);
}

dt {
  color: var(--muted);
}

dd {
  margin: 0;
  font-weight: 800;
  text-align: right;
}

.timeline {
  display: grid;
  gap: 12px;
  margin: 18px 0;
}

.timeline-item {
  display: grid;
  grid-template-columns: 22px 1fr;
  gap: 10px;
}

.timeline-item > span {
  width: 14px;
  height: 14px;
  margin-top: 3px;
  border: 2px solid #b9c5c0;
  border-radius: 50%;
}

.timeline-item.done > span {
  border-color: var(--green);
  background: var(--green);
}

.timeline-item strong,
.timeline-item small {
  display: block;
}

.timeline-item small {
  color: var(--muted);
}

.detail-actions {
  gap: 10px;
  flex-wrap: wrap;
}

.detail-actions button {
  flex: 1 1 auto;
  min-width: 130px;
}

.state.paid {
  background: #e7eceb;
  color: var(--teal-dark);
}

/* Toasts */
#toast-container {
  position: fixed;
  right: 18px;
  bottom: 18px;
  z-index: 2000;
  display: grid;
  gap: 8px;
}

.toast {
  min-width: 220px;
  max-width: 360px;
  padding: 12px 16px;
  border-radius: 10px;
  background: #18211f;
  color: #fff;
  font-weight: 700;
  font-size: 14px;
  box-shadow: var(--shadow);
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 0.25s ease, transform 0.25s ease;
}

.toast.show {
  opacity: 1;
  transform: translateY(0);
}

.toast.success { background: #0f6b4f; }
.toast.error { background: #a3342a; }
.toast.info { background: #1d3a35; }

@media (max-width: 640px) {
  #toast-container {
    right: 10px;
    left: 10px;
    bottom: 76px;
  }
  .toast { max-width: none; }
}

.site-strip {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
  gap: 12px;
  margin-top: 16px;
}

.site-card {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding: 16px;
}

.site-card strong,
.site-card span,
.site-numbers span {
  display: block;
}

.site-card span,
.site-numbers span {
  color: var(--muted);
}

.site-numbers {
  display: grid;
  gap: 5px;
  text-align: right;
}

.mobile-nav {
  display: none;
}

/* Drawer-only actions: they exist for the phone layout, where the top bar is
   trimmed to ☰ + title + New Entry. Hidden on desktop, which keeps its full
   top bar. */
.drawer-actions {
  display: none;
}

.drawer-actions-title {
  margin: 0 0 8px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
}

@media (max-width: 980px) {
  .app-shell {
    display: block;
  }

  /* The sidebar becomes a drawer instead of disappearing - the bottom bar only
     has room for 4 pages, and every other page has to stay reachable. */
  .sidebar {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 12;
    width: min(84vw, 290px);
    height: 100vh;
    overflow-y: auto;
    transform: translateX(-100%);
    transition: transform 0.18s ease-out;
    box-shadow: 0 0 40px rgba(0, 0, 0, 0.4);
  }

  body.nav-open .sidebar { transform: translateX(0); }

  .nav-toggle { display: inline-flex; align-items: center; justify-content: center; }

  .workspace {
    /* extra bottom room = mobile nav + the phone's own home-bar area, so the
       last row is never hidden underneath either (matters once installed to
       the home screen, where there is no browser chrome) */
    padding: 18px 14px calc(86px + env(safe-area-inset-bottom, 0px));
  }

  .topbar {
    align-items: flex-start;
  }

  .topbar-actions {
    width: 100%;
    flex-wrap: wrap;
    justify-content: flex-end;
  }

  /* PHONE: the top of every page used to repeat six buttons and a project box
     before any page content. Only "+ New Entry" stays; the rest moved into the
     ☰ drawer (.drawer-actions below). */
  .topbar-actions #btn-theme,
  .topbar-actions #btn-export,
  .topbar-actions #btn-backup-top,
  .topbar-actions #btn-paylist,
  .topbar-actions #btn-profile,
  .topbar-actions #btn-logout {
    display: none !important;
  }

  .topbar-actions #btn-new-request {
    flex: 1;
    min-height: 44px;
  }

  .drawer-actions {
    display: block;
    margin: 18px 18px 0;
    padding-top: 14px;
    border-top: 1px solid rgba(255, 255, 255, 0.12);
  }

  .drawer-actions .nav-item {
    width: 100%;
    min-height: 44px;
  }

  /* In the phone drawer everything must stack in normal flow. The Settings/Log/
     Help row and the sync box are absolutely positioned for the desktop
     sidebar, which made them sit ON TOP of the actions block here. */
  .sidebar-bottom,
  .sync-box {
    position: static !important;
    margin-top: 14px;
  }

  .sidebar {
    padding-bottom: calc(24px + env(safe-area-inset-bottom, 0px));
  }

  /* PHONE: the 2-line row layout itself now lives in the base rules (v4.28).
     What stays here is only what a phone needs on top of it - smaller type, a
     narrower party column, and dropping the two chips that carry the least. */
  .payment-row {
    gap: 10px;
    padding: 11px 0;
  }

  .row-title { gap: 6px; }

  .row-main p,
  .row-main small { font-size: 12px; }

  .row-main p { max-width: 68%; }

  /* the two chips that carry the least in a list - payment mode and category -
     are hidden here; kind and "via <engineer>" stay because they change meaning */
  .payment-row .tag.mode,
  .payment-row .tag.cat {
    display: none;
  }

  .payment-row .tag {
    padding: 1px 7px;
    font-size: 10.5px;
  }

  .payment-row .state {
    padding: 1px 8px;
    font-size: 10.5px;
  }

  .main-grid {
    grid-template-columns: 1fr;
  }

  .row-status,
  .approval-steps {
    justify-content: flex-start;
    text-align: left;
  }

  /* The detail panel shows whichever entry happens to be selected. On a phone
     it used to be hoisted ABOVE the page's own list (order: -1), so every page
     opened on a random bill and the real content was below the fold. It now
     follows the list, where it belongs. */
  .detail-panel {
    order: 2;
  }

  .site-card {
    display: grid;
  }

  .site-numbers {
    text-align: left;
  }

  .mobile-nav {
    position: fixed;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 10;
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    align-items: center;
    min-height: 64px;
    padding-bottom: env(safe-area-inset-bottom, 0px);
    border-top: 1px solid var(--line);
    background: var(--surface);
    box-shadow: 0 -12px 30px rgba(24, 33, 31, 0.08);
  }

  .mobile-nav button {
    min-height: 48px;
    border: 0;
    background: transparent;
    color: var(--muted);
    font-weight: 800;
  }

  .mobile-nav button.active {
    color: var(--teal-dark);
  }

  .mobile-nav .add-button {
    width: 48px;
    height: 48px;
    margin: auto;
    border-radius: 50%;
    background: var(--teal);
    color: #ffffff;
    font-size: 26px;
  }
}

@media (max-width: 640px) {
  h1 {
    font-size: 24px;
  }

  .topbar {
    display: grid;
  }

  .topbar-actions {
    display: grid;
    grid-template-columns: 1fr 1fr;
  }

  .topbar-actions select {
    grid-column: 1 / -1;
    width: 100%;
  }

  .metrics {
    gap: 10px;
  }

  .metric {
    padding: 14px;
  }

  .queue-panel,
  .detail-panel {
    padding: 14px;
  }

  .section-head {
    display: grid;
  }

  .filter-row {
    justify-content: flex-start;
  }
}

/* ---------- Archviz studio (Owner-private) ---------- */
.av-history {
  list-style: none;
  margin: 12px 0 0;
  padding: 10px 0 0;
  border-top: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 190px;
  overflow-y: auto;
}
.av-history li { display: flex; align-items: center; gap: 8px; font-size: 12.5px; }
.av-history li span { flex: 1; color: var(--muted); }
.av-history li b { font-weight: 700; white-space: nowrap; }
.av-del {
  border: none;
  background: none;
  color: var(--muted);
  cursor: pointer;
  font-size: 12px;
  padding: 2px 5px;
  border-radius: 6px;
}
.av-del:hover { color: var(--red); background: rgba(194, 65, 53, 0.1); }
.av-client-row {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  text-align: left;
  border: 1px solid var(--line);
  background: none;
  color: inherit;
  font-family: inherit;
  border-radius: 10px;
  padding: 8px 12px;
  margin-bottom: 6px;
  cursor: pointer;
}
.av-client-row:hover { border-color: var(--muted); }

/* ---------- Ledger + pie (Reports) ---------- */
.pie-flex { display: flex; gap: 24px; align-items: center; flex-wrap: wrap; margin: 6px 0 16px; }
.pie-legend { display: flex; flex-direction: column; gap: 6px; min-width: 250px; }
.legend-title { font-weight: 800; margin-bottom: 4px; }
.legend-row { display: flex; align-items: center; gap: 8px; font-size: 13px; }
.legend-dot { width: 12px; height: 12px; border-radius: 3px; flex: none; }
.legend-label { flex: 1; }
.legend-val { color: var(--muted); white-space: nowrap; }
.ledger-table, .cashbook-table { min-width: 900px; font-size: 12.5px; }
.cashbook-table { min-width: 1040px; }
.ledger-table tbody tr.ledger-row, .cashbook-table tbody tr.cb-row { cursor: pointer; }
.ledger-table tbody tr.ledger-row:hover td,
.cashbook-table tbody tr.cb-row:hover td { background: var(--surface-soft); }
.ledger-scroll { max-height: 540px; overflow: auto; }
.ledger-scroll .ledger-table thead th,
.ledger-scroll .cashbook-table thead th { position: sticky; top: 0; z-index: 1; }

/* Cash Book: one running-balance column per person (v4.25) */
.cashbook-table th.cb-person, .cashbook-table td.cb-person {
  border-left: 1px solid var(--line);
  white-space: nowrap;
  color: var(--muted);
}
/* Only the people this entry actually moved are shown in full strength. */
.cashbook-table td.cb-moved { color: var(--ink); font-weight: 600; background: var(--tint-teal); }
.cb-closing {
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
  border: 1px solid var(--line); border-left: 4px solid var(--teal);
  border-radius: 10px; padding: 10px 14px; margin-bottom: 14px;
  background: var(--surface-soft);
}
.cb-closing-label { color: var(--muted); font-size: 12px; margin-right: auto; }
.cb-closing-item { display: flex; flex-direction: column; gap: 2px; font-size: 12px; }
.cb-closing-item strong { font-size: 15px; white-space: nowrap; }

/* ---------- Insights page ---------- */
.insight-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 14px; margin-bottom: 8px; }
.insight-card { background: var(--surface); border: 1px solid var(--line); border-radius: 14px; padding: 14px 16px; box-shadow: var(--shadow); }
.insight-card .ic-label { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.06em; font-weight: 700; }
.insight-card .ic-value { font-size: 22px; font-weight: 800; margin: 4px 0 6px; }
.insight-card .ic-sub { font-size: 12px; color: var(--muted); display: flex; flex-direction: column; gap: 3px; }
.delta { font-weight: 700; }
.delta.good { color: var(--green); }
.delta.bad { color: var(--red); }
.delta.flat { color: var(--muted); font-weight: 500; }
.insight-section { margin: 22px 0; }
.insight-section h3 { margin: 0 0 10px; }
.chart-card { background: var(--surface); border: 1px solid var(--line); border-radius: 14px; padding: 14px 16px; }
.split-row { display: flex; align-items: center; gap: 12px; margin: 8px 0; font-size: 13px; }
.split-name { width: 180px; flex: none; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.split-bar { flex: 1; height: 18px; border-radius: 9px; overflow: hidden; display: flex; background: var(--surface-soft); }
.split-bar .sb-mat { background: #3b67b0; }
.split-bar .sb-lab { background: #e0862c; }
.split-pct { width: 230px; flex: none; color: var(--muted); font-size: 12px; text-align: right; white-space: nowrap; }
.vendor-row { display: flex; align-items: center; gap: 12px; margin: 8px 0; font-size: 13px; }
.vendor-name { width: 200px; flex: none; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vendor-bar { flex: 1; height: 14px; border-radius: 7px; background: var(--surface-soft); overflow: hidden; }
.vendor-bar span { display: block; height: 100%; background: var(--teal); border-radius: 7px; }
.vendor-amt { width: 190px; text-align: right; color: var(--muted); flex: none; white-space: nowrap; }
.muted-note { color: var(--muted); font-size: 12px; margin: 0; }
.profit-bar { flex: 1; height: 14px; border-radius: 7px; background: var(--surface-soft); overflow: hidden; }
.profit-fill { display: block; height: 100%; border-radius: 7px; }
.profit-fill.pos { background: var(--green); }
.profit-fill.neg { background: var(--red); }

/* ==========================================================================
   Phone tightening (v4.22) - KEEP THIS BLOCK LAST IN THE FILE.
   Media queries add no specificity, so these overrides only win by being the
   last rules in the file. Moving them up will silently un-do some of them.
   ========================================================================== */
@media (max-width: 640px) {
  .workspace { padding: 14px 12px calc(86px + env(safe-area-inset-bottom, 0px)); }
  h1 { font-size: 21px; }
  .topbar h1 { font-size: 20px; }
  #site-selector { max-width: 100%; }

  /* More columns per screen without dropping below a readable size. */
  .report-table { font-size: 12px; }
  .report-table th,
  .report-table td { padding: 6px 8px; }

  /* Nothing smaller than 12px on a phone. */
  .balance-modes span,
  .insight-card .ic-label,
  .chip .chip-sub,
  .split-pct,
  .vendor-amt,
  .muted-note { font-size: 12px; }

  /* Thumb-sized taps. Many of these buttons carry an inline min-height from the
     row that draws them, which is why the overrides have to be !important. */
  .chip { min-height: 38px; }
  .project-head .ghost-button,
  .contract-row .ghost-button,
  .balance-card .ghost-button,
  #list-container .ghost-button { min-height: 36px !important; padding: 4px 12px !important; font-size: 12px !important; }
  /* The ✏️ / × icon buttons inside Settings list chips. */
  #list-container .tag button { min-height: 30px !important; min-width: 30px !important; font-size: 14px !important; }
  .swatch { width: 34px; height: 34px; min-height: 34px; }

  /* Cards and metrics lose a little air so more fits above the fold. */
  .metric { padding: 12px; }
  .project-card { padding: 14px; }
  .overhead-totals { gap: 12px; padding: 10px 12px; }

  /* Long rows in Insights stop reserving fixed side columns. */
  .split-name, .vendor-name { width: 110px; }
  .split-pct, .vendor-amt { width: auto; }
}

/* ---- Office Costs: mode switch + grouped breakdown (v4.24) ---- */
.oh-breakdown {
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 14px 16px;
  margin-bottom: 14px;
  background: var(--surface-soft);
}
.oh-breakdown-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}
.oh-head-table { width: 100%; border-collapse: collapse; }
.oh-head-table td { padding: 5px 6px; border-bottom: 1px solid var(--line); font-size: 13px; }
.oh-head-table td:nth-child(2), .oh-head-table td:nth-child(3) { text-align: right; white-space: nowrap; }
.oh-head-table .oh-pct { color: var(--muted); width: 54px; }
.oh-head-row { cursor: pointer; }
.oh-head-row:hover { background: var(--tint-teal); }
.oh-head-row.active { background: var(--tint-teal); font-weight: 600; }
