/* Design tokens — three themes (Country/Dark/Light), switched via
   [data-theme] on <html> (see js/theme.js). "Country" — matching
   tech.ridgeway.cloud's look — is the default. All values below are
   re-mapped per theme; every other rule in this file only ever references
   the variable names, never a raw colour, so the whole app re-themes
   instantly. --font-display is used only for the app title/byline; every
   other font-family reference uses --font. */
:root {
  --font: "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, Arial, sans-serif;
  --font-display: var(--font);

  --app-bg: #14161a;
  --card-bg: #1c1f26;
  --card-bg-raised: #262a33;
  --border-subtle: #2c303a;
  --border-strong: #3d424e;

  --text-primary: #eef0f3;
  --muted: #8b93a1;
  --brand-accent: #4cc9f0;

  --btn-primary: #3b82f6;
  --btn-primary-hov: #5b9bfb;
  --btn-neutral: #262a33;
  --btn-neutral-hov: #323744;
  --btn-neutral-text: #eef0f3;
  --btn-accent: #16a184;
  --btn-accent-hov: #1cbe9c;
  --btn-destructive: #dc4a4a;
  --btn-destructive-hov: #ea5f5f;

  --gain: #34d399;
  --loss: #f87171;
  --warning: #fbbf24;
  --warning-bg: #3a2e10;
  --highlight: #eab308;

  --danger-bg: #3a1414;

  --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.35);
  --shadow-md: 0 6px 20px rgba(0, 0, 0, 0.4);
  --shadow-lg: 0 16px 48px rgba(0, 0, 0, 0.55);
  --overlay-bg: rgba(8, 9, 12, 0.65);
  --focus-ring: rgba(59, 130, 246, 0.35);

  --radius-sm: 7px;
  --radius-md: 11px;
  --radius-lg: 16px;

  --header-height: 53px;
}

[data-theme="light"] {
  --font-display: var(--font);
  --app-bg: #f2f3f6;
  --card-bg: #ffffff;
  --card-bg-raised: #f1f2f5;
  --border-subtle: #e2e4e9;
  --border-strong: #cfd2d9;

  --text-primary: #171a1f;
  --muted: #667085;
  --brand-accent: #0891b2;

  --btn-primary: #2563eb;
  --btn-primary-hov: #1d4ed8;
  --btn-neutral: #eceef2;
  --btn-neutral-hov: #dfe2e8;
  --btn-neutral-text: #171a1f;
  --btn-accent: #0d9488;
  --btn-accent-hov: #0b7d73;
  --btn-destructive: #dc2626;
  --btn-destructive-hov: #b91c1c;

  --gain: #059669;
  --loss: #dc2626;
  --warning: #b45309;
  --warning-bg: #fef3c7;
  --highlight: #b45309;

  --danger-bg: #fee2e2;

  --shadow-sm: 0 1px 2px rgba(16, 24, 40, 0.06);
  --shadow-md: 0 6px 20px rgba(16, 24, 40, 0.08);
  --shadow-lg: 0 16px 48px rgba(16, 24, 40, 0.14);
  --overlay-bg: rgba(23, 26, 31, 0.4);
  --focus-ring: rgba(37, 99, 235, 0.2);
}

/* "Country" — the default theme, matching tech.ridgeway.cloud: warm cream
   paper background, near-black warm text, deep forest-green brand accent,
   and an "Instrument Serif" display face for the app title (loaded from
   Google Fonts in index.html). */
