:root {
  --background: oklch(1 0 0);
  --foreground: oklch(0.147 0.004 49.25);
  --card: oklch(1 0 0);
  --card-foreground: oklch(0.147 0.004 49.25);
  --popover: oklch(1 0 0);
  --popover-foreground: oklch(0.147 0.004 49.25);
  --primary: oklch(0.553 0.195 38.402);
  --primary-foreground: oklch(0.98 0.016 73.684);
  --secondary: oklch(0.967 0.001 286.375);
  --secondary-foreground: oklch(0.21 0.006 285.885);
  --muted: oklch(0.97 0.001 106.424);
  --muted-foreground: oklch(0.553 0.013 58.071);
  --accent: oklch(0.97 0.001 106.424);
  --accent-foreground: oklch(0.216 0.006 56.043);
  --destructive: oklch(0.577 0.245 27.325);
  --border: oklch(0.923 0.003 48.717);
  --input: oklch(0.923 0.003 48.717);
  --ring: oklch(0.709 0.01 56.259);
  --chart-1: oklch(0.845 0.143 164.978);
  --chart-2: oklch(0.696 0.17 162.48);
  --chart-3: oklch(0.596 0.145 163.225);
  --chart-4: oklch(0.508 0.118 165.612);
  --chart-5: oklch(0.432 0.095 166.913);
  --radius: 0.625rem;
  --radius-sm: calc(var(--radius) - 4px);
  --radius-md: calc(var(--radius) - 2px);
  --radius-lg: var(--radius);
  --radius-xl: calc(var(--radius) + 4px);
  --sidebar: oklch(0.985 0.001 106.423);
  --sidebar-foreground: oklch(0.147 0.004 49.25);
  --sidebar-primary: oklch(0.646 0.222 41.116);
  --sidebar-primary-foreground: oklch(0.98 0.016 73.684);
  --sidebar-accent: oklch(0.97 0.001 106.424);
  --sidebar-accent-foreground: oklch(0.216 0.006 56.043);
  --sidebar-border: oklch(0.923 0.003 48.717);
  --sidebar-ring: oklch(0.709 0.01 56.259);
}

/* Automatic (system-preference) dark mode, unless the toggle below has set an
   explicit choice. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --background: oklch(0.147 0.004 49.25);
    --foreground: oklch(0.985 0.001 106.423);
    --card: oklch(0.216 0.006 56.043);
    --card-foreground: oklch(0.985 0.001 106.423);
    --popover: oklch(0.216 0.006 56.043);
    --popover-foreground: oklch(0.985 0.001 106.423);
    --primary: oklch(0.47 0.157 37.304);
    --primary-foreground: oklch(0.98 0.016 73.684);
    --secondary: oklch(0.274 0.006 286.033);
    --secondary-foreground: oklch(0.985 0 0);
    --muted: oklch(0.268 0.007 34.298);
    --muted-foreground: oklch(0.709 0.01 56.259);
    --accent: oklch(0.268 0.007 34.298);
    --accent-foreground: oklch(0.985 0.001 106.423);
    --destructive: oklch(0.704 0.191 22.216);
    --border: oklch(1 0 0 / 10%);
    --input: oklch(1 0 0 / 15%);
    --ring: oklch(0.553 0.013 58.071);
    --sidebar: oklch(0.216 0.006 56.043);
    --sidebar-foreground: oklch(0.985 0.001 106.423);
    --sidebar-primary: oklch(0.705 0.213 47.604);
    --sidebar-primary-foreground: oklch(0.98 0.016 73.684);
    --sidebar-accent: oklch(0.268 0.007 34.298);
    --sidebar-accent-foreground: oklch(0.985 0.001 106.423);
    --sidebar-border: oklch(1 0 0 / 10%);
    --sidebar-ring: oklch(0.553 0.013 58.071);
  }
}

/* Explicit dark mode from the toolbar toggle, regardless of system preference. */
:root[data-theme="dark"] {
  --background: oklch(0.147 0.004 49.25);
  --foreground: oklch(0.985 0.001 106.423);
  --card: oklch(0.216 0.006 56.043);
  --card-foreground: oklch(0.985 0.001 106.423);
  --popover: oklch(0.216 0.006 56.043);
  --popover-foreground: oklch(0.985 0.001 106.423);
  --primary: oklch(0.47 0.157 37.304);
  --primary-foreground: oklch(0.98 0.016 73.684);
  --secondary: oklch(0.274 0.006 286.033);
  --secondary-foreground: oklch(0.985 0 0);
  --muted: oklch(0.268 0.007 34.298);
  --muted-foreground: oklch(0.709 0.01 56.259);
  --accent: oklch(0.268 0.007 34.298);
  --accent-foreground: oklch(0.985 0.001 106.423);
  --destructive: oklch(0.704 0.191 22.216);
  --border: oklch(1 0 0 / 10%);
  --input: oklch(1 0 0 / 15%);
  --ring: oklch(0.553 0.013 58.071);
  --sidebar: oklch(0.216 0.006 56.043);
  --sidebar-foreground: oklch(0.985 0.001 106.423);
  --sidebar-primary: oklch(0.705 0.213 47.604);
  --sidebar-primary-foreground: oklch(0.98 0.016 73.684);
  --sidebar-accent: oklch(0.268 0.007 34.298);
  --sidebar-accent-foreground: oklch(0.985 0.001 106.423);
  --sidebar-border: oklch(1 0 0 / 10%);
  --sidebar-ring: oklch(0.553 0.013 58.071);
}

