/* Cashflow — one visual system: warm paper ground, white cards, spruce accent,
   red ink only for "over". Hanken Grotesk everywhere, tabular figures for money. */

@font-face {
  font-family: "Hanken Grotesk";
  src: url("/fonts/hanken-grotesk-var.woff2") format("woff2");
  font-weight: 100 900; font-style: normal; font-display: swap;
}

:root {
  --bg: #F6F4EF;
  --surface: #FFFFFF;
  --surface-2: #EDEAE2;
  --border: #E2DED3;
  --ink: #20312A;
  --ink-2: #57675E;
  --ink-3: #94A099;         /* disabled only */
  --brand: #166B4D;
  --brand-deep: #0E4A36;
  --brand-tint: #E0EDE6;
  --red: #B0382A;
  --red-tint: #F8E7E3;
  --track: #E6E2D7;
  --on-ink: #F3F1EA;        /* text on the dark banner */
  --amber: #E8C77C;         /* banner icon */
  --amber-deep: #5C4708;    /* expired-session banner */
  --red-edge: #EAC8C1;      /* border of an over-budget card */
  /* Amber = this month's plan does not fit. Distinct from red, which is kept
     for the one fact that matters: the household has crossed zero. --amber is
     a banner fill at ~1.7:1 and cannot carry text; these can. */
  --warn: #8C5A0B;          /* 5.34:1 on --bg, 5.87:1 on --surface */
  --warn-tint: #FBF1DE;
  --warn-edge: #E9D9B6;
  --radius-card: 22px;      /* cards, heroes, the floating bar */
  --radius: 14px;           /* anything inside a card */
  --radius-sm: 10px;
  --radius-sheet: 26px;     /* the top corners of a bottom sheet */
  --shadow: 0 2px 10px rgba(32, 49, 42, 0.05);
  --shadow-card: 0 10px 30px rgba(32, 49, 42, 0.09), 0 2px 6px rgba(32, 49, 42, 0.05);
  --shadow-raised: 0 8px 26px rgba(32, 49, 42, 0.14), 0 2px 6px rgba(32, 49, 42, 0.08);
  --font: "Hanken Grotesk", -apple-system, "Segoe UI", Roboto, sans-serif;
}

* { box-sizing: border-box; margin: 0; padding: 0; }
html { -webkit-text-size-adjust: 100%; }
body {
  font-family: var(--font);
  /* Same warm paper, with the far end a shade deeper so surfaces lift off it. */
  background: linear-gradient(180deg, var(--bg) 0%, #EDEAE0 100%);
  background-attachment: fixed;
  color: var(--ink);
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
  overscroll-behavior-y: none;
}
button, input { font: inherit; color: inherit; }
button { background: none; border: 0; cursor: pointer; -webkit-tap-highlight-color: transparent; }
ul { list-style: none; }
:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; border-radius: 4px; }

