:root {
  --bg: #f5f6f8;
  --surface: #ffffff;
  --border: #d8dce3;
  --text: #111827;
  --muted: #5b6471;
  --accent: #1f6feb;
  --accent-text: #ffffff;
  --danger: #b42318;
  --danger-bg: #fde8e6;
  --ok: #1a7f4e;
  --warn-bg: #fff4d6;
  --warn-text: #7a5a00;
  --shadow: 0 1px 2px rgba(17, 24, 39, 0.06);
  --radius: 8px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #0c1116;
    --surface: #161c24;
    --border: #2a323d;
    --text: #e7ebf1;
    --muted: #8b95a4;
    --accent: #4a8cff;
    --accent-text: #0a0f15;
    --danger: #ff7b6f;
    --danger-bg: #2a1414;
    --ok: #4ad29b;
    --warn-bg: #2a2412;
    --warn-text: #f0c454;
    --shadow: 0 1px 2px rgba(0, 0, 0, 0.4);
  }
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  font-size: 16px;
  line-height: 1.45;
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

h1 { font-size: 1.5rem; margin: 0 0 0.5rem; }
h2 { font-size: 1.15rem; margin: 1.5rem 0 0.5rem; }
h3 { font-size: 1.05rem; margin: 1.25rem 0 0.4rem; }
p { margin: 0 0 1rem; }

.muted { color: var(--muted); }

.topbar {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0.75rem 1rem;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  z-index: 10;
}
/* `display: flex` above wins over the html [hidden] attribute's
   default `display: none`. Restore correct hide behaviour. */
.topbar[hidden] { display: none; }
.brand {
  font-weight: 600;
  color: var(--text);
}
.brand:hover { text-decoration: none; }
.topnav {
  display: flex;
  gap: 0.25rem;
  flex: 1;
  flex-wrap: wrap;
}
.topnav a {
  padding: 0.5rem 0.75rem;
  border-radius: var(--radius);
  color: var(--text);
  min-height: 44px;
  display: inline-flex;
  align-items: center;
}
.topnav a.active {
  background: var(--bg);
  color: var(--accent);
}

main {
  max-width: 880px;
  margin: 0 auto;
  padding: 1rem;
}

/* Desktop widens the canvas to fit wide tables. 95% on big screens leaves
   only a small margin on each side; tables still rely on .table-wrap for
   internal horizontal scroll on very narrow screens. */
@media (min-width: 900px)  { main { max-width: 92%; } }
@media (min-width: 1400px) { main { max-width: 95%; } }

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.25rem;
  box-shadow: var(--shadow);
  margin-bottom: 1rem;
}
.card.narrow { max-width: 420px; margin: 3rem auto; }

label {
  display: block;
  font-size: 0.9rem;
  margin: 0.75rem 0 0.25rem;
  color: var(--muted);
}

input[type="text"],
input[type="password"],
input[type="number"],
input[type="date"],
input[type="email"],
select,
textarea {
  width: 100%;
  padding: 0.65rem 0.75rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text);
  font-size: 1rem;
  min-height: 44px;
}

input:focus, select:focus, textarea:focus {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

button,
label.btn-primary,
label.btn-secondary,
label.btn-ghost,
label.btn-danger,
a.btn-primary,
a.btn-secondary,
a.btn-ghost,
a.btn-danger {
  font-family: inherit;
  font-size: 1rem;
  cursor: pointer;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  padding: 0.6rem 1rem;
  min-height: 44px;
  min-width: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* Anchor buttons (e.g. Master PDF, per-category PDF links in the
     receipt-edit modal) keep their button look across all states; the
     default link underline must stay off so they read as chips, not
     hyperlinks. */
  text-decoration: none;
}
a.btn-primary:hover,
a.btn-secondary:hover,
a.btn-ghost:hover,
a.btn-danger:hover { text-decoration: none; }
button:disabled { opacity: 0.5; cursor: not-allowed; }
/* The hidden attribute must always win. The button display rule above
   otherwise overrides the user-agent [hidden] rule in engines that apply it
   without !important, which made hidden buttons (e.g. Retry Gemma on
   non-error Allocate rows) render anyway. */
button[hidden] { display: none; }

.btn-primary {
  background: var(--accent);
  color: var(--accent-text);
  border-color: var(--accent);
  font-weight: 600;
}
.btn-secondary {
  background: var(--surface);
  color: var(--text);
  border-color: var(--border);
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
}
.btn-ghost {
  background: transparent;
  border-color: transparent;
  color: var(--muted);
}
.btn-danger {
  background: var(--surface);
  color: var(--danger);
  border-color: var(--danger);
}

.row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 1rem;
  align-items: center;
}

