/* ============================================================ PRESETS — cover style definitions Each preset defines: bg, layout (position/align), per-field typography defaults, and a decoration recipe. ============================================================ */ const FONTS = { archivo: '"Archivo Black", sans-serif', bricolage: '"Bricolage Grotesque", sans-serif', manrope: '"Manrope", sans-serif', space: '"Space Grotesk", sans-serif', instrument: '"Instrument Serif", serif', playfair: '"Playfair Display", serif', garamond: '"EB Garamond", serif', mono: '"JetBrains Mono", ui-monospace, monospace', }; const FONT_LABEL = { archivo: 'Archivo Black', bricolage: 'Bricolage Grotesque', manrope: 'Manrope', space: 'Space Grotesk', instrument: 'Instrument Serif', playfair: 'Playfair Display', garamond: 'EB Garamond', mono: 'JetBrains Mono', }; const PRESETS = { magazine: { name: 'Журнал', desc: 'Display, плашка', bg: { mode: 'solid', color: '#F2EBDC' }, layout: { position: 'bottom', align: 'left' }, kicker: { font: 'archivo', size: 3.4, weight: 900, color: '#161616', case: 'upper', tracking: 0.18, lh: 1, plate: '#F2C84B', padded: true }, title: { font: 'bricolage', size: 15, weight: 800, color: '#161616', case: 'normal', tracking: -0.025, lh: 0.92 }, subtitle:{ font: 'manrope', size: 3.4, weight: 500, color: '#3C3A33', case: 'normal', tracking: 0, lh: 1.3 }, deco: 'magazine', }, book: { name: 'Книга', desc: 'Классика, серифы', bg: { mode: 'solid', color: '#1F3D2E' }, layout: { position: 'center', align: 'center' }, kicker: { font: 'garamond', size: 2.6, weight: 500, color: '#C9B66E', case: 'upper', tracking: 0.4, lh: 1, italic: true }, title: { font: 'instrument', size: 16, weight: 400, color: '#F4ECDD', case: 'normal', tracking: 0, lh: 1.0 }, subtitle:{ font: 'garamond', size: 3, weight: 400, color: '#C9B66E', case: 'normal', tracking: 0.02, lh: 1.4, italic: true }, deco: 'book', }, modern: { name: 'Модерн', desc: 'Минимал, воздух', bg: { mode: 'solid', color: '#F8F7F3' }, layout: { position: 'center', align: 'left' }, kicker: { font: 'manrope', size: 2.4, weight: 600, color: '#888680', case: 'upper', tracking: 0.32, lh: 1 }, title: { font: 'manrope', size: 10, weight: 200, color: '#1A1A1A', case: 'normal', tracking: -0.04, lh: 1.0 }, subtitle:{ font: 'manrope', size: 3, weight: 400, color: '#6E6C66', case: 'normal', tracking: 0, lh: 1.4 }, deco: 'modern', }, brutalist: { name: 'Brutalist', desc: 'Контраст, гротеск', bg: { mode: 'solid', color: '#F2DC1B' }, layout: { position: 'bottom', align: 'left' }, kicker: { font: 'mono', size: 2.6, weight: 500, color: '#0A0A0A', case: 'upper', tracking: 0.04, lh: 1 }, title: { font: 'archivo', size: 17, weight: 900, color: '#0A0A0A', case: 'upper', tracking: -0.03, lh: 0.86 }, subtitle:{ font: 'mono', size: 2.6, weight: 500, color: '#0A0A0A', case: 'normal', tracking: 0, lh: 1.4 }, deco: 'brutalist', }, editorial: { name: 'Editorial', desc: 'Серифы, контраст', bg: { mode: 'solid', color: '#F6F2EA' }, layout: { position: 'center', align: 'center' }, kicker: { font: 'manrope', size: 2.2, weight: 700, color: '#9C2B2B', case: 'upper', tracking: 0.35, lh: 1 }, title: { font: 'playfair', size: 13, weight: 700, color: '#1A1A1A', case: 'normal', tracking: -0.015, lh: 0.98, italic: true }, subtitle:{ font: 'garamond', size: 3.2, weight: 400, color: '#4A4742', case: 'normal', tracking: 0.01, lh: 1.4, italic: true }, deco: 'editorial', }, tech: { name: 'Tech', desc: 'Линейный, сетка', bg: { mode: 'solid', color: '#0B0B0E' }, layout: { position: 'bottom', align: 'left' }, kicker: { font: 'mono', size: 2.4, weight: 500, color: '#8B89F7', case: 'normal', tracking: 0.03, lh: 1 }, title: { font: 'space', size: 12, weight: 600, color: '#F4F4F6', case: 'normal', tracking: -0.025, lh: 0.98 }, subtitle:{ font: 'manrope', size: 2.8, weight: 400, color: '#85858E', case: 'normal', tracking: 0, lh: 1.45 }, deco: 'tech', }, photo: { name: 'Photo', desc: 'Фото на весь фон', bg: { mode: 'photo', seed: 'beauticard-1' }, layout: { position: 'bottom', align: 'left' }, kicker: { font: 'manrope', size: 2.4, weight: 600, color: '#FFFFFF', case: 'upper', tracking: 0.3, lh: 1, opacity: 0.85 }, title: { font: 'space', size: 11, weight: 700, color: '#FFFFFF', case: 'normal', tracking: -0.02, lh: 1.0 }, subtitle:{ font: 'manrope', size: 2.9, weight: 500, color: '#FFFFFF', case: 'normal', tracking: 0, lh: 1.4, opacity: 0.85 }, deco: 'photo', }, gradient: { name: 'Gradient', desc: 'Мягкий градиент', bg: { mode: 'mesh', a: '#FFB1A5', b: '#9D9AFF', c: '#FFE7A6' }, layout: { position: 'center', align: 'center' }, kicker: { font: 'manrope', size: 2.4, weight: 600, color: '#FFFFFF', case: 'upper', tracking: 0.32, lh: 1, opacity: 0.9 }, title: { font: 'space', size: 13, weight: 700, color: '#FFFFFF', case: 'normal', tracking: -0.025, lh: 1.0 }, subtitle:{ font: 'manrope', size: 3, weight: 500, color: '#FFFFFF', case: 'normal', tracking: 0, lh: 1.4, opacity: 0.85 }, deco: 'gradient', }, }; const PRESET_ORDER = ['magazine','book','modern','brutalist','editorial','tech','photo','gradient']; const ASPECTS = { '3:4': { w: 3, h: 4, label: '3:4', hint: 'Журнал' }, '1:1': { w: 1, h: 1, label: '1:1', hint: 'Соцсети' }, '16:9': { w: 16, h: 9, label: '16:9', hint: 'Блог' }, '9:16': { w: 9, h: 16, label: '9:16', hint: 'Stories' }, }; const POSITIONS = ['top','center','bottom']; const ALIGNS = ['left','center','right']; /* ============================================================ Backgrounds ============================================================ */ function BackgroundLayer({ bg, presetDeco }) { if (!bg) return null; if (bg.mode === 'solid') { return
; } if (bg.mode === 'gradient') { return ; } if (bg.mode === 'mesh') { return ; } if (bg.mode === 'photo') { const url = bg.url || `https://picsum.photos/seed/${encodeURIComponent(bg.seed || 'cover')}/900/1200`; return ( <> {presetDeco !== false && ( )} > ); } if (bg.mode === 'pattern') { const patterns = { dots: `radial-gradient(circle at 1px 1px, ${bg.fg} 1px, transparent 0) 0 0/${bg.scale||16}px ${bg.scale||16}px`, grid: `linear-gradient(${bg.fg} 1px, transparent 1px) 0 0/${bg.scale||24}px ${bg.scale||24}px, linear-gradient(90deg, ${bg.fg} 1px, transparent 1px) 0 0/${bg.scale||24}px ${bg.scale||24}px`, lines: `repeating-linear-gradient(45deg, ${bg.fg} 0 1px, transparent 1px ${bg.scale||10}px)`, }; return (