/* NP. Wealth — the house palette and type.
   ==========================================================================

   Loaded *after* the Tally design system, and it exists to overrule it. Tally
   ships a good dark-only theme in the shape every AI-assisted app is currently
   wearing: blue-black canvas, frosted glass, three aurora blobs, violet and
   mint. This file replaces the palette with one taken off the logo and adds a
   light theme. The type stays as Version 1 set it — a display serif was tried
   here and rejected.

   ---- How theming works here ----

   `document.documentElement` always carries a concrete `data-theme` of exactly
   `light` or `dark`. `system` is resolved in JS (see NP.applyTheme) and the
   media query is *watched* rather than written into CSS. That is why there are
   two blocks below and no `@media (prefers-color-scheme)` anywhere: with the
   media query in CSS, every semantic token would have to be written three
   times — light, dark, and dark-again-under-the-query — and the third copy is
   the one that silently rots.

   ---- Why the white-alpha ramp is redefined rather than replaced ----

   The app paints 89 surfaces and hairlines with `--white-a04` … `--white-a18`,
   which read as "a little bit of white over the dark canvas". On paper, white
   over white is nothing at all, so in the light theme those same tokens carry
   *ink* alphas instead. The names stop being literal, but every one of those 89
   call sites gets the right answer with no edit, and a token that means
   "hairline" in both themes is worth more than a token that means "white". */

/* ======================================================================
   Raw ramps — the same colours in both themes. Nothing here is used by
   the app directly; the semantic tokens below choose from these.
   ====================================================================== */
:root {
  /* The two colours in the logo, exactly as sampled from the master PNG's
     corner pixels. Everything else in the palette is derived from them. */
  --ci-navy: #003659;
  --ci-violet: #5D00A4;
  --ci-paper: #F4F2F0;

  /* Azure — the navy opened up into a usable ramp. */
  --azure-50: #E9F3FA;  --azure-100: #C8E1F0; --azure-200: #95C6E1;
  --azure-300: #60A7CD; --azure-400: #3587B4; --azure-500: #176B98;
  --azure-600: #06537A; --azure-700: #003659; --azure-800: #002840;
  --azure-900: #001B2C;

  /* Violet — same treatment for the other end of the gradient. */
  --violet-50: #F5EBFD;  --violet-100: #E5CEFA; --violet-200: #CEA5F4;
  --violet-300: #B57CEC; --violet-400: #9B54DF; --violet-500: #8334CC;
  --violet-600: #6E16B6; --violet-700: #5D00A4; --violet-800: #490080;
  --violet-900: #34005B;

  /* Money has two directions and they must never be the brand colour, or
     "this is ours" and "this is income" start to look like the same claim. */
  --green-300: #6EE7B7; --green-400: #34D399; --green-500: #0E9F6E; --green-600: #0A7A55;
  --rose-300: #FDA4AF;  --rose-400: #FB7185;  --rose-500: #E11D48;  --rose-600: #BE123C;
  --amber-300: #FCD34D; --amber-400: #FBBF24; --amber-500: #D97706; --amber-600: #B45309;

  /* Paper — warm, because a cool grey next to a cool navy reads as a screen
     and a warm one reads as a statement that arrived in an envelope. */
  --paper-0: #FFFFFF;  --paper-50: #FAF8F5; --paper-100: #F2EFEA;
  --paper-200: #E7E2D9; --paper-300: #D5CEC3;

  /* Night — the dark canvas, pulled toward the CI navy rather than neutral
     blue-black, so the logo sits on a surface of its own family. */
  --night-900: #040C15; --night-850: #071320; --night-800: #0B1B2B;
  --night-750: #102437; --night-700: #173044; --night-600: #22405A;

  /* Tally names these; keep them resolvable so nothing referencing the old
     vocabulary breaks, and let the themes below decide what they mean. */
  --ink-1000: var(--night-900); --ink-950: var(--night-900);
  --ink-900: var(--night-850);  --ink-850: var(--night-800);
  --ink-800: var(--night-750);  --ink-700: var(--night-700);
  --ink-600: var(--night-600);  --ink-500: #3A5570;
}

/* ======================================================================
   LIGHT
   ====================================================================== */
