## Context The app is a Next.js 16 candlestick chart annotation tool using Tailwind CSS 3 with shadcn-ui style CSS variables (HSL values in `:root`). Tailwind is already configured with `darkMode: ["class"]`, meaning the `.dark` class on `` controls dark mode. Currently only light-mode CSS variables are defined in `globals.css`, and the hacker-theme spec describes a dark-only neon green aesthetic. The app needs to support both themes with system detection and manual override. ## Goals / Non-Goals **Goals:** - Detect system color scheme preference (`prefers-color-scheme`) and apply matching theme on first load - Provide a manual toggle in the UI to switch between dark, light, and system modes - Persist the user's choice in `localStorage` - Avoid flash of wrong theme (FOUC) on page load - Define dark-mode CSS variables that maintain the hacker-theme aesthetic - Define light-mode CSS variables that provide a clean, readable alternative while keeping monospace typography and terminal feel **Non-Goals:** - Custom user-defined color themes beyond dark/light - Per-component theme overrides - Server-side theme detection (SSR will use system default, hydration applies preference) ## Decisions ### 1. Use `next-themes` for theme management **Choice**: Install and use `next-themes` library. **Rationale**: `next-themes` is the standard solution for Next.js theme switching. It handles: - System preference detection via `prefers-color-scheme` media query - Adding/removing the `.dark` class on `` (matches our existing `darkMode: ["class"]` Tailwind config) - `localStorage` persistence - FOUC prevention via inline script injection - SSR compatibility **Alternatives considered**: - **Custom React context + useEffect**: Would work but requires reimplementing FOUC prevention, system detection, and localStorage sync. `next-themes` is battle-tested and small (~2KB). - **CSS-only with `prefers-color-scheme`**: No manual toggle capability, which is a requirement. ### 2. Three-mode toggle: System / Light / Dark **Choice**: Offer three modes — System (follows OS), Light (forced), Dark (forced). **Rationale**: Users who want to match their OS get automatic switching. Users who prefer a specific theme can lock it in. This is the standard UX pattern. ### 3. CSS variable approach for both themes **Choice**: Define `:root` (light) and `.dark` (dark) CSS variable sets in `globals.css`. **Rationale**: The existing setup already uses HSL CSS variables consumed by Tailwind. Adding a `.dark` selector block with dark-mode values requires zero changes to component code — all `bg-background`, `text-foreground`, etc. classes automatically switch. The hacker-theme neon green palette maps to the dark variant. The light variant uses neutral/slate tones with green accents. ### 4. Theme toggle placement **Choice**: Place the theme toggle button in the sidebar, near the top or bottom of the tool list. **Rationale**: The sidebar is always visible and is the existing control surface. A small icon button (sun/moon/monitor icons from lucide-react) keeps it unobtrusive. Three-state cycle: click rotates through system → light → dark. ### 5. ThemeProvider wraps the app in layout.tsx **Choice**: Wrap `{children}` with `` from `next-themes` in the root layout. **Rationale**: This is the standard integration point. The provider must be a client component, so we'll create a thin `ThemeProvider` wrapper component. ## Risks / Trade-offs - **FOUC on first load**: `next-themes` injects a blocking script to prevent this, but in rare edge cases (slow JS) users might see a brief flash. → Mitigation: `next-themes` handles this well out of the box; `attribute="class"` config ensures Tailwind picks it up immediately. - **Chart library theming**: `lightweight-charts` has its own color configuration that's set programmatically, not via CSS. → Mitigation: The chart component will need to read the current theme and pass appropriate colors to the chart instance. Listen to theme changes and update chart colors accordingly. - **Hacker theme divergence**: The light theme won't have neon glow effects or scanlines — these only make sense on dark backgrounds. → Mitigation: This is intentional. The light theme keeps monospace fonts and terminal structure but uses conventional colors for readability. - **Component styles relying on hardcoded colors**: If any components use hardcoded hex colors instead of CSS variables, they won't switch. → Mitigation: Audit components during implementation and replace hardcoded values with CSS variable references.