/* Debt-Free & Budget Tracker — stylesheet v2
   Modern, paginated layout with 30 selectable theme presets, each
   available in a light and a dark variant (17 flat-color presets +
   9 gradient-sweep presets + 4 subtle-pattern presets).
   Keep this file in the same folder as the tracker .html file. */

/* ============================================================
   THEME TOKENS
   Every preset defines two blocks — [data-mode="light"] and
   [data-mode="dark"] — that redefine the same set of custom
   properties below. Preset (color/pattern identity) and mode
   (light/dark) are independent axes: switching one never changes
   the other. Everything else in this file reads from these
   variables, so neither axis ever needs a second stylesheet.

   --bg-image/--bg-size are an optional extra layer on top of the
   --bg/--bg-soft tokens — only the gradient/pattern presets (Sunrise,
   Lagoon, Orchard, Contour) set them; every other preset leaves them
   at the :root default (none/auto) and renders as a flat --bg color,
   same as before.
   ============================================================ */

/* ============================================================
   PRIVACY MODE
   Toggled from the "🙈 Hide data" button in the topbar (see
   #privacy-toggle-btn in app.js). Blurs every figure and label in the
   tracker's content areas — amounts, descriptions, chip values — so the
   screen is safe to have visible in public, without logging anyone out
   or losing their place. The topbar controls themselves stay sharp so
   the same button can turn it back off.

   #page-settings and #page-whatsnew are excluded from the blanket
   `.app-page` blur below: neither shows financial figures worth hiding
   (theme swatches, profile fields, the changelog), and since privacy
   defaults to hidden on every fresh page load, blurring them meant
   Settings looked broken by default every single time someone opened
   it — nothing to actually protect there, just an unreadable page
   until "Show data" was clicked.

   .profile-banner (the time-of-day greeting — "You've logged ₦X in
   expenses so far today", etc. — see timeOfDayMessage() in app.js) and
   .notif-dropdown (the 🔔 bell's notification history — debt-cleared,
   budget-threshold and money-badge entries all embed a real amount in
   plain sentence text) both sit in the topbar, outside every container
   above, so a real figure in a sentence used to stay fully readable even
   with privacy mode on. Blurred here the same blanket-container way as
   everything else, rather than trying to mask just the digits within
   the text.
   ============================================================ */
body[data-privacy="on"] .app-shell > .month-bar,
body[data-privacy="on"] .app-shell > .page-nav,
body[data-privacy="on"] .meta-chips,
body[data-privacy="on"] .overall,
body[data-privacy="on"] .profile-banner,
body[data-privacy="on"] .notif-dropdown,
body[data-privacy="on"] .app-page:not(#page-settings):not(#page-whatsnew){
  filter: blur(9px);
  user-select: none;
  transition: filter .15s ease;
}

:root{
  --bg:#F6F1E6; --bg-soft:#EFE7D4; --surface:#FFFFFF; --surface-2:#FBF6EA;
  --ink:#3B2F22; --muted:#8B7A5E; --line:#E6D9BC;
  --accent:#D98E2B; --accent-ink:#5C3B0E;
  --good:#4E8F5A; --bad:#D2603F; --info:#4E7FB8;
  --bg-image:none; --bg-size:auto;
  --radius-sm:10px; --radius-md:16px; --radius-lg:22px;
  --shadow-sm:0 2px 8px rgba(60,42,10,0.06);
  --shadow-md:0 8px 24px rgba(60,42,10,0.10);
  --font-display:'Quicksand',sans-serif; --font-body:'Quicksand',sans-serif; --font-mono:'Quicksand',sans-serif;
}
/* Safety fallback for a page that never sets data-theme-preset/data-mode
   at all (shouldn't happen once the picker/toggle have run, but matches
   :root's own values so there's no flash of anything else either way). */
body:not([data-theme-preset]), body:not([data-mode]){
  --bg:#F6F1E6; --bg-soft:#EFE7D4; --surface:#FFFFFF; --surface-2:#FBF6EA;
  --ink:#3B2F22; --muted:#8B7A5E; --line:#E6D9BC;
  --accent:#D98E2B; --accent-ink:#5C3B0E;
  --good:#4E8F5A; --bad:#D2603F; --info:#4E7FB8;
}

/* ---- 1. Meadow (default) ---- */
body[data-theme-preset="meadow"][data-mode="light"]{
  --bg:#F6F1E6; --bg-soft:#EFE7D4; --surface:#FFFFFF; --surface-2:#FBF6EA;
  --ink:#3B2F22; --muted:#8B7A5E; --line:#E6D9BC;
  --accent:#D98E2B; --accent-ink:#5C3B0E;
  --good:#4E8F5A; --bad:#D2603F; --info:#4E7FB8;
  --bg-image:linear-gradient(rgba(246,241,230,0.84), rgba(246,241,230,0.84)), url('images/themes/meadow.jpg'); --bg-size:cover;
}
body[data-theme-preset="meadow"][data-mode="dark"]{
  --bg:#1C1811; --bg-soft:#252018; --surface:#2D2720; --surface-2:#362F26;
  --ink:#F1ECE4; --muted:#B8A894; --line:#4B3F30;
  --accent:#E8B673; --accent-ink:#E0CAAE;
  --good:#7ECE92; --bad:#DE8D7C; --info:#81A9DA;
  --bg-image:linear-gradient(rgba(28,24,17,0.84), rgba(28,24,17,0.84)), url('images/themes/meadow.jpg'); --bg-size:cover;
}
/* ---- 2. Harbor ---- */
body[data-theme-preset="harbor"][data-mode="light"]{
  --bg:#EFF5F6; --bg-soft:#E3EEF0; --surface:#FFFFFF; --surface-2:#F5FAFB;
  --ink:#173238; --muted:#5E7C82; --line:#CFE2E5;
  --accent:#1E8C99; --accent-ink:#0B3A40;
  --good:#3F9E6B; --bad:#D0603F; --info:#2D6FA8;
  --bg-image:linear-gradient(rgba(239,245,246,0.84), rgba(239,245,246,0.84)), url('images/themes/harbor.jpg'); --bg-size:cover;
}
body[data-theme-preset="harbor"][data-mode="dark"]{
  --bg:#111B1C; --bg-soft:#182425; --surface:#202B2D; --surface-2:#263436;
  --ink:#E4F0F1; --muted:#94B4B8; --line:#30484B;
  --accent:#73DCE8; --accent-ink:#AEDBE0;
  --good:#7ECE92; --bad:#DE8D7C; --info:#81A9DA;
  --bg-image:linear-gradient(rgba(17,27,28,0.84), rgba(17,27,28,0.84)), url('images/themes/harbor.jpg'); --bg-size:cover;
}
/* ---- 3. Midnight ---- */
body[data-theme-preset="midnight"][data-mode="light"]{
  --bg:#EFF0F6; --bg-soft:#DEE1ED; --surface:#FFFFFF; --surface-2:#F6F6F9;
  --ink:#1B2137; --muted:#5E698D; --line:#D1D6E5;
  --accent:#2F52C6; --accent-ink:#121D3F;
  --good:#3F8D53; --bad:#BE4E37; --info:#4375B1;
  --bg-image:linear-gradient(rgba(239,240,246,0.84), rgba(239,240,246,0.84)), url('images/themes/midnight.jpg'); --bg-size:cover;
}
body[data-theme-preset="midnight"][data-mode="dark"]{
  --bg:#10141F; --bg-soft:#151A28; --surface:#1A2032; --surface-2:#1E2537;
  --ink:#E7EAF5; --muted:#8F97B3; --line:#2C3450;
  --accent:#6E8CF0; --accent-ink:#AEB9E0;
  --good:#63C98A; --bad:#EA7B72; --info:#7FA6F2;
  --bg-image:linear-gradient(rgba(16,20,31,0.84), rgba(16,20,31,0.84)), url('images/themes/midnight.jpg'); --bg-size:cover;
}
/* ---- 4. Bloom ---- */
body[data-theme-preset="bloom"][data-mode="light"]{
  --bg:#FBF0F1; --bg-soft:#F6E4E6; --surface:#FFFFFF; --surface-2:#FDF3F4;
  --ink:#4A2027; --muted:#9C6E76; --line:#F0D2D6;
  --accent:#D9587B; --accent-ink:#59101F;
  --good:#4E9166; --bad:#C64A3F; --info:#5E7CB0;
  --bg-image:linear-gradient(rgba(251,240,241,0.84), rgba(251,240,241,0.84)), url('images/themes/bloom.jpg'); --bg-size:cover;
}
body[data-theme-preset="bloom"][data-mode="dark"]{
  --bg:#1C1114; --bg-soft:#25181C; --surface:#2D2023; --surface-2:#36262A;
  --ink:#F1E4E8; --muted:#B8949E; --line:#4B3037;
  --accent:#E87393; --accent-ink:#E0AEBB;
  --good:#7ECE92; --bad:#DE8D7C; --info:#81A9DA;
  --bg-image:linear-gradient(rgba(28,17,20,0.84), rgba(28,17,20,0.84)), url('images/themes/bloom.jpg'); --bg-size:cover;
}
/* ---- 5. Fern ---- */
body[data-theme-preset="fern"][data-mode="light"]{
  --bg:#EEF3EA; --bg-soft:#E3EBDC; --surface:#FFFFFF; --surface-2:#F5F8F1;
  --ink:#1F2E1A; --muted:#6C7C5E; --line:#D3E0C6;
  --accent:#4B7F3C; --accent-ink:#17280F;
  --good:#3F8F52; --bad:#C15C3E; --info:#3F7A8C;
  --bg-image:linear-gradient(rgba(238,243,234,0.84), rgba(238,243,234,0.84)), url('images/themes/fern.jpg'); --bg-size:cover;
}
body[data-theme-preset="fern"][data-mode="dark"]{
  --bg:#141C11; --bg-soft:#1B2518; --surface:#232D20; --surface-2:#2A3626;
  --ink:#E7F1E4; --muted:#9CB894; --line:#364B30;
  --accent:#8DE873; --accent-ink:#B9E0AE;
  --good:#7ECE92; --bad:#DE8D7C; --info:#81A9DA;
  --bg-image:linear-gradient(rgba(20,28,17,0.84), rgba(20,28,17,0.84)), url('images/themes/fern.jpg'); --bg-size:cover;
}
/* ---- 6. Plum ---- */
body[data-theme-preset="plum"][data-mode="light"]{
  --bg:#F2EFF6; --bg-soft:#E6DEED; --surface:#FFFFFF; --surface-2:#F7F6F9;
  --ink:#2A1B37; --muted:#775E8D; --line:#DCD1E5;
  --accent:#7F2FC6; --accent-ink:#2A123F;
  --good:#3F8D53; --bad:#BE4E37; --info:#4375B1;
  --bg-image:linear-gradient(rgba(242,239,246,0.84), rgba(242,239,246,0.84)), url('images/themes/plum.jpg'); --bg-size:cover;
}
body[data-theme-preset="plum"][data-mode="dark"]{
  --bg:#1B1420; --bg-soft:#221A29; --surface:#271E30; --surface-2:#2C2237;
  --ink:#EFE4F5; --muted:#AC97BD; --line:#3E304C;
  --accent:#B984E8; --accent-ink:#C8AEE0;
  --good:#7BCB93; --bad:#EA8478; --info:#8AA6EE;
  --bg-image:linear-gradient(rgba(27,20,32,0.84), rgba(27,20,32,0.84)), url('images/themes/plum.jpg'); --bg-size:cover;
}
/* ---- 7. Terracotta ---- */
body[data-theme-preset="terracotta"][data-mode="light"]{
  --bg:#F7EEE6; --bg-soft:#F0E0D2; --surface:#FFFFFF; --surface-2:#FBF3EC;
  --ink:#3E2417; --muted:#93715A; --line:#E9D2BC;
  --accent:#C1592F; --accent-ink:#4E1D0A;
  --good:#4C8F5E; --bad:#B7412A; --info:#4E6E9A;
  --bg-image:linear-gradient(rgba(247,238,230,0.84), rgba(247,238,230,0.84)), url('images/themes/terracotta.jpg'); --bg-size:cover;
}
body[data-theme-preset="terracotta"][data-mode="dark"]{
  --bg:#1C1511; --bg-soft:#251C18; --surface:#2D2320; --surface-2:#362B26;
  --ink:#F1E8E4; --muted:#B89E94; --line:#4B3730;
  --accent:#E89473; --accent-ink:#E0BCAE;
  --good:#7ECE92; --bad:#DE8D7C; --info:#81A9DA;
  --bg-image:linear-gradient(rgba(28,21,17,0.84), rgba(28,21,17,0.84)), url('images/themes/terracotta.jpg'); --bg-size:cover;
}
/* ---- 8. Sunrise (warm gradient sweep) ---- */
body[data-theme-preset="sunrise"][data-mode="light"]{
  --bg:#F6F2EF; --bg-soft:#EDE5DE; --surface:#FFFFFF; --surface-2:#F9F7F6;
  --ink:#37281B; --muted:#8D745E; --line:#E5DBD1;
  --accent:#C6752F; --accent-ink:#3F2712;
  --good:#3F8D53; --bad:#BE4E37; --info:#4375B1;
  --bg-image:linear-gradient(rgba(246,242,239,0.84), rgba(246,242,239,0.84)), url('images/themes/sunrise.jpg'); --bg-size:cover;
}
body[data-theme-preset="sunrise"][data-mode="dark"]{
  --bg:#1C1711; --bg-soft:#251E18; --surface:#2D2620; --surface-2:#362D26;
  --ink:#F1EAE4; --muted:#B8A594; --line:#4B3C30;
  --accent:#E8A973; --accent-ink:#E0C5AE;
  --good:#7ECE92; --bad:#DE8D7C; --info:#81A9DA;
  --bg-image:linear-gradient(rgba(28,23,17,0.84), rgba(28,23,17,0.84)), url('images/themes/sunrise.jpg'); --bg-size:cover;
}
/* ---- 9. Lagoon (cool gradient sweep) ---- */
body[data-theme-preset="lagoon"][data-mode="light"]{
  --bg:#EFF4F6; --bg-soft:#DEE9ED; --surface:#FFFFFF; --surface-2:#F6F8F9;
  --ink:#1B3037; --muted:#5E818D; --line:#D1E0E5;
  --accent:#2FA0C6; --accent-ink:#12343F;
  --good:#3F8D53; --bad:#BE4E37; --info:#4375B1;
  --bg-image:linear-gradient(rgba(239,244,246,0.84), rgba(239,244,246,0.84)), url('images/themes/lagoon.jpg'); --bg-size:cover;
}
body[data-theme-preset="lagoon"][data-mode="dark"]{
  --bg:#111A1C; --bg-soft:#182225; --surface:#202A2D; --surface-2:#263236;
  --ink:#E4EEF1; --muted:#94AFB8; --line:#30444B;
  --accent:#73CBE8; --accent-ink:#AED4E0;
  --good:#7ECE92; --bad:#DE8D7C; --info:#81A9DA;
  --bg-image:linear-gradient(rgba(17,26,28,0.84), rgba(17,26,28,0.84)), url('images/themes/lagoon.jpg'); --bg-size:cover;
}
/* ---- 10. Orchard (dot-grid texture) ---- */
body[data-theme-preset="orchard"][data-mode="light"]{
  --bg:#F2F6EF; --bg-soft:#E5EDDE; --surface:#FFFFFF; --surface-2:#F7F9F6;
  --ink:#28371B; --muted:#748D5E; --line:#DBE5D1;
  --accent:#75C62F; --accent-ink:#273F12;
  --good:#3F8D53; --bad:#BE4E37; --info:#4375B1;
  --bg-image:linear-gradient(rgba(242,246,239,0.84), rgba(242,246,239,0.84)), url('images/themes/orchard.jpg'); --bg-size:cover;
}
body[data-theme-preset="orchard"][data-mode="dark"]{
  --bg:#171C11; --bg-soft:#1E2518; --surface:#262D20; --surface-2:#2D3626;
  --ink:#EAF1E4; --muted:#A5B894; --line:#3C4B30;
  --accent:#A9E873; --accent-ink:#C5E0AE;
  --good:#7ECE92; --bad:#DE8D7C; --info:#81A9DA;
  --bg-image:linear-gradient(rgba(23,28,17,0.84), rgba(23,28,17,0.84)), url('images/themes/orchard.jpg'); --bg-size:cover;
}
/* ---- 11. Contour (topographic-line texture) ---- */
body[data-theme-preset="contour"][data-mode="light"]{
  --bg:#EFF1F6; --bg-soft:#DEE2ED; --surface:#FFFFFF; --surface-2:#F6F7F9;
  --ink:#1B2337; --muted:#5E6C8D; --line:#D1D7E5;
  --accent:#2F5CC6; --accent-ink:#12203F;
  --good:#3F8D53; --bad:#BE4E37; --info:#4375B1;
  --bg-image:linear-gradient(rgba(239,241,246,0.84), rgba(239,241,246,0.84)), url('images/themes/contour.jpg'); --bg-size:cover;
}
body[data-theme-preset="contour"][data-mode="dark"]{
  --bg:#11151C; --bg-soft:#181C25; --surface:#20242D; --surface-2:#262B36;
  --ink:#E4E8F1; --muted:#949FB8; --line:#30384B;
  --accent:#7396E8; --accent-ink:#AEBDE0;
  --good:#7ECE92; --bad:#DE8D7C; --info:#81A9DA;
  --bg-image:linear-gradient(rgba(17,21,28,0.84), rgba(17,21,28,0.84)), url('images/themes/contour.jpg'); --bg-size:cover;
}

