/* Geist Sans, self-hosted (no external font request). Only the weights the
   app actually uses (font-normal/medium/semibold/bold); latin subset only. */
@import "@fontsource/geist-sans/latin-400.css";
@import "@fontsource/geist-sans/latin-500.css";
@import "@fontsource/geist-sans/latin-600.css";
@import "@fontsource/geist-sans/latin-700.css";

@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
  :root {
    --background: 0 0% 100%;
    --foreground: 224 71% 4%;

    --card: 0 0% 100%;
    --card-foreground: 224 71% 4%;

    --popover: 0 0% 100%;
    --popover-foreground: 224 71% 4%;

    --primary: 224 100% 57%;
    --primary-foreground: 0 0% 100%;

    --secondary: 220 14% 96%;
    --secondary-foreground: 224 71% 4%;

    --muted: 220 14% 96%;
    --muted-foreground: 220 9% 46%;

    --accent: 220 14% 96%;
    --accent-foreground: 224 71% 4%;

    --destructive: 0 84% 60%;
    --destructive-foreground: 0 0% 100%;

    --border: 220 13% 91%;
    --input: 220 13% 91%;
    --ring: 224 100% 57%;

    --radius: 0.5rem;

    --chart-green: 142 71% 45%;
    --chart-red: 0 84% 60%;
    --chart-blue: 224 100% 57%;
    --chart-purple: 262 83% 58%;
    --chart-orange: 27 96% 61%;
    --chart-yellow: 48 96% 53%;

    /* Chart series tokens — validated with the data-viz palette checker against
       the light card surface (#fff): lightness band, chroma floor, CVD
       separation and contrast all pass. The income/expense pair sits in the
       6-8 CVD floor band, which is legal only alongside secondary encoding, so
       those charts always ship a legend plus direct value labels. */
    --series-income: 142 71% 45%;
    --series-expense: 0 84% 60%;
    /* Single-hue ramp for magnitude (spend-by-category bars). */
    --series-magnitude: 224 100% 57%;

    --sidebar-background: 0 0% 98%;
    --sidebar-foreground: 224 71% 4%;
    --sidebar-primary: 224 100% 57%;
    --sidebar-primary-foreground: 0 0% 100%;
    --sidebar-accent: 220 14% 96%;
    --sidebar-accent-foreground: 224 71% 4%;
    --sidebar-border: 220 13% 91%;
    --sidebar-ring: 224 100% 57%;
  }

  .dark {
    --background: 220 20% 7%;
    --foreground: 210 20% 98%;

    --card: 220 18% 10%;
    --card-foreground: 210 20% 98%;

    --popover: 220 18% 10%;
    --popover-foreground: 210 20% 98%;

    --primary: 224 100% 57%;
    --primary-foreground: 0 0% 100%;

    --secondary: 220 16% 14%;
    --secondary-foreground: 210 20% 98%;

    --muted: 220 16% 14%;
    --muted-foreground: 218 11% 55%;

    --accent: 220 16% 14%;
    --accent-foreground: 210 20% 98%;

    --destructive: 0 63% 31%;
    --destructive-foreground: 0 0% 100%;

    --border: 220 14% 14%;
    --input: 220 14% 16%;
    --ring: 224 100% 57%;

    --chart-green: 142 71% 45%;
    --chart-red: 0 84% 60%;
    --chart-blue: 224 100% 57%;
    --chart-purple: 262 83% 58%;
    --chart-orange: 27 96% 61%;
    --chart-yellow: 48 96% 53%;

    /* Dark steps are re-derived for the dark card surface, not the light values
       reused — the previous tokens were identical in both themes. */
    --series-income: 142 71% 40%;
    --series-expense: 0 84% 51%;
    --series-magnitude: 224 100% 64%;

    --sidebar-background: 220 20% 7%;
    --sidebar-foreground: 210 20% 90%;
    --sidebar-primary: 224 100% 57%;
    --sidebar-primary-foreground: 0 0% 100%;
    --sidebar-accent: 220 16% 13%;
    --sidebar-accent-foreground: 210 20% 98%;
    --sidebar-border: 220 14% 12%;
    --sidebar-ring: 224 100% 57%;
  }
}

