/** * Процедурно-сгенерированная SVG-обложка в стиле ZeroPost. * Используется когда настоящая обложка ещё не сгенерирована. * Каждая статья получает уникальный, воспроизводимый узор. */ function rng(seed) { let t = seed + 0x6D2B79F5; return () => { t = Math.imul(t ^ (t >>> 15), t | 1); t ^= t + Math.imul(t ^ (t >>> 7), t | 61); return ((t ^ (t >>> 14)) >>> 0) / 4294967296; }; } // Только наши бренд-палитры — никакого произвольного фиолетового const PALETTES = [ { bg: '#ecfdf5', accent: '#10b981', soft: '#a7f3d0', dark: '#065f46' }, // emerald (основной) { bg: '#f0fdfa', accent: '#14b8a6', soft: '#99f6e4', dark: '#115e59' }, // teal { bg: '#f8fafc', accent: '#10b981', soft: '#d1fae5', dark: '#1e293b' }, // emerald+neutral { bg: '#fefce8', accent: '#d97706', soft: '#fde68a', dark: '#92400e' }, // amber { bg: '#eff6ff', accent: '#3b82f6', soft: '#bfdbfe', dark: '#1e40af' }, // blue ]; export default function ArticleCoverSVG({ article, className = '', aspect = '16/9' }) { const seed = (article?.id || 1) * 9301 + 49297; const rand = rng(seed); // Выбор палитры по id — не случайный, а детерминированный const palette = PALETTES[(article?.id || 0) % PALETTES.length]; const layers = 3 + Math.floor(rand() * 3); const shapes = []; for (let i = 0; i < layers; i++) { const kind = ['circle', 'circle', 'arc', 'rect'][Math.floor(rand() * 4)]; // circle чаще const opacity = 0.25 + rand() * 0.45; const colors = [palette.accent, palette.soft, palette.dark]; const fill = colors[Math.floor(rand() * colors.length)]; shapes.push({ kind, opacity, fill, r: rand }); } return (