/* Legacy aliases used throughout this file, mapped onto the theme tokens
   above so every component picks up the shadcn palette automatically. */
:root {
  --bg: var(--background);
  --panel: var(--card);
  --text: var(--foreground);
  --danger: var(--destructive);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 15px/1.5 system-ui, -apple-system, "Segoe UI", sans-serif;
}

.topbar {
  display: flex;
  align-items: baseline;
  gap: 24px;
  padding: 14px 24px;
  background: var(--panel);
  border-bottom: 1px solid var(--border);
}

.brand { font-weight: 700; font-size: 18px; text-decoration: none; color: var(--text); }
.topbar nav { display: flex; gap: 16px; }
.topbar a { color: var(--muted-foreground); text-decoration: none; }
/* .topbar a otherwise beats .btn's specificity and washes the CTA out to
   muted-foreground, which is illegible on the primary-colored background. */
.topbar .btn { color: var(--primary-foreground); }
.topbar nav a:hover { color: var(--primary); }

/* The panel is transparent to layout here so the bar stays one flex row; the
   phone rules below turn it into the collapsible menu. */
.nav-panel { display: contents; }
.nav-toggle { display: none; }

.theme-toggle {
  margin-left: auto;
  padding: 6px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--secondary);
  color: var(--secondary-foreground);
  font: inherit;
  font-size: 13px;
  cursor: pointer;
}
.theme-toggle:hover { background: var(--accent); color: var(--accent-foreground); }

main { max-width: 960px; margin: 0 auto; padding: 24px; }

.site-footer {
  max-width: 960px;
  margin: 0 auto;
  padding: 16px 24px 32px;
  font-size: 6px;
  color: var(--muted-foreground);
}
.site-footer a { color: inherit; }

h1 { font-size: 22px; margin: 0 0 16px; }
h2 { font-size: 15px; margin: 24px 0 8px; color: var(--muted-foreground); text-transform: uppercase; letter-spacing: .04em; }

.panel {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 20px;
}

.toolbar { display: flex; gap: 12px; align-items: end; margin-bottom: 16px; flex-wrap: wrap; }
.toolbar .field { margin: 0; }
.spacer { flex: 1; }

.field { margin-bottom: 14px; }
.field label { display: block; font-size: 13px; color: var(--muted-foreground); margin-bottom: 4px; }
.field .help { font-size: 12px; color: var(--muted-foreground); margin-top: 4px; }
.field .errors { color: var(--destructive); font-size: 13px; margin: 4px 0 0; padding-left: 16px; }

.input, .select {
  width: 100%;
  padding: 7px 9px;
  border: 1px solid var(--input);
  border-radius: var(--radius-md);
  background: var(--background);
  font: inherit;
  color: inherit;
}
.input:focus, .select:focus { outline: 2px solid var(--ring); outline-offset: -1px; }

/* Type-to-filter dropdown over a hidden <select>; see static/js/combobox.js. */
.combobox { position: relative; }
.combobox-list {
  position: absolute;
  z-index: 20;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  max-height: 240px;
  overflow-y: auto;
  margin: 0;
  padding: 4px;
  list-style: none;
  background: var(--popover);
  color: var(--popover-foreground);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: 0 6px 20px oklch(0 0 0 / 12%);
}
.combobox-list[hidden] { display: none; }
.combobox-option { padding: 7px 9px; border-radius: var(--radius-sm); cursor: pointer; }
.combobox-option.active { background: var(--accent); color: var(--accent-foreground); }
.combobox-option[aria-selected="true"] { font-weight: 600; }
.combobox-empty { padding: 7px 9px; font-size: 13px; color: var(--muted-foreground); }

.grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 16px; }
.grid .full { grid-column: 1 / -1; }

.stat-cards { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin-bottom: 16px; }
.stat-card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.stat-label { font-size: 12px; color: var(--muted-foreground); text-transform: uppercase; letter-spacing: .04em; }
.stat-value { font-size: 20px; font-weight: 600; }

