gentelella
Version:
Gentelella v4 — free admin template. 60 pages, 20 chart variants, fully interactive inbox & kanban, live theme generator, component playground, PWA-ready. Vite 8, vanilla JS, no Bootstrap, no jQuery.
416 lines (385 loc) • 26.2 kB
JavaScript
// Inline SVG dashboard mockups used as product gallery imagery in
// production/product_detail.html. Hand-crafted to mirror the actual v4
// design system (sidebar, topbar, cards, charts) so the product page sells
// the template using its own UI rather than emoji placeholders.
const COLORS = {
bg: '#f5f7fb',
bgDark: '#0f1623',
surface: '#ffffff',
surfaceDark: '#1a2332',
surfaceDk2: '#141d2b',
border: '#e6e7eb',
borderDark: 'rgba(255,255,255,0.1)',
text: '#1e2633',
textDark: '#e6ebf2',
muted: '#9ba5b1',
mutedDark: '#8a93a3',
primary: '#1ABB9C',
azure: '#4299e1',
yellow: '#f59f00',
red: '#d63939',
purple: '#ae3ec9',
green: '#2fb344',
blue: '#066fd1'
};
// Shared shell for dashboard mockups — sidebar, topbar, and brand mark.
function shell(t) {
return `
<!-- Sidebar -->
<rect width="60" height="300" fill="${COLORS.surfaceDark}"/>
<rect x="6" y="9" width="14" height="14" rx="3" fill="${COLORS.primary}"/>
<text x="13" y="20" font-size="9" font-weight="700" fill="white" text-anchor="middle" font-family="Inter,sans-serif">G</text>
<rect x="24" y="13" width="24" height="6" rx="1" fill="rgba(255,255,255,0.95)"/>
<rect x="6" y="38" width="20" height="3" rx="1" fill="rgba(255,255,255,0.18)"/>
<rect x="6" y="48" width="48" height="7" rx="2" fill="rgba(26,187,156,0.22)"/>
<rect x="6" y="60" width="48" height="6" rx="2" fill="rgba(255,255,255,0.05)"/>
<rect x="6" y="71" width="48" height="6" rx="2" fill="rgba(255,255,255,0.05)"/>
<rect x="6" y="82" width="48" height="6" rx="2" fill="rgba(255,255,255,0.05)"/>
<rect x="6" y="93" width="48" height="6" rx="2" fill="rgba(255,255,255,0.05)"/>
<rect x="6" y="113" width="20" height="3" rx="1" fill="rgba(255,255,255,0.18)"/>
<rect x="6" y="123" width="48" height="6" rx="2" fill="rgba(255,255,255,0.05)"/>
<rect x="6" y="134" width="48" height="6" rx="2" fill="rgba(255,255,255,0.05)"/>
<rect x="6" y="145" width="48" height="6" rx="2" fill="rgba(255,255,255,0.05)"/>
<rect x="6" y="280" width="48" height="13" rx="3" fill="rgba(255,255,255,0.04)"/>
<circle cx="13" cy="286.5" r="4" fill="${COLORS.primary}"/>
<!-- Topbar -->
<rect x="60" width="340" height="22" fill="${t === 'dark' ? COLORS.surfaceDk2 : COLORS.surface}"/>
<line x1="60" y1="22" x2="400" y2="22" stroke="${t === 'dark' ? COLORS.borderDark : COLORS.border}"/>
<rect x="70" y="8" width="38" height="4" rx="1" fill="${t === 'dark' ? COLORS.mutedDark : COLORS.muted}"/>
<circle cx="115" cy="10" r="1.2" fill="${t === 'dark' ? COLORS.mutedDark : COLORS.muted}"/>
<rect x="120" y="8" width="40" height="4" rx="1" fill="${t === 'dark' ? COLORS.textDark : COLORS.text}"/>
<rect x="240" y="6" width="60" height="11" rx="3" fill="${t === 'dark' ? '#0f1623' : COLORS.bg}"/>
<circle cx="320" cy="11" r="4" fill="none" stroke="${t === 'dark' ? COLORS.mutedDark : COLORS.muted}" stroke-width="1.2"/>
<circle cx="340" cy="11" r="4" fill="none" stroke="${t === 'dark' ? COLORS.mutedDark : COLORS.muted}" stroke-width="1.2"/>
<circle cx="362" cy="11" r="6" fill="${COLORS.primary}"/>
<text x="362" y="14" font-size="6" font-weight="700" fill="white" text-anchor="middle" font-family="Inter,sans-serif">A</text>
<!-- Page header -->
<rect x="70" y="32" width="50" height="4" rx="1" fill="${t === 'dark' ? COLORS.mutedDark : COLORS.muted}"/>
<rect x="70" y="40" width="80" height="6" rx="1" fill="${t === 'dark' ? COLORS.textDark : COLORS.text}"/>
`;
}
function statCard(x, y, accent, theme) {
const surface = theme === 'dark' ? COLORS.surfaceDk2 : COLORS.surface;
const border = theme === 'dark' ? COLORS.borderDark : COLORS.border;
const text = theme === 'dark' ? COLORS.textDark : COLORS.text;
const muted = theme === 'dark' ? COLORS.mutedDark : COLORS.muted;
return `
<g transform="translate(${x}, ${y})">
<rect width="105" height="56" rx="4" fill="${surface}" stroke="${border}"/>
<circle cx="20" cy="20" r="11" fill="${accent}" fill-opacity="0.14"/>
<rect x="14" y="16" width="12" height="8" rx="1.5" fill="${accent}"/>
<rect x="38" y="14" width="44" height="4" rx="1" fill="${muted}"/>
<rect x="38" y="24" width="32" height="8" rx="1" fill="${text}"/>
<rect x="38" y="38" width="56" height="3" rx="1" fill="${muted}"/>
<!-- mini sparkline -->
<polyline points="14,46 22,42 30,44 38,38 46,40" fill="none" stroke="${accent}" stroke-width="1.2"/>
</g>
`;
}
// Overview dashboard (light)
const overview = `<svg viewBox="0 0 400 300" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid slice" style="width:100%;height:100%">
<rect width="400" height="300" fill="${COLORS.bg}"/>
${shell('light')}
${statCard(70, 56, COLORS.primary, 'light')}
${statCard(180, 56, COLORS.azure, 'light')}
${statCard(290, 56, COLORS.yellow, 'light')}
<!-- Big chart card -->
<g transform="translate(70, 122)">
<rect width="215" height="170" rx="4" fill="${COLORS.surface}" stroke="${COLORS.border}"/>
<rect x="12" y="12" width="80" height="6" rx="1" fill="${COLORS.text}"/>
<rect x="12" y="22" width="50" height="3" rx="1" fill="${COLORS.muted}"/>
<rect x="170" y="12" width="34" height="11" rx="3" fill="${COLORS.bg}"/>
<rect x="173" y="15" width="10" height="5" rx="1" fill="${COLORS.primary}"/>
<!-- Grid lines -->
<line x1="20" y1="60" x2="200" y2="60" stroke="${COLORS.border}" stroke-dasharray="2,2"/>
<line x1="20" y1="90" x2="200" y2="90" stroke="${COLORS.border}" stroke-dasharray="2,2"/>
<line x1="20" y1="120" x2="200" y2="120" stroke="${COLORS.border}" stroke-dasharray="2,2"/>
<!-- Area fill -->
<polygon points="20,128 50,108 80,118 110,88 140,98 170,68 200,58 200,150 20,150" fill="${COLORS.primary}" fill-opacity="0.15"/>
<!-- Primary line -->
<polyline points="20,128 50,108 80,118 110,88 140,98 170,68 200,58" fill="none" stroke="${COLORS.primary}" stroke-width="2" stroke-linejoin="round"/>
<!-- Dashed secondary line -->
<polyline points="20,138 50,128 80,132 110,118 140,122 170,108 200,103" fill="none" stroke="${COLORS.azure}" stroke-width="1.5" stroke-dasharray="3,2"/>
<!-- X axis -->
<line x1="20" y1="150" x2="200" y2="150" stroke="${COLORS.border}"/>
<text x="22" y="160" font-size="5.5" fill="${COLORS.muted}">Mon</text>
<text x="50" y="160" font-size="5.5" fill="${COLORS.muted}">Tue</text>
<text x="80" y="160" font-size="5.5" fill="${COLORS.muted}">Wed</text>
<text x="110" y="160" font-size="5.5" fill="${COLORS.muted}">Thu</text>
<text x="140" y="160" font-size="5.5" fill="${COLORS.muted}">Fri</text>
<text x="170" y="160" font-size="5.5" fill="${COLORS.muted}">Sat</text>
<text x="195" y="160" font-size="5.5" fill="${COLORS.muted}" text-anchor="end">Sun</text>
</g>
<!-- Activity list -->
<g transform="translate(295, 122)">
<rect width="100" height="170" rx="4" fill="${COLORS.surface}" stroke="${COLORS.border}"/>
<rect x="10" y="12" width="55" height="6" rx="1" fill="${COLORS.text}"/>
${[
{ y: 28, c: COLORS.primary, w: 60 },
{ y: 50, c: COLORS.azure, w: 50 },
{ y: 72, c: COLORS.green, w: 56 },
{ y: 94, c: COLORS.yellow, w: 48 },
{ y: 116, c: COLORS.purple, w: 52 },
{ y: 138, c: COLORS.red, w: 56 }
].map((a) => `
<g transform="translate(10, ${a.y})">
<circle cx="9" cy="9" r="7" fill="${a.c}" fill-opacity="0.85"/>
<rect x="22" y="5" width="${a.w}" height="3" rx="1" fill="${COLORS.text}"/>
<rect x="22" y="11" width="${Math.round(a.w * 0.6)}" height="2.5" rx="1" fill="${COLORS.muted}"/>
</g>
`).join('')}
</g>
</svg>`;
// Analytics — multi-chart layout (light)
const analytics = `<svg viewBox="0 0 400 300" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid slice" style="width:100%;height:100%">
<rect width="400" height="300" fill="${COLORS.bg}"/>
${shell('light')}
<!-- Two chart cards -->
<g transform="translate(70, 56)">
<rect width="160" height="115" rx="4" fill="${COLORS.surface}" stroke="${COLORS.border}"/>
<rect x="10" y="10" width="80" height="6" rx="1" fill="${COLORS.text}"/>
<rect x="10" y="20" width="40" height="14" rx="1" fill="${COLORS.text}"/>
<rect x="55" y="24" width="40" height="6" rx="1" fill="${COLORS.green}" fill-opacity="0.8"/>
<!-- Bar chart -->
${[20, 35, 28, 50, 42, 58, 70, 65].map((h, i) => `
<rect x="${14 + i * 18}" y="${100 - h}" width="11" height="${h}" rx="2" fill="${[COLORS.primary, COLORS.azure, COLORS.yellow, COLORS.green, COLORS.purple, COLORS.red, COLORS.primary, COLORS.azure][i]}"/>
`).join('')}
</g>
<g transform="translate(240, 56)">
<rect width="155" height="115" rx="4" fill="${COLORS.surface}" stroke="${COLORS.border}"/>
<rect x="10" y="10" width="60" height="6" rx="1" fill="${COLORS.text}"/>
<!-- Donut -->
<circle cx="80" cy="68" r="32" fill="none" stroke="${COLORS.bg}" stroke-width="14"/>
<circle cx="80" cy="68" r="32" fill="none" stroke="${COLORS.primary}" stroke-width="14" stroke-dasharray="80 200" transform="rotate(-90 80 68)"/>
<circle cx="80" cy="68" r="32" fill="none" stroke="${COLORS.azure}" stroke-width="14" stroke-dasharray="40 200" stroke-dashoffset="-80" transform="rotate(-90 80 68)"/>
<circle cx="80" cy="68" r="32" fill="none" stroke="${COLORS.yellow}" stroke-width="14" stroke-dasharray="30 200" stroke-dashoffset="-120" transform="rotate(-90 80 68)"/>
<circle cx="80" cy="68" r="32" fill="none" stroke="${COLORS.purple}" stroke-width="14" stroke-dasharray="24 200" stroke-dashoffset="-150" transform="rotate(-90 80 68)"/>
<text x="80" y="65" font-size="8" font-weight="700" fill="${COLORS.text}" text-anchor="middle" font-family="Inter,sans-serif">8.4k</text>
<text x="80" y="75" font-size="5" fill="${COLORS.muted}" text-anchor="middle" font-family="Inter,sans-serif">devices</text>
<!-- Legend -->
<g transform="translate(118, 50)" font-family="Inter,sans-serif" font-size="5.5">
<rect width="6" height="6" rx="1" fill="${COLORS.primary}"/><text x="9" y="5" fill="${COLORS.text}">iOS</text><text x="35" y="5" fill="${COLORS.muted}" text-anchor="end">30%</text>
<g transform="translate(0, 11)"><rect width="6" height="6" rx="1" fill="${COLORS.azure}"/><text x="9" y="5" fill="${COLORS.text}">Android</text><text x="35" y="5" fill="${COLORS.muted}" text-anchor="end">25%</text></g>
<g transform="translate(0, 22)"><rect width="6" height="6" rx="1" fill="${COLORS.yellow}"/><text x="9" y="5" fill="${COLORS.text}">Desktop</text><text x="35" y="5" fill="${COLORS.muted}" text-anchor="end">20%</text></g>
<g transform="translate(0, 33)"><rect width="6" height="6" rx="1" fill="${COLORS.purple}"/><text x="9" y="5" fill="${COLORS.text}">Tablet</text><text x="35" y="5" fill="${COLORS.muted}" text-anchor="end">15%</text></g>
</g>
</g>
<!-- Wide line chart -->
<g transform="translate(70, 178)">
<rect width="325" height="115" rx="4" fill="${COLORS.surface}" stroke="${COLORS.border}"/>
<rect x="10" y="10" width="80" height="6" rx="1" fill="${COLORS.text}"/>
<rect x="10" y="20" width="50" height="3" rx="1" fill="${COLORS.muted}"/>
<line x1="14" y1="60" x2="315" y2="60" stroke="${COLORS.border}" stroke-dasharray="2,2"/>
<line x1="14" y1="80" x2="315" y2="80" stroke="${COLORS.border}" stroke-dasharray="2,2"/>
<polygon points="14,95 50,80 86,82 122,68 158,72 194,55 230,60 266,42 302,38 314,40 314,100 14,100" fill="${COLORS.primary}" fill-opacity="0.12"/>
<polyline points="14,95 50,80 86,82 122,68 158,72 194,55 230,60 266,42 302,38 314,40" fill="none" stroke="${COLORS.primary}" stroke-width="2" stroke-linejoin="round"/>
<polyline points="14,98 50,90 86,89 122,82 158,84 194,75 230,78 266,70 302,68 314,72" fill="none" stroke="${COLORS.azure}" stroke-width="1.5" stroke-dasharray="3,2"/>
</g>
</svg>`;
// Tables view (light)
const tables = `<svg viewBox="0 0 400 300" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid slice" style="width:100%;height:100%">
<rect width="400" height="300" fill="${COLORS.bg}"/>
${shell('light')}
<g transform="translate(70, 56)">
<rect width="325" height="237" rx="4" fill="${COLORS.surface}" stroke="${COLORS.border}"/>
<!-- Header -->
<rect x="14" y="12" width="60" height="6" rx="1" fill="${COLORS.text}"/>
<rect x="14" y="22" width="40" height="3" rx="1" fill="${COLORS.muted}"/>
<!-- Search -->
<rect x="220" y="12" width="90" height="14" rx="3" fill="${COLORS.bg}"/>
<rect x="226" y="17" width="60" height="4" rx="1" fill="${COLORS.muted}"/>
<!-- Table head -->
<rect x="14" y="40" width="297" height="18" rx="2" fill="${COLORS.bg}"/>
${['Order', 'Customer', 'Product', 'Status', 'Date'].map((h, i) => `
<text x="${22 + i * 60}" y="51" font-size="6" font-weight="600" fill="${COLORS.muted}" font-family="Inter,sans-serif">${h}</text>
`).join('')}
<!-- Rows -->
${[
{ id: '#7841', c: 'JD', cb: COLORS.primary, p: 'AdminLTE Pro', s: 'Paid', sb: COLORS.green, d: 'Apr 28' },
{ id: '#7840', c: 'AS', cb: COLORS.azure, p: 'Gentelella Theme', s: 'Processing', sb: COLORS.blue, d: 'Apr 27' },
{ id: '#7839', c: 'RJ', cb: COLORS.purple, p: 'Dashboard Pack', s: 'Paid', sb: COLORS.green, d: 'Apr 27' },
{ id: '#7838', c: 'EW', cb: COLORS.yellow, p: 'ArchitectUI', s: 'Pending', sb: COLORS.yellow, d: 'Apr 26' },
{ id: '#7837', c: 'MK', cb: COLORS.red, p: 'Bootstrap Bundle', s: 'Cancelled', sb: COLORS.red, d: 'Apr 25' },
{ id: '#7836', c: 'LP', cb: COLORS.green, p: 'UI Kit Pro', s: 'Paid', sb: COLORS.green, d: 'Apr 25' },
{ id: '#7835', c: 'DR', cb: COLORS.blue, p: 'Vue Admin', s: 'Paid', sb: COLORS.green, d: 'Apr 24' },
{ id: '#7834', c: 'YT', cb: COLORS.primary, p: 'React Dash', s: 'Processing', sb: COLORS.blue, d: 'Apr 24' }
].map((r, i) => `
<g transform="translate(0, ${68 + i * 21})">
<text x="22" y="7" font-size="6" font-weight="600" fill="${COLORS.primary}" font-family="Inter,sans-serif">${r.id}</text>
<circle cx="84" cy="5" r="5" fill="${r.cb}"/>
<text x="84" y="7" font-size="4.5" font-weight="700" fill="white" text-anchor="middle" font-family="Inter,sans-serif">${r.c}</text>
<text x="142" y="7" font-size="6" fill="${COLORS.text}" font-family="Inter,sans-serif">${r.p}</text>
<rect x="200" y="0" width="40" height="11" rx="3" fill="${r.sb}" fill-opacity="0.16"/>
<text x="220" y="7.5" font-size="5.5" font-weight="600" fill="${r.sb}" text-anchor="middle" font-family="Inter,sans-serif">${r.s}</text>
<text x="262" y="7" font-size="5.5" fill="${COLORS.muted}" font-family="Inter,sans-serif">${r.d}</text>
<line x1="14" y1="14" x2="311" y2="14" stroke="${COLORS.border}" stroke-opacity="0.5"/>
</g>
`).join('')}
</g>
</svg>`;
// Dark mode dashboard
const dark = `<svg viewBox="0 0 400 300" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid slice" style="width:100%;height:100%">
<rect width="400" height="300" fill="${COLORS.bgDark}"/>
${shell('dark')}
${statCard(70, 56, COLORS.primary, 'dark')}
${statCard(180, 56, COLORS.azure, 'dark')}
${statCard(290, 56, COLORS.purple, 'dark')}
<g transform="translate(70, 122)">
<rect width="215" height="170" rx="4" fill="${COLORS.surfaceDk2}" stroke="${COLORS.borderDark}"/>
<rect x="12" y="12" width="80" height="6" rx="1" fill="${COLORS.textDark}"/>
<rect x="12" y="22" width="50" height="3" rx="1" fill="${COLORS.mutedDark}"/>
<line x1="20" y1="60" x2="200" y2="60" stroke="${COLORS.borderDark}" stroke-dasharray="2,2"/>
<line x1="20" y1="90" x2="200" y2="90" stroke="${COLORS.borderDark}" stroke-dasharray="2,2"/>
<line x1="20" y1="120" x2="200" y2="120" stroke="${COLORS.borderDark}" stroke-dasharray="2,2"/>
<polygon points="20,128 50,108 80,118 110,88 140,98 170,68 200,58 200,150 20,150" fill="${COLORS.primary}" fill-opacity="0.22"/>
<polyline points="20,128 50,108 80,118 110,88 140,98 170,68 200,58" fill="none" stroke="${COLORS.primary}" stroke-width="2" stroke-linejoin="round"/>
<polyline points="20,138 50,128 80,132 110,118 140,122 170,108 200,103" fill="none" stroke="${COLORS.azure}" stroke-width="1.5" stroke-dasharray="3,2"/>
</g>
<g transform="translate(295, 122)">
<rect width="100" height="170" rx="4" fill="${COLORS.surfaceDk2}" stroke="${COLORS.borderDark}"/>
<rect x="10" y="12" width="55" height="6" rx="1" fill="${COLORS.textDark}"/>
${[
{ y: 28, c: COLORS.primary, w: 60 },
{ y: 50, c: COLORS.azure, w: 50 },
{ y: 72, c: COLORS.green, w: 56 },
{ y: 94, c: COLORS.yellow, w: 48 },
{ y: 116, c: COLORS.purple, w: 52 },
{ y: 138, c: COLORS.red, w: 56 }
].map((a) => `
<g transform="translate(10, ${a.y})">
<circle cx="9" cy="9" r="7" fill="${a.c}" fill-opacity="0.85"/>
<rect x="22" y="5" width="${a.w}" height="3" rx="1" fill="${COLORS.textDark}"/>
<rect x="22" y="11" width="${Math.round(a.w * 0.6)}" height="2.5" rx="1" fill="${COLORS.mutedDark}"/>
</g>
`).join('')}
</g>
</svg>`;
// Mobile mockup — phone frame containing scaled dashboard
const mobile = `<svg viewBox="0 0 400 300" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid slice" style="width:100%;height:100%">
<defs>
<linearGradient id="bgGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="${COLORS.primary}" stop-opacity="0.06"/>
<stop offset="100%" stop-color="${COLORS.azure}" stop-opacity="0.06"/>
</linearGradient>
</defs>
<rect width="400" height="300" fill="url(#bgGrad)"/>
<rect width="400" height="300" fill="${COLORS.bg}" fill-opacity="0.7"/>
<!-- Phone frame -->
<g transform="translate(140, 16)">
<rect width="120" height="268" rx="18" fill="#0f1623" stroke="#1a2332" stroke-width="2"/>
<rect x="6" y="6" width="108" height="256" rx="12" fill="${COLORS.bg}"/>
<!-- Notch -->
<rect x="50" y="6" width="20" height="4" rx="2" fill="#0f1623"/>
<!-- Mobile topbar -->
<rect x="6" y="14" width="108" height="20" fill="${COLORS.surface}"/>
<line x1="6" y1="34" x2="114" y2="34" stroke="${COLORS.border}"/>
<rect x="12" y="22" width="16" height="3" rx="1" fill="${COLORS.muted}"/>
<rect x="32" y="20" width="36" height="6" rx="1" fill="${COLORS.text}"/>
<circle cx="100" cy="24" r="5" fill="${COLORS.primary}"/>
<!-- Stat cards stacked -->
<g transform="translate(12, 42)">
<rect width="96" height="36" rx="3" fill="${COLORS.surface}" stroke="${COLORS.border}"/>
<circle cx="14" cy="18" r="8" fill="${COLORS.primary}" fill-opacity="0.14"/>
<rect x="8" y="14" width="12" height="8" rx="1" fill="${COLORS.primary}"/>
<rect x="28" y="11" width="36" height="3" rx="1" fill="${COLORS.muted}"/>
<rect x="28" y="19" width="24" height="7" rx="1" fill="${COLORS.text}"/>
<rect x="28" y="29" width="44" height="2.5" rx="1" fill="${COLORS.muted}"/>
</g>
<g transform="translate(12, 84)">
<rect width="96" height="36" rx="3" fill="${COLORS.surface}" stroke="${COLORS.border}"/>
<circle cx="14" cy="18" r="8" fill="${COLORS.azure}" fill-opacity="0.14"/>
<rect x="8" y="14" width="12" height="8" rx="1" fill="${COLORS.azure}"/>
<rect x="28" y="11" width="36" height="3" rx="1" fill="${COLORS.muted}"/>
<rect x="28" y="19" width="28" height="7" rx="1" fill="${COLORS.text}"/>
<rect x="28" y="29" width="44" height="2.5" rx="1" fill="${COLORS.muted}"/>
</g>
<!-- Chart card -->
<g transform="translate(12, 126)">
<rect width="96" height="80" rx="3" fill="${COLORS.surface}" stroke="${COLORS.border}"/>
<rect x="6" y="8" width="56" height="4" rx="1" fill="${COLORS.text}"/>
<rect x="6" y="16" width="40" height="2.5" rx="1" fill="${COLORS.muted}"/>
<polygon points="6,68 18,58 30,62 42,48 54,52 66,38 78,32 90,28 90,72 6,72" fill="${COLORS.primary}" fill-opacity="0.16"/>
<polyline points="6,68 18,58 30,62 42,48 54,52 66,38 78,32 90,28" fill="none" stroke="${COLORS.primary}" stroke-width="1.5" stroke-linejoin="round"/>
</g>
<!-- Activity rows -->
<g transform="translate(12, 212)">
${[COLORS.azure, COLORS.yellow, COLORS.purple].map((c, i) => `
<g transform="translate(0, ${i * 14})">
<circle cx="6" cy="6" r="4" fill="${c}"/>
<rect x="14" y="3" width="60" height="2.5" rx="1" fill="${COLORS.text}"/>
<rect x="14" y="8" width="40" height="2" rx="1" fill="${COLORS.muted}"/>
</g>
`).join('')}
</g>
<!-- Home indicator -->
<rect x="46" y="252" width="28" height="3" rx="1.5" fill="#0f1623" fill-opacity="0.4"/>
</g>
<!-- Decorative scattered dots -->
<g fill="${COLORS.primary}" fill-opacity="0.15">
<circle cx="40" cy="60" r="3"/>
<circle cx="80" cy="240" r="2.5"/>
<circle cx="320" cy="80" r="3"/>
<circle cx="360" cy="220" r="2"/>
<circle cx="50" cy="200" r="2"/>
</g>
</svg>`;
export const MOCKUPS = { overview, analytics, tables, dark, mobile };
// Smaller related-product thumbnails — abstract dashboard miniatures.
export const RELATED = {
bars: `<svg viewBox="0 0 200 150" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid slice" style="width:100%;height:100%">
<rect width="200" height="150" fill="${COLORS.surface}"/>
<rect width="200" height="22" fill="${COLORS.surfaceDark}"/>
<rect x="10" y="8" width="6" height="6" rx="1" fill="${COLORS.primary}"/>
<rect x="20" y="9" width="40" height="4" rx="1" fill="white" fill-opacity="0.9"/>
<circle cx="186" cy="11" r="4" fill="${COLORS.primary}"/>
<rect x="10" y="34" width="50" height="14" rx="2" fill="${COLORS.text}"/>
${[24, 38, 30, 56, 48, 70, 60, 80].map((h, i) => `
<rect x="${12 + i * 22}" y="${136 - h}" width="16" height="${h}" rx="2" fill="${[COLORS.primary, COLORS.azure, COLORS.yellow, COLORS.green, COLORS.purple, COLORS.red, COLORS.primary, COLORS.azure][i]}"/>
`).join('')}
</svg>`,
donut: `<svg viewBox="0 0 200 150" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid slice" style="width:100%;height:100%">
<rect width="200" height="150" fill="${COLORS.surface}"/>
<rect width="200" height="22" fill="${COLORS.surfaceDark}"/>
<rect x="10" y="8" width="6" height="6" rx="1" fill="${COLORS.primary}"/>
<rect x="20" y="9" width="40" height="4" rx="1" fill="white" fill-opacity="0.9"/>
<circle cx="186" cy="11" r="4" fill="${COLORS.primary}"/>
<circle cx="100" cy="86" r="42" fill="none" stroke="${COLORS.bg}" stroke-width="18"/>
<circle cx="100" cy="86" r="42" fill="none" stroke="${COLORS.primary}" stroke-width="18" stroke-dasharray="105 264" transform="rotate(-90 100 86)"/>
<circle cx="100" cy="86" r="42" fill="none" stroke="${COLORS.azure}" stroke-width="18" stroke-dasharray="55 264" stroke-dashoffset="-105" transform="rotate(-90 100 86)"/>
<circle cx="100" cy="86" r="42" fill="none" stroke="${COLORS.yellow}" stroke-width="18" stroke-dasharray="40 264" stroke-dashoffset="-160" transform="rotate(-90 100 86)"/>
<text x="100" y="84" font-size="14" font-weight="700" fill="${COLORS.text}" text-anchor="middle" font-family="Inter,sans-serif">8.4k</text>
<text x="100" y="96" font-size="6" fill="${COLORS.muted}" text-anchor="middle" font-family="Inter,sans-serif">devices</text>
</svg>`,
table: `<svg viewBox="0 0 200 150" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid slice" style="width:100%;height:100%">
<rect width="200" height="150" fill="${COLORS.surface}"/>
<rect width="200" height="22" fill="${COLORS.surfaceDark}"/>
<rect x="10" y="8" width="6" height="6" rx="1" fill="${COLORS.primary}"/>
<rect x="20" y="9" width="40" height="4" rx="1" fill="white" fill-opacity="0.9"/>
<circle cx="186" cy="11" r="4" fill="${COLORS.primary}"/>
<rect x="10" y="32" width="180" height="10" rx="2" fill="${COLORS.bg}"/>
${[0, 1, 2, 3, 4, 5].map((i) => `
<g transform="translate(10, ${48 + i * 16})">
<circle cx="6" cy="6" r="5" fill="${[COLORS.primary, COLORS.azure, COLORS.purple, COLORS.yellow, COLORS.red, COLORS.green][i]}"/>
<rect x="16" y="3" width="50" height="3" rx="1" fill="${COLORS.text}"/>
<rect x="16" y="9" width="36" height="2.5" rx="1" fill="${COLORS.muted}"/>
<rect x="120" y="2" width="38" height="9" rx="2" fill="${[COLORS.green, COLORS.blue, COLORS.green, COLORS.yellow, COLORS.red, COLORS.green][i]}" fill-opacity="0.18"/>
<rect x="170" y="5" width="14" height="3" rx="1" fill="${COLORS.muted}"/>
</g>
`).join('')}
</svg>`,
forms: `<svg viewBox="0 0 200 150" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid slice" style="width:100%;height:100%">
<rect width="200" height="150" fill="${COLORS.surface}"/>
<rect width="200" height="22" fill="${COLORS.surfaceDark}"/>
<rect x="10" y="8" width="6" height="6" rx="1" fill="${COLORS.primary}"/>
<rect x="20" y="9" width="40" height="4" rx="1" fill="white" fill-opacity="0.9"/>
<circle cx="186" cy="11" r="4" fill="${COLORS.primary}"/>
<rect x="10" y="32" width="60" height="6" rx="1" fill="${COLORS.text}"/>
<rect x="10" y="46" width="180" height="14" rx="2" fill="${COLORS.bg}" stroke="${COLORS.border}"/>
<rect x="10" y="66" width="40" height="3" rx="1" fill="${COLORS.muted}"/>
<rect x="10" y="74" width="180" height="14" rx="2" fill="${COLORS.bg}" stroke="${COLORS.border}"/>
<rect x="10" y="94" width="50" height="3" rx="1" fill="${COLORS.muted}"/>
<rect x="10" y="102" width="180" height="24" rx="2" fill="${COLORS.bg}" stroke="${COLORS.border}"/>
<rect x="10" y="132" width="60" height="12" rx="2" fill="${COLORS.primary}"/>
<text x="40" y="141" font-size="6" font-weight="600" fill="white" text-anchor="middle" font-family="Inter,sans-serif">Submit</text>
</svg>`
};