.grid-two {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 0.75rem 1rem;
}
.grid-three {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 0.75rem 1rem;
}
.span-two { grid-column: 1 / -1; }
.row-inline {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  margin-top: 1.6rem;
  cursor: pointer;
}
.row-inline input[type="checkbox"] { margin: 0; }

.banner-error {
  margin-top: 1rem;
  padding: 0.75rem 1rem;
  background: var(--danger-bg);
  color: var(--danger);
  border: 1px solid var(--danger);
  border-radius: var(--radius);
  white-space: pre-wrap;
}

.progress {
  margin-top: 1rem;
  padding: 0.75rem 1rem;
  background: var(--warn-bg);
  color: var(--warn-text);
  border: 1px solid var(--warn-text);
  border-radius: var(--radius);
}

.toast {
  position: fixed;
  bottom: 1rem;
  left: 50%;
  transform: translateX(-50%);
  background: var(--text);
  color: var(--bg);
  padding: 0.65rem 1rem;
  border-radius: var(--radius);
  z-index: 50;
  box-shadow: var(--shadow);
}

#camera-video {
  width: 100%;
  max-height: 60vh;
  background: #000;
  border-radius: var(--radius);
  margin-top: 1rem;
}
#capture-preview {
  width: 100%;
  max-height: 60vh;
  object-fit: contain;
  background: var(--bg);
  border-radius: var(--radius);
  margin-top: 1rem;
}

#review-image-wrap {
  margin: 0.5rem 0 1rem;
  text-align: center;
}
#review-image {
  max-width: 100%;
  max-height: 50vh;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
}

.readonly-field {
  padding: 0.65rem 0.75rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  min-height: 44px;
  display: flex;
  align-items: center;
}

.ocr-details {
  margin: 1rem 0;
  background: var(--bg);
  padding: 0.5rem 0.75rem;
  border-radius: var(--radius);
  border: 1px solid var(--border);
}
.ocr-details summary { cursor: pointer; font-weight: 600; }
.ocr-details pre {
  white-space: pre-wrap;
  word-break: break-word;
  margin: 0.75rem 0 0;
  font-size: 0.85rem;
  color: var(--muted);
  max-height: 30vh;
  overflow: auto;
}

.allocations {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}
.alloc-row {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0.75rem;
  background: var(--bg);
}
.alloc-row .grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 0.5rem 0.75rem;
}

.alloc-cat optgroup {
  font-weight: 700;
  color: var(--muted);
  font-style: normal;
}

select.vat-treatment {
  min-height: 44px;
  width: 100%;
  font-size: 0.95rem;
}

.reconcile-hint {
  margin-bottom: 0.5rem;
}