:root[data-theme="light"] {
  color-scheme: light;

  --bg-app: var(--paper-50);
  --bg-sunken: var(--paper-100);
  --surface-glass: rgba(255, 255, 255, .74);
  --surface-glass-strong: rgba(255, 255, 255, .90);
  --surface-solid: var(--paper-0);
  --surface-raised: var(--paper-0);

  /* fg-3 and fg-4 are pinned to measured contrast, not picked by eye: on the
     paper background fg-3 clears 4.5:1 for labels and fg-4 clears 3.5:1 for
     decorative micro-copy. Chosen lighter, both failed an audit of the real
     screens at 11px. */
  --fg-1: #0F2131; --fg-2: #2D4459; --fg-3: #5D7183; --fg-4: #6E8394;
  --fg-inverse: #FFFFFF;
  --text-title: var(--fg-1); --text-body: var(--fg-2);
  --text-muted: var(--fg-3); --text-faint: var(--fg-4);

  /* "A little bit of white" becomes "a little bit of ink". Same 89 call
     sites, opposite pigment. See the note at the top of the file. */
  --white-a04: rgba(15, 33, 49, .035);
  --white-a06: rgba(15, 33, 49, .055);
  --white-a08: rgba(15, 33, 49, .075);
  --white-a12: rgba(15, 33, 49, .12);
  --white-a18: rgba(15, 33, 49, .17);
  --white-a28: rgba(15, 33, 49, .26);
  /* Scrims stay dark in both themes: a dimmed backdrop has to dim. */
  --black-a30: rgba(15, 33, 49, .26);
  --black-a50: rgba(15, 33, 49, .42);
  --black-a70: rgba(15, 33, 49, .58);

  --border-hairline: var(--white-a12);
  --border-strong: var(--white-a18);

  --accent: var(--violet-700);
  --accent-alt: var(--azure-700);
  --accent-soft: var(--violet-500);
  --positive: var(--green-500);
  --negative: var(--rose-500);
  --warning: var(--amber-500);
  --focus-ring: var(--violet-500);

  --blue-400: var(--azure-500); --blue-500: var(--azure-600); --blue-600: var(--azure-700);
  --violet-vivid: var(--violet-600);
  --mint-400: var(--green-500); --mint-500: var(--green-500); --mint-600: var(--green-600);

  /* Glass is nearly off in daylight. Frosting a white card over a white page
     buys nothing and costs a compositor layer on every scroll. */
  --glass-blur: blur(14px) saturate(115%);
  --glass-blur-heavy: blur(22px) saturate(125%);
  --glass-blur-light: blur(8px) saturate(110%);
  --glass-bg: var(--surface-glass);
  --glass-bg-strong: var(--surface-glass-strong);
  --glass-border: var(--white-a12);

  --shadow-sm: 0 1px 2px rgba(15, 33, 49, .07);
  --shadow-md: 0 6px 20px -8px rgba(15, 33, 49, .16);
  --shadow-lg: 0 20px 48px -14px rgba(15, 33, 49, .20);
  --shadow-xl: 0 32px 80px -22px rgba(15, 33, 49, .24);
  --inner-lens: inset 0 1px 0 rgba(255, 255, 255, .85), inset 0 -1px 0 rgba(15, 33, 49, .05);
  --inner-well: inset 0 1px 3px rgba(15, 33, 49, .10);
  --glow-accent: 0 0 0 1px rgba(93, 0, 164, .22), 0 8px 28px -8px rgba(93, 0, 164, .30);
  --glow-positive: 0 8px 28px -8px rgba(14, 159, 110, .30);
  --glow-negative: 0 8px 28px -8px rgba(225, 29, 72, .28);
  --ring-focus: 0 0 0 2px var(--paper-0), 0 0 0 4px var(--violet-500);

  --elevation-card: var(--shadow-md), var(--inner-lens);
  --elevation-sheet: var(--shadow-xl), var(--inner-lens);
  --elevation-popover: var(--shadow-lg), var(--inner-lens);

  /* One wash from each end of the logo, not three aurora blobs. */
  --fade-aurora:
    radial-gradient(135% 95% at 0% 0%, rgba(0, 54, 89, .10) 0%, rgba(0, 54, 89, 0) 58%),
    radial-gradient(120% 90% at 100% 4%, rgba(93, 0, 164, .09) 0%, rgba(93, 0, 164, 0) 60%),
    var(--paper-50);
  --fade-spend:
    radial-gradient(110% 85% at 88% 0%, rgba(225, 29, 72, .09) 0%, rgba(225, 29, 72, 0) 60%),
    var(--paper-50);
  --fade-save:
    radial-gradient(110% 85% at 12% 0%, rgba(14, 159, 110, .10) 0%, rgba(14, 159, 110, 0) 58%),
    var(--paper-50);

  --grad-brand: linear-gradient(135deg, var(--ci-navy) 0%, var(--ci-violet) 100%);
  --grad-accent: linear-gradient(135deg, var(--violet-700) 0%, var(--azure-700) 100%);
  --grad-positive: linear-gradient(135deg, var(--green-500) 0%, var(--azure-600) 100%);
  --grad-negative: linear-gradient(135deg, var(--rose-500) 0%, var(--violet-600) 100%);
  --grad-sheen: linear-gradient(180deg, rgba(255, 255, 255, .70) 0%, rgba(255, 255, 255, 0) 46%);
  --grad-protect-bottom: linear-gradient(180deg, rgba(250, 248, 245, 0) 0%, rgba(250, 248, 245, .88) 62%, var(--paper-50) 100%);
  --grad-protect-top: linear-gradient(180deg, var(--paper-50) 0%, rgba(250, 248, 245, .85) 40%, rgba(250, 248, 245, 0) 100%);

  --cat-other: var(--fg-4);

  /* Pieces the components used to spell out in raw rgba, which is what made
     them dark-only. Named here so both themes get an answer. */
  --track: rgba(15, 33, 49, .10);        /* the unfilled part of a ring or bar */
  /* Set-aside gold. Deeper on paper than on night: the light amber that
     glows against a dark ledger turns to a highlighter smear on white. */
  --gold: #A9720B;
  --tooltip-bg: rgba(20, 32, 44, .94);   /* stays dark: a tooltip is an overlay */
  --tooltip-fg: #F4F7FA;
  --pill-scrim: rgba(255, 255, 255, .82);
  --mark-shadow: 0 2px 8px rgba(15, 33, 49, .18);
  --chart-shadow: drop-shadow(0 6px 16px rgba(15, 33, 49, .14));
}