.checkbox { display: flex; align-items: center; gap: 8px; }
.checkbox label { margin: 0; }

.btn {
  padding: 8px 16px;
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  background: var(--primary);
  color: var(--primary-foreground);
  font: inherit;
  cursor: pointer;
  text-decoration: none;
  display: inline-block;
}
.btn.secondary { background: var(--secondary); color: var(--secondary-foreground); border-color: var(--border); }
.btn:disabled { opacity: .6; cursor: progress; }

table { width: 100%; border-collapse: collapse; background: var(--panel); }
th, td { text-align: left; padding: 10px 12px; border-bottom: 1px solid var(--border); }
th { font-size: 12px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted-foreground); }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }
td .help { font-size: 12px; font-weight: 400; color: var(--muted-foreground); }
tbody tr:last-child td { border-bottom: none; }
.table-wrap { border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden; }

th.sortable { padding: 0; }
th.sortable a {
  display: block;
  padding: 10px 12px;
  color: inherit;
  text-decoration: none;
  white-space: nowrap;
}
th.sortable a:hover { color: var(--foreground); }
th.sortable.sorted-asc, th.sortable.sorted-desc { color: var(--primary); }
.sort-arrow { font-size: 10px; }

.tag { font-size: 12px; padding: 2px 8px; border-radius: 999px; background: var(--muted); color: var(--muted-foreground); }
.tag.income { background: color-mix(in oklab, var(--chart-2) 20%, var(--background)); color: var(--chart-4); }
.tag.expense { background: color-mix(in oklab, var(--destructive) 15%, var(--background)); color: var(--destructive); }
.tag.savings { background: color-mix(in oklab, var(--chart-2) 30%, var(--background)); color: var(--chart-4); }

.muted-row { opacity: .55; }

/* Compact phone list for transactions: hidden on wide screens, where the full
   table (.tx-table-wrap) is shown instead — see the max-width:720px rule. */
.tx-cards { display: none; }
.tx-date-header {
  padding: 14px 2px 6px;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--muted-foreground);
}
.tx-date-header:first-child { padding-top: 2px; }
.tx-card {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  margin-bottom: 8px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  color: inherit;
  text-decoration: none;
}
.tx-card-info { min-width: 0; flex: 1; }
.tx-vendor { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tx-notes { font-size: 12px; color: var(--muted-foreground); margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tx-tags { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 6px; }
.tx-card-amount { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }
.tx-total { font-variant-numeric: tabular-nums; font-weight: 600; }
.tx-arrow { color: var(--muted-foreground); font-size: 18px; line-height: 1; }

.empty { padding: 32px; text-align: center; color: var(--muted-foreground); }
.nonfield { color: var(--destructive); margin: 0 0 12px; }
.funds-warning { margin: 6px 0 0; }
.htmx-request .indicator { visibility: visible; }
.indicator { visibility: hidden; color: var(--muted-foreground); font-size: 13px; }
[x-cloak] { display: none !important; }

.row { display: flex; gap: 8px; align-items: center; }
.row .select { flex: 1; }
.nowrap { white-space: nowrap; }

.subpanel {
  margin-top: 12px;
  padding: 14px;
  border: 1px dashed var(--border);
  border-radius: var(--radius-md);
  background: var(--muted);
}
.subpanel .field:last-of-type { margin-bottom: 12px; }

.auth-card { max-width: 380px; margin: 48px auto; }
.auth-card h1 { margin-bottom: 18px; }
.auth-card .btn { width: 100%; }

.logout { display: flex; align-items: baseline; gap: 12px; margin: 0; }
.who { color: var(--muted-foreground); font-size: 13px; }
.linkbtn {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  color: var(--muted-foreground);
  cursor: pointer;
}
.linkbtn:hover { color: var(--primary); }

/* ---------------------------------------------------------------------------
   Amount-prefixed inputs and label rows, shared by several forms
   --------------------------------------------------------------------------- */

/* Amount and other prefixed inputs: the symbol sits inside the field's shell. */
.affix { position: relative; }
.affix .sign {
  position: absolute;
  left: 10px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--muted-foreground);
  font-size: 15px;
  pointer-events: none;
}
.affix .input { padding-left: 22px; }

.label-row { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.label-row label { margin-bottom: 0 !important; }
.label-row .side-link {
  font-size: 13px;
  font-weight: 600;
  color: var(--primary);
  text-decoration: underline;
}

/* ---------------------------------------------------------------------------
   Transaction flow (details step, then the optional photo step)
   --------------------------------------------------------------------------- */

/* A split is one budget item and its share of the receipt, with the amount kept
   narrow so the pair reads as a single line. */
.split-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 140px 32px;
  gap: 12px;
  align-items: start;
}
.split-row .field { margin-bottom: 14px; }
.row-remove {
  align-self: center;
  margin-top: 12px;
  width: 32px;
  height: 32px;
  border: none;
  border-radius: 50%;
  background: var(--secondary);
  color: var(--muted-foreground);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
}
.row-remove:hover { background: var(--accent); color: var(--destructive); }

.add-split { margin-top: 4px; }

/* A split's manually entered line items, nested inside its row. */
.items-block { grid-column: 1 / -1; margin: -4px 0 12px; }
.items-block .items-label { font-size: 12px; color: var(--muted-foreground); margin-bottom: 8px; }
.item-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 90px 130px 28px;
  gap: 8px;
  align-items: center;
  margin-bottom: 8px;
}
.item-row .row-remove { width: 28px; height: 28px; margin-top: 0; font-size: 15px; }
.btn.small { padding: 5px 12px; font-size: 13px; }
.add-item { margin-top: 2px; }

