import { createTheme, alpha, Shadows } from '@mui/material/styles'; import type { PaletteMode } from '@mui/material'; declare module '@mui/material/Paper' { interface PaperPropsVariantOverrides { highlighted: true; } } declare module '@mui/material/styles' { interface ColorRange { 50: string; 100: string; 200: string; 300: string; 400: string; 500: string; 600: string; 700: string; 800: string; 900: string; } interface PaletteColor extends ColorRange {} interface Palette { baseShadow: string; flows: { outflows: { primary: string; surface: string; text: string }; inflows: { primary: string; surface: string; text: string }; }; } } const defaultTheme = createTheme(); const customShadows: Shadows = [...defaultTheme.shadows]; /** * Stripe-like indigo brand. #635BFF ≈ hsl(243, 76%, 59%). * Single brand hue — no multi-colour accents. */ export const brand = { 50: 'hsl(250, 100%, 98%)', 100: 'hsl(250, 95%, 95%)', 200: 'hsl(249, 92%, 90%)', 300: 'hsl(248, 92%, 80%)', 400: 'hsl(245, 90%, 72%)', 500: 'hsl(243, 76%, 59%)', 600: 'hsl(243, 75%, 51%)', 700: 'hsl(243, 78%, 42%)', 800: 'hsl(242, 76%, 30%)', 900: 'hsl(241, 75%, 20%)', }; /** Cool, neutral grays. */ export const gray = { 50: 'hsl(220, 35%, 97%)', 100: 'hsl(220, 30%, 94%)', 200: 'hsl(220, 20%, 89%)', 300: 'hsl(220, 17%, 80%)', 400: 'hsl(220, 15%, 64%)', 500: 'hsl(220, 14%, 45%)', 600: 'hsl(220, 13%, 36%)', 700: 'hsl(220, 13%, 27%)', 750: 'hsl(220, 13%, 20%)', 800: 'hsl(220, 12%, 12%)', 850: 'hsl(220, 10%, 8%)', 900: 'hsl(220, 9%, 6%)', }; export const green = { 50: 'hsl(120, 80%, 98%)', 100: 'hsl(120, 75%, 94%)', 200: 'hsl(120, 75%, 87%)', 300: 'hsl(120, 61%, 77%)', 400: 'hsl(120, 44%, 53%)', 500: 'hsl(120, 59%, 30%)', 600: 'hsl(120, 70%, 25%)', 700: 'hsl(120, 75%, 16%)', 800: 'hsl(120, 84%, 10%)', 900: 'hsl(120, 87%, 6%)', }; export const orange = { 50: 'hsl(45, 100%, 97%)', 100: 'hsl(45, 92%, 90%)', 200: 'hsl(45, 94%, 80%)', 300: 'hsl(45, 90%, 65%)', 400: 'hsl(45, 90%, 40%)', 500: 'hsl(45, 90%, 35%)', 600: 'hsl(45, 91%, 25%)', 700: 'hsl(45, 94%, 20%)', 800: 'hsl(45, 95%, 16%)', 900: 'hsl(45, 93%, 12%)', }; export const red = { 50: 'hsl(0, 100%, 97%)', 100: 'hsl(0, 92%, 90%)', 200: 'hsl(0, 94%, 80%)', 300: 'hsl(0, 90%, 65%)', 400: 'hsl(0, 90%, 40%)', 500: 'hsl(0, 90%, 30%)', 600: 'hsl(0, 91%, 25%)', 700: 'hsl(0, 94%, 18%)', 800: 'hsl(0, 95%, 12%)', 900: 'hsl(0, 93%, 6%)', }; const darkBg = 'hsl(0, 0%, 9%)'; const darkPaper = 'hsl(0, 0%, 14%)'; const darkElevated = 'hsl(0, 0%, 19%)'; export const getDesignTokens = (mode: PaletteMode) => { customShadows[1] = mode === 'dark' ? '0 4px 16px rgba(0, 0, 0, 0.4), 0 8px 24px rgba(0, 0, 0, 0.3)' : 'hsla(220, 30%, 5%, 0.07) 0px 4px 16px 0px, hsla(220, 25%, 10%, 0.07) 0px 8px 16px -5px'; return { palette: { mode, primary: { light: brand[400], main: brand[500], dark: brand[700], contrastText: brand[50], ...(mode === 'dark' && { contrastText: brand[50], light: 'hsl(245, 85%, 70%)', main: 'hsl(243, 76%, 64%)', dark: 'hsl(243, 78%, 48%)', }), }, secondary: { light: gray[300], main: gray[600], dark: gray[800], contrastText: gray[50], ...(mode === 'dark' && { light: gray[200], main: gray[400], dark: gray[600], contrastText: gray[900], }), }, info: { light: brand[100], main: brand[400], dark: brand[600], contrastText: gray[50], ...(mode === 'dark' && { contrastText: 'hsl(210, 30%, 80%)', light: 'hsl(245, 60%, 60%)', main: 'hsl(243, 55%, 52%)', dark: 'hsl(243, 50%, 38%)', }), }, warning: { light: orange[300], main: orange[400], dark: orange[800], ...(mode === 'dark' && { light: 'hsl(45, 60%, 55%)', main: 'hsl(45, 55%, 45%)', dark: 'hsl(45, 50%, 30%)', }), }, error: { light: red[300], main: red[400], dark: red[800], ...(mode === 'dark' && { light: 'hsl(0, 55%, 60%)', main: 'hsl(0, 55%, 50%)', dark: 'hsl(0, 50%, 35%)', }), }, success: { light: green[300], main: green[400], dark: green[800], ...(mode === 'dark' && { light: 'hsl(120, 40%, 55%)', main: 'hsl(120, 40%, 45%)', dark: 'hsl(120, 35%, 30%)', }), }, grey: { ...gray, }, divider: mode === 'dark' ? 'hsla(0, 0%, 100%, 0.08)' : alpha(gray[300], 0.4), background: { default: 'hsl(0, 0%, 100%)', paper: 'hsl(220, 35%, 97%)', ...(mode === 'dark' && { default: darkBg, paper: darkPaper }), }, text: { primary: gray[800], secondary: gray[600], warning: orange[400], ...(mode === 'dark' && { primary: 'hsl(0, 0%, 92%)', secondary: 'hsl(0, 0%, 60%)' }), }, action: { hover: alpha(gray[200], 0.2), selected: `${alpha(gray[200], 0.3)}`, ...(mode === 'dark' && { hover: 'hsla(0, 0%, 100%, 0.06)', selected: 'hsla(0, 0%, 100%, 0.1)', }), }, flows: { outflows: { primary: mode === 'dark' ? 'hsl(0, 55%, 60%)' : '#d32f2f', surface: mode === 'dark' ? 'hsla(0, 35%, 25%, 0.6)' : '#fdecea', text: mode === 'dark' ? 'hsl(0, 60%, 80%)' : '#b71c1c', }, inflows: { primary: mode === 'dark' ? 'hsl(120, 40%, 55%)' : '#2e7d32', surface: mode === 'dark' ? 'hsla(120, 25%, 22%, 0.6)' : '#e8f5e9', text: mode === 'dark' ? 'hsl(120, 40%, 78%)' : '#1b5e20', }, }, }, typography: { fontFamily: 'Inter, sans-serif', h1: { fontSize: defaultTheme.typography.pxToRem(40), fontWeight: 600, lineHeight: 1.1, letterSpacing: '-0.025em', }, h2: { fontSize: defaultTheme.typography.pxToRem(32), fontWeight: 600, lineHeight: 1.2, letterSpacing: '-0.02em', }, h3: { fontSize: defaultTheme.typography.pxToRem(26), fontWeight: 600, lineHeight: 1.25, letterSpacing: '-0.015em', }, h4: { fontSize: defaultTheme.typography.pxToRem(20), fontWeight: 600, lineHeight: 1.4, letterSpacing: '-0.01em', }, h5: { fontSize: defaultTheme.typography.pxToRem(18), fontWeight: 600, lineHeight: 1.4, letterSpacing: '-0.005em', }, h6: { fontSize: defaultTheme.typography.pxToRem(16), fontWeight: 600, lineHeight: 1.5, }, subtitle1: { fontSize: defaultTheme.typography.pxToRem(16), fontWeight: 500, }, subtitle2: { fontSize: defaultTheme.typography.pxToRem(13), fontWeight: 500, }, body1: { fontSize: defaultTheme.typography.pxToRem(15), lineHeight: 1.5, }, body2: { fontSize: defaultTheme.typography.pxToRem(14), fontWeight: 400, lineHeight: 1.45, }, caption: { fontSize: defaultTheme.typography.pxToRem(12), fontWeight: 400, lineHeight: 1.4, }, overline: { fontSize: defaultTheme.typography.pxToRem(11), fontWeight: 600, lineHeight: 1.5, textTransform: 'uppercase', letterSpacing: '0.06em', }, }, shape: { borderRadius: 6, }, shadows: customShadows, }; };