/* ======================================================================
   DARK
   ====================================================================== */
:root[data-theme="dark"] {
  color-scheme: dark;

  --bg-app: var(--night-900);
  --bg-sunken: #02070D;
  --surface-glass: rgba(255, 255, 255, .05);
  --surface-glass-strong: rgba(255, 255, 255, .085);
  --surface-solid: var(--night-800);
  --surface-raised: var(--night-750);

  --fg-1: #F1F6FA; --fg-2: #C2D2E0; --fg-3: #93A9BC; --fg-4: #6F8798;
  --fg-inverse: var(--night-900);
  --text-title: var(--fg-1); --text-body: var(--fg-2);
  --text-muted: var(--fg-3); --text-faint: var(--fg-4);

  --white-a04: rgba(255, 255, 255, .04);
  --white-a06: rgba(255, 255, 255, .06);
  --white-a08: rgba(255, 255, 255, .085);
  --white-a12: rgba(255, 255, 255, .13);
  --white-a18: rgba(255, 255, 255, .19);
  --white-a28: rgba(255, 255, 255, .28);
  --black-a30: rgba(2, 7, 13, .35);
  --black-a50: rgba(2, 7, 13, .55);
  --black-a70: rgba(2, 7, 13, .74);

  --border-hairline: var(--white-a12);
  --border-strong: var(--white-a18);

  /* The CI colours themselves are too dark to carry text or an icon on this
     canvas, so the dark theme speaks in their lighter cousins and keeps the
     true navy-to-violet for the brand gradient, where it sits under a mark
     rather than under a word. */
  --accent: var(--violet-400);
  --accent-alt: var(--azure-300);
  --accent-soft: var(--violet-300);
  --positive: var(--green-400);
  --negative: var(--rose-400);
  --warning: var(--amber-400);
  --focus-ring: var(--azure-200);

  --blue-400: var(--azure-200); --blue-500: var(--azure-300); --blue-600: var(--azure-400);
  --violet-vivid: var(--violet-400);
  --mint-400: var(--green-300); --mint-500: var(--green-400); --mint-600: var(--green-500);

  --glass-blur: blur(22px) saturate(150%);
  --glass-blur-heavy: blur(36px) saturate(165%);
  --glass-blur-light: blur(12px) saturate(135%);
  --glass-bg: var(--surface-glass);
  --glass-bg-strong: var(--surface-glass-strong);
  --glass-border: var(--white-a12);

  --shadow-sm: 0 1px 2px rgba(2, 7, 13, .45);
  --shadow-md: 0 8px 24px -8px rgba(2, 7, 13, .62);
  --shadow-lg: 0 24px 60px -16px rgba(2, 7, 13, .74);
  --shadow-xl: 0 40px 100px -24px rgba(2, 7, 13, .82);
  --inner-lens: inset 0 1px 0 rgba(255, 255, 255, .14), inset 0 -1px 0 rgba(2, 7, 13, .38);
  --inner-well: inset 0 1px 3px rgba(2, 7, 13, .58);
  --glow-accent: 0 0 0 1px rgba(155, 84, 223, .34), 0 8px 32px -6px rgba(155, 84, 223, .40);
  --glow-positive: 0 8px 32px -6px rgba(52, 211, 153, .34);
  --glow-negative: 0 8px 32px -6px rgba(251, 113, 133, .34);
  --ring-focus: 0 0 0 2px var(--night-900), 0 0 0 4px var(--azure-200);

  --elevation-card: var(--shadow-md), var(--inner-lens);
  --elevation-sheet: var(--shadow-xl), var(--inner-lens);
  --elevation-popover: var(--shadow-lg), var(--inner-lens);

  --fade-aurora:
    radial-gradient(135% 95% at 0% 0%, rgba(0, 84, 138, .46) 0%, rgba(0, 84, 138, 0) 58%),
    radial-gradient(120% 90% at 100% 4%, rgba(93, 0, 164, .40) 0%, rgba(93, 0, 164, 0) 60%),
    var(--night-900);
  --fade-spend:
    radial-gradient(110% 85% at 88% 0%, rgba(225, 29, 72, .24) 0%, rgba(225, 29, 72, 0) 60%),
    var(--night-900);
  --fade-save:
    radial-gradient(110% 85% at 12% 0%, rgba(16, 185, 129, .24) 0%, rgba(16, 185, 129, 0) 58%),
    var(--night-900);

  --grad-brand: linear-gradient(135deg, var(--ci-navy) 0%, var(--ci-violet) 100%);
  --grad-accent: linear-gradient(135deg, var(--violet-500) 0%, var(--azure-500) 100%);
  --grad-positive: linear-gradient(135deg, var(--green-400) 0%, var(--azure-400) 100%);
  --grad-negative: linear-gradient(135deg, var(--rose-400) 0%, var(--violet-400) 100%);
  --grad-sheen: linear-gradient(180deg, rgba(255, 255, 255, .13) 0%, rgba(255, 255, 255, 0) 42%);
  --grad-protect-bottom: linear-gradient(180deg, rgba(4, 12, 21, 0) 0%, rgba(4, 12, 21, .88) 62%, var(--night-900) 100%);
  --grad-protect-top: linear-gradient(180deg, var(--night-900) 0%, rgba(4, 12, 21, .84) 40%, rgba(4, 12, 21, 0) 100%);

  --cat-other: var(--fg-4);

  --track: rgba(255, 255, 255, .08);
  --gold: #F0B429;
  --tooltip-bg: rgba(16, 36, 55, .94);
  --tooltip-fg: #F1F6FA;
  --pill-scrim: rgba(4, 12, 21, .74);
  --mark-shadow: 0 2px 10px rgba(2, 7, 13, .55);
  --chart-shadow: drop-shadow(0 6px 18px rgba(2, 7, 13, .50));
}