input[type="file"] {
  width: 100%;
  padding: 7px 9px;
  border: 1px solid var(--input);
  border-radius: var(--radius-md);
  background: var(--background);
  font: inherit;
  color: inherit;
}

.skip { display: block; text-decoration: none; margin-top: 12px; color: var(--muted-foreground); }
.skip:hover { color: var(--primary); }

.receipt-summary {
  padding: 14px 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--muted);
  margin-bottom: 20px;
}
.receipt-line { display: flex; justify-content: space-between; font-size: 18px; }
.receipt-splits { list-style: none; margin: 12px 0 0; padding: 12px 0 0; border-top: 1px solid var(--border); }
.receipt-splits li { display: flex; justify-content: space-between; font-size: 14px; color: var(--muted-foreground); }

.thumbs { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 24px; }
.thumbs img {
  width: 88px;
  height: 88px;
  object-fit: cover;
  border-radius: var(--radius-md);
  border: 1px solid var(--border);
}

.thumb { position: relative; }
.thumb form { margin: 0; }
.thumb-delete {
  position: absolute;
  top: 4px;
  right: 4px;
  width: 24px;
  height: 24px;
  padding: 0;
  display: grid;
  place-items: center;
  border: none;
  border-radius: 50%;
  background: rgba(0, 0, 0, .65);
  color: #fff;
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
}
.thumb-delete:hover { background: #b91c1c; }

.muted-link { color: var(--muted-foreground); }
button.muted-link {
  background: none;
  border: none;
  padding: 0;
  margin-left: 10px;
  font: inherit;
  cursor: pointer;
  text-decoration: none;
}
.danger-link { color: var(--danger); }
.danger-link:hover { text-decoration: underline; }

/* ---------------------------------------------------------------------------
   Month calendar of planned budget items
   --------------------------------------------------------------------------- */

.cal-head { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; }
.cal-head h1 { margin: 0; }
.cal-nav { display: flex; gap: 8px; }

.cal-totals { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 16px; }
.cal-total {
  flex: 1 1 140px;
  padding: 10px 14px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
}
.cal-total strong { display: block; font-size: 18px; font-variant-numeric: tabular-nums; }
.cal-total-label { font-size: 12px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted-foreground); }
.amt-pos { color: var(--chart-4); }
.amt-neg { color: var(--destructive); }

.progress-section-title { margin: 24px 0 10px; font-size: 15px; }
.progress-section-title:first-of-type { margin-top: 0; }

.cal-totals.smoothed { align-items: center; opacity: .85; }
.cal-totals-caption {
  flex: 1 1 100%;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--muted-foreground);
}

.cal {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 1px;
  background: var(--border);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
.cal-weekday {
  background: var(--panel);
  padding: 8px;
  text-align: center;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--muted-foreground);
}
.cal-day { background: var(--panel); min-height: 104px; padding: 6px; }
.cal-day.outside { background: var(--muted); color: var(--muted-foreground); }
.cal-day.today .cal-date {
  background: var(--primary);
  color: var(--primary-foreground);
  border-radius: 50%;
  width: 22px;
  height: 22px;
  display: grid;
  place-items: center;
}
.cal-date { font-size: 12px; color: var(--muted-foreground); margin-bottom: 4px; }

.cal-item {
  display: flex;
  justify-content: space-between;
  gap: 6px;
  padding: 2px 6px;
  margin-bottom: 3px;
  border-radius: var(--radius-sm);
  font-size: 12px;
  text-decoration: none;
  background: var(--muted);
  color: var(--muted-foreground);
}
.cal-item.income { background: color-mix(in oklab, var(--chart-2) 20%, var(--background)); color: var(--chart-4); }
.cal-item.expense { background: color-mix(in oklab, var(--destructive) 15%, var(--background)); color: var(--destructive); }
.cal-item.savings { background: color-mix(in oklab, var(--chart-2) 30%, var(--background)); color: var(--chart-4); }
.cal-item-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cal-item-amount { font-variant-numeric: tabular-nums; }