/* ---- 12. Raspberry ---- */
body[data-theme-preset="raspberry"][data-mode="light"]{
  --bg:#FBF0F2; --bg-soft:#F5E1E5; --surface:#FFFFFF; --surface-2:#FDF4F5;
  --ink:#4A1420; --muted:#9C5E6E; --line:#F0D0D6;
  --accent:#C6294B; --accent-ink:#4A0A18;
  --good:#4E9166; --bad:#C64A3F; --info:#5E7CB0;
  --bg-image:linear-gradient(rgba(251,240,242,0.84), rgba(251,240,242,0.84)), url('images/themes/raspberry.jpg'); --bg-size:cover;
}
body[data-theme-preset="raspberry"][data-mode="dark"]{
  --bg:#1C0F13; --bg-soft:#25161B; --surface:#2D1D22; --surface-2:#36232A;
  --ink:#F1DCE2; --muted:#B88C96; --line:#4B2A32;
  --accent:#E85C81; --accent-ink:#E0A4B4;
  --good:#7ECE92; --bad:#DE8D7C; --info:#81A9DA;
  --bg-image:linear-gradient(rgba(28,15,19,0.84), rgba(28,15,19,0.84)), url('images/themes/raspberry.jpg'); --bg-size:cover;
}
/* ---- 13. Mint ---- */
body[data-theme-preset="mint"][data-mode="light"]{
  --bg:#EEF7F3; --bg-soft:#DFEEE7; --surface:#FFFFFF; --surface-2:#F5FAF8;
  --ink:#123328; --muted:#5E8C7A; --line:#CFE7DC;
  --accent:#1FA383; --accent-ink:#0A3D30;
  --good:#3F8D53; --bad:#BE4E37; --info:#4375B1;
  --bg-image:linear-gradient(rgba(238,247,243,0.84), rgba(238,247,243,0.84)), url('images/themes/mint.jpg'); --bg-size:cover;
}
body[data-theme-preset="mint"][data-mode="dark"]{
  --bg:#0F1B17; --bg-soft:#16241F; --surface:#1D2C26; --surface-2:#22342D;
  --ink:#DFF1EA; --muted:#8FB8A9; --line:#2E4A40;
  --accent:#5EDCBA; --accent-ink:#AEE0D2;
  --good:#7ECE92; --bad:#DE8D7C; --info:#81A9DA;
  --bg-image:linear-gradient(rgba(15,27,23,0.84), rgba(15,27,23,0.84)), url('images/themes/mint.jpg'); --bg-size:cover;
}
/* ---- 14. Lavender ---- */
body[data-theme-preset="lavender"][data-mode="light"]{
  --bg:#F4F1FA; --bg-soft:#E8E2F3; --surface:#FFFFFF; --surface-2:#F8F6FC;
  --ink:#2B2140; --muted:#7C6E96; --line:#DDD3EC;
  --accent:#8067D6; --accent-ink:#2E2050;
  --good:#3F8D53; --bad:#BE4E37; --info:#4375B1;
  --bg-image:linear-gradient(rgba(244,241,250,0.84), rgba(244,241,250,0.84)), url('images/themes/lavender.jpg'); --bg-size:cover;
}
body[data-theme-preset="lavender"][data-mode="dark"]{
  --bg:#161320; --bg-soft:#1D1929; --surface:#242032; --surface-2:#2A2539;
  --ink:#E9E4F5; --muted:#A79ABE; --line:#392F4C;
  --accent:#A594EE; --accent-ink:#C8BEE0;
  --good:#7ECE92; --bad:#DE8D7C; --info:#81A9DA;
  --bg-image:linear-gradient(rgba(22,19,32,0.84), rgba(22,19,32,0.84)), url('images/themes/lavender.jpg'); --bg-size:cover;
}
/* ---- 15. Navy ---- */
body[data-theme-preset="navy"][data-mode="light"]{
  --bg:#EEF2F7; --bg-soft:#DEE6F0; --surface:#FFFFFF; --surface-2:#F5F8FB;
  --ink:#101E33; --muted:#556A8D; --line:#CFDBEC;
  --accent:#1D4E89; --accent-ink:#0A1E38;
  --good:#3F8D53; --bad:#BE4E37; --info:#4375B1;
  --bg-image:linear-gradient(rgba(238,242,247,0.84), rgba(238,242,247,0.84)), url('images/themes/navy.jpg'); --bg-size:cover;
}
body[data-theme-preset="navy"][data-mode="dark"]{
  --bg:#0D131F; --bg-soft:#131A28; --surface:#182132; --surface-2:#1C2738;
  --ink:#DEE6F5; --muted:#8797B8; --line:#2A3650;
  --accent:#5C8CE0; --accent-ink:#AEC3E0;
  --good:#7ECE92; --bad:#DE8D7C; --info:#81A9DA;
  --bg-image:linear-gradient(rgba(13,19,31,0.84), rgba(13,19,31,0.84)), url('images/themes/navy.jpg'); --bg-size:cover;
}
/* ---- 16. Mustard ---- */
body[data-theme-preset="mustard"][data-mode="light"]{
  --bg:#F8F4E2; --bg-soft:#EFE6C2; --surface:#FFFFFF; --surface-2:#FBF8EA;
  --ink:#332B0A; --muted:#8C7E3E; --line:#E7DC9C;
  --accent:#B8860B; --accent-ink:#3F3202;
  --good:#4C8F3E; --bad:#D2552F; --info:#3F82AE;
  --bg-image:linear-gradient(rgba(248,244,226,0.84), rgba(248,244,226,0.84)), url('images/themes/mustard.jpg'); --bg-size:cover;
}
body[data-theme-preset="mustard"][data-mode="dark"]{
  --bg:#1B1710; --bg-soft:#221D14; --surface:#2A241A; --surface-2:#322B1F;
  --ink:#F0EAD8; --muted:#B8A97E; --line:#453B27;
  --accent:#E0B84D; --accent-ink:#E0D0A0;
  --good:#7ECE92; --bad:#DE8D7C; --info:#81A9DA;
  --bg-image:linear-gradient(rgba(27,23,16,0.84), rgba(27,23,16,0.84)), url('images/themes/mustard.jpg'); --bg-size:cover;
}
/* ---- 17. Charcoal ---- */
body[data-theme-preset="charcoal"][data-mode="light"]{
  --bg:#F1F1F2; --bg-soft:#E4E4E6; --surface:#FFFFFF; --surface-2:#F8F8F8;
  --ink:#202124; --muted:#6C6D72; --line:#D7D7DA;
  --accent:#52565E; --accent-ink:#1A1B1E;
  --good:#3E9457; --bad:#C74C3B; --info:#3E6BD1;
  --bg-image:linear-gradient(rgba(241,241,242,0.84), rgba(241,241,242,0.84)), url('images/themes/charcoal.jpg'); --bg-size:cover;
}
body[data-theme-preset="charcoal"][data-mode="dark"]{
  --bg:#131315; --bg-soft:#19191C; --surface:#202023; --surface-2:#26262A;
  --ink:#E7E7E9; --muted:#98999E; --line:#333338;
  --accent:#9598A3; --accent-ink:#C8C9CE;
  --good:#7ECE92; --bad:#DE8D7C; --info:#81A9DA;
  --bg-image:linear-gradient(rgba(19,19,21,0.84), rgba(19,19,21,0.84)), url('images/themes/charcoal.jpg'); --bg-size:cover;
}
/* ---- 18. Forest ---- */
body[data-theme-preset="forest"][data-mode="light"]{
  --bg:#EEF3EE; --bg-soft:#DDE9DD; --surface:#FFFFFF; --surface-2:#F5F9F5;
  --ink:#12271A; --muted:#57795E; --line:#CFE0CF;
  --accent:#2C5F3C; --accent-ink:#0D2214;
  --good:#3E9457; --bad:#C74C3B; --info:#3E6BD1;
  --bg-image:linear-gradient(rgba(238,243,238,0.84), rgba(238,243,238,0.84)), url('images/themes/forest.jpg'); --bg-size:cover;
}
body[data-theme-preset="forest"][data-mode="dark"]{
  --bg:#0D160F; --bg-soft:#131F15; --surface:#18261A; --surface-2:#1D2D1F;
  --ink:#DFEFE2; --muted:#87AB8F; --line:#2A4130;
  --accent:#5C9E6E; --accent-ink:#AED4B4;
  --good:#7ECE92; --bad:#DE8D7C; --info:#81A9DA;
  --bg-image:linear-gradient(rgba(13,22,15,0.84), rgba(13,22,15,0.84)), url('images/themes/forest.jpg'); --bg-size:cover;
}
/* ---- 19. Aurora (green-violet gradient sweep) ---- */
body[data-theme-preset="aurora"][data-mode="light"]{
  --bg:#F1F4F0; --bg-soft:#E2ECE4; --surface:#FFFFFF; --surface-2:#F7FAF7;
  --ink:#1B2E22; --muted:#5E8D71; --line:#D1E5D6;
  --accent:#3FBF8F; --accent-ink:#123F2A;
  --good:#3F8D53; --bad:#BE4E37; --info:#4375B1;
  --bg-image:linear-gradient(rgba(241,244,240,0.84), rgba(241,244,240,0.84)), url('images/themes/aurora.jpg'); --bg-size:cover;
}
body[data-theme-preset="aurora"][data-mode="dark"]{
  --bg:#101A15; --bg-soft:#16221B; --surface:#1C2921; --surface-2:#223027;
  --ink:#E4F1E8; --muted:#8FB8A0; --line:#304B38;
  --accent:#66E0B0; --accent-ink:#AEE0C8;
  --good:#7ECE92; --bad:#DE8D7C; --info:#81A9DA;
  --bg-image:linear-gradient(rgba(16,26,21,0.84), rgba(16,26,21,0.84)), url('images/themes/aurora.jpg'); --bg-size:cover;
}
/* ---- 20. Sunset (pink-orange gradient sweep) ---- */
body[data-theme-preset="sunset"][data-mode="light"]{
  --bg:#FBF1EE; --bg-soft:#F6E2DA; --surface:#FFFFFF; --surface-2:#FDF6F3;
  --ink:#3E1E17; --muted:#9C6E5E; --line:#F0D6CC;
  --accent:#E85C6E; --accent-ink:#4E1A1F;
  --good:#3F8D53; --bad:#BE4E37; --info:#4375B1;
  --bg-image:linear-gradient(rgba(251,241,238,0.84), rgba(251,241,238,0.84)), url('images/themes/sunset.jpg'); --bg-size:cover;
}
body[data-theme-preset="sunset"][data-mode="dark"]{
  --bg:#1C1310; --bg-soft:#251A18; --surface:#2D211E; --surface-2:#362824;
  --ink:#F1E1DC; --muted:#B8968C; --line:#4B332C;
  --accent:#F08A96; --accent-ink:#E0B4B8;
  --good:#7ECE92; --bad:#DE8D7C; --info:#81A9DA;
  --bg-image:linear-gradient(rgba(28,19,16,0.84), rgba(28,19,16,0.84)), url('images/themes/sunset.jpg'); --bg-size:cover;
}
/* ---- 21. Honeycomb (crosshatch texture) ---- */
body[data-theme-preset="honeycomb"][data-mode="light"]{
  --bg:#F6F3EA; --bg-soft:#ECE4CD; --surface:#FFFFFF; --surface-2:#FAF7EF;
  --ink:#332B18; --muted:#8C7F5E; --line:#E5D9B6;
  --accent:#D9A02F; --accent-ink:#402F0A;
  --good:#3F8D53; --bad:#BE4E37; --info:#4375B1;
  --bg-image:linear-gradient(rgba(246,243,234,0.84), rgba(246,243,234,0.84)), url('images/themes/honeycomb.jpg'); --bg-size:cover;
}
body[data-theme-preset="honeycomb"][data-mode="dark"]{
  --bg:#1B1710; --bg-soft:#221D14; --surface:#2A241A; --surface-2:#322B1F;
  --ink:#F0EAD8; --muted:#B8A97E; --line:#453B27;
  --accent:#E8C373; --accent-ink:#E0D0AE;
  --good:#7ECE92; --bad:#DE8D7C; --info:#81A9DA;
  --bg-image:linear-gradient(rgba(27,23,16,0.84), rgba(27,23,16,0.84)), url('images/themes/honeycomb.jpg'); --bg-size:cover;
}