.reconcile {
  justify-content: space-between;
  margin: 1rem 0;
}
.badge {
  display: inline-block;
  padding: 0.35rem 0.75rem;
  border-radius: 999px;
  font-weight: 600;
  background: var(--bg);
  border: 1px solid var(--border);
}
.badge.ok { background: #e7f6ee; color: var(--ok); border-color: var(--ok); }
.badge.bad { background: var(--danger-bg); color: var(--danger); border-color: var(--danger); }
@media (prefers-color-scheme: dark) {
  .badge.ok { background: #122a1f; }
}

.table-wrap {
  width: 100%;
  overflow-x: auto;
  margin-top: 1rem;
  /* Fade hint on the right edge when content overflows */
  background:
    linear-gradient(to right, var(--surface) 0%, transparent 2%) left,
    linear-gradient(to left,  var(--surface) 0%, transparent 2%) right;
  background-attachment: local, scroll;
  background-repeat: no-repeat;
  background-size: 40px 100%;
}
table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.95rem;
  min-width: 560px;
}
th, td {
  text-align: left;
  padding: 0.6rem 0.5rem;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}
th { font-weight: 600; color: var(--muted); }

.kv {
  display: grid;
  grid-template-columns: 200px 1fr;
  gap: 0.35rem 1rem;
  margin: 0.5rem 0 1rem;
}
.kv dt { color: var(--muted); }
.kv dd { margin: 0; word-break: break-all; }

.filters { margin-bottom: 0.5rem; }

.badge {
  display: inline-block;
  padding: 0.15rem 0.55rem;
  border-radius: 999px;
  font-size: 0.85rem;
  font-weight: 500;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
}
.badge-submitted {
  background: #ddf4dd;
  border-color: #5aa85a;
  color: #2c6b2c;
}
.badge-pending {
  background: #fff3d6;
  border-color: #d6a63c;
  color: #6b4e0f;
}
@media (prefers-color-scheme: dark) {
  .badge-submitted { background: #13361a; border-color: #2f7a3a; color: #c5e8c5; }
  .badge-pending   { background: #3a2e0d; border-color: #a6862d; color: #f0dba1; }
}

/* ---------- Categories table ---------- */
.cat-readonly {
  color: var(--text);
  font-weight: 500;
}
.cat-desc-cell { min-width: 240px; max-width: 420px; }
.cat-desc-stack {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}
textarea.cat-desc-inline {
  width: 100%;
  min-height: 2.4rem;
  resize: vertical;
  font-family: inherit;
  font-size: 0.95rem;
  padding: 0.45rem 0.6rem;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
}
.cat-desc-expand { white-space: nowrap; }

/* Make Categories table cells breathe a little so columns don't squash. */
#cat-table th, #cat-table td { padding: 0.55rem 0.7rem; vertical-align: top; }
#cat-table th { font-weight: 600; color: var(--muted); }

/* ---------- Modal (used by category description popup) ---------- */
.modal {
  position: fixed;
  inset: 0;
  background: rgba(15, 23, 42, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 50;
  padding: 1rem;
}
.modal[hidden] { display: none; }
.modal-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.25rem;
  width: min(720px, 100%);
  box-shadow: var(--shadow);
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  max-height: calc(100vh - 2rem);
  overflow-y: auto;
}
/* Receipt edit modal — wider, room for the image + allocations form. */
.receipt-edit-card { width: min(960px, 100%); }
.receipt-edit-header { justify-content: space-between; align-items: center; }
.receipt-edit-header h2 { margin: 0; }
.receipt-edit-actions { justify-content: flex-end; flex-wrap: wrap; }
.rem-image-wrap { text-align: center; }
.rem-image-wrap img {
  max-width: 100%;
  max-height: 320px;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  cursor: zoom-in;
}
.rem-section-h { margin: 0.5rem 0 0; }
.modal-card textarea {
  width: 100%;
  resize: vertical;
  font-family: inherit;
  font-size: 1rem;
  padding: 0.7rem;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
}

@media (max-width: 600px) {
  .kv { grid-template-columns: 1fr; }
  .kv dd { margin-bottom: 0.5rem; }
  main { padding: 0.5rem; }
  .card { padding: 1rem; }
}

/* ---------- Native <dialog> used for the submission reference prompt ---------- */
dialog.app-dialog {
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 1.25rem;
  width: min(420px, calc(100vw - 2rem));
  margin: auto;
}
dialog.app-dialog::backdrop {
  background: rgba(15, 23, 42, 0.55);
}
dialog.app-dialog form {
  display: flex;
  flex-direction: column;
  width: 100%;
}
dialog.app-dialog h2 {
  margin: 0 0 0.25rem;
  font-size: 1.1rem;
}
dialog.app-dialog .row {
  margin-top: 1rem;
}
dialog.app-dialog label {
  margin-top: 0.5rem;
}

/* ---------- Mobile nav (burger + off-canvas drawer) ---------- */
.nav-burger {
  display: none;
  width: 44px;
  height: 44px;
  padding: 0;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius);
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  cursor: pointer;
}
.nav-burger span {
  display: block;
  width: 22px;
  height: 2px;
  background: var(--text);
  border-radius: 2px;
}
.nav-overlay {
  position: fixed;
  inset: 0;
  background: rgba(15, 23, 42, 0.55);
  opacity: 0;
  transition: opacity 0.2s ease;
  z-index: 40;
}
.nav-overlay.open { opacity: 1; }
.nav-overlay[hidden] { display: none; }
.nav-drawer {
  position: fixed;
  top: 0;
  left: 0;
  width: min(320px, 85vw);
  height: 100dvh;
  background: var(--surface);
  border-right: 1px solid var(--border);
  box-shadow: 2px 0 12px rgba(0, 0, 0, 0.2);
  z-index: 41;
  transform: translateX(-100%);
  transition: transform 0.2s ease;
  display: flex;
  flex-direction: column;
  padding-top: env(safe-area-inset-top);
}
.nav-drawer.open { transform: translateX(0); }
.nav-drawer[hidden] { display: none; }
.nav-drawer-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1rem 1rem 0.5rem;
  border-bottom: 1px solid var(--border);
}
.nav-drawer-title { font-weight: 600; font-size: 1.05rem; }
.nav-drawer-list {
  display: flex;
  flex-direction: column;
  padding: 0.5rem 0;
  gap: 0.15rem;
  flex: 1;
}
.nav-drawer-list a {
  padding: 0.85rem 1rem;
  color: var(--text);
  font-size: 1rem;
  border-left: 3px solid transparent;
  min-height: 48px;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.nav-drawer-list a:hover { text-decoration: none; background: var(--bg); }
.nav-drawer-list a.active {
  background: var(--bg);
  border-left-color: var(--accent);
  color: var(--accent);
}
.nav-drawer-foot {
  padding: 0.75rem 1rem calc(0.75rem + env(safe-area-inset-bottom));
  border-top: 1px solid var(--border);
}
body.nav-locked { overflow: hidden; }

@media (max-width: 900px) {
  .nav-burger { display: flex; }
  #nav-desktop { display: none; }
  .topbar { gap: 0.5rem; padding: 0.55rem 0.75rem; }
  .brand { font-size: 0.95rem; }
  #nav-inbox-status { display: none; } /* shows in the drawer footer instead */
}
@media (min-width: 901px) {
  .nav-drawer, .nav-overlay { display: none !important; }
}

/* ---------- Nav badges and inbox status ---------- */
/* The main badge is the routine "N waiting for approval" count, in the
   accent colour rather than red so it does not read as urgent. When any of
   those receipts errored out, .nav-badge-has-errors adds a red ring and the
   small .nav-badge-err pill shows the failed count, so a Gemma failure is
   visibly different from a normal pending queue. */
.nav-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.2rem;
  background: var(--accent);
  color: var(--accent-text);
  border-radius: 999px;
  padding: 0.05rem 0.45rem;
  font-size: 0.75rem;
  margin-left: 0.25rem;
  min-width: 1.4rem;
  text-align: center;
}
/* `display: inline-flex` wins over the HTML [hidden] attribute. Restore. */
.nav-badge[hidden] { display: none; }
.nav-badge.nav-badge-has-errors {
  box-shadow: 0 0 0 2px var(--danger);
}
.nav-badge-err {
  display: inline-block;
  /* Not var(--danger): in dark mode that token is a light coral meant for
     text on a dark surface, and white text on it reads poorly on a small
     pill. This stays a fixed dark red in both themes for reliable contrast
     with the white text. */
  background: #b3261e;
  color: white;
  border-radius: 999px;
  padding: 0 0.35rem;
  min-width: 1rem;
  line-height: 1.35;
}
.nav-badge-err[hidden] { display: none; }
.nav-status {
  margin-left: auto;
  font-size: 0.85rem;
  color: var(--muted);
  padding: 0.15rem 0.55rem;
  border-radius: 999px;
  border: 1px solid var(--border);
  cursor: pointer;
  transition: border-color 0.15s ease, color 0.15s ease;
}
.nav-status:hover {
  border-color: var(--accent);
  color: var(--accent);
}
.nav-status-busy {
  background: #fff3d6;
  color: #6b4e0f;
  border-color: #d6a63c;
}
.nav-status-busy:hover {
  border-color: #c49020;
  color: #5a3e00;
}

/* ---------- Allocation List ---------- */
.al-group { margin-top: 1rem; }
.al-group h3 {
  margin: 0.5rem 0 0.4rem;
  font-size: 1rem;
  color: var(--muted);
}
.al-table { width: 100%; border-collapse: collapse; font-size: 0.9rem; }
.al-table th, .al-table td {
  padding: 0.5rem 0.55rem;
  /* Top-align every cell so the Payee, Date, Total Incl VAT and
     Status / Why columns stay anchored to the same baseline as the
     first allocation when the Category and Description columns
     stretch vertically with multiple allocation rows. */
  vertical-align: top;
  border-bottom: 1px solid var(--border);
  text-align: left;
}
.al-thumb {
  width: 56px;
  height: 72px;
  object-fit: cover;
  border-radius: 4px;
  border: 1px solid var(--border);
  display: inline-block;
}
.al-thumb-missing {
  color: var(--muted);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.al-desc { max-width: 280px; }
.al-reason { font-size: 0.85rem; color: var(--muted); }
.al-reason-err { color: #b42318; }

.al-cat-col { min-width: 200px; max-width: 240px; }
.al-desc-col { min-width: 220px; max-width: 360px; }
.al-stack {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}
.al-cat-select, .al-vat-select, .al-desc-input {
  width: 100%;
  font-size: 0.9rem;
  min-height: 36px;
  padding: 0.35rem 0.5rem;
}
/* The per-line amount shown under a category picker on a split receipt. */
.al-alloc-amount {
  font-size: 0.8rem;
  margin-top: -0.15rem;
}
.al-desc-input {
  resize: vertical;
  min-height: 38px;
  line-height: 1.3;
  white-space: pre-wrap;
  word-break: break-word;
}
.al-table td { white-space: normal; }
.al-table .col-check { width: 36px; text-align: center; }
.al-table .col-check input[type="checkbox"] { width: auto; min-width: 0; min-height: 0; margin: 0; }

/* ---------- Lightbox ---------- */
.lightbox-card { max-width: min(90vw, 1000px); }
.lightbox-card img { max-width: 100%; max-height: 80vh; border-radius: 4px; }

/* ---------- Browse selection column ---------- */
#br-table .col-check { width: 36px; text-align: center; }
#br-table .col-check input[type="checkbox"] { width: auto; min-width: 0; min-height: 0; margin: 0; }

/* Multi-allocation rows: stack each allocation vertically so Category and
   Description line up across cells. */
.br-alloc-stack { display: flex; flex-direction: column; gap: 0.2rem; }
.br-alloc-cell { min-width: 140px; }
.br-desc-cell { min-width: 200px; max-width: 340px; white-space: normal; word-break: break-word; }

/* Marks a receipt whose amount is shared across more than one category, so
   it does not read as fully allocated to whichever category it happens to
   group under. */
.br-split-tag {
  display: inline-block;
  margin-top: 0.3rem;
  font-size: 0.7rem;
  color: var(--muted);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0.05rem 0.45rem;
}

.br-thumb {
  width: 48px;
  height: 64px;
  object-fit: cover;
  border-radius: 4px;
  border: 1px solid var(--border);
  display: inline-block;
}
.br-thumb-missing {
  color: var(--muted);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 64px;
}

/* Month + category grouping in the Browse table. Header rows span every
   column and sit visually above their cohort of receipt rows. Month rows
   use a strong solid rule in --text (near-black / near-white depending on
   theme); category rows use a dashed rule in the same colour so the
   hierarchy reads at a glance. */
#br-table tr.br-group-month > td {
  background: var(--bg);
  font-weight: 600;
  font-size: 1rem;
  padding: 0.65rem 0.75rem;
  border-top: 3px solid var(--text);
  border-bottom: 2px solid var(--text);
}
#br-table tr.br-group-cat > td {
  background: var(--surface);
  font-weight: 500;
  font-size: 0.9rem;
  color: var(--muted);
  padding: 0.4rem 0.75rem 0.4rem 1.75rem;
  border-top: 1px dashed var(--text);
  border-bottom: 1px dashed var(--text);
}

/* ---------- Category combobox ---------- */
.cat-combo {
  position: relative;
  display: block;
  width: 100%;
}
.cat-combo-input {
  width: 100%;
  padding-right: 1.9rem;
  box-sizing: border-box;
}
.cat-combo-toggle {
  position: absolute;
  right: 4px;
  top: 50%;
  transform: translateY(-50%);
  width: 1.6rem;
  height: 1.6rem;
  border: none;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  padding: 0;
  font-size: 0.95rem;
  line-height: 1;
}
.cat-combo-toggle:hover {
  color: var(--text);
}
.cat-combo-list {
  position: absolute;
  top: calc(100% + 2px);
  left: 0;
  right: 0;
  max-height: 280px;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  z-index: 40;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
}
.cat-combo-group {
  padding: 0.3rem 0.6rem;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  background: var(--bg);
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
}
.cat-combo-option {
  padding: 0.4rem 0.75rem;
  cursor: pointer;
  font-size: 0.9rem;
  color: var(--text);
}
.cat-combo-option:hover,
.cat-combo-option:focus {
  background: var(--bg);
}
.cat-combo-empty {
  padding: 0.4rem 0.75rem;
  color: var(--muted);
  font-style: italic;
}

/* Inline editables on the Allocation List. Compact widths so payee/date/total
   do not push the grid out of shape. */
.al-payee-input { width: 100%; min-width: 130px; }
.al-date-input { width: 100%; min-width: 110px; font-variant-numeric: tabular-nums; }
.al-total-input { width: 100%; min-width: 90px; text-align: right; font-variant-numeric: tabular-nums; }

/* ---------- Collapsible filter group ---------- */
.filters-collapse {
  margin: 0.5rem 0 1rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  padding: 0.25rem 0.75rem 0.5rem;
}
.filters-collapse > summary {
  cursor: pointer;
  padding: 0.5rem 0;
  font-weight: 600;
  min-height: 44px;
  display: flex;
  align-items: center;
  list-style: none;
}
.filters-collapse > summary::-webkit-details-marker { display: none; }
.filters-collapse > summary::before {
  content: "";
  display: inline-block;
  margin-right: 0.5rem;
  width: 0;
  height: 0;
  border-left: 6px solid var(--muted);
  border-top: 4px solid transparent;
  border-bottom: 4px solid transparent;
  transition: transform 0.15s ease;
}
.filters-collapse[open] > summary::before { transform: rotate(90deg); }
.filters-collapse .filters { margin-bottom: 0.25rem; }

/* ---------- Sticky bulk-submit bar ---------- */
.bulk-bar {
  position: sticky;
  bottom: 0;
  left: 0;
  right: 0;
  margin: 1rem -1.25rem -1.25rem;
  padding: 0.75rem 1.25rem calc(0.75rem + env(safe-area-inset-bottom));
  background: var(--surface);
  border-top: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  z-index: 20;
}
.bulk-bar[hidden] { display: none; }
.bulk-count { font-weight: 600; color: var(--muted); }
.bulk-actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}