@media (max-width: 720px) {
  .cal-day { min-height: 76px; }
  .cal-item-name { display: none; }
  .split-row { grid-template-columns: minmax(0, 1fr) 110px 28px; }
}

/* ---------------------------------------------------------------------------
   Phones and small tablets

   The bar collapses behind a menu button, the wide data tables restack as
   labelled cards, and every field goes full width. Inputs are bumped to 16px
   because iOS Safari zooms the page in on any smaller focused field.
   --------------------------------------------------------------------------- */

@media (max-width: 720px) {
  main { padding: 16px; }

  .topbar {
    flex-wrap: wrap;
    align-items: center;
    gap: 12px;
    padding: 12px 16px;
  }

  .nav-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin-left: auto;
    width: 44px;
    height: 44px;
    padding: 0;
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    background: none;
    color: var(--text);
    cursor: pointer;
  }
  /* Three bars drawn from one element: the middle is the box, the outer two its
     before/after, so the button needs no extra markup. */
  .nav-toggle-bars,
  .nav-toggle-bars::before,
  .nav-toggle-bars::after {
    display: block;
    width: 18px;
    height: 2px;
    border-radius: 2px;
    background: currentColor;
  }
  .nav-toggle-bars { position: relative; }
  .nav-toggle-bars::before,
  .nav-toggle-bars::after { content: ""; position: absolute; left: 0; }
  .nav-toggle-bars::before { top: -6px; }
  .nav-toggle-bars::after { top: 6px; }

  .nav-panel {
    display: none;
    flex-basis: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
  }
  .nav-panel.open { display: flex; }
  .nav-panel .spacer { display: none; }

  .topbar nav { flex-direction: column; gap: 0; }
  .topbar nav a { padding: 12px 2px; border-top: 1px solid var(--border); }

  .logout {
    align-items: center;
    justify-content: space-between;
    padding: 12px 2px 2px;
    border-top: 1px solid var(--border);
  }
  .linkbtn { min-height: 24px; }

  .toolbar { gap: 10px; }
  .toolbar .field { flex: 1 1 100%; }
  .toolbar .spacer { display: none; }
  .toolbar .btn { flex: 1 1 100%; text-align: center; }
  .toolbar .indicator { flex: 1 1 100%; }

  .input, .select, textarea { font-size: 16px; }
  .grid { grid-template-columns: minmax(0, 1fr); }
  .stat-cards { grid-template-columns: minmax(0, 1fr); }

  /* Data tables become one card per row, each cell a label/value line. */
  .table-wrap { border: none; border-radius: 0; overflow: visible; background: none; }
  .table-wrap table,
  .table-wrap thead,
  .table-wrap tbody,
  .table-wrap tr,
  .table-wrap th,
  .table-wrap td { display: block; }
  .table-wrap thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .table-wrap tbody tr {
    margin-bottom: 10px;
    padding: 4px 14px;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
  }
  .table-wrap td {
    display: flex;
    gap: 14px;
    justify-content: space-between;
    align-items: baseline;
    padding: 9px 0;
    text-align: right;
  }
  .table-wrap td::before {
    content: attr(data-label);
    flex: 0 0 auto;
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--muted-foreground);
    text-align: left;
  }
  /* Restore the divider the desktop rule drops on the final row: on a card it is
     the cells, not the rows, that need separating. */
  .table-wrap tbody tr:last-child td { border-bottom: 1px solid var(--border); }
  .table-wrap tbody td:last-child { border-bottom: none; }
  .table-wrap td > .cell { min-width: 0; text-align: right; }
  .table-wrap td.empty { display: block; padding: 28px 8px; text-align: center; }
  .table-wrap td.empty::before { content: none; }

  .auth-card { margin: 24px auto; }

  /* Transactions get a purpose-built card list instead of the generic
     restacked table on phones. */
  .tx-table-wrap { display: none; }
  .tx-cards { display: block; }
}

@media (max-width: 480px) {
  /* Stack the split so the budget item gets the full width and the amount sits
     beside the remove button. */
  .split-row { grid-template-columns: minmax(0, 1fr) 40px; column-gap: 10px; }
  .split-row .field:first-of-type { grid-column: 1 / -1; }
  .row-remove { width: 40px; height: 40px; }
  .item-row { grid-template-columns: minmax(0, 1fr) 32px; row-gap: 6px; }

  .thumbs img { width: 72px; height: 72px; }
  .receipt-line { font-size: 16px; }
}

