:root {
  font-family: system-ui, sans-serif;
  color-scheme: light dark;
  --surface: #fcfcfb;
  --card: #ffffff;
  --line: #e4e3df;
  --text: #0b0b0b;
  --text-2: #52514e;
  --text-3: #8a8984;
  --series-plan: #2a78d6;   /* categorical slot 1 (blue) */
  --series-whatif: #eb6834; /* categorical slot 2 (orange) */
  --status-good: #0ca30c;
  --status-critical: #d03b3b;
  --accent: var(--series-plan);
  --gap: .75rem;
}
@media (prefers-color-scheme: dark) {
  :root {
    --surface: #1a1a19;
    --card: #232322;
    --line: #38383580;
    --text: #f0efec;
    --text-2: #c3c2b7;
    --text-3: #8f8e87;
    --series-plan: #3987e5;
    --series-whatif: #d95926;
  }
}

/* ---- app shell: the page itself never scrolls; panes scroll inside ---- */
html, body { height: 100%; }
body { margin: 0; display: flex; flex-direction: column; overflow: hidden; background: var(--surface); color: var(--text); accent-color: var(--accent); }
header { flex: none; display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; padding: .6rem 1rem; border-bottom: 1px solid var(--line); background: var(--card); }
header a { color: inherit; text-decoration: none; }
nav { display: flex; gap: 1rem; }
nav a { color: var(--text-2); padding: .25rem 0; }
nav a.active { color: var(--text); font-weight: 600; }
main { flex: 1; min-height: 0; display: flex; flex-direction: column; width: 100%; max-width: 96rem; margin: 0 auto; padding: var(--gap) 1rem 1rem; box-sizing: border-box; }
.app { flex: 1; min-height: 0; display: grid; gap: var(--gap); }
/* a pane is a column that gives its spare height to .scroll */
.pane { min-height: 0; display: flex; flex-direction: column; }
.pane > .scroll { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
.pane > h2, .pane > .hint, .pane > form, .pane > .fields, .pane > h3, .pane > .card-head { flex: none; }
/* list header: title + "+ Add", which opens that list's add dialog */
.card-head { display: flex; align-items: center; justify-content: space-between; gap: .5rem; margin: 0 0 .5rem; }
.card-head h2 { margin: 0; }
.add-btn { border: 1px solid var(--accent); background: none; color: var(--accent); border-radius: .4rem; padding: .3rem .8rem; font-weight: 600; }
.add-btn:hover { background: var(--accent); color: #fff; }
dialog select { width: 100%; }

h1 { font-size: 1.5rem; margin: 0; }
h2 { font-size: 1.1rem; margin: 0 0 .5rem; }
h3 { font-size: .95rem; margin: .75rem 0 .4rem; color: var(--text-2); }
/* 1rem text in fields keeps iOS from zooming into them on focus */
input, select, button { font: inherit; font-size: 1rem; }
button { cursor: pointer; padding: .4rem .8rem; }
button.icon { padding: 0 .4rem; border: 0; background: none; color: var(--text-3); font-size: 1.1rem; }
button.icon:hover { color: var(--status-critical); }
input, select { padding: .4rem; min-width: 0; max-width: 100%; box-sizing: border-box; }
form { display: flex; gap: .5rem; flex-wrap: wrap; margin: .6rem 0 0; }
form > input { flex: 1; }
label { display: flex; flex-direction: column; gap: .25rem; font-size: .85rem; color: var(--text-2); }
label input { color: var(--text); }
.card { background: var(--card); border: 1px solid var(--line); border-radius: .5rem; padding: .85rem; box-sizing: border-box; }
.fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr)); gap: .6rem; }
.hint { color: var(--text-3); font-size: .85rem; margin: 0 0 .5rem; }
.when { color: var(--text-3); font-size: .85rem; }
.status { font-size: .9rem; margin: .4rem 0 0; }
.status.good { color: var(--status-good); }
.status.critical { color: var(--status-critical); }