/* ---- 22. Biker (brushed-metal texture) ---- */
body[data-theme-preset="biker"][data-mode="light"]{
  --bg:#ECEBE9; --bg-soft:#DFDCD8; --surface:#FFFFFF; --surface-2:#F5F4F2;
  --ink:#1C1C1C; --muted:#6E6A64; --line:#D3CFC9;
  --accent:#C8102E; --accent-ink:#4A0510;
  --good:#3F8D53; --bad:#BE4E37; --info:#4375B1;
  --bg-image:linear-gradient(rgba(236,235,233,0.84), rgba(236,235,233,0.84)), url('images/themes/biker.jpg'); --bg-size:cover;
}
body[data-theme-preset="biker"][data-mode="dark"]{
  --bg:#0C0C0D; --bg-soft:#151516; --surface:#1C1C1E; --surface-2:#232325;
  --ink:#F0EDEA; --muted:#A39D96; --line:#303032;
  --accent:#FF3B3B; --accent-ink:#FFC2C2;
  --good:#7ECE92; --bad:#DE8D7C; --info:#81A9DA;
  --bg-image:linear-gradient(rgba(12,12,13,0.84), rgba(12,12,13,0.84)), url('images/themes/biker.jpg'); --bg-size:cover;
}
/* ---- 23. Fire (warm gradient sweep) ---- */
body[data-theme-preset="fire"][data-mode="light"]{
  --bg:#FFF2E6; --bg-soft:#FFE1C7; --surface:#FFFFFF; --surface-2:#FFF8F0;
  --ink:#4A1A05; --muted:#A06A3E; --line:#F5CFA8;
  --accent:#FF5A1F; --accent-ink:#5C1A00;
  --good:#3F8D53; --bad:#BE4E37; --info:#4375B1;
  --bg-image:linear-gradient(rgba(255,242,230,0.84), rgba(255,242,230,0.84)), url('images/themes/fire.jpg'); --bg-size:cover;
}
body[data-theme-preset="fire"][data-mode="dark"]{
  --bg:#190803; --bg-soft:#230D05; --surface:#2B1208; --surface-2:#34160A;
  --ink:#FFE9DA; --muted:#D9906B; --line:#4A2412;
  --accent:#FF7A3D; --accent-ink:#FFC9A8;
  --good:#7ECE92; --bad:#DE8D7C; --info:#81A9DA;
  --bg-image:linear-gradient(rgba(25,8,3,0.84), rgba(25,8,3,0.84)), url('images/themes/fire.jpg'); --bg-size:cover;
}
/* ---- 24. Barbie ---- */
body[data-theme-preset="barbie"][data-mode="light"]{
  --bg:#FFF0F7; --bg-soft:#FFDCEC; --surface:#FFFFFF; --surface-2:#FFF6FA;
  --ink:#4A0030; --muted:#B4588F; --line:#FAC7E0;
  --accent:#FF1493; --accent-ink:#5C0030;
  --good:#3F8D53; --bad:#BE4E37; --info:#4375B1;
  --bg-image:linear-gradient(rgba(255,240,247,0.84), rgba(255,240,247,0.84)), url('images/themes/barbie.jpg'); --bg-size:cover;
}
body[data-theme-preset="barbie"][data-mode="dark"]{
  --bg:#1F0414; --bg-soft:#2B0A1E; --surface:#330E26; --surface-2:#3B122D;
  --ink:#FFE1F2; --muted:#E08AC0; --line:#4D1A38;
  --accent:#FF5CAD; --accent-ink:#FFC2E2;
  --good:#7ECE92; --bad:#DE8D7C; --info:#81A9DA;
  --bg-image:linear-gradient(rgba(31,4,20,0.84), rgba(31,4,20,0.84)), url('images/themes/barbie.jpg'); --bg-size:cover;
}
/* ---- 25. Studio Ghibli (gradient sweep) ---- */
body[data-theme-preset="ghibli"][data-mode="light"]{
  --bg:#F2F7E9; --bg-soft:#E3EFD2; --surface:#FFFFFF; --surface-2:#F8FBF2;
  --ink:#1F3326; --muted:#6E8C6E; --line:#D3E5C2;
  --accent:#6FA8DC; --accent-ink:#163049;
  --good:#4B8F5E; --bad:#C1603E; --info:#4F8FBE;
  --bg-image:linear-gradient(rgba(242,247,233,0.84), rgba(242,247,233,0.84)), url('images/themes/ghibli.jpg'); --bg-size:cover;
}
body[data-theme-preset="ghibli"][data-mode="dark"]{
  --bg:#0F1A14; --bg-soft:#16241B; --surface:#1D2C22; --surface-2:#233327;
  --ink:#E2F0E4; --muted:#8FB89E; --line:#2E4A37;
  --accent:#8FC6EE; --accent-ink:#C2E0F0;
  --good:#7ECE92; --bad:#DE8D7C; --info:#81A9DA;
  --bg-image:linear-gradient(rgba(15,26,20,0.84), rgba(15,26,20,0.84)), url('images/themes/ghibli.jpg'); --bg-size:cover;
}
/* ---- 26. Cyberpunk (neon gradient sweep) ---- */
body[data-theme-preset="cyberpunk"][data-mode="light"]{
  --bg:#F3EAF8; --bg-soft:#E8D4F2; --surface:#FFFFFF; --surface-2:#F8F1FB;
  --ink:#2A0A3D; --muted:#8E5EA8; --line:#DFC2EC;
  --accent:#E619B3; --accent-ink:#4D0540;
  --good:#3F8D53; --bad:#BE4E37; --info:#1FA3C4;
  --bg-image:linear-gradient(rgba(243,234,248,0.84), rgba(243,234,248,0.84)), url('images/themes/cyberpunk.jpg'); --bg-size:cover;
}
body[data-theme-preset="cyberpunk"][data-mode="dark"]{
  --bg:#07040F; --bg-soft:#0F0A1C; --surface:#150F24; --surface-2:#1A122C;
  --ink:#E8F6FF; --muted:#8E9DC8; --line:#2A2048;
  --accent:#00F0FF; --accent-ink:#AEF6FF;
  --good:#6EE88A; --bad:#FF5C7A; --info:#00F0FF;
  --bg-image:linear-gradient(rgba(7,4,15,0.84), rgba(7,4,15,0.84)), url('images/themes/cyberpunk.jpg'); --bg-size:cover;
}
/* ---- 27. Galaxy (cosmic gradient sweep) ---- */
body[data-theme-preset="galaxy"][data-mode="light"]{
  --bg:#EFEEFA; --bg-soft:#DEDCF2; --surface:#FFFFFF; --surface-2:#F6F5FC;
  --ink:#211B45; --muted:#6E67A0; --line:#D1CCEC;
  --accent:#6E4FE8; --accent-ink:#241552;
  --good:#3F8D53; --bad:#BE4E37; --info:#4375B1;
  --bg-image:linear-gradient(rgba(239,238,250,0.84), rgba(239,238,250,0.84)), url('images/themes/galaxy.jpg'); --bg-size:cover;
}
body[data-theme-preset="galaxy"][data-mode="dark"]{
  --bg:#0A0618; --bg-soft:#120B26; --surface:#191031; --surface-2:#20153C;
  --ink:#E8E4FF; --muted:#9A8FD4; --line:#302258;
  --accent:#A685FF; --accent-ink:#D8C8FF;
  --good:#7ECE92; --bad:#DE8D7C; --info:#81A9DA;
  --bg-image:linear-gradient(rgba(10,6,24,0.84), rgba(10,6,24,0.84)), url('images/themes/galaxy.jpg'); --bg-size:cover;
}
/* ---- 28. Matcha ---- */
body[data-theme-preset="matcha"][data-mode="light"]{
  --bg:#F3F6EA; --bg-soft:#E6ECD2; --surface:#FFFFFF; --surface-2:#F8FAF2;
  --ink:#263318; --muted:#7A8C5E; --line:#D9E3C2;
  --accent:#6B8E4E; --accent-ink:#223314;
  --good:#4C8F3E; --bad:#C1603E; --info:#4F8FA0;
  --bg-image:linear-gradient(rgba(243,246,234,0.84), rgba(243,246,234,0.84)), url('images/themes/matcha.jpg'); --bg-size:cover;
}
body[data-theme-preset="matcha"][data-mode="dark"]{
  --bg:#121810; --bg-soft:#192015; --surface:#1F281A; --surface-2:#263120;
  --ink:#E6EEDA; --muted:#9FB386; --line:#324028;
  --accent:#9BC46E; --accent-ink:#D0E6B4;
  --good:#7ECE92; --bad:#DE8D7C; --info:#81A9DA;
  --bg-image:linear-gradient(rgba(18,24,16,0.84), rgba(18,24,16,0.84)), url('images/themes/matcha.jpg'); --bg-size:cover;
}
/* ---- 29. Vaporwave (gradient sweep) ---- */
body[data-theme-preset="vaporwave"][data-mode="light"]{
  --bg:#FDEFFA; --bg-soft:#F8DCF2; --surface:#FFFFFF; --surface-2:#FEF5FC;
  --ink:#3A1050; --muted:#9A6EB8; --line:#F0CCEA;
  --accent:#8A7FFB; --accent-ink:#2E2066;
  --good:#3F8D53; --bad:#BE4E37; --info:#4FA8D9;
  --bg-image:linear-gradient(rgba(253,239,250,0.84), rgba(253,239,250,0.84)), url('images/themes/vaporwave.jpg'); --bg-size:cover;
}
body[data-theme-preset="vaporwave"][data-mode="dark"]{
  --bg:#160A24; --bg-soft:#1F0E32; --surface:#27123E; --surface-2:#2E1648;
  --ink:#F6E4FF; --muted:#C495E0; --line:#3E2358;
  --accent:#FF9DE2; --accent-ink:#FFD4F2;
  --good:#7ECE92; --bad:#DE8D7C; --info:#7FD8FF;
  --bg-image:linear-gradient(rgba(22,10,36,0.84), rgba(22,10,36,0.84)), url('images/themes/vaporwave.jpg'); --bg-size:cover;
}
/* ---- 30. Cozy Cabin ---- */
body[data-theme-preset="cozycabin"][data-mode="light"]{
  --bg:#F7EFE2; --bg-soft:#EEDFC6; --surface:#FFFFFF; --surface-2:#FBF6EC;
  --ink:#3A2514; --muted:#8C7152; --line:#E5D3B2;
  --accent:#8B5A2B; --accent-ink:#3A2410;
  --good:#4C8F3E; --bad:#B7412A; --info:#4E6E9A;
  --bg-image:linear-gradient(rgba(247,239,226,0.84), rgba(247,239,226,0.84)), url('images/themes/cozycabin.jpg'); --bg-size:cover;
}
body[data-theme-preset="cozycabin"][data-mode="dark"]{
  --bg:#1A120A; --bg-soft:#231A10; --surface:#2B2015; --surface-2:#33261A;
  --ink:#F1E4D2; --muted:#BFA183; --line:#4A3824;
  --accent:#D9A066; --accent-ink:#E8C9A0;
  --good:#7ECE92; --bad:#DE8D7C; --info:#81A9DA;
  --bg-image:linear-gradient(rgba(26,18,10,0.84), rgba(26,18,10,0.84)), url('images/themes/cozycabin.jpg'); --bg-size:cover;
}


/* ============================================================
   BASE
   ============================================================ */
*{box-sizing:border-box;}
/* The native `hidden` attribute must always win over any author rule that
   sets `display` unconditionally (e.g. .auth-loading-box below) — without
   this, an element with `hidden` in its HTML but a plain `display:flex`
   class rule shows up anyway, because author styles beat the browser's own
   `[hidden]{display:none}` default regardless of selector specificity. This
   is what let the sign-in loading card render at the same time as the
   sign-in form on every page load. */
[hidden]{display:none !important;}
html{-webkit-text-size-adjust:100%; scroll-padding-top:env(safe-area-inset-top, 0px);}
/* Backstop against any single element quietly forcing the whole page
   wider than the viewport (see .xl-user-wrap below for the case that
   actually did this on narrow phones) — deliberately horizontal-
   scrolling strips like .tabs-outer/.page-nav scope overflow-x:auto on
   themselves, so this doesn't affect them. */
html,body{overflow-x:hidden;}
body{
  margin:0; background-color:var(--bg); color:var(--ink);
  /* Every preset now layers a dimmed Unsplash photo (a solid scrim in
     --bg's own color, at the same opacity every preset uses, painted on
     top of the photo so it reads as a wash of color with a hint of
     texture/imagery showing through — not a busy photo behind text) on
     top of the flat --bg color via these three tokens. */
  background-image:var(--bg-image); background-size:var(--bg-size); background-position:center; background-attachment:fixed;
  font-family:var(--font-body); line-height:1.55; -webkit-font-smoothing:antialiased;
  min-height:100vh; transition:background-color .25s ease, color .25s ease;
  /* When installed as an app, keep content clear of the notch/status bar
     and the home-indicator area. env() is 0px in an ordinary browser tab. */
  padding-top:env(safe-area-inset-top, 0px);
  padding-bottom:env(safe-area-inset-bottom, 0px);
}
h1,h2,h3{font-family:var(--font-display); margin:0; letter-spacing:0; color:var(--ink);}
.mono{font-family:var(--font-mono);}
a{color:var(--accent);}
/* Form controls don't inherit the page font by default — the browser gives
   them its own UI font instead — so every input/select/textarea added by
   app.js (item labels, amounts, descriptions, category names, budgets...)
   rendered in a different font than the rest of the page until this rule
   forced them to match. */