@media (max-width: 700px) {
  .filters-collapse:not([open]) .filters { display: none; }
  .grid-three.filters { grid-template-columns: 1fr; }
  .bulk-bar .bulk-actions { flex: 1; justify-content: flex-end; }
  .bulk-bar .bulk-actions .btn-primary { flex: 1; }
  h1 { font-size: 1.25rem; }
  h2 { font-size: 1.05rem; margin-top: 1rem; }
  .card { padding: 0.85rem; margin-bottom: 0.75rem; }
  #review-image, #camera-video, #capture-preview { max-height: 52vh; }
  /* Collapse Categories table to card rows: each <tr> becomes a stacked block,
     each <td> grows its own label so users can scan fields without horizontal scroll. */
  #cat-table thead { display: none; }
  #cat-table tr {
    display: block;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    margin-bottom: 0.75rem;
    padding: 0.5rem 0.75rem;
    background: var(--surface);
  }
  #cat-table td {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 0.75rem;
    padding: 0.4rem 0;
    border-bottom: 1px dashed var(--border);
  }
  #cat-table td:last-child { border-bottom: none; }
  #cat-table td::before {
    content: attr(data-label);
    color: var(--muted);
    font-size: 0.82rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    flex-shrink: 0;
  }
  #cat-table td > * { flex: 1; min-width: 0; }
}