/* ---- plan page: chart + afford | needs ---- */
#plan { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); grid-template-rows: minmax(0, 1fr); }
#plan .pane-plan { display: flex; flex-direction: column; min-height: 0; gap: var(--gap); }
#plan .pane-plan .afford { flex: none; }
/* segmented switch: Chart | Needs on phones, Spent | Received always */
.seg { display: none; gap: .25rem; padding: .2rem; border-radius: .5rem; background: var(--line); }
.seg a, .seg button { flex: 1; border: 0; background: none; padding: .35rem .9rem; border-radius: .35rem; color: var(--text-2); text-decoration: none; text-align: center; font-size: .9rem; }
.seg .active { background: var(--card); color: var(--text); font-weight: 600; }
.seg.sub { display: flex; margin-left: auto; }
.month-nav .seg a { font-size: .9rem; color: var(--text-2); }
.month-nav .seg a.active { color: var(--text); }

/* ---- accounts and budget: a summary over two list cards ---- */
#accounts, #budget { grid-template-rows: minmax(0, 1fr); }
.board { min-height: 0; display: grid; gap: var(--gap); grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); grid-template-rows: auto minmax(0, 1fr); }
.board > .summary { grid-column: 1 / -1; padding: 0 .25rem; }
.board > .summary .hint { flex-basis: 100%; margin: 0; }
.list form.add { display: grid; grid-template-columns: 1fr 1fr; gap: .5rem; }
.list form.add .wide { grid-column: 1 / -1; }
.list form.add > * { width: 100%; min-width: 0; }
#accounts .list form.add button { grid-column: auto; }
#budget .list form.add button { grid-column: 1 / -1; }
/* settings: plan knobs | expense input choice with a live preview */
#settings { grid-template-columns: minmax(0, 26rem) minmax(0, 34rem); align-content: start; overflow-y: auto; }
.pickers { display: grid; gap: .4rem; margin-bottom: .75rem; }
.choice { flex-direction: row; align-items: flex-start; gap: .6rem; padding: .5rem .6rem; border: 1px solid var(--line); border-radius: .5rem; cursor: pointer; color: var(--text); font-size: .95rem; }
.choice:has(input:checked) { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.choice input { margin-top: .2rem; }
.choice span { display: flex; flex-direction: column; gap: .1rem; }
.choice small { color: var(--text-3); font-size: .8rem; }

/* accounts: edits wait for Save; a changed row and the save bar say so */
.pending { display: none; grid-column: 1 / -1; align-items: center; gap: .5rem; padding: .45rem .6rem; border: 1px solid var(--series-whatif); border-radius: .5rem; background: var(--card); position: sticky; top: 0; z-index: 2; }
.pending.show { display: flex; }
.pending .dot { color: var(--series-whatif); }
.pending span:nth-child(2) { margin-right: auto; }
.budget .was { display: none; font-size: .75rem; color: var(--text-3); }
.budget.changed .was { display: block; }
.budget.changed input { border-color: var(--series-whatif); box-shadow: 0 0 0 1px var(--series-whatif); }
.budget.changed .name::before { content: "● "; color: var(--series-whatif); }
.accounts .budget .name { display: block; }
.choice input { flex: none; }
[hidden] { display: none !important; }
.budget .name.link { border: 0; background: none; padding: 0; text-align: left; color: var(--text); font-size: 1rem; cursor: pointer; }
.budget .name.link:hover { color: var(--accent); text-decoration: underline; }

/* ---- drag pickers for an expense amount (picker.js) ---- */
.picker { margin: .25rem 0; outline: none; user-select: none; -webkit-user-select: none; }
.picker-readout { font-size: 1.6rem; font-weight: 700; text-align: center; font-variant-numeric: tabular-nums; }
.pk-hint { font-size: .8rem; color: var(--text-3); text-align: center; margin: .35rem 0 0; }
.pk-track { position: relative; height: 2.75rem; border-radius: 1.4rem; background: var(--line); touch-action: none; cursor: pointer; margin: .6rem 0 .3rem; }
.pk-fill { position: absolute; inset: 0 auto 0 0; border-radius: 1.4rem; background: var(--accent); opacity: .35; }
.pk-thumb { position: absolute; top: 50%; width: 2.3rem; height: 2.3rem; transform: translate(-50%, -50%); border-radius: 50%; background: var(--card); border: 3px solid var(--accent); box-sizing: border-box; }
.pk-ticks { position: relative; height: 1rem; font-size: .7rem; color: var(--text-3); }
.pk-ticks span { position: absolute; transform: translateX(-50%); white-space: nowrap; }
.pk-ticks span:first-child { transform: none; }
.pk-ticks span:last-child { transform: translateX(-100%); }
.pk-dial-wrap { position: relative; width: min(14rem, 100%); margin: 0 auto; }
.pk-dial { width: 100%; display: block; touch-action: none; cursor: grab; }
.pk-arc-bg { fill: none; stroke: var(--line); stroke-width: 16; stroke-linecap: round; }
.pk-arc { fill: none; stroke: var(--accent); stroke-width: 16; stroke-linecap: round; }
.pk-knob { fill: var(--card); stroke: var(--accent); stroke-width: 4; }
.pk-dial-wrap .picker-readout { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-size: 1.3rem; pointer-events: none; }
.pk-pad { touch-action: none; border: 1px dashed var(--text-3); border-radius: .6rem; padding: .8rem .5rem; text-align: center; cursor: ns-resize; }
.pk-near { color: var(--text-3); font-size: .95rem; min-height: 1.4em; font-variant-numeric: tabular-nums; }
.pk-grid { position: relative; display: grid; grid-template-columns: repeat(5, 1fr); grid-template-rows: repeat(9, 1fr); gap: 2px; height: 15rem; touch-action: none; cursor: crosshair; margin-top: .4rem; }
.pk-grid span { display: flex; align-items: center; justify-content: center; font-size: .68rem; background: var(--line); border-radius: .2rem; color: var(--text-3); }
.pk-grid-h, .pk-grid-v { position: absolute; pointer-events: none; background: var(--accent); opacity: .55; }
.pk-grid-h { left: 0; right: 0; height: 1px; }
.pk-grid-v { top: 0; bottom: 0; width: 1px; }
.pk-grid-dot { position: absolute; width: 1.4rem; height: 1.4rem; margin: -.7rem 0 0 -.7rem; border-radius: 50%; background: var(--accent); border: 3px solid var(--card); box-sizing: border-box; pointer-events: none; box-shadow: 0 1px 6px #0006; }
.pk-ruler { position: relative; height: 4.2rem; overflow: hidden; touch-action: none; cursor: ew-resize; border-radius: .5rem; background: var(--line); margin-top: .4rem; }
.pk-ruler-strip { position: absolute; inset: 0 auto 0 0; will-change: transform; }
.pk-ruler-strip i { position: absolute; bottom: 0; width: 1px; height: .6rem; background: var(--text-3); }
.pk-ruler-strip i.major { height: 1.4rem; background: var(--text-2); }
.pk-ruler-strip b { position: absolute; top: .35rem; transform: translateX(-50%); font-size: .7rem; font-weight: 400; color: var(--text-2); white-space: nowrap; }
.pk-ruler-mark { position: absolute; left: 50%; top: 0; bottom: 0; width: 2px; margin-left: -1px; background: var(--accent); }
/* quick add: the + on a category row, tap or drag up */
.categories .category .quick { touch-action: none; flex: none; width: 2.2rem; height: 2.2rem; min-height: 0; padding: 0; border: 1px solid var(--accent); border-radius: 50%; background: none; color: var(--accent); font-size: 1.2rem; line-height: 1; }
.categories .category .quick:active, .categories .category .quick.dragging { background: var(--accent); color: #fff; }
.categories .category.idle .name, .categories .category.idle .amount { color: var(--text-3); }
.quick-bubble { position: fixed; z-index: 50; pointer-events: none; transform: translate(-50%, -140%); background: var(--card); color: var(--text); border: 1px solid var(--accent); border-radius: .5rem; padding: .35rem .65rem; font-weight: 600; white-space: nowrap; box-shadow: 0 4px 16px #0005; font-variant-numeric: tabular-nums; }
.quick-bubble small { display: block; font-weight: 400; color: var(--text-3); }
#settings .round { margin-bottom: .5rem; }
.pk-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(6.5rem, 1fr)); gap: .4rem; margin-top: .4rem; }
.pk-tile { touch-action: none; min-height: 3.2rem; border: 1px solid var(--line); background: var(--card); border-radius: .5rem; color: var(--text); font-size: .9rem; }
.pk-tile.on { border-color: var(--accent); background: var(--accent); color: #fff; }
.pk-bubble { font-size: 1.1rem; min-height: 1.6em; }
#settings label .hint { margin: 0; font-size: .8rem; }

/* chart: fills the height its pane leaves (plan.js sizes the viewBox to match) */
.chart-wrap { position: relative; flex: 1; min-height: 12rem; display: flex; flex-direction: column; align-items: center; background: var(--card); border: 1px solid var(--line); border-radius: .5rem; padding: .5rem; box-sizing: border-box; }
.chart-wrap svg { flex: 0 1 auto; min-height: 0; width: 100%; height: auto; max-height: 100%; display: block; touch-action: pan-y; }
.chart-wrap svg text { font-size: 11px; fill: var(--text-2); }
.grid line { stroke: var(--line); stroke-width: 1; }
.zero { stroke: var(--text-3); stroke-width: 1; }
.buffer { stroke: var(--text-3); stroke-width: 1; stroke-dasharray: 2 4; }
.buffer-label { font-size: 10px; }
.crosshair { stroke: var(--text-3); stroke-width: 1; pointer-events: none; }
path.plan { fill: none; stroke: var(--series-plan); stroke-width: 2; stroke-linejoin: round; }
path.whatif { fill: none; stroke: var(--series-whatif); stroke-width: 2; stroke-dasharray: 6 4; stroke-linejoin: round; }
.shortfall line { stroke: var(--status-critical); stroke-width: 1; stroke-dasharray: 3 3; }
.shortfall text { fill: var(--status-critical); font-size: 10px; }
.marker { cursor: grab; touch-action: none; }
.marker line { stroke: var(--series-plan); stroke-width: 1; stroke-dasharray: 2 2; }
.marker circle { fill: var(--series-plan); stroke: var(--card); stroke-width: 2; }
.marker .hit { fill: transparent; stroke: none; } /* finger-sized target around the dot */
.marker text { fill: var(--text); font-size: 10px; pointer-events: none; }
.marker.off line { stroke: var(--text-3); }
.marker.off circle { fill: var(--card); stroke: var(--text-3); }
.marker.off .hit { fill: transparent; stroke: none; }
.marker.off text { fill: var(--text-3); }
.chart-tip { position: absolute; pointer-events: none; background: var(--card); border: 1px solid var(--line); border-radius: .3rem; padding: .3rem .5rem; font-size: .8rem; box-shadow: 0 2px 8px #0002; }
.legend { flex: none; align-self: stretch; display: flex; flex-wrap: wrap; gap: .25rem 1rem; font-size: .8rem; color: var(--text-2); padding: .4rem .25rem 0; }
.swatch { display: inline-block; width: 1.2rem; height: 0; border-top: 2px solid; vertical-align: middle; margin-right: .3rem; }
.swatch.plan { border-color: var(--series-plan); }
.swatch.whatif { border-color: var(--series-whatif); border-top-style: dashed; }
.swatch.buffer { border-color: var(--text-3); border-top-style: dotted; }

/* summary strip under the chart */
.summary { flex: none; display: flex; flex-wrap: wrap; gap: .5rem 1.5rem; padding: .25rem .25rem 0; align-items: baseline; }
.summary .status { flex-basis: 100%; margin: 0; }
.stat { display: flex; flex-direction: column; }
.stat .label { font-size: .8rem; color: var(--text-3); }
.stat strong { font-size: 1.1rem; }

/* ---- lists ---- */
ul { list-style: none; margin: 0; padding: 0; }
.goals li, .incomes li, .budgets li, .expenses li, .categories li, .months li { display: flex; align-items: center; gap: .75rem; padding: .4rem 0; border-bottom: 1px solid var(--line); }
.accounts .budget input { width: 9rem; }
.liabilities .budget input { color: var(--status-critical); }
.incomes .name { min-width: 0; }
.incomes .name small { display: block; color: var(--text-3); }
.goals .goal { padding: 0; }
.goal input[type=checkbox] { margin: 0; }
.goal .edit { flex: 1; display: flex; align-items: center; gap: .75rem; min-width: 0; padding: .5rem 0; border: 0; background: none; color: inherit; text-align: left; border-radius: .3rem; }
.goal .edit:hover { color: var(--accent); }
.goal .name { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.goal .amount { margin-left: 0; }
.goal .when { white-space: nowrap; min-width: 4.5rem; text-align: right; }
.goal.off .name, .goal.off .amount { color: var(--text-3); text-decoration: line-through; }
.amount { font-variant-numeric: tabular-nums; margin-left: auto; white-space: nowrap; }
.cashflow.income .amount { color: var(--status-good); }
.cashflows .total { color: var(--text-2); font-size: .9rem; border-bottom: 0; }
.expense .date { color: var(--text-3); font-size: .85rem; min-width: 6rem; }
.expense .name { min-width: 0; overflow-wrap: anywhere; }
.expense .name small { display: block; color: var(--text-3); }
.categories, .months { font-size: .9rem; }
/* budget: a field per category */
.budgets .budget { padding: .25rem 0; }
.budget .name { flex: 1; font-size: 1rem; color: var(--text); }
.budget input { width: 9rem; text-align: right; }
.budgets .total { color: var(--text-2); font-size: .9rem; border-bottom: 0; }
/* expenses summary: spent vs budget per category, with a bar */
.categories .category { flex-wrap: wrap; gap: .25rem .75rem; }
.categories .category .name { flex: 1; }
.categories .category small { color: var(--text-3); }
.categories .category.over .amount { color: var(--status-critical); }
.bar { flex-basis: 100%; height: 4px; border-radius: 2px; background: var(--line); overflow: hidden; }
.bar i { display: block; height: 100%; background: var(--series-plan); }
.category.over .bar i { background: var(--status-critical); }

/* ---- edit dialog ---- */
dialog { box-sizing: border-box; width: min(26rem, calc(100vw - 2rem)); padding: 1.25rem; border: 1px solid var(--line); border-radius: .5rem; background: var(--card); color: var(--text); box-shadow: 0 8px 32px #0004; }
dialog::backdrop { background: #0008; }
dialog form { display: flex; flex-direction: column; gap: .75rem; margin: 0; }
/* flex, not grid: Chrome sizes a grid row holding a type=month input far too tall */
dialog .fields { display: flex; gap: .75rem; }
dialog .fields label { flex: 1 1 0; min-width: 0; }
dialog input:not([type=checkbox]) { width: 100%; box-sizing: border-box; }
dialog .check { flex-direction: row; align-items: center; gap: .5rem; font-size: 1rem; color: var(--text); }
dialog .actions { display: flex; gap: .5rem; justify-content: flex-end; margin-top: .25rem; }
dialog .actions .danger { margin-right: auto; color: var(--status-critical); }
button.primary { background: var(--accent); color: #fff; border-color: var(--accent); }

/* ---- expenses page: form + totals | list ---- */
#expenses, #received { grid-template-columns: minmax(0, 2fr) minmax(0, 3fr); grid-template-rows: auto minmax(0, 1fr); }
#expenses .month-nav, #received .month-nav { grid-column: 1 / -1; }
.month-nav { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; }
.month-nav a, .month-nav .disabled { font-size: 1.5rem; text-decoration: none; color: var(--text-2); }
.month-nav .disabled { color: var(--text-3); }
#expense-summary { padding: .5rem .25rem 0; }
#expense-summary .categories, #expense-summary .months, #received-summary .categories, #received-summary .months { flex-basis: 100%; }

/* ---- bottom tab bar (phones only) ---- */
.tabs { display: none; }

/* ---- phones: one pane at a time, tab bar at the bottom ---- */
@media (max-width: 48rem) {
  header nav { display: none; }
  header { padding: .5rem .75rem; }
  main { padding: var(--gap) .75rem; }
  .app { display: flex; flex-direction: column; }
  .pane { flex: 1; }
  #plan .pane-plan { gap: .5rem; overflow-y: auto; } /* short phones: the chart keeps 12rem and the pane scrolls */
  #plan .seg { display: flex; flex: none; }
  .board { display: block; overflow-y: auto; overscroll-behavior: contain; }
  .board > * { margin-bottom: var(--gap); }
  #settings { display: block; overflow-y: auto; }
  #settings > .pane { margin-bottom: var(--gap); }
  .board .pane > .scroll { overflow: visible; }
  .month-nav h1 { font-size: 1.25rem; }
  .tabs { flex: none; display: flex; border-top: 1px solid var(--line); background: var(--card); padding: .25rem .25rem calc(.25rem + env(safe-area-inset-bottom)); }
  .tabs a, .tabs button { flex: 1; border: 0; background: none; padding: .55rem .1rem; color: var(--text-3); text-decoration: none; text-align: center; font-size: .82rem; border-radius: .4rem; }
  .tabs .active { color: var(--accent); font-weight: 600; }
  .card { padding: .75rem; }
  .chart-wrap { padding: .35rem .15rem; }
  form.add { display: grid; grid-template-columns: 1fr 1fr; gap: .5rem; }
  form.add .wide, form.add button { grid-column: 1 / -1; }
  form.add input, form.add select { width: 100%; }
  .goal .edit { flex-wrap: wrap; gap: 0 .75rem; }
  .goal .name { flex: 1 1 100%; }
  .goal .amount { margin-left: 0; }
  .goal .when { margin-left: auto; }
  .expense .date { min-width: 4.5rem; font-size: .8rem; }
  .summary { gap: .35rem 1.25rem; }
  #expenses, #received { display: flex; flex-direction: column; }
  dialog .actions { flex-wrap: wrap; }
  dialog .actions button { flex: 1; }
  dialog .actions .danger { flex-basis: 100%; margin-right: 0; }
}
/* wider than a phone: every pane is visible, whatever the tab signal says */
@media (min-width: 48.01rem) {
  .pane { display: flex !important; }
}

/* touch: finger-sized fields and buttons */
@media (pointer: coarse) {
  input:not([type=checkbox]):not([type=range]), select, button:not(.icon) { min-height: 2.75rem; }
  input[type=range] { height: 2.75rem; }
  input[type=checkbox] { width: 1.3rem; height: 1.3rem; margin: 0; }
  button.icon { min-width: 2.75rem; }
  .marker { cursor: default; }
}

/* Sign-in and registration */
.auth { display: flex; flex-direction: column; gap: .8rem; width: 100%; max-width: 24rem; margin: 3rem auto; }
.auth h1 { margin: 0; }
.auth .status:empty, .account .status:empty { display: none; }
.auth button { padding: .55rem .8rem; }
.account form { display: flex; flex-direction: column; gap: .6rem; align-items: flex-start; }
.account form .fields { width: 100%; }
.account-actions { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: .8rem; padding-top: .8rem; border-top: 1px solid var(--line); }
.banner { margin-right: auto; padding: .1rem .5rem; border-radius: .3rem; background: #b26b00; color: #fff; font-size: .8rem; font-weight: 600; }