/* ======================================================================
   Type
   ----------------------------------------------------------------------
   Manrope throughout, with tabular figures so a column of money lines up —
   the same setting Version 1 shipped, restored after a display serif was
   tried here and rejected.
   ====================================================================== */
:root {
  --font-display: "Manrope", "Helvetica Neue", sans-serif;
  --font-ui: "Manrope", "Helvetica Neue", sans-serif;
  --font-numeric: "Manrope", "Helvetica Neue", sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, monospace;
  --numeric-features: "tnum" 1;
  --ls-display: -0.03em;
}

/* Thai sits lower and needs no negative tracking; the Latin display tracking
   crushes its tone marks into the glyph below. */
:lang(th) { letter-spacing: 0; }

body {
  background: var(--bg-app);
  color: var(--text-body);
  font-family: var(--font-ui);
  font-variant-numeric: tabular-nums;
  transition: background-color var(--dur-base) var(--ease-standard);
}
h1, h2, h3, h4 { font-family: var(--font-display); }
a { color: var(--accent); }
a:hover { color: var(--text-title); }
::selection { background: color-mix(in oklab, var(--accent) 30%, transparent); color: var(--text-title); }

/* The scrollbar is part of the theme too; a pale gutter down the side of a
   dark page is the one thing that gives away a half-done light mode. */
* { scrollbar-color: var(--white-a18) transparent; }

/* ======================================================================
   Scale
   ----------------------------------------------------------------------
   This started life as "Friendly mode" — a second, larger set of tokens
   behind a switch. The switch is gone and these are simply the sizes now,
   because on the way through it became obvious there was never a case for
   the smaller ones: nobody was choosing between two apps, they were choosing
   between comfortable and cramped.

   Type up one step from Tally's defaults, taller rows, rounder corners. The
   app is dense by design and this is the single change that does most of the
   work of making it calm to read.
   ====================================================================== */
:root {
  --fs-body-m: 15px;
  --fs-body-s: 14px;
  --fs-label: 13px;
  --fs-micro: 12px;
  --fs-title-s: 18px;
  --fs-title-m: 21px;
  --fs-title-l: 26px;
  --fs-display-m: 34px;
  --fs-display-l: 42px;

  /* A 60px row is efficient; a 72px row is a target you can hit on a phone
     without looking at it. */
  --radius-sm: 14px;
  --radius-md: 18px;
  --radius-lg: 24px;
  --radius-xl: 32px;
  --row-h: 72px;
}

/* Sidebar rows are laid out inline, so the extra breathing room is applied
   here rather than threaded through the component as another prop. */
nav [role="button"] {
  padding-top: 13px;
  padding-bottom: 13px;
}