[data-theme="country"] {
  --font-display: "Instrument Serif", Georgia, serif;

  /* Same frosted-glass treatment as the two Glassmorphism themes further
     down — card/raised backgrounds and borders become translucent (instead
     of flat opaque colours) so the blur + gradient glow added below shows
     through. Hue is unchanged, just alpha. */
  --app-bg: #f4f1eb;
  --card-bg: rgba(255, 255, 255, 0.5);
  --card-bg-raised: rgba(232, 227, 216, 0.62);
  --border-subtle: rgba(224, 219, 204, 0.55);
  --border-strong: rgba(201, 190, 172, 0.7);

  --text-primary: #1a1917;
  --muted: #6b6558;
  --brand-accent: #2a3d28;

  /* Gradients instead of flat fills, mixing Country's own two brand
     colours (forest green + gold) rather than introducing new hues. */
  --btn-primary: linear-gradient(135deg, #2a3d28, #3a4f38);
  --btn-primary-hov: linear-gradient(135deg, #3a4f38, #4a5f48);
  --btn-neutral: linear-gradient(135deg, rgba(232, 227, 216, 0.75), rgba(232, 227, 216, 0.4));
  --btn-neutral-hov: linear-gradient(135deg, rgba(221, 214, 194, 0.88), rgba(221, 214, 194, 0.55));
  --btn-neutral-text: #1a1917;
  --btn-accent: linear-gradient(135deg, #2a3d28, #93701f);
  --btn-accent-hov: linear-gradient(135deg, #3a4f38, #a9832f);
  --btn-destructive: linear-gradient(135deg, #a1403a, #7d322d);
  --btn-destructive-hov: linear-gradient(135deg, #b94f48, #a1403a);

  --gain: #3f7d4f;
  --loss: #a1403a;
  --warning: #a1750f;
  --warning-bg: #f3e6c4;
  --highlight: #8a6d1f;

  --danger-bg: #f2ded9;

  --shadow-sm: 0 1px 3px rgba(26, 25, 23, 0.08);
  --shadow-md: 0 6px 20px rgba(26, 25, 23, 0.1);
  --shadow-lg: 0 16px 48px rgba(26, 25, 23, 0.18), 0 0 40px rgba(42, 61, 40, 0.14);
  --overlay-bg: rgba(26, 25, 23, 0.45);
  --focus-ring: rgba(42, 61, 40, 0.25);

  /* Softer, more rounded "Vision Pro" surfaces — matches both Glassmorphism themes. */
  --radius-sm: 9px;
  --radius-md: 16px;
  --radius-lg: 22px;

  /* Taller header — the title/byline block below is bigger in this theme. */
  --header-height: 74px;
}

/* "Dark Glassmorphism" — Apple Vision Pro meets modern SaaS: near-black
   base (#0B0F14), translucent frosted-glass cards, a purple→blue gradient
   glow behind everything, and blurred surfaces for the header/sidebar/modals.
   The actual blur/backdrop-filter/gradient rules live further down (search
   "glass" theme) since those aren't expressible as plain colour tokens —
   this block only sets the colour/shadow/radius variables every other rule
   already reads. */
[data-theme="glass"] {
  --font-display: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;

  --app-bg: #0b0f14;
  --card-bg: rgba(255, 255, 255, 0.055);
  --card-bg-raised: rgba(255, 255, 255, 0.09);
  --border-subtle: rgba(255, 255, 255, 0.12);
  --border-strong: rgba(255, 255, 255, 0.26);

  --text-primary: #f2f5fa;
  --muted: #98a2b3;
  --brand-accent: #a78bfa;

  --btn-primary: linear-gradient(135deg, #7c3aed, #3b82f6);
  --btn-primary-hov: linear-gradient(135deg, #8b5cf6, #60a5fa);
  --btn-neutral: linear-gradient(135deg, rgba(255, 255, 255, 0.11), rgba(255, 255, 255, 0.04));
  --btn-neutral-hov: linear-gradient(135deg, rgba(255, 255, 255, 0.19), rgba(255, 255, 255, 0.09));
  --btn-neutral-text: #f2f5fa;
  --btn-accent: linear-gradient(135deg, #22d3ee, #6366f1);
  --btn-accent-hov: linear-gradient(135deg, #67e8f9, #818cf8);
  --btn-destructive: linear-gradient(135deg, #ef4444, #dc2626);
  --btn-destructive-hov: linear-gradient(135deg, #f87171, #ef4444);

  --gain: #34d399;
  --loss: #fb7185;
  --warning: #fbbf24;
  --warning-bg: rgba(251, 191, 36, 0.14);
  --highlight: #c4b5fd;

  --danger-bg: rgba(239, 68, 68, 0.14);

  --shadow-sm: 0 2px 10px rgba(0, 0, 0, 0.4);
  --shadow-md: 0 10px 32px rgba(0, 0, 0, 0.5);
  --shadow-lg: 0 26px 64px rgba(0, 0, 0, 0.6), 0 0 44px rgba(124, 58, 237, 0.18);
  --overlay-bg: rgba(4, 6, 9, 0.75);
  --focus-ring: rgba(139, 92, 246, 0.4);

  /* Softer, more rounded "Vision Pro" surfaces. */
  --radius-sm: 9px;
  --radius-md: 16px;
  --radius-lg: 22px;

  --header-height: 60px;
}

/* "Light Glassmorphism" — the same frosted-glass, blurred-surface look as
   Dark Glassmorphism above, just flipped to a light base with an orange→red
   gradient glow instead of purple→blue. Structural rules (blur, gradients,
   large typography) live further down alongside the dark variant's. */
[data-theme="glass-light"] {
  --font-display: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;

  --app-bg: #faf6f3;
  --card-bg: rgba(255, 255, 255, 0.5);
  --card-bg-raised: rgba(255, 255, 255, 0.72);
  --border-subtle: rgba(120, 53, 15, 0.1);
  --border-strong: rgba(120, 53, 15, 0.22);

  --text-primary: #241a14;
  --muted: #8a7468;
  --brand-accent: #ea580c;

  --btn-primary: linear-gradient(135deg, #f97316, #ef4444);
  --btn-primary-hov: linear-gradient(135deg, #fb923c, #f87171);
  --btn-neutral: linear-gradient(135deg, rgba(120, 53, 15, 0.1), rgba(120, 53, 15, 0.03));
  --btn-neutral-hov: linear-gradient(135deg, rgba(120, 53, 15, 0.18), rgba(120, 53, 15, 0.08));
  --btn-neutral-text: #241a14;
  --btn-accent: linear-gradient(135deg, #fb7185, #f97316);
  --btn-accent-hov: linear-gradient(135deg, #fda4af, #fb923c);
  --btn-destructive: linear-gradient(135deg, #dc2626, #b91c1c);
  --btn-destructive-hov: linear-gradient(135deg, #ef4444, #dc2626);

  --gain: #059669;
  --loss: #dc2626;
  --warning: #b45309;
  --warning-bg: rgba(180, 83, 9, 0.14);
  --highlight: #c2410c;

  --danger-bg: rgba(220, 38, 38, 0.1);

  --shadow-sm: 0 2px 10px rgba(120, 53, 15, 0.1);
  --shadow-md: 0 10px 32px rgba(120, 53, 15, 0.14);
  --shadow-lg: 0 26px 64px rgba(120, 53, 15, 0.18), 0 0 44px rgba(249, 115, 22, 0.18);
  --overlay-bg: rgba(250, 246, 243, 0.7);
  --focus-ring: rgba(249, 115, 22, 0.35);

  /* Softer, more rounded "Vision Pro" surfaces — matches the dark variant. */
  --radius-sm: 9px;
  --radius-md: 16px;
  --radius-lg: 22px;

  --header-height: 60px;
}

/* "Professional" — institutional-confidence-meets-modern-fintech: a single
   deep ink-navy base throughout (no per-section light/dark flips — every
   other rule in this file assumes --text-primary reads correctly against
   both --app-bg and --card-bg, so unlike a marketing page this can't
   literally flip a "hero" section to warm off-white without a much bigger
   text-colour refactor). Warm off-white shows up instead as the dominant
   TEXT colour and as a restrained highlight surface (raised cards, active
   tabs), and the "one confident accent, used sparingly" is a single
   electric teal — spent almost entirely on primary CTAs, the brand
   wordmark, and focus rings, never on more than one element per view.
   Hairline borders (8–12% white opacity) replace heavy shadows; the only
   glow is a very low-opacity radial mesh behind the login screen (this
   app's closest equivalent to a marketing "hero") and a barely-there
   backdrop blur on the header — deliberately restrained to "glass used
   once, not everywhere", unlike the three Glassmorphism-flavoured themes
   above. Structural rules (grain overlay, header blur, card hover-lift,
   tabular-numeral stats) live further down, alongside the other themes'. */
[data-theme="professional"] {
  --font-display: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;

  --app-bg: #0b1220;
  --card-bg: #101828;
  --card-bg-raised: #16202f;
  --border-subtle: rgba(248, 247, 244, 0.08);
  --border-strong: rgba(248, 247, 244, 0.16);

  --text-primary: #f8f7f4;
  --muted: #8891a3;
  --brand-accent: #14b8a6;

  /* Deeper teal than --brand-accent for button fills specifically — the
     bright #14b8a6 reads great as TEXT on navy (7.5:1) but fails WCAG AA
     for the white button label on top of it (2.5:1). These two shades keep
     the same hue but darken enough for the forced-white .btn text to clear
     4.5:1 (see the code comment at the top of this file). */
  --btn-primary: #0f766e;
  --btn-primary-hov: #107a71;
  --btn-neutral: rgba(248, 247, 244, 0.06);
  --btn-neutral-hov: rgba(248, 247, 244, 0.1);
  --btn-neutral-text: #f8f7f4;
  --btn-accent: #115e59;
  --btn-accent-hov: #0f766e;
  --btn-destructive: #b3261e;
  --btn-destructive-hov: #dc2626;

  --gain: #22c55e;
  --loss: #f87171;
  --warning: #eab308;
  --warning-bg: rgba(234, 179, 8, 0.12);
  --highlight: #eab308;

  --danger-bg: rgba(239, 68, 68, 0.1);

  --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.3);
  --shadow-md: 0 8px 24px rgba(0, 0, 0, 0.35);
  --shadow-lg: 0 20px 50px rgba(0, 0, 0, 0.5), 0 0 40px rgba(20, 184, 166, 0.08);
  --overlay-bg: rgba(5, 8, 14, 0.7);
  --focus-ring: rgba(20, 184, 166, 0.35);

  /* "Rounded corners consistent at 12–16px; buttons pill or 8px, pick one" —
     8px for buttons/inputs (--radius-sm), 12/16 for cards and modals. */
  --radius-sm: 8px;
  --radius-md: 12px;
  --radius-lg: 16px;

  --header-height: 60px;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--app-bg);
  color: var(--text-primary);
  font-family: var(--font);
  font-size: 16px;
  transition: background 0.2s ease, color 0.2s ease;
}

.hidden { display: none !important; }

/* thin, theme-aware scrollbars */
* { scrollbar-width: thin; scrollbar-color: var(--border-strong) transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 8px; }
*::-webkit-scrollbar-track { background: transparent; }

/* consistent, visible keyboard focus everywhere, without adding an ugly
   default outline to every mouse click */
a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible {
  outline: 2px solid var(--btn-primary);
  outline-offset: 2px;
}

/* ---------- Login ---------- */
.login-screen {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--app-bg);
}
.login-card {
  background: var(--card-bg);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  padding: 36px 32px;
  width: 340px;
  max-width: 92vw;
  box-shadow: var(--shadow-lg);
}
.app-title { font-family: var(--font-display); font-size: 32px; font-weight: 700; margin: 0; color: var(--brand-accent); letter-spacing: -0.01em; line-height: 1.1; }
.app-byline { font-style: italic; font-family: var(--font-display); color: var(--muted); font-size: 0.85em; margin: 2px 0 0; }
.app-subtitle { color: var(--muted); margin: 14px 0 20px 0; }

/* Generic underlined text-button — used for secondary, low-emphasis actions
   that don't warrant a full .btn (e.g. "Forgot password?"). */
.link-btn {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  color: var(--brand-accent);
  cursor: pointer;
  text-decoration: underline;
}
.link-btn:hover { opacity: 0.8; }
.proj-info-link { margin-left: 8px; font-weight: 400; font-size: 12px; text-transform: none; letter-spacing: normal; color: var(--brand-accent); }
.login-forgot-link { display: block; margin: 8px 0 4px; text-align: right; }

/* ---------------------------------------------------------------------------
   "Corporate" theme — modelled on invesco.com (UK). A clean, light,
   institutional look: white cards on a cool light-grey page, deep "Invesco
   blue" navy text, a royal-blue primary and lightly-squared corners. Inter
   stands in for Invesco's grotesque brand typeface. Component-level touches
   (navy header, blue tab underline, squarer cards) are further down.
   --------------------------------------------------------------------------- */
[data-theme="corporate"] {
  --font: "Inter", "Helvetica Neue", Arial, sans-serif;
  --font-display: "Inter", "Helvetica Neue", Arial, sans-serif;

  --app-bg: #eef2f7;
  --card-bg: #ffffff;
  --card-bg-raised: #f5f8fc;
  --border-subtle: #dce3ec;
  --border-strong: #c2cdda;

  --text-primary: #0c1e42; /* Invesco deep navy */
  --muted: #566484;
  --brand-accent: #000ad2; /* Invesco blue (#000AD2, RGB 0/10/210) */

  /* Exact "Invesco blue" fills; dark enough for forced-white .btn labels. */
  --btn-primary: #000ad2;
  --btn-primary-hov: #1a24e6;
  --btn-neutral: #eef1f7;
  --btn-neutral-hov: #e0e6f0;
  --btn-neutral-text: #0c1e42;
  --btn-accent: #1a24e6;
  --btn-accent-hov: #000ad2;
  --btn-destructive: #c8102e; /* institutional red */
  --btn-destructive-hov: #a50d26;

  --gain: #157f3c;
  --loss: #c8102e;
  --warning: #b26a00;
  --warning-bg: rgba(178, 106, 0, 0.1);
  --highlight: #000ad2;

  --danger-bg: rgba(200, 16, 46, 0.08);

  --shadow-sm: 0 1px 2px rgba(12, 30, 66, 0.08);
  --shadow-md: 0 4px 16px rgba(12, 30, 66, 0.1);
  --shadow-lg: 0 20px 48px rgba(12, 30, 66, 0.16);
  --overlay-bg: rgba(12, 30, 66, 0.45);
  --focus-ring: rgba(0, 10, 210, 0.35);

  /* Squarer than the other themes for a corporate/institutional feel. */
  --radius-sm: 4px;
  --radius-md: 6px;
  --radius-lg: 10px;

  --header-height: 60px;
}

/* ---------------------------------------------------------------------------
   "Bread" theme — built on the deep navy of the Bread logo (#0B3661): a warm,
   friendly DARK theme. White text on layered navy surfaces (matching the white
   wordmark), a wheat-gold brand accent for titles/links/highlights (the crust),
   and soft rounded corners echoing the rounded logo lettering.
   --------------------------------------------------------------------------- */
[data-theme="bread"] {
  --font: "Inter", "Helvetica Neue", Arial, sans-serif;
  --font-display: "Inter", "Helvetica Neue", Arial, sans-serif;

  --app-bg: #082a4d;          /* a touch deeper than the logo navy so cards lift */
  --card-bg: #0b3661;         /* the logo navy */
  --card-bg-raised: #0f416f;
  --border-subtle: #1c4f80;
  --border-strong: #2c6199;

  --text-primary: #f4f8fc;    /* near-white, like the wordmark */
  --muted: #a6c1dc;
  --brand-accent: #e8b96a;    /* wheat-gold "crust" accent */

  /* Labels are forced white (.btn), so button fills stay readable blues; the
     gold shows through as the brand accent (title, links, underline, ticks). */
  --btn-primary: #2f6fb3;
  --btn-primary-hov: #3d82cc;
  --btn-neutral: #123f6b;
  --btn-neutral-hov: #17508a;
  --btn-neutral-text: #eaf2fb;
  --btn-accent: #1f5c9e;
  --btn-accent-hov: #2a6cb3;
  --btn-destructive: #d64550;
  --btn-destructive-hov: #b8323c;

  --gain: #4ade80;
  --loss: #f87171;
  --warning: #fbbf24;
  --warning-bg: rgba(251, 191, 36, 0.12);
  --highlight: #e8b96a;

  --danger-bg: rgba(248, 113, 113, 0.12);

  --shadow-sm: 0 1px 2px rgba(2, 12, 28, 0.4);
  --shadow-md: 0 4px 16px rgba(2, 12, 28, 0.5);
  --shadow-lg: 0 20px 48px rgba(2, 12, 28, 0.6);
  --overlay-bg: rgba(4, 18, 38, 0.6);
  --focus-ring: rgba(232, 185, 106, 0.4);

  /* Soft, friendly rounding to echo the rounded logo lettering. */
  --radius-sm: 8px;
  --radius-md: 12px;
  --radius-lg: 18px;

  --header-height: 60px;
}

/* Country theme: title sizes match tech.ridgeway.cloud's own (89.6px hero
   heading, 28.8px header wordmark) at desktop widths, scaling down smoothly
   on narrow screens via clamp() so nothing overflows. The login card also
   widens to give the much bigger serif title room to breathe. */
[data-theme="country"] .login-card { width: 460px; }
[data-theme="country"] .app-title {
  font-size: clamp(40px, 8vw, 89.6px);
  font-weight: 400;
  line-height: 1.02;
}
[data-theme="country"] .app-title-sm {
  font-size: clamp(18px, 3vw, 28.8px);
  font-weight: 400;
}
/* The byline reads too small next to the much bigger login-screen title —
   bump it up (login/signup only; the header's byline has its own rule). */
[data-theme="country"] .login-card .app-byline {
  font-size: 22px;
}
.login-card label, .modal-card label { display: block; margin: 12px 0 4px; color: var(--muted); font-size: 14px; font-weight: 600; }
.login-card input, .modal-card input, .modal-card select {
  width: 100%;
  padding: 9px 11px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-subtle);
  background: var(--card-bg-raised);
  color: var(--text-primary);
  font-family: var(--font);
  font-size: 16px;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.login-card input:focus, .modal-card input:focus, .modal-card select:focus {
  outline: none;
  border-color: var(--btn-primary);
  box-shadow: 0 0 0 3px var(--focus-ring);
}
/* The width:100% above targets text/email/password inputs — it also
   matched the "Remember me" checkbox (still an <input> inside .login-card),
   stretching its layout box to the full row width and pushing the label
   text onto the next line instead of sitting beside it. Scope it back down
   to its natural size within any .checkbox-row (login or modal). */
.checkbox-row input[type="checkbox"] { width: auto; flex-shrink: 0; }
.error-text { color: var(--loss); font-size: 14px; min-height: 16px; margin-top: 8px; }

/* ---------- Buttons ---------- */
.btn {
  font-family: var(--font);
  font-weight: 600;
  font-size: 15px;
  border: none;
  border-radius: var(--radius-sm);
  padding: 10px 16px;
  cursor: pointer;
  color: #fff;
  background: var(--btn-neutral);
  transition: background 0.15s ease, transform 0.1s ease, box-shadow 0.15s ease;
}
.btn:hover { background: var(--btn-neutral-hov); }
.btn:active { transform: translateY(1px); }
.btn-primary { background: var(--btn-primary); box-shadow: var(--shadow-sm); }
.btn-primary:hover { background: var(--btn-primary-hov); box-shadow: var(--shadow-md); }
.btn-neutral { background: var(--btn-neutral); color: var(--btn-neutral-text); }
.btn-neutral:hover { background: var(--btn-neutral-hov); }
.btn-accent { background: var(--btn-accent); box-shadow: var(--shadow-sm); }
.btn-accent:hover { background: var(--btn-accent-hov); box-shadow: var(--shadow-md); }
.btn-destructive { background: var(--btn-destructive); }
.btn-destructive:hover { background: var(--btn-destructive-hov); }
.btn-block { width: 100%; margin-top: 14px; }
.btn-sm { padding: 6px 10px; font-size: 14px; }
.btn:disabled { opacity: 0.5; cursor: not-allowed; transform: none; }
.file-btn { display: inline-flex; align-items: center; justify-content: center; }

/* ---------- App shell ---------- */
.app-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 14px 24px;
  background: var(--card-bg);
  border-bottom: 1px solid var(--border-subtle);
  position: relative;
  z-index: 50;
}
.header-left { display: flex; align-items: center; gap: 10px; min-width: 0; }
.header-title-block { display: flex; flex-direction: column; justify-content: center; min-width: 0; }
.app-title-sm { font-family: var(--font-display); font-size: 21px; margin: 0; white-space: nowrap; font-weight: 700; letter-spacing: -0.01em; line-height: 1.15; }
.header-title-block .app-byline { font-size: 14px; margin: 0; line-height: 1.1; white-space: nowrap; }
.app-version { color: var(--muted); font-size: 14px; white-space: nowrap; }
/* Lives at the bottom of the sidebar now (not the header) — margin-top:auto
   pushes it to the foot of the flex column, past whatever else is in the
   menu, rather than sitting right after the last button. Still shows on
   narrow screens now: the sidebar is a full-height drawer with room to
   spare, unlike the cramped header it used to clutter. */
.sidebar-version { margin-top: auto; padding-top: 10px; text-align: left; }
.header-right { display: flex; align-items: center; gap: 12px; flex-shrink: 0; }
.user-email { color: var(--muted); font-size: 14px; }

@media (max-width: 860px) {
  .app-header { padding: 10px 12px; gap: 8px; }
  .header-left { gap: 6px; }
  .header-right { gap: 8px; }
  .app-title-sm { font-size: 17px; }
  .user-email { max-width: 130px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
}

@media (max-width: 420px) {
  .user-email { display: none; } /* Sign Out button alone is enough context */
}

.menu-toggle {
  display: inline-block;
  background: transparent;
  border: 1px solid var(--border-subtle);
  color: var(--text-primary);
  border-radius: var(--radius-sm);
  font-size: 18px;
  line-height: 1;
  padding: 6px 10px;
  cursor: pointer;
  align-self: center;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.menu-toggle:hover { background: var(--card-bg-raised); border-color: var(--border-strong); }

/* ---------- Sidebar (left menu: portfolio switch + actions) ----------
   Always an off-canvas, slide-in/out burger menu — on every screen size,
   not just mobile — toggled via .menu-toggle / #btnMenuToggle. */
.app-body {
  display: flex;
  align-items: stretch;
  min-height: calc(100vh - var(--header-height));
}

.sidebar {
  width: 264px;
  flex-shrink: 0;
  background: var(--card-bg);
  border-right: 1px solid var(--border-subtle);
  padding: 20px 16px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  position: fixed;
  top: 0;
  left: 0;
  height: 100vh;
  z-index: 150;
  transform: translateX(-100%);
  transition: transform 0.22s ease;
  box-shadow: var(--shadow-lg);
  overflow-y: auto;
}
.sidebar.open { transform: translateX(0); }

.sidebar-divider { height: 1px; background: var(--border-subtle); margin: 10px 0; }

/* Collapsible sidebar sections (accordion). Each .sidebar-section holds a
   clickable title row that expands/collapses its .sidebar-section-body. */
.sidebar-section { border-top: 1px solid var(--border-subtle); }
.sidebar-section:first-of-type { border-top: none; }
.sidebar-section-title {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  width: 100%;
  gap: 10px;
  font-size: 13px;
  font-weight: 700;
  color: var(--muted);
  text-transform: none;
  letter-spacing: 0.06em;
  padding: 9px 8px;
  margin: 0;
  border-radius: 8px;
  background: none;
  border: none;
  cursor: pointer;
  text-align: left;
  font-family: inherit;
  transition: background 0.18s ease, color 0.18s ease, padding-left 0.18s ease;
}
.sidebar-section-label { flex: 1; min-width: 0; }
.sidebar-section-icon {
  width: 16px;
  height: 16px;
  flex: 0 0 16px;
  opacity: 0.65;
  transition: transform 0.18s ease, opacity 0.18s ease;
}
.sidebar-section-title:hover {
  color: var(--text-primary);
  background: var(--card-bg-raised);
  padding-left: 12px;
}
.sidebar-section-title:hover .sidebar-section-icon { opacity: 1; transform: scale(1.14); }
.admin-group-body .sidebar-section-icon { width: 14px; height: 14px; flex-basis: 14px; }
.sidebar-chevron {
  font-size: 12px;
  line-height: 1;
  transition: transform 0.18s ease;
  transform: rotate(0deg);
}
.sidebar-section.collapsed .sidebar-chevron { transform: rotate(-90deg); }
.sidebar-section-body {
  display: flex;
  flex-direction: column;
  gap: 8px;
  overflow: hidden;
  padding-bottom: 10px;
  /* Height is driven in JS (0 ⇆ content px ⇆ auto) so the section slides open
     smoothly like invesco.com's nav, rather than snapping via display:none.
     Easing/curve match a material-style ease-in-out. */
  transition: height 0.32s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.24s ease;
}
.sidebar-section.collapsed .sidebar-section-body {
  height: 0;
  opacity: 0;
  padding-bottom: 0;
}

/* Admin area: everything admin-only is grouped under one "Admin" section,
   set off from the normal menu by a thick divider so it's clearly separate. */
.admin-group { border-top: 3px solid var(--border-strong); margin-top: 6px; }
.admin-group > .sidebar-section-title { color: var(--text-primary); }
.admin-group-body { padding-left: 8px; border-left: 2px solid var(--border-subtle); margin-left: 2px; }
.admin-group-body .sidebar-subsection { border-top: 1px solid var(--border-subtle); }
.admin-group-body .sidebar-subsection:first-of-type { border-top: none; }
.admin-group-body .sidebar-subsection > .sidebar-section-title { font-size: 12px; }

.sidebar-actions { display: flex; flex-direction: column; gap: 8px; }
.sidebar-actions .btn { margin-top: 0; }
.sidebar-viewing { display: flex; flex-direction: column; gap: 6px; }
.sidebar-viewing .select { width: 100%; }

.theme-picker-row { display: flex; align-items: center; gap: 8px; }
.theme-picker-row .select { flex: 1; }

/* Keep every sidebar control inside the menu width. Selects have an intrinsic
   min-content width set by their longest <option> (e.g. "Dark Glassmorphism",
   "STOXX Europe 600 (GBP)"); without min-width:0 that overflows the sidebar
   and the flex row. width:100% + border-box makes buttons/inputs/selects fit
   the padded column exactly. */
.sidebar { overflow-x: hidden; }
.sidebar .select,
.sidebar .input,
.sidebar .btn {
  width: 100%;
  max-width: 100%;
  min-width: 0;
}
.sidebar .select {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Portfolio tabs (Pensions/ISAs/Other) — top-left, under the header, styled
   like actual file tabs (flat bottom, rounded top, attached to the content
   below) rather than plain buttons — matches the original v1 look. */
.tab-bar {
  display: flex;
  gap: 4px;
  padding: 12px 24px 0;
  background: var(--app-bg);
  flex-wrap: wrap;
}
.tab-btn {
  background: var(--card-bg);
  color: var(--muted);
  border: 1px solid var(--border-subtle);
  border-bottom: none;
  border-radius: 10px 10px 0 0;
  padding: 10px 20px;
  font-family: var(--font);
  font-weight: 600;
  font-size: 15px;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}
.tab-btn:hover { color: var(--text-primary); }
.tab-btn.active { background: var(--card-bg-raised); color: var(--text-primary); box-shadow: var(--shadow-sm); }
/* Markets and Find Investments are separate sections (not portfolios) —
   pinned as a pair to the far right of the tab bar, away from
   Pensions/ISAs/Other. Markets carries the auto margin so it (and
   Find Investments right after it) both get pushed over together. */
.tab-btn-markets { margin-left: auto; }

@media (max-width: 860px) {
  .tab-bar { padding: 10px 14px 0; gap: 3px; }
  .tab-btn { padding: 8px 14px; font-size: 14px; }
  .tab-btn-markets { margin-left: 0; }
}

.sidebar-overlay {
  display: none;
}
.sidebar-overlay.visible {
  display: block;
  position: fixed;
  inset: 0;
  background: var(--overlay-bg);
  z-index: 140;
}

.stale-warning {
  margin: 0 0 16px;
  background: var(--warning-bg);
  border: 1px solid var(--warning);
  color: var(--warning);
  padding: 10px 16px;
  border-radius: var(--radius-md);
  font-size: 15px;
}

/* Shown only while the admin account is viewing/editing someone else's
   tracker — deliberately louder than .stale-warning so it's impossible to
   mistake another account's data for your own. */
.admin-banner {
  margin: 0 0 16px;
  background: var(--danger-bg);
  border: 1px solid var(--loss);
  color: var(--loss);
  padding: 10px 16px;
  border-radius: var(--radius-md);
  font-size: 15px;
  font-weight: 700;
}

.view-container { flex: 1; min-width: 0; padding: 0 24px 40px; }

.card {
  background: var(--card-bg);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  padding: 18px;
  margin-bottom: 16px;
  box-shadow: var(--shadow-sm);
}

.select {
  background: var(--card-bg-raised);
  color: var(--text-primary);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  padding: 8px 10px;
  font-family: var(--font);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.select:focus { outline: none; border-color: var(--btn-primary); box-shadow: 0 0 0 3px var(--focus-ring); }

/* Tick boxes take the theme's brand colour when checked (navy in Corporate). */
input[type="checkbox"], input[type="radio"] { accent-color: var(--brand-accent); }
.snapshot-picker-label { color: var(--muted); font-size: 14px; }

.mobile-col-toggle { display: none; } /* desktop: all columns already visible */

@keyframes colSlideIn {
  from { opacity: 0; transform: translateX(-6px); }
  to { opacity: 1; transform: translateX(0); }
}

/* ---------- Narrow screens: tighten spacing, stack panels ---------- */
@media (max-width: 860px) {
  .view-container { padding: 0 14px 32px; }
  .summary-bar { gap: 20px; }

  /* Provider table: hide the detail columns (Start, History, One-off Pay
     In, Withdrawal, Std Monthly / Day, Std Monthly Out / Day) by default —
     the "Show More Columns" toggle above the table reveals them again. */
  .mobile-col-toggle { display: inline-block; margin: 10px 10px 0; }
  /* Higher specificity (.table-scroll prefix) so these beat the base
     `.rows-table { min-width: 1400px }` rule, which appears LATER in the file
     and would otherwise win at equal specificity — keeping the collapsed table
     at 1400px and forcing a long horizontal scroll to reach Current/Gain/%. */
  .table-scroll .rows-table { min-width: 0; width: 100%; }
  .table-scroll .rows-table .col-extra { display: none; }
  .table-scroll .rows-table.show-extra-cols { min-width: 1400px; }
  .table-scroll .rows-table.show-extra-cols .col-extra {
    display: table-cell;
    animation: colSlideIn 0.2s ease;
  }
  /* Tighten widths/padding in the collapsed view so Provider + Current Value +
     Gain + Performance all fit a phone's width — no horizontal scroll needed
     to see them. (Expanded "Show More Columns" restores the wide layout.) */
  /* Tight enough that Provider + Current + Gain + Performance + the chart icon
     all fit a ~360px phone width with NO horizontal overflow (which was pushing
     the actions column, and its chart icon, off the right edge). */
  .table-scroll .rows-table:not(.show-extra-cols) th,
  .table-scroll .rows-table:not(.show-extra-cols) td { padding-left: 4px; padding-right: 4px; font-size: 13px; }
  .table-scroll .rows-table:not(.show-extra-cols) input.readonly-name { width: 74px; }
  .table-scroll .rows-table:not(.show-extra-cols) input[type=text],
  .table-scroll .rows-table:not(.show-extra-cols) input[type=number] { width: 60px; font-size: 13px; }
  /* Collapsed mobile view: only the chart icon is needed — hide edit/delete so
     the chart icon pulls left and sits clear of the screen edge. (They return
     in "Show More Columns" / on desktop.) */
  .table-scroll .rows-table:not(.show-extra-cols) .row-actions .icon-btn:nth-child(n+2) { display: none; }
  .table-scroll .rows-table:not(.show-extra-cols) .icon-btn { padding: 4px 4px; font-size: 13px; }
  .table-scroll .rows-table:not(.show-extra-cols) td.actions-cell { padding-right: 10px; }

  .bottom-row { flex-direction: column; }
  .panel-compact { max-width: none; }
  .dashboard-chart-panel { min-width: 0; }
}

/* Phone rotated to landscape: blow the "All providers — growth over time"
   chart up to full screen for a proper look at the trend. Fires only on short-
   and-wide viewports (a phone on its side), and only on the dashboard tab —
   this panel lives inside main.view-container, which is hidden on the Markets
   and Find Investments tabs, so their own charts aren't affected. Chart.js v4
   auto-resizes to the container via ResizeObserver, so no JS is needed. */
@media (orientation: landscape) and (max-height: 500px) {
  .dashboard-chart-panel {
    position: fixed;
    inset: 0;
    z-index: 200;
    margin: 0;
    border-radius: 0;
    background: var(--card-bg);
    padding: 10px 12px;
    display: flex;
    flex-direction: column;
  }
  .dashboard-chart-panel .panel-title { margin-bottom: 4px; }
  .dashboard-chart-panel .dashboard-chart-canvas-wrap {
    flex: 1;
    min-height: 0;
    height: auto;
  }
  .dashboard-chart-panel .chart-footer { display: none; } /* maximise the chart area */
}

/* Portrait phone: the growth chart is unreadably squished, so hide it and show
   a prompt to rotate instead (landscape gives the full-screen view above). */
.chart-rotate-hint { display: none; }
@media (max-width: 860px) and (orientation: portrait) {
  .dashboard-chart-panel .dashboard-chart-canvas-wrap,
  .dashboard-chart-panel .chart-footer { display: none; }
  .dashboard-chart-panel .chart-rotate-hint {
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    gap: 8px;
    min-height: 120px;
    padding: 20px;
    color: var(--muted);
    font-size: 14px;
    border: 1px dashed var(--border-strong);
    border-radius: var(--radius-md);
  }
}

/* Individual provider chart on mobile: open full screen, in landscape. A phone
   can't be force-rotated by the page, so when it's held in PORTRAIT we rotate
   the chart modal itself 90° and size it to the swapped viewport dimensions —
   the chart then fills the screen sideways for a proper wide read. Chart.js v4
   resizes to the new container automatically (ResizeObserver). */
@media (max-width: 860px) and (orientation: portrait) {
  /* Sit above the dashboard chart's own landscape full-screen (z-index 200)
     so an open provider chart is never overlaid by the all-providers chart. */
  #chartModal { z-index: 300; }
  #chartModal .modal-card-wide {
    position: fixed;
    top: 50%;
    left: 50%;
    width: 100vh;
    height: 100vw;
    max-width: none;
    max-height: none;
    border-radius: 0;
    padding: 12px 14px;
    transform: translate(-50%, -50%) rotate(90deg);
    transform-origin: center center;
  }
  #chartModal .chart-footer { display: none; } /* maximise chart area */
}
/* Phone already in landscape: just go full screen, no rotation needed. Keyed on
   width alone (≤950px catches phones in landscape but not tablets/laptops) —
   the old max-height:500px gate was missing on taller phones, so on rotation
   neither this nor the portrait rule matched and the chart fell back to the
   small default modal. */
@media (max-width: 950px) and (orientation: landscape) {
  /* Above the dashboard chart's landscape full-screen (z-index 200) so tilting
     to landscape with a provider chart open keeps showing THAT chart, not the
     all-providers one. */
  #chartModal { z-index: 300; }
  #chartModal .modal-card-wide {
    position: fixed;
    inset: 0;
    width: 100vw;
    height: 100vh;
    max-width: none;
    max-height: none;
    border-radius: 0;
    padding: 10px 12px;
  }
  #chartModal .chart-footer { display: none; }
}

.summary-bar { display: flex; gap: 36px; align-items: center; flex-wrap: wrap; }
.stat-title { color: var(--muted); font-size: 13px; text-transform: none; letter-spacing: 0.04em; font-weight: 600; }
.stat-value { font-size: 24px; font-weight: 700; margin-top: 2px; letter-spacing: -0.01em; }
.stat-lg { font-size: 24px; }
.stat-sublabel { font-size: 13px; color: var(--muted); margin-top: 2px; }
.notify-label { margin-left: auto; color: var(--muted); font-size: 14px; }

/* Benchmark result, moved into the summary bar (far right) to free up the
   space the standalone Benchmark card used to take. */
.stat-benchmark { min-width: 180px; max-width: 260px; }
.stat-benchmark .panel-result { margin-top: 2px; }

.panel-title { font-size: 13px; font-weight: 700; color: var(--muted); letter-spacing: 0.06em; margin-bottom: 8px; }
/* Small "last refreshed" style caption next to a panel title (e.g. Index
   Chart's "Updates 12:00 UTC") — deliberately un-bold/un-tracked/normal
   case so it doesn't compete with the eyebrow-style title text next to it. */
.fi-index-updates-note { font-weight: 400; letter-spacing: normal; text-transform: none; margin-left: 4px; }
/* Projector card doesn't need the full table width — keep it compact and
   left-aligned. The freed-up space to its right holds the all-providers
   growth chart, in the same visual format as the per-provider charts. */
.panel-compact { max-width: 420px; flex-shrink: 0; }

.bottom-row { display: flex; gap: 16px; align-items: stretch; flex-wrap: wrap; }
.dashboard-chart-panel { flex: 1; min-width: 320px; display: flex; flex-direction: column; }
.dashboard-chart-canvas-wrap { min-height: 280px; flex: 1; }
.dashboard-chart-panel .chart-footer { max-height: 110px; margin-top: 8px; }
.panel-result { font-size: 16px; margin-top: 8px; }
.panel-result-lg { font-size: 21px; font-weight: 700; color: var(--highlight); }
.panel-sublabel { font-size: 13px; color: var(--muted); margin-top: 4px; }
.proj-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 12px; align-items: center; }
.proj-grid label { font-size: 14px; color: var(--muted); }
.input {
  background: var(--card-bg-raised);
  color: var(--text-primary);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  padding: 6px 8px;
  font-family: var(--font);
  width: 100%;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.input:focus { outline: none; border-color: var(--btn-primary); box-shadow: 0 0 0 3px var(--focus-ring); }
.checkbox-row { display: flex; align-items: center; gap: 8px; margin-top: 10px; font-size: 14px; color: var(--muted); }

/* ---------- Table ---------- */
.table-card { padding: 0; overflow: hidden; position: relative; }
/* Quick-save shortcut for the provider dash — same action as the sidebar's
   SAVE SNAPSHOT button, just reachable without opening the sidebar. Sits
   top-right of the card regardless of screen size or the "Show More
   Columns" toggle's own (independent) position. */
.table-card-save-btn {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 2;
  font-size: 17px;
  line-height: 1;
  padding: 6px 9px;
}
.table-scroll { overflow-x: auto; }
.rows-table { border-collapse: collapse; width: 100%; min-width: 1400px; }
/* History Log modal's table only has two columns (Date, Amount) and lives in
   a narrow modal-card — the 1400px min-width above is tuned for the wide
   provider dashboard table and was forcing an unnecessary horizontal
   scrollbar here. Scrolls vertically instead once there are enough
   transactions to need it. */
.history-log-table { min-width: 0; }
.history-log-scroll { overflow-x: visible; max-height: 50vh; overflow-y: auto; }
.rows-table th {
  text-align: left;
  font-size: 13px;
  color: var(--muted);
  text-transform: none;
  font-weight: 700;
  letter-spacing: 0.03em;
  padding: 12px 8px;
  border-bottom: 1px solid var(--border-subtle);
  position: sticky;
  top: 0;
  background: var(--card-bg);
}
.rows-table td {
  padding: 7px 8px;
  border-bottom: 1px solid var(--border-subtle);
  vertical-align: middle;
}
.rows-table tbody tr { transition: background 0.1s ease; }
.rows-table tbody tr:hover { background: var(--card-bg-raised); }
.rows-table input[type=text], .rows-table input[type=number] {
  background: var(--card-bg-raised);
  color: var(--text-primary);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  padding: 5px 6px;
  width: 90px;
  font-family: var(--font);
  font-size: 15px;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.rows-table input[type=text]:focus, .rows-table input[type=number]:focus {
  outline: none;
  border-color: var(--btn-primary);
  box-shadow: 0 0 0 3px var(--focus-ring);
}
.rows-table input.readonly-name { background: transparent; border: none; color: var(--text-primary); font-weight: 700; width: 140px; }
.rows-table input.day-input { width: 40px; }
.day-pair { display: flex; gap: 4px; align-items: center; }
.day-pair span { color: var(--muted); font-size: 13px; }
.history-cell-wrap { display: flex; gap: 4px; align-items: center; }
.history-cell-wrap input { min-width: 0; flex: 1; }
.history-cell-wrap .icon-btn { flex-shrink: 0; padding: 4px 6px; }
.cell-value { font-weight: 700; }
/* Desktop: provider table number values one point smaller than the base body
   size, so the figures sit a touch tighter on the wide layout. (Mobile keeps
   the larger size for touch legibility.) */
@media (min-width: 861px) {
  .rows-table td { font-size: 15px; }
  .rows-table input[type=text], .rows-table input[type=number] { font-size: 14px; }
  /* Desktop "Show More Columns": hide One-off Pay In + Withdrawal by default
     (they carry .col-desktop-extra); the toggle reveals them. Other columns
     stay visible on desktop. */
  .mobile-col-toggle { display: inline-block; margin: 12px 12px 0; }
  .rows-table .col-desktop-extra { display: none; }
  .rows-table.show-extra-cols .col-desktop-extra {
    display: table-cell;
    animation: colSlideIn 0.22s ease;
  }
}
/* Ticker/Company links to Google Finance (see tickerLinkHtml/companyLinkHtml
   in find-investments.js) — styled to read as a normal cell at rest, with an
   underline only on hover so the results table doesn't look link-heavy. */
#fiResultsBody a { color: inherit; text-decoration: none; }
#fiResultsBody a:hover { text-decoration: underline; color: var(--brand-accent); }

/* "More detail" buttons under each Find Investments mode's short blurb —
   opens #fiModeInfoModal with the fuller explanation (see MODE_INFO in
   find-investments.js). Styled as an inline text link, not a boxed button,
   so the trimmed-down mobile blurbs stay visually lightweight. */
.fi-more-detail {
  background: none;
  border: none;
  padding: 0;
  margin-left: 6px;
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  color: var(--brand-accent);
  cursor: pointer;
  text-decoration: underline;
  white-space: nowrap;
}
.fi-more-detail:hover { opacity: 0.8; }
.cell-muted { color: var(--muted); }
.cell-gain { color: var(--gain); }
.cell-loss { color: var(--loss); }
.cell-auto { color: var(--warning); }
/* width:1% + white-space:nowrap is the standard table trick to make a
   column shrink to its content instead of soaking up the table's leftover
   width — otherwise this, being the last/emptiest-header column, ends up
   stretched with the buttons stranded on the far side of dead space. */
.rows-table td.actions-cell { width: 1%; white-space: nowrap; }
.row-actions { display: flex; gap: 4px; }
.icon-btn {
  background: transparent;
  border: 1px solid var(--border-subtle);
  color: var(--muted);
  border-radius: var(--radius-sm);
  padding: 4px 8px;
  cursor: pointer;
  font-size: 14px;
  transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease;
}
.icon-btn:hover { color: var(--text-primary); border-color: var(--border-strong); background: var(--card-bg-raised); }

/* ---------- Modal ---------- */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: var(--overlay-bg);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 100;
}
.modal-card {
  background: var(--card-bg);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  padding: 26px;
  width: 380px;
  max-width: 92vw; /* never overflow narrow phones (SE / small Androids) */
  max-height: 90vh;
  overflow-y: auto;
  box-shadow: var(--shadow-lg);
}
/* Chart modal takes over almost the whole viewport so the graph itself gets
   as much room as possible, instead of being squeezed into a ~900px card. */
.modal-card-wide {
  width: 97vw;
  max-width: none;
  height: 94vh;
  max-height: 94vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.modal-card h2 { margin: 0 0 4px 0; font-weight: 700; letter-spacing: -0.01em; }
.modal-note { color: var(--muted); font-size: 14px; }
.modal-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 18px; }
.modal-header-row { display: flex; justify-content: space-between; align-items: center; flex-shrink: 0; }

.chart-canvas-wrap { flex: 1; min-height: 0; position: relative; margin-top: 8px; }
.chart-canvas-wrap canvas { width: 100% !important; height: 100% !important; }

.chart-footer {
  margin-top: 12px;
  font-size: 14px;
  color: var(--muted);
  white-space: pre-wrap;
  line-height: 1.6;
  flex-shrink: 0;
  max-height: 22vh;
  overflow-y: auto;
}

.toast {
  position: fixed;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--card-bg-raised);
  border: 1px solid var(--border-subtle);
  padding: 12px 20px;
  border-radius: var(--radius-md);
  z-index: 200;
  font-size: 15px;
  box-shadow: var(--shadow-lg);
}

/* ---------- Find Investments: index chart (top of tab) ---------- */
.fi-index-card { margin-bottom: 16px; }

/* Drag-to-reorder Markets-tab cards. Each .mkt-card gets a grip handle in
   its top-right corner; dragging it reorders the cards (order persisted). */
.mkt-card { position: relative; }
.mkt-drag-handle {
  position: absolute;
  top: 10px;
  right: 12px;
  z-index: 5;
  padding: 2px 6px;
  font-size: 18px;
  line-height: 1;
  letter-spacing: 2px;
  color: var(--muted);
  cursor: grab;
  user-select: none;
  border-radius: 6px;
  opacity: 0.55;
  transition: opacity 0.15s ease, background 0.15s ease;
}
.mkt-drag-handle:hover { opacity: 1; background: var(--border-subtle); }
.mkt-drag-handle:active { cursor: grabbing; }
.mkt-card.mkt-dragging { opacity: 0.5; outline: 2px dashed var(--brand-accent, var(--border-subtle)); outline-offset: -2px; }
.fi-index-row {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}
.fi-index-row .select { max-width: 280px; }
.fi-index-summary { font-size: 15px; color: var(--muted); }
.fi-index-summary strong { color: var(--text-primary); }
.fi-index-summary .gain { color: var(--gain); }
.fi-index-summary .loss { color: var(--loss); }

/* Market summary table — one-view snapshot of every indicator, below the chart. */
.fi-market-summary { margin-top: 16px; }
.panel-subtitle {
  font-size: 13px;
  font-weight: 700;
  color: var(--muted);
  text-transform: none;
  letter-spacing: 0.06em;
  margin-bottom: 6px;
}
.fi-summary-table { width: 100%; border-collapse: collapse; font-size: 15px; }
.fi-summary-table td {
  padding: 6px 8px;
  border-bottom: 1px solid var(--border-subtle);
  white-space: nowrap;
}
.fi-summary-table tr:last-child td { border-bottom: none; }
.fi-summary-table td:first-child { color: var(--text-primary); font-weight: 500; white-space: normal; }
.fi-summary-table .gain { color: var(--gain); }
.fi-summary-table .loss { color: var(--loss); }

.fi-index-description { margin: 0 0 14px; }
.fi-index-blurb { font-size: 15px; line-height: 1.55; color: var(--text-primary); margin: 0 0 8px; }
.fi-index-facts { margin: 0; font-size: 14px; }
.fi-index-facts dt { color: var(--muted); text-transform: none; letter-spacing: 0.03em; font-weight: 600; margin-top: 6px; }
.fi-index-facts dd { margin: 0 0 2px; color: var(--text-primary); }

.fi-period-row {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  margin-bottom: 14px;
}
.fi-period-btn {
  background: var(--card-bg-raised);
  color: var(--muted);
  border: 1px solid var(--border-subtle);
  border-radius: 999px;
  padding: 5px 13px;
  font-family: var(--font);
  font-weight: 600;
  font-size: 14px;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}
.fi-period-btn:hover { color: var(--text-primary); }
.fi-period-btn.active { background: var(--btn-primary); color: #fff; border-color: var(--btn-primary); box-shadow: var(--shadow-sm); }

.fi-index-chart-wrap { position: relative; height: 280px; }
.fi-index-empty {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  color: var(--muted);
  font-size: 15px;
  padding: 0 20px;
}

/* ---------- Find Investments (Mode 17 "Compounder" scan) ---------- */
.fi-settings-grid { grid-template-columns: 1fr 1fr 1fr 1fr; }
/* Grid items default to a content-based min-width (min-width: auto), which
   for a <select> means the browser won't shrink it below its WIDEST option
   text — e.g. "Cannibal Capital Allocators (share buyback compounders)" is
   far wider than a phone screen's half-column track. Without this, the
   select (and the whole grid/card) overflows the viewport to the right on
   mobile instead of wrapping its own text. min-width: 0 lets it actually
   shrink to the track width like every other grid item. */
.fi-settings-grid select,
.fi-settings-grid .select { width: 100%; min-width: 0; }
@media (max-width: 860px) {
  .fi-settings-grid { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 480px) {
  /* Two columns is still too tight for a label + select/input pair on a
     phone-width screen — stack to one column instead of squeezing text. */
  .fi-settings-grid { grid-template-columns: 1fr; }
}
.fi-actions-row { justify-content: flex-start; margin-top: 16px; flex-wrap: wrap; }
.fi-actions-row .select { max-width: 220px; width: 100%; min-width: 0; }

.fi-universe-import-row {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin: 10px 0 4px;
}
.fi-universe-import-row .snapshot-picker-label { flex: 1; min-width: 220px; }

.fi-progress-wrap {
  height: 10px;
  border-radius: 999px;
  background: var(--card-bg-raised);
  overflow: hidden;
  margin: 4px 0 10px;
}
.fi-progress-bar {
  height: 100%;
  width: 0%;
  background: var(--btn-primary);
  transition: width 0.3s ease;
}

.fi-results-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px 14px;
  padding: 16px 16px 0;
}
.fi-link-pref { margin: 0; white-space: nowrap; }

.fi-flag {
  display: inline-block;
  font-size: 12px;
  font-weight: 700;
  padding: 2px 6px;
  border-radius: 999px;
  margin-right: 4px;
  white-space: nowrap;
}
.fi-flag-caveat { background: var(--warning-bg); color: var(--warning); }
.fi-flag-buybacks { background: var(--card-bg-raised); color: var(--gain); }
.fi-flag-dilution { background: var(--danger-bg); color: var(--loss); }
.fi-flag-peg { background: var(--danger-bg); color: var(--loss); }

.fi-detail-body { font-size: 15px; line-height: 1.7; max-height: 60vh; overflow-y: auto; }
.fi-detail-body dt { color: var(--muted); font-size: 13px; text-transform: none; letter-spacing: 0.03em; margin-top: 8px; }
.fi-detail-body dd { margin: 0 0 2px; }

/* ================== "Dark Glassmorphism" theme — structural effects ==================
   The colour/shadow/radius tokens for this theme live up in the [data-theme="glass"]
   block near the top of the file, same as every other theme. What's here is
   the stuff that can't be expressed as a plain CSS variable: background
   gradients, backdrop-filter blur, gradient text, and the "large typography"
   sizing bumps. Every selector below is scoped to [data-theme="glass"] so it
   has zero effect on Country/Dark/Light. */

/* Dark base + a soft purple-to-blue glow, fixed so it doesn't scroll away. */
[data-theme="glass"] body {
  background:
    radial-gradient(circle at 15% -10%, rgba(139, 92, 246, 0.28), transparent 55%),
    radial-gradient(circle at 85% 0%, rgba(59, 130, 246, 0.22), transparent 50%),
    radial-gradient(circle at 50% 115%, rgba(99, 102, 241, 0.14), transparent 60%),
    var(--app-bg);
  background-attachment: fixed;
}

/* Frosted-glass cards — translucent + blurred so the gradient glow behind
   them shows through softly. */
[data-theme="glass"] .card,
[data-theme="glass"] .modal-card,
[data-theme="glass"] .login-card {
  backdrop-filter: blur(22px) saturate(160%);
  -webkit-backdrop-filter: blur(22px) saturate(160%);
}

/* Blur behind the header, sidebar drawer, and modal backdrop — the "blur
   effects behind menus" part of the brief. */
[data-theme="glass"] .app-header,
[data-theme="glass"] .sidebar {
  background: rgba(11, 15, 20, 0.55);
  backdrop-filter: blur(26px) saturate(160%);
  -webkit-backdrop-filter: blur(26px) saturate(160%);
}
[data-theme="glass"] .modal-overlay {
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}

/* Tabs, inputs, and selects pick up the same translucent glass treatment as
   cards, just without their own blur (they already sit on a blurred card). */
[data-theme="glass"] .tab-btn { background: rgba(255, 255, 255, 0.045); }
[data-theme="glass"] .tab-btn.active { background: rgba(255, 255, 255, 0.12); }
[data-theme="glass"] .select,
[data-theme="glass"] .input,
[data-theme="glass"] .login-card input,
[data-theme="glass"] .modal-card input,
[data-theme="glass"] .modal-card select {
  background: rgba(255, 255, 255, 0.055);
}

/* The dropdown POPUP list a <select> opens is painted by the OS/browser
   chrome, not this page — it can't inherit blur or a translucent rgba
   background like the closed control can. Left as-is, it fell back to each
   browser's own default (often a plain white popup), which combined with
   our light --text-primary option text made every option unreadable. Give
   the popup an explicit solid dark background here instead. */
[data-theme="glass"] select option {
  background-color: #141a24;
  color: var(--text-primary);
}

/* Gradient "purple → blue" title text. */
[data-theme="glass"] .app-title,
[data-theme="glass"] .app-title-sm {
  background: linear-gradient(135deg, #c4b5fd 0%, #93c5fd 60%, #67e8f9 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  font-weight: 800;
}

/* Every button now carries a gradient token (see the [data-theme="glass"]
   block above), not just Primary/Accent — give all four types a matching
   translucent border, and a soft glow tinted to each one's own colour
   instead of the flat shadow the other themes use. Neutral gets a subtle
   white glow to stay quiet next to the more colourful action buttons. */
[data-theme="glass"] .btn-primary,
[data-theme="glass"] .btn-accent,
[data-theme="glass"] .btn-neutral,
[data-theme="glass"] .btn-destructive {
  border: 1px solid rgba(255, 255, 255, 0.14);
}
[data-theme="glass"] .btn-primary,
[data-theme="glass"] .btn-accent {
  box-shadow: 0 4px 20px rgba(124, 58, 237, 0.35);
}
[data-theme="glass"] .btn-primary:hover,
[data-theme="glass"] .btn-accent:hover {
  box-shadow: 0 6px 28px rgba(124, 58, 237, 0.5);
}
[data-theme="glass"] .btn-neutral { box-shadow: 0 4px 16px rgba(255, 255, 255, 0.08); }
[data-theme="glass"] .btn-neutral:hover { box-shadow: 0 6px 22px rgba(255, 255, 255, 0.12); }
[data-theme="glass"] .btn-destructive { box-shadow: 0 4px 20px rgba(239, 68, 68, 0.32); }
[data-theme="glass"] .btn-destructive:hover { box-shadow: 0 6px 28px rgba(239, 68, 68, 0.45); }

/* ================== "Light Glassmorphism" theme — structural effects ==================
   Same idea as Dark Glassmorphism just above (see its comment for the full
   rationale) — the colour/shadow/radius tokens live in the [data-theme="glass-light"]
   block near the top of the file; this is the blur/gradient/typography
   plumbing that can't be a plain variable. Orange→red instead of purple→blue,
   light base instead of dark. */

/* Light base + a soft orange-to-red glow, fixed so it doesn't scroll away. */
[data-theme="glass-light"] body {
  background:
    radial-gradient(circle at 15% -10%, rgba(249, 115, 22, 0.22), transparent 55%),
    radial-gradient(circle at 85% 0%, rgba(239, 68, 68, 0.18), transparent 50%),
    radial-gradient(circle at 50% 115%, rgba(251, 146, 60, 0.14), transparent 60%),
    var(--app-bg);
  background-attachment: fixed;
}

/* Frosted-glass cards — translucent + blurred so the gradient glow behind
   them shows through softly. */
[data-theme="glass-light"] .card,
[data-theme="glass-light"] .modal-card,
[data-theme="glass-light"] .login-card {
  backdrop-filter: blur(22px) saturate(160%);
  -webkit-backdrop-filter: blur(22px) saturate(160%);
}

/* Blur behind the header, sidebar drawer, and modal backdrop. */
[data-theme="glass-light"] .app-header,
[data-theme="glass-light"] .sidebar {
  background: rgba(250, 246, 243, 0.6);
  backdrop-filter: blur(26px) saturate(160%);
  -webkit-backdrop-filter: blur(26px) saturate(160%);
}
[data-theme="glass-light"] .modal-overlay {
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}

/* Tabs, inputs, and selects pick up the same translucent glass treatment as
   cards, just without their own blur (they already sit on a blurred card). */
[data-theme="glass-light"] .tab-btn { background: rgba(120, 53, 15, 0.045); }
[data-theme="glass-light"] .tab-btn.active { background: rgba(120, 53, 15, 0.12); }
[data-theme="glass-light"] .select,
[data-theme="glass-light"] .input,
[data-theme="glass-light"] .login-card input,
[data-theme="glass-light"] .modal-card input,
[data-theme="glass-light"] .modal-card select {
  background: rgba(255, 255, 255, 0.55);
}

/* Same reasoning as the dark variant's option-popup fix above — the native
   dropdown list can't inherit blur/translucency, so give it an explicit
   solid (light) background instead of trusting the browser default. */
[data-theme="glass-light"] select option {
  background-color: #fdf8f4;
  color: var(--text-primary);
}

/* Gradient "orange → red" title text. */
[data-theme="glass-light"] .app-title,
[data-theme="glass-light"] .app-title-sm {
  background: linear-gradient(135deg, #f97316 0%, #ef4444 60%, #dc2626 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  font-weight: 800;
}

/* Every button now carries a gradient token, not just Primary/Accent — give
   all four types a matching translucent border, and a soft glow tinted to
   each one's own colour instead of the flat shadow the other themes use. */
[data-theme="glass-light"] .btn-primary,
[data-theme="glass-light"] .btn-accent,
[data-theme="glass-light"] .btn-neutral,
[data-theme="glass-light"] .btn-destructive {
  border: 1px solid rgba(255, 255, 255, 0.5);
}
[data-theme="glass-light"] .btn-primary,
[data-theme="glass-light"] .btn-accent {
  box-shadow: 0 4px 20px rgba(234, 88, 12, 0.3);
}
[data-theme="glass-light"] .btn-primary:hover,
[data-theme="glass-light"] .btn-accent:hover {
  box-shadow: 0 6px 28px rgba(234, 88, 12, 0.42);
}
[data-theme="glass-light"] .btn-neutral { box-shadow: 0 4px 16px rgba(120, 53, 15, 0.08); }
[data-theme="glass-light"] .btn-neutral:hover { box-shadow: 0 6px 22px rgba(120, 53, 15, 0.12); }
[data-theme="glass-light"] .btn-destructive { box-shadow: 0 4px 20px rgba(220, 38, 38, 0.28); }
[data-theme="glass-light"] .btn-destructive:hover { box-shadow: 0 6px 28px rgba(220, 38, 38, 0.4); }

/* ================== "Country" theme — Glassmorphism structural effects ==================
   Same brief as the two dedicated Glassmorphism themes above (frosted-glass
   blur, gradient glow, gradient title text, large typography) applied to
   Country's existing palette instead of a new one — no new hues, just
   translucency + blur + gradients built from the greens/gold Country
   already uses (see the [data-theme="country"] token block near the top,
   which was updated to make card/border colours translucent for this). */

/* Cream base + a very soft green-to-gold glow, fixed so it doesn't scroll away. */
[data-theme="country"] body {
  background:
    radial-gradient(circle at 15% -10%, rgba(42, 61, 40, 0.1), transparent 55%),
    radial-gradient(circle at 85% 0%, rgba(147, 112, 31, 0.1), transparent 50%),
    radial-gradient(circle at 50% 115%, rgba(63, 125, 79, 0.08), transparent 60%),
    var(--app-bg);
  background-attachment: fixed;
}

/* Frosted-glass cards — translucent + blurred so the gradient glow behind
   them shows through softly. */
[data-theme="country"] .card,
[data-theme="country"] .modal-card,
[data-theme="country"] .login-card {
  backdrop-filter: blur(22px) saturate(160%);
  -webkit-backdrop-filter: blur(22px) saturate(160%);
}

/* Blur behind the header, sidebar drawer, and modal backdrop. */
[data-theme="country"] .app-header,
[data-theme="country"] .sidebar {
  background: rgba(244, 241, 235, 0.65);
  backdrop-filter: blur(26px) saturate(160%);
  -webkit-backdrop-filter: blur(26px) saturate(160%);
}
[data-theme="country"] .modal-overlay {
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}

/* Tabs, inputs, and selects pick up the same translucent glass treatment as
   cards, just without their own blur (they already sit on a blurred card). */
[data-theme="country"] .tab-btn { background: rgba(232, 227, 216, 0.45); }
[data-theme="country"] .tab-btn.active { background: rgba(232, 227, 216, 0.85); }
[data-theme="country"] .select,
[data-theme="country"] .input,
[data-theme="country"] .login-card input,
[data-theme="country"] .modal-card input,
[data-theme="country"] .modal-card select {
  background: rgba(255, 255, 255, 0.5);
}

/* Same reasoning as the other two Glassmorphism themes — the native dropdown
   popup can't inherit blur/translucency, so give it an explicit solid
   background instead of trusting the browser default. */
[data-theme="country"] select option {
  background-color: #fbf9f4;
  color: var(--text-primary);
}

/* Gradient title text, mixing Country's own forest-green brand accent with
   its gold highlight — same idea as purple→blue / orange→red on the other
   two themes, just Country's existing colours. Font size/weight/line-height
   are untouched (set by the rules above, in the Login section) since
   Country's big serif title is already its own "large typography". */
[data-theme="country"] .app-title,
[data-theme="country"] .app-title-sm {
  background: linear-gradient(135deg, #2a3d28 0%, #5c7a52 50%, #93701f 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* Every button now carries a gradient token, not just Primary/Accent — give
   all four types a matching translucent border, and a soft glow tinted to
   each one's own colour instead of the flat shadow the other themes use. */
[data-theme="country"] .btn-primary,
[data-theme="country"] .btn-accent,
[data-theme="country"] .btn-neutral,
[data-theme="country"] .btn-destructive {
  border: 1px solid rgba(255, 255, 255, 0.4);
}
[data-theme="country"] .btn-primary,
[data-theme="country"] .btn-accent {
  box-shadow: 0 4px 20px rgba(42, 61, 40, 0.25);
}
[data-theme="country"] .btn-primary:hover,
[data-theme="country"] .btn-accent:hover {
  box-shadow: 0 6px 28px rgba(42, 61, 40, 0.35);
}
[data-theme="country"] .btn-neutral { box-shadow: 0 4px 16px rgba(26, 25, 23, 0.06); }
[data-theme="country"] .btn-neutral:hover { box-shadow: 0 6px 22px rgba(26, 25, 23, 0.1); }
[data-theme="country"] .btn-destructive { box-shadow: 0 4px 20px rgba(161, 64, 58, 0.28); }
[data-theme="country"] .btn-destructive:hover { box-shadow: 0 6px 28px rgba(161, 64, 58, 0.4); }

/* Large typography — bigger, bolder numbers and headings throughout. Shared
   across all three Glassmorphism-flavoured themes since the sizing itself
   doesn't differ, just the colours set above/further up. Country's app-title
   / app-title-sm are deliberately excluded here — its own serif clamp()
   sizing (see the Login section) is already bigger than these values. */
[data-theme="glass"] .app-title,
[data-theme="glass-light"] .app-title { font-size: 38px; }
[data-theme="glass"] .app-title-sm,
[data-theme="glass-light"] .app-title-sm { font-size: 26px; }
[data-theme="glass"] .stat-value,
[data-theme="glass-light"] .stat-value,
[data-theme="country"] .stat-value { font-size: 29px; font-weight: 800; letter-spacing: -0.02em; }
[data-theme="glass"] .stat-lg,
[data-theme="glass-light"] .stat-lg,
[data-theme="country"] .stat-lg { font-size: 32px; }
[data-theme="glass"] .stat-title,
[data-theme="glass-light"] .stat-title,
[data-theme="country"] .stat-title { font-size: 14px; letter-spacing: 0.06em; }
[data-theme="glass"] .panel-result-lg,
[data-theme="glass-light"] .panel-result-lg,
[data-theme="country"] .panel-result-lg { font-size: 27px; }
[data-theme="glass"] .panel-title,
[data-theme="glass-light"] .panel-title,
[data-theme="country"] .panel-title { font-size: 14px; letter-spacing: 0.08em; }
.fi-detail-body dl { margin: 0; }

/* ================== "Professional" theme — structural effects ==================
   Restrained by design, per its own brief: hairline borders instead of heavy
   glass, ONE accent colour spent sparingly, glassmorphism used at most once
   (the header only) rather than on every surface like the three themes
   above. */

/* Fine grain/noise texture (2–4% opacity) + a very low-opacity radial glow —
   this app's login screen is the closest equivalent to a marketing "hero",
   so that's the only place the glow lives; the rest of the app stays a flat
   ink navy so content (tables, numbers) reads as the priority, not the chrome. */
[data-theme="professional"] .login-screen {
  background:
    radial-gradient(circle at 20% -10%, rgba(20, 184, 166, 0.09), transparent 55%),
    radial-gradient(circle at 85% 10%, rgba(20, 184, 166, 0.05), transparent 50%),
    var(--app-bg);
  position: relative;
}
[data-theme="professional"] .login-screen::before {
  content: "";
  position: absolute;
  inset: 0;
  opacity: 0.035;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
[data-theme="professional"] .login-card {
  position: relative;
  z-index: 1;
}

/* Glassmorphism used exactly once — the sticky header — with a much
   subtler blur/opacity than the three Glassmorphism themes above, per the
   brief's "hairline border, frosted blur" nav spec. Sidebar and cards stay
   flat/opaque; this is deliberately the one place it happens. */
[data-theme="professional"] .app-header {
  background: rgba(11, 18, 32, 0.72);
  backdrop-filter: blur(14px) saturate(140%);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  border-bottom: 1px solid var(--border-subtle);
}

/* Brand wordmark: tight tracking, no gradient fill (that's a Country/Glass
   flourish) — the accent colour alone carries it. */
[data-theme="professional"] .app-title,
[data-theme="professional"] .app-title-sm {
  font-weight: 700;
  letter-spacing: -0.02em;
}

/* Eyebrow labels — uppercase, small, accent-coloured, per the brief — applied
   to the two labels that already play that role in this app's layout
   (stat captions and panel section titles). */
[data-theme="professional"] .stat-title,
[data-theme="professional"] .panel-title,
[data-theme="professional"] .sidebar-section-title {
  color: var(--brand-accent);
  letter-spacing: 0.12em;
}

/* Tabular, oversized figures for any stat display — numerals never jump
   around as they update, and read with the scale/confidence the brief
   calls for without breaking this dashboard's inline multi-stat layout
   (a literal 48–96px would blow out the summary bar). */
[data-theme="professional"] .stat-value,
[data-theme="professional"] .cell-value {
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}
[data-theme="professional"] .stat-value { font-size: 30px; font-weight: 700; }
[data-theme="professional"] .stat-lg { font-size: 34px; }
[data-theme="professional"] .panel-result-lg { font-size: 28px; font-variant-numeric: tabular-nums; }

/* Capability-card hover: border brightening only — no lift/translate, so
   dashboard cards stay put rather than shifting under the cursor. */
[data-theme="professional"] .card {
  transition: border-color 0.18s ease, box-shadow 0.18s ease;
}
[data-theme="professional"] .card:hover {
  border-color: var(--border-strong);
  box-shadow: var(--shadow-md);
}

/* Buttons: solid (primary, teal — the one place the accent is "spent") vs.
   ghost (neutral — hairline border, transparent fill) rather than the
   gradient-and-glow treatment the other themes use. */
[data-theme="professional"] .btn {
  border: 1px solid transparent;
  transition: background 0.18s ease, border-color 0.18s ease, transform 0.15s ease, box-shadow 0.18s ease;
}
[data-theme="professional"] .btn-neutral {
  border-color: var(--border-subtle);
}
[data-theme="professional"] .btn-neutral:hover {
  border-color: var(--border-strong);
}

@media (prefers-reduced-motion: reduce) {
  [data-theme="professional"] .card,
  [data-theme="professional"] .btn {
    transition: none !important;
  }
}

/* ---------- Sector Heatmap (Markets tab) ---------- */
.sector-heatmap-card { margin-top: 16px; }
.sector-heatmap-header-row { display: flex; justify-content: space-between; align-items: center; gap: 12px; margin-bottom: 6px; flex-wrap: wrap; }
.sector-heatmap-user-row {
  display: flex;
  align-items: center;
  gap: 8px 12px;
  flex-wrap: wrap;
  padding: 10px 12px;
  margin-bottom: 14px;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  background: var(--card-bg-raised);
}
/* Native <select> sizes its closed box to fit its WIDEST option text and
   won't shrink below that on its own (same issue fixed for .fi-settings-grid
   above) — the long "6x daily — adds a second overnight check..." option
   made this overflow the card on mobile instead of wrapping. flex: 1 1 220px
   + min-width: 0 lets it shrink to whatever room is left on its line (or
   wrap to its own line via the row's flex-wrap); the browser just clips the
   CLOSED-state text if the box ends up narrower than that — the full option
   list is unaffected in the open dropdown. */
.sector-heatmap-user-row .select { flex: 1 1 220px; min-width: 0; max-width: 100%; }

.sector-heatmap-alerts { display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px; }
.sector-alert-item {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-subtle);
  background: var(--card-bg-raised);
  font-size: 14px;
}
.sector-alert-kind {
  flex: 0 0 auto;
  font-size: 12px;
  font-weight: 700;
  text-transform: none;
  letter-spacing: 0.04em;
  padding: 2px 7px;
  border-radius: 999px;
  background: var(--warning-bg);
  color: var(--warning);
}
.sector-alert-message { flex: 1 1 260px; color: var(--text-primary); }
.sector-alert-time { flex: 0 0 auto; color: var(--muted); font-size: 13px; white-space: nowrap; }

/* Own table styling rather than the wide 1400px-min provider table — this
   grid has 12 narrow columns (Snapshot + 11 sectors) and reads best compact. */
.sector-heatmap-table { border-collapse: collapse; width: 100%; min-width: 0; }
.sector-heatmap-table th {
  text-align: center;
  font-size: 12px;
  color: var(--muted);
  text-transform: none;
  font-weight: 700;
  letter-spacing: 0.02em;
  padding: 8px 4px;
  border-bottom: 1px solid var(--border-subtle);
  white-space: nowrap;
}
.sector-heatmap-table th:first-child { text-align: left; }
.sector-heatmap-table td {
  text-align: center;
  font-size: 14px;
  font-weight: 600;
  padding: 7px 4px;
  border-bottom: 1px solid var(--border-subtle);
  white-space: nowrap;
}
.sector-heatmap-table td:first-child { text-align: left; font-weight: 400; font-size: 13px; }
.sector-heat-cell { cursor: pointer; transition: outline-color 0.1s ease; outline: 1px solid transparent; outline-offset: -1px; }
.sector-heat-cell:hover { outline-color: var(--border-strong); }
/* Admin-only per-row delete "✕" (see sector-heatmap.js renderHeatmapTable) —
   sits inline after the timestamp text in the first cell rather than a
   dedicated actions column, keeping this already-wide 12-column table from
   getting any wider. */
.sector-snapshot-delete { margin-left: 6px; padding: 2px 6px; font-size: 12px; vertical-align: middle; }

/* Sector drill-down modal table (public/js/sector-heatmap.js openSectorDetail) —
   same compact numbers-table idea as the heatmap grid, but with a Name
   column so it's left-aligned rather than centered throughout. */
.sector-detail-table { border-collapse: collapse; width: 100%; min-width: 0; font-size: 14px; }
.sector-detail-table th {
  text-align: left;
  font-size: 12px;
  color: var(--muted);
  text-transform: none;
  font-weight: 700;
  letter-spacing: 0.02em;
  padding: 6px 8px 6px 0;
  border-bottom: 1px solid var(--border-subtle);
  white-space: nowrap;
}
.sector-detail-table td { padding: 6px 8px 6px 0; border-bottom: 1px solid var(--border-subtle); white-space: nowrap; }

/* Hover popover (public/js/sector-heatmap.js showSectorHoverPopover) — a
   quick, colour-coded glance at a sector cell's constituents, positioned
   next to the cursor without needing a click. pointer-events:none so it
   never itself becomes the mouseout target and fights the cell's own hover
   state. */
.sector-hover-popover {
  position: fixed;
  z-index: 300;
  background: var(--card-bg-raised);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  padding: 8px 10px;
  max-width: 260px;
  pointer-events: none;
}
.sector-hover-title { font-weight: 700; font-size: 13px; color: var(--text-primary); margin-bottom: 4px; }
.sector-hover-row { display: flex; align-items: baseline; gap: 8px; padding: 2px 0; font-size: 13px; white-space: nowrap; }
.sector-hover-ticker { flex: 0 0 auto; min-width: 40px; font-weight: 600; color: var(--muted); }

/* ---------- Bank Accounts: spending globe ---------- */
.bank-card { display: flex; flex-direction: column; }
.bank-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 12px 0 6px; }
.bank-summary { font-size: 14px; color: var(--text-primary); margin: 4px 0 10px; min-height: 18px; }
.bank-cards { display: flex; flex-wrap: wrap; gap: 8px 14px; align-items: center; }
.bank-card-chip { display: inline-flex; align-items: center; gap: 6px; padding: 6px 10px; border: 1px solid var(--border-subtle); border-radius: var(--radius-sm); background: var(--card-bg-raised); font-size: 13px; }
.bank-card-chip b { font-variant-numeric: tabular-nums; }
.bank-card-total { border-style: dashed; }
.bank-swatch { display: inline-block; width: 10px; height: 10px; border-radius: 50%; flex: 0 0 10px; }
.bank-tip .bank-swatch { margin-right: 4px; }
.bank-people { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 4px 0 8px; }
.bank-people .select { width: auto; min-width: 140px; max-width: 220px; }
.bank-card-editor { border: 1px solid var(--border-subtle); border-radius: var(--radius-sm); background: var(--card-bg-raised); padding: 10px 12px; margin: 0 0 10px; }
.bank-card-row { display: flex; align-items: center; gap: 10px; margin: 6px 0; }
.bank-card-code { min-width: 90px; font-size: 13px; color: var(--muted); }
.bank-card-row .input { max-width: 220px; }

/* Category breakdown (deposits & debits) */
.bank-breakdown { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin: 6px 0 4px; }
.bank-breakdown-col { border: 1px solid var(--border-subtle); border-radius: var(--radius-md); padding: 10px 12px; background: var(--card-bg-raised); }
.bank-breakdown-head { display: flex; justify-content: space-between; align-items: baseline; font-weight: 700; font-size: 13px; text-transform: none; letter-spacing: 0.04em; color: var(--muted); margin-bottom: 6px; }
.bank-breakdown-total { font-size: 15px; color: var(--text-primary); font-variant-numeric: tabular-nums; }
.bank-cat { border-top: 1px solid var(--border-subtle); }
.bank-cat > summary { display: flex; justify-content: space-between; align-items: center; gap: 10px; padding: 8px 2px; cursor: pointer; list-style: none; }
.bank-cat > summary::-webkit-details-marker { display: none; }
.bank-cat > summary::before { content: "▸"; color: var(--muted); font-size: 11px; transition: transform 0.15s ease; }
.bank-cat[open] > summary::before { transform: rotate(90deg); }
.bank-cat-name { flex: 1; font-weight: 600; }
.bank-cat-total { font-variant-numeric: tabular-nums; white-space: nowrap; }
.bank-cat-table { margin: 2px 0 8px 16px; }
.bank-cat-table td { padding: 3px 8px 3px 0; vertical-align: middle; }
.bank-recat { font-size: 11px; padding: 2px 4px; border: 1px solid var(--border-subtle); border-radius: var(--radius-sm); background: var(--card-bg-raised); color: var(--text-primary); max-width: 130px; }
.bank-tx-type { color: var(--muted); font-size: 11px; white-space: nowrap; }
@media (max-width: 860px) { .bank-breakdown { grid-template-columns: 1fr; } }
.bank-globe-wrap { position: relative; width: 100%; height: 560px; border-radius: var(--radius-md); overflow: hidden; background: radial-gradient(circle at 50% 40%, rgba(0,20,60,0.06), transparent 70%); }
.bank-globe { width: 100%; height: 100%; }
.bank-globe canvas { display: block; }
.bank-globe-empty {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  text-align: center; padding: 24px; color: var(--muted); font-size: 14px; pointer-events: none;
}
/* Hover tooltip rendered by globe.gl's pointLabel. */
.bank-tip {
  background: var(--card-bg); color: var(--text-primary);
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md); padding: 10px 12px; max-width: 320px;
}
.bank-tip-title { font-weight: 700; font-size: 14px; }
.bank-tip-sub { color: var(--muted); font-size: 12px; margin-bottom: 6px; }
.bank-tip-table { width: 100%; border-collapse: collapse; font-size: 12px; }
.bank-tip-table td { padding: 2px 6px 2px 0; white-space: nowrap; vertical-align: top; }
.bank-tip-table td:nth-child(2) { color: var(--muted); max-width: 150px; overflow: hidden; text-overflow: ellipsis; }

/* Let our .bank-tip provide the popup chrome, not MapLibre's default white box. */
.maplibregl-popup-content { background: transparent !important; box-shadow: none !important; padding: 0 !important; }
.maplibregl-popup-tip { display: none !important; }
.bank-globe { border-radius: var(--radius-md); overflow: hidden; }

@media (max-width: 860px) {
  .bank-globe-wrap { height: 62vh; }
}

/* ===========================================================================
   Corporate (Invesco) theme — component touches on top of the tokens above.
   White header with a navy wordmark, blue underline on the active tab,
   lightly-squared white cards with a hairline border, and Invesco-blue
   uppercase section/panel titles — echoing invesco.com's clean, institutional
   layout.
   =========================================================================== */
[data-theme="corporate"] .app-header {
  background: #ffffff;
  border-bottom: 1px solid var(--border-strong);
  box-shadow: 0 1px 0 rgba(15, 36, 64, 0.04);
}
[data-theme="corporate"] .app-title,
[data-theme="corporate"] .app-title-sm {
  color: var(--brand-accent); /* Invesco blue wordmark */
  font-weight: 800;
  letter-spacing: -0.02em;
}
/* Blue accent bar under the wordmark, like Invesco's logo lockup. */
[data-theme="corporate"] .app-title::after {
  content: "";
  display: block;
  width: 34px;
  height: 3px;
  margin-top: 6px;
  background: var(--brand-accent);
  border-radius: 2px;
}
[data-theme="corporate"] .tab-btn {
  position: relative;
  background: transparent;
  border-radius: 0;
  color: var(--muted);
  font-weight: 600;
  font-size: 14px;
  padding: 9px 12px;
  border: none;
  transition: color 0.22s ease;
}
/* Invesco-style hover: text eases from grey to blue while a blue underline
   slides in from the left. The active tab keeps the underline pinned. */
[data-theme="corporate"] .tab-btn::after {
  content: "";
  position: absolute;
  left: 12px;
  right: 12px;
  bottom: 0;
  height: 2px;
  background: var(--brand-accent);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 0.24s ease;
}
[data-theme="corporate"] .tab-btn:hover { color: var(--brand-accent); }
[data-theme="corporate"] .tab-btn:hover::after,
[data-theme="corporate"] .tab-btn.active::after { transform: scaleX(1); }
[data-theme="corporate"] .tab-btn.active {
  background: transparent;
  color: var(--text-primary);
  box-shadow: none;
}
@media (prefers-reduced-motion: reduce) {
  [data-theme="corporate"] .tab-btn,
  [data-theme="corporate"] .tab-btn::after { transition: none; }
}
[data-theme="corporate"] .card {
  border: 1px solid var(--border-subtle);
  box-shadow: var(--shadow-sm);
}
[data-theme="corporate"] .card:hover { box-shadow: var(--shadow-md); }
[data-theme="corporate"] .stat-title,
[data-theme="corporate"] .panel-title,
[data-theme="corporate"] .sidebar-section-title,
[data-theme="corporate"] .panel-subtitle {
  color: var(--brand-accent);
  text-transform: none;
  letter-spacing: 0.08em;
}
[data-theme="corporate"] .stat-value { font-weight: 800; letter-spacing: -0.02em; }
[data-theme="corporate"] .btn { border-radius: var(--radius-sm); font-weight: 600; }
/* Navy hero on the sign-in screen, matching Invesco's dark feature banners. */
[data-theme="corporate"] .login-screen {
  background: linear-gradient(160deg, #000ad2 0%, #0c1e42 100%);
}
[data-theme="corporate"] .login-card {
  border: 1px solid var(--border-subtle);
  box-shadow: var(--shadow-lg);
}

/* ===================== EVENT TRENDS (Find Investments module) ===================== */
.trends-toolbar {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 14px;
}
.trends-toolbar .select { max-width: 200px; }
#trendsMeta { margin-left: auto; }

.trends-results {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 14px;
}
.trend-empty {
  color: var(--muted);
  padding: 18px 4px;
  font-size: 0.95em;
}

.trend-card {
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  background: var(--card-bg-raised);
  padding: 14px;
  box-shadow: var(--shadow-sm);
}
.trend-card-head {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 8px;
}
.trend-icon { font-size: 1.2em; }
.trend-theme {
  font-weight: 700;
  color: var(--text-primary);
  font-size: 1.02em;
}
.trend-geo, .trend-ai {
  font-size: 0.72em;
  font-weight: 700;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--brand-accent);
  color: #fff;
}
.trend-ai { background: #7c3aed; }
.trend-sources { margin-left: auto; display: flex; gap: 4px; flex-wrap: wrap; }
.trend-src {
  font-size: 0.68em;
  color: var(--muted);
  border: 1px solid var(--border-subtle);
  border-radius: 999px;
  padding: 1px 7px;
}
.trend-note {
  color: var(--muted);
  font-size: 0.86em;
  margin: 0 0 10px;
  line-height: 1.4;
}
.trend-triggers { display: flex; flex-wrap: wrap; gap: 5px; margin-bottom: 10px; }
.trend-chip {
  font-size: 0.74em;
  background: var(--card-bg);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  padding: 2px 8px;
  color: var(--text-primary);
}
.trend-tickers { display: flex; flex-direction: column; gap: 4px; }
.trend-tickers-neg { margin-top: 10px; }
.trend-tickers-label {
  font-size: 0.72em;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
  margin-bottom: 2px;
}
.trend-ticker {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 0.86em;
  padding: 3px 0;
  border-bottom: 1px dashed var(--border-subtle);
}
.trend-ticker:last-child { border-bottom: none; }
.trend-arrow { font-size: 0.8em; width: 12px; text-align: center; }
.trend-pos .trend-arrow { color: var(--gain); }
.trend-neg .trend-arrow { color: var(--loss); }
.trend-sym { font-weight: 700; color: var(--text-primary); min-width: 48px; }
.trend-name {
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 1;
}
.trend-exch {
  font-size: 0.72em;
  color: var(--muted);
  opacity: 0.8;
}
.trend-move { font-weight: 600; margin-left: auto; font-variant-numeric: tabular-nums; }
.trend-move.up { color: var(--gain); }
.trend-move.down { color: var(--loss); }
.trend-move.flat { color: var(--muted); }
.trend-articles {
  margin-top: 10px;
  display: flex;
  flex-direction: column;
  gap: 3px;
  border-top: 1px solid var(--border-subtle);
  padding-top: 8px;
}
.trend-article {
  font-size: 0.8em;
  color: var(--brand-accent);
  text-decoration: none;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.trend-article:hover { text-decoration: underline; }
.trend-article em { color: var(--muted); font-style: normal; }

/* --- Brand logo wordmark: shown in every theme, in place of the text title.
   The PNG is used as a CSS mask so the wordmark takes each theme's own title
   colour (--text-primary) — one white asset recolours itself per theme, so it
   stays legible on light (Corporate), dark (Bread/Dark) and glass backgrounds
   alike. Aspect ratio matches the source asset (388×120). --- */
.app-logo {
  display: block;
  height: 30px;
  width: 97px; /* 30 × 388/120 */
  background-color: var(--text-primary);
  -webkit-mask: url("../img/bread-logo.png") no-repeat center / contain;
  mask: url("../img/bread-logo.png") no-repeat center / contain;
}
/* Hide the text wordmark in the header (every theme) — the logo replaces it. */
.header-title-block .app-title-sm,
.header-title-block .app-byline { display: none; }

/* --- Logo on the LOGIN card only (not signup/verify, which keep their own
   headings): swap the "Portfolio" title for the logo, every theme. --- */
#loginScreen .login-card .app-title,
#loginScreen .login-card .app-byline { display: none; }
.app-logo-login {
  height: 54px;
  width: 175px; /* 54 × 388/120 */
  margin: 4px auto 20px;
}