button,input,select,textarea{font-family:inherit;}
::selection{background:var(--accent); color:#fff;}
:focus-visible{outline:2px solid var(--accent); outline-offset:2px;}

.app-shell{max-width:1040px; margin:0 auto; padding:0 20px 60px; position:relative; z-index:1;}

/* ============================================================
   TOP BAR — brand, clock/countdown, excel + settings toolbar
   ============================================================ */
.topbar{padding:22px 0 14px;}
.brand-row{display:flex; align-items:center; justify-content:space-between; flex-wrap:wrap; gap:10px;}
.brand{display:flex; align-items:center; gap:10px; text-decoration:none; color:inherit;}
.brand-mark{line-height:1;}
.brand-mark img{width:28px; height:28px; display:block; border-radius:7px;}
.brand-text h1{font-size:clamp(19px,2.6vw,24px); font-weight:700;}
.brand-text .tag{font-size:12px; color:var(--muted); margin-top:1px;}

/* grid, not flex-wrap: flex-wrap packed however many chips fit per row
   by each chip's own content width, so rows ended up with uneven chip
   counts (a long label like "Days until debt-free" alone on its row,
   shorter ones 2-up) and no two chips ever matched width. auto-fit +
   minmax gives every chip in a row the same width and reflows the
   column count to the viewport on its own, no breakpoints needed. */
.meta-chips{display:grid; grid-template-columns:repeat(auto-fit,minmax(140px,1fr)); gap:10px; margin-top:14px;}
.chip{font-family:var(--font-mono); border:1px solid var(--line); background:var(--surface); border-radius:var(--radius-sm); padding:8px 14px; display:flex; flex-direction:column; gap:2px; box-shadow:var(--shadow-sm);}
.chip .lbl{font-size:9.5px; letter-spacing:.04em; color:var(--muted); font-family:var(--font-display); font-weight:600;}
.chip .val{font-size:16px; font-weight:700; color:var(--ink);}
.chip.countdown .val{color:var(--accent);}
.chip.level .val{color:var(--accent);}
.chip.streak .val{color:var(--bad);}
.chip.streak.streak-zero .val{color:var(--muted);} /* no streak yet today — don't flex a fire emoji at 0 */
.chip.outstanding .val{color:var(--bad);}
.chip.outstanding.clear .val{color:var(--good);} /* nothing left owing on any debt */
.chip.net .val{color:var(--good);}
.chip.net.bad .val{color:var(--bad);} /* this month is running a shortfall, not a surplus */
.chip.savings .val{color:var(--good);}
.chip.gifts .val{color:var(--accent);}
.chip.investments .val{color:var(--good);}
.chip.networth .val{color:var(--good);}
.chip .val span{font-size:10.5px; color:var(--muted); font-weight:400; margin-left:4px; font-family:var(--font-body);}

/* toolbar (excel + currency/payday + user + theme) */
.toolbar{margin-top:14px; padding:10px 12px; border:1px solid var(--line); border-radius:var(--radius-md); background:var(--surface); display:flex; flex-wrap:wrap; align-items:center; gap:8px; box-shadow:var(--shadow-sm);}
.settings-save-bar{display:flex; flex-wrap:wrap; align-items:center; gap:10px; margin-bottom:20px; padding-bottom:16px; border-bottom:1px solid var(--line);}
.toolbar .xl-title{font-family:var(--font-display); font-weight:700; font-size:12px; color:var(--muted); text-transform:uppercase; letter-spacing:.05em; margin-right:2px;}
.xl-btn{font-family:var(--font-display); font-weight:600; font-size:12.5px; padding:7px 12px; border-radius:10px; border:1px solid var(--line); background:transparent; color:var(--ink); cursor:pointer; display:inline-flex; align-items:center; gap:5px; transition:background .15s ease,border-color .15s ease;}
.xl-btn:hover{background:var(--bg-soft); border-color:var(--accent);}
.xl-btn:disabled{opacity:.4; cursor:default; pointer-events:none;}
.xl-btn.primary{background:var(--accent); border-color:var(--accent); color:#fff;}
.xl-btn.primary:hover{filter:brightness(.94);}
.xl-set{font-size:12px; color:var(--muted); display:inline-flex; align-items:center; gap:5px; font-weight:600;}
.xl-set select{font-family:inherit; font-size:12px; padding:5px 7px; border-radius:8px; border:1px solid var(--line); background:var(--bg-soft); color:var(--ink);}
/* Hide/Undo/Redo/Settings/notifications/email/Sign out all in one row —
   flex-wrap still lets it break onto more than one line on a narrow phone
   (the html,body overflow-x:hidden backstop above covers that case) without
   the whole cluster needing a second, separate row on wider screens. */
.xl-user-wrap{display:flex; flex-direction:column; align-items:flex-end; gap:6px; margin-left:auto;}
.xl-actions-row{display:flex; flex-wrap:wrap; align-items:center; justify-content:flex-end; gap:6px;}
.xl-user{font-size:12.5px; font-weight:700; color:var(--ink);}
.xl-status{width:100%; font-size:11.5px; color:var(--muted); margin-top:2px;}

/* notification bell + dropdown */
.notif-wrap{position:relative; display:inline-flex;}
.notif-badge{position:absolute; top:-4px; right:-4px; min-width:15px; height:15px; padding:0 3px; border-radius:8px; background:var(--bad); color:#fff; font-size:9.5px; font-weight:700; line-height:15px; text-align:center; font-family:var(--font-display);}
.notif-dropdown{position:absolute; top:calc(100% + 8px); right:0; width:320px; max-width:calc(100vw - 32px); max-height:420px; overflow-y:auto; background:var(--surface); border:1px solid var(--line); border-radius:var(--radius-md); box-shadow:var(--shadow-md,0 8px 24px rgba(0,0,0,.15)); z-index:50;}
.notif-dropdown-head{font-family:var(--font-display); font-weight:700; font-size:13px; padding:10px 14px; border-bottom:1px solid var(--line);}
.notif-list{display:flex; flex-direction:column;}
.notif-item{display:flex; gap:10px; padding:10px 14px; border-bottom:1px solid var(--line);}
.notif-item:last-child{border-bottom:none;}
.notif-item.unread{background:var(--bg-soft);}
.notif-icon{font-size:16px; line-height:1.4;}
.notif-body{flex:1; min-width:0;}
.notif-title{font-size:12.5px; font-weight:700; color:var(--ink);}
.notif-text{font-size:12px; color:var(--muted); margin-top:1px;}
.notif-time{font-size:10.5px; color:var(--muted); margin-top:3px;}
.notif-empty{padding:16px 14px; font-size:12.5px; color:var(--muted); text-align:center;}
.notif-actions{display:flex; flex-direction:column; gap:4px; flex-shrink:0;}
.notif-keep-btn,.notif-del-btn{background:none; border:none; cursor:pointer; font-size:13px; line-height:1; padding:2px; border-radius:6px; opacity:.55;}
.notif-keep-btn:hover,.notif-del-btn:hover{opacity:1; background:var(--bg-soft);}
.notif-keep-btn.active{opacity:1;}

/* personalized greeting + quote banner, moved into the top bar */
.profile-banner{display:flex; align-items:center; gap:12px; margin-top:14px; padding:10px 14px; border:1px solid var(--line); border-radius:var(--radius-md); background:var(--surface); box-shadow:var(--shadow-sm);}
.profile-avatar{font-size:28px; line-height:1; flex-shrink:0;}
.profile-avatar img{width:28px; height:28px; display:block; border-radius:50%; object-fit:cover;}
.avatar-upload-row{display:flex; align-items:center; gap:8px; flex-wrap:wrap;}
.avatar-upload-status{font-size:11.5px; color:var(--muted);}
.profile-banner-text{min-width:0;}
.profile-banner .time-message{font-size:13px; font-weight:600; color:var(--ink); margin-top:0;}
.profile-banner .quote-banner{border:none; background:none; padding:0; margin:2px 0 0; text-align:left; font-size:12px; color:var(--muted); font-weight:400;}

/* profile avatar picker (Settings — Profile) */
.avatar-picker{display:flex; flex-wrap:wrap; gap:8px;}
.avatar-picker-item{font-size:20px; line-height:1; width:40px; height:40px; display:flex; align-items:center; justify-content:center; border-radius:50%; border:2px solid var(--line); background:var(--bg-soft); cursor:pointer;}
.avatar-picker-item.selected{border-color:var(--accent); background:var(--surface);}

/* top-bar chip picker (Settings — which meta-chips show at the top) */
.chip-picker{display:flex; flex-wrap:wrap; gap:8px 18px;}
.chip-picker-item{display:inline-flex; align-items:center; gap:6px; font-size:13px; color:var(--ink); cursor:pointer;}
.notify-pref-list{display:flex; flex-wrap:wrap; gap:8px 18px; margin-top:14px; padding-top:14px; border-top:1px dashed var(--line);}

/* visible-tabs picker (Settings — which tabs show, and in what order) */
.tab-order-list{display:flex; flex-direction:column; gap:4px;}
.tab-order-row{display:flex; align-items:center; gap:10px; padding:4px 0;}
.tab-order-arrows{display:inline-flex; gap:2px; width:40px; flex:0 0 auto;}
.tab-order-btn{font-family:inherit; font-size:11px; line-height:1; padding:4px 6px; border:1px solid var(--line); border-radius:6px; background:var(--surface); color:var(--ink); cursor:pointer;}
.tab-order-btn:hover:not(:disabled){background:var(--bg-soft);}
.tab-order-btn:disabled{opacity:.3; cursor:default;}
.tab-order-fixed-note{display:inline-flex; align-items:center; justify-content:center; width:100%; font-size:12px; color:var(--muted);}

/* theme picker */
.theme-picker{display:inline-flex; align-items:center; gap:6px; margin-left:6px; position:relative;}
.theme-picker-label{font-size:11px; color:var(--muted); font-weight:600;}
/* Shows which of the 30 themes is hovered/focused (or, once the pointer
   leaves, whichever is actually applied) — the swatches themselves are
   just small color circles, so without this there was no way to tell
   what a swatch even *was* short of reading its title-attribute tooltip,
   which touch devices never show at all. */
.theme-picker-current{display:block; font-size:12px; font-weight:700; color:var(--ink); margin-top:3px;}
.theme-swatches{display:flex; gap:8px; flex-wrap:wrap;}
/* The Theme row alone (30 swatches and counting) needs the full width of
   its .toolbar row to wrap sensibly — left inline-flex like every other
   .theme-picker row here (Pet, weather, etc, which stay compact on
   purpose), it was squeezed into whatever leftover width the toolbar's
   own flex-wrap happened to give it, wrapping into a narrow, cut-off-
   looking column instead of spanning the available width. */
.theme-picker-full{display:flex; flex-basis:100%; width:100%; align-items:flex-start; margin-left:0;}
.theme-picker-full .theme-swatches{flex:1;}
/* Fixed width, not shrink-to-fit: #theme-picker-current's text changes
   length on every hover (theme names range from "Mint" to "Studio Ghibli
   (gradient)"), and a shrink-to-fit label next to a flex:1 row means that
   every such change reflows the swatches sideways — moving whichever one
   the pointer is actually sitting on out from under it, which fires a
   mouseleave, which reverts the label, which moves the swatch back under
   the pointer, which fires mouseenter again... a jittery feedback loop on
   every hover. A fixed box the text can never resize removes the feedback
   loop entirely; long names just wrap inside it instead. */
.theme-picker-full .theme-picker-label{flex:0 0 92px; width:92px;}
/* 44x44 is the standard minimum comfortable tap target (WCAG 2.5.5) — sized
   up from the original 22px circle so each swatch is reliably tappable on
   its own without catching a neighbor, rather than leaving the hit area
   tiny and relying on zoom/precision. */
.theme-swatch{width:44px; height:44px; border-radius:50%; border:2px solid var(--surface); box-shadow:0 0 0 1px var(--line); cursor:pointer; padding:0; position:relative;}
.theme-swatch.active{box-shadow:0 0 0 2px var(--accent);}
/* Gamification: themes unlocked via level/achievement (see THEMES'
   `requires` entries in app.js) — dimmed with a 🔒 overlay until earned;
   still clickable so the click handler's "locked theme" notice fires. */
.theme-swatch.locked{opacity:.4; filter:grayscale(.6);}
.theme-swatch.locked::after{content:'🔒'; position:absolute; inset:0; display:flex; align-items:center; justify-content:center; font-size:17px;}
/* Icon-only variant of .xl-btn — the light/dark mode toggle sits with the
   other top-right toolbar controls (see #theme-toggle-btn in sign-in.html)
   rather than floating fixed on the page like its old, dead incarnation did. */
.theme-toggle{padding:7px 10px; font-size:14px; line-height:1;}
/* Same icon-only sizing, for the gear that opens the Settings page (see
   #page-settings) — sits with Undo/Redo rather than as a page-nav tab,
   so it needs its own small button here instead of .page-nav-btn's
   larger, labeled tab styling. */
#settings-nav-btn{padding:7px 10px; font-size:14px; line-height:1;}
/* Same icon-only sizing as .theme-toggle — see #ambient-toggle-btn in
   sign-in.html / ambient-audio.js. .active marks the synthesized ambient
   pad as currently on, matching the accent-outline convention .theme-swatch
   .active and .pet-swatch.active already use elsewhere in this toolbar. */
.ambient-toggle{padding:7px 10px; font-size:14px; line-height:1;}
.ambient-toggle.active{border-color:var(--accent); background:var(--bg-soft);}
/* Same icon-only sizing/active convention as .ambient-toggle, for the
   daily-reminder toggle in the Settings page's Reminders section. */
.reminder-toggle{padding:7px 10px; font-size:14px; line-height:1;}
.reminder-toggle.active{border-color:var(--accent); background:var(--bg-soft);}
.reminder-toggle:disabled{opacity:.4; cursor:not-allowed;}
.pet-swatches{display:flex; gap:5px; flex-wrap:wrap;}
.weather-swatches{display:flex; gap:5px; flex-wrap:wrap;}
.pet-swatch{width:24px; height:24px; border-radius:50%; border:2px solid var(--surface); box-shadow:0 0 0 1px var(--line); cursor:pointer; padding:0; position:relative; background:var(--bg-soft); font-size:13px; line-height:1; display:flex; align-items:center; justify-content:center;}
.pet-swatch.active{box-shadow:0 0 0 2px var(--accent);}
.pet-swatch.locked{opacity:.4; filter:grayscale(.6);}
.pet-swatch.locked::after{content:'🔒'; position:absolute; inset:0; display:flex; align-items:center; justify-content:center; font-size:11px;}

/* ============================================================
   MONTH PICKER + PERIOD BAR (persists above page nav)
   A fixed-width prev/current/next control replaces what used to be one
   .tab button per tracked month in a horizontally-scrolling strip — that
   grew unbounded as more months got added. The dropdown (.month-picker-menu)
   reuses the same status-dot convention (grey/gold/green = empty/partial/
   complete) the old tabs used.
   ============================================================ */
.month-bar{margin:18px 0 0; display:flex; align-items:center; gap:16px; flex-wrap:wrap;}
.month-picker{display:flex; align-items:center; gap:8px;}
.month-meta{display:flex; flex-direction:column; gap:4px;}
.month-nav-btn{font-family:var(--font-display); font-weight:700; font-size:16px; line-height:1; padding:6px 12px; border-radius:10px; border:1px solid var(--line); background:var(--surface); color:var(--ink); cursor:pointer;}
.month-nav-btn:disabled{opacity:.35; cursor:not-allowed;}
.month-nav-btn:not(:disabled):hover{border-color:var(--accent);}
.month-picker-wrap{position:relative;}
.month-picker-toggle{font-family:var(--font-display); font-weight:600; font-size:13px; padding:8px 14px; border-radius:12px; border:1px solid var(--line); background:var(--surface); color:var(--ink); cursor:pointer; white-space:nowrap; display:flex; align-items:center; gap:7px; min-width:140px; justify-content:center;}
.month-picker-toggle:hover, .month-picker-toggle.open{border-color:var(--accent); background:var(--bg-soft);}
.month-picker-toggle .caret{font-size:10px; color:var(--muted);}
.month-picker-toggle .dot{width:6px; height:6px; border-radius:50%; background:var(--line); flex:0 0 auto;}
.month-picker-toggle .dot.complete{background:var(--good);}
.month-picker-toggle .dot.partial{background:var(--accent);}
.month-picker-toggle .dot.skipped{background:var(--muted); opacity:.5;}
.month-picker-menu{position:absolute; top:calc(100% + 6px); left:50%; transform:translateX(-50%); z-index:70; min-width:200px; max-height:280px; overflow-y:auto; background:var(--surface); border:1px solid var(--line); border-radius:var(--radius-md); box-shadow:var(--shadow-md); padding:6px;}
.month-picker-row{font-family:var(--font-display); font-weight:600; font-size:12.5px; padding:8px 10px; border-radius:9px; color:var(--muted); cursor:pointer; white-space:nowrap; display:flex; align-items:center; gap:7px;}
.month-picker-row:hover{background:var(--bg-soft);}
.month-picker-row.active{color:var(--ink); background:var(--bg-soft);}
.month-picker-row .dot{width:6px; height:6px; border-radius:50%; background:var(--line); flex:0 0 auto;}
.month-picker-row.complete .dot{background:var(--good);}
.month-picker-row.partial .dot{background:var(--accent);}
.month-picker-row.skipped{opacity:.55;}
.month-picker-row.skipped .dot{background:var(--muted);}
.month-picker-row-label{flex:1;}
.month-picker-skip-btn{flex:0 0 auto; border:none; background:transparent; cursor:pointer; font-size:12px; padding:2px 4px; border-radius:6px; opacity:.6;}
.month-picker-skip-btn:hover{opacity:1; background:var(--bg-soft);}
.month-picker-add{border-top:1px dashed var(--line); margin-top:4px; padding-top:10px; color:var(--accent);}
.month-picker-add .dot{display:none;}
.month-period{font-size:12.5px; color:var(--muted); font-family:var(--font-mono);}
.month-start-override{display:flex; align-items:center; gap:6px; font-size:12px; color:var(--muted);}
.month-start-override select{font-family:var(--font-body); font-size:12px; color:var(--ink); background:var(--surface); border:1px solid var(--line); border-radius:8px; padding:3px 6px;}
.time-message{font-size:13px; color:var(--muted); margin-top:2px;}
.month-bar .time-message{flex:1 1 100%; margin-top:0;}

/* ============================================================
   PAGE NAV — the 6 sections, in place of one long scroll
   ============================================================ */
/* Scrolls horizontally instead of wrapping — at desktop widths 9 tabs plus
   the right-pushed What's New (.page-nav-btn-right's margin-left:auto)
   used to run out of row space and wrap What's New onto its own line
   alone, looking cut off rather than just "more tabs than fit." Scrolling
   was already how this was handled under 700px; it works just as well
   above that width, so it's no longer gated behind that breakpoint. */
.page-nav{display:flex; flex-wrap:nowrap; overflow-x:auto; gap:6px; margin:16px 0 20px; border-bottom:1px solid var(--line); padding-bottom:2px; box-shadow:inset -18px 0 12px -12px rgba(0,0,0,.18);}
.page-nav-btn{flex:0 0 auto; font-family:var(--font-display); font-weight:700; font-size:13px; padding:9px 16px; border:none; background:transparent; color:var(--muted); cursor:pointer; border-radius:10px 10px 0 0; position:relative; top:1px; display:inline-flex; align-items:center; gap:6px;}
.page-nav-btn .ic{font-size:14px;}
.page-nav-btn:hover{color:var(--ink); background:var(--bg-soft);}
.page-nav-btn.active{color:var(--accent-ink); background:var(--surface); border:1px solid var(--line); border-bottom-color:var(--surface);}
.page-nav-btn-right{margin-left:auto;}
.whatsnew-tab-dot{display:inline-block; width:7px; height:7px; border-radius:50%; background:var(--bad);}
.app-page{display:none; animation:pageIn .18s ease;}
.app-page.active{display:block;}
@keyframes pageIn{from{opacity:0; transform:translateY(4px);} to{opacity:1; transform:none;}}

/* ============================================================
   CARDS / GENERAL SURFACES
   ============================================================ */
.card{border:1px solid var(--line); border-radius:var(--radius-lg); background:var(--surface); padding:18px 20px; box-shadow:var(--shadow-sm);}

.overall{border:1px solid var(--line); border-radius:var(--radius-lg); background:var(--surface); padding:18px 20px; margin:0 0 20px; box-shadow:var(--shadow-sm);}
.overall-head{display:flex; justify-content:space-between; align-items:baseline; margin-bottom:12px; flex-wrap:wrap; gap:8px;}
.overall-head h2{font-size:13.5px; text-transform:uppercase; letter-spacing:.04em; color:var(--muted); font-weight:600;}
.overall-nums{display:flex; gap:24px; flex-wrap:wrap;}
.overall-track{height:8px; background:var(--bg-soft); border-radius:6px; overflow:hidden; margin-top:12px;}
.overall-fill{height:100%; background:var(--good); border-radius:6px; transition:width .3s ease;}

.summary-grid{display:flex; flex-direction:column; gap:1px; margin-bottom:20px;}
.summary-row{display:grid; gap:1px; background:var(--line); border:1px solid var(--line); border-radius:var(--radius-md); overflow:hidden;}
.summary-row.row1{grid-template-columns:repeat(6,1fr);}
.summary-row.row2{grid-template-columns:repeat(3,1fr);}
.summary-card{background:var(--surface); padding:13px 15px;}
.summary-card .lbl{font-size:9.5px; text-transform:uppercase; letter-spacing:.05em; color:var(--muted);}
.summary-card .num{font-family:var(--font-mono); font-size:18px; font-weight:700; margin-top:4px;}
.summary-card .num.green{color:var(--good);} .summary-card .num.coral{color:var(--bad);} .summary-card .num.gold{color:var(--accent);}
.summary-card .subnote{font-size:9.5px; color:var(--muted); margin-top:3px;}

/* ===== Sign-in gate ===== */
body.ft-locked > *:not(#auth-overlay):not(script){display:none !important;}
body.ft-locked{overflow:hidden;}
#auth-overlay{display:none; position:fixed; inset:0; z-index:5000; align-items:center; justify-content:center; padding:20px; overflow-y:auto; background:var(--bg);}
body.ft-locked #auth-overlay{display:flex;}
.auth-card{width:100%; max-width:400px; background:var(--surface); border:1px solid var(--line); border-radius:var(--radius-lg); padding:28px 26px 22px; box-shadow:var(--shadow-md); color:var(--ink);}
.auth-logo{text-align:center; line-height:1;}
.auth-logo img{width:34px; height:34px; display:block; margin:0 auto; border-radius:8px;}
.auth-card h2{font-size:22px; text-align:center; margin:8px 0 2px; color:var(--ink);}
.auth-sub{text-align:center; color:var(--muted); font-size:13px; margin:0 0 16px;}
.auth-tabs{display:flex; gap:6px; background:var(--bg-soft); padding:4px; border-radius:12px; margin-bottom:14px;}
.auth-tabs button{flex:1; font-family:var(--font-display); font-weight:600; font-size:13px; padding:8px 10px; border:0; border-radius:9px; background:transparent; color:var(--muted); cursor:pointer;}
.auth-tabs button.active{background:var(--surface); color:var(--ink); box-shadow:var(--shadow-sm);}
.auth-card label.auth-field{display:block; font-size:11.5px; font-weight:700; color:var(--muted); text-transform:uppercase; letter-spacing:.05em; margin-bottom:12px;}
.auth-card input[type=text],.auth-card input[type=password]{display:block; width:100%; margin-top:5px; padding:10px 12px; font-size:15px; font-family:var(--font-body); border:1px solid var(--line); border-radius:10px; background:var(--bg-soft); color:var(--ink); outline:none; text-transform:none; letter-spacing:0; font-weight:500;}
.auth-card input[type=text]:focus,.auth-card input[type=password]:focus{border-color:var(--accent);}
.auth-row{display:flex; flex-direction:column; gap:6px; margin:2px 0 12px;}
.auth-check{display:flex; align-items:center; gap:8px; font-size:12px; color:var(--muted); cursor:pointer;}
.auth-error{min-height:18px; font-size:12.5px; color:var(--bad); font-weight:600; margin-bottom:8px;}
.auth-submit{width:100%; font-family:var(--font-display); font-weight:700; font-size:14.5px; padding:11px; border:0; border-radius:11px; background:var(--accent); color:#fff; cursor:pointer;}
.auth-submit:hover{filter:brightness(.95);}
.auth-link{display:block; margin:12px auto 0; background:none; border:none; color:var(--muted); font-size:12px; text-decoration:underline; cursor:pointer;}
.auth-note{font-size:11px; color:var(--muted); text-align:center; margin:16px 0 0; line-height:1.5;}
/* Biometric shortcut on the plain sign-in form (#auth-biometric-btn) —
   secondary-styled (outline, not the solid accent fill) so it reads as the
   quick option, not a replacement for the real submit button below it. */
.auth-biometric-btn{margin-bottom:14px; background:transparent; border:1.5px solid var(--accent); color:var(--accent-ink);}
.auth-biometric-btn:hover{background:color-mix(in srgb, var(--accent) 10%, transparent); filter:none;}
.auth-divider{display:flex; align-items:center; gap:10px; margin:0 0 14px; font-size:11px; color:var(--muted); text-transform:uppercase; letter-spacing:.03em;}
.auth-divider::before,.auth-divider::after{content:''; flex:1; height:1px; background:var(--line);}
.auth-loading-box{display:flex; flex-direction:column; align-items:center; gap:14px; padding:48px 26px;}
.auth-loading-spin{line-height:1; display:inline-block; animation:authSpin 1s linear infinite;}
.auth-loading-spin img{width:38px; height:38px; display:block; border-radius:9px;}
.auth-loading-box p{font-family:var(--font-display); font-weight:600; font-size:14px; color:var(--muted); margin:0; text-align:center;}
@keyframes authSpin{from{transform:rotate(0deg);} to{transform:rotate(360deg);}}
/* prefers-reduced-motion is already handled globally, see bottom of file */

/* ============================================================
   LANDING PAGE — marketing page (index.html). Lives on its own
   document now, separate from the sign-in/app page (sign-in.html).
   #landing-page is a direct child of <body>, so the sign-in gate
   rule above (body.ft-locked > * { display:none !important; })
   would hide the whole page if that class ever ends up on <body>
   here (e.g. a stale service-worker cache). The !important below
   is required — a plain `display:block` cannot win against that
   rule and silently renders as background-only, no text.
   ============================================================ */
#landing-page{display:block !important;}

.landing-inner{max-width:1040px; margin:0 auto; padding:0 20px 60px;}

.landing-nav{display:flex; align-items:center; justify-content:space-between; padding:20px 0;}
.landing-brand{display:flex; align-items:center; gap:8px; font-family:var(--font-display); font-weight:800; font-size:19px; color:var(--ink); text-decoration:none;}
.landing-mark{line-height:1;}
.landing-mark img{width:22px; height:22px; display:block; border-radius:6px;}
.landing-nav-links{display:flex; align-items:center; gap:18px;}
.landing-nav-link{font-family:var(--font-display); font-weight:600; font-size:13.5px; color:var(--muted); text-decoration:none;}
.landing-nav-link:hover{color:var(--ink);}
.landing-nav-signin{display:inline-block; text-decoration:none; font-family:var(--font-display); font-weight:700; font-size:13px; padding:9px 18px; border-radius:var(--radius-sm); border:1px solid var(--line); background:var(--surface); color:var(--ink); cursor:pointer; box-shadow:var(--shadow-sm);}
.landing-nav-signin:hover{background:var(--bg-soft);}

.landing-hero{display:flex; align-items:center; gap:40px; padding:36px 0 56px; flex-wrap:wrap;}
.landing-hero-copy{flex:1 1 380px; min-width:280px;}
.landing-eyebrow{display:inline-block; font-family:var(--font-display); font-weight:700; font-size:12.5px; color:var(--accent-ink); background:var(--surface-2); border:1px solid var(--line); padding:6px 14px; border-radius:999px; margin-bottom:16px;}
.landing-hero-copy h1{font-size:clamp(28px,4.4vw,42px); line-height:1.15; margin:0 0 16px; font-weight:800;}
.landing-sub{font-size:16px; color:var(--muted); max-width:480px; margin:0 0 26px;}
.landing-cta-row{display:flex; flex-wrap:wrap; gap:12px; margin-bottom:18px;}
.landing-cta-primary{display:inline-block; text-decoration:none; text-align:center; font-family:var(--font-display); font-weight:700; font-size:15px; padding:14px 26px; border-radius:var(--radius-sm); border:none; background:var(--accent); color:#fff; cursor:pointer; box-shadow:var(--shadow-md);}
.landing-cta-primary:hover{filter:brightness(1.05);}
.landing-cta-secondary{display:inline-block; text-decoration:none; text-align:center; font-family:var(--font-display); font-weight:700; font-size:15px; padding:14px 26px; border-radius:var(--radius-sm); border:1px solid var(--line); background:var(--surface); color:var(--ink); cursor:pointer;}
.landing-cta-secondary:hover{background:var(--bg-soft);}
.landing-trust{font-size:12.5px; color:var(--muted); max-width:460px; margin:0;}

.landing-hero-art{flex:1 1 280px; min-width:240px; display:flex; justify-content:center;}
.landing-hero-photo-wrap{position:relative; width:100%; max-width:320px;}
.landing-hero-photo{display:block; width:100%; height:auto; aspect-ratio:2/3; object-fit:cover; border-radius:var(--radius-lg); box-shadow:var(--shadow-md); border:1px solid var(--line);}
.landing-card-mock{width:100%; max-width:300px; background:var(--surface); border:1px solid var(--line); border-radius:var(--radius-lg); padding:22px; box-shadow:var(--shadow-md); font-family:var(--font-display);}
.landing-card-mock.landing-card-mock-float{position:absolute; left:-14px; bottom:-20px; width:200px; max-width:70%; padding:16px;}
.lm-row{display:flex; align-items:center; justify-content:space-between; font-weight:700; font-size:14px; color:var(--ink); margin-bottom:10px;}
.lm-pill{font-family:var(--font-mono); font-size:12px; background:var(--surface-2); border:1px solid var(--line); padding:3px 10px; border-radius:999px; color:var(--accent-ink);}
.lm-track{height:10px; border-radius:999px; background:var(--bg-soft); overflow:hidden; margin-bottom:16px;}
.lm-fill{height:100%; background:var(--accent); border-radius:999px;}
.lm-small{font-size:12.5px; font-weight:600; color:var(--muted); margin-bottom:0;}
.lm-small b{color:var(--accent-ink); font-family:var(--font-mono); font-size:14px;}

.landing-features{padding:36px 0;}
.landing-features h2{font-size:clamp(20px,2.8vw,26px); text-align:center; margin:0 0 28px; font-weight:800;}
.landing-feature-grid{display:grid; grid-template-columns:repeat(auto-fit,minmax(220px,1fr)); gap:16px;}
.landing-feature{background:var(--surface); border:1px solid var(--line); border-radius:var(--radius-md); padding:20px; box-shadow:var(--shadow-sm);}
.lf-ic{font-size:24px; margin-bottom:8px;}
.landing-feature h3{font-size:15.5px; margin:0 0 6px; font-weight:700;}
.landing-feature p{font-size:13.5px; color:var(--muted); margin:0; line-height:1.5;}

.landing-screens{padding:20px 0 36px;}
.landing-screens h2{font-size:clamp(20px,2.8vw,26px); text-align:center; margin:0 0 28px; font-weight:800;}
.landing-screens-grid{display:grid; grid-template-columns:1fr 1fr; gap:18px;}
.landing-screen-wide{grid-column:1 / -1;}
.landing-screen{margin:0; background:var(--surface); border:1px solid var(--line); border-radius:var(--radius-md); padding:10px; box-shadow:var(--shadow-sm);}
.landing-screen img{display:block; width:100%; height:auto; border-radius:var(--radius-sm);}
.landing-screen figcaption{font-size:13px; color:var(--muted); text-align:center; padding:12px 8px 4px; line-height:1.4;}
@media (max-width:700px){
  .landing-screens-grid{grid-template-columns:1fr;}
}

/* Rotates through the same feature list the signed-in promo banners use
   (see PREMIUM_PROMO_FEATURES in app.js) via the small inline script at
   the bottom of index.html — this page never loads app.js itself, so the
   list is duplicated there in miniature rather than shared. */
.landing-premium{padding:8px 0 44px;}
.landing-premium-inner{position:relative; text-align:center; color:#fff; border-radius:var(--radius-lg); overflow:hidden; padding:44px 24px; background:linear-gradient(180deg, rgba(20,16,8,.72) 0%, rgba(20,16,8,.82) 100%), url('images/premium-banner-side.jpg'); background-size:cover; background-position:center; box-shadow:var(--shadow-md);}
.landing-premium-inner .landing-eyebrow{background:rgba(255,255,255,.14); border-color:rgba(255,255,255,.3); color:#fff;}
.landing-premium-inner h2{font-size:clamp(20px,2.8vw,26px); margin:0 0 22px; font-weight:800; color:#fff;}
.landing-premium-rotator{display:flex; align-items:center; justify-content:center; gap:14px; max-width:460px; margin:0 auto 14px; min-height:54px; text-align:left;}
.landing-premium-icon{font-size:30px; line-height:1; flex:0 0 auto;}
.landing-premium-title{font-family:var(--font-display); font-weight:700; font-size:15.5px;}
.landing-premium-desc{font-size:13px; opacity:.92; margin-top:3px; line-height:1.4;}
.landing-premium-dots{display:flex; gap:6px; justify-content:center; margin-bottom:22px;}
.landing-premium-dot{width:6px; height:6px; border-radius:50%; border:none; padding:0; background:rgba(255,255,255,.35); cursor:pointer;}
.landing-premium-dot.active{background:#fff;}
.landing-premium-price{font-family:var(--font-display); font-weight:700; font-size:13px; opacity:.85; margin:0 0 18px;}

.landing-final-cta{text-align:center; padding:48px 0 20px;}
.landing-final-cta h2{font-size:clamp(19px,2.6vw,24px); margin:0 0 18px; font-weight:800;}
.landing-final-cta-inner{display:flex; align-items:center; justify-content:center; gap:28px; flex-wrap:wrap;}
.landing-final-cta-photo{width:150px; height:150px; object-fit:cover; border-radius:var(--radius-lg); box-shadow:var(--shadow-md); border:1px solid var(--line); flex:0 0 auto;}
.landing-final-cta-text{text-align:left;}

.landing-footer{text-align:center; font-size:12px; color:var(--muted); padding:24px 0 8px;}

/* ---- signed-out.html: centered confirmation card ---- */
.signedout-hero{display:flex; justify-content:center; padding:60px 0 70px;}
.signedout-card{max-width:440px; width:100%; text-align:center; background:var(--surface); border:1px solid var(--line); border-radius:var(--radius-lg); padding:40px 32px; box-shadow:var(--shadow-md);}
.signedout-icon{font-size:40px; margin-bottom:14px;}
.signedout-card h1{font-size:clamp(22px,3vw,28px); margin:0 0 12px; font-weight:800;}
.signedout-card p{font-size:14.5px; color:var(--muted); margin:0 0 24px; line-height:1.6;}

@media (max-width:640px){
  .landing-hero{padding:20px 0 40px; text-align:center;}
  .landing-cta-row{justify-content:center;}
  .landing-hero-art{order:-1;}
  .landing-final-cta-inner{flex-direction:column;}
  .landing-final-cta-text{text-align:center;}
}

/* ---- faq.html / terms.html: standalone pages, no sign-in required to read them ----
   The max-width used to sit on .faq-hero itself, sized for "Help & FAQ" —
   fine there, but it also squeezed terms.html's longer "Terms & Conditions
   and Privacy Policy" into an unnecessary two-line wrap even on a wide
   screen. The title now uses the full hero width (wrapping only when it
   actually needs to); only the paragraph underneath keeps a narrower
   column, since line length only matters for readability on body text. */
.faq-hero{padding:8px 0 32px;}
.faq-hero h1{font-size:clamp(24px,3.4vw,32px); margin:0 0 10px; font-weight:800; max-width:900px;}
.faq-hero p{font-size:14.5px; color:var(--muted); margin:0; line-height:1.6; max-width:640px;}
.faq-section{padding-bottom:36px;}
.faq-section h2{font-size:clamp(18px,2.4vw,21px); margin:0 0 14px; font-weight:800;}
.faq-item{background:var(--surface); border:1px solid var(--line); border-radius:var(--radius-md); margin-bottom:10px; overflow:hidden;}
.faq-item summary{list-style:none; cursor:pointer; padding:14px 18px; font-family:var(--font-display); font-weight:700; font-size:14.5px; color:var(--ink); display:flex; align-items:center; gap:10px;}
.faq-item summary::-webkit-details-marker{display:none;}
.faq-item summary::before{content:'▸'; font-size:12px; color:var(--muted); flex:0 0 auto; transition:transform .15s;}
.faq-item[open] summary::before{transform:rotate(90deg);}
.faq-item summary:hover{background:var(--bg-soft);}
.faq-body{padding:0 18px 16px 42px; font-size:13.5px; color:var(--muted); line-height:1.65;}
.faq-body p{margin:0 0 10px;}
.faq-body p:last-child{margin-bottom:0;}
.faq-body ul{margin:0 0 10px; padding-left:20px;}
.faq-body li{margin-bottom:4px;}

/* ===== Section headers / lists (income, debt, gifts, savings, expenses) =====
   Every .app-page section used to rely on whatever margin its own last
   child happened to carry — a trailing <p>, a .toolbar (margin-top only,
   no margin-bottom), a bare list div with none at all — so the gap before
   the next section's heading varied section to section for no reason.
   One deliberate margin-bottom here, collapsing with (not stacking onto)
   any margin a section's last child already has, makes every gap equal. */
.app-page section{margin-bottom:28px;}
.app-page section:last-child{margin-bottom:0;}
.section-head{display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap:8px; margin-bottom:14px;}
.section-head h2{font-size:17px; font-weight:700;}
/* Small inline marker next to a section heading (e.g. "🏦 Import a bank
   statement ✨ Premium") flagging a feature gated by isFeatureUnlocked()
   in app.js — purely a label, the actual lock/unlock is the
   #<feature>-locked / #<feature>-content pair that same function toggles. */
.premium-badge{display:inline-block; font-size:10.5px; font-weight:700; padding:2px 8px; border-radius:999px; background:var(--accent); color:#fff; vertical-align:middle; margin-left:4px;}
.head-right{display:flex; align-items:center; gap:8px; flex-wrap:wrap;}
/* Settings: each category (👤 Profile, 🎨 Appearance, etc.) opens as its
   own page instead of all 12 sitting on one long scroll. #settings-menu
   lists every category; clicking one hides the menu and shows the
   matching .settings-subpage (see the click delegation in app.js), and
   each subpage's own back button returns to the menu. */
.settings-menu{display:flex; flex-direction:column; gap:8px;}
.settings-menu-item{display:flex; align-items:center; justify-content:space-between; width:100%; text-align:left; padding:16px 18px; border:1px solid var(--line); border-radius:var(--radius-md); background:var(--surface); box-shadow:var(--shadow-sm); cursor:pointer; font-family:var(--font-display); font-weight:700; font-size:15px; color:var(--ink);}
.settings-menu-item:hover{border-color:var(--accent); background:var(--bg-soft);}
.settings-menu-chevron{color:var(--muted); font-size:20px; line-height:1;}
.settings-back-btn{display:inline-flex; align-items:center; gap:4px; margin-bottom:18px; background:none; border:none; padding:0; font-family:var(--font-display); font-weight:700; font-size:14px; color:var(--accent-ink); cursor:pointer;}
.settings-back-btn:hover{text-decoration:underline;}
.totals{font-family:var(--font-mono); font-size:12px; color:var(--muted);}
.select-btn,.reset-btn{font-family:var(--font-display); font-weight:600; font-size:11.5px; padding:6px 11px; border-radius:9px; border:1px solid var(--line); background:var(--surface); color:var(--muted); cursor:pointer;}
.select-btn:hover{border-color:var(--good); color:var(--good);}
.reset-btn:hover{border-color:var(--bad); color:var(--bad);}

.extra-add-label{font-size:12.5px; font-weight:700; color:var(--muted); text-transform:uppercase; letter-spacing:.03em; margin:0 0 8px;}
.extra-add{display:flex; flex-wrap:wrap; gap:8px; margin:0 0 16px;}
.extra-add input,.extra-add select{font-family:var(--font-body); font-size:13.5px; padding:9px 12px; border-radius:10px; border:1px solid var(--line); background:var(--surface); color:var(--ink); flex:1; min-width:140px;}
/* The description field's placeholder ("Add a source, e.g. Side gig
   payout") is far longer than the amount field's ("Amount $") — equal
   flex:1 on both meant they split the row evenly and the longer one
   just clipped mid-word on a narrow phone. Letting the amount field stay
   compact gives the description room to actually show its placeholder. */
.extra-add input[type="number"]{flex:0 1 100px; min-width:90px;}
.extra-add input[type="text"]{flex:2 1 180px;}
.extra-add input:focus,.extra-add select:focus{border-color:var(--accent);}
.extra-add button{font-family:var(--font-display); font-weight:700; font-size:13.5px; padding:9px 18px; border-radius:10px; border:none; background:var(--accent); color:#fff; cursor:pointer;}
.recurring-toggle{display:flex; align-items:center; gap:5px; font-size:12.5px; color:var(--muted); white-space:nowrap; flex:0 0 auto; cursor:pointer;}
.recurring-toggle input{flex:0 0 auto; width:auto;}
.extra-add button:hover{filter:brightness(.95);}

.card-list{display:flex; flex-direction:column; gap:8px; margin-bottom:8px;}
.item-row{display:flex; align-items:center; gap:12px; padding:11px 14px; border:1px solid var(--line); border-radius:12px; background:var(--surface); flex-wrap:wrap;}
.item-row:hover{border-color:var(--accent);}
.item-amt{font-family:var(--font-mono); font-weight:700; width:110px; text-align:right;}
.item-desc{flex:1; min-width:120px;}
.item-date{font-size:11px; color:var(--muted); font-family:var(--font-mono);}
.empty-note{font-size:12.5px; color:var(--muted); font-style:italic; padding:8px 2px;}

/* ============================================================
   ITEM-ROW internals (renderList()/renderGiftList() in app.js —
   Income, Debts' per-month rows, Gifts, Savings-app checklist).
   The .item-row wrapper above was styled, but every element it
   actually renders inside that wrapper (checkbox, label, sub-text,
   currency prefix, delete button, the "checked" state) had no
   rules at all, so ticking or reading any of these lists rendered
   as unstyled, default-browser text and controls.
   ============================================================ */
.item-row input[type=checkbox].checkbox{width:18px; height:18px; accent-color:var(--accent); flex:0 0 auto; cursor:pointer;}
.item-row .item-label{flex:1; min-width:140px; display:flex; flex-direction:column; gap:2px;}
.item-row .item-label-input{font-family:var(--font-body); font-size:14px; font-weight:600; color:var(--ink); border:none; background:transparent; padding:2px 0; width:100%;}
.item-row .item-label-input:focus{outline:none; text-decoration:underline; text-decoration-color:var(--accent);}
.item-row .sub{font-size:11px; color:var(--muted); font-family:var(--font-mono);}
.item-row .sub.tick-date{color:var(--good);}
.item-row .currency-prefix{display:flex; align-items:center; gap:4px; flex:0 0 auto;}
.item-row .currency-prefix span{font-family:var(--font-mono); font-size:12.5px; color:var(--muted);}
.item-row .del{flex:0 0 auto; width:26px; height:26px; border:none; border-radius:8px; background:transparent; color:var(--muted); cursor:pointer; font-size:13px; line-height:1;}
.item-row .del:hover{background:var(--bg-soft); color:var(--bad);}
.item-row.checked{background:var(--bg-soft); border-color:var(--line);}
/* text-decoration doesn't render on an <input>'s value text in Chromium/Firefox,
   so a checked row's label dims via color + opacity instead of a strikethrough. */
.item-row.checked .item-label-input{color:var(--muted); opacity:.75;}

/* ============================================================
   EXTRA / GOAL ROWS — the .desc/.date/.amt trio (extra income and
   savings top-up entries, renderExtraList()/renderSavingsTopupList()
   in app.js) and gift-goal cards (renderGoalCards()) were likewise
   never given any CSS of their own.
   ============================================================ */
.extra-row{display:flex; align-items:center; gap:12px; padding:11px 14px; border:1px solid var(--line); border-radius:12px; background:var(--surface); flex-wrap:wrap;}
.extra-row:hover{border-color:var(--accent);}
.extra-row .desc{flex:1; min-width:160px; display:flex; flex-direction:column; gap:2px;}
.extra-row .desc-input{font-family:var(--font-body); font-size:14px; font-weight:600; color:var(--ink); border:none; background:transparent; padding:2px 0; width:100%;}
.extra-row .desc-input:focus{outline:none; text-decoration:underline; text-decoration-color:var(--accent);}
.extra-row .date{font-size:11px; color:var(--muted); font-family:var(--font-mono);}
.extra-row .amt{font-family:var(--font-mono); font-weight:700; flex:0 0 auto;}
.extra-row .del{flex:0 0 auto; width:26px; height:26px; border:none; border-radius:8px; background:transparent; color:var(--muted); cursor:pointer; font-size:13px; line-height:1;}
.extra-row .del:hover{background:var(--bg-soft); color:var(--bad);}

.goal-card{display:flex; align-items:center; gap:12px; padding:13px 15px; border:1px solid var(--line); border-radius:var(--radius-md); background:var(--surface); margin-bottom:10px; flex-wrap:wrap;}
.goal-card:hover{border-color:var(--accent);}
.goal-card .gname{flex:1; min-width:160px; display:flex; flex-direction:column; gap:2px;}
.goal-card .gname-input{font-family:var(--font-display); font-size:14px; font-weight:700; color:var(--ink); border:none; background:transparent; padding:2px 0; width:100%;}
.goal-card .gname-input:focus{outline:none; text-decoration:underline; text-decoration-color:var(--accent);}
.goal-card .gmeta{font-size:11px; color:var(--muted); font-family:var(--font-mono);}
.goal-card .gamt{font-family:var(--font-mono); font-weight:700; font-size:14px; flex:0 0 auto;}
.goal-card .del{flex:0 0 auto; width:26px; height:26px; border:none; border-radius:8px; background:transparent; color:var(--muted); cursor:pointer; font-size:13px; line-height:1;}
.goal-card .del:hover{background:var(--bg-soft); color:var(--bad);}

/* ============================================================
   WHAT'S NEW — a plain, static changelog list (see #page-whatsnew).
   No live data, so this is hand-written markup rather than something
   render() builds, unlike almost every other page in the app.
   ============================================================ */
.whatsnew-list{display:flex; flex-direction:column; gap:12px;}
.whatsnew-item{padding:14px 16px; border:1px solid var(--line); border-left:3px solid var(--accent); border-radius:var(--radius-md); background:var(--surface);}
.whatsnew-title{font-family:var(--font-display); font-weight:700; font-size:14px; color:var(--ink); margin-bottom:4px;}
.whatsnew-body{font-size:12.5px; color:var(--muted); line-height:1.5;}
.whatsnew-item:not(.expanded) .whatsnew-body{display:none;}
.whatsnew-readmore-btn{display:block; margin-top:6px; padding:0; border:0; background:none; font-family:var(--font-display); font-weight:600; font-size:11.5px; color:var(--accent); cursor:pointer;}
.whatsnew-item.expanded .whatsnew-readmore-btn{margin-top:8px;}

/* ============================================================
   EXPENSE CATEGORY BREAKDOWN (renderLivingCategoryChart()) and
   CATEGORY MANAGEMENT rows (renderLivingCategoryManage()) — same
   story: rendered by app.js with no matching CSS anywhere.
   ============================================================ */
#living-cat-chart{display:flex; flex-direction:column; gap:10px;}
.cat-row{padding:2px 0;}
.cat-row-top{display:flex; align-items:center; gap:8px; margin-bottom:5px;}
.cat-dot{width:10px; height:10px; border-radius:50%; flex:0 0 auto;}
.cat-name{flex:1; font-weight:600; font-size:13px; color:var(--ink);}
.cat-amt{font-family:var(--font-mono); font-size:12.5px; font-weight:700; color:var(--ink);}
.cat-track{height:7px; background:var(--bg-soft); border-radius:6px; overflow:hidden; margin-bottom:4px;}
.cat-fill{height:100%; border-radius:6px; transition:width .3s ease;}
.cat-pct{font-size:11px; color:var(--muted); font-family:var(--font-mono); padding-left:18px;}

.cat-manage-row{display:flex; align-items:center; gap:8px; padding:8px 10px; border:1px solid var(--line); border-radius:10px; background:var(--surface); flex-wrap:wrap;}
.cat-manage-row .living-cat-name-input{font-family:var(--font-body); font-size:13px; font-weight:600; color:var(--ink); border:1px solid transparent; background:transparent; border-radius:8px; padding:6px 8px; flex:1; min-width:100px;}
.cat-manage-row .living-cat-name-input:focus{border-color:var(--accent); background:var(--bg-soft); outline:none;}
.cat-manage-row .living-cat-budget-input{font-family:var(--font-mono); font-size:13px; color:var(--ink); border:1px solid var(--line); background:var(--bg-soft); border-radius:8px; padding:6px 8px; width:110px;}
.cat-manage-row .living-cat-budget-input:focus{border-color:var(--accent); outline:none;}
.cat-manage-row .living-cat-del{flex:0 0 auto; width:26px; height:26px; border:none; border-radius:8px; background:transparent; color:var(--muted); cursor:pointer; font-size:13px; line-height:1;}
.cat-manage-row .living-cat-del:hover{background:var(--bg-soft); color:var(--bad);}
.cat-rollover-toggle{display:inline-flex; align-items:center; gap:4px; font-size:11px; color:var(--muted); cursor:pointer; flex:0 0 auto; white-space:nowrap;}
.cat-rollover-toggle input{accent-color:var(--accent); cursor:pointer;}
.cat-manage-row .sub{flex:1 1 100%; font-size:11px; color:var(--accent-ink); font-family:var(--font-mono);}

/* ===== Zero-based monthly budget plan ===== */
.budget-plan-card{border:1px solid var(--line); border-radius:var(--radius-lg); background:var(--surface); padding:16px 18px; margin-bottom:16px; box-shadow:var(--shadow-sm);}
.budget-plan-card h3{font-weight:600; font-size:12px; color:var(--muted); text-transform:uppercase; letter-spacing:.03em; margin-bottom:10px;}
.budget-plan-row{display:flex; justify-content:space-between; align-items:center; padding:5px 0; font-size:13px;}
.budget-plan-row.sub{padding-left:14px; font-size:12px; color:var(--muted);}
.budget-plan-row.head{font-weight:700; border-top:1px dashed var(--line); margin-top:4px; padding-top:9px;}
.budget-plan-row.unassigned{border-top:2px solid var(--line); margin-top:4px; padding-top:10px; font-weight:800; color:var(--good);}
.budget-plan-row.unassigned.over{color:var(--bad);}

/* ============================================================
   EXPENSE DAILY LOG (renderLivingDailyLog()) — grouped by day,
   each day holding one or more .entry-row lines. Also unstyled.
   ============================================================ */
.living-list-head{display:flex; justify-content:space-between; align-items:baseline; margin-bottom:8px;}
.living-list-head h3{margin:0;}
.living-list-head-actions{display:flex; align-items:baseline; gap:14px;}
.link-btn{border:none; background:transparent; color:var(--accent); font-family:var(--font-body); font-size:12px; font-weight:700; cursor:pointer; padding:2px 0;}
.link-btn:hover{text-decoration:underline;}
#living-list{display:flex; flex-direction:column; gap:16px;}
.day-group{border:1px solid var(--line); border-radius:var(--radius-md); background:var(--surface); padding:12px 14px;}
.day-head{display:flex; justify-content:space-between; align-items:baseline; width:100%; margin-bottom:8px; padding-bottom:8px; border-bottom:1px dashed var(--line); border-left:none; border-right:none; border-top:none; background:transparent; font:inherit; color:inherit; cursor:pointer; text-align:left;}
.day-head-left{display:flex; align-items:center; gap:8px;}
.day-chevron{font-size:10px; color:var(--muted); width:10px; display:inline-block;}
.day-head-right{display:flex; align-items:center; gap:10px;}
.day-date{font-weight:700; font-size:12.5px; color:var(--ink);}
.day-count{font-size:11px; color:var(--muted);}
.day-total{font-size:12.5px; font-weight:700; color:var(--muted);}
.day-entries[hidden]{display:none;}
.entry-row{display:flex; align-items:center; gap:10px; padding:6px 0; flex-wrap:wrap;}
.entry-row .cat-dot{margin-top:1px;}
.entry-mid{flex:1; min-width:150px; display:flex; flex-direction:column; gap:3px;}
.entry-desc-input{font-family:var(--font-body); font-size:13.5px; font-weight:600; color:var(--ink); border:none; background:transparent; padding:1px 0; width:100%;}
.entry-desc-input:focus{outline:none; text-decoration:underline; text-decoration-color:var(--accent);}
.entry-cat-select{font-family:var(--font-mono); font-size:10.5px; color:var(--muted); border:none; background:transparent; padding:0; width:fit-content; max-width:100%;}
.entry-cat-select:focus{outline:none;}
.entry-row .currency-prefix{flex:0 0 auto;}
.entry-amt-input{font-family:var(--font-mono); font-weight:700; font-size:13px; border:none; background:transparent; width:90px; text-align:right;}
.entry-amt-input:focus{outline:none;}
.entry-del{flex:0 0 auto; width:24px; height:24px; border:none; border-radius:8px; background:transparent; color:var(--muted); cursor:pointer; font-size:12px; line-height:1;}
.entry-del:hover{background:var(--bg-soft); color:var(--bad);}
.entry-select-box{flex:0 0 auto; width:16px; height:16px; margin:0; accent-color:var(--accent); cursor:pointer;}
.entry-row.selected{background:color-mix(in srgb, var(--accent) 8%, transparent); border-radius:8px; margin:0 -8px; padding:6px 8px;}

/* ===== Bulk actions bar (daily expenses log) ===== */
.bulk-actions-bar{display:flex; flex-wrap:wrap; align-items:center; gap:10px; margin-bottom:12px; padding:10px 14px; border-radius:var(--radius-md); background:color-mix(in srgb, var(--accent) 12%, var(--surface)); border:1px solid var(--accent);}
.bulk-actions-bar[hidden]{display:none;}
.bulk-count{font-weight:700; font-size:12.5px; color:var(--accent-ink); margin-right:4px;}
.bulk-actions-bar select{font-family:var(--font-body); font-size:12.5px; padding:6px 9px; border-radius:8px; border:1px solid var(--line); background:var(--surface); color:var(--ink);}

/* ============================================================
   PERCENTAGE-CHANGE BADGES (month-over-month trend pills, used in
   the category breakdown and savings-app list) — also had no CSS.
   ============================================================ */
.pct-badge{display:inline-block; font-family:var(--font-mono); font-size:10.5px; font-weight:700; padding:2px 7px; border-radius:999px; background:var(--bg-soft); color:var(--muted);}
.pct-badge.up{background:color-mix(in srgb, var(--bad) 14%, var(--surface)); color:var(--bad);}
.pct-badge.down{background:color-mix(in srgb, var(--good) 14%, var(--surface)); color:var(--good);}
.pct-badge.new{background:color-mix(in srgb, var(--accent) 16%, var(--surface)); color:var(--accent-ink);}

/* Import/export status line (xlSetStatus() in app.js) never colored
   by outcome — success/failure/warning all looked identical. */
.xl-status.ok{color:var(--good);}
.xl-status.err{color:var(--bad);}
.xl-status.warn{color:var(--accent-ink);}

/* Bank statement import preview (stmtShowPreview() in app.js) — a plain
   scrollable table, same borrowed .xl-status palette for the +/− amounts
   as the rest of the import/export status line uses for ok/err/warn. */
.stmt-preview-table-wrap{max-height:260px; overflow-y:auto; border:1px solid var(--line); border-radius:var(--radius-md); margin-bottom:10px;}
.stmt-preview-table{width:100%; border-collapse:collapse; font-size:12px;}
.stmt-preview-table th{position:sticky; top:0; background:var(--bg-soft); text-align:left; padding:6px 10px; font-weight:700; border-bottom:1px solid var(--line);}
.stmt-preview-table td{padding:6px 10px; border-bottom:1px solid var(--line); white-space:nowrap;}
.stmt-preview-table td:nth-child(2){white-space:normal; max-width:260px;}
.stmt-preview-table td.stmt-out{color:var(--bad); font-weight:600;}
.stmt-preview-table td.stmt-in{color:var(--good); font-weight:600;}

.payoff-panel{border:1px dashed var(--line); border-radius:var(--radius-md); padding:14px 16px; margin:0 0 16px; background:var(--bg-soft);}
.payoff-panel h3{font-size:13px; font-weight:700; margin-bottom:8px;}
.payoff-panel-head{display:flex; justify-content:space-between; align-items:baseline; gap:10px;}
.payoff-panel-head h3{margin-bottom:8px;}
/* .payoff-head (id="payoff-head"/"accounts-head") holds the same .n/.lbl/.val
   stat blocks as .overall-nums — lay it out the same way, not as the plain
   single-line label row this rule used to be. */
.payoff-head{display:flex; gap:20px; flex-wrap:wrap; margin-bottom:12px;}
.payoff-head .n .lbl, .overall-nums .n .lbl{font-size:9.5px; text-transform:uppercase; color:var(--muted); letter-spacing:.05em;}
.payoff-head .n .val, .overall-nums .n .val{font-family:var(--font-mono); font-size:17px; font-weight:700; margin-top:3px;}

/* ============================================================
   DEBT-SERIES / SAVINGS-ACCOUNT ROWS (#payoff-list, #accounts-list —
   see renderDebtOverview()/renderSavingsAccounts() in app.js). These
   rows (.ds-row and friends) had no rules at all, so they rendered as
   unstyled, default-font text the moment a debt or savings app was added.
   ============================================================ */
#payoff-list, #accounts-list{display:flex; flex-direction:column; gap:10px;}
.ds-row{border:1px solid var(--line); border-radius:var(--radius-md); background:var(--surface); padding:13px 15px;}
.ds-top{display:flex; justify-content:space-between; align-items:center; gap:10px; flex-wrap:wrap; margin-bottom:8px;}
.ds-name{font-family:var(--font-display); font-weight:700; font-size:14px; color:var(--ink);}
.ds-ongoing-badge{font-size:12px; opacity:.7;}
.ds-top-right{display:flex; align-items:center; gap:6px;}
.ds-top .del{flex:0 0 auto; width:22px; height:22px; border:none; border-radius:7px; background:transparent; color:var(--muted); cursor:pointer; font-size:12px; line-height:1;}
.ds-top .del:hover{background:var(--bg-soft); color:var(--bad);}
.ds-left{font-family:var(--font-mono); font-weight:700; font-size:12.5px; color:var(--bad);}
.ds-left.clear{color:var(--good);}
.ds-track{height:8px; background:var(--bg-soft); border-radius:6px; overflow:hidden; margin-bottom:8px;}
.ds-fill{height:100%; background:var(--accent); border-radius:6px; transition:width .3s ease;}
.ds-meta{font-size:11.5px; color:var(--muted); font-family:var(--font-mono);}
.ds-pay{display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin-top:11px; padding-top:11px; border-top:1px dashed var(--line);}
.ds-extra-input,.acct-wd-input,.ds-total-input,.acct-rate-input,.ri-amt-input,.inv-price-input,.inv-price-date{font-family:var(--font-body); font-size:13px; padding:8px 11px; border-radius:9px; border:1px solid var(--line); background:var(--bg-soft); color:var(--ink); width:160px;}
.ds-extra-input:focus,.acct-wd-input:focus,.ds-total-input:focus,.acct-rate-input:focus,.ri-amt-input:focus,.inv-price-input:focus,.inv-price-date:focus{border-color:var(--accent);}
.acct-currency-select,.item-currency-select{font-family:var(--font-body); font-size:13px; padding:6px 9px; border-radius:9px; border:1px solid var(--line); background:var(--bg-soft); color:var(--ink);}
.acct-currency-row{opacity:.9;}
.item-currency-badge{font-family:var(--font-display); font-weight:700; font-size:10px; letter-spacing:.03em; color:var(--accent); background:var(--bg-soft); border:1px solid var(--line); border-radius:6px; padding:2px 6px; flex:0 0 auto;}
.currency-converted{color:var(--accent) !important;}
#currency-rates-list{margin-top:14px; padding:10px 12px; border:1px solid var(--line); border-radius:var(--radius-md); background:var(--surface); box-shadow:var(--shadow-sm);}
.currency-rate-row{display:flex; align-items:center; gap:8px; margin:0 0 8px;}
.currency-rate-row:last-child{margin-bottom:0;}
.currency-rate-input{font-family:var(--font-body); font-size:13px; padding:6px 9px; border-radius:9px; border:1px solid var(--line); background:var(--bg-soft); color:var(--ink); width:120px;}
.ds-pay-btn,.acct-wd-btn{font-family:var(--font-display); font-weight:700; font-size:12px; padding:8px 13px; border-radius:9px; border:none; background:var(--accent); color:#fff; cursor:pointer; white-space:nowrap;}
.ds-pay-btn:hover,.acct-wd-btn:hover{filter:brightness(.95);}
.ds-clear-btn{background:var(--surface); color:var(--ink); border:1px solid var(--line);}
.hint{font-size:10.5px; color:var(--muted);}

.goal-list-head{display:flex; justify-content:space-between; align-items:baseline; margin-bottom:8px;}
.goal-list-head h3{margin:0; font-size:12.5px; font-weight:700; color:var(--muted); text-transform:uppercase; letter-spacing:.03em;}
.goal-list{display:flex; flex-direction:column; gap:10px; margin-bottom:16px;}
.savings-goal{border:1px solid var(--line); border-radius:var(--radius-md); background:var(--bg-soft); padding:14px 16px; margin-bottom:16px;}
.savings-goal-head{display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap:8px; margin-bottom:8px;}
.sg-label{font-weight:700; font-size:14px;}
.savings-goal-set{display:flex; gap:6px;}
.savings-goal-set input{font-family:var(--font-body); font-size:13px; padding:7px 10px; border-radius:9px; border:1px solid var(--line); background:var(--surface); width:120px;}
.savings-goal-set button{font-family:var(--font-display); font-weight:700; font-size:12.5px; padding:7px 13px; border-radius:9px; border:none; background:var(--accent); color:#fff; cursor:pointer;}
.savings-goal-track{height:9px; background:var(--surface); border-radius:6px; overflow:hidden; border:1px solid var(--line);}
.savings-goal-fill{height:100%; background:var(--good); border-radius:6px; transition:width .3s ease;}
.savings-goal-nums{display:flex; justify-content:space-between; font-family:var(--font-mono); font-size:12px; color:var(--muted); margin-top:6px;}
.savings-goal-pct{font-weight:700; color:var(--accent);}
.savings-apps-block .note{font-size:12px; color:var(--muted); margin:2px 0 12px;}

.living-subpanel{border:1px solid var(--line); border-radius:var(--radius-md); background:var(--surface); padding:14px 16px; margin-bottom:14px;}
.living-subpanel h3{font-size:12.5px; font-weight:700; color:var(--muted); text-transform:uppercase; letter-spacing:.03em; margin-bottom:10px;}
.living-subpanel-toggle{display:flex; align-items:center; gap:6px; width:100%; font-family:inherit; font-size:12.5px; font-weight:700; color:var(--muted); text-transform:uppercase; letter-spacing:.03em; border:none; background:transparent; padding:0; margin-bottom:10px; cursor:pointer; text-align:left;}
.living-subpanel-body[hidden]{display:none;}
.chart-scroll{overflow-x:auto;}

/* ===== Multi-month trend sparklines (Net Worth tab) ===== */
.trend-grid{display:grid; grid-template-columns:repeat(2,1fr); gap:14px; margin-bottom:20px;}
@media (max-width:640px){ .trend-grid{grid-template-columns:1fr;} }
.trend-mini-card{border:1px solid var(--line); border-radius:var(--radius-lg); background:var(--surface); padding:14px 16px; box-shadow:var(--shadow-sm);}
.trend-mini-head{display:flex; justify-content:space-between; align-items:baseline; margin-bottom:6px;}
.trend-mini-label{font-weight:600; font-size:12px; color:var(--muted); text-transform:uppercase; letter-spacing:.03em;}
.trend-mini-val{font-family:var(--font-mono); font-weight:700; font-size:14px; color:var(--ink);}
.trend-mini-svg{display:block; width:100%; height:80px;}
.trend-mini-svg .trend-empty-label{font-size:11px; fill:var(--muted);}
.manage-cats{border:1px dashed var(--line); border-radius:var(--radius-md); background:var(--bg-soft); padding:14px 16px; margin:16px 0;}
.manage-cats-head{display:flex; align-items:center; gap:8px; width:100%; font-family:inherit; font-weight:700; font-size:13.5px; margin-bottom:4px; border:none; background:transparent; color:inherit; padding:0; cursor:pointer; text-align:left;}
.manage-cats-body[hidden]{display:none;}
.cat-manage-list{display:flex; flex-direction:column; gap:6px; margin:10px 0;}
.new-cat-form{display:flex; gap:8px; flex-wrap:wrap; margin-top:8px;}
.new-cat-form input{font-family:var(--font-body); font-size:13px; padding:8px 11px; border-radius:9px; border:1px solid var(--line); background:var(--surface); flex:1; min-width:130px;}
.new-cat-form button{font-family:var(--font-display); font-weight:700; font-size:12.5px; padding:8px 14px; border-radius:9px; border:none; background:var(--accent); color:#fff; cursor:pointer;}

.mvl-card{border:1px solid var(--line); border-radius:var(--radius-lg); background:var(--surface); padding:16px 20px; margin:0 0 20px; box-shadow:var(--shadow-sm);}
.mvl-card h3{font-weight:600; font-size:12px; color:var(--muted); text-transform:uppercase; letter-spacing:.03em; margin-bottom:10px;}
.mvl-row{display:flex; align-items:center; gap:14px; flex-wrap:wrap; padding:7px 0; border-bottom:1px dashed var(--line);}
.mvl-row:last-child{border-bottom:none; padding-bottom:0;}
.mvl-label{font-weight:600; font-size:13px; min-width:80px; flex:0 0 auto;}
.mvl-nums{font-family:var(--font-mono); font-size:12px; color:var(--muted); flex:1; min-width:160px;}
.mvl-nums b{color:var(--ink);}
.mvl-empty{font-size:12px; color:var(--muted); font-style:italic;}
.mvl-trophy{margin-top:10px; padding-top:10px; border-top:1px dashed var(--line); font-size:12.5px; color:var(--accent-ink);}
.mvl-trophy[hidden]{display:none;}

/* ===== Mini-quests ===== */
.quests-card{border:1px solid var(--line); border-radius:var(--radius-lg); background:var(--surface); padding:16px 20px; margin:0 0 20px; box-shadow:var(--shadow-sm);}
.quests-card h3{font-weight:600; font-size:12px; color:var(--muted); text-transform:uppercase; letter-spacing:.03em; margin-bottom:12px;}
.quest-row{margin-bottom:12px;}
.quest-row:last-child{margin-bottom:0;}
.quest-top{display:flex; align-items:center; gap:8px; margin-bottom:5px;}
.quest-icon{font-size:15px; flex:0 0 auto;}
.quest-label{font-weight:600; font-size:12.5px; flex:1;}
.quest-period{font-size:10px; color:var(--muted); text-transform:uppercase; letter-spacing:.03em; flex:0 0 auto;}
.quest-track{height:7px; background:var(--bg-soft); border-radius:6px; overflow:hidden;}
.quest-fill{height:100%; background:var(--accent); border-radius:6px; transition:width .3s ease;}
.quest-row.done .quest-fill{background:var(--good);}
.quest-meta{font-family:var(--font-mono); font-size:10.5px; color:var(--muted); margin-top:4px;}
.quest-row.done .quest-meta{color:var(--good);}

.budget-health{display:flex; justify-content:space-between; align-items:center; gap:18px; border:1px solid var(--line); border-radius:var(--radius-lg); padding:15px 18px; margin:0 0 18px; flex-wrap:wrap; box-shadow:var(--shadow-sm); border-left-width:5px;}
.budget-health.ok{background:color-mix(in srgb, var(--good) 8%, var(--surface)); border-left-color:var(--good);}
.budget-health.over{background:color-mix(in srgb, var(--bad) 8%, var(--surface)); border-left-color:var(--bad);}
.bh-left{display:flex; align-items:center; gap:12px; min-width:200px;}
.bh-icon{font-size:24px; line-height:1;}
.bh-status{font-weight:700; font-size:15px;}
.budget-health.ok .bh-status{color:var(--good);}
.budget-health.over .bh-status{color:var(--bad);}
.bh-sub{font-size:11.5px; color:var(--muted); margin-top:2px;}
.bh-right{text-align:right;}
.bh-amt{font-family:var(--font-mono); font-size:20px; font-weight:700;}
.budget-health.ok .bh-amt{color:var(--good);}
.budget-health.over .bh-amt{color:var(--bad);}
.bh-amt-lbl{font-size:9.5px; text-transform:uppercase; letter-spacing:.05em; color:var(--muted); margin-top:2px;}
.bh-breakdown{width:100%; display:flex; gap:16px; flex-wrap:wrap; font-family:var(--font-mono); font-size:11px; color:var(--muted); padding-top:11px; margin-top:2px; border-top:1px dashed var(--line);}
.bh-breakdown b{color:var(--ink);}

footer{padding:26px 0 36px; color:var(--muted); font-size:11.5px; border-top:1px solid var(--line); margin-top:12px;}

/* ===== Quotes ===== */
.quote-banner{border:1px dashed var(--line); border-radius:var(--radius-md); background:var(--surface); padding:13px 18px; margin:0 0 20px; text-align:center; font-family:var(--font-display); font-size:13.5px; color:var(--accent-ink); font-weight:600; font-style:italic;}
.quote-banner.pulse{animation:quotePulse .6s ease;}
@keyframes quotePulse{0%{transform:scale(.97); opacity:.35;} 60%{transform:scale(1.015);} 100%{transform:scale(1); opacity:1;}}

/* ===== Spotify playlist embed (Settings, and Overview when set) ===== */
.spotify-embed-wrap{border-radius:var(--radius-md); overflow:hidden; margin:12px 0; box-shadow:var(--shadow-sm);}
.spotify-embed-wrap iframe{display:block; border:none;}

/* ===== XP / Level / Badges ===== */
.global-search-wrap{position:relative; margin:0 0 16px;}
.global-search-row{display:flex; gap:8px;}
.global-search-input{width:100%; flex:1; min-width:0; box-sizing:border-box; font-family:var(--font-body); font-size:14px; padding:11px 14px; border-radius:12px; border:1px solid var(--line); background:var(--surface); color:var(--ink);}
.global-search-input:focus{border-color:var(--accent);}
#global-search-filter-toggle{flex:0 0 auto;}
#global-search-filter-toggle.active{background:var(--accent); color:#fff; border-color:var(--accent);}
.global-search-filters{display:flex; flex-wrap:wrap; align-items:flex-end; gap:10px 16px; margin-top:10px; padding:12px 14px; border:1px solid var(--line); border-radius:var(--radius-md); background:var(--bg-soft);}
.global-search-filters[hidden]{display:none;}
.gsf-field{display:flex; flex-direction:column; gap:4px; font-size:10.5px; font-weight:700; color:var(--muted); text-transform:uppercase; letter-spacing:.03em;}
.gsf-field input{font-family:var(--font-body); font-size:13px; padding:7px 9px; border-radius:8px; border:1px solid var(--line); background:var(--surface); color:var(--ink); width:130px;}
.gsf-kinds{display:flex; flex-wrap:wrap; gap:4px 14px; align-items:center;}
.global-search-results{position:absolute; top:calc(100% + 4px); left:0; right:0; z-index:60; max-height:320px; overflow-y:auto; background:var(--surface); border:1px solid var(--line); border-radius:var(--radius-md); box-shadow:var(--shadow-md); padding:6px;}
.search-result-row{display:flex; align-items:center; gap:8px; padding:8px 10px; border-radius:9px; cursor:pointer; font-size:12.5px;}
.search-result-row:hover{background:var(--bg-soft);}
.sr-kind{font-family:var(--font-display); font-weight:700; font-size:10px; text-transform:uppercase; letter-spacing:.03em; color:var(--accent); flex:0 0 auto; width:50px;}
.sr-label{flex:1; color:var(--ink); white-space:nowrap; overflow:hidden; text-overflow:ellipsis;}
.sr-month{color:var(--muted); flex:0 0 auto;}
.sr-amt{flex:0 0 auto; color:var(--ink);}
.xp-panel{border:1px solid var(--line); border-radius:var(--radius-lg); background:var(--surface); padding:16px 20px; margin:0 0 20px; box-shadow:var(--shadow-sm);}
.xp-head{display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap:8px; margin-bottom:9px;}
.xp-level{font-family:var(--font-display); font-weight:800; font-size:15px; color:var(--accent); display:flex; align-items:center; gap:7px;}
.xp-level .badge-icon{font-size:18px;}
.xp-track{height:9px; background:var(--bg-soft); border-radius:8px; overflow:hidden;}
.xp-fill{height:100%; width:0%; background:var(--accent); border-radius:8px; transition:width .4s ease;}
.xp-sub{font-family:var(--font-mono); font-size:10.5px; color:var(--muted); margin-top:6px;}
.badge-row{display:flex; flex-wrap:wrap; gap:6px; margin-top:12px;}
/* Icon-only on Overview — same small circular-swatch footprint as
   .theme-swatch/.pet-swatch, so dozens of achievements fit on one compact row
   instead of the old full-label pills. Full labels are on the XP page;
   here the label is just the title tooltip. */
.badge-chip{display:flex; align-items:center; justify-content:center; width:26px; height:26px; border-radius:50%; background:var(--bg-soft); border:1px solid var(--line); font-size:13px; line-height:1; cursor:default;}
.badge-chip.locked{opacity:.35; filter:grayscale(1);}
.badge-chip-empty{font-size:12px; color:var(--muted);}

/* ===== Debt "boss" health bars ===== */
.ds-boss-row{display:flex; align-items:center; gap:10px; margin-bottom:10px;}
.ds-boss-icon{font-size:28px; line-height:1; flex:0 0 auto;}
.ds-boss-bar-wrap{flex:1; min-width:0;}
.ds-boss-label{font-family:var(--font-display); font-weight:800; font-size:9.5px; letter-spacing:.06em; color:var(--muted); margin-bottom:3px;}
.ds-hp-track{height:11px; border-radius:7px;}
.ds-hp-fill{border-radius:7px; transition:width .4s ease, background .4s ease;}

/* ===== Debt payoff strategy (snowball / avalanche / own pace) ===== */
.payoff-strategy{margin:12px 0 16px; padding:12px 14px; border:1px solid var(--line); border-radius:var(--radius-md); background:var(--surface);}
.payoff-strategy-picker{display:flex; flex-wrap:wrap; gap:8px; margin-bottom:8px;}
.payoff-strategy-btn{font-family:var(--font-display); font-weight:700; font-size:12.5px; padding:7px 13px; border-radius:999px; border:1.5px solid var(--line); background:transparent; color:var(--muted); cursor:pointer;}
.payoff-strategy-btn:hover{border-color:var(--accent);}
.payoff-strategy-btn.active{background:var(--accent); border-color:var(--accent); color:#fff;}
.payoff-strategy-note{font-size:12px; color:var(--muted); margin:0; max-width:640px;}
.payoff-strategy-projection{font-size:12.5px; color:var(--accent-ink); background:color-mix(in srgb, var(--accent) 10%, transparent); border-radius:9px; padding:8px 11px; margin:8px 0 0;}
.payoff-strategy-projection[hidden]{display:none;}
.ds-rate-row{display:flex; align-items:center; gap:10px; flex-wrap:wrap; margin-bottom:6px;}
.ds-rate-label{font-size:11px; color:var(--muted); display:inline-flex; align-items:center; gap:5px;}
.ds-rate-input{width:52px; font-family:var(--font-mono); font-size:12px; padding:3px 6px; border-radius:6px; border:1px solid var(--line); background:var(--bg-soft); color:var(--ink); text-align:right;}
.ds-priority-badge{font-family:var(--font-display); font-weight:700; font-size:10.5px; color:#fff; background:var(--accent); border-radius:999px; padding:3px 10px;}
.ds-priority-rank{font-size:10.5px; color:var(--muted);}

/* ===== Prestige ===== */
.prestige-panel{border:1px dashed var(--accent); border-radius:var(--radius-md); background:color-mix(in srgb, var(--accent) 8%, var(--surface)); padding:16px 18px;}
.prestige-panel p{font-size:13px; color:var(--ink); margin:0 0 12px; max-width:640px;}
.prestige-stars{font-size:18px; letter-spacing:2px; margin-bottom:10px; color:var(--muted);}

/* ===== Growing garden companion (alongside the pet) ===== */
.growth-tree{position:fixed; bottom:calc(16px + env(safe-area-inset-bottom, 0px)); left:16px; z-index:25; display:flex; flex-direction:column; align-items:center; gap:4px;}
.growth-tree-face{width:72px; height:72px; border-radius:50%; background:var(--surface); border:1px solid var(--line); display:flex; align-items:center; justify-content:center; font-size:32px; box-shadow:var(--shadow-md);}
.growth-tree-label{font-family:var(--font-display); font-weight:700; font-size:10px; color:var(--muted); background:var(--surface); border:1px solid var(--line); border-radius:999px; padding:2px 9px;}
@media (max-width:640px){
  .growth-tree{bottom:10px; left:10px;}
  .growth-tree-face{width:48px; height:48px; font-size:22px;}
  .growth-tree-label{font-size:9px;}
}

/* ===== Shareable milestone card modal ===== */
.milestone-modal-overlay{position:fixed; inset:0; z-index:6000; display:flex; align-items:center; justify-content:center; padding:20px; background:rgba(0,0,0,.55);}
.milestone-modal-overlay[hidden]{display:none;}
.milestone-modal{position:relative; background:var(--surface); border-radius:var(--radius-lg); padding:16px; box-shadow:var(--shadow-md); max-width:min(420px,90vw);}
.milestone-modal-close{position:absolute; top:8px; right:8px; width:28px; height:28px; border-radius:50%; border:none; background:var(--bg-soft); color:var(--ink); cursor:pointer; font-size:13px;}
#milestone-canvas{display:block; width:100%; height:auto; border-radius:var(--radius-md); margin-bottom:12px;}
.milestone-modal-actions{display:flex; gap:8px; justify-content:center;}
.xp-page-breakdown{font-family:var(--font-mono); font-size:11.5px; color:var(--muted); margin:10px 0 0;}
/* A little tighter than a first pass — smaller minimum column, icon and
   padding both trimmed down — while keeping the icon+label layout the
   Overview row no longer has room for. */
/* #xp-badge-grid is now a column of category sections (see XP_CATEGORIES
   in app.js) rather than one flat grid — .xp-badge-category-grid is what
   carries the actual grid layout, once per category. */
.xp-badge-grid{display:flex; flex-direction:column; gap:16px;}
.xp-badge-category-head{font-family:var(--font-display); font-weight:700; font-size:12px; color:var(--muted); text-transform:uppercase; letter-spacing:.03em; margin:0 0 8px;}
.xp-badge-category-grid{display:grid; grid-template-columns:repeat(auto-fill,minmax(180px,1fr)); gap:7px;}
.xp-badge-card{display:flex; align-items:center; gap:8px; background:var(--bg-soft); border:1px solid var(--line); border-radius:var(--radius-sm); padding:8px 10px;}
.xp-badge-card .b-icon{font-size:17px; line-height:1; flex:0 0 auto;}
.xp-badge-card .b-label{font-family:var(--font-display); font-weight:700; font-size:11.5px; color:var(--ink); line-height:1.25;}
.xp-badge-card.locked{opacity:.4; filter:grayscale(1);}
.xp-badge-card.earned{border-color:var(--accent); box-shadow:0 0 0 1px var(--accent) inset;}
.xp-badge-all-earned{font-size:13px; color:var(--muted); margin:4px 0 0;}

/* ===== Cat companion ===== */
.cat-companion{position:fixed; bottom:calc(16px + env(safe-area-inset-bottom, 0px)); right:16px; z-index:25; display:flex; align-items:flex-end; gap:8px;}
.cat-speech{background:var(--surface); border:1px solid var(--line); border-radius:12px; padding:8px 12px; font-size:11.5px; max-width:165px; box-shadow:var(--shadow-md); display:none; color:var(--ink);}
.cat-companion:hover .cat-speech,.cat-companion.show-speech .cat-speech{display:block;}
.cat-face{width:150px; height:150px; border-radius:50%; background:var(--surface); border:1px solid var(--line); display:flex; align-items:center; justify-content:center; font-size:78px; box-shadow:var(--shadow-md); cursor:pointer; animation:catBob 3s ease-in-out infinite;}
@keyframes catBob{0%,100%{transform:translateY(0);} 50%{transform:translateY(-4px);}}
/* .petted replaces the idle catBob loop with a one-shot bounce (higher
   specificity than .cat-face alone, so it wins for the animation's
   duration) — a distinct "that landed" reaction to a click or a tick,
   separate from the ambient float. */
.cat-face.petted{animation:catPet .5s ease;}
@keyframes catPet{0%{transform:scale(1);} 35%{transform:scale(1.22);} 65%{transform:scale(.92);} 100%{transform:scale(1);}}
.cat-pop{position:absolute; right:6px; bottom:174px; font-size:51px; opacity:0; pointer-events:none;}
.cat-pop.pop{animation:catPop .9s ease forwards;}
@keyframes catPop{0%{opacity:0; transform:translateY(0) scale(.6);} 25%{opacity:1; transform:translateY(-8px) scale(1.1);} 100%{opacity:0; transform:translateY(-32px) scale(.9);}}

/* ===== Premium promo banners (top + side) ===== */
/* Both pull their rotating content from PREMIUM_PROMO_FEATURES via
   initPremiumPromo() in app.js — hidden entirely for a Premium account or
   once dismissed this session. The scrim is lighter than the 84%-opaque
   one full-page theme photos use (see the --bg-image rules near the top
   of this file) since there's far less competing content in a banner this
   size, and the photo itself is part of what should read as "nice" here. */
.premium-promo-banner{position:relative; margin-top:14px; border-radius:var(--radius-md); overflow:hidden; color:#fff; background:linear-gradient(100deg, rgba(20,16,8,.78) 0%, rgba(20,16,8,.5) 55%, rgba(20,16,8,.25) 100%), url('images/premium-banner-top.jpg'); background-size:cover; background-position:center; box-shadow:var(--shadow-md);}
.premium-promo-banner[hidden]{display:none;}
.premium-promo-content{display:flex; align-items:center; gap:14px; padding:16px 50px 14px 18px;}
.premium-promo-icon{font-size:30px; line-height:1; flex:0 0 auto;}
.premium-promo-text{flex:1 1 auto; min-width:0;}
.premium-promo-eyebrow{font-family:var(--font-display); font-weight:700; font-size:10.5px; text-transform:uppercase; letter-spacing:.06em; opacity:.85;}
.premium-promo-title{font-family:var(--font-display); font-weight:700; font-size:15px; margin-top:1px;}
.premium-promo-desc{font-size:12.5px; opacity:.92; margin-top:2px; max-width:520px;}
.premium-promo-cta{flex:0 0 auto; font-family:var(--font-display); font-weight:700; font-size:12.5px; padding:8px 16px; border-radius:999px; border:none; background:#fff; color:#5C3B0E; cursor:pointer;}
.premium-promo-dismiss{position:absolute; top:8px; right:10px; width:24px; height:24px; border-radius:50%; border:none; background:rgba(255,255,255,.18); color:#fff; cursor:pointer; font-size:12px; line-height:1;}
.premium-promo-dots{display:flex; gap:5px; justify-content:center; padding:0 0 10px;}
.premium-promo-dot{width:6px; height:6px; border-radius:50%; border:none; padding:0; background:rgba(255,255,255,.35); cursor:pointer;}
.premium-promo-dot.active{background:#fff;}
@media (max-width:640px){
  .premium-promo-content{flex-wrap:wrap; padding:14px 42px 10px 14px;}
  .premium-promo-cta{margin-left:44px;}
}

/* Side banner: fixed to the right edge, vertically centered, desktop only
   — there's no spare width for it alongside the single-column phone
   layout, and the top banner above already covers the same ground there. */
.premium-promo-side{position:fixed; top:50%; right:0; transform:translateY(-50%); z-index:24; width:190px; border-radius:var(--radius-md) 0 0 var(--radius-md); overflow:hidden; color:#fff; text-align:center; padding:16px 14px 14px; background:linear-gradient(180deg, rgba(10,8,4,.3) 0%, rgba(10,8,4,.82) 65%), url('images/premium-banner-side.jpg'); background-size:cover; background-position:center; box-shadow:var(--shadow-md);}
.premium-promo-side[hidden]{display:none;}
@media (max-width:1100px){ .premium-promo-side{display:none;} }
.premium-promo-side-dismiss{position:absolute; top:6px; right:8px; width:22px; height:22px; border-radius:50%; border:none; background:rgba(255,255,255,.18); color:#fff; cursor:pointer; font-size:11px; line-height:1;}
.premium-promo-side-icon{font-size:26px; margin-top:6px;}
.premium-promo-side-eyebrow{font-family:var(--font-display); font-weight:700; font-size:10px; text-transform:uppercase; letter-spacing:.06em; opacity:.85; margin-top:4px;}
.premium-promo-side-title{font-family:var(--font-display); font-weight:700; font-size:13.5px; margin-top:3px;}
.premium-promo-side-desc{font-size:11px; opacity:.92; margin-top:5px; line-height:1.35;}
.premium-promo-side-cta{margin-top:10px; font-family:var(--font-display); font-weight:700; font-size:12px; padding:7px 14px; border-radius:999px; border:none; background:#fff; color:#5C3B0E; cursor:pointer;}

/* ===== Confetti / sparkle (kept, toned down) ===== */
/* Sits above the app's own content (falls/drifts in front of cards, same
   as real weather would) but below #confetti-canvas, so a milestone burst
   is never obscured by falling snow/rain, and below every modal overlay. */
#weather-canvas{position:fixed; inset:0; pointer-events:none; z-index:40;}
#confetti-canvas{position:fixed; inset:0; pointer-events:none; z-index:60;}
.sparkle{display:none;} /* the paginated layout no longer needs the ambient sky décor */

/* ===== Responsive ===== */
@media (max-width:700px){
  .summary-row.row1{grid-template-columns:1fr 1fr;}
  .summary-row.row2{grid-template-columns:1fr;}
  .item-row{flex-wrap:wrap;}
  .item-amt{width:90px;}
  .overall-nums{gap:16px;}
  /* Hide/Undo/Redo/Settings/🔔/name/Sign out right-align on one line by
     design (see .xl-actions-row) — fine when they all fit, but on a narrow
     phone they wrap onto 2+ lines, and right-aligning each wrapped line
     independently left a ragged, inconsistent-looking stagger (the fuller
     first line sits near the left edge just from filling the width, while
     a half-empty second line visibly clumps over to the right). Left-
     aligning once wrapped reads as one coherent block instead. */
  .xl-actions-row{justify-content:flex-start;}
  /* .notif-dropdown's on-screen position is computed in JS (see the
     notification bell IIFE in app.js) from the bell button's actual
     bounding rect, not assumed from this breakpoint — whether the actions
     row above has actually wrapped (and so where the bell ends up) depends
     on content width (a long signed-in email, for instance), not just
     viewport width, so a static left:0/right:0 swap here got it wrong at
     plenty of real phone widths. No override needed here any more. */
}
@media (min-width:701px) and (max-width:920px){
  .summary-row.row1{grid-template-columns:repeat(3,1fr);}
  .summary-row.row2{grid-template-columns:repeat(3,1fr);}
}
@media (max-width:600px){
  .cat-companion{bottom:10px; right:10px;}
  .cat-face{width:88px; height:88px; font-size:40px;}
  .cat-pop{bottom:102px; font-size:30px;}
}

@media (prefers-reduced-motion:reduce){
  *{animation-duration:.01ms !important; animation-iteration-count:1 !important; transition-duration:.01ms !important;}
}

/* ============================================================
   IDLE / SESSION-CAP SIGN-OUT WARNING (see auto-logout.js)
   Shown on the signed-in app page only — separate from the
   body.ft-locked sign-in gate above.
   ============================================================ */
#idle-warning-overlay{display:none; position:fixed; inset:0; z-index:6000; align-items:center; justify-content:center; padding:20px; background:rgba(0,0,0,.4);}
#idle-warning-overlay.open{display:flex;}
#idle-warning-overlay .auth-card{max-width:360px; text-align:center;}
#idle-warning-overlay #idle-warning-count{font-weight:700; color:var(--accent);}
#idle-warning-overlay .auth-submit{margin-top:6px;}
#idle-warning-overlay .auth-link{margin-top:10px;}
/* Same fixed-overlay pattern as #idle-warning-overlay, shown/hidden via the
   `hidden` attribute (see the global [hidden] rule near the top of this
   file) rather than a .open class, matching #auth-loading-box's convention. */
#pin-setup-overlay{position:fixed; inset:0; z-index:6000; display:flex; align-items:center; justify-content:center; padding:20px; background:rgba(0,0,0,.4);}
#pin-setup-overlay .auth-card{max-width:380px;}
#pin-setup-overlay .auth-submit{margin-top:6px;}
#pin-setup-overlay .auth-link{margin-top:10px;}
#pin-unlock-card .auth-link{margin-top:10px;}

/* Same fixed-overlay pattern as #pin-setup-overlay above — the security PIN
   gate confirming a sensitive action (deleting an entry, revealing hidden
   data, finishing a password sign-in). See openPinGate() in app.js. */
#pin-gate-overlay{position:fixed; inset:0; z-index:6000; display:flex; align-items:center; justify-content:center; padding:20px; background:rgba(0,0,0,.4);}
#pin-gate-overlay .auth-card{max-width:380px;}
#pin-gate-overlay .auth-submit{margin-top:6px;}
#pin-gate-overlay .auth-link{margin-top:10px;}

/* Same fixed-overlay pattern as #pin-gate-overlay above — Settings →
   Security's "Change password" form. See changePassword() in app.js. */
#password-change-overlay{position:fixed; inset:0; z-index:6000; display:flex; align-items:center; justify-content:center; padding:20px; background:rgba(0,0,0,.4);}
#password-change-overlay .auth-card{max-width:380px;}
#password-change-overlay .auth-submit{margin-top:6px;}
#password-change-overlay .auth-link{margin-top:10px;}

/* Same fixed-overlay pattern as #password-change-overlay above — Settings →
   Security's "Update recovery email" form. See updateRecoveryEmail() in
   app.js. */
#recovery-email-overlay{position:fixed; inset:0; z-index:6000; display:flex; align-items:center; justify-content:center; padding:20px; background:rgba(0,0,0,.4);}
#recovery-email-overlay .auth-card{max-width:380px;}
#recovery-email-overlay .auth-submit{margin-top:6px;}
#recovery-email-overlay .auth-link{margin-top:10px;}

#onboarding-overlay{position:fixed; inset:0; z-index:6000; display:flex; align-items:center; justify-content:center; padding:20px; background:rgba(0,0,0,.4);}
.onboarding-card{max-width:400px; text-align:center;}
.onboarding-icon{font-size:40px; line-height:1; margin-bottom:6px;}
.onboarding-dots{display:flex; justify-content:center; gap:6px; margin:14px 0;}
.onboarding-dot{width:7px; height:7px; border-radius:50%; background:var(--line);}
.onboarding-dot.active{background:var(--accent);}
.onboarding-nav{display:flex; align-items:center; justify-content:space-between; gap:10px;}
.onboarding-nav .auth-link{margin:0;}
.onboarding-nav-right{display:flex; align-items:center; gap:8px;}
.onboarding-nav-right .auth-submit{margin:0; width:auto; padding:9px 18px;}

/* ============================================================
   SETTINGS-ONLY VIEW (settings.html)
   That page shares this exact stylesheet and app shell with
   sign-in.html/index.html (see settings.html's own inline script for
   why) but should show only the Settings section — no month picker,
   overview stats, debt/savings pages, or the motivational quote, all
   of which belong to the tracker itself. Rather than removing those
   elements from the DOM (many of app.js's render functions write into
   them unconditionally and aren't null-guarded), settings.html tags
   <body> with this class and everything tracker-
   specific is just hidden here; app.js keeps rendering into it same
   as always, harmlessly, off-screen.
   ============================================================ */
body.settings-only-view .brand-row .tag,
body.settings-only-view .meta-chips,
body.settings-only-view .overall,
body.settings-only-view .profile-banner,
body.settings-only-view .month-bar,
body.settings-only-view .page-nav,
body.settings-only-view #page-overview,
body.settings-only-view #page-income,
body.settings-only-view #page-debts,
body.settings-only-view #page-gifts,
body.settings-only-view #page-savings,
body.settings-only-view #page-expenses,
body.settings-only-view #page-xp,
body.settings-only-view #page-whatsnew,
body.settings-only-view .app-shell > footer{
  display:none !important;
}