/* ---------------------------------------------------------------------------
   Redesign additions
   --------------------------------------------------------------------------- */

/* Two inks that have to swap by theme.

   --link is orange text (nav hover, side links, the sorted column header). The
   imported --primary reads 5.2:1 on a light ground but only 2.4:1 on a dark card,
   so dark takes --sidebar-primary, the one orange that survives there.

   --pos is money going the right way. --chart-4 is 5.4:1 on light but 3.3:1 on a
   dark card, so dark steps up to --chart-2.

   --focus-ring is the same value in both themes: --ring is 2.6:1 on white, under
   the 3:1 a focus indicator needs. */
:root {
  --link: var(--primary);
  --pos: var(--chart-4);
  --focus-ring: var(--sidebar-primary);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --link: var(--sidebar-primary);
    --pos: var(--chart-2);
  }
}
:root[data-theme="dark"] {
  --link: var(--sidebar-primary);
  --pos: var(--chart-2);
}

.topbar nav a:hover,
.label-row .side-link,
.linkbtn:hover,
th.sortable.sorted-asc,
th.sortable.sorted-desc { color: var(--link); }

.amt-pos { color: var(--pos); }

.input:focus,
.select:focus,
textarea:focus,
input[type="file"]:focus,
.btn:focus-visible,
.step:focus-visible,
button:focus-visible,
a:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: -1px;
}

/* A page title with its one primary action beside it. */
.page-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 16px;
}
.page-head h1 { margin: 0; }
.page-head .btn { white-space: nowrap; }
.page-head-actions { display: flex; gap: 8px; }

/* The one headline figure on a screen, a step above .stat-value. */
.hero-label { font-size: 12px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted-foreground); }
.hero-value {
  font-size: 36px;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
  margin-top: 2px;
}

/* Progress meters. .meter-wrap reserves room above the bar for the "today" tick's
   label, which sits outside the bar so the bar itself can stay overflow-clipped. */
.meter-wrap { position: relative; padding-top: 14px; }
.meter-tick-label {
  position: absolute;
  top: 0;
  transform: translateX(-50%);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--muted-foreground);
}
.meter {
  position: relative;
  height: 12px;
  border-radius: 999px;
  background: var(--muted);
}
.meter.small { height: 8px; }
.meter-fill {
  height: 100%;
  border-radius: 999px;
  background: var(--primary);
  max-width: 100%;
}
.meter-fill.over { background: var(--destructive); }
.meter-fill.pos { background: var(--pos); }
.meter-tick {
  position: absolute;
  top: -4px;
  bottom: -4px;
  width: 2px;
  border-radius: 1px;
  background: var(--foreground);
}
.meter-caption {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  margin-top: 10px;
  font-size: 13px;
  color: var(--muted-foreground);
}
.meter-caption .num { font-variant-numeric: tabular-nums; color: var(--foreground); }

/* A card whose rows are links: the watchlist and the recent-transaction list. */
.list-card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
.list-row {
  display: block;
  padding: 12px 14px;
  color: var(--text);
  text-decoration: none;
}
.list-row + .list-row { border-top: 1px solid var(--border); }
.list-row:hover { background: var(--muted); }
.list-row-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}
.list-row-head strong { font-weight: 600; }
.list-row-note { font-size: 12px; color: var(--muted-foreground); margin-top: 6px; font-variant-numeric: tabular-nums; }
.list-row .amount { font-variant-numeric: tabular-nums; font-weight: 600; white-space: nowrap; }

.section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin: 24px 0 8px;
}
.section-head h2 { margin: 0; }
.section-head a { font-size: 13px; color: var(--link); text-decoration: none; }

.two-col { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 24px; }

/* Label/value pairs on a detail page. */
.detail-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin: 0; }
.detail-grid dt { font-size: 12px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted-foreground); }
.detail-grid dd { margin: 0; }
.detail-grid dd.num { font-variant-numeric: tabular-nums; }

/* A recessed block that says what a destructive button will do. */
.danger-zone {
  margin-top: 24px;
  padding: 14px;
  border-radius: var(--radius-lg);
  background: var(--muted);
}
.danger-zone p { margin: 0 0 10px; font-size: 12px; color: var(--foreground); }
.btn.danger { background: var(--background); color: var(--destructive); border-color: var(--destructive); }

/* ---------------------------------------------------------------------------
   The transaction wizard
   --------------------------------------------------------------------------- */

.steps { display: flex; gap: 4px; margin-bottom: 16px; }
.step {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  min-height: 48px;
  padding: 4px 0;
  border: none;
  background: none;
  font: inherit;
  color: var(--muted-foreground);
  cursor: pointer;
}
.step-num {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--muted);
  color: var(--muted-foreground);
  font-size: 13px;
}
.step-name { font-size: 11px; }
.step.done { color: var(--text); }
.step.done .step-num { background: var(--background); border: 1px solid var(--foreground); color: var(--foreground); }
.step.current { color: var(--text); font-weight: 600; }
.step.current .step-num { background: var(--primary); color: var(--primary-foreground); font-weight: 600; }