/* ---------- Mobile cards: Allocate + Browse tables ---------- */
/* Below 700px both receipt tables trade the wide horizontal-scroll grid for
   stacked card rows so every control (Approve / Retry / Full edit / Delete,
   Edit, checkboxes) is reachable without sideways scrolling. The DOM stays
   the same table; tr/td only switch display type, so in-place row removal,
   bulk selection state and the thumbnail lightbox keep working unchanged. */
@media (max-width: 700px) {
  .al-table,
  #br-table { display: block; width: 100%; min-width: 0; }
  .al-table thead,
  #br-table thead { display: none; }
  .al-table tbody,
  #br-table tbody { display: block; width: 100%; }
  .al-table .col-check,
  #br-table .col-check { width: auto; }

  /* ----- Allocate: one card per proposal ----- */
  /* Grid map: row 1 = checkbox | thumb | payee, row 2 = date + total under
     the payee, rows 3+ = category / description / VAT / status / buttons
     spanning the full card width. The thumb spans rows 1-2. */
  .al-table tbody tr {
    display: grid;
    grid-template-columns: 24px 60px 1fr 1fr;
    gap: 0.45rem 0.5rem;
    align-items: start;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    padding: 0.6rem;
    margin-bottom: 0.65rem;
  }
  .al-table tbody td {
    display: block;
    border-bottom: none;
    padding: 0;
    min-width: 0;
    max-width: none;
  }
  .al-table tbody td:nth-child(1) { grid-column: 1; grid-row: 1; padding-top: 0.55rem; }
  .al-table tbody td:nth-child(2) { grid-column: 2; grid-row: 1 / 3; }
  .al-table tbody td:nth-child(3) { grid-column: 3 / 5; grid-row: 1; }
  .al-table tbody td:nth-child(4) { grid-column: 3; grid-row: 2; }
  .al-table tbody td:nth-child(5) { grid-column: 4; grid-row: 2; }
  .al-table tbody td:nth-child(n+6) { grid-column: 1 / -1; }
  /* Compact header inputs so dd/mm/yyyy and the total fit their half-width
     columns. Scoped under .al-table to outrank the global input rules. */
  .al-table .al-payee-input,
  .al-table .al-date-input,
  .al-table .al-total-input {
    min-width: 0;
    min-height: 40px;
    padding: 0.45rem 0.5rem;
  }
  .al-table .al-date-input,
  .al-table .al-total-input { font-size: 0.95rem; }
  /* Status line reads inline: "Status: Ready". */
  .al-table tbody td:nth-child(9)::before {
    content: "Status: ";
    color: var(--muted);
    font-size: 0.85rem;
  }
  /* Action buttons share the card width and wrap when Retry appears. */
  .al-table tbody td:nth-child(10) .row { margin-top: 0.1rem; }
  .al-table tbody td:nth-child(10) .row button { flex: 1 1 auto; }

  /* ----- Browse: one compact card per receipt ----- */
  /* Grid map: row 1 = checkbox | thumb | payee, row 2 = date, rows 3+ =
     category / description / VAT full width, footer row = total |
     submission chip | Edit. Month and category group headers stay plain
     full-width bars (overrides further down). */
  #br-table tbody tr {
    display: grid;
    grid-template-columns: 24px 56px 1fr auto;
    gap: 0.35rem 0.5rem;
    align-items: start;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    padding: 0.6rem;
    margin-bottom: 0.65rem;
  }
  #br-table tbody td {
    display: block;
    border-bottom: none;
    padding: 0;
    min-width: 0;
    max-width: none;
  }
  #br-table tbody td:nth-child(1) { grid-column: 1; grid-row: 1; padding-top: 0.15rem; }
  #br-table tbody td:nth-child(2) { grid-column: 2; grid-row: 1 / 3; }
  #br-table tbody td:nth-child(4) { grid-column: 3 / 5; grid-row: 1; font-weight: 600; }
  #br-table tbody td:nth-child(3) { grid-column: 3 / 5; grid-row: 2; font-size: 0.85rem; color: var(--muted); }
  #br-table tbody td:nth-child(5) { grid-column: 1 / -1; font-weight: 500; }
  #br-table tbody td:nth-child(6) { grid-column: 1 / -1; font-size: 0.9rem; }
  #br-table tbody td:nth-child(7) { grid-column: 1 / -1; font-size: 0.8rem; color: var(--muted); }
  #br-table tbody td:nth-child(7)::before { content: "VAT: "; }
  #br-table tbody td:nth-child(8) { grid-column: 1 / 3; align-self: center; font-weight: 600; }
  #br-table tbody td:nth-child(8)::before { content: "R "; color: var(--muted); font-weight: 400; }
  #br-table tbody td:nth-child(9) { grid-column: 3; align-self: center; }
  #br-table tbody td:nth-child(10) { grid-column: 4; justify-self: end; }

  /* Section labels above the stacked Allocate fields. */
  .al-table tbody td:nth-child(4)::before,
  .al-table tbody td:nth-child(5)::before,
  .al-table tbody td:nth-child(6)::before,
  .al-table tbody td:nth-child(7)::before,
  .al-table tbody td:nth-child(8)::before {
    content: "";
    display: block;
    color: var(--muted);
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin-bottom: 0.2rem;
  }
  .al-table tbody td:nth-child(4)::before { content: "Date"; }
  .al-table tbody td:nth-child(5)::before { content: "Total incl"; }
  .al-table tbody td:nth-child(6)::before { content: "Category"; }
  .al-table tbody td:nth-child(7)::before { content: "Description"; }
  .al-table tbody td:nth-child(8)::before { content: "VAT"; }

  /* Month / category group headers keep their full-width divider look. */
  #br-table tbody tr.br-group-month,
  #br-table tbody tr.br-group-cat {
    display: block;
    border: none;
    border-radius: 0;
    background: none;
    padding: 0;
    margin: 0 0 0.65rem;
  }
  #br-table tbody tr.br-group-month { margin-top: 0.75rem; }
  #br-table tbody tr.br-group-month > td,
  #br-table tbody tr.br-group-cat > td { display: block; }
  #br-table tbody tr.br-group-cat > td { padding-left: 0.75rem; }

  /* Placeholder rows ("No receipts found.") span the whole card. */
  #br-table tbody td[colspan] {
    grid-column: 1 / -1;
    grid-row: auto;
    padding: 0;
  }

  /* Align the sticky bulk bar with the 0.85rem card padding used below
     700px so it no longer bleeds past the card edge. */
  .bulk-bar {
    margin: 0.75rem -0.85rem -0.85rem;
    padding: 0.6rem 0.85rem calc(0.6rem + env(safe-area-inset-bottom));
  }
}