.icon { display: inline-flex; width: 22px; height: 22px; flex: none; }
.icon svg { width: 100%; height: 100%; }
.icon.inline { width: 16px; height: 16px; vertical-align: -3px; }
.icon.dim { color: var(--ink-2); }
.icon.spin svg { animation: spin 1.2s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

.grow { flex: 1 1 auto; min-width: 0; }

/* ---------- app shell ---------- */

#app { min-height: 100dvh; }
.boot-splash { min-height: 100dvh; background: var(--bg); }

.app-shell {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}
.screen {
  flex: 1;
  width: 100%;
  max-width: 640px;
  margin: 0 auto;
  padding: max(12px, env(safe-area-inset-top)) 16px calc(104px + env(safe-area-inset-bottom));
}

/* ---------- banners ---------- */

.banner {
  display: flex; gap: 10px; align-items: center;
  background: var(--ink); color: var(--on-ink);
  padding: 10px max(16px, env(safe-area-inset-left));
  padding-top: max(10px, env(safe-area-inset-top));
  font-size: 0.9rem; font-weight: 500;
}
.banner .icon { color: var(--amber); }
.banner-warn { background: var(--amber-deep); cursor: pointer; }

/* ---------- headers ---------- */

.month-head { padding: 6px 0 14px; }
.hh-name {
  font-size: 0.85rem; font-weight: 600; color: var(--ink-2);
  letter-spacing: 0.01em;
}
.month-nav { display: flex; align-items: center; gap: 4px; }
.month-title {
  font-size: 1.6rem; font-weight: 800; letter-spacing: -0.01em;
  /* A long cashflow name must never push the month onto a second line. */
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.icon-btn {
  width: 44px; height: 44px; display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%; color: var(--ink-2);
}
.icon-btn:active { background: var(--surface-2); }
.icon-btn-spacer { width: 44px; }
.year-link { margin-top: 2px; padding-left: 0; }

.detail-head { display: flex; align-items: center; gap: 6px; padding: 6px 0 12px; }
.detail-title {
  flex: 1; font-size: 1.35rem; font-weight: 800; letter-spacing: -0.01em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-align: center;
}

/* ---------- hero ---------- */

.hero {
  background: var(--surface);
  border: 0;
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  padding: 22px 20px 20px;
  margin-bottom: 12px;
}
.hero-label {
  font-size: 0.9rem; font-weight: 600; color: var(--ink-2);
}
.hero-amount {
  font-size: clamp(2.4rem, 11vw, 3.2rem);
  font-weight: 800; letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  color: var(--brand-deep);
  margin: 2px 0 4px;
}
.hero-amount.neg, .hero-amount-sm.neg, .cat-left.neg, .year-diff.neg { color: var(--red); }
.hero-amount-sm {
  font-size: 2rem; font-weight: 800; letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums; color: var(--brand-deep); margin: 2px 0 4px;
}
.hero-sub { font-size: 0.9rem; color: var(--ink-2); margin-bottom: 12px; font-variant-numeric: tabular-nums; }
.hero-neg { border-color: var(--red-edge); }
.hero-compact { padding: 16px 18px 16px; }

/* The hero before we know what is in the account: it asks for the missing
   figure rather than printing a red "Short by" it cannot explain. */
.hero-amount-muted { color: var(--ink-2); }
.hero-amount.warn, .hero-amount-sm.warn { color: var(--warn); }
.hero-warn { border-color: var(--warn-edge); background: var(--warn-tint); }
.hero .hero-line + .hero-line { margin-top: 6px; }

/* The three lines: what came in, what is still to allocate, what is saving.
   Equal weight on purpose — he asked to "see where money is going", and that
   is a flow, not a headline with footnotes. */
/* The Budget headline: a ring for how much of the plan is spent, the figure
   you act on beside it, then the other two side by side under a rule. */
.hero-top { display: flex; align-items: center; gap: 20px; }
.hero-top-text { min-width: 0; }

.ring { position: relative; width: 96px; height: 96px; flex: none; }
.ring svg { transform: rotate(-90deg); display: block; }
.ring-track { stroke: var(--track); }
.ring-fill { stroke: var(--brand); }
.ring-fill.ring-over { stroke: var(--warn); }
.ring-mid {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
}
.ring-pct { font-size: 1.3rem; font-weight: 800; letter-spacing: -0.02em; line-height: 1; }
.ring-cap { font-size: 0.7rem; font-weight: 600; color: var(--ink-2); margin-top: 2px; }

/* The category's colour: a dot beside its name, so the list below the ring is
   the ring's legend and no slice is identified by colour alone. */
/* Tapping the ring opens the breakdown; it has to look like it does something. */
/* The name of the cashflow you are in IS the way to leave it — no mystery icon. */
.month-row { display: flex; align-items: center; gap: 10px; }
/* Pull the chevron flush with the content edge so the month sits at the left
   margin rather than one tap target in from it. */
.month-nav { flex: 1; min-width: 0; margin-left: -12px; }

.space-switch {
  flex: none;
  display: flex; align-items: center; gap: 2px;
  height: 44px; max-width: 38%;
  padding: 0 8px 0 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 22px;
  box-shadow: var(--shadow);
  color: var(--ink);
}
.space-name {
  font-size: 0.95rem; font-weight: 700;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.space-switch .space-caret {
  width: 17px; height: 17px; flex: none;
  transform: rotate(90deg);
  color: var(--ink-2);
}
.space-switch:active { background: var(--surface-2); }

.space-list { display: flex; flex-direction: column; margin: 8px 0 4px; }
.space-row {
  display: flex; align-items: center; gap: 10px;
  width: 100%; min-height: 52px; padding: 0 4px;
  text-align: left; font-size: 1rem; font-weight: 600;
  border-bottom: 1px solid var(--border);
}
.space-row.on { color: var(--brand-deep); }

.space-kinds { border: 0; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 8px; }
.space-kind {
  display: flex; align-items: flex-start; gap: 12px;
  min-height: 44px; padding: 12px 14px;
  background: var(--surface); border-radius: var(--radius);
  box-shadow: var(--shadow); cursor: pointer;
}
.space-kind input { margin-top: 3px; accent-color: var(--brand); flex: none; }
.space-kind-tight { padding: 10px 14px; align-items: center; }
.share-facts { gap: 2px; margin: 14px 0 4px; }
.share-fact {
  display: flex; align-items: center; gap: 10px;
  min-height: 40px; font-size: 0.9rem; color: var(--ink-2);
}
.share-url { font-size: 0.85rem; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.onb-actions { display: flex; flex-direction: column; gap: 10px; }
.space-kind-tight input { margin-top: 0; }
.space-kind-text { display: flex; flex-direction: column; gap: 2px; }
.space-kind-label { font-size: 0.95rem; font-weight: 600; }
.space-kind-sub { font-size: 0.8rem; color: var(--ink-2); line-height: 1.4; }
.setting-row-danger .grow { color: var(--red); }

.ring-tap { border: 0; background: none; padding: 0; display: block; }
.ring-tap:active { transform: scale(0.97); }

/* Where the month went, in words: every slice named, "others" opened up, and
   the ring's empty part given a name of its own. */
.bd-list { display: flex; flex-direction: column; }
.bd-row {
  display: grid;
  grid-template-columns: 12px 1fr auto auto;
  align-items: baseline; gap: 10px;
  padding: 12px 0;
  border-bottom: 1px solid var(--border);
}
.bd-dot {
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--dot); align-self: center;
}
.bd-dot-open { border: 2px solid var(--border); background: none; }
.bd-name { font-size: 0.98rem; font-weight: 600; }
.bd-pct { font-size: 0.82rem; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.bd-amount {
  font-size: 1rem; font-weight: 700; color: var(--brand-deep);
  font-variant-numeric: tabular-nums; min-width: 82px; text-align: right;
}
.bd-inside {
  display: flex; flex-direction: column;
  padding: 4px 0 10px 22px;
}
.bd-sub {
  display: flex; justify-content: space-between; gap: 12px;
  padding: 5px 0; font-size: 0.88rem; color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}
.bd-left { margin-top: 6px; }
.bd-left .bd-row { border-bottom: 0; }
.bd-left .bd-amount { color: var(--ink); }

.pay-counted {
  font-size: 0.82rem; line-height: 1.5; color: var(--ink-2);
  margin-top: 6px; font-variant-numeric: tabular-nums;
}
.pay-counted strong { color: var(--ink); }

.cat-dot {
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--dot, var(--brand));
  flex: none; margin-right: 8px;
}
.cat-row-top { display: flex; align-items: center; gap: 0; }

/* Automatic plus five colours in the category editor. Five is the measured
   limit of what the eye separates in a small ring — see CATEGORY_COLORS in
   util.js. Six chips at 44px need 314px, which fits the narrowest phone, but
   the row wraps rather than overflowing if it ever grows again. */
.swatches { display: flex; flex-wrap: wrap; gap: 10px; }
.swatch {
  width: 44px; height: 44px; border-radius: 50%;
  border: 2px solid transparent;
  display: flex; align-items: center; justify-content: center;
  position: relative;
}
/* Absolute, so the sparkle on the Automatic chip sits ON the dot rather than
   beside it — as flex siblings they shared the row and squashed the circle
   into a 20x26 oval. */
.swatch::before {
  content: ""; width: 26px; height: 26px; border-radius: 50%;
  background: var(--swatch);
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
}
.swatch.on { border-color: var(--ink); }
.swatch.on::before { width: 20px; height: 20px; }
/* The automatic chip wears the colour the category would actually be given, so
   choosing it is not a leap of faith — with a mark on top saying who chose. */
.swatch-auto::before { opacity: 0.45; }
.swatch-auto .icon {
  position: relative; width: 20px; height: 20px; color: var(--ink);
}
.swatch-auto.on::before { width: 26px; height: 26px; opacity: 0.6; }

.money-cols { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
.money-col { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.money-col-label { font-size: 0.78rem; font-weight: 600; color: var(--ink-2); }
.money-col-amount {
  font-size: 1.32rem; font-weight: 800; letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums; color: var(--brand-deep);
}
.money-col-amount.warn { color: var(--warn); }
.hero-top .money-col-amount { font-size: 2.05rem; letter-spacing: -0.03em; line-height: 1.05; }
.hero-top .money-col-label { font-size: 0.82rem; }
.money-line-note {
  display: block; font-size: 0.76rem; line-height: 1.4; color: var(--ink-2);
  margin-top: 2px; font-variant-numeric: tabular-nums;
}
.money-line-note.warn { color: var(--warn); }
.money-line-note.good { color: var(--brand-deep); }
.hero-rule { border-top: 1px solid var(--border); margin: 18px 0 16px; }
.hero .hero-line + .hero-line { margin-top: 6px; }

/* A paycheque you edited: say at once whether it matched your usual one. */
.pay-row-wrap + .pay-row-wrap { margin-top: 4px; }
.pay-row-note {
  display: block; font-size: 0.8rem; line-height: 1.4;
  margin: 2px 0 6px; font-variant-numeric: tabular-nums;
}
.pay-row-note:empty { margin: 0; }
.pay-row-note-low { color: var(--warn); }
.pay-row-note-high { color: var(--brand-deep); }
.money-line-note.warn { color: var(--warn); }
.money-line-note.good { color: var(--brand-deep); }
.money-line-note + .money-line-note { margin-top: 3px; }

/* Saved up: one quiet row normally, a bordered card when it goes below zero.
   The month keeps the display type slot, so this figure stays smaller even
   when it is the more serious of the two. */
.saved-strip-when, .saved-strip-note {
  font-size: 0.8rem; color: var(--ink-2);
}
.saved-strip-note { flex-basis: 100%; }
.saved-strip strong { font-variant-numeric: tabular-nums; color: var(--brand-deep); }
.saved-strip { flex-wrap: wrap;
  box-shadow: var(--shadow-card);
}
.saved-card {
  width: 100%; text-align: left;
  display: flex; flex-direction: column; gap: 2px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-card); box-shadow: var(--shadow);
  padding: 14px; margin-bottom: 12px;
}
.saved-card-warn { border-color: var(--warn-edge); background: var(--warn-tint); }
.saved-card-red { border-color: var(--red-edge); background: var(--red-tint); }
.saved-card-label { font-size: 0.9rem; font-weight: 600; color: var(--ink-2); }
.saved-card-note { font-size: 0.85rem; color: var(--ink-2); margin: 2px 0 6px; line-height: 1.45; }
.link-like { font-size: 0.88rem; font-weight: 600; color: var(--brand); }

/* Sign-in: what to do when you are locked out. Closed by default so it does
   not shout at everyone who can remember their password. */
.forgot { margin-top: 14px; }
.forgot summary {
  font-size: 0.92rem; font-weight: 600; color: var(--brand);
  cursor: pointer; padding: 8px 0; min-height: 44px;
  display: flex; align-items: center;
}
.forgot .card-sub { margin-top: 2px; }
.hero-cta { margin-top: 10px; }
.hero-xref {
  font-size: 0.85rem; line-height: 1.45; color: var(--ink-2);
  margin: 10px 0 0;
}
.hero-xref em { font-style: normal; font-weight: 600; color: var(--ink); }
/* Quieter than a payday note: this is a caveat, not news. */
.month-note-quiet { border-style: dashed; }
.month-note-quiet .icon { color: var(--ink-2); }

/* ---------- bars ---------- */

.bar { height: 8px; background: var(--track); border-radius: 99px; overflow: hidden; }
.bar-fill { height: 100%; background: var(--brand); border-radius: 99px; }
.bar-fill.bar-over { background: var(--red); }

/* ---------- income strip ---------- */

.income-strip {
  width: 100%;
  display: flex; align-items: center; gap: 10px;
  background: var(--brand-tint);
  color: var(--brand-deep);
  border-radius: var(--radius-card);
  padding: 12px 14px;
  margin-bottom: 12px;
  font-size: 0.95rem; font-weight: 500;
  text-align: left;
  box-shadow: var(--shadow-card);
}
.income-strip .icon { color: var(--brand); }
.income-strip strong { font-variant-numeric: tabular-nums; font-weight: 700; }
.income-strip:active { filter: brightness(0.97); }

/* ---------- install nudge ---------- */

.nudge {
  display: flex; gap: 8px; align-items: flex-start;
  background: var(--surface);
  border: 1px dashed var(--border);
  border-radius: var(--radius-card);
  padding: 14px;
  margin-bottom: 12px;
}
.nudge-body strong { font-size: 0.95rem; }
.nudge-body p { font-size: 0.88rem; color: var(--ink-2); margin-top: 2px; }

/* ---------- category list ---------- */

.cat-list { display: flex; flex-direction: column; gap: 8px; }
.section-label {
  font-size: 0.78rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--ink-2);
  margin: 18px 4px 8px;
}
.cat-row-unfunded {
  border-style: dashed;
  box-shadow: none;
  background: transparent;
  padding: 10px 14px;
}
.cat-row-unfunded .cat-name { color: var(--ink-2); font-weight: 500; }
.set-budget-chip {
  flex: none;
  font-size: 0.82rem; font-weight: 600;
  color: var(--brand-deep);
  background: var(--brand-tint);
  border-radius: 99px;
  padding: 4px 12px;
}
.hidden-tag {
  margin-left: 8px;
  font-size: 0.7rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em;
  background: var(--surface-2); color: var(--ink-2);
  border-radius: 99px; padding: 2px 8px;
  vertical-align: 2px;
}
.hidden-list { margin-top: 10px; border-top: 1px solid var(--border); }
.hidden-summary {
  list-style: none;
  display: flex; align-items: center; gap: 8px;
  min-height: 44px;
  font-size: 0.85rem; color: var(--ink-2);
  cursor: pointer;
}
.hidden-summary::-webkit-details-marker { display: none; }
.hidden-summary::before {
  content: "";
  width: 7px; height: 7px; flex: none;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(-45deg);
  transition: transform 0.15s ease-out;
}
.hidden-list[open] .hidden-summary::before { transform: rotate(45deg); }
.dim-row { color: var(--ink-2); }
.cat-row {
  width: 100%;
  background: var(--surface);
  border: 0;
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  padding: 12px 14px;
  text-align: left;
  transition: transform 0.12s ease-out;
}
.cat-row:active { transform: scale(0.985); }
.cat-row-top {
  display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
}
.cat-name {
  font-weight: 600; font-size: 1rem;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cat-left {
  font-weight: 700; font-size: 0.98rem; color: var(--brand-deep);
  font-variant-numeric: tabular-nums; flex: none;
}
.cat-row-sub {
  display: flex; justify-content: space-between;
  font-size: 0.84rem; color: var(--ink-2);
  margin: 1px 0 8px; font-variant-numeric: tabular-nums;
}

/* ---------- transactions ---------- */

.row-actions { display: flex; gap: 8px; margin-bottom: 14px; }
.tx-list {
  background: var(--surface);
  border: 0;
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  overflow: hidden;
}
.tx-row {
  width: 100%;
  display: flex; align-items: center; gap: 12px;
  padding: 12px 14px;
  text-align: left;
  border-bottom: 1px solid var(--border);
}
.tx-row:last-child { border-bottom: 0; }
.tx-row:active { background: var(--surface-2); }
.tx-mid { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.tx-note {
  font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tx-date { font-size: 0.82rem; color: var(--ink-2); }
.tx-amount { font-weight: 700; font-variant-numeric: tabular-nums; }

.member-dot {
  width: 32px; height: 32px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: var(--dot, var(--brand));
  color: #fff; font-size: 0.78rem; font-weight: 700; letter-spacing: 0.02em;
}
.member-dot.sm { width: 24px; height: 24px; font-size: 0.65rem; }

/* ---------- empty states ---------- */

.empty {
  text-align: center;
  padding: 36px 24px;
  color: var(--ink-2);
  font-size: 0.95rem;
  display: flex; flex-direction: column; gap: 14px; align-items: center;
}

/* ---------- year ---------- */

.year-totals { display: flex; gap: 8px; margin-bottom: 12px; }
.year-total-card {
  flex: 1;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow);
  padding: 12px 14px;
  display: flex; flex-direction: column; gap: 2px;
}
.year-total-label { font-size: 0.82rem; color: var(--ink-2); font-weight: 500; }
.year-total-card strong { font-size: 1.15rem; font-weight: 800; font-variant-numeric: tabular-nums; }
.year-list {
  background: var(--surface); border: 0;
  border-radius: var(--radius-card); box-shadow: var(--shadow-card); overflow: hidden;
}
.year-row {
  width: 100%;
  display: flex; align-items: center; gap: 12px;
  padding: 12px 14px; text-align: left;
  border-bottom: 1px solid var(--border);
}
.year-row:last-child { border-bottom: 0; }
.year-row:active { background: var(--surface-2); }
.year-month { width: 36px; font-weight: 700; color: var(--ink-2); flex: none; }
.year-mid { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.year-sub { font-size: 0.8rem; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.year-diff { font-weight: 600; font-size: 0.88rem; font-variant-numeric: tabular-nums; flex: none; }
.year-diff.pos { color: var(--brand-deep); }

/* ---------- family cards ---------- */

.card {
  background: var(--surface);
  border: 0;
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  padding: 18px;
  margin-bottom: 12px;
}
.card-title { font-size: 1.05rem; font-weight: 700; margin-bottom: 10px; }
.card-sub { font-size: 0.88rem; color: var(--ink-2); margin-bottom: 10px; }
.plain-list { display: flex; flex-direction: column; }
.member-row, .goal-row {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 0;
  border-bottom: 1px solid var(--border);
}
.plain-list li:last-child { border-bottom: 0; }
.you-tag {
  margin-left: 8px;
  font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em;
  background: var(--brand-tint); color: var(--brand-deep);
  border-radius: 99px; padding: 2px 8px;
}
.dim-amount { color: var(--ink-2); font-size: 0.9rem; font-variant-numeric: tabular-nums; flex: none; }
.struck { text-decoration: line-through; color: var(--ink-2); }

.goal-check {
  width: 26px; height: 26px; flex: none;
  border: 2px solid var(--border); border-radius: 8px;
  display: inline-flex; align-items: center; justify-content: center;
  color: #fff;
}
.goal-check.done { background: var(--brand); border-color: var(--brand); }
.goal-check .icon { width: 16px; height: 16px; }

.invite-row { display: flex; align-items: center; gap: 10px; }
.invite-code {
  flex: 1;
  font-size: 1.5rem; font-weight: 800; letter-spacing: 0.18em;
  background: var(--surface-2);
  border-radius: var(--radius-sm);
  padding: 10px 14px;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

.data-row { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }
.file-btn { position: relative; overflow: hidden; }
.file-btn input { position: absolute; inset: 0; opacity: 0; cursor: pointer; }
.sync-row {
  display: flex; align-items: center; gap: 10px;
  font-size: 0.88rem; color: var(--ink-2);
  border-top: 1px solid var(--border);
  padding-top: 12px;
}
/* Signing out is safe, not destructive — red stays reserved for "over". */
.signout { margin: 4px auto 0; color: var(--ink-2); display: flex; }

/* ---------- buttons ---------- */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font-weight: 600; font-size: 0.95rem;
  border-radius: 12px;
  padding: 11px 16px;
  min-height: 44px;
  transition: transform 0.12s ease-out, filter 0.12s ease-out;
}
.btn:active { transform: scale(0.97); }
.btn .icon { width: 18px; height: 18px; }
.btn-big { width: 100%; padding: 14px 18px; font-size: 1.02rem; }
.btn-primary { background: var(--brand); color: #fff; box-shadow: var(--shadow); }
.btn-primary:active { filter: brightness(0.92); }
.btn-primary:disabled { background: var(--ink-3); box-shadow: none; cursor: default; transform: none; }
.btn-secondary { background: var(--brand-tint); color: var(--brand-deep); }
.btn-secondary:active { filter: brightness(0.95); }
.btn-ghost { background: transparent; color: var(--brand-deep); padding: 8px 10px; min-height: 40px; }
.btn-danger { background: var(--red); color: #fff; }
.btn-danger-ghost { background: transparent; color: var(--red); }
.btn-danger-ghost:active { background: var(--red-tint); }

.row-x {
  width: 38px; height: 38px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%; color: var(--ink-2);
}
.row-x:active { background: var(--surface-2); }
.row-x .icon { width: 17px; height: 17px; }

/* ---------- forms ---------- */

.field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px; }
.field-label { font-size: 0.88rem; font-weight: 600; color: var(--ink-2); }
.field-hint {
  display: flex; gap: 8px; align-items: center;
  font-size: 0.85rem; color: var(--ink-2); margin: 4px 0 10px;
}
.field-hint .icon { width: 16px; height: 16px; flex: none; }
.input {
  width: 100%;
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 11px 12px;
  min-height: 46px;
  font-size: 1rem;
}
.input::placeholder { color: var(--ink-2); opacity: 1; }
.input:focus-visible,
.input:focus {
  border-color: var(--brand);
  outline: 2px solid var(--brand);
  outline-offset: 1px;
}
.input-code { text-transform: uppercase; letter-spacing: 0.2em; font-weight: 700; text-align: center; }
.form-error {
  background: var(--red-tint); color: var(--red);
  font-size: 0.9rem; font-weight: 500;
  border-radius: var(--radius-sm);
  padding: 10px 12px; margin-bottom: 12px;
}

.money-input { position: relative; width: 110px; flex: none; }
.money-sign {
  position: absolute; left: 10px; top: 50%; transform: translateY(-50%);
  color: var(--ink-2); font-weight: 600; pointer-events: none;
}
.input-money { padding-left: 24px; text-align: right; font-variant-numeric: tabular-nums; }

.toggle-row {
  display: flex; gap: 10px; align-items: flex-start;
  margin-top: 14px; font-size: 0.92rem;
}
.toggle-row input { width: 20px; height: 20px; accent-color: var(--brand); flex: none; margin-top: 1px; }

/* ---------- onboarding ---------- */

.onb {
  min-height: 100dvh;
  max-width: 560px; margin: 0 auto;
  padding: max(20px, env(safe-area-inset-top)) 22px calc(24px + env(safe-area-inset-bottom));
  display: flex; flex-direction: column;
}
.onb-hero { text-align: center; padding: 7vh 0 4vh; }
.brand-mark {
  width: 76px; height: 76px; margin: 0 auto 16px;
  background: var(--brand); color: #fff;
  border-radius: 22px;
  display: flex; align-items: center; justify-content: center;
  box-shadow: var(--shadow-raised);
}
.brand-mark .icon { width: 40px; height: 40px; }
.onb-title { font-size: 2.2rem; font-weight: 800; letter-spacing: -0.02em; }
.onb-tag { color: var(--ink-2); font-size: 1.02rem; margin-top: 6px; }
.onb-points { display: flex; flex-direction: column; gap: 16px; padding: 8px 4px 28px; }
.onb-points li { display: flex; gap: 14px; align-items: flex-start; font-size: 0.98rem; color: var(--ink-2); }
.onb-points li strong { color: var(--ink); font-weight: 700; }
.onb-points .icon { color: var(--brand); margin-top: 1px; }
.onb-actions { margin-top: auto; display: flex; flex-direction: column; gap: 10px; }

.onb-form { padding-top: max(12px, env(safe-area-inset-top)); }
.onb-back { align-self: flex-start; margin-bottom: 6px; margin-left: -8px; }
.onb-h2 { font-size: 1.55rem; font-weight: 800; letter-spacing: -0.01em; margin-bottom: 6px; }
.onb-sub { color: var(--ink-2); font-size: 0.95rem; margin-bottom: 18px; }
.onb-footer {
  position: sticky; bottom: 0;
  margin-top: auto;
  padding: 12px 0 max(4px, env(safe-area-inset-bottom));
  background: linear-gradient(to top, var(--bg) 70%, transparent);
  display: flex; flex-direction: column; gap: 8px;
}
.setup-total { font-size: 0.92rem; color: var(--ink-2); text-align: center; font-variant-numeric: tabular-nums; }
.setup-total strong { color: var(--brand-deep); }

.step-dots { display: flex; gap: 6px; margin-bottom: 16px; }
.step-dot { width: 8px; height: 8px; border-radius: 99px; background: var(--track); }
.step-dot.on { background: var(--brand); width: 22px; }
.step-dot.done { background: var(--brand); opacity: 0.45; }

.setup-list { display: flex; flex-direction: column; gap: 8px; margin-bottom: 12px; }
.setup-row { display: flex; gap: 8px; align-items: center; }
.src-name { font-weight: 500; }

.color-row { display: flex; gap: 10px; flex-wrap: wrap; }
.color-swatch {
  width: 40px; height: 40px; border-radius: 50%;
  background: var(--swatch);
  display: inline-flex; align-items: center; justify-content: center;
  color: #fff;
  border: 3px solid transparent;
  transition: transform 0.12s ease-out;
}
.color-swatch.on { border-color: var(--ink); transform: scale(1.08); }
.color-swatch .icon { width: 18px; height: 18px; }

/* ---------- tab bar ---------- */

.tabbar {
  position: fixed;
  left: 12px; right: 12px;
  bottom: max(12px, env(safe-area-inset-bottom));
  height: 68px;
  display: flex; align-items: center; justify-content: space-around;
  background: color-mix(in srgb, var(--surface) 88%, transparent);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-raised);
  padding: 0 8px;
  z-index: 20;
}
.tab {
  flex: 1;
  min-height: 52px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  color: var(--ink-2);
  border-radius: var(--radius);
}
.tab.on { color: var(--brand-deep); background: var(--brand-tint); box-shadow: inset 0 0 0 1px var(--brand); }
.tab.on .tab-label { font-weight: 800; }
.tabbar { gap: 4px; }
.tab-label { font-size: 0.72rem; font-weight: 600; }
.fab-add {
  width: 52px; height: 52px; flex: none;
  align-self: center;
  background: var(--brand); color: #fff;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  box-shadow: var(--shadow-raised);
  transition: transform 0.12s ease-out;
}
.fab-add:active { transform: scale(0.94); }
.fab-add .icon { width: 23px; height: 23px; }

/* ---------- sheets ---------- */

.sheet-back {
  position: fixed; inset: 0; z-index: 40;
  background: rgba(24, 34, 29, 0.45);
  display: flex; align-items: flex-end; justify-content: center;
  animation: fade-in 0.18s ease-out;
}
.sheet {
  width: 100%; max-width: 560px;
  max-height: 94dvh;
  background: var(--bg);
  border-radius: var(--radius-sheet) var(--radius-sheet) 0 0;
  display: flex; flex-direction: column;
  animation: slide-up 0.22s cubic-bezier(0.2, 0.9, 0.3, 1);
  overflow: hidden;
}
@keyframes slide-up { from { transform: translateY(40px); opacity: 0.6; } to { transform: none; opacity: 1; } }
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
.sheet-head {
  display: flex; align-items: center;
  padding: 8px 10px 0;
}
.sheet-title { flex: 1; text-align: center; font-size: 1.02rem; font-weight: 700; }
.sheet-spacer { width: 64px; }
.sheet-grip {
  width: 40px; height: 4px; border-radius: 2px;
  background: var(--border);
  margin: 8px auto 2px;
  flex: none;
}
.sheet-body { padding: 12px 18px 4px; overflow-y: auto; }
.sheet-footer {
  position: sticky; bottom: 0;
  padding: 10px 0 max(14px, env(safe-area-inset-bottom));
  background: var(--bg);
  border-top: 1px solid var(--border);
}
.sheet .btn-danger-ghost { margin: 0 auto 14px; }

/* ---------- add sheet ---------- */

.add-body { display: flex; flex-direction: column; overflow-y: auto; padding: 0 16px; }

/* The amount is one large field the phone's own number pad fills in. */
.amount-field {
  display: flex; align-items: baseline; justify-content: center;
  gap: 4px;
  padding: 18px 0 22px;
}
.amount-sign {
  font-size: clamp(1.8rem, 7vw, 2.2rem);
  font-weight: 700; color: var(--ink-2);
}
.amount-input {
  width: 100%;
  max-width: 7ch;
  border: 0; background: none; padding: 0;
  font-family: inherit;
  font-size: clamp(2.6rem, 13vw, 3.4rem);
  font-weight: 800; letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  color: var(--brand-deep);
  text-align: left;
}
.amount-input:focus { outline: none; }
/* ...but never with no indication at all: the field is borderless by design,
   so focus is shown as an underline rather than a ring. */
.amount-input:focus-visible,
.amount-input:focus {
  border-bottom: 2px solid var(--brand);
  padding-bottom: 2px;
}
.amount-input::placeholder { color: var(--ink-3); }

.add-fields { padding-bottom: 16px; }
.chip-row { display: flex; gap: 8px; align-items: center; margin-bottom: 10px; flex-wrap: wrap; }
.date-chip {
  border: 1.5px solid var(--border);
  background: var(--surface);
  border-radius: 99px;
  padding: 7px 14px;
  font-size: 0.88rem; font-weight: 600; color: var(--ink-2);
}
.date-chip.on { background: var(--ink); border-color: var(--ink); color: #fff; }
.date-chip-input { padding: 4px 10px; display: inline-flex; }
.date-input {
  border: 0; background: none; font-size: 0.88rem; font-weight: 600; color: var(--ink-2);
  width: 118px;
}

.where-label { font-size: 0.85rem; font-weight: 700; color: var(--ink-2); margin: 6px 0 8px; }
/* One scroll, not two: the chips flow and the sheet itself scrolls, so a
   row is never sliced in half by an inner scroll box. */
.where-wrap {
  display: flex; flex-wrap: wrap; gap: 8px;
  margin-bottom: 14px;
}
.where-chip {
  border: 1.5px solid var(--border);
  background: var(--surface);
  border-radius: 99px;
  padding: 8px 14px;
  font-size: 0.9rem; font-weight: 600;
  transition: transform 0.1s ease-out;
}
.where-chip:active { transform: scale(0.96); }
.where-chip.on { background: var(--brand); border-color: var(--brand); color: #fff; }
.note-input { margin: 8px 0 4px; }
.save-btn { margin: 0; }

/* ---------- tx actions sheet ---------- */

.tx-actions { padding: 10px 18px 8px; display: flex; flex-direction: column; gap: 10px; }
.tx-meta { display: flex; gap: 12px; align-items: center; padding: 6px 2px 10px; }
.tx-meta-text { display: flex; flex-direction: column; gap: 2px; }
.tx-meta-text span { font-size: 0.88rem; color: var(--ink-2); }

/* ---------- confirm modal ---------- */

.modal-back {
  position: fixed; inset: 0; z-index: 60;
  background: rgba(24, 34, 29, 0.45);
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
  animation: fade-in 0.15s ease-out;
}
.confirm {
  background: var(--surface);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-raised);
  padding: 20px;
  width: 100%; max-width: 360px;
}
.confirm h3 { font-size: 1.1rem; font-weight: 700; margin-bottom: 6px; }
.confirm p { color: var(--ink-2); font-size: 0.92rem; margin-bottom: 16px; }
.confirm-actions { display: flex; justify-content: flex-end; gap: 8px; }

/* ---------- toast ---------- */

.toast {
  position: fixed; left: 50%; bottom: calc(96px + env(safe-area-inset-bottom));
  transform: translateX(-50%) translateY(12px);
  background: var(--ink); color: var(--on-ink);
  font-size: 0.92rem; font-weight: 500;
  border-radius: 99px;
  padding: 11px 18px;
  box-shadow: var(--shadow-raised);
  opacity: 0; pointer-events: none;
  transition: opacity 0.2s ease-out, transform 0.2s ease-out;
  z-index: 80;
  max-width: min(92vw, 480px);
  text-align: center;
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

/* ---------- larger screens (iPad) ---------- */

@media (min-width: 700px) {
  .screen { max-width: 880px; padding-top: 24px; }
  .cat-list {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
  }
  .hero-amount { font-size: 3.4rem; }
  .sheet-back { align-items: center; }
  .sheet { border-radius: 20px; max-height: 86dvh; }
  .amount-input { font-size: 3.2rem; }
  .card { break-inside: avoid; }
}

@media (prefers-reduced-motion: reduce) {
  /* Movement goes away; feedback does not. State changes land instantly,
     and the "busy" spinner becomes a pulse so waiting still looks like
     waiting rather than a frozen screen. */
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .icon.spin svg {
    animation: pulse 1.4s ease-in-out infinite !important;
    animation-duration: 1.4s !important;
    animation-iteration-count: infinite !important;
  }
}

@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }

/* ---------- pay + import ---------- */

.select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2357675E' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9.5 12 15.5 18 9.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  background-size: 18px;
  padding-right: 34px;
}
.pay-card {
  background: var(--surface);
  border: 0;
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  padding: 12px 14px 4px;
}
.pay-card-head { display: flex; gap: 8px; align-items: center; margin-bottom: 8px; }
.pay-card-body { display: flex; flex-wrap: wrap; gap: 10px; }
.field-inline { flex: 1 1 150px; margin-bottom: 10px; }
.field-inline .money-input { width: 100%; }
.hidden { display: none; }
.src-expected { display: block; font-size: 0.8rem; color: var(--ink-2); font-weight: 400; }

.import-result {
  background: var(--brand-tint);
  border-radius: var(--radius-card);
  padding: 14px 16px;
  margin-bottom: 12px;
}
.import-result-head {
  display: flex; gap: 8px; align-items: center;
  color: var(--brand-deep); margin-bottom: 8px;
}
.import-facts { display: flex; flex-direction: column; gap: 4px; font-size: 0.92rem; color: var(--ink-2); }
.import-facts li { padding-left: 14px; position: relative; }
.import-facts li::before {
  content: ""; position: absolute; left: 0; top: 0.62em;
  width: 5px; height: 5px; border-radius: 50%; background: var(--brand);
}
.import-facts strong { color: var(--ink); font-variant-numeric: tabular-nums; }
.import-spinner { display: flex; justify-content: center; padding: 28px 0; color: var(--brand); }
.import-spinner .icon { width: 34px; height: 34px; }

/* ---------- touch targets ---------- */
/* Every control clears 44px of tappable height, even where the painted
   shape is smaller — fingers get the full box, the design keeps its scale. */

.row-x { width: 44px; height: 44px; }
.btn-ghost { min-height: 44px; }
.date-chip, .where-chip { min-height: 44px; display: inline-flex; align-items: center; }
.date-chip-input { padding: 0 10px; }
.date-input { min-height: 44px; }
.goal-check {
  width: 44px; height: 44px;
  border: 0; background: none; border-radius: 0;
  position: relative;
}
.goal-check::before {
  content: "";
  position: absolute; left: 9px; top: 9px;
  width: 26px; height: 26px;
  border: 2px solid var(--border); border-radius: 8px;
  background: var(--surface);
}
.goal-check.done::before { background: var(--brand); border-color: var(--brand); }
.goal-check .icon { position: relative; z-index: 1; }
.goal-row { gap: 4px; }

/* ---------- plan tab ---------- */

.setting-row {
  width: 100%;
  display: flex; align-items: center; gap: 10px;
  padding: 11px 0;
  min-height: 46px;
  text-align: left;
  border-bottom: 1px solid var(--border);
}
.plain-list li:last-child .setting-row { border-bottom: 0; }
.setting-row:active { background: var(--surface-2); }
.setting-row .icon { color: var(--ink-3); }
.plan-note {
  font-size: 0.9rem; color: var(--ink-2);
  margin: 0 4px 12px;
}
.plan-note strong { color: var(--brand-deep); font-variant-numeric: tabular-nums; }

/* ---------- income paycheques ---------- */

.pay-block {
  border-top: 1px solid var(--border);
  padding: 14px 0 6px;
}
.pay-block:first-child { border-top: 0; }
.pay-block-head {
  display: flex; align-items: baseline; gap: 10px;
  margin-bottom: 8px;
}
.pay-block-basis { font-size: 0.82rem; color: var(--ink-2); flex: none; }
.pay-rows { display: flex; flex-direction: column; gap: 8px; }
.pay-row { display: flex; align-items: center; gap: 10px; }
.pay-row-label { flex: 1; font-size: 0.92rem; color: var(--ink-2); }
.pay-hint {
  display: flex; gap: 6px; align-items: center;
  font-size: 0.82rem; color: var(--ink-2);
  margin-top: 8px;
}
.pay-hint .icon { width: 15px; height: 15px; flex: none; }
.pay-add { padding-left: 0; margin-top: 2px; }
.pay-total {
  display: flex; align-items: baseline; gap: 10px;
  border-top: 1px solid var(--border);
  padding-top: 12px; margin-top: 6px;
  font-size: 0.95rem; color: var(--ink-2);
}
.pay-total strong {
  font-size: 1.2rem; font-weight: 800; color: var(--brand-deep);
  font-variant-numeric: tabular-nums;
}

/* Says which month an entry will land in, shown only when that is not
   the month you are already looking at. */
.lands-note {
  display: none;
  gap: 6px; align-items: center;
  font-size: 0.85rem; color: var(--ink-2);
  margin: 0 0 10px;
}
.lands-note.show { display: flex; }
.lands-note strong { color: var(--ink); }
.lands-note .icon { width: 16px; height: 16px; flex: none; }

/* ---------- saved up ---------- */

.month-note {
  display: flex; gap: 10px; align-items: flex-start;
  background: var(--surface);
  border: 0;
  border-radius: var(--radius-card);
  padding: 12px 14px;
  margin-bottom: 12px;
  font-size: 0.9rem; color: var(--ink-2);
  box-shadow: var(--shadow-card);
}
.month-note .icon { color: var(--brand); flex: none; margin-top: 1px; }
.month-note strong { color: var(--ink); }

.saved-strip {
  width: 100%;
  display: flex; align-items: center; gap: 12px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow);
  padding: 12px 14px;
  margin-bottom: 12px;
  text-align: left;
}
.saved-strip:active { background: var(--surface-2); }
.saved-strip .icon { color: var(--brand); }
.saved-label { display: block; font-size: 0.82rem; color: var(--ink-2); font-weight: 500; }
.saved-amount {
  display: block;
  font-size: 1.15rem; font-weight: 800; color: var(--brand-deep);
  font-variant-numeric: tabular-nums;
}
.saved-strip.neg .saved-amount { color: var(--red); }
.saved-delta {
  flex: none; text-align: right;
  font-size: 0.92rem; font-weight: 700; color: var(--brand-deep);
  font-variant-numeric: tabular-nums;
}
.saved-delta.neg { color: var(--red); }
.saved-delta-sub {
  display: block;
  font-size: 0.72rem; font-weight: 500; color: var(--ink-2);
}

.saved-list {
  background: var(--surface);
  border: 0;
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  overflow: hidden;
}
.saved-row {
  padding: 12px 14px;
  border-bottom: 1px solid var(--border);
}
.saved-row:last-child { border-bottom: 0; }
.saved-row-top,
.saved-row-bottom {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
}
.saved-row-month { font-weight: 600; font-size: 0.98rem; }
.saved-row-net {
  font-weight: 700; font-size: 0.98rem; flex: none;
  font-variant-numeric: tabular-nums;
}
.saved-row-net.pos { color: var(--brand-deep); }
.saved-row-net.neg { color: var(--red); }
.saved-row-flow {
  font-size: 0.8rem; color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}
.saved-row-flow strong { color: var(--ink); font-weight: 600; }
.saved-row-run {
  font-size: 0.78rem; color: var(--ink-2); flex: none;
  font-variant-numeric: tabular-nums;
}
.field-note { font-size: 0.8rem; color: var(--ink-2); margin-top: 2px; }
.year-totals { flex-wrap: wrap; }
.year-total-card { min-width: 30%; }
.year-total-card strong.neg { color: var(--red); }
.year-row-future { opacity: 0.55; }
.year-diff.dim { color: var(--ink-2); }

/* ---------- install first ---------- */

.install-card {
  background: var(--surface);
  border: 0;
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  padding: 20px 18px;
}
.install-title {
  font-size: 1.25rem; font-weight: 800; letter-spacing: -0.01em;
  margin-bottom: 8px;
}
.install-why {
  font-size: 0.95rem; color: var(--ink-2);
  margin-bottom: 18px;
}
.install-why strong { color: var(--ink); }

.install-steps {
  display: flex; flex-direction: column; gap: 14px;
  margin-bottom: 18px;
  list-style: none;
}
.install-steps li {
  display: flex; gap: 12px; align-items: flex-start;
  font-size: 0.98rem; color: var(--ink-2);
}
.install-steps strong { color: var(--ink); font-weight: 700; }
.step-num {
  flex: none;
  width: 26px; height: 26px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: var(--brand-tint); color: var(--brand-deep);
  font-size: 0.85rem; font-weight: 700;
}
.install-note {
  display: flex; gap: 8px; align-items: center; justify-content: center;
  font-size: 0.88rem; color: var(--ink-2);
  margin-bottom: 4px;
}
.install-note .icon { width: 17px; height: 17px; flex: none; color: var(--brand); }
.version-line {
  text-align: center;
  font-size: 0.78rem; color: var(--ink-2);
  margin: 4px 0 2px;
}
.install-private {
  display: flex; gap: 8px; align-items: flex-start;
  background: var(--surface-2);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
  margin-bottom: 14px;
  font-size: 0.85rem; color: var(--ink-2);
}
.install-private .icon { width: 16px; height: 16px; flex: none; margin-top: 1px; }

/* ---------- money card ---------- */

.money-card { padding-bottom: 14px; }
.money-row,
.money-row-tap {
  width: 100%;
  display: flex; align-items: baseline; gap: 10px;
  padding: 9px 0;
  min-height: 44px;
  text-align: left;
}
.money-row-tap:active { background: var(--surface-2); }
.money-row-label { flex: 1; font-size: 0.95rem; color: var(--ink-2); }
.money-row-amount {
  font-size: 1.05rem; font-weight: 700; flex: none;
  font-variant-numeric: tabular-nums;
}
.money-row-amount.dim { color: var(--ink-2); font-weight: 600; }
.money-row-amount.neg { color: var(--red); }
.money-row-tap .icon { align-self: center; }

.money-total {
  display: flex; align-items: baseline; gap: 10px;
  border-top: 2px solid var(--ink);
  margin-top: 4px;
  padding-top: 12px;
}
.money-total .money-row-label { font-weight: 700; color: var(--ink); }
.money-total-amount {
  font-size: 1.5rem; font-weight: 800; flex: none;
  color: var(--brand-deep);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}
.money-total.neg .money-total-amount { color: var(--red); }
.money-note {
  font-size: 0.85rem; color: var(--ink-2);
  margin-top: 10px;
}
.link-btn {
  color: var(--brand-deep);
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 2px;
  padding: 0;
  min-height: 0;
}

/* ---------- one-verdict hero ---------- */

/* The subtraction that produces the hero figure, stated in one line so the
   family can see where the number came from without a second card. */
.hero-line {
  font-size: 0.9rem; color: var(--ink-2);
  text-wrap: pretty;
  margin: 2px 0 12px;
  font-variant-numeric: tabular-nums;
}
/* An inline link inside a sentence: grow the tappable box with padding and
   pull it back with margin, so the finger target grows and the line does not. */
.hero-line .link-btn {
  font-size: 0.9rem; font-weight: 700;
  padding: 12px 4px;
  margin: -12px -4px;
}
.money-input-wide { width: 100%; max-width: 220px; }
.money-input-wide .input-money { font-size: 1.3rem; font-weight: 700; }
.month-note-ok .icon { color: var(--brand); }
.month-note-warn { border-color: var(--amber); background: color-mix(in srgb, var(--amber) 12%, var(--surface)); }
.month-note-warn .icon { color: var(--amber-deep); }

/* ---------- add sheet: suggestions first ---------- */

.where-more { margin-bottom: 14px; }
.where-summary {
  list-style: none;
  display: flex; align-items: center; gap: 8px;
  min-height: 44px;
  font-size: 0.9rem; font-weight: 600;
  color: var(--brand-deep);
  cursor: pointer;
}
.where-summary::-webkit-details-marker { display: none; }
.where-summary::before {
  content: "";
  width: 8px; height: 8px; flex: none;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(-45deg);
  transition: transform 0.15s ease-out;
}
.where-more[open] .where-summary::before { transform: rotate(45deg); }
.where-search { margin-bottom: 10px; }

/* ---------- tab bar: the add key sits IN the bar ----------
   Three tabs cannot have a centred in-bar button: the bar's midpoint lands
   in the middle of the second tab. Floating it above the bar centres it but
   then it covers a card, a row, or a line of text on every screen. Sitting
   between the first and second tab covers nothing, which matters more than
   being exactly centred. */
.fab-add { order: 0; }

/* ---------- toast with an action ---------- */
.toast { display: flex; align-items: center; gap: 14px; }
.toast-action {
  flex: none;
  color: #9FD6BA;
  font-weight: 700;
  padding: 4px 2px;
  min-height: 36px;
}

/* Monthly spending and yearly spending each own their sticky heading. */
.budget-categories { margin: 18px 0 24px; }
.category-heading {
  position: sticky; top: 0; z-index: 10;
  display: flex; gap: 9px; align-items: center;
  padding: calc(12px + env(safe-area-inset-top)) 0 12px;
  margin: 0 0 10px;
  background: var(--bg); border-bottom: 1px solid var(--border);
  font-size: 1.05rem; font-weight: 800;
}
.category-heading .icon, .card-title > .icon { color: var(--brand); flex: none; }
.heading-year { color: var(--ink-2); font-size: .85rem; font-weight: 500; }
.card-title:has(> .icon) { display: flex; align-items: center; gap: 9px; }
.plan-hint { margin: 14px 0; font-size: .88rem; }
.plan-hint .link-btn { min-height: 44px; text-align: left; }
.detail-spacer { width: 44px; }
.plan-summary {
  position: sticky; top: 0; z-index: 10;
  display: flex; justify-content: space-between; align-items: center; gap: 12px;
  margin: 0 -2px 16px; padding: calc(12px + env(safe-area-inset-top)) 14px 12px;
  background: var(--brand-tint); color: var(--brand-deep);
  border: 1px solid var(--border); border-radius: 12px;
  font-size: .9rem; box-shadow: var(--shadow-card);
}
.plan-summary strong { font-variant-numeric: tabular-nums; white-space: nowrap; }
.plan-summary-over { color: var(--red); background: var(--red-tint); }
/* The concept is HTML text with scalable native icons, so it stays legible on phones. */
.concept-screen { max-width: 520px; margin: auto; }
.concept-lead { font-size: 1.15rem; font-weight: 700; margin: 4px 0 18px; }
.concept-flow { margin: 0 0 20px; }
.concept-in { text-align: center; }
.concept-in strong { display: block; font-size: 1.05rem; }
.concept-in span, .concept-out span, .concept-transfer p span { display: block; color: var(--ink-2); font-size: .85rem; font-weight: 400; }
.concept-arrow { text-align: center; color: var(--brand); font-size: 1.7rem; line-height: 1.2; }
.concept-account { display: grid; grid-template-columns: 72px 1fr; align-items: center; gap: 0 12px; padding: 14px; border: 1px solid var(--border); border-radius: 18px; background: var(--surface); }
.concept-account h3 { font-size: 1.08rem; }
.concept-account p { font-size: .9rem; color: var(--ink-2); }
.concept-bowl { width: 72px; height: 60px; color: var(--brand); }
.concept-account .concept-out { grid-column: 1 / -1; margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border); color: var(--brand-deep); font-weight: 700; }
.concept-account-small { margin: 0 12px; background: var(--brand-tint); }
.concept-transfer { display: flex; align-items: center; justify-content: center; gap: 14px; padding: 14px 0; }
.concept-transfer p { font-size: .9rem; }
.concept-flow figcaption { margin: 12px 4px 0; font-size: .8rem; color: var(--ink-2); }
.concept-rule { font-size: .95rem; margin-bottom: 16px; }
.concept-tabs { background: var(--surface); border-radius: 14px; padding: 14px; }
.concept-tabs p { display: flex; gap: 10px; font-size: .9rem; }
.concept-tabs p + p { margin-top: 12px; }
.concept-tabs .icon { color: var(--brand); flex: none; }
.concept-refresher { margin: 14px 0; font-size: .8rem; color: var(--ink-2); }
.concept-preference { display: flex; align-items: center; gap: 10px; min-height: 44px; padding: 8px 0; font-size: .82rem; color: var(--ink-2); }
.concept-preference input { width: 20px; height: 20px; flex: none; accent-color: var(--brand); }
.concept-screen > .btn { margin-top: 10px; }

.setting-row .grow { overflow-wrap: anywhere; }
@media (max-width: 440px) {
  .income-setting { display: grid; grid-template-columns: minmax(0, 1fr) 24px; gap: 3px 10px; }
  .income-setting .grow { grid-column: 1; }
  .income-setting .dim-amount { grid-column: 1; grid-row: 2; font-size: .85rem; }
  .income-setting > .icon { grid-column: 2; grid-row: 1 / span 2; }
}