.step-title { margin: 0 0 14px; }
.step-actions { display: flex; align-items: center; gap: 10px; margin-top: 20px; }
.step-actions .btn { min-height: 48px; display: inline-flex; align-items: center; justify-content: center; }
.step-actions .grow { flex: 1; }

/* Step 1: the two big "do you have a receipt" choices. */
.choice {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 56px;
  margin-bottom: 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--panel);
  font-size: 15px;
  cursor: pointer;
}
.choice.primary { background: var(--primary); color: var(--primary-foreground); border-color: var(--primary); font-weight: 600; }
.choice input[type="file"] { position: absolute; width: 1px; height: 1px; opacity: 0; padding: 0; border: 0; }

/* Step 3: the running tally over the splits. */
.allocation {
  padding: 12px 14px;
  margin-bottom: 16px;
  border-radius: var(--radius-lg);
  background: var(--muted);
}
.allocation-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  font-size: 13px;
}
.allocation-head .label { font-size: 12px; text-transform: uppercase; letter-spacing: .04em; }
.allocation-head .figure { font-variant-numeric: tabular-nums; }
.allocation .meter { background: var(--background); margin-top: 8px; }
.allocation p { margin: 8px 0 0; font-size: 12px; }
.allocation .over { color: var(--destructive); font-weight: 600; }

/* Each split becomes its own card in the wizard so the nested items read as
   belonging to it rather than floating between splits. */
.split-card {
  padding: 14px;
  margin-bottom: 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--panel);
}
.split-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 8px;
}
.split-card-head h3 {
  margin: 0;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--muted-foreground);
}
.split-card .row-remove { margin-top: 0; }
.add-split { width: 100%; border: 1px dashed var(--border); background: var(--panel); color: var(--text); min-height: 48px; font-weight: 600; }

.summary-card {
  padding: 14px;
  border-radius: var(--radius-lg);
  background: var(--muted);
}
.summary-card h3 {
  margin: 0 0 8px;
  font-size: 15px;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--foreground);
}

/* Receipt thumbnails with a remove control, used on step 1. */
.thumb { position: relative; }
.thumb .row-remove { position: absolute; top: -10px; right: -10px; margin: 0; }
.thumb-placeholder {
  display: grid;
  place-items: center;
  width: 88px;
  height: 88px;
  border: 1px dashed var(--border);
  border-radius: var(--radius-md);
  font-size: 12px;
  color: var(--muted-foreground);
  text-align: center;
}

/* The calendar's selected-day panel. */
.day-panel { margin-top: 16px; }
.day-panel-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.day-panel-head h2 { margin: 0; }
.day-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 0;
  border-top: 1px solid var(--border);
}
.day-row .amount { font-variant-numeric: tabular-nums; font-weight: 600; white-space: nowrap; }

@media (max-width: 720px) {
  .two-col { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .btn { min-height: 44px; display: inline-flex; align-items: center; justify-content: center; }
  .hero-value { font-size: 32px; }
  .page-head { gap: 10px; }
  .split-card .item-row { grid-template-columns: minmax(0, 1fr) 90px 28px; }
}

@media (max-width: 480px) {
  .split-card .item-row { grid-template-columns: minmax(0, 1fr) 32px; row-gap: 6px; }
}

/* The topbar's one primary action. On phones it drops into the open menu panel
   and spans it, below the links. */
.nav-cta { font-size: 13px; padding: 6px 12px; }
@media (max-width: 720px) {
  .nav-cta { margin-top: 12px; width: 100%; }
}

/* The budget list's closing total. Reads as a footer row on a wide screen, and as
   one more labelled card once the table restacks. */
.total-row td { background: var(--muted); font-size: 12px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted-foreground); }
.total-row td strong { font-size: 18px; text-transform: none; letter-spacing: 0; color: var(--foreground); font-variant-numeric: tabular-nums; }

/* Inside a split card the remove control moves up to the card's own header, so the
   budget item and its amount are the only two columns left. */
.split-card .split-row { grid-template-columns: minmax(0, 1fr) 140px; }
.split-card .items-block { margin: 4px 0 0; }
@media (max-width: 480px) {
  .split-card .split-row { grid-template-columns: minmax(0, 1fr); }
  .split-card .split-row .field:first-of-type { grid-column: auto; }
}

