  :root {
    --bg: #f6f5f1; --panel: #ffffff; --line: #e9e7e0; --text: #22221f; --muted: #8c897f;
    --faint: #efede7; --good: #5d7f6c; --spend: #c47a58; --income: #9fb8a8; --warn: #b8893a;
    --radius: 20px; --shadow: 0 18px 50px rgba(34, 34, 31, .12);
  }
  @media (prefers-color-scheme: dark) {
    :root {
      --bg: #151614; --panel: #1d1e1b; --line: #2b2c28; --text: #ecebe6; --muted: #8f8d85;
      --faint: #262723; --good: #8fb39e; --spend: #d9936f; --income: #4f6b5b; --warn: #d6a95a;
      --shadow: 0 18px 50px rgba(0, 0, 0, .5);
    }
  }

  /* ---------- Themes (set on <html data-theme="…">; none = follow the system) ---------- */
  :root { --accent: var(--text); --on-accent: var(--bg); color-scheme: light dark; }
  html[data-theme="light"] { --bg: #f6f5f1; --panel: #ffffff; --line: #e9e7e0; --text: #22221f; --muted: #8c897f; --faint: #efede7;
    --good: #5d7f6c; --spend: #c47a58; --income: #9fb8a8; --warn: #b8893a; --shadow: 0 18px 50px rgba(34,34,31,.12); color-scheme: light; }
  html[data-theme="dark"] { --bg: #151614; --panel: #1d1e1b; --line: #2b2c28; --text: #ecebe6; --muted: #8f8d85; --faint: #262723;
    --good: #8fb39e; --spend: #d9936f; --income: #4f6b5b; --warn: #d6a95a; --shadow: 0 18px 50px rgba(0,0,0,.5); color-scheme: dark; }
  html[data-theme="midnight"] { --bg: #0a0f1e; --panel: #111830; --line: #1f2946; --text: #e8ecfa; --muted: #8b97bb; --faint: #19223f;
    --good: #34d399; --spend: #fb7185; --income: #38bdf8; --warn: #fbbf24; --accent: #7c5cff; --on-accent: #ffffff;
    --hero-grad: linear-gradient(90deg, #a78bfa, #38bdf8); --shadow: 0 18px 50px rgba(0,0,0,.6); color-scheme: dark; }
  html[data-theme="neon"] { --bg: #0d0221; --panel: #170838; --line: #2c1860; --text: #f6f2ff; --muted: #a79bd6; --faint: #221049;
    --good: #2ef2b4; --spend: #ff4d9d; --income: #00e0ff; --warn: #ffd166; --accent: #ff2e97; --on-accent: #ffffff;
    --hero-grad: linear-gradient(90deg, #ff2e97, #ffb347 55%, #00e0ff); --shadow: 0 18px 60px rgba(255,46,151,.15); color-scheme: dark; }
  html[data-theme="ocean"] { --bg: #041318; --panel: #0a2029; --line: #15343f; --text: #e2f5f8; --muted: #7ea5ae; --faint: #0f2b35;
    --good: #2dd4bf; --spend: #ff8a4c; --income: #3b9eff; --warn: #facc15; --accent: #14b8a6; --on-accent: #032126;
    --hero-grad: linear-gradient(90deg, #5eead4, #3b9eff); --shadow: 0 18px 50px rgba(0,0,0,.55); color-scheme: dark; }
  html[data-theme="sunrise"] { --bg: #fff7ee; --panel: #ffffff; --line: #f3e2cf; --text: #221a14; --muted: #8e7765; --faint: #fdecd9;
    --good: #0f9d6b; --spend: #e8452c; --income: #2f7ff0; --warn: #d98b00; --accent: #e8452c; --on-accent: #ffffff;
    --hero-grad: linear-gradient(90deg, #e8452c, #f59e0b); --shadow: 0 18px 50px rgba(232,69,44,.12); color-scheme: light; }
  html[data-theme="forest"] { --bg: #0e1612; --panel: #15211b; --line: #233429; --text: #e7f0e9; --muted: #8aa596; --faint: #1b2a22;
    --good: #6fcf97; --spend: #f2994a; --income: #56ccf2; --warn: #f2c94c; --accent: #6fcf97; --on-accent: #08130d;
    --hero-grad: linear-gradient(90deg, #6fcf97, #f2c94c); --shadow: 0 18px 50px rgba(0,0,0,.55); color-scheme: dark; }
  html[data-theme="nord"] { --bg: #242933; --panel: #2e3440; --line: #3b4252; --text: #eceff4; --muted: #a3acbd; --faint: #353c4a;
    --good: #a3be8c; --spend: #d08770; --income: #88c0d0; --warn: #ebcb8b; --accent: #88c0d0; --on-accent: #242933;
    --hero-grad: linear-gradient(90deg, #88c0d0, #b48ead); --shadow: 0 18px 50px rgba(0,0,0,.45); color-scheme: dark; }
  html[data-theme="rose"] { --bg: #fdf6f7; --panel: #ffffff; --line: #f1dfe3; --text: #2a1b20; --muted: #95747d; --faint: #f9e8ec;
    --good: #2f9e72; --spend: #d6456e; --income: #6b7fe0; --warn: #c98a1b; --accent: #d6456e; --on-accent: #ffffff;
    --hero-grad: linear-gradient(90deg, #d6456e, #9b6bdf); --shadow: 0 18px 50px rgba(214,69,110,.12); color-scheme: light; }
  html[data-theme="carbon"] { --bg: #161618; --panel: #1f1f23; --line: #2f2f36; --text: #f3f3f5; --muted: #9b9ba6; --faint: #2a2a30;
    --good: #39ff9f; --spend: #ff3d81; --income: #19e3ff; --warn: #ffe14d; --accent: #39ff9f; --on-accent: #0b0b0c;
    --hero-grad: linear-gradient(90deg, #39ff9f, #19e3ff); --shadow: 0 18px 50px rgba(0,0,0,.6); color-scheme: dark; }
  html[data-theme="carbon"] .fill { box-shadow: 0 0 10px color-mix(in srgb, var(--spend) 70%, transparent); }
  html[data-theme="carbon"] .fill.good { box-shadow: 0 0 10px color-mix(in srgb, var(--good) 70%, transparent); }
  html[data-theme="carbon"] .btn.primary { box-shadow: 0 0 16px color-mix(in srgb, var(--accent) 45%, transparent); }
  /* selected nav: a soft accent tint plus a short glowing pill, instead of an outlined box with a corner-clipped bar */
  html[data-theme="carbon"] .nav a.on { position: relative; background: color-mix(in srgb, var(--accent) 9%, transparent); box-shadow: none; }
  html[data-theme="carbon"] .nav a.on::before { content: ""; position: absolute; left: 0; top: 50%; width: 3px; height: 16px; margin-top: -8px; border-radius: 0 3px 3px 0;
    background: var(--accent); box-shadow: 0 0 8px color-mix(in srgb, var(--accent) 60%, transparent); }
  html[data-theme="carbon"] .nav a.on svg { filter: drop-shadow(0 0 3px color-mix(in srgb, var(--accent) 50%, transparent)); }
  html[data-theme="carbon"] .chart rect { filter: drop-shadow(0 0 6px currentColor); }
  html[data-theme="carbon"] .pos, html[data-theme="carbon"] .down { text-shadow: 0 0 10px color-mix(in srgb, var(--good) 45%, transparent); }
  html[data-theme="carbon"] .neg, html[data-theme="carbon"] .up { text-shadow: 0 0 10px color-mix(in srgb, var(--spend) 45%, transparent); }
  html[data-theme="carbon"] .big { filter: drop-shadow(0 0 18px rgba(57,255,159,.25)); }
  /* glow on the underline only, inside the tab: an outer shadow is clipped by the scrolling tab row and leaves a sliver at the tab's right edge */
  html[data-theme="carbon"] .tabs a.on { box-shadow: 0 0 14px color-mix(in srgb, var(--accent) 45%, transparent); }
  html[data-theme="carbon"] .bulkbar { box-shadow: 0 0 20px color-mix(in srgb, var(--accent) 25%, transparent); }
  html[data-theme] .big.negative { --hero-grad: linear-gradient(90deg, var(--spend), var(--warn)); }
  html[data-theme="carbon"] .big.negative { filter: drop-shadow(0 0 18px rgba(255,61,129,.3)); }
  html[data-theme] .big { background: var(--hero-grad, none); -webkit-background-clip: text; background-clip: text; }
  html[data-theme="midnight"] .big, html[data-theme="neon"] .big, html[data-theme="ocean"] .big, html[data-theme="sunrise"] .big, html[data-theme="carbon"] .big, html[data-theme="glass"] .big,
  html[data-theme="forest"] .big, html[data-theme="nord"] .big, html[data-theme="rose"] .big { color: transparent; }
  .btn.primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
  .nav a.on svg { color: var(--accent); }
  .seg button.on { color: var(--accent); }
  .tabs a.on { border-color: var(--accent); }
  input:focus, select:focus, textarea:focus { border-color: var(--accent); }
  .themes { display: flex; flex-wrap: wrap; gap: 8px; padding: 6px 12px 12px; }
  .settings .themes button.on { outline: 2px solid var(--accent); outline-offset: 2px; }
  .settings .themes button { display: inline-block; width: 34px; height: 34px; border-radius: 50%; border: 2px solid var(--line); cursor: pointer; padding: 0; }
  .foot .label { font-size: 11px; text-transform: uppercase; letter-spacing: .08em; color: var(--muted); padding: 0 12px; }
  * { box-sizing: border-box; }
  html, body { margin: 0; background: var(--bg); color: var(--text); }
  body { font: 14.5px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto, sans-serif; -webkit-font-smoothing: antialiased; }
  a { color: inherit; }
  button, input, select, textarea { font: inherit; color: inherit; }
  .num { font-variant-numeric: tabular-nums; }
  [hidden] { display: none !important; }

  /* ---------- Shell ---------- */
  .app { display: grid; grid-template-columns: 224px 1fr; min-height: 100vh; }
  .side { position: sticky; top: 0; height: 100vh; padding: 28px 16px; border-right: 1px solid var(--line); display: flex; flex-direction: column; gap: 4px; overflow-y: auto; }
  .brand { font-weight: 650; font-size: 17px; letter-spacing: -.01em; padding: 0 12px 22px; }
  .nav a { display: flex; align-items: center; gap: 11px; padding: 8px 12px; border-radius: 10px; text-decoration: none; color: var(--muted); font-weight: 500; }
  .nav a:hover { background: var(--faint); color: var(--text); }
  .nav a.on { background: var(--panel); color: var(--text); box-shadow: 0 1px 0 var(--line), 0 0 0 1px var(--line); }
  .nav svg { width: 17px; height: 17px; flex: none; }
  .nav-h { font-size: 11px; text-transform: uppercase; letter-spacing: .08em; color: var(--muted); padding: 16px 12px 5px; }
  .side .foot .nav a { display: flex; align-items: center; gap: 11px; padding: 8px 12px; border-radius: 10px; font-size: inherit; font-weight: 500; margin-bottom: 6px; }
  .side .foot .nav a.on { color: var(--text); }
  .list.menu .row { padding: 13px 0; align-items: center; }
  .list.menu .row .name { display: flex; gap: 12px; align-items: center; }
  .list.menu .ic { width: 20px; height: 20px; display: inline-flex; flex: none; }
  .list.menu .ic svg { width: 20px; height: 20px; flex: none; }     /* sized outright: Safari can give an unsized svg in a flex box no height */
  .list.menu + .list.menu { margin-top: 12px; border-top: 1px solid var(--line); }     /* Settings, set apart from the pages above it */
  .list.menu + .list.menu .row:first-child { padding-top: 13px; }
  .menu-h { margin: 22px 0 2px; }
  .side .spacer { flex: 1; }
  .side .foot a, .side .foot button { display: block; width: 100%; text-align: left; background: none; border: 0; padding: 7px 12px; color: var(--muted); font-size: 13px; text-decoration: none; cursor: pointer; border-radius: 8px; }
  .side .foot a:hover, .side .foot button:hover { background: var(--faint); color: var(--text); }
  main { padding: 34px 44px 72px; width: 100%; }

  /* ---------- Page head ---------- */
  .head { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; margin-bottom: 28px; flex-wrap: wrap; }
  .head h1 { font-size: 26px; font-weight: 600; letter-spacing: -.02em; margin: 0; }
  .head .sub { color: var(--muted); margin: 2px 0 0; font-size: 13.5px; }
  .head .actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
  .month { display: flex; align-items: center; gap: 4px; }
  .month span { min-width: 132px; text-align: center; font-weight: 500; }
  .month .today-gap { visibility: hidden; }
  .month span small.cycle { display: block; font-size: 11px; font-weight: 400; color: var(--muted); line-height: 1.2; }
  .round { width: 32px; height: 32px; border-radius: 50%; border: 1px solid var(--line); background: var(--panel); cursor: pointer; font-size: 15px; line-height: 1; }
  .round:disabled { opacity: .35; cursor: default; }

  /* ---------- Buttons & inputs ---------- */
  .btn { display: inline-flex; align-items: center; gap: 6px; padding: 8px 15px; border-radius: 10px; border: 1px solid var(--line); background: var(--panel); cursor: pointer; font-weight: 500; text-decoration: none; white-space: nowrap; }
  .btn:hover { border-color: var(--muted); }
  .btn.primary:hover { opacity: .88; }
  .btn.danger { color: var(--spend); }
  .btn.small { padding: 5px 11px; font-size: 13px; border-radius: 8px; }
  .btn:disabled { opacity: .5; cursor: default; }
  .link { background: none; border: 0; padding: 0; color: var(--muted); cursor: pointer; text-decoration: underline; text-underline-offset: 3px; font-size: 13px; }
  .link:hover { color: var(--text); }
  label { display: block; font-size: 12.5px; color: var(--muted); margin-bottom: 14px; }
  label > input, label > select, label > textarea { display: block; width: 100%; margin-top: 5px; }
  input[type=text], input[type=number], input[type=date], input[type=password], input[type=search], select, textarea {
    padding: 9px 12px; border: 1px solid var(--line); border-radius: 10px; background: var(--panel); font-size: 14.5px; outline: none; min-width: 0; max-width: 100%; }
  input:focus, select:focus, textarea:focus { border-color: var(--muted); }
  textarea { resize: vertical; }
  label.check { display: flex; align-items: center; gap: 8px; font-size: 13.5px; color: var(--text); }
  label.check input { width: auto; margin: 0; }
  .grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 0 14px; }
  .grid2 > * { min-width: 0; }
  .seg { display: inline-flex; flex-wrap: wrap; max-width: 100%; background: var(--faint); border-radius: 12px; padding: 3px; margin-bottom: 18px; }
  .seg button { border: 0; background: none; padding: 7px 16px; border-radius: 9px; cursor: pointer; color: var(--muted); font-weight: 500; }
  .seg button.on { background: var(--panel); color: var(--text); box-shadow: 0 1px 3px rgba(0,0,0,.08); }
  .tabs { display: flex; gap: 22px; border-bottom: 1px solid var(--line); margin-bottom: 20px; overflow-x: auto; }
  .tabs a { padding: 0 0 11px; text-decoration: none; color: var(--muted); font-weight: 500; border-bottom: 2px solid transparent; margin-bottom: -1px; white-space: nowrap; }
  .tabs a.on { color: var(--text); border-color: var(--accent); }
  .toolbar { display: flex; gap: 12px; align-items: center; justify-content: space-between; margin-bottom: 16px; flex-wrap: wrap; }
  .cleanup-list { display: flex; flex-direction: column; gap: 20px; max-width: 720px; }
  .cleanup .row.check { justify-content: flex-start; align-items: center; gap: 10px; margin: 0; cursor: pointer; }
  .cleanup .btn { margin-top: 14px; }
  .report-empty { margin: -4px 4px 20px; }
  /* Reports: what it went on (categories, budgets, tags) on the left, who it went to or came from on the right */
  .report-cols { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px; align-items: start; margin-bottom: 20px; }
  .report-cols > div { display: flex; flex-direction: column; gap: 20px; min-width: 0; }
  .report-cols > div:empty { display: none; }
  @media (max-width: 900px) { .report-cols { grid-template-columns: minmax(0, 1fr); } }
  .search { position: relative; flex: 1; max-width: 420px; }
  .search input { width: 100%; padding-left: 36px; }
  .search svg { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); width: 16px; height: 16px; color: var(--muted); pointer-events: none; }

  /* ---------- Panels ---------- */
  .panel { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); padding: 26px; }
  .panel h2 { font-size: 15px; font-weight: 600; margin: 0 0 3px; }
  .panel .lead { color: var(--muted); font-size: 13px; margin: 0 0 20px; }
  .panel.flush { padding: 0; overflow: hidden; }
  .panel-head { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
  .eyebrow { font-size: 11.5px; text-transform: uppercase; letter-spacing: .09em; color: var(--muted); margin-bottom: 5px; }
  .grid { display: grid; grid-template-columns: 1.25fr 1fr; gap: 20px; }
  .stack { display: grid; gap: 20px; align-content: start; }
  .full { grid-column: 1 / -1; }
  /* Overview cards: flow into as many ~380px columns as fit, balanced automatically */
  .cards { columns: 3 380px; column-gap: 20px; margin-bottom: 20px; }
  .cards > .panel { break-inside: avoid; display: inline-block; width: 100%; margin-bottom: 20px; }
  /* Settings: named groups of rows in one column, with rarely used forms folded away */
  .settings { max-width: 720px; }
  /* One category at a time (settings.ts). Wide screens: the title and the list of categories on the left, staying in
     place (it sticks at main's top padding, where it starts, so it never moves). Phones: the list is the first screen. */
  .set-nav { display: none; }
  @media (min-width: 1100px) {
    .set-layout { display: grid; grid-template-columns: 184px minmax(0, 720px); gap: 36px; align-items: start; }
    .set-side { position: sticky; top: 34px; }
    html.compact .set-side { top: 24px; }
    .set-side .head { margin-bottom: 20px; padding-left: 12px; }
    .set-nav { display: flex; flex-direction: column; gap: 2px; }
    .set-nav a { padding: 8px 12px; border-radius: 9px; color: var(--muted); font-size: 14px; font-weight: 500; text-decoration: none; transition: background .12s, color .12s; }
    .set-nav a:hover { background: var(--faint); color: var(--text); }
    .set-nav a.on { background: var(--panel); color: var(--text); box-shadow: 0 0 0 1px var(--line); }
  }
  @media (max-width: 1099px) {
    .settings > .set-group > .set-h { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }   /* the page title already names it */
  }
  .set-menu a.set-row { color: var(--text); text-decoration: none; }
  .set-menu .set-label { display: flex; flex-direction: column; gap: 1px; }
  .set-menu .chev { width: 16px; height: 16px; flex: none; color: var(--muted); }
  .set-back { display: inline-flex; align-items: center; gap: 2px; margin: 0 0 6px -10px; padding: 4px 8px 4px 2px; border-radius: 8px; color: var(--accent); font-size: 15px; font-weight: 500; text-decoration: none; }
  .set-back svg { width: 20px; height: 20px; flex: none; }
  .set-group { margin-bottom: 28px; }
  .set-h { font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: .08em; color: var(--muted); margin: 0 0 8px 4px; }
  .set-panel { padding: 0 20px; }
  .set-foot { font-size: 12.5px; color: var(--muted); margin: 8px 4px 0; line-height: 1.45; }
  .set-row, .set-more > summary { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 13px 0; min-height: 50px; box-sizing: border-box; }
  .set-panel > * + * { border-top: 1px solid var(--line); }
  .set-label { min-width: 0; flex: 1 1 auto; }
  .set-label .sub-s { margin-top: 2px; line-height: 1.4; }
  .set-ctl { display: flex; align-items: center; gap: 10px; flex: none; max-width: 60%; color: var(--muted); }
  .set-ctl select { width: auto; min-width: 120px; margin: 0; }
  .set-ctl .themes { padding: 0; justify-content: flex-end; }
  .set-ctl .themes button { width: 26px; height: 26px; }
  .set-code { overflow-wrap: anywhere; font-size: 12.5px; }
  .set-key input { width: 130px; min-width: 0; margin: 0; font-family: ui-monospace, monospace; font-size: 13px; }
  .set-more > summary { cursor: pointer; list-style: none; }
  .set-more > summary::-webkit-details-marker { display: none; }
  .set-more > summary::after { content: ''; flex: none; width: 7px; height: 7px; margin: 0 4px 0 -6px; border: solid var(--muted); border-width: 0 1.5px 1.5px 0; transform: rotate(-45deg); transition: transform .15s; }
  .set-more[open] > summary::after { transform: rotate(45deg); }
  .set-more > summary > :first-child { flex: 1; }
  .set-body { padding: 0 0 16px; }
  .set-body > p.sub-s { line-height: 1.45; }
  /* Customize: colour wells and sliders in the Appearance group */
  .set-ctl input[type=color] { -webkit-appearance: none; appearance: none; width: 44px; height: 30px; margin: 0; padding: 2px; border: 1px solid var(--line); border-radius: 9px; background: none; cursor: pointer; }
  .set-ctl input[type=color]::-webkit-color-swatch-wrapper { padding: 0; }
  .set-ctl input[type=color]::-webkit-color-swatch { border: 0; border-radius: 6px; }
  .set-ctl input[type=color]::-moz-color-swatch { border: 0; border-radius: 6px; }
  .set-ctl input[type=range] { width: 150px; margin: 0; accent-color: var(--accent); }
  .set-ctl output { min-width: 40px; text-align: right; font-variant-numeric: tabular-nums; font-size: 13px; }
  .theme-custom > * + * { border-top: 1px solid var(--line); }
  .set-inline { display: flex; gap: 8px; } .set-inline select { flex: 1; margin: 0; }
  input.switch { -webkit-appearance: none; appearance: none; flex: none; width: 46px; height: 28px; margin: 0; padding: 0; border: 0; border-radius: 99px; background: var(--line); position: relative; cursor: pointer; transition: background .18s; }
  input.switch::after { content: ''; position: absolute; top: 3px; left: 3px; width: 22px; height: 22px; border-radius: 50%; background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.25); transition: transform .18s; }
  input.switch:checked { background: var(--accent); }
  input.switch:checked::after { transform: translateX(18px); }
  input.switch:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
  @media (max-width: 520px) {
    .set-panel { padding: 0 16px; }
    .set-row:has(.themes), .set-row:has(.set-key) { flex-wrap: wrap; }
    .set-row:has(.themes) .set-ctl, .set-row:has(.set-key) .set-ctl { max-width: none; width: 100%; }
    .set-ctl .themes { justify-content: flex-start; }
    .set-key input { flex: 1; }
    .set-ctl input[type=range] { width: 110px; }
  }
  .wide { display: grid; grid-template-columns: 1fr; gap: 20px; }
  @media (min-width: 1700px) { .wide { grid-template-columns: 1fr 1.4fr; } }
  .hero { display: grid; grid-template-columns: 1.3fr 2fr; gap: 32px; align-items: end; margin-bottom: 40px; }
  .big { font-size: 52px; font-weight: 300; letter-spacing: -.03em; line-height: 1; }
  .stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; }
  .stat .val { font-size: 25px; letter-spacing: -.02em; }
  .stat .sub, .sub-s { font-size: 12.5px; color: var(--muted); }
  .kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 16px; margin-bottom: 22px; }
  .kpi { background: var(--panel); border: 1px solid var(--line); border-radius: 16px; padding: 16px 18px; }
  .kpi .val { font-size: 22px; letter-spacing: -.02em; }
  .total { font-size: 28px; font-weight: 300; letter-spacing: -.02em; margin-bottom: 14px; }
  .up { color: var(--spend); } .down { color: var(--good); }
  .neg { color: var(--spend); } .pos { color: var(--good); } .neutral { color: var(--muted); }

  .row { display: flex; justify-content: space-between; gap: 12px; align-items: baseline; }
  .row .name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .list .row { padding: 10px 0; border-top: 1px solid var(--line); }
  .list .row:first-child { border-top: none; padding-top: 0; }
  .list a.row { text-decoration: none; }
  .list a.row:hover .name { text-decoration: underline; text-underline-offset: 3px; }
  .track { position: relative; height: 6px; background: var(--faint); border-radius: 99px; margin: 7px 0 4px; }
  .fill { position: absolute; inset: 0 auto 0 0; background: var(--spend); border-radius: 99px; opacity: .85; max-width: 100%; }
  .fill.good { background: var(--good); } .fill.over { background: var(--spend); opacity: 1; }
  .fill.warn { background: var(--warn, #d9a13b); } .track.pace .today { position: absolute; top: -3px; bottom: -3px; width: 2px; margin-left: -1px; background: var(--text); opacity: .45; border-radius: 2px; }
  .panel.drafts { margin-bottom: 16px; } .panel.drafts .row .name { font: inherit; color: inherit; }
  .tick { position: absolute; top: -4px; width: 2px; height: 14px; background: var(--text); opacity: .35; border-radius: 1px; }
  .cat { margin-bottom: 16px; } .cat:last-child { margin-bottom: 0; }
  .cat .sub { font-size: 12px; color: var(--muted); }
  .legend { display: flex; gap: 16px; font-size: 12px; color: var(--muted); margin-top: 18px; }
  .legend i { display: inline-block; width: 10px; height: 10px; border-radius: 3px; margin-right: 6px; vertical-align: -1px; }
  .chart svg { width: 100%; height: auto; display: block; }
  .chart text { fill: var(--muted); font-size: 12px; }
  .empty { color: var(--muted); font-size: 14px; padding: 6px 0; }
  .center-empty { text-align: center; color: var(--muted); padding: 48px 20px; }
  .loading { color: var(--muted); padding: 90px 0; text-align: center; }
  .error { background: var(--faint); border-radius: 14px; padding: 16px 18px; color: var(--text); }
  .chip { display: inline-block; font-size: 11.5px; padding: 1px 8px; border-radius: 99px; background: var(--faint); color: var(--muted); margin-right: 4px; white-space: nowrap; }
  .chip.good { color: var(--good); } .chip.warn { color: var(--warn); } .chip.bad { color: var(--spend); }
  .saved-reports { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin: 0 0 16px; } .saved-reports .chip { font-size: 13px; padding: 3px 4px 3px 10px; display: inline-flex; gap: 4px; align-items: center; margin: 0; } .saved-reports .chip a { color: inherit; text-decoration: none; } .saved-reports .chip.on { color: var(--text); box-shadow: inset 0 0 0 1px var(--line); } .saved-reports .chip button { border: 0; background: none; color: inherit; cursor: pointer; font-size: 14px; padding: 0 4px; } .save-report { display: inline-flex; gap: 6px; } .save-report input { width: 190px; padding: 4px 10px; font-size: 13px; }
  .tagcloud { display: flex; flex-wrap: wrap; gap: 8px; }
  .tagcloud .chip { font-size: 13px; padding: 4px 6px 4px 12px; display: inline-flex; gap: 6px; align-items: center; }
  .tagcloud .chip a { text-decoration: none; color: var(--text); }
  .tagcloud .chip button { border: 0; background: none; cursor: pointer; color: var(--muted); padding: 0 4px; font-size: 14px; }

  /* ---------- Tables ---------- */
  table.tbl { width: 100%; border-collapse: collapse; }
  .tbl th { text-align: left; font-size: 11.5px; text-transform: uppercase; letter-spacing: .07em; color: var(--muted); font-weight: 500; padding: 14px 16px 10px; border-bottom: 1px solid var(--line); }
  .tbl td { padding: 12px 16px; border-bottom: 1px solid var(--line); vertical-align: middle; }
  .tbl tr:last-child td { border-bottom: none; }
  .tbl tr.click { cursor: pointer; }
  .tbl tr.click:hover td { background: var(--faint); }
  .tbl .r { text-align: right; }
  .tbl .date { color: var(--muted); white-space: nowrap; width: 80px; }
  .tbl .desc { font-weight: 500; }
  .tbl .meta { margin-top: 3px; }
  .tbl .flow { color: var(--muted); font-size: 13px; max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .tbl .amt { text-align: right; white-space: nowrap; font-weight: 500; font-variant-numeric: tabular-nums; }
  .tbl .act { text-align: right; white-space: nowrap; width: 1%; }
  .tbl input.inline { width: 120px; padding: 6px 10px; text-align: right; }
  .tbl .sel { width: 36px; padding-right: 0; }
  .tbl .sel input { width: 16px; height: 16px; cursor: pointer; accent-color: var(--accent); }
  .bulkbar { position: sticky; top: calc(10px + env(safe-area-inset-top, 0px)); z-index: 6; display: flex; flex-wrap: wrap; gap: 8px; align-items: center; background: var(--panel); border: 1px solid var(--accent);
    border-radius: 14px; padding: 10px 14px; margin-bottom: 14px; box-shadow: var(--shadow); }
  .bulkbar strong { margin-right: 6px; }
  .bulkbar select, .bulkbar input { padding: 6px 10px; font-size: 13.5px; }
  .extra { background: var(--panel); border: 1px solid var(--line); border-radius: 16px; padding: 16px 18px; margin-top: 14px; }
  .extra h3 { font-size: 14px; margin: 0 0 10px; }
  .rulegroup summary { cursor: pointer; list-style: none; display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 16px 20px; }
  .rulegroup summary::-webkit-details-marker { display: none; }
  .rulegroup[open] summary { border-bottom: 1px solid var(--line); }
  .editor-row { display: grid; grid-template-columns: 1fr 1fr auto; gap: 8px; align-items: center; margin-bottom: 8px; }
  .editor-row .x { border: 0; background: none; cursor: pointer; color: var(--muted); font-size: 18px; }
  .pager { display: flex; justify-content: space-between; align-items: center; padding: 14px 16px; border-top: 1px solid var(--line); color: var(--muted); font-size: 13px; }

  /* ---------- Drawer, dialog, toast ---------- */
  .scrim { position: fixed; inset: 0; background: rgba(20, 20, 18, .28); opacity: 0; visibility: hidden; pointer-events: none; transition: opacity .2s, visibility 0s .2s; z-index: 20; }
  /* hidden, not just see-through, while closed: Safari 26 tints the status bar with any fixed element's colour, even an invisible one */
  .scrim.open { opacity: 1; visibility: visible; pointer-events: auto; transition: opacity .2s; }
  .drawer { position: fixed; top: 0; right: 0; bottom: 0; width: min(520px, 100vw); background: var(--bg); box-shadow: var(--shadow); transform: translateX(105%); transition: transform .24s ease; z-index: 21; display: flex; flex-direction: column; }
  .drawer.open { transform: none; }
  .drawer header { display: flex; justify-content: space-between; align-items: center; padding: 22px 26px 8px; }
  .drawer header h2 { margin: 0; font-size: 18px; font-weight: 600; }
  .drawer .body { padding: 14px 26px 26px; overflow-y: auto; flex: 1; }
  .drawer footer { display: flex; gap: 10px; justify-content: flex-end; padding: 16px 26px; border-top: 1px solid var(--line); background: var(--bg); }
  .drawer footer .grow { flex: 1; }
  .split { background: var(--panel); border: 1px solid var(--line); border-radius: 16px; padding: 18px 18px 4px; margin-bottom: 14px; }
  .split .split-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px; font-weight: 600; font-size: 13px; }
  .form-err { background: var(--faint); color: var(--spend); border-radius: 10px; padding: 10px 12px; margin-bottom: 14px; font-size: 13.5px; }
  .hint { font-size: 12px; color: var(--muted); margin: -8px 0 14px; }
  dialog { border: 1px solid var(--line); border-radius: 18px; padding: 24px; background: var(--panel); color: var(--text); max-width: 400px; box-shadow: var(--shadow); }
  dialog::backdrop { background: rgba(20, 20, 18, .3); }
  dialog h3 { margin: 0 0 8px; font-size: 16px; }
  dialog p { margin: 0 0 20px; color: var(--muted); }
  dialog .btns { display: flex; justify-content: flex-end; gap: 10px; }
  /* What's new (features/whatsnew.ts): the release's highlights, once after an update */
  dialog.whatsnew { width: min(440px, calc(100vw - 32px)); max-width: none; max-height: calc(100dvh - 48px); padding: 0; overflow: hidden; flex-direction: column; }
  dialog.whatsnew[open] { display: flex; animation: wn-in .32s cubic-bezier(.2, .9, .3, 1.15); }
  dialog.whatsnew[open]::backdrop { animation: wn-fade .25s ease; }
  @keyframes wn-in { from { opacity: 0; transform: translateY(14px) scale(.97); } }
  @keyframes wn-fade { from { opacity: 0; } }
  .whatsnew header { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; padding: 22px 24px 0; }
  .whatsnew h3 { margin: 2px 0 0; font-size: 22px; font-weight: 650; letter-spacing: -.01em; }
  .whatsnew .wn-x { width: 32px; height: 32px; color: var(--muted); }
  .whatsnew .wn-x svg { display: block; width: 14px; height: 14px; }
  .whatsnew .wn-lead { margin: 8px 24px 0; font-size: 14px; line-height: 1.45; }
  .whatsnew .wn-list { list-style: none; margin: 0; padding: 18px 24px 4px; display: grid; gap: 16px; overflow-y: auto; overscroll-behavior: contain; }
  .whatsnew .wn-list li { display: flex; gap: 14px; align-items: flex-start; }
  .whatsnew .wn-ic { flex: none; width: 38px; height: 38px; border-radius: 12px; display: grid; place-items: center; background: var(--faint); color: var(--accent); }
  .whatsnew .wn-ic svg { display: block; width: 20px; height: 20px; }
  .whatsnew .wn-list li > div > strong { display: block; font-size: 14.5px; font-weight: 600; line-height: 1.3; }
  .whatsnew .wn-list li > div > span { display: block; margin-top: 2px; font-size: 13.5px; line-height: 1.45; color: var(--muted); }
  .whatsnew .btns { padding: 18px 24px 22px; flex-wrap: wrap; }
  .whatsnew .btns .btn { justify-content: center; }
  @media (max-width: 520px) {
    .whatsnew .btns .btn { flex: 1; padding: 11px 15px; }
  }
  @media (prefers-reduced-motion: reduce) { dialog.whatsnew[open], dialog.whatsnew[open]::backdrop { animation: none; } }
  .toast { position: fixed; left: 50%; bottom: 28px; transform: translate(-50%, 20px); background: var(--text); color: var(--bg); padding: 10px 18px; border-radius: 99px; font-size: 13.5px; opacity: 0; transition: all .2s; z-index: 40; pointer-events: none; max-width: 90vw; }
  .toast.show { opacity: 1; transform: translate(-50%, 0); }

  /* ---------- Login ---------- */
  .login { min-height: 100vh; display: grid; place-items: center; padding: calc(20px + env(safe-area-inset-top, 0px)) 20px calc(20px + env(safe-area-inset-bottom, 0px)); }
  .login form { width: min(360px, 100%); background: var(--panel); border: 1px solid var(--line); border-radius: 24px; padding: 34px 30px; }
  .login h1 { margin: 0 0 4px; font-size: 22px; font-weight: 600; }
  .login p { margin: 0 0 24px; color: var(--muted); font-size: 13.5px; }
  .login .btn { width: 100%; justify-content: center; padding: 10px; margin-top: 6px; }

  /* ---------- Motion & snappiness ---------- */
  .btn, .round, .nav a, .tbl tr.click td, .seg button { transition: background .12s, border-color .12s, transform .08s, opacity .12s; }
  .btn:active, .round:active, .fab:active { transform: scale(.97); }
  #view.enter > * { animation: fadeUp .22s ease both; }
  #view.enter.anim:not(.calm) > * { animation-name: fadeIn; }     /* the cards inside rise on their own (.anim), so the page only fades */
  #view.enter .cards > * { animation: fadeUp .28s ease both; }
  #view.enter .cards > :nth-child(2) { animation-delay: .03s; } #view.enter .cards > :nth-child(3) { animation-delay: .06s; }
  #view.enter .cards > :nth-child(4) { animation-delay: .09s; } #view.enter .cards > :nth-child(n+5) { animation-delay: .12s; }
  @keyframes fadeUp { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
  .sk { background: linear-gradient(90deg, var(--faint) 25%, var(--line) 50%, var(--faint) 75%); background-size: 200% 100%; border-radius: 8px; animation: shimmer 1.1s infinite linear; }
  @keyframes shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }
  .drawer { transition: transform .2s cubic-bezier(.2,.8,.2,1); }
  @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation: none !important; transition: none !important; } }
  .tbl, .cards > .panel { contain: layout paint; }
  .attention { border-color: var(--warn); }
  .attention .row .name { white-space: normal; }
  /* in a narrow tile the action drops under the text instead of squeezing it to a word per line */
  .attention .row { flex-wrap: wrap; row-gap: 4px; } .attention .row .name { flex: 1 1 9em; }
  .offline { padding-top: calc(6px + env(safe-area-inset-top, 0px) + var(--edge)) !important; position: fixed; top: 0; left: 0; right: 0; z-index: 70; background: var(--warn); color: #111; text-align: center; font-size: 13px; padding: 6px 12px; }
  /* ---------- Floating add button ---------- */
  .fab { position: fixed; right: 28px; bottom: 28px; width: 56px; height: 56px; border-radius: 50%; border: 0; background: var(--accent); color: var(--on-accent);
    font-size: 28px; line-height: 1; cursor: pointer; box-shadow: var(--shadow); z-index: 15; }
  .fab:hover { filter: brightness(1.08); }
  /* ---------- Undo toast ---------- */
  .undo { position: fixed; left: 50%; bottom: 28px; transform: translateX(-50%); background: var(--text); color: var(--bg); border-radius: 99px; padding: 8px 8px 8px 18px;
    display: flex; gap: 14px; align-items: center; z-index: 41; font-size: 13.5px; line-height: 1.3; box-shadow: var(--shadow);
    width: max-content; max-width: min(520px, calc(100vw - 28px)); box-sizing: border-box; }
  .undo > span:first-child { flex: 1; min-width: 0; }
  .undo button { flex: none; background: var(--bg); color: var(--text); border: 0; border-radius: 99px; padding: 6px 14px; font-weight: 600; cursor: pointer; }
  .undo .bar { position: absolute; left: 18px; right: 18px; bottom: 3px; height: 2px; background: var(--bg); opacity: .4; transform-origin: left; animation: drain 5s linear forwards; border-radius: 2px; }
  @keyframes drain { to { transform: scaleX(0); } }
  /* ---------- Chart tooltip ---------- */
  .tip { position: fixed; z-index: 45; pointer-events: none; background: var(--text); color: var(--bg); padding: 8px 12px; border-radius: 10px; font-size: 12.5px; line-height: 1.5; box-shadow: var(--shadow); }
  /* Hover band: drawn behind the bars and only over the plot area, so it stops at the axis and leaves the month label alone */
  .flowchart .band { fill: var(--text); fill-opacity: 0; pointer-events: none; transition: fill-opacity .12s; }
  .flowchart .col:hover .band { fill-opacity: .06; }
  .flowchart .col:hover text { fill: var(--text); }
  .chart rect:is(.hit, .band) { filter: none !important; }
  .chart .pt { cursor: default; }
  .chart .pt .dot { transition: r .1s; }
  .chart .pt:hover .dot { r: 6.5; }
  .tip { white-space: pre-line; max-width: 320px; }
  /* ---------- Charts: smooth lines, donuts, progress rings ---------- */
  .lines { display: block; width: 100%; height: auto; overflow: visible; }
  .lines .grid line { stroke: var(--line); stroke-dasharray: 3 5; }
  .lines text { font-size: 11px; fill: var(--muted); }
  .chart .lines rect { filter: none !important; }
  .lines + .legend { margin-top: 10px; }
  .report-top { display: grid; grid-template-columns: minmax(0, 1.7fr) minmax(0, 1fr); gap: 20px; margin-bottom: 20px; align-items: stretch; }
  .report-top.one { grid-template-columns: minmax(0, 1fr); }
  .report-top > .panel { margin: 0; }
  @media (max-width: 900px) { .report-top { grid-template-columns: minmax(0, 1fr); } }
  .donut, .ring { position: relative; display: grid; place-items: center; }
  .donut { width: min(180px, 64%); margin: 4px auto 18px; }
  .donut svg, .ring svg { width: 100%; height: auto; transform: rotate(-90deg); overflow: visible; }
  :is(.donut, .ring) circle { fill: none; }
  .donut .base { stroke: var(--faint); stroke-width: 14; }
  .donut .seg { stroke-width: 14; }
  .donut .seg { transition: stroke-width .15s, opacity .15s; cursor: pointer; }
  .donut .seg:hover, .donut.hot .seg.on { stroke-width: 18; }
  .donut.hot .seg:not(.on) { opacity: .35; }
  .share .part { transition: opacity .15s; }
  .share:has(.donut.hot) .part:not(.hot) { opacity: .45; }
  :is(.donut, .ring) .mid { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; line-height: 1.2; pointer-events: none; }
  .donut .mid strong { font-size: 22px; font-weight: 650; letter-spacing: -.01em; }
  .donut .mid .eyebrow { margin: 0 0 2px; }
  .parts { display: flex; flex-direction: column; gap: 10px; }
  .part { display: grid; grid-template-columns: 10px minmax(0, 8fr) minmax(0, 5fr) 38px; gap: 10px; align-items: center; font-size: 13.5px; }
  .part > i { width: 9px; height: 9px; border-radius: 50%; }
  .part .name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .part .name a { color: inherit; text-decoration: none; }
  .part .name .sub-s { display: block; overflow: hidden; text-overflow: ellipsis; margin-top: 1px; }
  .part .track { margin: 0; height: 5px; }
  .part .track .fill { opacity: 1; }
  .part .num { text-align: right; color: var(--muted); font-size: 12.5px; }
  .ring { width: 92px; flex: none; }
  .ring .base { stroke: var(--faint); stroke-width: 10; }
  .ring .seg { stroke: var(--accent); stroke-width: 10; stroke-linecap: round; }
  .ring.good .seg { stroke: var(--good); }
  .ring .mid strong { font-size: 19px; font-weight: 650; }
  .ring .mid span { font-size: 11px; color: var(--muted); }
  .goal { display: flex; align-items: center; gap: 18px; margin: 4px 0 16px; }
  /* ---------- Page entrance (polish.ts playIn adds .anim; a card that arrives late gets .pop) ---------- */
  @media (prefers-reduced-motion: no-preference) {
    #view.anim:not(.calm) :is(.hero, .kpi, .panel, .insight) { animation: riseIn .5s cubic-bezier(.2, .8, .2, 1) both; animation-delay: calc(var(--i, 0) * 45ms); }
    :is(#view.anim, .pop) .draw { stroke-dasharray: 1; animation: drawIn 1.1s .2s cubic-bezier(.45, 0, .2, 1) both; }
    :is(#view.anim, .pop) .draw.late { animation-delay: .4s; }
    :is(#view.anim, .pop) .area { animation: fadeIn .9s .55s ease both; }
    :is(#view.anim, .pop) :is(.flowchart, .barchart, .sbars) .bar { transform-box: fill-box; transform-origin: 50% 100%; animation: growUp .7s cubic-bezier(.2, .8, .2, 1) both; animation-delay: calc(.15s + var(--j, 0) * 60ms); }
    :is(#view.anim, .pop) .fill { transform-origin: left; animation: growRight .8s .2s cubic-bezier(.2, .8, .2, 1) both; }
    :is(#view.anim, .pop) :is(.donut, .ring) .seg { animation: sweepIn .6s cubic-bezier(.3, 0, .2, 1) both; animation-delay: calc(.25s + var(--at, 0) * .9s); }
    :is(#view.anim, .pop) .chart .pt .dot { animation: fadeIn .4s 1.1s both; }
  }
  /* ---------- Overview: Add cards (Customize), the newer charts ---------- */
  .dash-add { flex-basis: 100%; margin-top: 6px; }
  .dash-add .eyebrow { margin-bottom: 8px; }
  .add-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 8px; }
  .add-card { display: flex; gap: 12px; align-items: center; text-align: left; padding: 10px 14px 10px 10px; border: 1px dashed color-mix(in srgb, var(--text) 22%, var(--line));
    border-radius: 16px; background: transparent; color: var(--text); font: inherit; cursor: pointer; }
  .add-card:hover { border-style: solid; background: var(--faint); }
  .add-card strong { display: block; font-size: 14px; font-weight: 600; }
  .add-card .sub-s { display: block; margin-top: 1px; }
  .add-card .plus-i { flex: none; width: 30px; height: 30px; border-radius: 50%; display: grid; place-items: center; background: color-mix(in srgb, var(--accent) 15%, transparent); color: var(--accent); font-size: 18px; font-weight: 600; }
  .barchart { display: block; width: 100%; height: auto; overflow: visible; }
  .barchart text { font-size: 11px; fill: var(--muted); }
  .barchart text.bv { font-size: 11.5px; font-weight: 600; fill: var(--text); }
  .barchart .bar { fill: var(--good); }
  .barchart .bar.neg { fill: var(--spend); }
  .trends { display: grid; }
  .trend-row { display: grid; grid-template-columns: minmax(0, 1fr) auto 76px; gap: 14px; align-items: center; padding: 10px 0; border-top: 1px solid var(--line); }
  .trend-row:first-child { border-top: 0; padding-top: 2px; }
  .trend-row .name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .trend-row .sub-s { display: block; margin-top: 1px; }
  .trend-row .num { text-align: right; }
  .sbars { display: block; }
  .sbars .bar { fill: color-mix(in srgb, var(--muted) 40%, transparent); }
  .sbars .bar.now { fill: var(--accent); }
  @media (hover: hover) {
    .sbars g[data-tip]:hover .bar { fill: color-mix(in srgb, var(--muted) 70%, transparent); }
    .sbars g[data-tip]:hover .bar.now { fill: color-mix(in srgb, var(--accent) 80%, var(--text)); }
  }
  @keyframes riseIn { from { opacity: 0; transform: translateY(14px); } }
  @keyframes drawIn { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }
  @keyframes fadeIn { from { opacity: 0; } }
  @keyframes growUp { from { transform: scaleY(0); } }
  @keyframes growRight { from { transform: scaleX(0); } }
  @keyframes sweepIn { from { stroke-dasharray: 0 100; } }
  /* ---------- Command palette ---------- */
  .palette { position: fixed; inset: 0; background: rgba(20,20,18,.35); z-index: 50; display: grid; justify-items: center; align-items: start; padding-top: 12vh; }
  .palette-box { width: min(620px, 92vw); background: var(--panel); border: 1px solid var(--line); border-radius: 18px; box-shadow: var(--shadow); overflow: hidden; animation: fadeUp .14s ease both; }
  .pal-top { display: flex; align-items: center; gap: 10px; padding: 0 16px 0 20px; border-bottom: 1px solid var(--line); }
  .pal-top > svg { width: 18px; height: 18px; flex: none; color: var(--muted); }
  .palette-box .pal-top input { flex: 1; min-width: 0; width: 100%; border: 0; border-radius: 0; padding: 18px 0; font-size: 16px; background: transparent; box-shadow: none; outline: none; -webkit-appearance: none; appearance: none; }
  .pal-top input::-webkit-search-cancel-button { display: none; }
  .pal-cancel { display: none; flex: none; font-size: 16px; }
  .pal-list { max-height: 52vh; overflow-y: auto; padding: 6px; overscroll-behavior: contain; }
  .pal-h { font-size: 11.5px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); padding: 10px 14px 4px; }
  .pal-item { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 10px 14px; border-radius: 10px; cursor: pointer; }
  .pal-main { display: flex; flex-direction: column; min-width: 0; }
  .pal-l, .pal-sub { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .pal-sub { font-size: 12.5px; color: var(--muted); margin-top: 1px; }
  .pal-item .k, .pal-item .num { flex: none; font-size: 12px; color: var(--muted); }
  .pal-item .num { font-size: 14px; } .pal-item .num.neg { color: var(--text); } .pal-item .num.pos { color: var(--good); }
  .pal-wait { cursor: default; } .pal-wait .spin { margin-right: 8px; }
  details.pal-flash { border-radius: 8px; }
  .pal-flash { animation: palFlash 1.6s ease-out; scroll-margin-top: calc(env(safe-area-inset-top, 0px) + 64px); }
  @keyframes palFlash { 0%, 30% { box-shadow: 0 0 0 3px var(--accent); } 100% { box-shadow: 0 0 0 3px transparent; } }
  .side-search { display: flex; align-items: center; gap: 10px; margin: 0 0 14px; padding: 8px 10px 8px 12px; border: 1px solid var(--line); border-radius: 10px; background: var(--panel); color: var(--muted); font: inherit; font-size: 14px; cursor: pointer; text-align: left; }
  .side-search svg { width: 16px; height: 16px; flex: none; } .side-search span { flex: 1; } .side-search kbd { font-size: 11px; padding: 2px 6px; }
  .side-search:hover { color: var(--text); border-color: color-mix(in srgb, var(--text) 25%, var(--line)); }
  .search-btn { display: none; }
  .sheet-search { display: flex; align-items: center; gap: 10px; width: 100%; margin: 0 0 8px; padding: 11px 12px; border: 0; border-radius: 10px; background: var(--faint); color: var(--muted); font: inherit; font-size: 16px; text-align: left; cursor: pointer; }
  .sheet-search svg { width: 18px; height: 18px; flex: none; }
  .pal-item.on { background: var(--faint); box-shadow: inset 3px 0 0 var(--accent); }
  .pal-foot { display: flex; gap: 16px; padding: 10px 16px; border-top: 1px solid var(--line); font-size: 12px; color: var(--muted); }
  /* ---------- Date picker ---------- */
  input[type=date]::-webkit-calendar-picker-indicator { opacity: .55; cursor: pointer; }
  .calpop { position: fixed; z-index: 60; background: var(--panel); border: 1px solid var(--line); border-radius: 16px; box-shadow: var(--shadow); padding: 12px; width: 270px; animation: fadeUp .12s ease both; }
  .calpop .ch { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; font-weight: 600; }
  .calpop .ch button { border: 0; background: none; cursor: pointer; font-size: 18px; color: var(--muted); padding: 2px 8px; border-radius: 8px; }
  .calpop .ch button:hover { background: var(--faint); color: var(--text); }
  .calpop .grid7 { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; text-align: center; }
  .calpop .dow { font-size: 11px; color: var(--muted); padding: 4px 0; }
  .calpop .d { border: 0; background: none; padding: 7px 0; border-radius: 8px; cursor: pointer; font-size: 13px; }
  .calpop .d:hover { background: var(--faint); }
  .calpop .d.out { color: var(--muted); opacity: .5; }
  .calpop .d.today { box-shadow: inset 0 0 0 1px var(--accent); }
  .calpop .d.sel { background: var(--accent); color: var(--on-accent); }
  .calpop .cf { display: flex; justify-content: space-between; margin-top: 8px; }
  /* ---------- Phone tab bar ---------- */
  .tabbar { position: fixed; left: 0; right: 0; bottom: 0; z-index: 16; background: var(--panel); border-top: 1px solid var(--line);
    display: none; grid-template-columns: repeat(5, 1fr); padding: 6px 4px calc(6px + env(safe-area-inset-bottom)); }
  .tabbar a, .tabbar button { display: flex; flex-direction: column; align-items: center; gap: 2px; font-size: 11px; color: var(--muted); text-decoration: none; background: none; border: 0; padding: 6px 0; cursor: pointer; }
  .tabbar a.on { color: var(--accent); }
  .tabbar svg { width: 22px; height: 22px; }
  .fab { display: grid; place-items: center; padding: 0; }
  .fab svg { width: 26px; height: 26px; }
  .tabbar .plus svg { width: 24px; height: 24px; }
  .tabbar .plus { width: 46px; height: 46px; margin: -18px auto 0; border-radius: 50%; background: var(--accent); color: var(--on-accent); font-size: 26px; box-shadow: var(--shadow); padding: 0; display: grid; place-items: center; }
  /* ---------- Grouped transaction feed ---------- */
  .panel.flush { overflow: clip; }
  /* Rows are grids and each day is its own block, so a day's header pushes the previous one away while scrolling */
  .tbl.feed { contain: none; display: block; --cols: minmax(0, 2.2fr) minmax(0, 1.4fr) minmax(0, 1fr) minmax(110px, auto); }
  .tbl.feed.has-sel { --cols: 44px minmax(0, 2.2fr) minmax(0, 1.4fr) minmax(0, 1fr) minmax(110px, auto); }
  .tbl.feed tbody.day { display: block; }
  .tbl.feed tr { display: grid; grid-template-columns: var(--cols); }
  .tbl.feed tr.dayhead { display: block; position: sticky; top: env(safe-area-inset-top, 0px); z-index: 3; }
  .tbl.feed tr.dayhead td { display: block; }
  .tbl.feed tr[data-gid] td { display: flex; align-items: center; min-width: 0; }
  .tbl.feed tr[data-gid] td.amt { justify-content: flex-end; }
  .tbl.feed td.sel { width: auto; padding-right: 0; }
  .tbl.feed td.flow { max-width: none; }
  .tbl.feed td.flow > span, .tbl.feed td.catcol > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
  .tbl.feed tr.dayhead td { padding: 0; border-bottom: 1px solid var(--line); background: transparent; }
  .tbl.feed tr.dayhead div { display: flex; justify-content: space-between; align-items: center; padding: 8px 16px; font-size: 12px; font-weight: 600; letter-spacing: .02em; color: var(--muted);
    background: color-mix(in srgb, color-mix(in srgb, var(--faint) 60%, var(--panel)) 90%, transparent); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); }
  .tbl.feed tr.dayhead .num { font-weight: 500; }
  .tbl.feed tr.dayhead .num.pos { color: var(--good); }
  .tbl.feed tbody.day:not(:first-child) tr.dayhead div { box-shadow: inset 0 1px 0 var(--line); }
  .tbl.feed tbody.day tr:last-child td { border-bottom: none; }
  .tbl.feed td { padding-top: 11px; padding-bottom: 11px; }
  .txmain { display: flex; align-items: center; gap: 12px; min-width: 0; }
  .txmain .txt { min-width: 0; }
  .txmain .desc { overflow: hidden; text-overflow: ellipsis; }
  .tbl.feed .meta { display: flex; flex-wrap: wrap; gap: 4px 0; align-items: center; margin-top: 2px; }
  .cat-s { display: none; font-size: 12.5px; color: var(--muted); margin-right: 8px; }
  .show-s { display: none; }
  .tbl .namecol { min-width: 220px; }
  form.range { display: flex; gap: 8px; align-items: center; flex: 0 1 460px; min-width: 0; }
  form.range input { flex: 1 1 0; width: 0; }
  .tbl.feed .catcol { color: var(--muted); font-size: 13.5px; }
  .av { --h: 220; --c: hsl(var(--h) 62% 48%); flex: none; width: 36px; height: 36px; border-radius: 50%; display: inline-grid; place-items: center;
    font-size: 13px; font-weight: 650; letter-spacing: -.02em; line-height: 1;
    background: color-mix(in oklab, var(--c) 17%, var(--panel)); color: color-mix(in oklab, var(--c) 48%, var(--text));
    box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--c) 22%, transparent); }
  .av.xfer { --c: var(--muted); }
  .av { position: relative; overflow: hidden; }
  /* A logo fetched through /logo/ covers the monogram; if there is none, the img is removed (core/logo.ts) */
  .av img.logo { position: absolute; inset: 0; width: 100%; height: 100%; box-sizing: border-box; padding: 16%; object-fit: contain; background: #fff; border-radius: inherit; opacity: 0; transition: opacity .15s; }
  .av img.logo.ok { opacity: 1; }
  .av.sm { width: 26px; height: 26px; font-size: 10.5px; }
  .acct { display: inline-flex; align-items: center; gap: 10px; }
  .acct + .sub-s { margin-left: 36px; }
  .av svg { width: 17px; height: 17px; }
  .av.lg { width: 52px; height: 52px; font-size: 19px; }
  .av.lg svg { width: 24px; height: 24px; }
  .selall { margin: 0 0 0 auto; font-size: 13px; color: var(--muted); }
  .nm { display: inline-block; }
  .head h1 { width: fit-content; }
  /* ---------- Drawer hero ---------- */
  .drawer header { align-items: flex-start; }
  .dhero { display: flex; gap: 14px; align-items: center; min-width: 0; }
  .dhero .eyebrow { margin-bottom: 1px; }
  .dhero h2 { font-size: 19px !important; line-height: 1.25; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 340px; }
  .dh-txt { min-width: 0; }
  /* ---------- Insight cards ---------- */
  main#view { min-width: 0; }
  .insights { min-width: 0; display: grid; grid-auto-flow: column; grid-auto-columns: minmax(260px, 1fr); gap: 14px; margin: -14px 0 24px; overflow-x: auto; scroll-snap-type: x mandatory;
    scrollbar-width: none; padding: 2px; }
  .insights::-webkit-scrollbar { display: none; }
  .insight { --tone: var(--muted); position: relative; scroll-snap-align: start; display: flex; gap: 12px; align-items: flex-start; text-decoration: none;
    background: var(--panel); border: 1px solid var(--line); border-radius: 16px; padding: 14px 36px 14px 14px; transition: border-color .15s, transform .15s; }
  .insight:hover { border-color: color-mix(in srgb, var(--tone) 55%, var(--line)); transform: translateY(-1px); }
  .insight.t-up { --tone: var(--spend); } .insight.t-down { --tone: var(--good); } .insight.t-warn { --tone: var(--warn); }
  .insight .ic { flex: none; width: 34px; height: 34px; border-radius: 10px; display: grid; place-items: center; color: var(--tone); background: color-mix(in srgb, var(--tone) 18%, transparent); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--tone) 22%, transparent); }
  .insight .ic svg { width: 18px; height: 18px; }
  .insight .t { font-weight: 600; font-size: 14px; line-height: 1.35; }
  .insight .d { font-size: 12.5px; color: var(--muted); margin-top: 2px; line-height: 1.45; }
  .insight .x { position: absolute; top: 8px; right: 8px; width: 24px; height: 24px; border: 0; border-radius: 50%; background: none; color: var(--muted); cursor: pointer; font-size: 16px; line-height: 1; opacity: 0; transition: opacity .15s, background .15s; }
  .insight:hover .x, .insight .x:focus-visible { opacity: 1; }
  .insight .x:hover { background: var(--faint); color: var(--text); }
  @media (hover: none) { .insight .x { opacity: .7; } }
  /* ---------- Part 2: widgets, sheets, pickers, charts ---------- */
  .cards .w { break-inside: avoid; display: inline-block; width: 100%; margin-bottom: 20px; vertical-align: top; }
  .cards .w > .panel { contain: layout paint; }
  .cards .w.wide { column-span: all; display: block; }
  .dash-bar { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; background: var(--panel); border: 1px dashed var(--accent); border-radius: 14px; padding: 10px 14px; margin-bottom: 18px; font-size: 13px; color: var(--muted); }
  .dash-bar .grow, .wctl .grow { flex: 1; }
  .dash-opts { display: flex; gap: 10px 16px; align-items: center; flex-wrap: wrap; flex-basis: 100%; padding-top: 10px; border-top: 1px solid var(--line); }
  .dash-opts .grow { flex: 1; }
  .dash-opts label.check { font-size: 13px; }
  .seg.mini { margin: 0; } .seg.mini button { padding: 4px 12px; font-size: 12.5px; }
  /* Customizable overview (ui.js): bands of --n columns you arrange yourself, with wide cards between the bands */
  .dash-wrap { --gap: 20px; }
  .cards.free { columns: auto; }
  /* The insight strip uses the same columns and gutters as the cards, so their edges line up (it still scrolls sideways
     when there are more insights than columns; on phones it keeps its peek-at-the-next-card width) */
  .dash-wrap:not([data-n="1"]) .insights { grid-auto-columns: calc((100% - (var(--n) - 1) * var(--gap)) / var(--n)); gap: var(--gap); padding: 2px 0; margin-bottom: calc(var(--gap) - 2px); }
  .dash-wrap .insight { border-radius: var(--radius); }
  .cards.free .band { display: grid; grid-template-columns: repeat(var(--n, 3), minmax(0, 1fr)); gap: var(--gap); align-items: start; margin-bottom: var(--gap); }
  .cards.free .dcol { display: flex; flex-direction: column; gap: var(--gap); min-width: 0; }
  .cards.free .w { display: block; margin-bottom: 0; }
  .cards.free > .w, .cards.free .dash-rest > .w { margin-bottom: var(--gap); }
  .dash-more { display: block; width: 100%; padding: 12px; }
  /* Freeform tiles (ui.js gridLayout): 24 columns, 8px rows; each tile's spot is set inline */
  .cards.grid { display: grid; grid-template-columns: repeat(24, minmax(0, 1fr)); grid-auto-rows: 8px; column-gap: var(--gap); row-gap: 0; align-items: start; margin-bottom: var(--gap); }
  .cards.grid > .w { display: block; margin: 0; min-width: 0; }
  /* while customizing, faint column guides show what the tiles snap to */
  .cards.grid.editing { background-image: linear-gradient(to right, color-mix(in srgb, var(--accent) 3.5%, transparent) 0 calc(100% - var(--gap)), transparent 0);
    background-size: calc((100% + var(--gap)) / 24) 100%; border-radius: 12px; }
  .cards.grid .rsz { position: absolute; right: -6px; bottom: -6px; width: 22px; height: 22px; cursor: nwse-resize; z-index: 2; touch-action: none; border-radius: 6px;
    background: linear-gradient(135deg, transparent 0 45%, var(--accent) 45% 55%, transparent 55% 65%, var(--accent) 65% 75%, transparent 75%); }
  .cards.grid.editing .w > .rsz { pointer-events: auto; }
  .cards.free.editing .dcol { min-height: 110px; border-radius: var(--radius); background: color-mix(in srgb, var(--accent) 5%, transparent); }
  .cards.editing .w { position: relative; border-radius: var(--radius); outline: 1.5px dashed color-mix(in srgb, var(--accent) 45%, transparent); outline-offset: 3px; cursor: grab; }
  .cards.editing .w > :not(.wctl):not(.rsz):not(.wopts) { pointer-events: none; }
  .cards.editing .w.off > :not(.wctl):not(.rsz):not(.wopts) { opacity: .35; filter: grayscale(1); }
  .cards.editing .w { user-select: none; -webkit-user-select: none; }
  /* the spot the tile will land in, while you carry a solid copy of it */
  .cards.editing .w.dragging { background: color-mix(in srgb, var(--accent) 7%, transparent); outline-color: color-mix(in srgb, var(--accent) 70%, transparent); }
  .cards.editing .w.dragging > * { opacity: 0; }
  .cards.moving, .cards.moving * { cursor: grabbing !important; }
  .dash-ghost { position: fixed; z-index: 60; margin: 0; pointer-events: none; border-radius: var(--radius); will-change: transform; transform-origin: 50% 40%; display: flex; flex-direction: column; }
  .dash-ghost > .panel { flex: 1; }
  .dash-ghost > .panel { background: linear-gradient(var(--panel), var(--panel)), var(--bg); box-shadow: 0 24px 60px rgba(0,0,0,.28), 0 4px 14px rgba(0,0,0,.12); }
  .dash-ghost > :not(.wctl) { pointer-events: none; }
  .wctl { display: flex; align-items: center; gap: 6px; margin-bottom: 8px; font-size: 12.5px; }
  .wctl .grip { cursor: grab; color: var(--muted); font-size: 16px; }
  .wctl button { border: 1px solid var(--line); background: var(--panel); border-radius: 8px; padding: 3px 9px; cursor: pointer; font-size: 12.5px; }
  .wctl button:hover { border-color: var(--muted); }
  /* a tile's own settings, opened with its ⚙ button while customizing */
  .wopts { display: grid; gap: 8px; margin: 0 0 10px; padding: 12px 14px; background: var(--panel); border: 1px solid var(--line); border-radius: 12px; font-size: 13px; cursor: default; }
  .wopts[hidden] { display: none; }
  .wopts .wopt { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
  .wopts .wopt select { width: auto; margin: 0; padding: 4px 8px; }
  .row .spark { flex: none; margin-left: auto; margin-right: 12px; align-self: center; overflow: visible; }
  .spark polyline { fill: none; stroke: var(--muted); stroke-width: 1.6; stroke-linejoin: round; stroke-linecap: round; }
  .spark circle { fill: var(--muted); }
  .spark.good polyline { stroke: var(--good); } .spark.good circle { fill: var(--good); }
  .spark.bad polyline { stroke: var(--spend); } .spark.bad circle { fill: var(--spend); }
  .hm { display: grid; gap: 6px; }
  .hm-dow, .hm-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 5px; }
  .hm-dow span { text-align: center; font-size: 11px; color: var(--muted); }
  .hm-cell { aspect-ratio: 1; border-radius: 8px; border: 0; padding: 0; font-size: 11px; color: var(--muted); display: grid; place-items: center; cursor: pointer;
    background: color-mix(in srgb, var(--spend) var(--p, 0%), var(--faint)); transition: transform .12s; }
  .hm-cell[style*="--p"] { color: color-mix(in srgb, var(--text) 80%, transparent); }
  .hm-cell:not(:disabled):hover { transform: scale(1.08); }
  .hm-cell:disabled { cursor: default; }
  .hm-cell.pad { background: none; }
  .hm-cell.fut { background: none; box-shadow: inset 0 0 0 1px var(--line); opacity: .6; }
  .hm-cell.today { box-shadow: inset 0 0 0 2px var(--accent); }
  .hm-foot { display: flex; justify-content: space-between; gap: 10px; margin-top: 14px; font-size: 12.5px; color: var(--muted); flex-wrap: wrap; }
  .sankey svg { width: 100%; height: auto; display: block; }
  .sankey .lk { fill-opacity: .26; transition: fill-opacity .15s; }
  .sankey .lk:hover { fill-opacity: .55; }
  .sankey .sk-name { fill: var(--text); font-size: 12.5px; font-weight: 500; }
  .sankey .sk-amt { fill: var(--muted); font-size: 11.5px; }
  /* Labels inside the chart (narrow cards) sit over the bands, which are faint enough to read text on; taps go
     through them to the band underneath */
  .sankey .sk-in text { pointer-events: none; }
  .sankey .sk-in .sk-name { font-weight: 600; }
  .tbl.feed .inl { cursor: pointer; border-radius: 6px; transition: background .12s, box-shadow .12s; }
  .tbl.feed .catcol .inl { padding: 3px 7px; margin-left: -7px; }
  .tbl.feed .inl:hover { background: var(--faint); box-shadow: 0 0 0 1px var(--line); color: var(--text); }
  .chip.ghost { background: none; box-shadow: inset 0 0 0 1px dashed var(--line); border: 1px dashed var(--line); opacity: 0; }
  .tbl.feed tr:hover .chip.ghost, .tbl.feed tr.kfocus .chip.ghost { opacity: 1; }
  @media (hover: none) { .chip.ghost { display: none; } }
  .tbl.feed tr[data-gid] { scroll-margin: 48px 0 90px; }
  .tbl.feed tr.kfocus td { background: color-mix(in srgb, var(--accent) 7%, var(--panel)); }
  .tbl.feed tr.kfocus td:first-child { box-shadow: inset 3px 0 0 var(--accent); }
  .tbl.feed tr.saving { opacity: .55; }
  .tbl.feed tr.saving .amt, .tbl.feed tr.saving .inl { background: linear-gradient(90deg, transparent, var(--faint), transparent); background-size: 200% 100%; animation: shimmer 1s infinite linear; }
  .tbl.feed tr.saved td { animation: savedFlash .9s ease; }
  @keyframes savedFlash { from { background: color-mix(in srgb, var(--good) 16%, var(--panel)); } }
  .tbl.feed tbody.day { content-visibility: auto; contain-intrinsic-size: auto 260px; }
  .more { display: flex; gap: 10px; align-items: center; justify-content: center; padding: 18px; color: var(--muted); font-size: 13px; border-top: 1px solid var(--line); }
  .spin { width: 16px; height: 16px; border-radius: 50%; border: 2px solid var(--line); border-top-color: var(--accent); animation: spin .8s linear infinite; display: inline-block; }
  @keyframes spin { to { transform: rotate(360deg); } }
  .pickpop { position: fixed; z-index: 62; background: var(--panel); border: 1px solid var(--line); border-radius: 14px; box-shadow: var(--shadow); overflow: hidden; animation: fadeUp .12s ease both; }
  .pickpop input { width: 100%; border: 0; border-bottom: 1px solid var(--line); border-radius: 0; padding: 11px 14px; background: transparent; }
  .pickpop .pk-list { max-height: 260px; overflow-y: auto; padding: 4px; }
  .pickpop .pal-item { padding: 8px 12px; }
  kbd { font: 12px/1 ui-monospace, SFMono-Regular, Menlo, monospace; padding: 4px 7px; border-radius: 6px; border: 1px solid var(--line); border-bottom-width: 2px; background: var(--panel); color: var(--text); }
  .toggles { display: grid; gap: 2px; margin: 4px 0 6px; }
  .toggles button { display: flex !important; align-items: center; gap: 9px; }
  .toggles button svg { width: 15px; height: 15px; flex: none; }
  .toggles button.on { color: var(--text) !important; }
  .toggles.sheet { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 22px; }
  .toggles.sheet button svg { width: 16px; height: 16px; }
  .ptr { position: fixed; top: env(safe-area-inset-top, 0px); left: 50%; z-index: 30; width: 40px; height: 40px; border-radius: 50%; background: var(--panel); box-shadow: var(--shadow); display: grid; place-items: center;
    color: var(--muted); transform: translate(-50%, -50px); opacity: 0; transition: transform .25s, opacity .25s; pointer-events: none; }
  .ptr svg { width: 20px; height: 20px; }
  .ptr.armed { color: var(--accent); }
  .ptr.busy svg { animation: spin .8s linear infinite; color: var(--accent); }
  .nlq { position: relative; margin-bottom: 18px; }
  .nlq > svg { position: absolute; left: 13px; top: 13px; width: 17px; height: 17px; color: var(--accent); pointer-events: none; }
  .nlq input { width: 100%; padding: 11px 14px 11px 38px; border: 1px solid color-mix(in srgb, var(--accent) 35%, var(--line)); border-radius: 12px; background: var(--panel); font-size: 15px; color: var(--text); }
  .nlchips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
  .nlchips:empty { display: none; }
  .nlchip { font-size: 12px; background: color-mix(in srgb, var(--accent) 10%, var(--panel)); color: var(--text); border-radius: 99px; padding: 3px 10px; animation: fadeUp .15s ease both; }
  .nlchip em { font-style: normal; color: var(--muted); margin-right: 5px; }
  input.filled { box-shadow: 0 0 0 2px color-mix(in srgb, var(--good) 35%, transparent); }
  .grab { display: none; }
  /* Privacy: blur money everywhere (hover to peek on desktop) */
  html.privacy .num, html.privacy .amt, html.privacy .big, html.privacy .val, html.privacy .total, html.privacy .insight .d, html.privacy .tip, html.privacy .hm-foot strong,
  html.privacy .dhero .sub-s, html.privacy .cat .sub, html.privacy .sub-s, html.privacy .kpi .val { filter: blur(7px); transition: filter .15s; }
  html.privacy .settings .sub-s { filter: none; }   /* Settings hints hold no amounts */
  html.privacy .amtx { visibility: hidden; }
  html.privacy .spark { opacity: .5; }
  @media (hover: hover) { html.privacy .num:hover, html.privacy .amt:hover, html.privacy .val:hover, html.privacy .total:hover, html.privacy .big:hover { filter: none; } }
  /* Compact density */
  html.compact body { font-size: 13.5px; }
  html.compact main { padding-top: 24px; }
  html.compact .panel { padding: 18px 20px; }
  html.compact .cards { column-gap: 14px; } html.compact .cards:not(.free) .w { margin-bottom: 14px; } html.compact .dash-wrap { --gap: 14px; }
  html.compact .tbl.feed td { padding-top: 6px; padding-bottom: 6px; }
  html.compact .tbl.feed tr.dayhead div { padding-top: 5px; padding-bottom: 5px; }
  html.compact .av { width: 28px; height: 28px; font-size: 11px; }
  html.compact .av svg { width: 14px; height: 14px; }
  html.compact .hero { margin-bottom: 26px; } html.compact .big { font-size: 42px; }
  html.compact .list .row { padding: 7px 0; }
  html.compact .head { margin-bottom: 18px; }
  html.compact .kpi { padding: 12px 14px; }

  /* ---------- Theme: Liquid glass neon ---------- */
  html[data-theme="glass"] { --bg: #07060f; --panel: rgba(24, 20, 48, .52); --line: rgba(255, 255, 255, .13); --text: #f5f3ff; --muted: #aaa4cc; --faint: rgba(255, 255, 255, .07);
    --good: #3dffb5; --spend: #ff4fd8; --income: #37f5ff; --warn: #ffd84d; --accent: #37f5ff; --on-accent: #04121a;
    --hero-grad: linear-gradient(90deg, #37f5ff, #b86bff 50%, #ff4fd8); --shadow: 0 20px 60px rgba(0, 0, 0, .55); --radius: 22px; color-scheme: dark;
    --glass: linear-gradient(150deg, rgba(255,255,255,.11), rgba(255,255,255,.035) 42%, rgba(255,255,255,.06));
    --glass-edge: inset 0 1px 0 rgba(255,255,255,.22), inset 0 -1px 0 rgba(255,255,255,.05), inset 1px 0 0 rgba(255,255,255,.06);
    /* what Settings → Appearance → Customize can change (themevars.ts sets these on <html>) */
    --glow1: #ff4fd8; --glow2: #37f5ff; --glow3: #8c5cff; --glass-base: #14102a; --glass-tint: 38%; --glass-blur: 26px;
    background: var(--bg); }
  html[data-theme="glass"] body { background: transparent; }
  /* drifting neon light behind the glass. The drift keeps the browser drawing every frame even when nothing else moves,
     so it stays still unless you turn Moving light on (Settings → Appearance → Customize; themevars.ts sets --glass-motion: running) */
  html[data-theme="glass"] body::after { content: ''; position: fixed; inset: -20vmax; z-index: -1; pointer-events: none;
    background:
      radial-gradient(38vmax 38vmax at 18% 22%, color-mix(in srgb, var(--glow1) 42%, transparent), transparent 62%),
      radial-gradient(42vmax 42vmax at 82% 30%, color-mix(in srgb, var(--glow2) 30%, transparent), transparent 60%),
      radial-gradient(46vmax 46vmax at 55% 88%, color-mix(in srgb, var(--glow3) 40%, transparent), transparent 62%),
      radial-gradient(30vmax 30vmax at 90% 85%, color-mix(in srgb, var(--good) 16%, transparent), transparent 60%);
    filter: saturate(130%); animation: glassDrift 38s ease-in-out infinite alternate; animation-play-state: var(--glass-motion, paused); }
  @keyframes glassDrift { 0% { transform: translate3d(0, 0, 0) rotate(0deg); } 50% { transform: translate3d(4vmax, -3vmax, 0) rotate(8deg); } 100% { transform: translate3d(-3vmax, 3vmax, 0) rotate(-6deg); } }
  /* frosted surfaces */
  html[data-theme="glass"] :is(.panel, .daycards tbody.day, .daycards > .center-empty, .kpi, .insight, .extra, .split, .login form, .dash-bar) {
    background: var(--glass), color-mix(in srgb, var(--glass-base) var(--glass-tint), transparent); border: 1px solid rgba(255, 255, 255, .14);
    box-shadow: var(--glass-edge), 0 12px 40px rgba(0, 0, 0, .35);
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(170%); backdrop-filter: blur(var(--glass-blur)) saturate(170%); }
  html[data-theme="glass"] :is(.drawer, dialog, .calpop, .pickpop, .palette-box, .bulkbar) {
    background: var(--glass), rgba(14, 11, 30, .72); border-color: rgba(255, 255, 255, .16);
    -webkit-backdrop-filter: blur(34px) saturate(180%); backdrop-filter: blur(34px) saturate(180%); }
  html[data-theme="glass"] .drawer { box-shadow: var(--glass-edge), -20px 0 80px rgba(0, 0, 0, .5); }
  html[data-theme="glass"] .drawer footer { background: transparent; border-top-color: rgba(255, 255, 255, .1); }
  html[data-theme="glass"] .tabbar { background: rgba(14, 11, 30, .55); border-top-color: rgba(255, 255, 255, .12);
    -webkit-backdrop-filter: blur(30px) saturate(180%); backdrop-filter: blur(30px) saturate(180%); }
  html[data-theme="glass"] :is(input[type=text], input[type=number], input[type=date], input[type=password], input[type=search], select, textarea, .btn, .round, .wctl button) {
    background: rgba(255, 255, 255, .06); border-color: rgba(255, 255, 255, .15); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .08); }
  html[data-theme="glass"] select option { background: #16122e; }
  html[data-theme="glass"] :is(input, select, textarea):focus { border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent), 0 0 18px color-mix(in srgb, var(--accent) 25%, transparent); }
  html[data-theme="glass"] .seg { background: rgba(255, 255, 255, .06); }
  html[data-theme="glass"] :is(.seg button, .tabs a).on { background: rgba(255, 255, 255, .14); color: var(--text); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .2); }
  html[data-theme="glass"] .tbl.feed tr.dayhead div { background: rgba(20, 16, 42, .55); }
  html[data-theme="glass"] .tbl tr.click:hover td { background: rgba(255, 255, 255, .05); }
  html[data-theme="glass"] .side { border-right-color: rgba(255, 255, 255, .08); background: rgba(10, 8, 22, .35); -webkit-backdrop-filter: blur(20px); backdrop-filter: blur(20px); }
  /* neon glow */
  html[data-theme="glass"] .btn.primary, html[data-theme="glass"] .fab, html[data-theme="glass"] .tabbar .plus {
    background: linear-gradient(135deg, var(--accent), var(--glow3)); border-color: transparent; color: var(--on-accent); box-shadow: 0 0 22px color-mix(in srgb, var(--accent) 45%, transparent), inset 0 1px 0 rgba(255, 255, 255, .5); }
  html[data-theme="glass"] .nav a.on { background: rgba(255, 255, 255, .08); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .12), 0 0 0 1px rgba(255, 255, 255, .1); }
  html[data-theme="glass"] .nav a.on svg, html[data-theme="glass"] .tabbar a.on svg { filter: drop-shadow(0 0 6px var(--accent)); }
  html[data-theme="glass"] .fill { box-shadow: 0 0 12px color-mix(in srgb, var(--spend) 70%, transparent); }
  html[data-theme="glass"] .fill.good { box-shadow: 0 0 12px color-mix(in srgb, var(--good) 70%, transparent); }
  html[data-theme="glass"] .track { background: rgba(255, 255, 255, .08); }
  html[data-theme="glass"] .big { filter: drop-shadow(0 0 22px rgba(184, 107, 255, .35)); }
  html[data-theme="glass"] .pos, html[data-theme="glass"] .down { text-shadow: 0 0 12px color-mix(in srgb, var(--good) 45%, transparent); }
  html[data-theme="glass"] .neg, html[data-theme="glass"] .up { text-shadow: 0 0 12px color-mix(in srgb, var(--spend) 40%, transparent); }
  html[data-theme="glass"] .chart rect { filter: drop-shadow(0 0 6px currentColor); }
  html[data-theme="glass"] .sankey .lk { fill-opacity: .32; }
  html[data-theme="glass"] .tabs a.on { text-shadow: 0 0 12px color-mix(in srgb, var(--accent) 60%, transparent); }
  html[data-theme="glass"] .tabs { background: rgba(255, 255, 255, .06); }
  html[data-theme="glass"] .hm-cell[style*="--p"] { box-shadow: 0 0 10px color-mix(in srgb, var(--spend) calc(var(--p) * .6), transparent); }
  html[data-theme="glass"] .av { box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 0 0 1px color-mix(in oklab, var(--c) 35%, transparent), 0 0 14px color-mix(in oklab, var(--c) 30%, transparent); }
  html[data-theme="glass"] .appbar.scrolled { background: rgba(10, 8, 24, .45); }
  html[data-theme="glass"] .scrim { background: rgba(4, 3, 12, .45); }
  @media (prefers-reduced-motion: reduce) { html[data-theme="glass"] body::after { animation: none; } }
  /* Moving light under blurred glass makes the browser re-blur every blurred surface on every frame. Pause it while scrolling
     (the cards and sidebar lose their live blur below, with the Frosted ones). */
  html.scrolling[data-theme="glass"] body::after { animation-play-state: paused; }
  /* ---------- Alignment: centered labels, even controls, room to breathe ---------- */
  .btn { justify-content: center; text-align: center; }
  .round { display: inline-grid; place-items: center; padding: 0; flex: none; }
  .month { gap: 6px; }
  .month .round { width: 34px; height: 34px; }
  .month .btn { height: 34px; padding-block: 0; }
  .row > span:is(.neutral, .num):last-child { white-space: nowrap; }
  .panel-head { flex-wrap: wrap; row-gap: 8px; }
  .panel-head > .check { white-space: nowrap; }
  .show-s { display: none; }
  .review-row > .btn { flex: none; }
  .drawer footer { flex-wrap: wrap; align-items: center; }
  @media (min-width: 901px) { main { padding-bottom: 112px; } }     /* the last card scrolls clear of the + button */
  @media (max-width: 600px) {
    .tbl .show-s { display: block; margin-top: 4px; }
    .review-row > .btn .lbl { display: none; }
    .review-row > .btn { width: 36px; height: 36px; padding: 0; border-radius: 50%; }
    .drawer footer { gap: 8px; padding: 14px 16px calc(14px + env(safe-area-inset-bottom)); }
    .drawer footer .btn { padding: 9px 12px; }
    .drawer footer .grow { flex: 1 1 0; min-width: 0; }
  }
  /* ---------- Shape, every theme: pill buttons and switches, a floating sidebar and tab bar ----------
     Colors come from the theme; Frosted glass and the glass/neon themes lay their own on top. */
  .btn, .btn.small { border-radius: 999px; }
  .seg { border-radius: 22px; }
  .seg button { border-radius: 999px; }
  :is(.seg button, .tabs a).on { background: var(--accent); color: var(--on-accent); box-shadow: none; }
  .tabs { width: fit-content; max-width: 100%; gap: 2px; padding: 4px; border: 0; border-radius: 999px; background: var(--faint); box-shadow: inset 0 0 0 1px var(--line); scrollbar-width: none; }
  .tabs::-webkit-scrollbar { display: none; }
  .tabs a { padding: 7px 14px; margin: 0; border: 0; border-radius: 999px; line-height: 1.2; }
  .tabs a.on .neutral { color: inherit; opacity: .7; }
  @media (min-width: 901px) {
    .side { margin: 14px 0 14px 14px; height: calc(100vh - 28px); top: 14px; border: 1px solid var(--line); border-radius: 26px; background: var(--panel); box-shadow: var(--shadow); }
  }
  .nav a { border-radius: 999px; }
  .nav a.on { background: color-mix(in srgb, var(--accent) 13%, transparent); box-shadow: none; }
  html[data-theme="carbon"] .nav a.on::before { display: none; }
  .tabbar { left: 14px; right: 14px; bottom: calc(10px + env(safe-area-inset-bottom)); padding: 6px; border: 1px solid var(--line); border-radius: 999px; align-items: center;
    background: color-mix(in srgb, var(--panel) 84%, transparent); box-shadow: var(--shadow); -webkit-backdrop-filter: blur(24px) saturate(160%); backdrop-filter: blur(24px) saturate(160%); }
  .tabbar :is(a, button) { position: relative; z-index: 1; }
  .tabbar a { border-radius: 999px; padding: 7px 0; margin: 0 3px; }
  .tabbar .plus { margin: 0 auto; width: 48px; height: 48px; }
  .tab-pill { display: block; position: absolute; left: 0; top: 6px; bottom: 6px; border-radius: 999px; pointer-events: none; background: color-mix(in srgb, var(--accent) 15%, transparent); }
  .tab-pill.off { opacity: 0; }
  .pill-ready .tab-pill { transition: transform .42s cubic-bezier(.3, 1.3, .5, 1), width .42s cubic-bezier(.3, 1.3, .5, 1), opacity .2s; }
  /* Folded while scrolling down (phone.ts): the bar shrinks away into the + button at the bottom right (#fab).
     Only transform and opacity move, so the phone never has to lay out or re-blur anything per frame. */
  .tabbar { transform-origin: calc(100% - 30px) 50%; transition: transform .34s cubic-bezier(.3, 1.1, .4, 1), opacity .22s ease, visibility 0s; }
  .tabbar.mini { transform: scale(.18, .7); opacity: 0; visibility: hidden; pointer-events: none;
    transition: transform .3s cubic-bezier(.5, 0, .7, .4), opacity .2s ease .06s, visibility 0s .3s; }
  @media (max-width: 900px) {
    main { padding-bottom: calc(96px + env(safe-area-inset-bottom, 0px)) !important; }
    :is(.undo, .toast) { bottom: calc(env(safe-area-inset-bottom, 0px) + 92px); }
    /* Phones: the bar spans the screen above the floating tab bar instead of a narrow centred pill that wraps */
    .undo { left: 14px; right: 14px; transform: none; width: auto; max-width: none; border-radius: 22px; padding: 10px 10px 10px 18px; font-size: 14.5px; }
    .undo button { padding: 10px 18px; font-size: 14.5px; }
  }
  /* ---------- Theme: Frosted glass (warm light glass over a soft-focus room) ---------- */
  html[data-theme="frosted"] { --bg: #d9c7b3; --panel: rgba(255, 250, 244, .5); --line: rgba(255, 255, 255, .55); --text: #1d1915; --muted: #6a5e54; --faint: rgba(255, 255, 255, .35);
    --good: #2a9163; --spend: #d94f27; --income: #2a9163; --warn: #c98a12; --accent: #e2552c; --on-accent: #ffffff;
    --shadow: 0 18px 50px rgba(60, 35, 15, .18); --radius: 22px; color-scheme: light;
    --ink: #17130f; --frost-edge: inset 0 1px 0 rgba(255, 255, 255, .75), inset 0 0 0 1px rgba(255, 255, 255, .35);
    /* what Settings → Appearance → Customize can change (themevars.ts sets these on <html>): the room's colors and the glass */
    --glow1: #8a5a3c; --glow2: #f1e4d3; --glow3: #5f6b4a; --glass-base: #fffaf4; --glass-tint: 22%; --glass-blur: 28px;
    background: var(--bg); }
  html[data-theme="frosted"] body { background: transparent; }
  /* the room: wood, a bright window, a dark screen, a plant, a rug */
  html[data-theme="frosted"] body::after { content: ''; position: fixed; inset: 0; z-index: -1; pointer-events: none;
    background:
      radial-gradient(30vmax 40vmax at 12% 18%, color-mix(in srgb, var(--glow1) 70%, transparent), transparent 70%),
      radial-gradient(40vmax 26vmax at 70% 12%, color-mix(in srgb, var(--glow2) 95%, transparent), transparent 70%),
      radial-gradient(34vmax 22vmax at 55% 48%, rgba(40, 32, 28, .5), transparent 70%),
      radial-gradient(28vmax 28vmax at 88% 70%, color-mix(in srgb, var(--glow3) 55%, transparent), transparent 70%),
      radial-gradient(50vmax 30vmax at 40% 95%, color-mix(in srgb, var(--glow1) 75%, transparent), transparent 70%),
      linear-gradient(180deg, color-mix(in srgb, var(--bg) 40%, #fff), var(--bg)); }
  html[data-theme="frosted"] :is(.panel, .daycards tbody.day, .daycards > .center-empty, .kpi, .insight, .extra, .split, .login form, .dash-bar) {
    background: linear-gradient(160deg, rgba(255, 255, 255, .42), rgba(255, 255, 255, .18)), color-mix(in srgb, var(--glass-base) var(--glass-tint), transparent);
    border: 1px solid rgba(255, 255, 255, .6); box-shadow: var(--frost-edge), 0 10px 30px rgba(70, 40, 20, .12);
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(150%); backdrop-filter: blur(var(--glass-blur)) saturate(150%); }
  html[data-theme="frosted"] :is(.drawer, dialog, .calpop, .pickpop, .palette-box, .bulkbar) {
    background: rgba(250, 243, 235, .8); border-color: rgba(255, 255, 255, .7);
    -webkit-backdrop-filter: blur(36px) saturate(160%); backdrop-filter: blur(36px) saturate(160%); }
  html[data-theme="frosted"] .drawer footer { background: transparent; border-top-color: rgba(255, 255, 255, .6); }
  html[data-theme="frosted"] :is(input[type=text], input[type=number], input[type=date], input[type=password], input[type=search], select, textarea, .round, .wctl button) {
    background: rgba(255, 255, 255, .45); border-color: rgba(255, 255, 255, .7); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .6); }
  html[data-theme="frosted"] select option { background: #f6efe7; }
  html[data-theme="frosted"] :is(input, select, textarea):focus { border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent); }
  /* pill buttons: ink for the main action, glass for the rest */
  html[data-theme="frosted"] .btn { background: rgba(255, 255, 255, .45); border-color: rgba(255, 255, 255, .7); }
  html[data-theme="frosted"] .btn.primary { background: var(--ink); color: #fff; border-color: var(--ink); box-shadow: 0 6px 18px rgba(23, 19, 15, .25); }
  html[data-theme="frosted"] .seg { background: rgba(255, 255, 255, .35); }
  html[data-theme="frosted"] .seg button.on { background: var(--ink); color: #fff; }
  html[data-theme="frosted"] .tbl.feed td { background: rgba(255, 250, 244, .42); border-color: rgba(255, 255, 255, .5); }
  html[data-theme="frosted"] .tbl.feed tr.dayhead div { background: rgba(255, 248, 240, .6); -webkit-backdrop-filter: blur(20px); backdrop-filter: blur(20px); }
  html[data-theme="frosted"] .tbl tr.click:hover td { background: rgba(255, 255, 255, .35); }
  html[data-theme="frosted"] .tabs { background: rgba(255, 255, 255, .35); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .5); }
  html[data-theme="frosted"] .tabs a.on { background: var(--ink); color: #fff; }
  html[data-theme="frosted"] .track { background: rgba(255, 255, 255, .5); }
  html[data-theme="frosted"] .big { color: var(--text); }
  html[data-theme="frosted"] .appbar.scrolled { background: rgba(240, 228, 214, .55); }
  html[data-theme="frosted"] .scrim { background: rgba(40, 25, 12, .25); }
  /* floating glass sidebar, a white pill on the current page */
  html[data-theme="frosted"] .side { background: rgba(255, 250, 244, .38); border: 1px solid rgba(255, 255, 255, .6); box-shadow: var(--frost-edge), 0 10px 30px rgba(70, 40, 20, .12);
    -webkit-backdrop-filter: blur(28px) saturate(150%); backdrop-filter: blur(28px) saturate(150%); }
  html[data-theme="frosted"] .nav a.on { background: #fff; color: var(--text); box-shadow: 0 4px 14px rgba(70, 40, 20, .14); }
  /* floating glass tab bar on phones, a white pill on the current tab */
  html[data-theme="frosted"] .tabbar { background: rgba(255, 250, 244, .55); border: 1px solid rgba(255, 255, 255, .7); box-shadow: var(--frost-edge), 0 14px 40px rgba(60, 35, 15, .22);
    -webkit-backdrop-filter: blur(30px) saturate(170%); backdrop-filter: blur(30px) saturate(170%); }
  html[data-theme="frosted"] .tabbar a { color: #5d5249; }
  html[data-theme="frosted"] .tabbar a.on { color: var(--text); }
  html[data-theme="frosted"] .tab-pill { background: #fff; box-shadow: 0 3px 12px rgba(70, 40, 20, .16); }
  html[data-theme="frosted"] :is(.tabbar .plus, .fab) { background: var(--ink); color: #fff; box-shadow: 0 6px 18px rgba(23, 19, 15, .3); }
  /* Other scenes (Settings → Appearance → Customize colors → Scene; themevars.ts sets data-scene). Each sets its own
     colors for the three --glow variables, so your own colors still apply on top. */
  html[data-theme="frosted"][data-scene="dunes"] { --bg: #e7a07f; --glow1: #b5654a; --glow2: #fff1d6; --glow3: #f3c9b8; }
  html[data-theme="frosted"][data-scene="dunes"] body::after { background:
      radial-gradient(16vmax 16vmax at 72% 26%, var(--glow2), transparent 70%),
      radial-gradient(60vmax 40vmax at 72% 26%, color-mix(in srgb, var(--glow2) 45%, transparent), transparent 70%),
      radial-gradient(70vmax 18vmax at 50% 72%, color-mix(in srgb, var(--glow1) 45%, transparent), transparent 70%),
      radial-gradient(90vmax 30vmax at 15% 100%, var(--glow1), transparent 70%),
      radial-gradient(80vmax 26vmax at 90% 95%, color-mix(in srgb, var(--glow1) 70%, var(--glow2)), transparent 70%),
      linear-gradient(180deg, var(--glow3), var(--bg)); }
  html[data-theme="frosted"][data-scene="garden"] { --bg: #cfd8bf; --glow1: #5f8050; --glow2: #fffbe6; --glow3: #a9bf8e; --accent: #d9662f; }
  html[data-theme="frosted"][data-scene="garden"] body::after { background:
      radial-gradient(50vmax 34vmax at 55% 8%, var(--glow2), transparent 70%),
      radial-gradient(26vmax 34vmax at 6% 30%, var(--glow1), transparent 70%),
      radial-gradient(30vmax 26vmax at 96% 22%, color-mix(in srgb, var(--glow1) 80%, transparent), transparent 70%),
      radial-gradient(40vmax 26vmax at 80% 80%, var(--glow3), transparent 70%),
      radial-gradient(44vmax 24vmax at 18% 92%, color-mix(in srgb, var(--glow1) 65%, var(--glow3)), transparent 70%),
      linear-gradient(180deg, color-mix(in srgb, var(--glow2) 60%, var(--bg)), var(--bg)); }
  html[data-theme="frosted"][data-scene="coast"] { --bg: #e8d8bd; --glow1: #3f87a3; --glow2: #f2f8fb; --glow3: #9ccbd8; --accent: #e0612f; }
  html[data-theme="frosted"][data-scene="coast"] body::after { background:
      radial-gradient(60vmax 20vmax at 50% 0%, var(--glow2), transparent 70%),
      radial-gradient(18vmax 14vmax at 78% 18%, #fff, transparent 70%),
      radial-gradient(100vmax 22vmax at 50% 52%, var(--glow1), transparent 70%),
      radial-gradient(70vmax 12vmax at 30% 44%, var(--glow3), transparent 70%),
      linear-gradient(180deg, var(--glow3) 0%, var(--glow2) 30%, color-mix(in srgb, var(--glow1) 60%, var(--glow3)) 48%, var(--glow1) 58%, var(--bg) 72%, var(--bg)); }
  html[data-theme="frosted"][data-scene="blossom"] { --bg: #f1d3df; --glow1: #d47fa8; --glow2: #fff4f8; --glow3: #a596e0; --accent: #d9467a; }
  html[data-theme="frosted"][data-scene="blossom"] body::after { background:
      radial-gradient(36vmax 30vmax at 15% 15%, var(--glow1), transparent 70%),
      radial-gradient(44vmax 30vmax at 70% 10%, var(--glow2), transparent 70%),
      radial-gradient(36vmax 36vmax at 92% 60%, var(--glow3), transparent 70%),
      radial-gradient(30vmax 24vmax at 30% 70%, color-mix(in srgb, var(--glow1) 55%, var(--glow2)), transparent 70%),
      radial-gradient(50vmax 26vmax at 50% 100%, color-mix(in srgb, var(--glow3) 70%, var(--glow1)), transparent 70%),
      linear-gradient(180deg, var(--glow2), var(--bg)); }
  /* Your photo, softened like the scenes */
  html[data-theme="frosted"][data-scene="photo"] body::after { inset: -60px; background: var(--photo) center / cover no-repeat; filter: blur(22px) saturate(115%); }
  /* Night city: the same glass, dark */
  html[data-theme="frosted"][data-scene="night"] { --bg: #120f1c; --glow1: #ff7a3d; --glow2: #3b2a6b; --glow3: #2bb3c9; --text: #f4efe9; --muted: #aba2b6; --faint: rgba(255, 255, 255, .08); --panel: rgba(29, 24, 40, .6);
    --line: rgba(255, 255, 255, .14); --glass-base: #1d1828; --glass-tint: 45%; --accent: #ff7a3d; --on-accent: #1a0d05; --ink: #f4efe9; --good: #47d18c; --income: #47d18c; --spend: #ff7a3d; color-scheme: dark;
    --frost-edge: inset 0 1px 0 rgba(255, 255, 255, .16), inset 0 0 0 1px rgba(255, 255, 255, .05); }
  html[data-theme="frosted"][data-scene="night"] body::after { background:
      /* soft, dim city lights: bright spots behind text made it hard to read */
      radial-gradient(18vmax 18vmax at 14% 26%, color-mix(in srgb, var(--glow1) 34%, transparent), transparent 70%),
      radial-gradient(16vmax 16vmax at 70% 18%, color-mix(in srgb, color-mix(in srgb, var(--glow1) 60%, #ffd36b) 26%, transparent), transparent 70%),
      radial-gradient(18vmax 18vmax at 92% 52%, color-mix(in srgb, var(--glow3) 30%, transparent), transparent 70%),
      radial-gradient(16vmax 16vmax at 30% 70%, color-mix(in srgb, color-mix(in srgb, var(--glow3) 50%, #b56bff) 26%, transparent), transparent 70%),
      radial-gradient(60vmax 40vmax at 50% 20%, var(--glow2), transparent 70%),
      linear-gradient(180deg, #1b1530, var(--bg)); }
  html[data-theme="frosted"][data-scene="night"] :is(.panel, .daycards tbody.day, .daycards > .center-empty, .kpi, .insight, .extra, .split, .login form, .dash-bar) {
    background: linear-gradient(160deg, rgba(255, 255, 255, .1), rgba(255, 255, 255, .03)), color-mix(in srgb, var(--glass-base) var(--glass-tint), transparent);
    border-color: rgba(255, 255, 255, .13); box-shadow: var(--frost-edge), 0 12px 40px rgba(0, 0, 0, .35); }
  html[data-theme="frosted"][data-scene="night"] :is(.drawer, dialog, .calpop, .pickpop, .palette-box, .bulkbar) { background: rgba(26, 21, 36, .82); border-color: rgba(255, 255, 255, .14); }
  html[data-theme="frosted"][data-scene="night"] :is(input[type=text], input[type=number], input[type=date], input[type=password], input[type=search], select, textarea, .round, .wctl button, .btn, .seg, .tabs) {
    background: rgba(255, 255, 255, .07); border-color: rgba(255, 255, 255, .14); box-shadow: none; }
  html[data-theme="frosted"][data-scene="night"] select option { background: #1d1828; }
  html[data-theme="frosted"][data-scene="night"] :is(.btn.primary, .seg button.on, .tabs a.on, .tabbar .plus, .fab) { background: var(--ink); color: #15111c; border-color: var(--ink); }
  html[data-theme="frosted"][data-scene="night"] :is(.tbl.feed td) { background: rgba(29, 24, 40, .45); border-color: rgba(255, 255, 255, .08); }
  html[data-theme="frosted"][data-scene="night"] .tbl.feed tr.dayhead div { background: rgba(26, 21, 36, .7); }
  html[data-theme="frosted"][data-scene="night"] .side { background: rgba(26, 21, 36, .5); border-color: rgba(255, 255, 255, .14); }
  html[data-theme="frosted"][data-scene="night"] .tabbar { background: rgba(26, 21, 36, .8); border-color: rgba(255, 255, 255, .14); }
  html[data-theme="frosted"][data-scene="night"] .tabbar a { color: var(--muted); }
  html[data-theme="frosted"][data-scene="night"] :is(.tab-pill, .nav a.on) { background: rgba(255, 255, 255, .16); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .2); }
  html[data-theme="frosted"][data-scene="night"] :is(.tabbar a.on, .nav a.on) { color: var(--text); }
  html[data-theme="frosted"][data-scene="night"] .track { background: rgba(255, 255, 255, .1); }
  html[data-theme="frosted"][data-scene="night"] .appbar.scrolled { background: rgba(18, 15, 28, .55); }
  /* Both glass themes: what's behind a card is only soft light (no card overlaps another), so a live blur under every card
     looks the same but makes the browser re-blur each card on every scroll frame, every entrance animation and, in
     Liquid glass, every frame of the moving light. Only floating things keep it (tab bar, sheets, menus).
     Same selector list as the rules that add the blur: :is() takes its most specific entry, so a shorter list loses. */
  html:is([data-theme="glass"], [data-theme="frosted"]) :is(.panel, .daycards tbody.day, .daycards > .center-empty, .kpi, .insight, .extra, .split, .dash-bar) { -webkit-backdrop-filter: none; backdrop-filter: none; }
  html[data-theme="glass"] .side { -webkit-backdrop-filter: none; backdrop-filter: none; }
  @media (max-width: 900px) {
    .tbl.feed tr.dayhead div { -webkit-backdrop-filter: none; backdrop-filter: none; }     /* one blur per day header adds up on a long feed */
    html[data-theme="glass"] .tbl.feed tr.dayhead div { background: rgba(20, 16, 42, .9); }
    html[data-theme="frosted"] .tbl.feed tr.dayhead div { background: rgba(255, 248, 240, .88); }
    html[data-theme="frosted"][data-scene="night"] .tbl.feed tr.dayhead div { background: rgba(30, 25, 40, .92); }
  }
  /* ---------- iPhone: notch / home bar, no accidental zoom, native-app shell ---------- */
  body { touch-action: manipulation; }
  /* iOS 26 draws its own blur under the status bar in a Home Screen app, reaching about 30pt below the safe area. Nothing in the page can turn it off,
     so the title bar, search field and other top controls sit --edge lower than the safe area. Landscape phones hide the status bar. */
  :root { --edge: 0px; }
  @media (orientation: portrait) { html.ios-web { --edge: 28px; } }
  /* No fixed strip behind the status bar: Safari 26 paints the colour of a fixed element at the top edge as a solid band there,
     which hid the page (see .scrim too). Without one, Safari and the Home Screen app show the page through their own blur. */
  html.native { -webkit-tap-highlight-color: transparent; -webkit-touch-callout: none; }
  html.native body { -webkit-user-select: none; user-select: none; }
  html.native input, html.native textarea, html.native [contenteditable] { -webkit-user-select: text; user-select: text; }
  @media (max-width: 900px) {
    main#view { padding-top: calc(22px + env(safe-area-inset-top, 0px)) !important;
      padding-left: calc(16px + env(safe-area-inset-left, 0px)) !important; padding-right: calc(16px + env(safe-area-inset-right, 0px)) !important; }
    input[type=text], input[type=number], input[type=date], input[type=password], input[type=search], select, textarea { font-size: 16px; }
    .drawer { max-height: calc(100dvh - env(safe-area-inset-top, 0px) - var(--edge) - 12px); }
  }
  /* ---------- App shell (iPhone app / Home Screen): iOS title bar, sheets, touch feel ---------- */
  .appbar { display: none; }
  @media (max-width: 900px) {
    html.shell .appbar { display: flex; position: fixed; top: 0; left: 0; right: 0; z-index: 18; height: calc(env(safe-area-inset-top, 0px) + var(--edge) + 44px);
      padding: calc(env(safe-area-inset-top, 0px) + var(--edge)) 70px 0; align-items: center; justify-content: center; pointer-events: none; transition: transform .3s cubic-bezier(.2, .8, .2, 1), background-color .2s, box-shadow .2s; }
    html.shell .appbar.scrolled { background: color-mix(in srgb, var(--bg) 80%, transparent); -webkit-backdrop-filter: saturate(180%) blur(20px); backdrop-filter: saturate(180%) blur(20px);
      box-shadow: 0 .5px 0 color-mix(in srgb, var(--text) 18%, transparent); }
    html.shell .ab-title { font-weight: 600; font-size: 17px; opacity: 0; transform: translateY(6px); transition: opacity .18s, transform .18s; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    html.shell .appbar.scrolled .ab-title { opacity: 1; transform: none; }
    html.shell .ab-back { position: absolute; left: 4px; bottom: 0; height: 44px; display: flex; align-items: center; gap: 3px; padding: 0 10px 0 6px; color: var(--accent);
      text-decoration: none; font-size: 17px; pointer-events: auto; max-width: 45%; }
    html.shell .ab-back span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    html.shell .ab-back svg { width: 12px; height: 21px; flex: none; }
    html.shell .ab-back:active { opacity: .35; }
    html.shell main#view { padding-top: calc(env(safe-area-inset-top, 0px) + var(--edge) + 44px) !important; }
    html.shell #view > .shell-hide { display: none; }
    html.shell .head { margin-bottom: 18px; }
    html.shell .head h1 { font-size: 32px; font-weight: 700; letter-spacing: .003em; line-height: 1.12; }
    html.shell .tbl.feed tr.dayhead { top: calc(env(safe-area-inset-top, 0px) + var(--edge) + 44px); }
    html.shell .bulkbar { top: calc(env(safe-area-inset-top, 0px) + var(--edge) + 52px); }
    html.shell .ptr { top: calc(env(safe-area-inset-top, 0px) + var(--edge) + 44px); }
    /* Scrolling down slides the title bar away (phone.ts foldOnScroll); scrolling up or reaching the top brings it back */
    html.shell.scroll-down .appbar { transform: translateY(-100%); }
    html.shell :is(.tbl.feed tr.dayhead, .bulkbar) { transition: top .3s cubic-bezier(.2, .8, .2, 1); }
    html.shell.scroll-down .tbl.feed tr.dayhead { top: calc(env(safe-area-inset-top, 0px) + var(--edge)); }
    html.shell.scroll-down .bulkbar { top: calc(env(safe-area-inset-top, 0px) + var(--edge) + 8px); }
    /* Native tab bar in the iPhone app replaces the web one */
    html.native-tabs .tabbar { display: none !important; }
    html.native-tabs main#view { padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 49px + 28px) !important; }
    html.native-tabs .undo, html.native-tabs .toast { bottom: calc(env(safe-area-inset-bottom, 0px) + 62px); }
    /* iOS page sheet: the page behind steps back while a sheet is open */
    html.shell #app { transform-origin: 50% var(--sy, 0px); transition: transform .42s cubic-bezier(.2,.9,.25,1), filter .42s; }
    html.shell.sheet-open #app { transform: scale(.94); filter: brightness(.9); }
    html.shell.sheet-open, html.shell.sheet-open body { background: #000; }
    html.shell .scrim { background: rgba(0, 0, 0, .25); }
    html.shell .drawer { border-radius: 14px 14px 0 0; }
  }
  /* Touch: iOS-style press feedback instead of mouse hover effects */
  @media (hover: none) {
    .btn:hover { border-color: var(--line); } .btn.primary:hover { opacity: 1; }
    .tbl tr.click:hover td { background: transparent; }
    .nav a:hover, .side .foot a:hover, .side .foot button:hover { background: none; }
    .insight:hover { transform: none; border-color: var(--line); }
    .tbl.feed .inl:hover { background: none; box-shadow: none; color: inherit; }
    .list a.row:hover .name { text-decoration: none; }
    .tbl.feed tr.click:active td, .tbl tr.click:active td { background: var(--faint); transition: none; }
    .btn:active, .round:active, .link:active, .list a.row:active, .insight:active, .hm-cell:active, .tabbar a:active, .pal-item:active, .wctl button:active { opacity: .45; transform: none; transition: none; }
    .tbl.feed .inl:active { background: var(--faint); }
  }
  /* Push / pop page transitions (like navigating in an iOS app) */
  html[data-vtdir="push"]::view-transition-old(page) { animation: vtPushOut .4s cubic-bezier(.2,.9,.25,1) both; }
  html[data-vtdir="push"]::view-transition-new(page) { animation: vtPushIn .4s cubic-bezier(.2,.9,.25,1) both; }
  html[data-vtdir="pop"]::view-transition-old(page) { animation: vtPopOut .34s cubic-bezier(.3,.8,.3,1) both; z-index: 2; }
  html[data-vtdir="pop"]::view-transition-new(page) { animation: vtPopIn .34s cubic-bezier(.3,.8,.3,1) both; }
  @keyframes vtPushIn { from { transform: translateX(100%); } }
  @keyframes vtPushOut { to { transform: translateX(-28%); opacity: .6; } }
  @keyframes vtPopIn { from { transform: translateX(-28%); opacity: .6; } }
  @keyframes vtPopOut { to { transform: translateX(100%); } }
  /* ---------- View Transitions ---------- */
  ::view-transition-group(*) { animation-duration: .32s; animation-timing-function: cubic-bezier(.2,.8,.2,1); }
  html.vt-page #view { view-transition-name: page; }
  /* The tab bar stays put while the page under it moves (otherwise the page's picture covers it mid-slide) */
  html.vt-page .tabbar { view-transition-name: tabbar; }
  ::view-transition-group(tabbar), ::view-transition-new(tabbar) { animation: none; }
  ::view-transition-old(tabbar) { display: none; }
  ::view-transition-old(page) { animation: vtFadeOut .14s ease both; }
  ::view-transition-new(page) { animation: vtFadeUp .26s cubic-bezier(.2,.8,.2,1) both; }
  html[data-vtdir="next"]::view-transition-old(page) { animation: vtOutLeft .2s ease both; }
  html[data-vtdir="next"]::view-transition-new(page) { animation: vtInRight .3s cubic-bezier(.2,.8,.2,1) both; }
  html[data-vtdir="prev"]::view-transition-old(page) { animation: vtOutRight .2s ease both; }
  html[data-vtdir="prev"]::view-transition-new(page) { animation: vtInLeft .3s cubic-bezier(.2,.8,.2,1) both; }
  ::view-transition-old(ptitle), ::view-transition-new(ptitle) { height: 100%; width: auto; object-fit: contain; object-position: left center; }
  ::view-transition-group(ptitle) { animation-duration: .36s; z-index: 2; }
  html.vt-drawer-open .drawer, html.vt-drawer-close .drawer { view-transition-name: drawer; transition: none; }
  html.vt-drawer-open .scrim, html.vt-drawer-close .scrim { view-transition-name: scrim; transition: none; }
  html.vt-drawer-open::view-transition-old(drawer) { display: none; }
  html.vt-drawer-open::view-transition-new(drawer) { animation: vtInDrawer .34s cubic-bezier(.2,.8,.2,1) both; }
  html.vt-drawer-close::view-transition-new(drawer) { display: none; }
  html.vt-drawer-close::view-transition-old(drawer) { animation: vtOutDrawer .26s cubic-bezier(.4,0,.6,1) both; }
  ::view-transition-group(txav) { animation-duration: .38s; z-index: 5; }
  ::view-transition-old(txav), ::view-transition-new(txav) { height: 100%; width: 100%; }
  ::view-transition-old(txav) { animation: vtFadeOut .12s ease both; }
  ::view-transition-new(txav) { animation: none; }
  html.vt-theme::view-transition-old(root), html.vt-theme::view-transition-new(root) { animation: none; mix-blend-mode: normal; }
  html.vt-theme::view-transition-group(root) { animation-duration: .52s; }
  @keyframes vtFadeOut { to { opacity: 0; } }
  @keyframes vtFadeUp { from { opacity: 0; transform: translateY(10px); } }
  @keyframes vtOutLeft { to { opacity: 0; transform: translateX(-28px); } }
  @keyframes vtInRight { from { opacity: 0; transform: translateX(36px); } }
  @keyframes vtOutRight { to { opacity: 0; transform: translateX(28px); } }
  @keyframes vtInLeft { from { opacity: 0; transform: translateX(-36px); } }
  @keyframes vtInDrawer { from { transform: translateX(100%); } }
  @keyframes vtOutDrawer { to { transform: translateX(100%); } }
  @keyframes vtInSheet { from { transform: translateY(100%); } }
  @keyframes vtOutSheet { to { transform: translateY(100%); } }
  /* Printing (or saving as PDF): ink on white whatever the theme, no floating controls, and the coloured dots, bars and fills kept.
     Browsers drop background colours when printing unless told otherwise, and that's what the bars and legend dots are made of;
     Safari also prints a fading SVG gradient as a solid block, so chart fills become a flat tint of their colour (set on the path). */
  @media print {
    :root, html[data-theme] { --bg: #fff !important; --panel: #fff !important; --line: #e9e7e0 !important; --text: #22221f !important; --muted: #75726a !important;
      --faint: #efede7 !important; --good: #3f7a5a !important; --spend: #c0603a !important; --income: #6f9a82 !important; --warn: #b8893a !important;
      --shadow: none !important; --edge: 0px !important; color-scheme: light; }
    html, body { background: #fff !important; color: var(--text); }
    *, *::before, *::after { -webkit-print-color-adjust: exact; print-color-adjust: exact; text-shadow: none !important; }
    body::before, body::after { display: none !important; }
    .side, .head .actions, .toolbar, .drawer, .scrim, .toast, .undo, .tabbar, .fab, .search-btn, .demo-badge, .tip, .ptr, .offline, .saved-reports, .save-report { display: none !important; }
    .app { display: block; } main, main#view { padding: 0 !important; max-width: none; }
    :is(.panel, .kpi, .insight, .extra, .split, .dash-bar, .daycards tbody.day) { background: #fff !important; border: 1px solid var(--line) !important; box-shadow: none !important;
      -webkit-backdrop-filter: none !important; backdrop-filter: none !important; animation: none !important; }
    .panel, .kpi, .part, .tbl tr { break-inside: avoid; }
    .report-cols .panel { break-inside: auto; }
    .panel-head, .panel .lead, .panel h2 { break-after: avoid; } .donut { break-inside: avoid; }
    .track { background: var(--faint) !important; }
    :is(.area, .soft) { fill: currentColor; fill-opacity: .16; animation: none !important; }
    :is(.draw, .fill, .seg, .bar) { animation: none !important; } .fill { box-shadow: none !important; }
  }
  @media (max-width: 900px) {
    .tabbar:not([hidden]) { display: grid; }
    .fab { right: calc(14px + env(safe-area-inset-right, 0px)); bottom: calc(13px + env(safe-area-inset-bottom, 0px)); z-index: 17;
      opacity: 0; visibility: hidden; transform: scale(.4); pointer-events: none; transition: transform .2s ease, opacity .15s ease, visibility 0s .2s; }
    .fab.on { opacity: 1; visibility: visible; transform: none; pointer-events: auto; transition: transform .42s cubic-bezier(.3, 1.5, .5, 1) .1s, opacity .2s ease .1s, visibility 0s; }
    .side { display: none !important; }
    main { padding-bottom: 110px !important; }
    .btn { padding: 10px 16px; } .btn.small { padding: 8px 13px; }
    .tbl td { padding-top: 14px; padding-bottom: 14px; }
    .tbl .sel { display: none; }
    .app { grid-template-columns: 1fr; }
    .side { position: sticky; z-index: 5; height: auto; flex-direction: row; align-items: center; padding: 10px 12px; overflow-x: auto; background: var(--bg); border-right: 0; border-bottom: 1px solid var(--line); }
    .brand { padding: 0 10px 0 4px; }
    .nav { display: flex; gap: 2px; }
    .nav a span { display: none; }
    html[data-theme="carbon"] .nav a.on::before { display: none; }
    .side .spacer, .nav-h, .side .foot > :not(#navFoot) { display: none; }
    .side .foot .nav a { margin: 0; } .side .foot .nav a span { display: none; }
    main { padding: 22px 16px 60px; }
    .hero, .grid { grid-template-columns: 1fr; }
    .big { font-size: 40px; }
    .stats { gap: 12px; } .stat .val { font-size: 19px; }
    .panel { padding: 20px; }
    .tbl .hide-s { display: none; }
    .cat-s { display: inline; }
    .show-s { display: initial; }
    div.show-s { display: block; }
    .tbl .namecol { min-width: 0; }
    .tbl input.inline { width: 96px; }
    .grid2.stack-s { grid-template-columns: 1fr; }
    form.range { flex-basis: 100%; gap: 6px; }
    form.range > span { display: none; }
    .stat input { max-width: 100%; }
    .tbl.feed, .tbl.feed.has-sel { --cols: minmax(0, 1fr) auto; }
    .tbl.feed .hide-s, .tbl.feed .sel { display: none !important; }
    .tbl.feed tr.dayhead div { padding: 7px 12px; }
    .av { width: 38px; height: 38px; }
    .insights { grid-auto-columns: 82%; margin-top: -18px; }
    .dhero h2 { max-width: 62vw; }
    /* Bottom sheet */
    .drawer { top: auto; left: 0; right: 0; width: 100%; max-height: 92vh; max-height: 92dvh; border-radius: 22px 22px 0 0; transform: translateY(105%); box-shadow: 0 -10px 40px rgba(0,0,0,.25); }
    .drawer.open { transform: none; }
    .drawer.dragging { transition: none !important; }
    .grab { display: block; width: 40px; height: 5px; border-radius: 99px; background: var(--line); margin: 9px auto -4px; flex: none; }
    .drawer header { padding-top: 14px; touch-action: none; }
    .drawer footer { padding-bottom: calc(16px + env(safe-area-inset-bottom)); }
    /* More buttons than fit (Delete, Duplicate, Refund…): the ones before the gap go on a row of their own */
    .drawer footer:has(> .btn + .btn + .grow) { flex-wrap: wrap; }
    .drawer footer:has(> .btn + .btn + .grow) > .grow { flex: 0 0 100%; margin: -5px 0; }
    .drawer footer:has(> .btn + .btn + .grow) > .btn { flex: 1 1 0; justify-content: center; text-align: center; padding-left: 8px; padding-right: 8px; }
    html.vt-drawer-open::view-transition-new(drawer) { animation-name: vtInSheet; }
    html.vt-drawer-close::view-transition-old(drawer) { animation-name: vtOutSheet; }
    .cards.editing .w { cursor: default; }
    .wctl .grip { touch-action: none; font-size: 20px; padding: 4px 8px 4px 2px; margin: -4px 0; }
    .tbl td, .tbl th { padding-left: 12px; padding-right: 12px; }
  }
  @media (max-width: 400px) {
    .tbl td, .tbl th { padding-left: 9px; padding-right: 9px; }
  }

  /* ---------- Universal search on phones: a search button up top, and a full-screen search ---------- */
  @media (max-width: 900px) {
    .search-btn { display: grid; place-items: center; position: fixed; z-index: 19; top: calc(env(safe-area-inset-top, 0px) + 6px); right: calc(16px + env(safe-area-inset-right, 0px));
      width: 36px; height: 36px; padding: 0; border-radius: 50%; border: 1px solid var(--line); background: color-mix(in srgb, var(--panel) 85%, transparent);
      -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px); color: var(--text); cursor: pointer; }
    .search-btn svg { width: 18px; height: 18px; }
    html.shell .search-btn { top: calc(env(safe-area-inset-top, 0px) + var(--edge) + 4px); right: calc(10px + env(safe-area-inset-right, 0px)); border-color: transparent; background: none; -webkit-backdrop-filter: none; backdrop-filter: none; color: var(--accent); }
    html.shell .search-btn svg { width: 22px; height: 22px; }
    /* leaves with the title bar, by the same distance so the two move as one */
    .search-btn { transition: transform .3s cubic-bezier(.2, .8, .2, 1), opacity .2s; }
    html.scroll-down .search-btn { transform: translateY(calc(-1 * (env(safe-area-inset-top, 0px) + var(--edge) + 44px))); opacity: 0; pointer-events: none; }
    html:not(.shell) #view > .head:first-child { padding-right: 52px; }
    html.pal-open .search-btn, #app[hidden] ~ .search-btn { display: none; }
    .palette { padding: 0; align-items: stretch; background: var(--bg); }
    .palette-box { width: 100%; height: 100vh; height: 100dvh; border: 0; border-radius: 0; box-shadow: none; display: flex; flex-direction: column; background: var(--bg); animation: none; }
    .pal-top { padding: calc(env(safe-area-inset-top, 0px) + max(8px, var(--edge) + 4px)) calc(14px + env(safe-area-inset-right, 0px)) 8px calc(16px + env(safe-area-inset-left, 0px)); border-bottom: 0; gap: 12px; }
    .palette-box .pal-top input { padding: 10px 12px 10px 36px; margin-left: -34px; border-radius: 10px; background: var(--faint); font-size: 17px; }
    .pal-top > svg { position: relative; z-index: 1; margin-left: 10px; }
    .pal-cancel { display: block; color: var(--accent); }
    .pal-list { flex: 1; max-height: none; padding: 4px calc(8px + env(safe-area-inset-right, 0px)) calc(20px + env(safe-area-inset-bottom, 0px)) calc(8px + env(safe-area-inset-left, 0px)); -webkit-overflow-scrolling: touch; }
    .pal-item { padding: 12px 10px; min-height: 48px; }
    .pal-item.on { background: none; box-shadow: none; }
    .pal-foot { display: none; }
  }
  @media (max-width: 900px) and (hover: none) { .pal-item:active { background: var(--faint); opacity: 1; } }

  /* ---------- Bills calendar ---------- */
  .bcal-dow, .bcal-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 6px; }
  .bcal-dow span { font-size: 11.5px; color: var(--muted); padding: 0 4px 6px; }
  .bcal-day { min-height: 92px; border-radius: 10px; background: var(--faint); padding: 6px; display: flex; flex-direction: column; gap: 4px; min-width: 0; }
  .bcal-day.pad { background: none; }
  .bcal-day.past:not(.today) .d { opacity: .55; }
  .bcal-day.today { box-shadow: inset 0 0 0 2px var(--accent); }
  .bcal-day .d { font-size: 12px; color: var(--muted); }
  .bpill { display: flex; justify-content: space-between; gap: 6px; border: 0; border-radius: 7px; padding: 3px 6px; font: inherit; font-size: 11.5px; cursor: pointer; text-align: left;
    color: var(--text); background: color-mix(in srgb, var(--tone, var(--muted)) 18%, var(--panel)); border-left: 3px solid var(--tone, var(--muted)); }
  .bpill .nm { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .bpill .num { flex: none; color: var(--muted); }
  .bpill.good { --tone: var(--good); } .bpill.warn { --tone: var(--warn); } .bpill.bad { --tone: var(--spend); }
  .bpill:hover { filter: brightness(1.05); }
  .bcal-agenda { display: none; }
  .bcal-agenda-day + .bcal-agenda-day { margin-top: 16px; }
  .bcal-agenda button.row { width: 100%; border: 0; border-top: 1px solid var(--line); background: none; font: inherit; color: inherit; padding: 9px 0; cursor: pointer; text-align: left; }
  @media (max-width: 700px) {
    .bcal { display: none; } .bcal-agenda { display: block; }
  }

  /* ---------- Monthly recap ---------- */
  .recap-notes { margin-bottom: 20px; }
  .recap-notes ul { margin: 0; padding-left: 18px; display: grid; gap: 6px; font-size: 15px; }
  .list button.row { width: 100%; border: 0; border-top: 1px solid var(--line); background: none; font: inherit; color: inherit; padding: 10px 0; cursor: pointer; text-align: left; align-items: center; }
  .list button.row:first-child { border-top: none; padding-top: 0; }
  .list button.row:hover .name > span:last-child { text-decoration: underline; text-underline-offset: 3px; }

  /* ---------- Payee page ---------- */
  .payee-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 14px 24px; }

  /* ---------- Forecast what-ifs ---------- */
  .whatif { display: grid; grid-template-columns: 2fr 1fr 1fr 1.2fr 1.2fr auto; gap: 8px; align-items: center; }
  @media (max-width: 800px) { .whatif { grid-template-columns: 1fr 1fr; } .whatif input[name=label] { grid-column: 1 / -1; } }

  /* ---------- Review queue ---------- */
  .review-row { display: flex; align-items: center; gap: 12px; padding: 10px 0; border-top: 1px solid var(--line); transition: opacity .2s, transform .2s; }
  .review-row:first-child { border-top: none; padding-top: 0; }
  .review-row.gone { opacity: 0; transform: translateX(24px); }
  .review-main { flex: 1; min-width: 0; display: flex; align-items: center; gap: 12px; border: 0; background: none; font: inherit; color: inherit; cursor: pointer; text-align: left; padding: 0; }
  .review-main .txt { flex: 1; min-width: 0; display: flex; flex-direction: column; }
  .review-main .desc, .review-main .sub-s { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .review-main:hover .desc { text-decoration: underline; text-underline-offset: 3px; }
  @media (max-width: 600px) { .review-row { flex-wrap: wrap; } .review-row > .btn { margin-left: auto; } }

  /* Map page (pages/map.ts): a Leaflet map of OpenStreetMap pictures with pins on top */
  /* isolate keeps Leaflet's z-index 400–1000 panes and controls under the tab bar and other fixed chrome */
  .map { height: min(62vh, 560px); min-height: 320px; background: var(--faint, #eee); touch-action: none; overscroll-behavior: contain; isolation: isolate; }
  .map.leaflet-container { background: var(--faint, #eee); font: inherit; font-size: 12px; }
  .leaflet-marker-icon.map-pin { border-radius: 50%; border: 2px solid #fff; background: var(--spend, #e5484d); color: #fff; font-size: 12px; font-weight: 600; line-height: 1;
    display: grid; place-items: center; cursor: pointer; box-shadow: 0 2px 6px rgba(0,0,0,.3); box-sizing: border-box; }
  .leaflet-marker-icon.map-pin.on { background: var(--accent); color: var(--on-accent); }
  form.ask { display: flex; align-items: center; gap: 10px; background: var(--panel); border: 1px solid var(--line); border-radius: 14px; padding: 6px 14px; margin-bottom: 16px; }
  form.ask svg { width: 18px; height: 18px; color: var(--muted); flex: none; }
  form.ask input { border: 0; background: none; flex: 1; font-size: 16px; padding: 8px 0; outline: none; box-shadow: none; }
  .ask-answer .ask-title { font-size: 18px; line-height: 1.45; margin: 6px 0 12px; }
  .ask-answer .list button.row { width: 100%; text-align: left; font: inherit; color: inherit; background: none; border: 0; border-top: 1px solid var(--line); border-radius: 0; padding-left: 0; padding-right: 0; cursor: pointer; }
  .ask-answer { margin-bottom: 16px; }
  .ask-examples { display: flex; flex-wrap: wrap; gap: 8px; }
  .ask-examples .chip { font-size: 13px; padding: 5px 12px; border: 0; cursor: pointer; white-space: normal; text-align: left; }

  /* ---------- Transaction feed: day titles, category colours, quieter amounts ---------- */
  .tbl.feed tr.dayhead .dd { color: var(--muted); font-weight: 500; }
  .tbl.feed tr.dayhead .num { padding: 2px 9px; border-radius: 999px; background: var(--faint); color: var(--text); font-size: 12px; font-weight: 600; }
  .tbl.feed tr.dayhead .num.pos { color: var(--good); background: color-mix(in srgb, var(--good) 13%, transparent); }
  /* Money out reads in the text colour; only money in is green */
  .tbl.feed .amt { font-weight: 600; }
  .tbl.feed .amt.neg { color: var(--text); text-shadow: none; }
  /* The category's colour (the same as its slice in "Where it went"): a ring round the avatar and a dot by its name */
  .tbl.feed tr[style*="--cat"] .av { outline: 2px solid var(--cat); outline-offset: 2px; }
  .tbl.feed tr[style*="--cat"] :is(.cat-s, .catcol > span)::before { content: ""; display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: var(--cat); margin-right: 6px; vertical-align: 1px; }
  .tbl.feed tr[style*="--cat"] :is(.cat-s, .catcol > span) { color: color-mix(in oklab, var(--cat) 38%, var(--muted)); }
  .bud-s, .tag-s { font-size: 12.5px; color: var(--muted); opacity: .85; margin-right: 8px; white-space: nowrap; }
  /* Swipe a row left for Categorize and Delete (features/phone.ts): the cells slide by --sx and the buttons fill the gap */
  .tbl.feed tr[data-gid] { position: relative; }
  .tbl.feed tr[data-sw] > td:not(.swacts) { transform: translateX(var(--sx, 0px)); transition: transform .34s cubic-bezier(.25, 1, .4, 1); }
  .tbl.feed tr[data-sw].swiping > td { transition: none; }
  .tbl.feed tr[data-gid] td.swacts { position: absolute; top: 0; right: 0; bottom: 0; width: calc(-1 * var(--sx, 0px)); padding: 0; border: 0; display: flex; align-items: stretch; overflow: hidden; transition: width .34s cubic-bezier(.25, 1, .4, 1); }
  .swacts button { flex: 1 1 0; min-width: 0; border: 0; border-radius: 0; padding: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
    font: inherit; font-size: 11.5px; font-weight: 600; color: #fff; overflow: hidden; white-space: nowrap; cursor: pointer; }
  .swacts .sw-cat { background: #4a7bd8; }
  .swacts .sw-del { background: var(--spend); }
  .swacts svg { width: 20px; height: 20px; flex: none; }

  /* ---------- Transactions page: the month at a glance, search and filters in one row, each day a card ---------- */
  .txsum { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 14px 36px; padding: 18px 22px; margin-bottom: 16px; }
  .txsum .ts-k { display: flex; gap: 30px; }
  .txsum .ts-k > div { display: flex; flex-direction: column; gap: 3px; }
  .txsum .ts-k strong { font-size: 21px; font-weight: 600; letter-spacing: -.01em; }
  .txsum .ts-k strong.pos { text-shadow: none; }
  .dbars { flex: 1 1 280px; display: flex; align-items: flex-end; gap: 2px; height: 48px; min-width: 0; }
  .dbars .db { flex: 1 1 0; min-width: 0; height: 100%; padding: 0; border: 0; background: none; display: flex; align-items: flex-end; cursor: pointer; }
  .dbars .db i { display: block; width: 100%; height: max(3px, calc(var(--v) * 100%)); border-radius: 3px; background: color-mix(in srgb, var(--spend) 50%, var(--faint)); transform-origin: bottom; transition: background .15s; }
  .dbars .db:hover i, .dbars .db:active i { background: var(--spend); }
  .dbars .db.now i { background: var(--accent); }
  .dbars .db.fut { cursor: default; }
  .dbars .db.fut i { background: var(--faint); }
  #view.anim:not(.calm) .dbars .db i { animation: growUp .55s cubic-bezier(.2, .8, .2, 1) both; }
  .txbar { display: flex; gap: 10px; align-items: center; margin-bottom: 16px; }
  .txbar .search { flex: 0 1 340px; max-width: none; }
  .txbar .search input { border-radius: 999px; }
  .txbar .tabs { margin: 0; flex: none; }
  .txbar .selall { margin-left: auto; }
  .daycards tbody.day { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); overflow: clip; margin-bottom: 12px;
    scroll-margin-top: calc(env(safe-area-inset-top, 0px) + 14px); -webkit-backdrop-filter: none !important; backdrop-filter: none !important; }
  .daycards .tbl.feed tr.dayhead { position: static; }
  .daycards .tbl.feed tr.dayhead td { border-bottom: 0; }
  #view .daycards .tbl.feed tr.dayhead div { background: none; -webkit-backdrop-filter: none; backdrop-filter: none; box-shadow: none; padding: 13px 16px 2px; font-size: 13px; letter-spacing: 0; color: var(--text); }
  .daycards > .center-empty { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); }
  .daycards tbody.day.flash { animation: dayFlash 1.4s ease; }
  @keyframes dayFlash { 0%, 35% { box-shadow: 0 0 0 2px var(--accent); } 100% { box-shadow: 0 0 0 2px transparent; } }
  @media (max-width: 900px) {
    .head .new-tx { display: none; }       /* the + in the corner does this */
    .txsum { padding: 14px 16px; gap: 12px; }
    .txsum .ts-k { width: 100%; justify-content: space-between; gap: 12px; }
    .txsum .ts-k strong { font-size: 19px; }
    .dbars { flex-basis: 100%; height: 40px; }
    .txbar { gap: 8px; }
    /* Search folds to a round button next to the filters, and takes the row while it's in use */
    .txbar .search { flex: 0 0 40px; min-width: 0; transition: flex-basis .25s ease; }
    /* padding 0 while folded: the 38px icon padding made the input 52px wide, spilling out of its 40px circle under the filters */
    .txbar .search input { height: 40px; padding: 0; }
    .txbar.searching .search input, .txbar .search:focus-within input, .txbar .search input:not(:placeholder-shown) { padding: 0 12px 0 38px; }
    .txbar .search input::placeholder { color: transparent; }
    .txbar .search:focus-within input::placeholder { color: var(--muted); }
    .txbar.searching .search, .txbar .search:focus-within, .txbar .search:has(input:not(:placeholder-shown)) { flex: 1 1 auto; }
    .txbar.searching .tabs, .txbar:has(.search:focus-within) .tabs, .txbar:has(.search input:not(:placeholder-shown)) .tabs { display: none; }
    /* the filters fill the rest of the row, so it ends on the cards' right edge */
    .txbar .tabs { flex: 1 1 auto; min-width: 0; overflow-x: auto; }
    .txbar .tabs a { flex: 1 0 auto; padding: 7px 11px; text-align: center; }
    .txbar .selall { display: none; }
    @media (max-width: 380px) { .txbar .tabs a { padding: 7px 8px; } }
    #view .daycards .tbl.feed tr.dayhead div { padding: 12px 14px 2px; }
  }

  .txsum:empty { min-height: 95px; }
  @media (max-width: 900px) { .txsum:empty { min-height: 136px; } }

  /* ---------- Hours of work (core/worklens.ts): under money out in the feed ---------- */
  .tbl.feed tr[data-gid] td.amt:has(.hrs) { flex-direction: column; align-items: flex-end; justify-content: center; gap: 1px; }
  .tbl .amt .hrs { font-size: 11.5px; font-weight: 500; color: var(--muted); letter-spacing: .01em; }
  .set-num { width: 110px; text-align: right; }

  /* ---------- Net worth time scrubber (features/networth.ts) ---------- */
  .nw-scrub { position: relative; margin-top: auto; touch-action: pan-y; cursor: ew-resize; -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
  .panel.stat.nw .nw-scrub .mini-line { margin-top: 0; }
  .nw-scrub .nw-guide { position: absolute; top: 12px; bottom: 0; left: var(--x, 0); width: 0; border-left: 1px dashed var(--muted); opacity: 0; pointer-events: none; transition: opacity .15s; }
  .nw-scrub .nw-knob { position: absolute; left: var(--x, 0); top: var(--ky, 0); width: 12px; height: 12px; margin: -6px 0 0 -6px; border-radius: 50%;
    box-shadow: 0 0 0 2.5px var(--panel); opacity: 0; pointer-events: none; transition: opacity .15s; }
  .nw.scrubbing .nw-guide, .nw.scrubbing .nw-knob { opacity: 1; }
  .nw.scrubbing > .big { color: var(--accent); }
  .nw-open { margin-left: 4px; font: inherit; font-weight: 600; }

  /* ---------- Year in Money (pages/year.ts): a full-screen story ---------- */
  html:has(#story) { overflow: hidden; }
  html:has(#story) .tabbar, html:has(#story) .fab { visibility: hidden; }
  .story { --st-pad: max(28px, calc(50% - 240px)); position: fixed; inset: 0; z-index: 60; background: var(--bg); color: var(--text); overflow: hidden; touch-action: none;
    -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
  /* The bars, the × and every card's text share one column (--st-pad), so their edges line up */
  .st-prog { position: absolute; z-index: 3; top: calc(10px + env(safe-area-inset-top) + var(--edge)); left: var(--st-pad); right: var(--st-pad); display: flex; gap: 4px; }
  .st-prog i { flex: 1; height: 3px; border-radius: 2px; background: color-mix(in srgb, var(--text) 16%, transparent); overflow: hidden; }
  .st-prog b { display: block; height: 100%; width: 0; background: var(--text); }
  .st-prog i.done b { width: 100%; }
  .st-prog i.run b { animation: stFill 6.5s linear forwards; }
  .story.paused .st-prog i.run b { animation-play-state: paused; }
  @keyframes stFill { to { width: 100%; } }
  /* An icon, not the × character: a font's × sits on its baseline, so it lands low and differs by system font */
  .st-x { position: absolute; z-index: 4; top: calc(22px + env(safe-area-inset-top) + var(--edge)); right: var(--st-pad); width: 40px; height: 40px; min-width: 0; min-height: 0; padding: 0; margin: 0;
    display: grid; place-items: center; border: 0; border-radius: 50%; background: color-mix(in srgb, var(--text) 9%, transparent); color: var(--text); line-height: 0; cursor: pointer; }
  .st-x svg { display: block; width: 16px; height: 16px; }
  .st-deck { position: absolute; inset: 0; }
  .st-card { position: absolute; inset: 0; display: flex; flex-direction: column; justify-content: center; gap: 6px;
    padding: calc(80px + env(safe-area-inset-top) + var(--edge)) var(--st-pad) calc(60px + env(safe-area-inset-bottom));
    background: radial-gradient(90% 45% at 50% 0%, color-mix(in srgb, var(--accent) 9%, transparent), transparent 70%);
    opacity: 0; visibility: hidden; transform: scale(1.04); transition: opacity .35s ease, transform .5s cubic-bezier(.2, .8, .2, 1), visibility 0s .35s; }
  .st-card.on { opacity: 1; visibility: visible; transform: none; transition: opacity .35s ease, transform .5s cubic-bezier(.2, .8, .2, 1); }
  .st-card.past { transform: scale(.96); }
  .st-in { opacity: 0; transform: translateY(18px); }
  .st-card.on .st-in { animation: stIn .6s cubic-bezier(.2, .8, .2, 1) both; animation-delay: calc(var(--d) * .32s + .1s); }
  @keyframes stIn { to { opacity: 1; transform: none; } }
  .st-kick { font-size: 13px; font-weight: 600; letter-spacing: .14em; text-transform: uppercase; color: var(--muted); margin-bottom: 8px; }
  .st-big { font-size: clamp(84px, 26vw, 150px); line-height: .95; margin: 0; font-weight: 800; letter-spacing: -.04em; }
  .st-h { font-size: clamp(30px, 8vw, 44px); line-height: 1.1; margin: 2px 0; font-weight: 750; letter-spacing: -.02em; overflow-wrap: anywhere; }
  .st-num { font-size: clamp(46px, 14vw, 76px); line-height: 1.05; font-weight: 700; color: var(--accent); letter-spacing: -.03em; margin: 2px 0 6px; }
  .st-num small { font-size: .42em; font-weight: 650; letter-spacing: 0; opacity: .85; }
  .st-p { font-size: 18px; line-height: 1.4; margin: 4px 0; color: var(--muted); }
  .st-p strong { color: var(--text); }
  .st-p strong { font-weight: 750; }
  .st-hint { margin-top: 28px; font-size: 14px; opacity: .65; animation: stPulse 1.8s ease-in-out infinite; }
  @keyframes stPulse { 50% { opacity: .3; } }
  .st-years { display: flex; gap: 10px; margin-top: 18px; }
  .st-yr { color: var(--text); text-decoration: none; font-weight: 600; font-size: 14px; padding: 7px 14px; border-radius: 999px; background: var(--faint, var(--line)); }
  .st-day { height: 14px; border-radius: 7px; background: var(--faint, var(--line)); margin: 16px 0 10px; overflow: hidden; }
  .st-day i { display: block; height: 100%; width: 0; border-radius: 7px; background: var(--accent); }
  .st-card.on .st-day i { animation: stGrow 1.1s cubic-bezier(.2, .8, .2, 1) .9s forwards; }
  @keyframes stGrow { to { width: var(--p); } }
  .st-bars { display: grid; gap: 8px; margin-top: 18px; }
  .st-bar { position: relative; display: flex; justify-content: space-between; gap: 10px; padding: 9px 12px; border-radius: 10px; font-size: 15px; overflow: hidden; background: var(--faint, var(--line)); }
  .st-bar::before { content: ""; position: absolute; inset: 0 auto 0 0; width: 0; background: color-mix(in srgb, var(--accent) 22%, transparent); border-radius: inherit; }
  .st-card.on .st-bar::before { animation: stGrowW .9s cubic-bezier(.2, .8, .2, 1) both; animation-delay: calc(.8s + var(--j) * .08s); }
  @keyframes stGrowW { to { width: var(--w); } }
  .st-bar > * { position: relative; }
  .st-bar span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .st-list { display: grid; gap: 4px; margin-top: 16px; }
  .st-row { display: flex; align-items: center; gap: 10px; font-size: 15px; padding: 6px 0; border-top: 1px solid var(--line); }
  .st-row span:not(.av) { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .st-months { display: grid; grid-template-columns: repeat(12, 1fr); gap: 5px; align-items: end; height: 170px; margin: 18px 0 8px; }
  .st-months > div { display: flex; flex-direction: column; justify-content: flex-end; align-items: center; gap: 6px; height: 100%; }
  .st-months i { display: block; width: 100%; height: 0; border-radius: 5px; background: color-mix(in srgb, var(--text) 22%, transparent); }
  .st-months .hi i { background: var(--accent); }
  .st-months .fut i { background: var(--line); }
  .st-card.on .st-months i { animation: stGrowH .8s cubic-bezier(.2, .8, .2, 1) both; animation-delay: calc(.7s + var(--j) * .05s); }
  @keyframes stGrowH { from { height: 0; } to { height: max(3px, var(--v)); } }
  .st-months span { font-size: 11px; opacity: .7; }
  .st-btns { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 26px; }
  .st-btns .btn { min-width: 0; }
  
  @media (prefers-reduced-motion: reduce) {
    .st-card, .st-card.on { transition: opacity .2s; transform: none; }
    .st-card.on .st-in, .st-card.on .st-day i, .st-card.on .st-bar::before, .st-card.on .st-months i { animation-duration: .01s; animation-delay: 0s; }
  }
  /* ---------- Bento Overview (dashboard.ts): tiles small, medium or large; phones two small ones to a row ---------- */
  .cards .w { container-type: inline-size; }
  .cards.bento { display: grid; grid-template-columns: repeat(var(--units, 2), minmax(0, 1fr)); gap: var(--gap); align-items: stretch; grid-auto-flow: row; margin-bottom: var(--gap); }
  .cards.bento.editing { grid-auto-flow: row; }
  .cards.bento > .w, .cards.bento .dash-rest > .w { display: flex; flex-direction: column; margin: 0; min-width: 0; }
  .cards.bento > .w > .panel, .cards.bento .dash-rest > .w > .panel { flex: 1; }
  .cards.bento > .w.m, .cards.bento .dash-rest > .w.m { grid-column: span 2; }
  .cards.bento > .w.l, .cards.bento .dash-rest > .w.l { grid-column: 1 / -1; }
  .cards.bento .dash-rest:not([hidden]) { display: contents; }
  .cards.bento .dash-more { grid-column: 1 / -1; }
  .cards.bento .wctl { flex-wrap: nowrap; }
  .cards.bento .wctl strong { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .cards.bento .wctl button { flex: none; }
  @media (max-width: 900px) {
    .dash-wrap { --gap: 12px; }
    .cards.bento .panel { padding: 18px 16px; }
    .cards.bento .panel h2 { font-size: 14.5px; }
  }
  /* number tiles */
  .panel.stat { display: flex; flex-direction: column; }
  .panel.stat .eyebrow { margin-bottom: 6px; }
  .panel.stat .panel-head { margin-bottom: 4px; } .panel.stat .panel-head .eyebrow { margin: 0; }
  .stat-v { font-size: 30px; font-weight: 400; letter-spacing: -.025em; line-height: 1.1; }
  .panel.stat .big { font-size: clamp(34px, 11cqi, 52px); }
  .panel.stat .sub-s { margin-top: 4px; }
  .panel.stat .sbars { width: 100%; height: auto; max-height: 56px; margin-top: auto; padding-top: 14px; }
  .panel.stat .ring { width: 64px; margin: auto 0 0 auto; padding-top: 10px; }
  .panel.stat .ring .mid strong { font-size: 14px; } .panel.stat .ring .mid span { font-size: 10px; }
  .panel.stat.nw .mini-line { display: block; width: 100%; height: 64px; margin-top: auto; padding-top: 12px; overflow: visible; }
  .panel.stat.nw .sk { margin-top: auto; }
  @container (min-width: 240px) { .panel.stat .ring { width: 84px; } .panel.stat .ring .mid strong { font-size: 16px; } }
  /* the insights, one at a time and swiped through on a phone, stacked in a wide tile */
  .cards .w[data-w="insights"] .insights { margin: 0; padding: 0; grid-auto-columns: 100%; gap: 10px; }
  .cards .w[data-w="insights"] .insight { height: 100%; }
  @container (max-width: 520px) { .cards .w[data-w="insights"] .insights { grid-auto-columns: 88%; } .cards .w[data-w="insights"] .insights:has(> :only-child) { grid-auto-columns: 100%; } }
  @container (min-width: 521px) { .cards .w[data-w="insights"] .insights { grid-auto-flow: row; overflow: visible; } }
  @container (min-width: 760px) { .cards .w[data-w="insights"] .insights { grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: var(--gap, 20px); } }
  /* ring charts beside their list, once the tile has room for both */
  @container (min-width: 300px) {
    .cards .share { display: grid; grid-template-columns: minmax(104px, 38%) minmax(0, 1fr); gap: 18px; align-items: center; }
    .cards .share .donut { width: 100%; margin: 0; }
    .cards .share .part { grid-template-columns: 10px minmax(0, 1fr) 34px; gap: 8px; }
    .cards .share .part .track { display: none; }
  }
  @container (max-width: 380px) { .cards .share .donut .mid strong { font-size: 17px; } .cards .share .donut .mid .eyebrow { font-size: 9.5px; } }
  /* budgets as rings */
  .brings { display: grid; grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); gap: 16px 10px; margin-top: 6px; }
  .bring { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 2px; min-width: 0; color: inherit; text-decoration: none; }
  .bring .ring { width: 64px; margin-bottom: 6px; }
  .bring .ring .mid strong { font-size: 13.5px; }
  .bring .name { font-size: 13px; font-weight: 500; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .bring .sub-s { font-size: 11.5px; }
  .ring.warn .seg { stroke: var(--warn); } .ring.over .seg { stroke: var(--spend); }
  .list .row.more { color: var(--muted); font-size: 13.5px; text-decoration: none; }
  /* Customize as an icon on a phone, so the month picker and it share one row */
  .dash-edit { display: inline-flex; align-items: center; gap: 6px; }
  .dash-edit svg { width: 16px; height: 16px; flex: none; display: none; }
  @media (max-width: 900px) {
    .dash-edit { width: 38px; height: 38px; padding: 0 !important; justify-content: center; border-radius: 50%; }
    .dash-edit svg { display: block; } .dash-edit span { display: none; }
  }

  /* ---------- Collapsible sidebar (prefs.ts toggleSide): folds down to its icons ---------- */
  .brand { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
  .side-tg { display: grid; place-items: center; width: 30px; height: 30px; margin: -6px -6px -6px 0; padding: 0; border: 0; border-radius: 9px; background: none; color: var(--muted); cursor: pointer; }
  .side-tg:hover { background: var(--faint); color: var(--text); }
  .side-tg svg { width: 18px; height: 18px; transition: transform .25s ease; }
  @media (min-width: 901px) {
    .app { transition: grid-template-columns .25s ease; }
    html.side-mini .app { grid-template-columns: 70px 1fr; }
    html.side-mini .side { padding-left: 6px; padding-right: 6px; overflow-x: hidden; align-items: center; }
    html.side-mini .side > * { align-self: stretch; }
    html.side-mini .brand { justify-content: center; padding: 0 0 18px; }
    html.side-mini .brand > span { display: none; }
    html.side-mini .side-tg { margin: 0; }
    html.side-mini .side-tg svg { transform: scaleX(-1); }
    html.side-mini .side-search { justify-content: center; flex: none; width: 40px; height: 38px; margin-inline: auto; padding: 0; }
    html.side-mini .side-search :is(span, kbd) { display: none; }
    html.side-mini .nav a, html.side-mini .side .foot .nav a { justify-content: center; width: 40px; height: 38px; margin-inline: auto; padding: 0; }
    html.side-mini .nav a span { display: none; }
    html.side-mini .nav-h { height: 1px; padding: 0; margin: 10px 12px; background: var(--line); font-size: 0; }
    html.side-mini .side .foot :is(.toggles button, a, button) { text-align: center; }
    html.side-mini .side .foot .toggles button { display: flex; justify-content: center; }
    html.side-mini .side .foot .toggles button span, html.side-mini #ffLink, html.side-mini .side .foot > button { display: none; }
  }
  @media (max-width: 520px) {
    .head .actions:has(.dash-edit) { gap: 8px; flex-wrap: nowrap; }
    .head .actions:has(.dash-edit) .month span { min-width: 0; padding: 0 4px; }
    .head .actions:has(.dash-edit) .month .btn { padding-inline: 12px; }
    .month .today-gap { display: none; }
  }
  /* a narrow tile: bills put the amount under the name rather than cutting the name short; budget rings two to a row */
  @container (max-width: 240px) {
    .w[data-w="bills"] .list .row:not(.more) { display: grid; grid-template-columns: minmax(0, 1fr); gap: 2px; }
    .w[data-w="bills"] .list .row .name { white-space: normal; }
    .w[data-w="bills"] .list .row .num { text-align: left; font-weight: 600; }
    .brings { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px 6px; }
    .bring .ring { width: 54px; } .bring .ring .mid strong { font-size: 12px; }
  }
  @container (max-width: 240px) { .w[data-w="bills"] .lead { display: none; } }
  .cards.bento .w[data-w="budgets"] > .panel { display: flex; flex-direction: column; }
  .cards.bento .w[data-w="budgets"] .brings { margin-block: auto; padding-top: 10px; }
  /* a half-width tile's controls, small enough to share the row with its name */
  #dash.bento .w.s .wctl { gap: 4px; }
  #dash.bento .w.s .wctl button { padding: 3px 7px; font-size: 12px; }
  #dash.bento .w.s .wctl .grip { padding-right: 0; }
  @container (max-width: 200px) { #dash.bento .wctl strong { display: none; } }     /* (the tile shows its own title just below) */
  /* Add cards: a sketch of each card (tilepreview.ts), popping up on hover, or a thumbnail on a touch screen */
  .add-card { position: relative; }
  .add-card > span:nth-child(2) { flex: 1; min-width: 0; }
  .add-card .pv { flex: none; display: block; color: var(--text); }
  .add-card .tpv { display: block; width: 100%; height: auto; }
  @media (hover: hover) {
    .add-card .pv { position: absolute; z-index: 20; left: 50%; bottom: calc(100% + 10px); width: 240px; padding: 10px; border: 1px solid var(--line); border-radius: 16px;
      background: linear-gradient(var(--panel), var(--panel)), var(--bg); box-shadow: var(--shadow); opacity: 0; visibility: hidden; transform: translate(-50%, 6px); pointer-events: none; transition: opacity .15s ease, transform .15s ease, visibility 0s .15s; }
    .add-card:is(:hover, :focus-visible) .pv { opacity: 1; visibility: visible; transform: translate(-50%, 0); transition: opacity .15s ease .12s, transform .15s ease .12s, visibility 0s .12s; }
  }
  @media (hover: none) { .add-card .pv { width: 72px; padding: 4px; border-radius: 8px; background: color-mix(in srgb, var(--panel) 70%, transparent); border: 1px solid var(--line); } }
  /* Earned: in and out on one scale */
  .panel.stat .io { display: grid; gap: 8px; margin-top: auto; padding-top: 14px; }
  .io-r { display: grid; grid-template-columns: 2.4em minmax(0, 1fr) auto; align-items: center; gap: 8px; font-size: 12px; }
  .io-l { color: var(--muted); }
  .io-t { height: 8px; border-radius: 99px; background: color-mix(in srgb, var(--muted) 16%, transparent); overflow: hidden; }
  .io-t i { display: block; height: 100%; border-radius: inherit; transition: width .5s cubic-bezier(.2, .8, .2, 1); }
  .io-t i.in { background: var(--good); } .io-t i.out { background: color-mix(in srgb, var(--spend) 70%, transparent); } .io-t i.over { background: var(--spend); }
  .io-v { min-width: 4.5em; text-align: right; color: var(--muted); }
  @container (max-width: 190px) { .io-v { display: none; } .io-r { grid-template-columns: 2.4em minmax(0, 1fr); } }
  /* a card with nothing for this month keeps its spot */
  .panel.quiet .lead { margin-bottom: 0; }
  .attention .all-clear { display: flex; align-items: center; gap: 8px; margin: 14px 0 0; color: var(--muted); font-size: 13.5px; }
  .attention .all-clear span { display: grid; place-items: center; width: 22px; height: 22px; border-radius: 50%; background: color-mix(in srgb, var(--good) 18%, transparent); color: var(--good); font-size: 12px; }
  .attention .att-more { display: contents; }
  .attention .att-more[hidden] { display: none; }
  @media (min-width: 700px) { .attention :is(.list, .all-clear) { min-height: var(--att-h, 88px); } }
  .attention .all-clear { align-items: flex-start; }
  .dash-ghost > .wctl { visibility: hidden; }
  /* Bento: what's inside a card grows with the card (cqi = 1% of the card's width), within sensible bounds */
  .cards.bento .panel.stat .stat-v { font-size: clamp(28px, 13cqi, 48px); }
  .cards.bento .panel.stat .sbars { flex: 1 1 auto; height: clamp(56px, 26cqi, 130px); max-height: none; }
  .cards.bento .panel.stat.nw .mini-line { height: clamp(64px, 20cqi, 150px); }
  .cards.bento .panel.stat .io { gap: clamp(10px, 4cqi, 18px); }
  .cards.bento .io-r { grid-template-columns: minmax(0, 1fr) auto; row-gap: 5px; font-size: clamp(12px, 4.4cqi, 14.5px); }
  .cards.bento .io-r .io-t { grid-column: 1 / -1; grid-row: 2; }
  .cards.bento .io-r .io-v { display: block; min-width: 0; }
  .cards.bento .io-t { height: clamp(9px, 4cqi, 14px); }
  .cards.bento .w[data-w="safe"] .total { font-size: clamp(28px, 7.5cqi, 46px); }
  .cards.bento .brings { grid-template-columns: repeat(auto-fill, minmax(clamp(84px, 34cqi, 170px), 1fr)); }
  .cards.bento .bring .ring { width: clamp(54px, 28cqi, 120px); }
  .cards.bento .bring .ring .mid strong { font-size: clamp(13.5px, 4.4cqi, 20px); }
  .cards.bento .share .donut .mid strong { font-size: clamp(17px, 4.6cqi, 26px); }
  /* a very wide category card: the ring and its list stay together rather than the percentages drifting to the far edge */
  @container (min-width: 760px) { .cards .share { grid-template-columns: minmax(104px, 280px) minmax(0, 460px); justify-content: center; gap: 40px; } }
  /* Bento: what's inside also fills the card's height, since a row is as tall as its tallest card */
  .cards.bento > .w > .panel:is(.stat, .sankey, .attention), .cards.bento .w:is([data-w="spending"], [data-w="cash"], [data-w="cards"], [data-w="loans"], [data-w="bills"]) > .panel { display: flex; flex-direction: column; }
  .cards.bento .panel.stat.nw .mini-line { flex: 1 1 0; height: auto; min-height: clamp(64px, 20cqi, 150px); }
  .cards.bento .panel.stat .sbars { flex: 1 1 0; height: auto; min-height: clamp(56px, 26cqi, 130px); }
  .cards.bento .sankey .sk-box { flex: 1; position: relative; min-height: var(--sk-h, 220px); }
  .cards.bento .sankey .sk-box > svg { position: absolute; inset: 0; width: 100%; height: 100%; }
  .cards.bento .w[data-w="spending"] .share { flex: 1; align-items: center; }
  .cards.bento .w[data-w="spending"] .share .parts { align-self: stretch; display: flex; flex-direction: column; justify-content: space-evenly; }
  /* a list spreads down the card rather than leaving its bottom empty */
  .cards.bento .w:is([data-w="cash"], [data-w="cards"], [data-w="bills"]) .list, .cards.bento .w[data-w="loans"] .loan-rows { flex: 1; display: flex; flex-direction: column; justify-content: space-evenly; }
  /* the ring grows into a tall card too */
  .cards.bento .w[data-w="spending"] .share { grid-template-columns: minmax(104px, min(46%, 340px)) minmax(0, 1fr); }
  /* the month's days stretch to the card's height */
  .cards.bento .w[data-w="heatmap"] > .panel { display: flex; flex-direction: column; }
  .cards.bento .w[data-w="heatmap"] .hm { flex: 1; grid-template-rows: auto 1fr; }
  .cards.bento .w[data-w="heatmap"] .hm-grid { grid-auto-rows: 1fr; }
  .cards.bento .w[data-w="heatmap"] .hm-cell { aspect-ratio: auto; min-height: clamp(22px, 9cqi, 34px); }
  /* a narrow balances card: name and amount get the room, the 30-day line steps aside */
  @container (max-width: 320px) { .w:is([data-w="cash"], [data-w="cards"]) .list .row > svg { display: none; } }

  /* ---------- Timeline: months down a line, newest on top ----------
     Phones: the line runs down the left with each month to its right. Wide screens: the line runs down the middle,
     months alternate sides, and each one's date sits across the line from it. Each row draws its own piece of the
     line (--sx is where it crosses the row), so the line can stop at the last dot. */
  .tl { list-style: none; margin: 0 auto; padding: 0; max-width: 1080px; --dot: 14px; }
  .tl > li { position: relative; --sx: 12px; }
  .tl > li::before { content: ""; position: absolute; top: 0; bottom: 0; left: var(--sx); width: 2px; margin-left: -1px; background: var(--line); }
  .tl > li:first-child::before { top: 50%; }
  .tl-item, .tl-more { padding: 0 0 16px 36px; }
  .tl-dot { position: absolute; left: var(--sx); top: var(--dy, 31px); width: var(--dot); height: var(--dot); margin: calc(var(--dot) / -2) 0 0 calc(var(--dot) / -2); border-radius: 50%; z-index: 1;
    background: var(--panel); border: 2.5px solid var(--muted); box-sizing: border-box; }
  .tl-dot.pos { background: var(--good); border-color: var(--good); box-shadow: 0 0 0 4px color-mix(in srgb, var(--good) 20%, transparent); }
  .tl-dot.neg { background: var(--spend); border-color: var(--spend); box-shadow: 0 0 0 4px color-mix(in srgb, var(--spend) 20%, transparent); }
  .tl-date { display: none; }
  .tl .tl-card.panel { padding: 20px 22px; margin: 0; }
  .tl-card h2 { margin: 0; font-size: 15px; line-height: 20px; }
  .tl-head { display: flex; align-items: center; gap: 8px; min-width: 0; }
  .tl-tag { font-size: 11px; font-weight: 600; line-height: 18px; padding: 0 8px; border-radius: 999px; background: var(--faint); color: var(--muted); white-space: nowrap; }
  .tl-nw { display: flex; align-items: baseline; flex-wrap: wrap; gap: 2px 10px; margin: 12px 0 16px; }
  .tl-nw .eyebrow { width: 100%; margin: 0; }
  .tl-nw strong { font-size: 26px; font-weight: 650; letter-spacing: -.01em; line-height: 1.15; }
  .tl-nw > span:last-child { font-size: 13px; font-weight: 500; }
  .tl-flow { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
  .tl-flow > div { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
  .tl-flow .eyebrow { margin: 0; }
  .tl-flow .num { font-size: 15px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .tl-flow .sub-s { font-size: 12px; white-space: nowrap; }
  @container (max-width: 380px) { .tl-of { display: none; } }
  .tl .tl-card.panel { container-type: inline-size; }
  .tl-flow i { display: block; height: 4px; border-radius: 2px; width: var(--w); min-width: 3px; margin-top: 3px; }
  .tl-top { margin: 14px 0 0; font-size: 13px; color: var(--muted); }
  .tl-top strong { color: var(--text); font-weight: 600; }
  .tl-moments { list-style: none; padding: 0; margin: 12px 0 0; display: flex; flex-wrap: wrap; gap: 6px; }
  .tl-moments li { font-size: 12.5px; font-weight: 500; line-height: 18px; padding: 3px 10px; border-radius: 999px; background: var(--faint); }
  .tl-moments li.pos { color: var(--good); background: color-mix(in srgb, var(--good) 14%, transparent); }
  .tl-moments li.neg { color: var(--spend); background: color-mix(in srgb, var(--spend) 14%, transparent); }
  .tl-links { display: flex; gap: 18px; margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line); }
  .tl-go { display: inline-flex; align-items: center; gap: 1px; background: none; border: 0; padding: 0; color: var(--muted); font: inherit; font-size: 13px; font-weight: 500; line-height: 20px; cursor: pointer; }
  .tl-go svg { width: 14px; height: 14px; }
  @media (hover: hover) { .tl-go:hover { color: var(--text); } }
  .tl-item.quiet { --dy: 25px; }
  .tl-item.quiet .tl-card.panel { padding-top: 14px; padding-bottom: 14px; }
  .tl-item.quiet .tl-card p { margin: 2px 0 0; }
  .tl-year { padding: 6px 0 18px; }
  .tl-year span { position: relative; z-index: 1; display: inline-block; font-size: 13px; font-weight: 700; line-height: 26px; padding: 0 12px; border-radius: 999px; background: var(--accent); color: var(--on-accent); font-variant-numeric: tabular-nums; }
  .tl-end { padding: 0 0 8px 36px; --dy: 11px; }
  .tl-end::before { bottom: auto !important; height: 11px; }
  .tl-end p { margin: 0; color: var(--muted); font-size: 13px; line-height: 22px; }
  .tl-end p strong { color: var(--text); }
  .tl-new { animation: riseIn .45s cubic-bezier(.2, .8, .2, 1) both; }
  @media (min-width: 1000px) {
    .tl { --gap: 40px; }
    .tl > li { --sx: 50%; }
    .tl-item, .tl-more { width: 50%; box-sizing: border-box; }
    .tl-item.l { padding: 0 var(--gap) 22px 0; --sx: 100%; }
    .tl-item.r, .tl-more { margin-left: 50%; padding: 0 0 22px var(--gap); --sx: 0%; }
    .tl-date { display: block; position: absolute; top: var(--dy, 31px); transform: translateY(-50%); color: var(--muted); font-size: 12px; line-height: 16px; font-variant-numeric: tabular-nums; }
    .tl-date strong { display: block; color: var(--text); font-size: 17px; line-height: 22px; font-weight: 650; }
    .tl-item.l .tl-date { left: calc(100% + var(--gap)); }
    .tl-item.r .tl-date { right: calc(100% + var(--gap)); text-align: right; }
    .tl-year, .tl-end { text-align: center; }
    .tl-end { padding: 26px 0 8px; --dy: 7px; }
    .tl-end::before { height: 7px; }
  }
  /* the Overview's Net worth heading opens the timeline */
  .nw-tl { display: inline-flex; align-items: center; gap: 1px; color: var(--muted); text-decoration: none; }
  .nw-tl svg { width: 13px; height: 13px; }
  @media (hover: hover) { .nw-tl:hover { color: var(--text); } }
  /* ---------- Hover: things lean toward the mouse (mouse and trackpad only, never with Reduce motion) ---------- */
  /* Nothing with text in it moves by CSS transition or by a part of a pixel: Chrome on Windows draws text that's
     animating (or sitting between pixels) blurred until it settles. So dock.ts and magnet.ts move text in whole device
     pixels themselves, and only icons (SVG, which stays sharp) scale with transitions. */
  /* The sidebar swells like the macOS Dock: dock.ts sets --dock (0 to 1) on each link by how near the pointer is, and
     --dock-x, the label's nudge in whole pixels. The rows and the hover pill stay where they are. */
  @media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
    .side .nav a svg { scale: calc(1 + var(--dock, 0) * .3); transition: scale .2s cubic-bezier(.2, .8, .2, 1); }
    .side .nav a span { translate: var(--dock-x, 0px) 0; }
    html.side-mini .side .nav a svg { scale: calc(1 + var(--dock, 0) * .42); }
    .side-search svg, .side-tg svg { transition: scale .2s cubic-bezier(.2, .8, .2, 1), transform .25s ease; }
    .side-search:hover svg, .side-tg:hover svg { scale: 1.14; }
    /* Magnetic hover (magnet.ts): what's under the mouse leans toward it, eased frame by frame in whole pixels. It adds
       .mag with --mx/--my; the translate only exists while it does, since any translate makes a stacking context.
       Buttons and Overview tiles also rise (1px, 2px), counted into the same lean. */
    .mag { translate: var(--mx, 0px) var(--my, 0px); }
  }
  /* Collapsed sidebar: the name of the icon under the mouse (dock.ts), in the chart tooltip's style, pointing at it */
  .side-tip { z-index: 60; padding: 6px 11px; font-size: 13px; font-weight: 500; line-height: 1.35; white-space: nowrap; opacity: 0; visibility: hidden; }
  .side-tip::before { content: ""; position: absolute; left: -4px; top: 50%; width: 8px; height: 8px; margin-top: -4px; background: inherit; border-radius: 2px; transform: rotate(45deg); }
  .side-tip.on { opacity: 1; visibility: visible; }
  @media (prefers-reduced-motion: no-preference) { .side-tip.on { transition: opacity .12s ease .06s; } }