/* ─── V2 Perplexity-Inspired Theme ─── */
@layer base {
  .ui-v2 {
    --background: 40 20% 98%;
    --foreground: 20 10% 10%;

    --card: 0 0% 100%;
    --card-foreground: 20 10% 10%;

    --popover: 0 0% 100%;
    --popover-foreground: 20 10% 10%;

    --primary: 174 60% 40%;
    --primary-foreground: 0 0% 100%;

    --secondary: 40 10% 94%;
    --secondary-foreground: 20 10% 10%;

    --muted: 40 10% 96%;
    --muted-foreground: 20 5% 45%;

    --accent: 40 10% 94%;
    --accent-foreground: 20 10% 10%;

    --destructive: 0 84% 60%;
    --destructive-foreground: 0 0% 100%;

    --border: 40 10% 90%;
    --input: 40 10% 90%;
    --ring: 174 60% 40%;

    --sidebar-background: 40 15% 97%;
    --sidebar-foreground: 20 10% 10%;
    --sidebar-primary: 174 60% 40%;
    --sidebar-primary-foreground: 0 0% 100%;
    --sidebar-accent: 40 10% 94%;
    --sidebar-accent-foreground: 20 10% 10%;
    --sidebar-border: 40 10% 92%;
    --sidebar-ring: 174 60% 40%;
  }

  .ui-v2.dark {
    --background: 0 0% 7%;
    --foreground: 30 10% 93%;

    --card: 0 0% 10%;
    --card-foreground: 30 10% 93%;

    --popover: 0 0% 10%;
    --popover-foreground: 30 10% 93%;

    --primary: 174 60% 45%;
    --primary-foreground: 0 0% 100%;

    --secondary: 0 0% 14%;
    --secondary-foreground: 30 10% 93%;

    --muted: 0 0% 13%;
    --muted-foreground: 0 0% 55%;

    --accent: 0 0% 14%;
    --accent-foreground: 30 10% 93%;

    --destructive: 0 72% 51%;
    --destructive-foreground: 0 0% 100%;

    --border: 0 0% 15%;
    --input: 0 0% 17%;
    --ring: 174 60% 45%;

    --chart-green: 142 60% 50%;
    --chart-red: 0 75% 60%;

    --sidebar-background: 0 0% 6%;
    --sidebar-foreground: 30 10% 85%;
    --sidebar-primary: 174 60% 45%;
    --sidebar-primary-foreground: 0 0% 100%;
    --sidebar-accent: 0 0% 12%;
    --sidebar-accent-foreground: 30 10% 93%;
    --sidebar-border: 0 0% 13%;
    --sidebar-ring: 174 60% 45%;
  }
}

/* ─── V2 Typography & Component Overrides ─── */
.ui-v2 body {
  font-size: 14px;
  line-height: 1.5;
  letter-spacing: -0.011em;
}

.ui-v2 h1, .ui-v2 h2, .ui-v2 h3, .ui-v2 h4, .ui-v2 h5, .ui-v2 h6 {
  font-weight: 600;
  letter-spacing: -0.03em;
}

.ui-v2 .shadow-sm {
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
}

/* Added briefly around a theme change (see lib/themeTransition.ts) so the whole
   page flips in one frame instead of fading element by element. */
.theme-switching,
.theme-switching *,
.theme-switching *::before,
.theme-switching *::after {
  transition: none !important;
}

.ui-v2 * {
  transition-property: color, background-color, border-color;
  transition-duration: 150ms;
  transition-timing-function: ease;
}

/* ─── V2 Button Overrides ───
   Scoped to real <button> elements only. This used to also match any
   [role="button"] div (a clickable dropzone, a budget row you click to edit),
   which pressed and scaled those down as if they were buttons, and felt
   wrong on things that don't look like one. */
.ui-v2 button {
  border-radius: 0.5rem;
  transition: background-color 300ms ease-out, border-color 300ms ease-out, color 300ms ease-out, opacity 300ms ease-out;
}

/* V2 primary buttons: inverted fg/bg like Perplexity */
.ui-v2 .bg-primary {
  background-color: hsl(var(--foreground)) !important;
  color: hsl(var(--background)) !important;
}
.ui-v2 .bg-primary:hover {
  background-color: hsl(var(--foreground) / 0.85) !important;
}

/* V2 outline/default buttons: subtle border style */
.ui-v2 .border-input {
  border-color: hsl(var(--border));
}
.ui-v2 .border-input:hover {
  background-color: hsl(var(--muted));
  border-color: hsl(var(--muted));
}

/* ─── V2 Sidebar Icon Uniformity ─── */
.ui-v2 [data-sidebar="menu"] svg,
.ui-v2 [data-sidebar="content"] svg {
  color: currentColor;
  opacity: 0.7;
}

.ui-v2 [data-sidebar="menu"] a[data-active="true"] svg,
.ui-v2 [data-sidebar="content"] a.bg-sidebar-accent svg {
  opacity: 1;
}

@layer base {
  * {
    @apply border-border;
  }

  body {
    @apply bg-background text-foreground;
    font-family: 'Geist Sans', system-ui, -apple-system, sans-serif;
    letter-spacing: -0.01em;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
  }

  h1, h2, h3, h4, h5, h6 {
    letter-spacing: -0.025em;
  }
}

