/* ── Google Fonts ────────────────────────────────────────────────────────── */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600&display=swap');

/* ── Theme variables ─────────────────────────────────────────────────────── */
:root {
  --bg:            #f8fafc;
  --surface:       #ffffff;
  --surface2:      #f9fafb;
  --surface3:      #f1f5f9;
  /* Highlighted rows — the active trip, an interest payment due soon, a report
     section header. travel.js, insights.js and reports.js have asked for this
     for a long time and no theme defined it, so the highlights resolved to
     nothing and those rows looked ordinary.
     Defining it as --surface2 was not enough: that is the zebra stripe's own
     colour, so a highlighted row came out identical to every second ordinary
     row. It has to be a colour the striping does not already use.
     Declared once here rather than per theme — custom properties substitute at
     use, so this picks up each theme's own emphasis colour. */
  --bg-alt:        var(--primary-light);
  --border:        #e5e7eb;
  --border-light:  #f3f4f6;
  --text:          #111827;
  --text-muted:    #6b7280;
  --text-label:    #4b5563;
  --sidebar-from:  #1e3a5f;
  --sidebar-to:    #0f172a;
  --sidebar-text:  rgba(255,255,255,.88);
  --sidebar-muted: rgba(255,255,255,.4);
  --sidebar-hover: rgba(255,255,255,.1);
  --sidebar-active:#3b82f6;
  --primary:       #3b82f6;
  --primary-light: #eff6ff;
  --primary-dark:  #2563eb;
  --success:       #10b981;
  --success-light: #ecfdf5;
  --success-dark:  #059669;
  --danger:        #ef4444;
  --danger-light:  #fef2f2;
  --warning:       #f59e0b;
  --warning-light: #fffbeb;
  --purple:        #8b5cf6;
  --purple-light:  #f5f3ff;
  --teal:          #14b8a6;
  --teal-light:    #f0fdfa;
  --pink:          #ec4899;
  --shadow-sm:     0 1px 2px rgba(0,0,0,.04), 0 1px 3px rgba(0,0,0,.03);
  --shadow:        0 4px 6px -1px rgba(0,0,0,.06), 0 2px 4px -2px rgba(0,0,0,.04);
  --shadow-lg:     0 10px 20px -5px rgba(0,0,0,.07), 0 6px 8px -4px rgba(0,0,0,.03);
  --shadow-xl:     0 20px 40px -10px rgba(0,0,0,.08);
  --radius:        16px;
  --radius-sm:     11px;
  --radius-xs:     6px;
  --th-bg:         #f9fafb;
  --th-color:      #6b7280;
  --progress-bg:   #e5e7eb;
  --input-bg:      #ffffff;
  --input-border:  #e5e7eb;
  --card-glow:     rgba(59,130,246,.05);
  --gradient-1:    linear-gradient(135deg, #3b82f6, #8b5cf6);
  --gradient-2:    linear-gradient(135deg, #10b981, #14b8a6);
  --gradient-3:    linear-gradient(135deg, #f59e0b, #ef4444);
  /* Density custom properties (overridden by JS) */
  --page-padding:  2.25rem 2.5rem;
  --card-padding:  1.35rem 1.4rem;
  --panel-padding: 1.75rem;
  --cell-padding:  .85rem 1.1rem;
  --grid-gap:      1.1rem;
}

[data-theme="dark"] {
  --bg:            #0a0f1e;
  --surface:       #1c2740;
  --surface2:      #26324f;
  --surface3:      #111a2e;
  --border:        #37476a;
  --border-light:  #26324f;
  --text:          #f1f5f9;
  --text-muted:    #94a3b8;
  --text-label:    #cbd5e1;
  --sidebar-from:  #0a0f1e;
  --sidebar-to:    #050810;
  --sidebar-text:  rgba(255,255,255,.85);
  --sidebar-muted: rgba(255,255,255,.3);
  --sidebar-hover: rgba(255,255,255,.07);
  --sidebar-active:#3b82f6;
  --primary:       #60a5fa;
  --primary-light: rgba(96,165,250,.15);
  --primary-dark:  #3b82f6;
  --success:       #34d399;
  --success-light: rgba(52,211,153,.15);
  --success-dark:  #10b981;
  --danger:        #f87171;
  --danger-light:  rgba(248,113,113,.15);
  --warning:       #fbbf24;
  --warning-light: rgba(251,191,36,.15);
  --purple:        #a78bfa;
  --purple-light:  rgba(167,139,250,.15);
  --teal:          #2dd4bf;
  --teal-light:    rgba(45,212,191,.15);
  --shadow-sm:     0 1px 3px rgba(0,0,0,.4);
  --shadow:        0 4px 6px -1px rgba(0,0,0,.5);
  --shadow-lg:     0 10px 25px -5px rgba(0,0,0,.6);
  --shadow-xl:     0 20px 40px -10px rgba(0,0,0,.7);
  --th-bg:         #26324f;
  --th-color:      #94a3b8;
  --progress-bg:   #37476a;
  --input-bg:      #1c2740;
  --input-border:  #37476a;
  --card-glow:     rgba(96,165,250,.06);
  --gradient-1:    linear-gradient(135deg, #3b82f6, #8b5cf6);
  --gradient-2:    linear-gradient(135deg, #10b981, #14b8a6);
  --gradient-3:    linear-gradient(135deg, #f59e0b, #ef4444);
}

[data-theme="ocean"] {
  --bg:            #e8f4fc;
  --surface:       #ffffff;
  --surface2:      #f0f9ff;
  --surface3:      #e0f2fe;
  --border:        #bae6fd;
  --border-light:  #e0f2fe;
  --text:          #0c4a6e;
  --text-muted:    #0369a1;
  --text-label:    #075985;
  --sidebar-from:  #0369a1;
  --sidebar-to:    #0c4a6e;
  --sidebar-text:  rgba(255,255,255,.9);
  --sidebar-muted: rgba(255,255,255,.4);
  --sidebar-hover: rgba(255,255,255,.12);
  --sidebar-active:#38bdf8;
  --primary:       #0284c7;
  --primary-light: #e0f2fe;
  --primary-dark:  #0369a1;
  --success:       #059669;
  --success-light: #d1fae5;
  --success-dark:  #047857;
  --danger:        #dc2626;
  --danger-light:  #fee2e2;
  --warning:       #d97706;
  --warning-light: #fef3c7;
  --purple:        #7c3aed;
  --purple-light:  #ede9fe;
  --teal:          #0891b2;
  --teal-light:    #cffafe;
  --shadow-sm:     0 1px 3px rgba(3,105,161,.08);
  --shadow:        0 4px 6px -1px rgba(3,105,161,.1);
  --shadow-lg:     0 10px 25px -5px rgba(3,105,161,.12);
  --shadow-xl:     0 20px 40px -10px rgba(3,105,161,.15);
  --th-bg:         #e0f2fe;
  --th-color:      #0369a1;
  --progress-bg:   #bae6fd;
  --input-bg:      #ffffff;
  --input-border:  #bae6fd;
  --card-glow:     rgba(2,132,199,.06);
  --gradient-1:    linear-gradient(135deg, #0284c7, #0891b2);
  --gradient-2:    linear-gradient(135deg, #059669, #0891b2);
  --gradient-3:    linear-gradient(135deg, #d97706, #dc2626);
}

[data-theme="forest"] {
  --bg:            #ecfdf5;
  --surface:       #ffffff;
  --surface2:      #f0fdf4;
  --surface3:      #dcfce7;
  --border:        #bbf7d0;
  --border-light:  #dcfce7;
  --text:          #14532d;
  --text-muted:    #166534;
  --text-label:    #15803d;
  --sidebar-from:  #166534;
  --sidebar-to:    #14532d;
  --sidebar-text:  rgba(255,255,255,.9);
  --sidebar-muted: rgba(255,255,255,.4);
  --sidebar-hover: rgba(255,255,255,.12);
  --sidebar-active:#4ade80;
  --primary:       #16a34a;
  --primary-light: #dcfce7;
  --primary-dark:  #15803d;
  --success:       #15803d;
  --success-light: #d1fae5;
  --success-dark:  #166534;
  --danger:        #dc2626;
  --danger-light:  #fee2e2;
  --warning:       #d97706;
  --warning-light: #fef3c7;
  --purple:        #7c3aed;
  --purple-light:  #ede9fe;
  --teal:          #0d9488;
  --teal-light:    #ccfbf1;
  --shadow-sm:     0 1px 3px rgba(22,101,52,.06);
  --shadow:        0 4px 6px -1px rgba(22,101,52,.08);
  --shadow-lg:     0 10px 25px -5px rgba(22,101,52,.1);
  --shadow-xl:     0 20px 40px -10px rgba(22,101,52,.12);
  --th-bg:         #dcfce7;
  --th-color:      #166534;
  --progress-bg:   #bbf7d0;
  --input-bg:      #ffffff;
  --input-border:  #bbf7d0;
  --card-glow:     rgba(22,163,74,.06);
  --gradient-1:    linear-gradient(135deg, #16a34a, #0d9488);
  --gradient-2:    linear-gradient(135deg, #15803d, #0d9488);
  --gradient-3:    linear-gradient(135deg, #d97706, #dc2626);
}

[data-theme="sunset"] {
  --bg:            #fff7ed;
  --surface:       #ffffff;
  --surface2:      #fffbf5;
  --surface3:      #ffedd5;
  --border:        #fed7aa;
  --border-light:  #ffedd5;
  --text:          #431407;
  --text-muted:    #9a3412;
  --text-label:    #c2410c;
  --sidebar-from:  #c2410c;
  --sidebar-to:    #7c2d12;
  --sidebar-text:  rgba(255,255,255,.9);
  --sidebar-muted: rgba(255,255,255,.4);
  --sidebar-hover: rgba(255,255,255,.12);
  --sidebar-active:#fb923c;
  --primary:       #ea580c;
  --primary-light: #ffedd5;
  --primary-dark:  #c2410c;
  --success:       #16a34a;
  --success-light: #d1fae5;
  --success-dark:  #15803d;
  --danger:        #dc2626;
  --danger-light:  #fee2e2;
  --warning:       #d97706;
  --warning-light: #fef3c7;
  --purple:        #7c3aed;
  --purple-light:  #ede9fe;
  --teal:          #0d9488;
  --teal-light:    #ccfbf1;
  --shadow-sm:     0 1px 3px rgba(194,65,12,.06);
  --shadow:        0 4px 6px -1px rgba(194,65,12,.08);
  --shadow-lg:     0 10px 25px -5px rgba(194,65,12,.1);
  --shadow-xl:     0 20px 40px -10px rgba(194,65,12,.12);
  --th-bg:         #ffedd5;
  --th-color:      #9a3412;
  --progress-bg:   #fed7aa;
  --input-bg:      #ffffff;
  --input-border:  #fed7aa;
  --card-glow:     rgba(234,88,12,.06);
  --gradient-1:    linear-gradient(135deg, #ea580c, #d97706);
  --gradient-2:    linear-gradient(135deg, #16a34a, #0d9488);
  --gradient-3:    linear-gradient(135deg, #d97706, #dc2626);
}

/* ── NEW THEMES ──────────────────────────────────────────────────────────── */

[data-theme="midnight"] {
  --bg:            #0f0f23;
  --surface:       #26265a;
  --surface2:      #30306e;
  --surface3:      #181840;
  --border:        #44447e;
  --border-light:  #30306e;
  --text:          #e8e8f0;
  --text-muted:    #9898c8;
  --text-label:    #b8b8d8;
  --sidebar-from:  #1a1a3e;
  --sidebar-to:    #0a0a20;
  --sidebar-text:  rgba(255,255,255,.85);
  --sidebar-muted: rgba(255,255,255,.3);
  --sidebar-hover: rgba(255,255,255,.08);
  --sidebar-active:#818cf8;
  --primary:       #818cf8;
  --primary-light: rgba(129,140,248,.15);
  --primary-dark:  #6366f1;
  --success:       #34d399;
  --success-light: rgba(52,211,153,.15);
  --success-dark:  #10b981;
  --danger:        #fb7185;
  --danger-light:  rgba(251,113,133,.15);
  --warning:       #fbbf24;
  --warning-light: rgba(251,191,36,.15);
  --purple:        #c084fc;
  --purple-light:  rgba(192,132,252,.15);
  --teal:          #2dd4bf;
  --teal-light:    rgba(45,212,191,.15);
  --pink:          #f472b6;
  --shadow-sm:     0 1px 3px rgba(0,0,0,.5);
  --shadow:        0 4px 8px rgba(0,0,0,.5);
  --shadow-lg:     0 10px 25px rgba(0,0,0,.6);
  --shadow-xl:     0 20px 40px rgba(0,0,0,.7);
  --th-bg:         #30306e;
  --th-color:      #9898c8;
  --progress-bg:   #44447e;
  --input-bg:      #26265a;
  --input-border:  #44447e;
  --card-glow:     rgba(129,140,248,.08);
  --gradient-1:    linear-gradient(135deg, #818cf8, #c084fc);
  --gradient-2:    linear-gradient(135deg, #34d399, #2dd4bf);
  --gradient-3:    linear-gradient(135deg, #fbbf24, #fb7185);
}

[data-theme="rose"] {
  --bg:            #fff1f2;
  --surface:       #ffffff;
  --surface2:      #fff5f6;
  --surface3:      #ffe4e6;
  --border:        #fecdd3;
  --border-light:  #ffe4e6;
  --text:          #4c0519;
  --text-muted:    #be123c;
  --text-label:    #9f1239;
  --sidebar-from:  #be123c;
  --sidebar-to:    #881337;
  --sidebar-text:  rgba(255,255,255,.9);
  --sidebar-muted: rgba(255,255,255,.4);
  --sidebar-hover: rgba(255,255,255,.12);
  --sidebar-active:#fb7185;
  --primary:       #e11d48;
  --primary-light: #ffe4e6;
  --primary-dark:  #be123c;
  --success:       #16a34a;
  --success-light: #d1fae5;
  --success-dark:  #15803d;
  --danger:        #dc2626;
  --danger-light:  #fee2e2;
  --warning:       #d97706;
  --warning-light: #fef3c7;
  --purple:        #7c3aed;
  --purple-light:  #ede9fe;
  --teal:          #0d9488;
  --teal-light:    #ccfbf1;
  --pink:          #ec4899;
  --shadow-sm:     0 1px 3px rgba(190,18,60,.06);
  --shadow:        0 4px 6px rgba(190,18,60,.08);
  --shadow-lg:     0 10px 25px rgba(190,18,60,.1);
  --shadow-xl:     0 20px 40px rgba(190,18,60,.12);
  --th-bg:         #ffe4e6;
  --th-color:      #be123c;
  --progress-bg:   #fecdd3;
  --input-bg:      #ffffff;
  --input-border:  #fecdd3;
  --card-glow:     rgba(225,29,72,.06);
  --gradient-1:    linear-gradient(135deg, #e11d48, #ec4899);
  --gradient-2:    linear-gradient(135deg, #16a34a, #0d9488);
  --gradient-3:    linear-gradient(135deg, #d97706, #dc2626);
}

[data-theme="lavender"] {
  --bg:            #f5f3ff;
  --surface:       #ffffff;
  --surface2:      #faf8ff;
  --surface3:      #ede9fe;
  --border:        #ddd6fe;
  --border-light:  #ede9fe;
  --text:          #2e1065;
  --text-muted:    #6d28d9;
  --text-label:    #7c3aed;
  --sidebar-from:  #6d28d9;
  --sidebar-to:    #4c1d95;
  --sidebar-text:  rgba(255,255,255,.9);
  --sidebar-muted: rgba(255,255,255,.4);
  --sidebar-hover: rgba(255,255,255,.12);
  --sidebar-active:#a78bfa;
  --primary:       #7c3aed;
  --primary-light: #ede9fe;
  --primary-dark:  #6d28d9;
  --success:       #16a34a;
  --success-light: #d1fae5;
  --success-dark:  #15803d;
  --danger:        #dc2626;
  --danger-light:  #fee2e2;
  --warning:       #d97706;
  --warning-light: #fef3c7;
  --purple:        #7c3aed;
  --purple-light:  #ede9fe;
  --teal:          #0d9488;
  --teal-light:    #ccfbf1;
  --pink:          #ec4899;
  --shadow-sm:     0 1px 3px rgba(109,40,217,.06);
  --shadow:        0 4px 6px rgba(109,40,217,.08);
  --shadow-lg:     0 10px 25px rgba(109,40,217,.1);
  --shadow-xl:     0 20px 40px rgba(109,40,217,.12);
  --th-bg:         #ede9fe;
  --th-color:      #6d28d9;
  --progress-bg:   #ddd6fe;
  --input-bg:      #ffffff;
  --input-border:  #ddd6fe;
  --card-glow:     rgba(124,58,237,.06);
  --gradient-1:    linear-gradient(135deg, #7c3aed, #a78bfa);
  --gradient-2:    linear-gradient(135deg, #16a34a, #0d9488);
  --gradient-3:    linear-gradient(135deg, #d97706, #dc2626);
}

[data-theme="aurora"] {
  --bg:            #071a1f;
  --surface:       #0f2b33;
  --surface2:      #143840;
  --surface3:      #0a2129;
  --border:        #1f4d57;
  --border-light:  #143840;
  --text:          #e0f7fa;
  --text-muted:    #7dd3d8;
  --text-label:    #a5e8ec;
  --sidebar-from:  #0a3d42;
  --sidebar-to:    #051f22;
  --sidebar-text:  rgba(255,255,255,.88);
  --sidebar-muted: rgba(255,255,255,.35);
  --sidebar-hover: rgba(255,255,255,.1);
  --sidebar-active:#2dd4bf;
  --primary:       #22d3ee;
  --primary-light: rgba(34,211,238,.15);
  --primary-dark:  #06b6d4;
  --success:       #34d399;
  --success-light: rgba(52,211,153,.15);
  --success-dark:  #10b981;
  --danger:        #f87171;
  --danger-light:  rgba(248,113,113,.15);
  --warning:       #fbbf24;
  --warning-light: rgba(251,191,36,.15);
  --purple:        #c084fc;
  --purple-light:  rgba(192,132,252,.15);
  --teal:          #2dd4bf;
  --teal-light:    rgba(45,212,191,.15);
  --shadow-sm:     0 1px 3px rgba(0,0,0,.4);
  --shadow:        0 4px 8px rgba(0,0,0,.5);
  --shadow-lg:     0 10px 25px rgba(0,0,0,.6);
  --shadow-xl:     0 20px 40px rgba(0,0,0,.7);
  --th-bg:         #143840;
  --th-color:      #7dd3d8;
  --progress-bg:   #1f4d57;
  --input-bg:      #0f2b33;
  --input-border:  #1f4d57;
  --card-glow:     rgba(34,211,238,.08);
  --gradient-1:    linear-gradient(135deg, #22d3ee, #a78bfa);
  --gradient-2:    linear-gradient(135deg, #34d399, #2dd4bf);
  --gradient-3:    linear-gradient(135deg, #fbbf24, #f87171);
}

[data-theme="coffee"] {
  --bg:            #faf6f1;
  --surface:       #ffffff;
  --surface2:      #f5efe6;
  --surface3:      #ede0d1;
  --border:        #ddc9ae;
  --border-light:  #ede0d1;
  --text:          #3e2723;
  --text-muted:    #6d4c41;
  --text-label:    #5d4037;
  --sidebar-from:  #4e342e;
  --sidebar-to:    #2c1a17;
  --sidebar-text:  rgba(255,255,255,.9);
  --sidebar-muted: rgba(255,255,255,.4);
  --sidebar-hover: rgba(255,255,255,.12);
  --sidebar-active:#d7a86e;
  --primary:       #8d5b3f;
  --primary-light: #ede0d1;
  --primary-dark:  #6d4530;
  --success:       #16a34a;
  --success-light: #d1fae5;
  --success-dark:  #15803d;
  --danger:        #dc2626;
  --danger-light:  #fee2e2;
  --warning:       #d97706;
  --warning-light: #fef3c7;
  --purple:        #7c3aed;
  --purple-light:  #ede9fe;
  --teal:          #0d9488;
  --teal-light:    #ccfbf1;
  --shadow-sm:     0 1px 3px rgba(93,64,55,.06);
  --shadow:        0 4px 6px rgba(93,64,55,.08);
  --shadow-lg:     0 10px 25px rgba(93,64,55,.1);
  --shadow-xl:     0 20px 40px rgba(93,64,55,.12);
  --th-bg:         #ede0d1;
  --th-color:      #6d4c41;
  --progress-bg:   #ddc9ae;
  --input-bg:      #ffffff;
  --input-border:  #ddc9ae;
  --card-glow:     rgba(141,91,63,.06);
  --gradient-1:    linear-gradient(135deg, #8d5b3f, #d7a86e);
  --gradient-2:    linear-gradient(135deg, #16a34a, #0d9488);
  --gradient-3:    linear-gradient(135deg, #d97706, #dc2626);
}

[data-theme="slate"] {
  --bg:            #0d1117;
  --surface:       #161b22;
  --surface2:      #1c2128;
  --surface3:      #21262d;
  --border:        #30363d;
  --border-light:  #21262d;
  --text:          #e6edf3;
  --text-muted:    #8b949e;
  --text-label:    #c9d1d9;
  --sidebar-from:  #161b22;
  --sidebar-to:    #010409;
  --sidebar-text:  rgba(255,255,255,.88);
  --sidebar-muted: rgba(255,255,255,.35);
  --sidebar-hover: rgba(255,255,255,.08);
  --sidebar-active:#58a6ff;
  --primary:       #58a6ff;
  --primary-light: rgba(88,166,255,.15);
  --primary-dark:  #388bfd;
  --success:       #3fb950;
  --success-light: rgba(63,185,80,.15);
  --success-dark:  #2ea043;
  --danger:        #f85149;
  --danger-light:  rgba(248,81,73,.15);
  --warning:       #d29922;
  --warning-light: rgba(210,153,34,.15);
  --purple:        #bc8cff;
  --purple-light:  rgba(188,140,255,.15);
  --teal:          #39c5cf;
  --teal-light:    rgba(57,197,207,.15);
  --shadow-sm:     0 1px 3px rgba(0,0,0,.5);
  --shadow:        0 4px 8px rgba(0,0,0,.5);
  --shadow-lg:     0 10px 25px rgba(0,0,0,.6);
  --shadow-xl:     0 20px 40px rgba(0,0,0,.7);
  --th-bg:         #1c2128;
  --th-color:      #8b949e;
  --progress-bg:   #30363d;
  --input-bg:      #0d1117;
  --input-border:  #30363d;
  --card-glow:     rgba(88,166,255,.08);
  --gradient-1:    linear-gradient(135deg, #58a6ff, #bc8cff);
  --gradient-2:    linear-gradient(135deg, #3fb950, #39c5cf);
  --gradient-3:    linear-gradient(135deg, #d29922, #f85149);
}

/* ── Base ────────────────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; }
body {
  font-family: 'Inter', system-ui, -apple-system, sans-serif;
  background:
    radial-gradient(ellipse 1200px 600px at 15% -10%, var(--card-glow), transparent 60%),
    radial-gradient(ellipse 900px 500px at 100% 0%, var(--card-glow), transparent 55%),
    var(--bg);
  background-attachment: fixed;
  color: var(--text);
  min-height: 100vh;
  font-size: 14.5px;
  line-height: 1.65;
  transition: background-color .3s ease, color .3s ease;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  letter-spacing: -0.01em;
}

/* ── Layout ──────────────────────────────────────────────────────────────── */
.app-layout { display: flex; min-height: 100vh; }

/* ── Sidebar ─────────────────────────────────────────────────────────────── */
.sidebar {
  width: 260px;
  min-width: 260px;
  background: linear-gradient(180deg, var(--sidebar-from) 0%, var(--sidebar-to) 100%);
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
  overflow-x: hidden;
  scrollbar-width: thin;
  scrollbar-color: rgba(255,255,255,.1) transparent;
  box-shadow: 4px 0 24px rgba(0,0,0,.08);
}

.sidebar-header {
  padding: 1.5rem 1.25rem 1.25rem;
  border-bottom: 1px solid rgba(255,255,255,.08);
  position: relative;
}

.sidebar-logo {
  font-size: 1.15rem;
  font-weight: 800;
  color: white;
  display: flex;
  align-items: center;
  gap: .6rem;
  margin-bottom: 1rem;
  letter-spacing: -.01em;
}

.sidebar-logo .logo-icon {
  width: 36px;
  height: 36px;
  background: linear-gradient(135deg, #3b82f6, #8b5cf6);
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.1rem;
  flex-shrink: 0;
  box-shadow: 0 4px 15px rgba(59,130,246,.4);
}

.theme-switcher {
  display: flex;
  gap: .35rem;
  flex-wrap: wrap;
}

.theme-btn {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 2px solid rgba(255,255,255,.2);
  cursor: pointer;
  transition: all .2s ease;
  position: relative;
}
.theme-btn:hover { transform: scale(1.3); border-color: white; box-shadow: 0 0 12px rgba(255,255,255,.3); }
.theme-btn[data-theme="light"]    { background: linear-gradient(135deg,#f1f5f9,#e2e8f0); }
.theme-btn[data-theme="dark"]     { background: linear-gradient(135deg,#1e293b,#0f172a); }
.theme-btn[data-theme="ocean"]    { background: linear-gradient(135deg,#0284c7,#0c4a6e); }
.theme-btn[data-theme="forest"]   { background: linear-gradient(135deg,#16a34a,#14532d); }
.theme-btn[data-theme="sunset"]   { background: linear-gradient(135deg,#ea580c,#7c2d12); }
.theme-btn[data-theme="midnight"] { background: linear-gradient(135deg,#818cf8,#1a1a3e); }
.theme-btn[data-theme="rose"]     { background: linear-gradient(135deg,#fb7185,#881337); }
.theme-btn[data-theme="lavender"] { background: linear-gradient(135deg,#a78bfa,#4c1d95); }
.theme-btn[data-theme="aurora"]   { background: linear-gradient(135deg,#22d3ee,#a78bfa); }
.theme-btn[data-theme="coffee"]   { background: linear-gradient(135deg,#d7a86e,#4e342e); }
.theme-btn[data-theme="slate"]    { background: linear-gradient(135deg,#58a6ff,#0d1117); }

.theme-btn-add {
  width: 22px; height: 22px; border-radius: 50%;
  border: 2px dashed rgba(255,255,255,.4);
  display: flex; align-items: center; justify-content: center;
  font-size: .8rem; line-height: 1; color: rgba(255,255,255,.6);
  cursor: pointer; transition: all .2s ease; flex-shrink: 0;
}
.theme-btn-add:hover { transform: scale(1.3); border-color: white; color: white; }

.theme-btn-remove {
  display: none; position: absolute; top: -6px; right: -6px;
  width: 14px; height: 14px; border-radius: 50%;
  background: var(--danger, #ef4444); color: #fff;
  font-size: .6rem; line-height: 14px; text-align: center;
  cursor: pointer;
}
.theme-btn.custom-theme:hover .theme-btn-remove { display: block; }

.theme-add-popover {
  position: absolute; top: 100%; left: 1.25rem; margin-top: .5rem;
  z-index: 500; width: 220px; background: var(--surface); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg); padding: .85rem; text-align: left;
}
.theme-add-popover .field { margin-bottom: .55rem; }
.theme-add-popover label { font-size: .7rem; color: var(--text-muted); display: block; margin-bottom: .2rem; }
.theme-add-popover input[type="text"] {
  width: 100%; padding: .4rem .55rem; border: 1px solid var(--input-border);
  border-radius: 6px; background: var(--input-bg); color: var(--text); font-size: .82rem;
}
.theme-add-colors { display: grid; grid-template-columns: 1fr 1fr; gap: .5rem; }
.theme-add-popover input[type="color"] { width: 100%; height: 28px; border: 1px solid var(--input-border); border-radius: 6px; padding: 2px; background: var(--input-bg); cursor: pointer; }
.theme-add-btns { display: flex; justify-content: flex-end; gap: .4rem; margin-top: .5rem; }

.sidebar-nav { padding: .75rem 0 1rem; flex: 1; }
.nav-group { margin-bottom: .15rem; }

.nav-group-label {
  font-size: .62rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .14em;
  color: var(--sidebar-muted);
  padding: 1rem 1.25rem .4rem;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  user-select: none;
}
.nav-group-chevron {
  font-size: .65rem;
  transition: transform .2s ease;
  opacity: .7;
}
@media (min-width: 769px) {
  .nav-group.collapsed .nav-group-chevron { transform: rotate(-90deg); }
  .nav-group.collapsed .nav-group-items { display: none; }
}

.nav-btn {
  display: flex;
  align-items: center;
  gap: .7rem;
  width: calc(100% - .75rem);
  text-align: left;
  background: none;
  border: none;
  color: var(--sidebar-text);
  padding: .65rem 1.25rem;
  font-size: .85rem;
  font-family: inherit;
  cursor: pointer;
  border-radius: 0 10px 10px 0;
  transition: all .2s ease;
  position: relative;
  margin-right: .75rem;
}
.nav-btn .nav-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  font-size: .95rem;
  flex-shrink: 0;
  font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", "Twemoji Mozilla", sans-serif;
  text-align: center;
  line-height: 1;
}
.nav-btn:hover { background: var(--sidebar-hover); color: white; }
.nav-btn:hover .nav-icon { transform: scale(1.12); }
.nav-btn .nav-icon { transition: transform .2s cubic-bezier(.2,.8,.2,1); }
a.nav-btn, a.nav-btn:visited, a.nav-btn:link, a.nav-btn:active { text-decoration: none; color: rgba(255,255,255,.85); }
.nav-btn.active {
  background: linear-gradient(90deg, rgba(255,255,255,.16), rgba(255,255,255,.04));
  color: white;
  font-weight: 600;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.06);
}
.nav-btn.active::before {
  content: '';
  position: absolute;
  left: 0; top: 4px; bottom: 4px;
  width: 3px;
  background: var(--sidebar-active);
  border-radius: 0 3px 3px 0;
  box-shadow: 0 0 8px var(--sidebar-active);
}

/* ── Main content ────────────────────────────────────────────────────────── */
.main-content { flex: 1; overflow-y: auto; min-width: 0; width: 100%; }

.page { display: none; padding: var(--page-padding, 2.25rem 2.5rem); animation: pageIn .3s ease; }
.page.active { display: block; }

@keyframes pageIn {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: none; }
}

/* ── Page header ─────────────────────────────────────────────────────────── */
.page-title {
  font-size: 1.85rem;
  font-weight: 800;
  letter-spacing: -.03em;
  background: var(--gradient-1);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  display: inline-block;
  padding-bottom: .1rem;
}
.page-subtitle {
  font-size: .88rem;
  color: var(--text-muted);
  margin-top: .35rem;
  line-height: 1.5;
}

h2 {
  font-size: 1rem;
  font-weight: 800;
  color: var(--text);
  margin-bottom: 1.15rem;
  letter-spacing: -.01em;
}

/* ── Stat cards ──────────────────────────────────────────────────────────── */
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 1.1rem;
  margin-bottom: 2rem;
}

.card {
  background: var(--surface);
  border-radius: var(--radius);
  padding: 1.4rem 1.5rem;
  box-shadow: var(--shadow-sm), 0 0 0 1px var(--border-light);
  border: 1px solid var(--border);
  transition: transform .25s cubic-bezier(.2,.8,.2,1), box-shadow .25s ease, border-color .25s ease;
  position: relative;
  overflow: hidden;
}
.card:hover {
  box-shadow: var(--shadow-lg), 0 0 0 1px var(--primary);
  transform: translateY(-3px);
  border-color: transparent;
}

.card .lbl {
  font-size: .7rem;
  font-weight: 600;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: .07em;
  margin-bottom: .45rem;
}
.card .val {
  font-size: 1.5rem;
  font-weight: 800;
  line-height: 1.2;
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
}

/* Card colour accents — top border + a faint tinted wash for personality */
.card-green  { border-top: 3px solid var(--success) !important; background: linear-gradient(180deg, var(--success-light) 0%, var(--surface) 55%) !important; }
.card-blue   { border-top: 3px solid var(--primary) !important; background: linear-gradient(180deg, var(--primary-light) 0%, var(--surface) 55%) !important; }
.card-orange { border-top: 3px solid var(--warning) !important; background: linear-gradient(180deg, var(--warning-light) 0%, var(--surface) 55%) !important; }
.card-red    { border-top: 3px solid var(--danger)  !important; background: linear-gradient(180deg, var(--danger-light)  0%, var(--surface) 55%) !important; }
.card-purple { border-top: 3px solid var(--purple)  !important; background: linear-gradient(180deg, var(--purple-light)  0%, var(--surface) 55%) !important; }
.card-teal   { border-top: 3px solid var(--teal)    !important; background: linear-gradient(180deg, var(--teal-light)    0%, var(--surface) 55%) !important; }

/* Colour helpers */
.green  { color: var(--success); }
.blue   { color: var(--primary); }
.orange { color: var(--warning); }
.purple { color: var(--purple); }
.red    { color: var(--danger); }
.teal   { color: var(--teal); }
.pink   { color: var(--pink); }
.pl-pos { color: var(--success); font-weight: 600; }
.pl-neg { color: var(--danger);  font-weight: 600; }

/* ── Panel ───────────────────────────────────────────────────────────────── */
.panel {
  background: var(--surface);
  border-radius: var(--radius);
  padding: 1.75rem;
  box-shadow: var(--shadow-sm), 0 0 0 1px var(--border-light);
  margin-bottom: 1.75rem;
  border: 1px solid var(--border);
  transition: box-shadow .25s ease, border-color .25s ease;
  overflow-x: auto;
}
.panel:hover { box-shadow: var(--shadow); border-color: var(--border); }

.panel > h2:first-child {
  font-size: .8rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .1em;
  color: var(--text-muted);
  margin-bottom: 1.5rem;
  padding-bottom: .85rem;
  border-bottom: 2px solid var(--border-light);
  position: relative;
}
.panel > h2:first-child::after {
  content: '';
  position: absolute;
  left: 0; bottom: -2px;
  width: 46px;
  height: 2px;
  background: var(--gradient-1);
  border-radius: 2px;
}

/* ── Form ────────────────────────────────────────────────────────────────── */
.row {
  display: flex;
  gap: 1rem;
  flex-wrap: wrap;
  align-items: flex-end;
  margin-bottom: 1.25rem;
}

.field {
  display: flex;
  flex-direction: column;
  gap: .4rem;
  min-width: 130px;
}

.field label {
  font-size: .72rem;
  font-weight: 600;
  color: var(--text-label);
  text-transform: uppercase;
  letter-spacing: .05em;
}

.field input, .field select {
  padding: .6rem .9rem;
  border: 1.5px solid var(--input-border);
  border-radius: var(--radius-sm);
  font-size: .9rem;
  font-family: inherit;
  width: 100%;
  background: var(--input-bg);
  color: var(--text);
  transition: all .2s ease;
  outline: none;
}
.field input:hover, .field select:hover {
  border-color: var(--text-muted);
}
.field input:focus, .field select:focus {
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--card-glow), 0 0 0 1px var(--primary);
}
.field input::placeholder { color: var(--text-muted); opacity: .55; }

/* ── Buttons ─────────────────────────────────────────────────────────────── */
.btn {
  padding: .6rem 1.25rem;
  border: none;
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-size: .85rem;
  font-weight: 600;
  font-family: inherit;
  transition: all .2s ease;
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  white-space: nowrap;
  letter-spacing: .01em;
  position: relative;
  overflow: hidden;
}

.btn::after {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(255,255,255,.12);
  opacity: 0;
  transition: opacity .15s;
}
.btn:active::after { opacity: 1; }
.btn:active { transform: scale(.97); }

.btn-blue {
  background: linear-gradient(135deg, var(--primary), var(--primary-dark));
  color: white;
  box-shadow: 0 2px 8px color-mix(in srgb, var(--primary) 35%, transparent);
}
.btn-blue:hover { box-shadow: 0 6px 18px color-mix(in srgb, var(--primary) 45%, transparent); transform: translateY(-1px); }

.btn-green {
  background: linear-gradient(135deg, var(--success), var(--success-dark));
  color: white;
  box-shadow: 0 2px 8px color-mix(in srgb, var(--success) 35%, transparent);
}
.btn-green:hover { box-shadow: 0 6px 18px color-mix(in srgb, var(--success) 45%, transparent); transform: translateY(-1px); }

.btn-gray { background: var(--text-muted); color: white; }
.btn-gray:hover { opacity: .85; transform: translateY(-1px); }

.btn-outline {
  background: transparent;
  border: 1.5px solid var(--border);
  color: var(--text);
}
.btn-outline:hover { border-color: var(--primary); color: var(--primary); background: var(--card-glow); transform: translateY(-1px); }

.btn-red { background: none; border: none; color: var(--danger); cursor: pointer; font-size: 1rem; padding: .25rem .45rem; border-radius: var(--radius-xs); transition: all .15s; }
.btn-red:hover { background: var(--danger-light); }

.btn-sm { padding: .3rem .7rem; font-size: .78rem; }

/* ── Table ───────────────────────────────────────────────────────────────── */
.table-wrap { overflow-x: auto; border-radius: var(--radius-sm); }

table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: .86rem; }

thead tr { border-bottom: none; }

th {
  background: var(--th-bg);
  color: var(--th-color);
  font-size: .68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .07em;
  padding: .85rem 1.1rem;
  text-align: left;
  white-space: nowrap;
  border-bottom: 2px solid var(--primary);
}
th:first-child { border-radius: var(--radius-sm) 0 0 0; }
th:last-child  { border-radius: 0 var(--radius-sm) 0 0; }

td {
  padding: .85rem 1.1rem;
  border-bottom: 1px solid var(--border-light);
  color: var(--text);
  vertical-align: middle;
  max-width: 220px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  transition: background .15s ease;
}
td:hover { white-space: normal; overflow: visible; }

tbody tr { transition: all .15s ease; }

/* Child combinators throughout, not descendant ones.
   `tbody tr:hover td` reaches every cell below a hovered row, including the
   cells of a table nested inside it — so hovering one row lit up an entire
   expanded panel, and the zebra rule painted a nested table's rows on the
   OUTER table's parity, producing bands that lined up with nothing a reader
   could see. Wherever a page nested a table (education fees, property
   expenses, bond coupons, card transactions, child plans) it inherited all
   three rules and had to fight them back off with hand-weighted overrides.
   `>` confines each rule to the table that declares it. */
tbody > tr:hover > td { background: var(--card-glow); }
tbody > tr:last-child > td { border-bottom: none; }

/* Zebra stripe — very subtle */
tbody > tr:nth-child(even) > td { background: var(--surface2); }
tbody > tr:nth-child(even):hover > td { background: var(--card-glow); }

/* A row picked out from the rest: the trip being viewed, an interest payment
   due soon, a subtotal.

   It has to paint the cells, not the row. A <tr> background sits behind its
   cells, so on any even row the zebra rule's own td background covered it
   completely — an inline `style="background:var(--bg-alt)"` on the row was
   visible on odd rows and invisible on even ones, which is worse than not
   working at all, because it works just often enough to look intentional. */
tbody > tr.row-alt > td { background: var(--bg-alt); }
tbody > tr.row-alt:hover > td { background: var(--card-glow); }

/* Amount cells */
td.amount { font-variant-numeric: tabular-nums; font-weight: 600; font-family: 'JetBrains Mono', 'Inter', monospace; font-size: .82rem; }

/* ── Badges ──────────────────────────────────────────────────────────────── */
.badge {
  display: inline-flex;
  align-items: center;
  padding: .25rem .7rem;
  border-radius: 999px;
  font-size: .7rem;
  font-weight: 600;
  text-transform: capitalize;
  letter-spacing: .02em;
}

/* Expense badges */
.badge-food, .badge-dining        { background: #fef3c7; color: #92400e; }
.badge-groceries                  { background: #d1fae5; color: #065f46; }
.badge-transport, .badge-fuel     { background: #dbeafe; color: #1e40af; }
.badge-vehicle                    { background: #fef9c3; color: #713f12; }
.badge-travel                     { background: #e0e7ff; color: #3730a3; }
.badge-utilities, .badge-internet { background: #ede9fe; color: #5b21b6; }
.badge-rent                       { background: #fce7f3; color: #9d174d; }
.badge-health, .badge-medicines   { background: #fee2e2; color: #991b1b; }
.badge-fitness                    { background: #ccfbf1; color: #134e4a; }
.badge-entertainment              { background: #fae8ff; color: #701a75; }
.badge-shopping, .badge-clothing  { background: #fce7f3; color: #9d174d; }
.badge-subscriptions              { background: #dbeafe; color: #1e40af; }
.badge-education, .badge-books    { background: #d1fae5; color: #065f46; }
.badge-family                     { background: #fef3c7; color: #92400e; }
.badge-gifts, .badge-festivals    { background: #fce7f3; color: #9d174d; }
.badge-charity                    { background: #d1fae5; color: #065f46; }
.badge-household                  { background: #f1f5f9; color: #475569; }
.badge-emi                        { background: #fee2e2; color: #991b1b; }
.badge-taxes                      { background: #fee2e2; color: #991b1b; }
.badge-general, .badge-other      { background: #f1f5f9; color: #475569; }

/* Income badges */
.badge-inc-salary                 { background: #d1fae5; color: #065f46; }
.badge-inc-bonus, .badge-inc-arrears, .badge-inc-gratuity { background: #fef3c7; color: #92400e; }
.badge-inc-freelance, .badge-inc-consulting { background: #dbeafe; color: #1e40af; }
.badge-inc-business               { background: #ede9fe; color: #5b21b6; }
.badge-inc-dividend, .badge-inc-interest, .badge-inc-capital_gains { background: #ccfbf1; color: #134e4a; }
.badge-inc-rental                 { background: #fce7f3; color: #9d174d; }
.badge-inc-mf_redemption          { background: #dbeafe; color: #1e40af; }
.badge-inc-pension                { background: #f1f5f9; color: #475569; }
.badge-inc-gift, .badge-inc-cashback, .badge-inc-refund { background: #fef3c7; color: #92400e; }
.badge-inc-other                  { background: #f1f5f9; color: #475569; }

/* Savings/gold/other badges */
.badge-ppf  { background: #ccfbf1; color: #134e4a; }
.badge-epf  { background: #dbeafe; color: #1e40af; }
.badge-fd   { background: #fef3c7; color: #92400e; }
.badge-coins     { background: #fef9c3; color: #713f12; }
.badge-jewellery { background: #fce7f3; color: #9d174d; }
.badge-bar       { background: #f1f5f9; color: #475569; }
.badge-life      { background: #d1fae5; color: #065f46; }
.badge-term      { background: #dbeafe; color: #1e40af; }
.badge-vehicle-ins { background: #fef3c7; color: #92400e; }

/* Loan badges */
.badge-loan-home      { background: #dbeafe; color: #1e40af; }
.badge-loan-car       { background: #fef3c7; color: #92400e; }
.badge-loan-personal  { background: #fee2e2; color: #991b1b; }
.badge-loan-education { background: #d1fae5; color: #065f46; }
.badge-loan-other     { background: #f1f5f9; color: #475569; }

/* Extra badges */
.badge-loan     { background: #fee2e2; color: #991b1b; }
.badge-personal { background: #ede9fe; color: #5b21b6; }
.badge-medical  { background: #fed7d7; color: #742a2a; }
.badge-salary   { background: #d1fae5; color: #065f46; }
[class^="badge-"]:not([class*=" "]) { background: #f1f5f9; color: #475569; }

/* ── Progress bar ────────────────────────────────────────────────────────── */
.progress-bar {
  height: 7px;
  background: var(--progress-bg);
  border-radius: 999px;
  overflow: hidden;
  margin-top: .4rem;
}
.progress-fill { height: 100%; border-radius: 999px; transition: width .6s cubic-bezier(.4,0,.2,1); }
.fill-ok   { background: linear-gradient(90deg, #10b981, #34d399); }
.fill-warn { background: linear-gradient(90deg, #f59e0b, #fbbf24); }
.fill-over { background: linear-gradient(90deg, #ef4444, #f87171); }

/* ── Layout helpers ──────────────────────────────────────────────────────── */
.two-col   { display: grid; grid-template-columns: 1fr 1fr; gap: 1.75rem; }

@media (min-width: 1600px) {
  .cards { grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); }
}
@media (min-width: 2000px) {
  .cards { grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); }
}

.preview-bar {
  font-size: .82rem;
  color: var(--text-muted);
  margin-top: .6rem;
  padding: .7rem 1rem;
  background: var(--surface2);
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-light);
}

.returned td { opacity: .4; text-decoration: line-through; }

/* ── Empty state ─────────────────────────────────────────────────────────── */
.empty-state {
  text-align: center;
  padding: 3.5rem 1.5rem;
  color: var(--text-muted);
}
.empty-state .empty-icon { font-size: 3.5rem; opacity: .35; margin-bottom: .75rem; }
.empty-state p { font-size: .9rem; line-height: 1.6; }

/* ── Category chips ──────────────────────────────────────────────────────── */
.cat-chip {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: .2rem .2rem .2rem .6rem;
  font-size: .82rem;
  transition: all .15s ease;
}
.cat-chip:hover { border-color: var(--primary); }

.cat-del {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--text-muted);
  font-size: .9rem;
  line-height: 1;
  padding: .1rem .3rem;
  border-radius: 999px;
  transition: all .15s;
}
.cat-del:hover { background: var(--danger); color: white; }

.cat-edit {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--text-muted);
  font-size: .78rem;
  padding: .1rem .25rem;
  border-radius: 4px;
  transition: all .15s;
}
.cat-edit:hover { background: var(--primary); color: white; }

/* ── Member filter chips ─────────────────────────────────────────────────── */
.member-chip {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  padding: .55rem 1.15rem;
  border-radius: 12px;
  border: 2px solid var(--border);
  background: linear-gradient(180deg, var(--surface), var(--surface2));
  color: var(--text);
  font-size: .85rem;
  font-weight: 600;
  cursor: pointer;
  font-family: inherit;
  box-shadow: 0 1px 3px rgba(0,0,0,.08), inset 0 1px 0 rgba(255,255,255,.4);
  transition: color .2s ease, border-color .2s ease, background .2s ease,
              box-shadow .2s ease, transform .15s ease;
}
.member-chip:hover {
  border-color: var(--primary);
  color: var(--primary);
  transform: translateY(-2px);
  box-shadow: 0 6px 14px rgba(0,0,0,.12);
}
.member-chip.active {
  background: linear-gradient(135deg, var(--primary), var(--primary-dark));
  border-color: var(--primary);
  color: white;
  box-shadow: 0 4px 14px rgba(59,130,246,.35), inset 0 1px 0 rgba(255,255,255,.25);
}
.member-chip.active:hover { color: #fff; transform: translateY(-2px); }

/* ── Accent chips ───────────────────────────────────────────────────────────
   The same device the summary cards use: a coloured top edge over a tint that
   fades into the surface. On a card it says what the number is about; here it
   gives each filter its own colour, so you come back to a page and find the
   one you want by colour before you have read a word of it.

   Selected, the chip fills with its own accent rather than the house blue —
   a green chip that turns blue when you press it has told you two different
   things about itself. */
.member-chip[class*="chip-a-"] { border-top-width: 3px; }
.sav-subchip[class*="chip-a-"] { border-top-width: 2.5px; }

/* "All" — no colour of its own, because it is the absence of a filter. Lit,
   it takes the house colour, which is what "everything" should look like. */
:is(.member-chip, .sav-subchip).chip-a-neutral {
  border-top-color: var(--text-muted);
  background: linear-gradient(180deg, var(--surface2) 0%, var(--surface) 70%);
}
:is(.member-chip, .sav-subchip).chip-a-neutral:hover {
  border-color: var(--primary); color: var(--primary);
}
/* Icons inside buttons: sized once, and on currentColor so they invert with
   the button rather than staying a coloured sticker on a filled one. */
.btn .btn-ic { width: 14px; height: 14px; flex: 0 0 auto; }
.btn { display: inline-flex; align-items: center; gap: .4rem; }
.btn-edit .btn-ic, .btn-red .btn-ic { width: 15px; height: 15px; }
.btn-edit, .btn-red { display: inline-flex; align-items: center; justify-content: center; }

:is(.member-chip, .sav-subchip).chip-a-neutral.active {
  background: linear-gradient(135deg, var(--primary), var(--primary-dark));
  border-color: var(--primary);
  box-shadow: 0 4px 14px color-mix(in srgb, var(--primary) 38%, transparent),
              inset 0 1px 0 rgba(255,255,255,.25);
}

:is(.member-chip, .sav-subchip).chip-a-blue { border-top-color: var(--primary); background: linear-gradient(180deg, var(--primary-light) 0%, var(--surface) 70%); }
:is(.member-chip, .sav-subchip).chip-a-green { border-top-color: var(--success); background: linear-gradient(180deg, var(--success-light) 0%, var(--surface) 70%); }
:is(.member-chip, .sav-subchip).chip-a-orange { border-top-color: var(--warning); background: linear-gradient(180deg, var(--warning-light) 0%, var(--surface) 70%); }
:is(.member-chip, .sav-subchip).chip-a-red { border-top-color: var(--danger); background: linear-gradient(180deg, var(--danger-light) 0%, var(--surface) 70%); }
:is(.member-chip, .sav-subchip).chip-a-purple { border-top-color: var(--purple); background: linear-gradient(180deg, var(--purple-light) 0%, var(--surface) 70%); }
:is(.member-chip, .sav-subchip).chip-a-teal { border-top-color: var(--teal); background: linear-gradient(180deg, var(--teal-light) 0%, var(--surface) 70%); }

:is(.member-chip, .sav-subchip).chip-a-blue:hover { border-color: var(--primary); color: var(--primary); }
:is(.member-chip, .sav-subchip).chip-a-green:hover { border-color: var(--success); color: var(--success); }
:is(.member-chip, .sav-subchip).chip-a-orange:hover { border-color: var(--warning); color: var(--warning); }
:is(.member-chip, .sav-subchip).chip-a-red:hover { border-color: var(--danger); color: var(--danger); }
:is(.member-chip, .sav-subchip).chip-a-purple:hover { border-color: var(--purple); color: var(--purple); }
:is(.member-chip, .sav-subchip).chip-a-teal:hover { border-color: var(--teal); color: var(--teal); }

:is(.member-chip, .sav-subchip).chip-a-blue.active { background: linear-gradient(135deg, var(--primary), color-mix(in srgb, var(--primary) 72%, #000)); border-color: var(--primary); box-shadow: 0 4px 14px color-mix(in srgb, var(--primary) 38%, transparent), inset 0 1px 0 rgba(255,255,255,.25); }
:is(.member-chip, .sav-subchip).chip-a-green.active { background: linear-gradient(135deg, var(--success), color-mix(in srgb, var(--success) 72%, #000)); border-color: var(--success); box-shadow: 0 4px 14px color-mix(in srgb, var(--success) 38%, transparent), inset 0 1px 0 rgba(255,255,255,.25); }
:is(.member-chip, .sav-subchip).chip-a-orange.active { background: linear-gradient(135deg, var(--warning), color-mix(in srgb, var(--warning) 72%, #000)); border-color: var(--warning); box-shadow: 0 4px 14px color-mix(in srgb, var(--warning) 38%, transparent), inset 0 1px 0 rgba(255,255,255,.25); }
:is(.member-chip, .sav-subchip).chip-a-red.active { background: linear-gradient(135deg, var(--danger), color-mix(in srgb, var(--danger) 72%, #000)); border-color: var(--danger); box-shadow: 0 4px 14px color-mix(in srgb, var(--danger) 38%, transparent), inset 0 1px 0 rgba(255,255,255,.25); }
:is(.member-chip, .sav-subchip).chip-a-purple.active { background: linear-gradient(135deg, var(--purple), color-mix(in srgb, var(--purple) 72%, #000)); border-color: var(--purple); box-shadow: 0 4px 14px color-mix(in srgb, var(--purple) 38%, transparent), inset 0 1px 0 rgba(255,255,255,.25); }
:is(.member-chip, .sav-subchip).chip-a-teal.active { background: linear-gradient(135deg, var(--teal), color-mix(in srgb, var(--teal) 72%, #000)); border-color: var(--teal); box-shadow: 0 4px 14px color-mix(in srgb, var(--teal) 38%, transparent), inset 0 1px 0 rgba(255,255,255,.25); }

:is(.member-chip, .sav-subchip)[class*="chip-a-"].active,
:is(.member-chip, .sav-subchip)[class*="chip-a-"].active:hover { color: #fff; }
:is(.member-chip, .sav-subchip)[class*="chip-a-"].active .chip-n,
.sav-subchip[class*="chip-a-"].active .sav-subchip-n { opacity: .85; }

/* ── One structure for every filter chip: [icon] Label [count] ───────────────
   Nine pages had built these five different ways — "All (12)", "All", bare
   emoji, a bold amount, a parenthesised rupee total — so the same control
   looked like a different control on each page. These two classes are what
   make them one thing, and they live here rather than under any one page's id
   so a chip added later gets them for free.

   The icon is drawn, not typed. Emoji sit on their own baseline, render
   differently on every platform, and cannot take the chip's colour — so the
   icon stayed a coloured sticker while the label went white on selection. A
   stroked SVG on currentColor follows both the theme and the selected state.
   Member chips keep their emoji: that is the person's own choice, not
   decoration. */
.member-chip .chip-ic {
  width: 16px; height: 16px;
  flex: 0 0 auto;
  opacity: .85;
}
.member-chip.active .chip-ic { opacity: 1; }
/* A count is a count, not part of the name — so it is quieter than the label
   and set in lining figures, which stops the chips jittering as counts change. */
.member-chip .chip-n {
  font-size: .74rem;
  font-weight: 600;
  opacity: .6;
  font-variant-numeric: tabular-nums;
}
.member-chip.active .chip-n { opacity: .82; }
/* A money total alongside a count: readable, still subordinate to the label. */
.member-chip .chip-amt {
  font-size: .76rem;
  font-weight: 600;
  opacity: .75;
  font-variant-numeric: tabular-nums;
}
.member-chip.active .chip-amt { opacity: .9; }
/* Something needing attention, on a chip that otherwise only reports. */
.member-chip .chip-flag {
  font-size: .7rem;
  font-weight: 700;
  color: var(--warning);
  background: var(--warning-light, transparent);
  border-radius: 5px;
  padding: 0 .3rem;
}
.member-chip.active .chip-flag { color: #fff; background: rgba(255,255,255,.22); }
/* The gap between label, count and amount is the chip's own, so every page
   spaces them identically instead of each one inventing a separator. */
.member-chip { gap: .38rem; }

/* Savings once carried this treatment alone, under its own id. It is what
   .member-chip looks like everywhere now, so there is nothing left to override
   here — the whole point being that a chip is a chip wherever you meet it. */



/* ── The kinds inside the chosen group ───────────────────────────────────────
   The same chip as above, smaller. Same corners, same lift, same fill when
   chosen — a chip should not change species halfway down the page — with size
   alone carrying the fact that this row refines the one above it.

   The parent is a wrapping flex row, so this has to claim a full line: left
   inline it sat beside the group chips and read as more of the same, which is
   the confusion it exists to remove. */
.sav-subfilter {
  flex-basis: 100%;
  width: 100%;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .35rem;
  margin: .6rem 0 0;
  padding-left: .15rem;
}
.sav-subchip {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  padding: .34rem .7rem;
  border-radius: 9px;
  border: 1.5px solid var(--border);
  background: linear-gradient(180deg, var(--surface), var(--surface2));
  color: var(--text);
  font-family: inherit;
  font-size: .78rem;
  font-weight: 600;
  cursor: pointer;
  box-shadow: 0 1px 2px rgba(0,0,0,.06), inset 0 1px 0 rgba(255,255,255,.35);
  transition: color .2s ease, border-color .2s ease, background .2s ease,
              box-shadow .2s ease, transform .15s ease;
}
.sav-subchip:hover {
  border-color: var(--primary);
  color: var(--primary);
  transform: translateY(-1px);
  box-shadow: 0 4px 10px rgba(0,0,0,.1);
}
.sav-subchip .sav-subchip-n {
  font-size: .7rem;
  font-weight: 600;
  opacity: .6;
  font-variant-numeric: tabular-nums;
}
.sav-subchip.active {
  background: linear-gradient(135deg, var(--primary), var(--primary-dark));
  border-color: var(--primary);
  color: #fff;
  box-shadow: 0 3px 10px rgba(59,130,246,.3), inset 0 1px 0 rgba(255,255,255,.22);
}
.sav-subchip.active:hover { color: #fff; transform: translateY(-1px); }
.sav-subchip.active .sav-subchip-n { opacity: .85; }
/* Only on the chosen one, where it means something: press it to go back to the
   whole group. */
/* The second row's icons are barely smaller than the first's, so the two rows
   read as one control rather than two different kinds of thing. The cross that
   used to sit on the chosen one is gone: pressing it again clears it, which is
   one less thing to aim at and matches everything else in the app. */
.sav-subchip .chip-ic { width: 15px; height: 15px; flex: 0 0 auto; opacity: .85; }
.sav-subchip.active .chip-ic { opacity: 1; }

/* ── Dashboard net worth ─────────────────────────────────────────────────── */
#nw-total {
  font-size: 2.2rem;
  font-weight: 800;
  background: linear-gradient(135deg, var(--success), var(--teal));
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  letter-spacing: -.03em;
}

/* ── Sold/inactive row styling ───────────────────────────────────────────── */
tr.sold td { opacity: .45; }
tr.sold td:first-child::before { content: '🏷️ '; }

/* ── Edit button ─────────────────────────────────────────────────────────── */
.btn-edit {
  background: none;
  border: none;
  color: var(--primary);
  cursor: pointer;
  font-size: .9rem;
  padding: .2rem .4rem;
  border-radius: var(--radius-xs);
  transition: all .15s;
}
.btn-edit:hover { background: var(--primary-light); }

.drive-bulk-move-btn {
  border: 1.5px solid var(--border) !important;
  border-radius: var(--radius-xs);
  padding: .3rem .7rem !important;
  font-size: .78rem !important;
}
.drive-bulk-move-btn:hover { border-color: var(--primary); }

.drive-view-btn {
  border: none; cursor: pointer; background: none; color: var(--text-muted);
}
.drive-view-btn.active { background: var(--primary-light); color: var(--primary); }

/* ── Date group header in expenses table ─────────────────────────────────── */
tr.date-group-header td {
  border-top: 2px solid var(--border) !important;
  border-bottom: none !important;
  background: var(--surface2) !important;
  font-weight: 600;
}
tr.date-group-header + tr td { border-top: none; }
tr.date-group-header:nth-child(even) td,
tr.date-group-header:nth-child(odd) td { background: var(--surface2) !important; }

/* ── Scrollbar ───────────────────────────────────────────────────────────── */
::-webkit-scrollbar { width: 7px; height: 7px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 999px; border: 1px solid transparent; background-clip: padding-box; }
::-webkit-scrollbar-thumb:hover { background: var(--text-muted); }

/* ── Focus ring ──────────────────────────────────────────────────────────── */
button:focus-visible, input:focus-visible, select:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}

/* ── Animations ──────────────────────────────────────────────────────────── */
.card {
  animation: cardIn .4s cubic-bezier(.4,0,.2,1) both;
}
@keyframes cardIn {
  from { opacity: 0; transform: translateY(8px) scale(.98); }
  to { opacity: 1; transform: none; }
}

/* Stagger card animations */
.cards .card:nth-child(1) { animation-delay: 0s; }
.cards .card:nth-child(2) { animation-delay: .04s; }
.cards .card:nth-child(3) { animation-delay: .08s; }
.cards .card:nth-child(4) { animation-delay: .12s; }
.cards .card:nth-child(5) { animation-delay: .16s; }
.cards .card:nth-child(6) { animation-delay: .2s; }
.cards .card:nth-child(7) { animation-delay: .24s; }
.cards .card:nth-child(8) { animation-delay: .28s; }

/* ── Responsive table columns ────────────────────────────────────────────── */
th { white-space: nowrap; }
td:nth-child(2) { white-space: normal; min-width: 100px; max-width: 200px; }
td:last-child, td:nth-last-child(2) { white-space: nowrap; }
#gold-list td, #sil-list td { white-space: nowrap; }
#gold-list td:nth-child(2), #sil-list td:nth-child(2) { white-space: normal; }
.main-content { overflow-x: hidden; }
.page { overflow-x: auto; }

/* ── Print ───────────────────────────────────────────────────────────────── */
@media print {
  .sidebar, .btn, button { display: none !important; }
  .page { display: none !important; }
  #page-dashboard { display: block !important; padding: 0; }
  body { background: white; }
  .panel, .card { box-shadow: none; border: 1px solid #e2e8f0; }
  /* Without this, browsers strip background colors/gradients when printing
     or saving to PDF — the colored dashboard cards would render as plain
     white with invisible white-on-white text. */
  * { -webkit-print-color-adjust: exact !important; print-color-adjust: exact !important; color-adjust: exact !important; }
}

/* ── PWA / iOS safe areas ────────────────────────────────────────────────── */
body {
  padding-top: env(safe-area-inset-top);
  padding-bottom: env(safe-area-inset-bottom);
  padding-left: env(safe-area-inset-left);
  padding-right: env(safe-area-inset-right);
}

/* ── Responsive ──────────────────────────────────────────────────────────── */
@media (max-width: 768px) {
  .app-layout { flex-direction: column; }
  .sidebar {
    width: 100%;
    height: auto;
    position: fixed;
    z-index: 100;
    max-height: 50vh;
    overflow-y: auto;
    box-shadow: 0 4px 20px rgba(0,0,0,.2);
  }
  .sidebar-header { padding: .75rem; }
  .sidebar-logo { font-size: .95rem; }
  .sidebar-nav { display: flex; flex-wrap: wrap; padding: .25rem .5rem .5rem; }
  .nav-group { display: contents; }
  .nav-group-items { display: contents; }
  .nav-group-label { display: none; }
  .nav-btn { width: auto; padding: .35rem .7rem; font-size: .78rem; border-radius: var(--radius-xs); margin-right: 0; }
  .nav-btn.active::before { display: none; }
  .main-content { margin-top: 0; padding-top: .5rem; }
  .page { padding: .85rem !important; }
  .two-col { grid-template-columns: 1fr; }
  .cards { grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); gap: .6rem; }
  .card .val { font-size: 1.1rem; }
  .row { gap: .5rem; }
  .field { min-width: 100px; }
  table { font-size: .78rem; }
  th, td { padding: .5rem .6rem; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   MOBILE APP — Native-feeling PWA for iOS / Android
   ═══════════════════════════════════════════════════════════════════════════ */

/* Hide mobile nav on desktop */
.mobile-nav, .mob-sheet, .mob-sheet-overlay { display: none; }

@media (max-width: 768px) {

  /* ── Hide desktop sidebar, show mobile nav ─────────────────────────────── */
  .sidebar { display: none !important; }
  .mobile-nav { display: flex !important; }

  .app-layout { flex-direction: column; }

  .main-content {
    padding-bottom: calc(70px + env(safe-area-inset-bottom));
    min-height: 100vh;
    overflow-x: hidden;
    overflow-y: visible;
  }

  .page {
    padding: 1rem .85rem 2rem !important;
    animation: mobPageIn .25s ease;
  }
  @keyframes mobPageIn {
    from { opacity: 0; transform: translateX(12px); }
    to { opacity: 1; transform: none; }
  }

  /* ── Bottom Tab Bar ────────────────────────────────────────────────────── */
  .mobile-nav {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 1000;
    background: var(--surface);
    border-top: 1px solid var(--border);
    display: flex !important;
    justify-content: space-around;
    align-items: stretch;
    padding: 0;
    padding-bottom: env(safe-area-inset-bottom);
    box-shadow: 0 -4px 20px rgba(0,0,0,.08);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
  }

  .mob-tab {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    padding: 8px 4px 6px;
    background: none;
    border: none;
    cursor: pointer;
    color: var(--text-muted);
    font-family: inherit;
    transition: all .2s ease;
    position: relative;
    -webkit-tap-highlight-color: transparent;
  }

  .mob-tab .mob-icon {
    font-size: 1.35rem;
    line-height: 1;
    transition: transform .2s ease;
  }

  .mob-tab .mob-label {
    font-size: .62rem;
    font-weight: 600;
    letter-spacing: .02em;
    text-transform: uppercase;
  }

  .mob-tab.active {
    color: var(--primary);
  }
  .mob-tab.active .mob-icon {
    transform: scale(1.15);
  }
  .mob-tab.active::after {
    content: '';
    position: absolute;
    top: 0;
    left: 25%;
    right: 25%;
    height: 3px;
    background: var(--primary);
    border-radius: 0 0 3px 3px;
  }

  .mob-tab:active {
    transform: scale(.92);
  }

  /* ── Bottom Sheet (More menu) ──────────────────────────────────────────── */
  .mob-sheet-overlay {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,.4);
    z-index: 1001;
    opacity: 0;
    transition: opacity .3s ease;
    -webkit-backdrop-filter: blur(4px);
    backdrop-filter: blur(4px);
  }
  .mob-sheet-overlay.open {
    display: block;
    opacity: 1;
  }

  .mob-sheet {
    display: block;
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 1002;
    background: var(--surface);
    border-radius: 20px 20px 0 0;
    padding: .75rem 1rem calc(1rem + env(safe-area-inset-bottom));
    transform: translateY(100%);
    transition: transform .35s cubic-bezier(.32,.72,0,1);
    box-shadow: 0 -10px 40px rgba(0,0,0,.15);
    max-height: 75vh;
    overflow-y: auto;
  }
  .mob-sheet.open {
    transform: translateY(0);
  }

  .mob-sheet-handle {
    width: 36px;
    height: 4px;
    background: var(--border);
    border-radius: 999px;
    margin: 0 auto .75rem;
  }

  .mob-sheet-title {
    font-size: .75rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .1em;
    color: var(--text-muted);
    margin-bottom: .75rem;
    padding-left: .25rem;
  }

  .mob-sheet-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: .5rem;
  }

  .mob-sheet-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .35rem;
    padding: .85rem .5rem;
    background: var(--surface2);
    border: 1px solid var(--border-light);
    border-radius: var(--radius-sm);
    cursor: pointer;
    font-family: inherit;
    font-size: 1.5rem;
    color: var(--text);
    transition: all .15s ease;
    -webkit-tap-highlight-color: transparent;
  }
  .mob-sheet-item span {
    font-size: .65rem;
    font-weight: 600;
    color: var(--text-muted);
    text-align: center;
    line-height: 1.2;
  }
  .mob-sheet-item:active {
    transform: scale(.94);
    background: var(--primary-light);
  }

  /* ── Mobile page header ────────────────────────────────────────────────── */
  .page-title {
    font-size: 1.35rem;
  }

  /* ── Mobile cards ──────────────────────────────────────────────────────── */
  .cards {
    grid-template-columns: repeat(2, 1fr);
    gap: .65rem;
    margin-bottom: 1.25rem;
  }
  .card {
    padding: .9rem 1rem;
    border-radius: var(--radius-sm);
  }
  .card .lbl { font-size: .6rem; }
  .card .val { font-size: 1.15rem; }

  /* ── Mobile panels ─────────────────────────────────────────────────────── */
  .panel {
    padding: 1rem;
    border-radius: var(--radius-sm);
    margin-bottom: 1rem;
  }

  /* ── Mobile forms ──────────────────────────────────────────────────────── */
  .row {
    gap: .6rem;
  }
  .field {
    min-width: 0;
    flex: 1 1 calc(50% - .3rem);
  }
  .field input, .field select {
    padding: .6rem .75rem;
    font-size: .9rem;
    border-radius: var(--radius-xs);
  }

  /* ── Mobile tables ─────────────────────────────────────────────────────── */
  table { font-size: .76rem; }
  th { font-size: .6rem; padding: .55rem .5rem; }
  td { padding: .6rem .5rem; font-size: .78rem; }

  /* ── Mobile buttons ────────────────────────────────────────────────────── */
  .btn {
    padding: .55rem 1rem;
    font-size: .82rem;
    border-radius: var(--radius-xs);
  }
  .btn-sm { padding: .35rem .6rem; font-size: .72rem; }

  /* ── Two/three col → single col ────────────────────────────────────────── */
  .two-col { grid-template-columns: 1fr; gap: 1rem; }

  /* ── Net worth on mobile ───────────────────────────────────────────────── */
  #nw-total { font-size: 1.6rem; }

  /* ── Member chips ──────────────────────────────────────────────────────── */
  .member-chip {
    padding: .3rem .65rem;
    font-size: .75rem;
  }

  /* ── Badge ─────────────────────────────────────────────────────────────── */
  .badge { font-size: .62rem; padding: .18rem .5rem; }

  /* ── Disable card hover effects on touch ───────────────────────────────── */
  .card:hover {
    transform: none;
    box-shadow: var(--shadow-sm);
  }

  /* ── Stagger animations faster on mobile ───────────────────────────────── */
  .cards .card:nth-child(n) { animation-delay: 0s; }
  .card { animation-duration: .2s; }
}

/* ── Extra small phones (iPhone SE, etc.) ────────────────────────────────── */
@media (max-width: 375px) {
  .cards { grid-template-columns: 1fr 1fr; gap: .5rem; }
  .card .val { font-size: 1rem; }
  .mob-sheet-grid { grid-template-columns: repeat(3, 1fr); }
  .page { padding: .75rem .65rem 2rem !important; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   TOAST NOTIFICATIONS
   ═══════════════════════════════════════════════════════════════════════════ */
#toast-container {
  position: fixed;
  top: 1rem;
  right: 1rem;
  z-index: 9999;
  display: flex;
  flex-direction: column;
  gap: .5rem;
  pointer-events: none;
}
.toast {
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: .6rem;
  padding: .75rem 1.15rem;
  border-radius: 12px;
  font-size: .84rem;
  font-weight: 500;
  box-shadow: 0 8px 30px rgba(0,0,0,.12);
  animation: toastIn .3s ease;
  max-width: 380px;
  backdrop-filter: blur(12px);
}
.toast.toast-success { background: #ecfdf5; color: #065f46; border: 1px solid #a7f3d0; }
.toast.toast-error   { background: #fef2f2; color: #991b1b; border: 1px solid #fecaca; }
.toast.toast-info    { background: #eff6ff; color: #1e40af; border: 1px solid #bfdbfe; }
.toast.toast-warning { background: #fffbeb; color: #92400e; border: 1px solid #fde68a; }
.toast.toast-out { animation: toastOut .25s ease forwards; }
@keyframes toastIn { from { opacity: 0; transform: translateX(40px); } to { opacity: 1; transform: translateX(0); } }
@keyframes toastOut { from { opacity: 1; transform: translateX(0); } to { opacity: 0; transform: translateX(40px); } }

/* ═══════════════════════════════════════════════════════════════════════════
   LOADING SPINNER
   ═══════════════════════════════════════════════════════════════════════════ */
.spinner {
  display: inline-block;
  width: 18px;
  height: 18px;
  border: 2.5px solid var(--border);
  border-top-color: var(--primary);
  border-radius: 50%;
  animation: spin .6s linear infinite;
  vertical-align: middle;
}
@keyframes spin { to { transform: rotate(360deg); } }
.loading-row td { text-align: center; padding: 2rem; color: var(--text-muted); }

/* ═══════════════════════════════════════════════════════════════════════════
   SORTABLE TABLE COLUMNS
   ═══════════════════════════════════════════════════════════════════════════ */
th.sortable {
  cursor: pointer;
  user-select: none;
  position: relative;
  padding-right: 1.2rem;
}
th.sortable:hover { color: var(--primary); }
th.sortable::after {
  content: '⇅';
  position: absolute;
  right: .3rem;
  font-size: .65rem;
  opacity: .35;
}
th.sortable.sort-asc::after { content: '▲'; opacity: .7; }
th.sortable.sort-desc::after { content: '▼'; opacity: .7; }

/* ═══════════════════════════════════════════════════════════════════════════
   FORM VALIDATION
   ═══════════════════════════════════════════════════════════════════════════ */
.field input:invalid:not(:placeholder-shown),
.field input.invalid {
  border-color: var(--danger) !important;
  box-shadow: 0 0 0 2px rgba(239,68,68,.12);
}

/* ═══════════════════════════════════════════════════════════════════════════
   EMPTY STATE
   ═══════════════════════════════════════════════════════════════════════════ */
.empty-state {
  text-align: center;
  padding: 3rem 1.5rem;
  color: var(--text-muted);
}
.empty-state .empty-icon {
  font-size: 3rem;
  margin-bottom: .75rem;
  opacity: .4;
}
.empty-state p {
  font-size: .9rem;
  line-height: 1.6;
  max-width: 360px;
  margin: 0 auto;
}

/* ═══════════════════════════════════════════════════════════════════════════
   TOPBAR
   ═══════════════════════════════════════════════════════════════════════════ */
#topbar {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--bg);
  border-bottom: 1px solid var(--border);
}
@media (max-width: 768px) {
  #topbar { display: none !important; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   VIEWER MODE — hide write controls
   ═══════════════════════════════════════════════════════════════════════════ */
body.viewer-mode .admin-only,
body.viewer-mode .btn-red,
body.viewer-mode .btn-edit,
body.viewer-mode [onclick*="del"],
body.viewer-mode [onclick*="clear"],
body.viewer-mode [onclick*="Clear"] {
  display: none !important;
}
body.viewer-mode .bulk-chk-expenses,
body.viewer-mode .bulk-chk-savings,
body.viewer-mode .bulk-chk-gold,
body.viewer-mode .bulk-chk-stocks,
body.viewer-mode .bulk-chk-mutualfunds,
body.viewer-mode .bulk-chk-realestate,
body.viewer-mode .bulk-chk-loans,
body.viewer-mode .bulk-chk-recurring,
body.viewer-mode .bulk-chk-goals,
body.viewer-mode [type="checkbox"][onchange*="toggleAll"] {
  display: none !important;
}

/* ═══════════════════════════════════════════════════════════════════════════
   MEMBER MODE — create/edit allowed, delete is not (applies to member and
   viewer, since both carry .member-mode; viewer already hides everything
   via the broader rule above, so this only changes behavior for member).
   ═══════════════════════════════════════════════════════════════════════════ */
body.member-mode .btn-red,
body.member-mode [onclick*="del"],
body.member-mode [onclick*="clear"],
body.member-mode [onclick*="Clear"],
body.member-mode .bulk-chk-expenses,
body.member-mode .bulk-chk-savings,
body.member-mode .bulk-chk-gold,
body.member-mode .bulk-chk-stocks,
body.member-mode .bulk-chk-mutualfunds,
body.member-mode .bulk-chk-realestate,
body.member-mode .bulk-chk-loans,
body.member-mode .bulk-chk-recurring,
body.member-mode .bulk-chk-goals,
body.member-mode [type="checkbox"][onchange*="toggleAll"] {
  display: none !important;
}

/* ═══════════════════════════════════════════════════════════════════════════
   FUND SEARCH DROPDOWN
   ═══════════════════════════════════════════════════════════════════════════ */
.fund-search-results {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0,0,0,.12);
  max-height: 250px;
  overflow-y: auto;
  z-index: 200;
  margin-top: 2px;
}
.fund-search-results .fund-item {
  padding: .45rem .7rem;
  font-size: .78rem;
  cursor: pointer;
  border-bottom: 1px solid var(--border);
  transition: background .1s;
}
.fund-search-results .fund-item:hover {
  background: var(--primary-light);
}
.fund-search-results .fund-item:last-child {
  border-bottom: none;
}


/* ═══════════════════════════════════════════════════════════════════════════
   DRAG AND DROP
   ═══════════════════════════════════════════════════════════════════════════ */
.drag-over {
  outline: 3px dashed var(--primary) !important;
  outline-offset: -3px;
  background: var(--primary-light) !important;
}

.drop-zone {
  border: 2px dashed var(--border);
  border-radius: var(--radius);
  padding: 2rem;
  text-align: center;
  color: var(--text-muted);
  font-size: .85rem;
  transition: all .2s;
  cursor: pointer;
}
.drop-zone:hover, .drop-zone.drag-over {
  border-color: var(--primary);
  background: var(--primary-light);
  color: var(--primary);
}


/* ═══════════════════════════════════════════════════════════════════════════
   PRIVACY MODE — blur amounts on Dashboard and Insights
   ═══════════════════════════════════════════════════════════════════════════ */
body.privacy-mode #page-dashboard .val,
body.privacy-mode #page-dashboard td:nth-child(2),
body.privacy-mode #page-insights .val,
body.privacy-mode #page-insights td:nth-last-child(-n+4):not(:last-child) {
  filter: blur(8px);
  user-select: none;
  transition: filter .3s ease;
}
body.privacy-mode #page-dashboard .card:hover .val,
body.privacy-mode #page-insights .card:hover .val {
  filter: blur(0);
}

/* ═══════════════════════════════════════════════════════════════════════════
   LOGIN SCREEN
   ═══════════════════════════════════════════════════════════════════════════ */
.login-screen {
  position: fixed; inset: 0; z-index: 10000;
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
  background:
    radial-gradient(circle at 15% 20%, color-mix(in srgb, var(--primary) 16%, transparent), transparent 55%),
    radial-gradient(circle at 85% 15%, color-mix(in srgb, var(--purple) 14%, transparent), transparent 50%),
    radial-gradient(circle at 50% 100%, color-mix(in srgb, var(--teal) 12%, transparent), transparent 55%),
    var(--bg);
}

.login-blob {
  position: absolute; border-radius: 50%; filter: blur(60px);
  opacity: .55; pointer-events: none;
  animation: loginBlobFloat 16s ease-in-out infinite;
}
.login-blob-1 {
  width: 420px; height: 420px; top: -140px; left: -120px;
  background: radial-gradient(circle, var(--primary), transparent 70%);
  animation-delay: 0s;
}
.login-blob-2 {
  width: 380px; height: 380px; bottom: -160px; right: -100px;
  background: radial-gradient(circle, var(--purple), transparent 70%);
  animation-delay: -5s;
}
.login-blob-3 {
  width: 300px; height: 300px; bottom: 10%; left: 8%;
  background: radial-gradient(circle, var(--teal), transparent 70%);
  animation-delay: -10s;
}
/* ── The rupee behind it all ─────────────────────────────────────────────────
   A currency-marked texture rather than a picture: it is a MASK over a solid
   colour, so the ₹ takes whichever theme is on instead of being baked to one
   palette, and it costs one inline data URI — no request, and nothing for the
   content-security policy to argue with. Kept at a few percent opacity: the
   card in front has to stay the thing you read. */
.login-rupees {
  position: absolute; inset: 0; pointer-events: none;
  background-color: var(--primary);
  opacity: .06;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%27200%27%20height%3D%27200%27%20viewBox%3D%270%200%20200%20200%27%3E%3Cg%20fill%3D%27%23000%27%20font-family%3D%27system-ui%2C-apple-system%2CSegoe%20UI%2CRoboto%2Csans-serif%27%20font-weight%3D%27700%27%3E%3Ctext%20x%3D%2726%27%20y%3D%2770%27%20font-size%3D%2752%27%20transform%3D%27rotate%28-14%2026%2070%29%27%3E%E2%82%B9%3C%2Ftext%3E%3Ctext%20x%3D%27132%27%20y%3D%27152%27%20font-size%3D%2734%27%20transform%3D%27rotate%2811%20132%20152%29%27%3E%E2%82%B9%3C%2Ftext%3E%3Ctext%20x%3D%2796%27%20y%3D%2744%27%20font-size%3D%2722%27%20transform%3D%27rotate%28-6%2096%2044%29%27%3E%E2%82%B9%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fsvg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%27200%27%20height%3D%27200%27%20viewBox%3D%270%200%20200%20200%27%3E%3Cg%20fill%3D%27%23000%27%20font-family%3D%27system-ui%2C-apple-system%2CSegoe%20UI%2CRoboto%2Csans-serif%27%20font-weight%3D%27700%27%3E%3Ctext%20x%3D%2726%27%20y%3D%2770%27%20font-size%3D%2752%27%20transform%3D%27rotate%28-14%2026%2070%29%27%3E%E2%82%B9%3C%2Ftext%3E%3Ctext%20x%3D%27132%27%20y%3D%27152%27%20font-size%3D%2734%27%20transform%3D%27rotate%2811%20132%20152%29%27%3E%E2%82%B9%3C%2Ftext%3E%3Ctext%20x%3D%2796%27%20y%3D%2744%27%20font-size%3D%2722%27%20transform%3D%27rotate%28-6%2096%2044%29%27%3E%E2%82%B9%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fsvg%3E");
  -webkit-mask-size: 200px 200px;  mask-size: 200px 200px;
  -webkit-mask-repeat: repeat;     mask-repeat: repeat;
}

/* Three big ones drifting behind the card, for depth the flat tile cannot
   give on its own. Blurred, so they never compete with the form. */
.login-rupee {
  position: absolute;
  font-weight: 800;
  line-height: 1;
  pointer-events: none;
  user-select: none;
  filter: blur(1.5px);
  animation: loginRupeeDrift 22s ease-in-out infinite;
}
.login-rupee-1 {
  font-size: 15rem; top: 6%; left: 4%;
  color: color-mix(in srgb, var(--primary) 22%, transparent);
  animation-delay: 0s;
}
.login-rupee-2 {
  font-size: 11rem; bottom: 8%; right: 6%;
  color: color-mix(in srgb, var(--purple) 20%, transparent);
  animation-delay: -8s;
}
.login-rupee-3 {
  font-size: 7rem; top: 58%; left: 12%;
  color: color-mix(in srgb, var(--teal) 20%, transparent);
  animation-delay: -15s;
}
@keyframes loginRupeeDrift {
  0%, 100% { transform: translate(0, 0) rotate(-4deg); }
  50%      { transform: translate(18px, -26px) rotate(3deg); }
}
/* On a phone the big glyphs crowd the card rather than framing it. */
@media (max-width: 640px) {
  .login-rupee-1 { font-size: 9rem; top: 3%; left: -2%; }
  .login-rupee-2 { font-size: 7rem; bottom: 4%; right: -2%; }
  .login-rupee-3 { display: none; }
  .login-rupees { -webkit-mask-size: 150px 150px; mask-size: 150px 150px; }
}

@keyframes loginBlobFloat {
  0%, 100% { transform: translate(0, 0) scale(1); }
  33%      { transform: translate(30px, -25px) scale(1.08); }
  66%      { transform: translate(-20px, 20px) scale(0.95); }
}
@media (prefers-reduced-motion: reduce) {
  .login-blob,
  .login-rupee { animation: none; }
}

/* ── The split: a brand side and a form side ─────────────────────────────────
   Every colour here is a theme variable, so the panel is indigo under the
   default, rose under rose, teal under ocean. Nothing is a literal hex — the
   first thing a stranger sees should not be the one part of the app that
   ignores the theme they chose. */
.login-split {
  position: relative; z-index: 1;
  display: flex;
  width: min(940px, 94vw);
  border-radius: 26px;
  overflow: hidden;
  box-shadow: 0 30px 80px -20px rgba(0,0,0,.3), var(--shadow-xl);
  animation: loginCardIn .5s cubic-bezier(.16,1,.3,1);
}
.login-brand {
  flex: 1 1 44%;
  position: relative;
  overflow: hidden;
  display: flex; flex-direction: column; justify-content: center;
  padding: 3rem 2.4rem;
  color: #fff;
  /* Built on the sidebar's own gradient rather than on --primary/--purple.
     Those two are light in the dark themes — they have to be, they sit on a
     dark background — so a panel made of them put white text on pale lavender
     and midnight became unreadable. The sidebar tokens are the one pair every
     theme guarantees will carry white text, and using them means you sign in
     on the colour the sidebar then greets you with. The brand colour is
     layered over the top, so it still looks like the theme you chose. */
  background:
    radial-gradient(circle at 18% 12%, color-mix(in srgb, var(--primary) 52%, transparent), transparent 62%),
    radial-gradient(circle at 88% 92%, color-mix(in srgb, var(--purple) 42%, transparent), transparent 58%),
    linear-gradient(150deg, var(--sidebar-from), var(--sidebar-to));
}
/* The big rupee sunk into the panel. */
.login-brand-mark {
  position: absolute; right: -2.5rem; bottom: -4rem;
  font-size: 19rem; font-weight: 800; line-height: 1;
  opacity: .13; pointer-events: none; user-select: none;
}
.login-brand-logo {
  width: 74px; height: 74px; margin-bottom: 1.2rem;
  border-radius: 20px;
  display: flex; align-items: center; justify-content: center;
  background: rgba(255,255,255,.18);
  border: 1px solid rgba(255,255,255,.22);
}
.login-brand-logo svg { width: 38px; height: 38px; }
.login-brand-name {
  font-size: 2.1rem; font-weight: 800; letter-spacing: -.02em;
  margin: 0 0 .5rem; color: #fff;
}
.login-brand-line {
  margin: 0 0 1.3rem; max-width: 30ch;
  font-size: .95rem; line-height: 1.55; opacity: .92;
}
.login-brand-points { list-style: none; padding: 0; margin: 0; display: grid; gap: .45rem; }
.login-brand-points li {
  display: flex; align-items: flex-start; gap: .55rem;
  font-size: .845rem; line-height: 1.4; opacity: .95;
}
.login-brand-points li svg { margin-top: .18rem; }
.login-brand-points li svg { width: 15px; height: 15px; flex: none; }

/* On a phone the panel becomes a header strip: the name and the promise are
   worth the space, three bullet points and a watermark are not. */
@media (max-width: 820px) {
  .login-split { flex-direction: column; width: min(440px, 94vw); }
  .login-brand { padding: 1.9rem 1.7rem; }
  .login-brand-points, .login-brand-mark { display: none; }
  .login-brand-line { margin-bottom: 0; }
  .login-brand-logo { width: 54px; height: 54px; border-radius: 15px; margin-bottom: .9rem; }
  .login-brand-logo svg { width: 28px; height: 28px; }
  .login-brand-name { font-size: 1.7rem; }
}

.login-card {
  position: relative; z-index: 1;
  background: color-mix(in srgb, var(--surface) 82%, transparent);
  backdrop-filter: blur(22px) saturate(160%);
  -webkit-backdrop-filter: blur(22px) saturate(160%);
  border: 0;
  border-radius: 0;
  padding: 2.75rem 2.4rem 2.4rem;
  box-shadow: none;
  flex: 1 1 56%;
  min-width: 0;
  max-width: none; width: auto; text-align: left;
  background: var(--surface);
  backdrop-filter: none; -webkit-backdrop-filter: none;
}
.login-card .login-title { font-size: 1.28rem; margin-bottom: .3rem; }
.login-card .login-subtitle { margin-bottom: 1.5rem; }
/* Both links keep their own line: "Forgot" and "password?" were splitting
   across a line break, leaving one word stranded. */
.login-links {
  display: flex; flex-direction: column; align-items: center; gap: .45rem;
  margin-top: 1.1rem; font-size: .85rem; color: var(--text-muted);
}
.login-links a { color: var(--primary); font-weight: 600; text-decoration: none; white-space: nowrap; }
.login-links a:hover { text-decoration: underline; }
@keyframes loginCardIn {
  from { opacity: 0; transform: translateY(14px) scale(.97); }
  to   { opacity: 1; transform: none; }
}


.login-title {
  margin: 0 0 .25rem; font-size: 1.5rem; font-weight: 800;
  letter-spacing: -.02em; color: var(--text);
  background: var(--gradient-1); -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent;
}
.login-subtitle { color: var(--text-muted); font-size: .85rem; margin-bottom: 1.75rem; }

.login-field { text-align: left; margin-bottom: 1.1rem; }
.login-field label {
  font-size: .74rem; font-weight: 700; color: var(--text-muted);
  display: block; margin-bottom: .4rem; text-transform: uppercase; letter-spacing: .05em;
}
.login-input-wrap { position: relative; }
.login-input-wrap svg {
  position: absolute; left: .85rem; top: 50%; transform: translateY(-50%);
  color: var(--text-muted); opacity: .6; pointer-events: none; transition: color .2s, opacity .2s;
}
.login-input-wrap input {
  width: 100%; padding: .75rem .9rem .75rem 2.6rem;
  border: 1.5px solid var(--input-border); border-radius: 12px;
  font-size: .95rem; background: var(--input-bg); color: var(--text);
  box-sizing: border-box; outline: none; font-family: inherit;
  transition: border-color .2s, box-shadow .2s;
}
.login-input-wrap input:focus {
  border-color: var(--primary);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--primary) 16%, transparent);
}
.login-input-wrap input:focus + svg,
.login-input-wrap:has(input:focus) svg { color: var(--primary); opacity: 1; }

.login-btn {
  position: relative; overflow: hidden; width: 100%; padding: .85rem;
  background: var(--gradient-1); color: #fff; border: none; border-radius: 12px;
  font-size: .95rem; font-weight: 700; letter-spacing: .01em; cursor: pointer;
  box-shadow: var(--shadow-lg); transition: transform .2s, box-shadow .2s;
}
.login-btn::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(115deg, transparent 40%, rgba(255,255,255,.35) 50%, transparent 60%);
  transform: translateX(-100%); transition: transform .6s ease;
}
.login-btn:hover { transform: translateY(-2px); box-shadow: var(--shadow-xl); }
.login-btn:hover::after { transform: translateX(100%); }
.login-btn:active { transform: translateY(0); }

.login-links { margin-top: .85rem; font-size: .82rem; color: var(--text-muted); }
.login-links a { color: var(--primary); font-weight: 600; text-decoration: none; }
.login-links a:hover { text-decoration: underline; }

/* ── Education: school-year list ──────────────────────────────────────────── */
.edu-tabs { display: flex; gap: .5rem; flex-wrap: wrap; margin-bottom: 1rem; }
.edu-tabs .btn { display: inline-flex; align-items: center; gap: .45rem; }

/* Count and total ride on the tab so the split can be read without opening
   both sides. */
.edu-tab-count {
  min-width: 1.35rem;
  padding: 0 .35rem;
  border-radius: 999px;
  background: var(--surface3);
  color: var(--text-label);
  font-size: .72rem;
  font-weight: 700;
  line-height: 1.35rem;
  text-align: center;
}
.btn-blue .edu-tab-count { background: rgba(255,255,255,.25); color: #fff; }
.edu-tab-sum { font-size: .74rem; font-weight: 500; opacity: .75; }

/* The academic year a school year belongs to — derived, never stored, so it is
   styled as a quiet label rather than as data someone typed. */
.edu-ay {
  display: inline-block;
  padding: .15rem .55rem;
  border-radius: 6px;
  background: var(--surface3);
  border: 1px solid var(--border);
  font-family: 'JetBrains Mono', monospace;
  font-size: .74rem;
  font-variant-numeric: tabular-nums;
  color: var(--text-label);
  white-space: nowrap;
}

/* A row that expands into a table of its own. */
tr.parent-row > td {
  background: var(--surface2);
  border-bottom: 1px solid var(--border);
}
tr.parent-row.is-open > td { background: var(--primary-light); }
tr.parent-row.is-open > td:first-child { box-shadow: inset 3px 0 0 var(--primary); }
tr.parent-row:hover > td { background: var(--card-glow); }

/* Where a year's money went. A footer rather than a header: it is a summary of
   the rows above, and reads as one once they have been seen. */
.subtable tfoot td {
  padding: .55rem .9rem;
  border-top: 1px solid var(--border);
  background: var(--surface2);
  font-size: .78rem;
}
.subtable-foot-types { white-space: normal; color: var(--text-muted); }
.subtable-foot-type { display: inline-block; margin-right: .9rem; white-space: nowrap; }
.subtable-foot-type b { color: var(--text); font-variant-numeric: tabular-nums; }
.subtable tfoot .subtable-foot-total { font-weight: 700; }

/* ── Nested detail tables ─────────────────────────────────────────────────────
   For a table whose rows expand into rows of a different shape. Used by the
   education fee list and by a property's additional expenses.

   Both pages used to render the expanded rows as plain rows of the outer table,
   which meant they inherited its column headers while carrying entirely
   different values. Education put a date under "Grade" and a fee type under
   "Institution". Property expenses were worse, three levels of row sharing one
   header: an expense's date sat under "Type", its description under "Count",
   its invoice number under "Sub-categories".

   A row that means something different needs headers of its own. That is all
   this is: the expanded rows get their own table, and carry only what actually
   varies between them.

   `.subtable-cell` is the outer <td colspan> that holds one; `.subtable` is the
   table inside it. They nest — a subtable's own row can expand into another —
   so nothing here assumes a single level. */
td.subtable-cell {
  padding: 0 0 0 2.25rem !important;
  max-width: none !important;
  white-space: normal !important;
  background: var(--surface3);
}
tr:hover > td.subtable-cell { background: var(--surface3); }

.subtable {
  width: 100%;
  border-collapse: collapse;
  border-left: 3px solid var(--primary);
  background: var(--surface);
}
.subtable th {
  padding: .5rem .9rem;
  font-size: .66rem;
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--text-muted);
  background: var(--surface2);
  border-bottom: 1px solid var(--border);
  border-radius: 0;
  text-align: left;
}
.subtable td {
  padding: .6rem .9rem;
  font-size: .84rem;
  border-bottom: 1px solid var(--border-light);
  background: transparent;
  max-width: none;
}
.subtable tbody > tr:last-child > td { border-bottom: none; }
/* Left unstriped deliberately: the list is short and reads better plain. */
.subtable tbody > tr > td { background: transparent; }
.subtable tbody > tr:hover > td { background: var(--card-glow); }

.subtable .subtable-date {
  font-family: 'JetBrains Mono', monospace;
  font-size: .78rem;
  font-variant-numeric: tabular-nums;
  color: var(--text-label);
  white-space: nowrap;
}
/* Amounts align on the right in both tables — the year totals in the outer one
   are meant to be compared down the column just as the fees are. */
.amt-cell {
  text-align: right;
  font-family: 'JetBrains Mono', monospace;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  white-space: nowrap;
}
th.amt-cell { text-align: right; }
/* Free text is the one column allowed to wrap — truncating a note to an
   ellipsis hides the only part of the row that is not already structured. */
.subtable .subtable-note {
  white-space: normal;
  color: var(--text-muted);
  font-size: .8rem;
  line-height: 1.45;
  min-width: 12rem;
}
/* A missing optional value should read as absent, not as content. */
.subtable .blank-cell { color: var(--border); }
.subtable .subtable-actions { white-space: nowrap; text-align: right; }

/* .badge alone sets only the pill shape — the colour comes from a per-category
   modifier (.badge-fuel and friends), and fee types come from the categories
   table, so there is no modifier to match. Left bare it rendered as bold text
   with stray padding. A neutral chip reads as a tag without inventing a colour
   scheme for values the database is free to change. */
.subtable .badge {
  background: var(--surface3);
  color: var(--text-label);
  border: 1px solid var(--border);
}

.caret-cell { color: var(--text-muted); font-size: .7rem; }

/* ── Bonds: the next coupon ──────────────────────────────────────────────────
   Amount first, date under it. The amount is what the row is scanned for —
   "what am I getting" — and the date qualifies it. */
.bond-next { display: flex; flex-direction: column; line-height: 1.25; }
.bond-next-amt {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  font-size: .82rem;
}
.bond-next-date { font-size: .7rem; color: var(--text-muted); white-space: nowrap; }
/* A projection, not a payment that has happened. Marked so the two are never
   read as the same kind of number. */
.bond-next-est {
  font-size: .6rem;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  padding: 0 .25rem;
  border-radius: 3px;
  background: var(--surface3);
  color: var(--text-muted);
}

/* ── Property expenses: pick a category, then read one list ──────────────────
   Modelled on the Insurance page, where a policy gives way to a page of its
   own rather than unfolding in place. Expenses used to nest three levels of
   collapsible table — a type opened into sub-categories, which opened into
   bills — so reaching one bill took two expansions, and everything opened on
   the way there stayed on screen. */
.re-cat-cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(165px, 1fr));
  gap: .6rem;
  margin-bottom: 1rem;
}
.re-cat {
  display: flex;
  flex-direction: column;
  gap: .2rem;
  padding: .7rem .85rem .6rem;
  text-align: left;
  font-family: inherit;
  cursor: pointer;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  transition: border-color .15s ease, box-shadow .15s ease, transform .15s ease;
}
.re-cat:hover { border-color: var(--primary); transform: translateY(-1px); }
.re-cat.is-active {
  border-color: var(--primary);
  box-shadow: 0 0 0 1px var(--primary), var(--shadow-sm);
  background: var(--primary-light);
}
.re-cat-name {
  font-size: .78rem; font-weight: 600; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.re-cat-val {
  font-size: 1.05rem; font-weight: 700; color: var(--text);
  font-variant-numeric: tabular-nums;
}
.re-cat-meta { font-size: .68rem; color: var(--text-muted); }
/* The share as a rule under the figure. A stacked bar across the top could not
   show the 0.2% category at all; here every category gets its own scale. */
.re-cat-bar {
  position: relative; display: block; height: 3px; margin-top: .35rem;
  border-radius: 2px; background: var(--surface3); overflow: hidden;
}
.re-cat-bar > i {
  position: absolute; inset: 0 auto 0 0;
  border-radius: 2px; display: block; min-width: 2px;
}

.re-exp-detail {
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: .9rem 1rem 1rem;
  background: var(--surface);
}
.re-exp-head {
  display: flex; justify-content: space-between; align-items: flex-start;
  gap: 1rem; margin-bottom: .8rem;
}
.re-exp-title { font-size: .98rem; font-weight: 700; }
.re-exp-sub { font-size: .76rem; color: var(--text-muted); margin-top: .15rem; }
.re-sub-chips {
  display: flex; flex-wrap: wrap; gap: .4rem; margin-bottom: .9rem;
  padding-bottom: .8rem; border-bottom: 1px solid var(--border-light);
}
.re-sub-chips .member-chip { font-size: .75rem; padding: .25rem .6rem; }
.re-sub-chips .member-chip b { font-weight: 700; margin-left: .15rem; }
.re-exp-hint { font-size: .78rem; color: var(--text-muted); padding: .5rem 0; }

@media (max-width: 820px) {
  td.subtable-cell { padding-left: .5rem !important; }
  .subtable .subtable-note { min-width: 0; }
}

/* ── Emergency sheet ─────────────────────────────────────────────────────── */
#em-sheet .em-section { margin-bottom: 1.25rem; }
#em-sheet h3 { font-size: .95rem; margin: 0 0 .4rem; }
#em-sheet .em-note { padding: .6rem .8rem; border: 1px solid var(--border); border-radius: var(--radius-xs); font-size: .9rem; }
.em-missing { color: var(--danger); font-style: italic; }

/* Hover and focus effects that used to be inline onmouseover/onfocus scripts,
   which the Content-Security-Policy no longer runs. !important because the
   elements carry inline styles for their resting look. */
.hover-danger:hover { border-color: var(--danger) !important; color: var(--danger) !important; }
.hover-surface:hover { background: var(--surface2) !important; }
#global-search:focus { border-color: var(--primary) !important; }

/* The 👁 beside a masked account or card number. */
.btn-icon { background: none; border: none; cursor: pointer; padding: 0 .2rem; font-size: .9em; opacity: .7; }
.btn-icon:hover { opacity: 1; }

/* Waiting approvals, beside the nav link. */
.nav-badge { display: inline-block; min-width: 1.2rem; padding: 0 .35rem; margin-left: .35rem; border-radius: 999px;
  background: var(--danger); color: #fff; font-size: .7rem; font-weight: 700; line-height: 1.2rem; text-align: center; }
.text-muted { color: var(--text-muted); }
.text-danger { color: var(--danger); }

/* Reconcile page tabs */
.rec-tab.active { background: var(--primary); color: #fff; border-color: var(--primary); }

/* Lockers page */
.lck-line { font-size: .8rem; color: var(--text-muted); }
.lck-due-soon { color: var(--warning); font-weight: 600; }
.lck-due-over { color: var(--danger); font-weight: 700; }
.lck-tab.active { background: var(--primary); color: #fff; border-color: var(--primary); }
.lck-visit-cols { display: grid; grid-template-columns: 1fr 1.6fr; gap: 1rem; margin-top: .5rem; }
@media (max-width: 800px) { .lck-visit-cols { grid-template-columns: 1fr; } }
.lck-subhead { font-size: .75rem; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--text-muted); margin-bottom: .4rem; }
.lck-out-row { display: flex; gap: .5rem; align-items: flex-start; padding: .35rem .2rem; border-bottom: 1px solid var(--border); font-size: .85rem; cursor: pointer; }
.lck-timeline { display: flex; flex-direction: column; gap: .5rem; }
.lck-visit { border-left: 3px solid var(--primary); padding: .35rem .75rem; background: var(--surface2); border-radius: 0 8px 8px 0; }
.lck-in { color: var(--success); font-size: .85rem; }
.lck-outline { color: var(--danger); font-size: .85rem; }
.lckv-row { flex-wrap: nowrap; align-items: flex-end; }
.lckv-row .field { min-width: 0; }
@media (max-width: 700px) { .lckv-row { flex-wrap: wrap; } }

/* ═══════════════════════════════════════════════════════════════════════════
   APPROVALS — one card per request, so a phone never has to scroll sideways
   to reach the Approve button.
   ═══════════════════════════════════════════════════════════════════════════ */
.apr-list { display: flex; flex-direction: column; gap: .6rem; }
.apr-card {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface2);
  padding: .75rem .85rem;
  display: flex;
  flex-direction: column;
  gap: .3rem;
}
.apr-head { display: flex; justify-content: space-between; align-items: baseline; gap: .5rem; flex-wrap: wrap; }
.apr-status { font-size: .72rem; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--text-muted); }
.apr-pending, .apr-approving { color: var(--warning); }
.apr-approved { color: var(--success); }
.apr-rejected, .apr-failed { color: var(--danger); }
.apr-fields { font-size: .82rem; line-height: 1.5; word-break: break-word; }
.apr-meta { font-size: .75rem; color: var(--text-muted); }
.apr-actions { display: flex; gap: .5rem; margin-top: .35rem; }
@media (max-width: 768px) {
  .apr-actions { flex-direction: column; }
  .apr-actions .btn { width: 100%; padding: .6rem 1rem; font-size: .85rem; }
}

/* ── The "More" sheet's own furniture ──────────────────────────────────────
   The sheet is built from the sidebar at open time (buildMobileSheet), so
   these style whatever that produces: a heading per sidebar group, a filter
   box, and a count on a tile that carries one. */
.mob-sheet-search { display: none; }
@media (max-width: 768px) {
  .mob-sheet-search {
    display: block;
    width: 100%;
    padding: .6rem .75rem;
    margin-bottom: .75rem;
    border: 1.5px solid var(--border);
    border-radius: var(--radius-xs);
    background: var(--input-bg);
    color: var(--text);
    font-size: .95rem;   /* 16px or more, or iOS zooms the page on focus */
    font-family: inherit;
  }
  .mob-sheet-group {
    grid-column: 1 / -1;
    font-size: .68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--text-muted);
    padding: .5rem .25rem .1rem;
  }
  .mob-sheet-group:first-child { padding-top: 0; }
  .mob-sheet-item { position: relative; }
  .mob-sheet-badge, .mob-tab-badge {
    position: absolute;
    top: 4px;
    right: 6px;
    min-width: 17px;
    padding: 1px 4px;
    border-radius: 999px;
    background: var(--danger);
    color: #fff;
    font-size: .6rem;
    font-weight: 700;
    line-height: 15px;
    text-align: center;
  }
  .mob-tab-badge { top: 4px; right: 50%; margin-right: -22px; }
}

/* The locker whose detail panel is open, so the row and the panel below it
   read as one thing. */
.lck-row-open > td {
  background: var(--card-glow);
  box-shadow: inset 3px 0 0 var(--primary);
}

/* The account column was squeezing "SBI FD 2026" onto two lines while the
   table had space to spare on the right. The badge never breaks from the name
   it belongs to. */
#sav-list td:nth-child(2) { min-width: 15rem; }
#sav-list td:nth-child(2) .badge { white-space: nowrap; }

/* ── One size for every glyph that leads a button ────────────────────────────
   Emoji are text: each platform renders them at its own metrics and on its own
   baseline, so ✓, 🔄 and 🗑 came out three different sizes in the same row and
   no amount of CSS could reach a bare character to fix it. Wrapping the
   leading glyph gives something to size — a fixed box, one font size, one
   baseline — so a row of buttons lines up whatever glyphs it happens to carry.

   This makes them uniform, not drawn. The chips' icons are real SVGs on
   currentColor; these are still emoji and still cannot take the button's
   colour. Replacing the art is the next step, not this one. */
.btn-gl {
  display: inline-block;
  /* Absolute, not em. Relative sizing made the glyph follow each button's own
     scale, which meant five different sizes across the app and two in a single
     row — a small "Live Rate" beside a large "Update All". One size, wherever
     it appears. */
  width: 1.1rem;
  font-size: .95rem;
  line-height: 1;
  text-align: center;
  flex: 0 0 auto;
  font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
  font-variant-emoji: text;
}

/* The Part B statement on screen. The print window carries its own copy of
   these, because theme variables mean nothing in a new document. */
.f16-head { display: flex; justify-content: space-between; align-items: flex-end;
            border-bottom: 2px solid var(--border); padding-bottom: .6rem; margin-bottom: 1rem; }
.f16-title { font-size: 1.15rem; font-weight: 800; }
.f16-sub { font-size: .82rem; color: var(--text-muted); }
.f16-table { width: 100%; border-collapse: collapse; max-width: 640px; }
.f16-table td { padding: .35rem .5rem; border-bottom: 1px solid var(--border-light); }
.f16-section td { background: var(--surface2); font-weight: 700; font-size: .7rem;
                  text-transform: uppercase; letter-spacing: .06em; padding-top: .6rem; }
.f16-note { font-size: .74rem; color: var(--text-muted); margin-top: .9rem; max-width: 640px; }


/* Contacts. A phone book is scanned, not read: rows sit tight together, the
   line under a name is for what the phone called the relationship, and the
   header stays put when a few hundred of them scroll past. */
.mpd-table { font-size: .83rem; border-collapse: collapse; table-layout: auto; }
/* A name is the thing you scan for, so it gets room before anything else and
   does not wrap onto two lines to make space for an address. */
.mpd-table td:nth-child(2) { min-width: 11rem; }
.mpd-table td:nth-child(3) { white-space: nowrap; }
.mpd-table thead th {
  position: sticky; top: 0; z-index: 1;
  background: var(--surface); text-align: left;
  font-size: .7rem; letter-spacing: .04em; text-transform: uppercase;
  color: var(--text-muted); font-weight: 600;
  padding: .4rem .5rem; border-bottom: 1px solid var(--border);
}
.mpd-table tbody tr { border-bottom: 1px solid var(--border); }
.mpd-table tbody tr:last-child { border-bottom: 0; }
.mpd-table tbody tr:hover { background: var(--surface2); }
.mpd-table a[href^="tel:"] { color: var(--text); text-decoration: none; }
.mpd-table a[href^="tel:"]:hover { color: var(--primary); text-decoration: underline; }


/* The move notice. Fixed to the bottom rather than the top: the sidebar and
   the search bar are already fixed up there, and a bar that fights them is a
   bar that covers something. */
.moved-notice {
  /* Above the login screen, which is fixed at 10000 and otherwise covers
     this completely — and somebody stuck at the sign-in page on the old
     address is precisely who needs to be told where the app went. */
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 10001;
  background: var(--sidebar-from); color: #fff;
  border-top: 1px solid rgba(255,255,255,.15);
  box-shadow: 0 -6px 24px rgba(0,0,0,.18);
}
.moved-notice-body {
  max-width: 1100px; margin: 0 auto; padding: .7rem 1rem;
  display: flex; align-items: center; gap: 1rem; flex-wrap: wrap;
  justify-content: space-between;
}
.moved-notice-text { font-size: .85rem; line-height: 1.5; }
.moved-notice-text b { font-weight: 700; }
/* The consequences, quieter than the headline but on the same bar — they are
   the part that stops a working move looking like a broken one. */
.moved-notice-fine { display: block; font-size: .76rem; opacity: .8; margin-top: .15rem; }
.moved-notice-actions { display: flex; gap: .4rem; align-items: center; flex-shrink: 0; }
@media (max-width: 640px) {
  .moved-notice-body { padding: .6rem .75rem; }
  .moved-notice-actions { width: 100%; }
}