/* List / Calendar switch, shared by the two month views. */
.seg {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 4px;
  padding: 4px;
  margin-bottom: 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
}
.seg > * {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 36px;
  border-radius: var(--radius-md);
  font-size: 13px;
  color: var(--text);
  text-decoration: none;
}
.seg .seg-current { background: var(--primary); color: var(--primary-foreground); font-weight: 600; }

/* A category on the progress list, opening to the budget items inside it. */
.cat-row + .cat-row { border-top: 1px solid var(--border); }
.cat-row summary { padding: 12px 14px; cursor: pointer; list-style: none; }
.cat-row summary::-webkit-details-marker { display: none; }
.cat-row summary:hover { background: var(--muted); }
.cat-row[open] summary { background: var(--muted); }
.cat-items { padding: 4px 14px 12px; }
.cat-item {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 8px 0;
  font-size: 13px;
}
.cat-item + .cat-item { border-top: 1px solid var(--border); }
.cat-item .num { font-variant-numeric: tabular-nums; color: var(--muted-foreground); }
.cat-item-side { display: flex; align-items: center; flex-wrap: wrap; justify-content: flex-end; gap: 8px; }
.inline-form { display: inline; margin: 0; }

/* The calendar's day cells are links now; the chips inside them are not. */
a.cal-day { display: block; color: inherit; text-decoration: none; }
a.cal-day:hover { background: var(--muted); }
a.cal-day.outside:hover { background: var(--accent); }
.cal-day.selected { outline: 2px solid var(--primary); outline-offset: -2px; }
.cal-day.today .cal-date { display: grid; }
.cal-item { display: flex; }

/* ---------------------------------------------------------------------------
   Corrections found by looking at the rendered pages
   --------------------------------------------------------------------------- */

/* Meters are spans in some markup, and an inline box ignores height. */
.meter, .meter-fill { display: block; }
.list-row-note { display: block; }

/* Without this, every link outside a styled container falls back to browser blue.
   More specific rules (.topbar a, .list-row, .muted-link) still win. */
a { color: var(--link); }

/* The month heading keeps its line; the nav drops below it when there isn't room. */
.cal-head { flex-wrap: wrap; }
.cal-head h1 { white-space: nowrap; }

/* A day cell has to clip: a four-figure amount is wider than a column on a phone. */
.cal-day { overflow: hidden; }
.cal-more {
  display: block;
  padding: 1px 6px;
  font-size: 11px;
  color: var(--muted-foreground);
}

@media (max-width: 720px) {
  /* Put the theme toggle before the menu button so the menu stays under the thumb
     at the end of the bar. */
  .theme-toggle { order: 1; margin-left: auto; }
  .nav-toggle { order: 2; margin-left: 8px; }
  .nav-panel { order: 3; }

  /* Three short figures side by side read better than three stacked cards. */
  .stat-cards.compact { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
  .stat-cards.compact .stat-card { padding: 12px 10px; }
  .stat-cards.compact .stat-value { font-size: 17px; }

  .cal-item { font-size: 11px; padding: 1px 4px; }
  .cal-item-amount { overflow: hidden; text-overflow: ellipsis; }

  /* A restacked row is a card, but one label/value per line makes a very tall one.
     Pair the short cells two to a row with the label above the value, and let the
     name and the actions span the width. */
  .compact-cards tbody tr {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0 14px;
    padding: 12px 14px;
  }
  .compact-cards tbody td {
    display: block;
    padding: 6px 0;
    text-align: left;
    border-bottom: none;
  }
  .compact-cards tbody tr:last-child td { border-bottom: none; }
  .compact-cards tbody td::before { display: block; margin-bottom: 2px; }
  .compact-cards tbody td > .cell { text-align: left; }
  .compact-cards tbody td:first-child,
  .compact-cards tbody td:last-child { grid-column: 1 / -1; }
  .compact-cards tbody td:first-child { padding-top: 0; }
  .compact-cards tbody td:first-child::before { display: none; }
  .compact-cards tbody td:last-child {
    display: flex;
    gap: 16px;
    padding-top: 10px;
    margin-top: 4px;
    border-top: 1px solid var(--border);
  }
  .compact-cards tbody td:last-child::before { display: none; }
  .compact-cards tbody td.empty { grid-column: 1 / -1; }
  .compact-cards .total-row { grid-template-columns: minmax(0, 1fr); }
  .compact-cards .total-row td:first-child { padding-bottom: 0; }
  .compact-cards .total-row td:last-child { display: none; }
}

/* A day cell is about 48px wide on a phone, which is not enough for "1,234.56".
   The name is already hidden there, so show the amount rounded instead. */
.cal-item-short { display: none; font-variant-numeric: tabular-nums; }
@media (max-width: 720px) {
  .cal-item-amount { display: none; }
  .cal-item-short { display: inline; }
}
