: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 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; }

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; }

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

.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; }
tbody tr:last-child td { border-bottom: none; }
.table-wrap { border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden; }

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

.muted-row { opacity: .55; }

.empty { padding: 32px; text-align: center; color: var(--muted-foreground); }
.nonfield { color: var(--destructive); margin: 0 0 12px; }
.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);
}

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

/* ---------------------------------------------------------------------------
   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); }
.cal-total.net strong { color: var(--primary); }

.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 oklch, var(--chart-2) 20%, var(--background)); color: var(--chart-4); }
.cal-item.expense { background: color-mix(in oklch, var(--destructive) 15%, var(--background)); color: var(--destructive); }
.cal-item.savings { background: color-mix(in oklch, var(--primary) 15%, var(--background)); color: var(--primary); }
.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); }

  /* 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; }
}

@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; }
}