/* ---------- Capture screen: tertiary "Advanced camera" entry ---------- */
.capture-advanced {
  margin-top: 0.5rem;
}
.capture-advanced .btn-ghost {
  padding-left: 0.25rem;
  padding-right: 0.25rem;
}
.capture-advanced-hint {
  margin: 0.1rem 0 0 0.25rem;
  font-size: 0.8rem;
}

/* ---------- Camera controls (zoom slider, corner handles) ---------- */
.camera-stage {
  position: relative;
  margin-top: 1rem;
}
.camera-controls {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-top: 0.5rem;
  flex-wrap: wrap;
}
.camera-controls label {
  margin: 0;
  font-size: 0.85rem;
  color: var(--muted);
}
.camera-controls input[type="range"] {
  flex: 1;
  min-width: 140px;
}
.camera-hint {
  font-size: 0.85rem;
  color: var(--muted);
}

.camera-reticle {
  position: absolute;
  top: 10%;
  left: 10%;
  right: 10%;
  bottom: 10%;
  pointer-events: none;
  z-index: 10;
  opacity: 0.7;
  transition: opacity 0.2s ease, border-color 0.2s ease;
  display: flex;
}
.camera-reticle.active {
  opacity: 1;
}
.camera-reticle .tl, .camera-reticle .tr, .camera-reticle .bl, .camera-reticle .br {
  position: absolute;
  width: 40px;
  height: 40px;
  border: 4px solid #fff;
}
.camera-reticle.active .tl, .camera-reticle.active .tr, .camera-reticle.active .bl, .camera-reticle.active .br {
  border-color: #34d399; /* Green when autocapture is locking on */
}
.camera-reticle .tl { top: 0; left: 0; border-right: none; border-bottom: none; }
.camera-reticle .tr { top: 0; right: 0; border-left: none; border-bottom: none; }
.camera-reticle .bl { bottom: 0; left: 0; border-right: none; border-top: none; }
.camera-reticle .br { bottom: 0; right: 0; border-left: none; border-top: none; }