@keyframes fade-in-up {
  from {
    opacity: 0;
    transform: translateY(12px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* Route change: a quick fade, no movement (the old slide-up made every page
   and settings tab look like it was rising from the bottom). */
@keyframes page-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

.animate-page-in {
  animation: page-in 0.18s ease-out both;
}

@media (prefers-reduced-motion: reduce) {
  .animate-page-in { animation: none; }
}

.animate-fade-in-up {
  animation: fade-in-up 0.4s ease-out both;
}

/* Public landing page: scroll reveal (src/lib/reveal.ts), hero rise (used by
   the static pre-render, which can't run the intro animation without delaying
   first paint) and a cross-fade between full page loads. */
.reveal-pending { opacity: 0; transform: translateY(28px); }
.reveal-run {
  transition: opacity 0.8s cubic-bezier(0.22, 0.61, 0.36, 1), transform 0.8s cubic-bezier(0.22, 0.61, 0.36, 1);
}
@keyframes hero-rise {
  from { opacity: 0.35; transform: translateY(16px); }
  to { opacity: 1; transform: none; }
}
.hero-rise { animation: hero-rise 0.8s cubic-bezier(0.22, 0.61, 0.36, 1) both; }
.hero-rise-2 { animation-delay: 0.12s; }
@view-transition { navigation: auto; }
::view-transition-old(root), ::view-transition-new(root) { animation-duration: 0.28s; }
@media (prefers-reduced-motion: reduce) {
  .reveal-pending { opacity: 1; transform: none; }
  .hero-rise { animation: none; }
  @view-transition { navigation: none; }
}

/* Hide scrollbar utility */
.scrollbar-hide {
  -ms-overflow-style: none;
  scrollbar-width: none;
}
.scrollbar-hide::-webkit-scrollbar {
  display: none;
}

/* Sidebar label fade transitions */
[data-state="collapsed"] [data-sidebar="sidebar"] .sidebar-label {
  opacity: 0;
  max-width: 0;
  overflow: hidden;
  pointer-events: none;
  transform: translateX(-4px);
  transition: opacity 200ms ease-out, max-width 200ms ease-out, transform 200ms ease-out;
}
[data-state="expanded"] [data-sidebar="sidebar"] .sidebar-label {
  opacity: 1;
  max-width: 200px;
  overflow: hidden;
  transform: translateX(0);
  transition: opacity 250ms 80ms ease-out, max-width 250ms 80ms ease-out, transform 250ms 80ms ease-out;
}

/* Reports' Print button: the sidebar, its rail and the sticky header are all
   navigation chrome with nothing to print. Layout's <main> already drops its
   own padding and scroll clipping via print:p-0/print:overflow-visible; this
   is the rest, global because the sidebar mounts outside any page's markup. */
@media print {
  /* [data-sidebar="sidebar"] is only the visible panel; its parent (marked
     by data-side + data-variant, unique to Sidebar's own root) is what
     actually reserves the layout gap on desktop and has to go too, or the
     page prints with the sidebar's width left blank on the left. */
  [data-side][data-variant],
  [data-sidebar="sidebar"],
  [data-sidebar="rail"] {
    display: none !important;
  }
}

/* The logo follows each surface's theme, independently of the app root. */
.brand-wordmark {
  color: hsl(172 62% 30%);
}
.dark .brand-wordmark {
  color: hsl(168 42% 62%);
}
.landing-light .brand-wordmark {
  color: hsl(var(--l-accent));
}
.landing-dark .brand-wordmark {
  color: hsl(var(--l-accent));
}

/* ── Public landing page palette ─────────────────────────────────────────── */
.landing-dark {
  --l-bg: 0 0% 4%;
  --l-fg: 0 0% 98%;
  --l-muted: 0 0% 62%;
  --l-line: 0 0% 15%;
  --l-card: 0 0% 8%;
  --l-card2: 0 0% 11%;
  --l-accent: 168 42% 62%;
  --l-accent-fg: 0 0% 7%;
  --l-invert: 0 0% 100%;
  --l-invert-fg: 0 0% 5%;
  --l-paper: 45 25% 95%;
  --l-ink: 0 0% 6%;
  --l-ink-muted: 0 0% 38%;
}
.landing-light {
  --l-bg: 45 25% 96%;
  --l-fg: 0 0% 6%;
  --l-muted: 0 0% 38%;
  --l-line: 40 10% 86%;
  --l-card: 0 0% 100%;
  --l-card2: 45 20% 93%;
  --l-accent: 172 62% 30%;
  --l-accent-fg: 0 0% 100%;
  --l-invert: 0 0% 6%;
  --l-invert-fg: 0 0% 100%;
  --l-paper: 0 0% 5%;
  --l-ink: 0 0% 98%;
  --l-ink-muted: 0 0% 62%;
}
