'use client'; import { createContext, useContext, useEffect, useState } from 'react'; import type { ReactNode } from 'react'; type Theme = 'light' | 'dark'; type Accent = 'sage' | 'cobalt' | 'terracotta' | 'graphite'; interface AccentTokens { light: { brand: string; deep: string; soft: string; softInk: string; brandInk: string }; dark: { brand: string; deep: string; soft: string; softInk: string; brandInk: string }; } const ACCENTS: Record = { sage: { light: { brand: '#10b981', deep: '#059669', soft: 'rgba(16,185,129,0.1)', softInk: '#047857', brandInk: '#ffffff' }, dark: { brand: '#34d399', deep: '#10b981', soft: 'rgba(52,211,153,0.15)', softInk: '#6ee7b7', brandInk: '#022c22' }, }, cobalt: { light: { brand: '#3b82f6', deep: '#2563eb', soft: 'rgba(59,130,246,0.1)', softInk: '#1d4ed8', brandInk: '#ffffff' }, dark: { brand: '#60a5fa', deep: '#3b82f6', soft: 'rgba(96,165,250,0.15)', softInk: '#93c5fd', brandInk: '#172554' }, }, terracotta: { light: { brand: '#f43f5e', deep: '#e11d48', soft: 'rgba(244,63,94,0.1)', softInk: '#be123c', brandInk: '#ffffff' }, dark: { brand: '#fb7185', deep: '#f43f5e', soft: 'rgba(251,113,133,0.15)', softInk: '#fda4af', brandInk: '#4c0519' }, }, graphite: { light: { brand: '#52525b', deep: '#3f3f46', soft: 'rgba(82,82,91,0.1)', softInk: '#27272a', brandInk: '#ffffff' }, dark: { brand: '#a1a1aa', deep: '#71717a', soft: 'rgba(161,161,170,0.15)', softInk: '#d4d4d8', brandInk: '#18181b' }, }, }; interface ThemeContextValue { theme: Theme; accent: Accent; setTheme: (t: Theme) => void; setAccent: (a: Accent) => void; toggleTheme: () => void; } const ThemeContext = createContext(null); export function useTheme(): ThemeContextValue { const ctx = useContext(ThemeContext); if (!ctx) throw new Error('useTheme must be used inside ThemeProvider'); return ctx; } function applyAccent(accent: Accent, theme: Theme) { const ac = ACCENTS[accent][theme]; const r = document.documentElement.style; r.setProperty('--brand', ac.brand); r.setProperty('--brand-deep', ac.deep); r.setProperty('--brand-soft', ac.soft); r.setProperty('--brand-soft-ink', ac.softInk); r.setProperty('--brand-ink', ac.brandInk); r.setProperty('--viz-1', ac.brand); } export function ThemeProvider({ children }: { children: ReactNode }) { const [theme, setThemeState] = useState('light'); const [accent, setAccentState] = useState('sage'); // Hydrate from localStorage on mount (server renders light/sage defaults). useEffect(() => { const savedTheme = (localStorage.getItem('mt-theme') as Theme | null) ?? 'light'; const savedAccent = (localStorage.getItem('mt-accent') as Accent | null) ?? 'sage'; setThemeState(savedTheme); setAccentState(savedAccent); }, []); // Sync theme to DOM + localStorage. useEffect(() => { document.documentElement.setAttribute('data-theme', theme); localStorage.setItem('mt-theme', theme); }, [theme]); // Sync accent to DOM + localStorage. useEffect(() => { applyAccent(accent, theme); localStorage.setItem('mt-accent', accent); }, [accent, theme]); function setTheme(t: Theme) { setThemeState(t); } function setAccent(a: Accent) { setAccentState(a); } function toggleTheme() { setThemeState((prev) => (prev === 'light' ? 'dark' : 'light')); } return ( {children} ); }