/* ---------- Submissions screen ---------- */
.sub-filter-row label {
  font-size: 0.85rem;
  color: var(--muted);
}
/* Override the global "select { width: 100% }" rule. Without this the
   dropdown stretches to fill the flex row and bumps Refresh onto a
   second line. The select sits inline with its label and the button. */
.sub-filter-row select {
  width: auto;
  min-width: 14rem;
  max-width: 22rem;
}
.sub-filter-row .sub-show-archived {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  cursor: pointer;
  user-select: none;
}
.sub-filter-row .sub-show-archived input[type="checkbox"] {
  margin: 0;
}
/* Archived batch cards: muted so the user's eye lands on what still
   needs to be processed in the accounting system. */
.sub-batch.archived {
  opacity: 0.65;
}
.sub-batch.archived .sub-batch-head {
  background: var(--surface-alt, var(--surface));
}
.sub-fy-group {
  margin-bottom: 2rem;
}
.sub-fy-heading {
  font-size: 1rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
  margin: 0 0 0.75rem;
  padding-bottom: 0.35rem;
  border-bottom: 1px solid var(--border);
}
.sub-month-group {
  margin-bottom: 1.5rem;
}
.sub-month-heading {
  font-size: 1rem;
  font-weight: 600;
  color: var(--fg);
  margin: 0 0 0.5rem;
}
.sub-batch {
  border: 1px solid var(--border);
  border-radius: 8px;
  margin-bottom: 0.75rem;
  overflow: hidden;
}
.sub-batch-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem 1.25rem;
  padding: 0.75rem 1rem 0.5rem;
  background: var(--surface);
}
.sub-batch-title {
  font-weight: 600;
  font-size: 0.95rem;
  flex: 1 1 auto;
}
.sub-batch-meta {
  font-size: 0.82rem;
  color: var(--muted);
  white-space: nowrap;
}
.sub-batch-totals {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.5rem;
  padding: 0.4rem 1rem;
  background: var(--surface-alt, var(--surface));
  border-top: 1px solid var(--border);
  font-size: 0.85rem;
}
.sub-batch-totals span {
  color: var(--muted);
}
.sub-batch-totals strong {
  margin-left: 0.2em;
}
.sub-batch-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  padding: 0.6rem 1rem;
  border-top: 1px solid var(--border);
}
details.sub-cats {
  padding: 0.5rem 1rem 0.75rem;
  border-top: 1px solid var(--border);
}
details.sub-cats > summary {
  cursor: pointer;
  font-size: 0.85rem;
  color: var(--muted);
  padding: 0.25rem 0;
  user-select: none;
  list-style: none;
}
details.sub-cats > summary::-webkit-details-marker { display: none; }
details.sub-cats > summary::before { content: "› "; font-weight: 700; }
details.sub-cats[open] > summary::before { content: "v "; }
.sub-cat-table {
  width: 100%;
  border-collapse: collapse;
  margin-top: 0.5rem;
  font-size: 0.85rem;
}
.sub-cat-table th,
.sub-cat-table td {
  text-align: left;
  padding: 0.25rem 0.5rem;
  border-bottom: 1px solid var(--border);
}
.sub-cat-table th {
  font-weight: 600;
  color: var(--muted);
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.sub-cat-table td.sub-num,
.sub-cat-table th.sub-num {
  text-align: right;
}
.sub-cat-link {
  font-size: 0.82rem;
  color: var(--accent, #2563eb);
  text-decoration: none;
}
.sub-cat-link:hover { text-decoration: underline; }
.sub-cat-link.missing {
  color: var(--muted);
  pointer-events: none;
  text-decoration: none;
}
#sub-list:empty::after {
  content: "No submitted batches found.";
  display: block;
  color: var(--muted);
  font-size: 0.9rem;
  padding: 1rem 0;
}

/* ---------- Capture status bar ---------- */
.capture-status-bar {
  display: flex;
  gap: 1rem;
  margin-top: 0.75rem;
}
.capture-status-item {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.2rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1rem;
  text-decoration: none;
  color: var(--text);
  box-shadow: var(--shadow);
  transition: border-color 0.15s ease;
}
.capture-status-item:hover {
  border-color: var(--accent);
  text-decoration: none;
}
.capture-status-num {
  font-size: 2rem;
  font-weight: 700;
  line-height: 1;
  color: var(--accent);
}
.capture-status-label {
  font-size: 0.85rem;
  color: var(--muted);
}
