import type { OverlayStyle } from '@/store/overlayStore' export interface OverlayPalette { id: string name: string swatches: string[] // preview dots (2-3 hex/rgba) bg?: string // panel background (color or gradient) border?: string // full CSS border declaration shadow?: string // box-shadow text?: string // primary text color text2?: string // secondary text color chroma?: string // characteristic color: retro border hex, neon/matrix phosphor hex, glam metal rgb-string chroma2?: string // for RGB string "r,g,b" when chroma is hex (used for --accent-rgb override) titleBg?: string // Y2K titlebar gradient bodyBg?: string // Y2K body gradient } const PALETTES: Record = { classic: [ { id: 'default', name: 'Тёмный', swatches: ['#0a0a10', '#ffffff', '#888888'], bg: 'rgba(10,10,16,0.82)', border: '1px solid rgba(255,255,255,0.09)', shadow: '0 8px 32px rgba(0,0,0,0.55)', text: '#ffffff', text2: 'rgba(255,255,255,0.45)', chroma: 'rgba(255,255,255,0.06)', }, { id: 'warm', name: 'Тёплый', swatches: ['#160c06', '#ffeedd', '#dca850'], bg: 'rgba(22,12,6,0.86)', border: '1px solid rgba(220,168,80,0.20)', shadow: '0 8px 32px rgba(20,8,0,0.6)', text: '#ffeedd', text2: 'rgba(255,200,120,0.50)', chroma: 'rgba(220,168,80,0.10)', }, { id: 'ocean', name: 'Морской', swatches: ['#040a1a', '#ddeeff', '#3c82ff'], bg: 'rgba(4,10,26,0.88)', border: '1px solid rgba(60,130,255,0.22)', shadow: '0 8px 32px rgba(0,10,40,0.6)', text: '#ddeeff', text2: 'rgba(100,170,255,0.50)', chroma: 'rgba(60,130,255,0.08)', }, { id: 'frost', name: 'Белый', swatches: ['#ffffff', '#111111', '#bbbbbb'], bg: 'rgba(255,255,255,0.90)', border: '1px solid rgba(0,0,0,0.09)', shadow: '0 8px 32px rgba(0,0,0,0.15)', text: '#111111', text2: 'rgba(0,0,0,0.42)', chroma: 'rgba(0,0,0,0.05)', }, ], aero: [ { id: 'default', name: 'Небо', swatches: ['#bee6ff', '#78b9ff', '#003a6e'], bg: 'linear-gradient(160deg,rgba(190,230,255,0.55) 0%,rgba(120,185,255,0.42) 100%)', border: '1.5px solid rgba(255,255,255,0.72)', shadow: '0 4px 20px rgba(80,160,255,0.30),inset 0 1.5px 0 rgba(255,255,255,0.65)', text: '#003a6e', text2: 'rgba(0,60,130,0.60)', }, { id: 'rose', name: 'Роза', swatches: ['#ffc8d7', '#ff87af', '#6e0030'], bg: 'linear-gradient(160deg,rgba(255,200,215,0.55) 0%,rgba(255,135,175,0.42) 100%)', border: '1.5px solid rgba(255,255,255,0.72)', shadow: '0 4px 20px rgba(255,100,160,0.30),inset 0 1.5px 0 rgba(255,255,255,0.65)', text: '#6e0030', text2: 'rgba(130,0,60,0.60)', }, { id: 'mint', name: 'Мята', swatches: ['#b4ffd2', '#50dc9b', '#003a20'], bg: 'linear-gradient(160deg,rgba(180,255,210,0.55) 0%,rgba(80,220,155,0.42) 100%)', border: '1.5px solid rgba(255,255,255,0.72)', shadow: '0 4px 20px rgba(60,200,130,0.30),inset 0 1.5px 0 rgba(255,255,255,0.65)', text: '#003a20', text2: 'rgba(0,80,50,0.60)', }, { id: 'lavender', name: 'Лаванда', swatches: ['#dcc8ff', '#9b7dff', '#3a006e'], bg: 'linear-gradient(160deg,rgba(220,200,255,0.55) 0%,rgba(155,125,255,0.42) 100%)', border: '1.5px solid rgba(255,255,255,0.72)', shadow: '0 4px 20px rgba(130,80,255,0.30),inset 0 1.5px 0 rgba(255,255,255,0.65)', text: '#3a006e', text2: 'rgba(70,0,140,0.55)', }, ], retro: [ { id: 'default', name: 'Янтарь', swatches: ['#0c0500', '#c07030', '#f8d090'], bg: 'rgba(12,5,0,0.94)', border: '2px solid #c07030', shadow: '0 0 28px rgba(180,90,20,0.45),4px 4px 0 rgba(0,0,0,0.6)', text: '#f8d090', text2: '#9a6020', chroma: 'rgba(180,100,20,0.30)', }, { id: 'phosphor', name: 'Фосфор', swatches: ['#000c04', '#30c060', '#90f8b0'], bg: 'rgba(0,12,4,0.94)', border: '2px solid #30c060', shadow: '0 0 28px rgba(20,160,60,0.45),4px 4px 0 rgba(0,0,0,0.6)', text: '#90f8b0', text2: '#207840', chroma: 'rgba(20,160,60,0.28)', }, { id: 'crt', name: 'CRT синий', swatches: ['#000412', '#3060c0', '#90b8f8'], bg: 'rgba(0,4,18,0.94)', border: '2px solid #3060c0', shadow: '0 0 28px rgba(30,80,200,0.45),4px 4px 0 rgba(0,0,0,0.6)', text: '#90b8f8', text2: '#204880', chroma: 'rgba(30,80,200,0.30)', }, { id: 'blood', name: 'Красный', swatches: ['#0e0202', '#c02828', '#f89090'], bg: 'rgba(14,2,2,0.94)', border: '2px solid #c02828', shadow: '0 0 28px rgba(180,28,20,0.45),4px 4px 0 rgba(0,0,0,0.6)', text: '#f89090', text2: '#802020', chroma: 'rgba(180,28,20,0.28)', }, ], neon: [ { id: 'default', name: 'Акцент', swatches: ['#00000a', 'var(--accent)', 'var(--accent)'], bg: 'rgba(0,0,10,0.90)', }, { id: 'cyan', name: 'Голубой', swatches: ['#00040c', '#00e5ff', '#00e5ff'], bg: 'rgba(0,4,12,0.92)', chroma: '#00e5ff', chroma2: '0,229,255', }, { id: 'magenta', name: 'Пурпур', swatches: ['#0a0008', '#ff00cc', '#ff00cc'], bg: 'rgba(10,0,8,0.92)', chroma: '#ff00cc', chroma2: '255,0,204', }, { id: 'lime', name: 'Лайм', swatches: ['#000a04', '#00ff88', '#00ff88'], bg: 'rgba(0,10,4,0.92)', chroma: '#00ff88', chroma2: '0,255,136', }, ], clean: [ { id: 'default', name: 'Стандарт', swatches: ['transparent', '#ffffff', 'var(--accent)'], }, { id: 'shadow', name: 'С тенью', swatches: ['transparent', '#ffffff', '#666666'], text: '#ffffff', }, { id: 'dark-text', name: 'Тёмный', swatches: ['transparent', '#111111', '#333333'], text: '#111111', text2: 'rgba(0,0,0,0.50)', }, { id: 'warm-text', name: 'Тёплый', swatches: ['transparent', '#ffeedd', '#ddaa66'], text: '#ffeedd', text2: 'rgba(255,200,120,0.60)', }, ], y2k: [ { id: 'default', name: 'Лунный', swatches: ['#c8d0e0', '#1a4090', '#000060'], titleBg: 'linear-gradient(90deg,#1a4090 0%,#4a80d0 40%,#1a4090 100%)', bodyBg: 'linear-gradient(160deg,#dce4f0,#c0c8e0)', text: '#000060', text2: '#404880', }, { id: 'rose', name: 'Розовый', swatches: ['#f0d4dc', '#901440', '#600020'], titleBg: 'linear-gradient(90deg,#901440 0%,#d04080 40%,#901440 100%)', bodyBg: 'linear-gradient(160deg,#f0d4dc,#d0b0c0)', text: '#600020', text2: '#804060', }, { id: 'dark', name: 'Тёмный', swatches: ['#c0c0c8', '#484848', '#000020'], titleBg: 'linear-gradient(90deg,#282828 0%,#484848 40%,#282828 100%)', bodyBg: 'linear-gradient(160deg,#c0c0c8,#a0a0b0)', text: '#000020', text2: '#303040', }, { id: 'forest', name: 'Лесной', swatches: ['#d4ecd8', '#106020', '#004010'], titleBg: 'linear-gradient(90deg,#106020 0%,#308040 40%,#106020 100%)', bodyBg: 'linear-gradient(160deg,#d4ecd8,#b8d8c0)', text: '#004010', text2: '#306040', }, ], lofi: [ { id: 'default', name: 'Коричневый', swatches: ['#2a1a0e', '#fde8c0', '#e8a060'], bg: 'rgba(42,26,14,0.92)', text: '#fde8c0', text2: 'rgba(var(--accent-rgb),0.60)', }, { id: 'night', name: 'Ночной', swatches: ['#0c1020', '#c0d4f8', '#7090d8'], bg: 'rgba(12,16,32,0.92)', text: '#c0d4f8', text2: 'rgba(var(--accent-rgb),0.60)', }, { id: 'forest', name: 'Лесной', swatches: ['#0c1c10', '#c8f0c8', '#60c870'], bg: 'rgba(12,28,16,0.92)', text: '#c8f0c8', text2: 'rgba(var(--accent-rgb),0.60)', }, { id: 'plum', name: 'Сливовый', swatches: ['#1c0c20', '#e8c0f8', '#c060d8'], bg: 'rgba(28,12,32,0.92)', text: '#e8c0f8', text2: 'rgba(var(--accent-rgb),0.60)', }, ], glam: [ { id: 'default', name: 'Золото', swatches: ['#1c1204', '#d4af37', '#f0c840'], bg: 'linear-gradient(145deg,rgba(28,18,4,0.95),rgba(16,10,2,0.95))', chroma: '212,175,55', text: '#f0c840', text2: 'rgba(200,150,30,0.65)', }, { id: 'silver', name: 'Серебро', swatches: ['#101214', '#c0c8d2', '#e0e8f0'], bg: 'linear-gradient(145deg,rgba(16,18,20,0.96),rgba(10,12,14,0.96))', chroma: '192,200,210', text: '#e0e8f0', text2: 'rgba(160,170,180,0.65)', }, { id: 'rose-gold', name: 'Розовое золото', swatches: ['#160e0e', '#dc9e8e', '#f0c8b8'], bg: 'linear-gradient(145deg,rgba(22,14,14,0.95),rgba(14,8,8,0.95))', chroma: '220,158,142', text: '#f0c8b8', text2: 'rgba(200,140,120,0.65)', }, { id: 'emerald', name: 'Изумруд', swatches: ['#08140e', '#32b478', '#80f8c0'], bg: 'linear-gradient(145deg,rgba(8,20,14,0.95),rgba(4,12,8,0.95))', chroma: '50,180,120', text: '#80f8c0', text2: 'rgba(40,160,100,0.65)', }, ], matrix: [ { id: 'default', name: 'Зелёный', swatches: ['#000800', '#00ff32', '#00ff32'], bg: 'rgba(0,8,0,0.93)', chroma: '#00ff32', chroma2: '0,255,50', border: '1px solid rgba(0,255,50,0.35)', }, { id: 'cyan', name: 'Голубой', swatches: ['#00040c', '#00e5ff', '#00e5ff'], bg: 'rgba(0,4,12,0.93)', chroma: '#00e5ff', chroma2: '0,229,255', border: '1px solid rgba(0,229,255,0.35)', }, { id: 'amber', name: 'Янтарь', swatches: ['#0c0800', '#ffb400', '#ffb400'], bg: 'rgba(12,8,0,0.93)', chroma: '#ffb400', chroma2: '255,180,0', border: '1px solid rgba(255,180,0,0.35)', }, { id: 'violet', name: 'Пурпур', swatches: ['#08000c', '#cc00ff', '#cc00ff'], bg: 'rgba(8,0,12,0.93)', chroma: '#cc00ff', chroma2: '204,0,255', border: '1px solid rgba(204,0,255,0.35)', }, ], } export function getPalettes(style: OverlayStyle): OverlayPalette[] { return PALETTES[style] ?? PALETTES.classic } export function getPalette(style: OverlayStyle, paletteId: string): OverlayPalette { const list = getPalettes(style) return list.find(p => p.id === paletteId) ?? list[0] } // ── Custom palette ──────────────────────────────────────────────────────────── export interface ColorFieldDef { key: string label: string default: string // hex default for the color picker } export const STYLE_CUSTOM_FIELDS: Record = { classic: [ { key: 'bg', label: 'Фон', default: '#0a0a10' }, { key: 'chroma', label: 'Рамка', default: '#ffffff' }, { key: 'text', label: 'Текст', default: '#ffffff' }, { key: 'text2', label: 'Текст 2', default: '#888888' }, ], aero: [ { key: 'bg', label: 'Цвет', default: '#bee6ff' }, { key: 'text', label: 'Текст', default: '#003a6e' }, { key: 'text2', label: 'Текст 2', default: '#004488' }, ], retro: [ { key: 'bg', label: 'Фон', default: '#0c0500' }, { key: 'chroma', label: 'Хром', default: '#c07030' }, { key: 'text', label: 'Текст', default: '#f8d090' }, { key: 'text2', label: 'Текст 2', default: '#9a6020' }, ], neon: [ { key: 'bg', label: 'Фон', default: '#00000a' }, { key: 'chroma', label: 'Свечение', default: '#de9cfe' }, ], clean: [ { key: 'text', label: 'Текст', default: '#ffffff' }, { key: 'text2', label: 'Текст 2', default: '#888888' }, ], y2k: [ { key: 'titleBg', label: 'Заголовок', default: '#1a4090' }, { key: 'bodyBg', label: 'Тело', default: '#c0c8e0' }, { key: 'text', label: 'Текст', default: '#000060' }, { key: 'text2', label: 'Текст 2', default: '#404880' }, ], lofi: [ { key: 'bg', label: 'Фон', default: '#2a1a0e' }, { key: 'text', label: 'Текст', default: '#fde8c0' }, { key: 'text2', label: 'Текст 2', default: '#e8a060' }, ], glam: [ { key: 'bg', label: 'Фон', default: '#1c1204' }, { key: 'chroma', label: 'Металл', default: '#d4af37' }, { key: 'text', label: 'Текст', default: '#f0c840' }, ], matrix: [ { key: 'bg', label: 'Фон', default: '#000800' }, { key: 'chroma', label: 'Фосфор', default: '#00ff32' }, ], } function hexToRgba(hex: string, a: number): string { if (!/^#[0-9a-fA-F]{6}$/.test(hex)) return hex const r = parseInt(hex.slice(1, 3), 16) const g = parseInt(hex.slice(3, 5), 16) const b = parseInt(hex.slice(5, 7), 16) return `rgba(${r},${g},${b},${a})` } function hexToRgb(hex: string): string { if (!/^#[0-9a-fA-F]{6}$/.test(hex)) return '128,128,128' const r = parseInt(hex.slice(1, 3), 16) const g = parseInt(hex.slice(3, 5), 16) const b = parseInt(hex.slice(5, 7), 16) return `${r},${g},${b}` } export function buildCustomPalette( style: OverlayStyle, data: Record, ): OverlayPalette { const pal: OverlayPalette = { id: 'custom', name: 'Свой', swatches: [] } if (data.text) pal.text = data.text if (data.text2) pal.text2 = data.text2 if (data.bg) { if (style === 'aero') { pal.bg = `linear-gradient(160deg,${hexToRgba(data.bg, 0.55)} 0%,${hexToRgba(data.bg, 0.38)} 100%)` } else { const alpha = style === 'classic' ? 0.85 : 0.92 pal.bg = hexToRgba(data.bg, alpha) } } if (data.chroma) { switch (style) { case 'glam': pal.chroma = hexToRgb(data.chroma) break case 'neon': case 'matrix': pal.chroma = data.chroma pal.chroma2 = hexToRgb(data.chroma) if (style === 'matrix') { pal.border = `1px solid ${hexToRgba(data.chroma, 0.38)}` } break case 'retro': pal.chroma = hexToRgba(data.chroma, 0.30) pal.border = `2px solid ${data.chroma}` pal.shadow = `0 0 28px ${hexToRgba(data.chroma, 0.45)},4px 4px 0 rgba(0,0,0,0.6)` break case 'classic': pal.border = `1px solid ${hexToRgba(data.chroma, 0.28)}` pal.chroma = hexToRgba(data.chroma, 0.10) break default: pal.chroma = data.chroma } } if (data.titleBg) pal.titleBg = data.titleBg if (data.bodyBg) pal.bodyBg = data.bodyBg return pal }