const fs = require('fs');
const path = require('path');
const data = require('./styles-complete.json');
const styles = Object.values(data);
// Categorize each style
const categoryMap = {
'Tech Minimal': 'minimalist', 'Minimalist Monochrome': 'minimalist', 'Swiss / International Typographic': 'minimalist',
'Aesthetic Harmony': 'minimalist', 'Minimalist Line Art': 'minimalist', 'Flat 2.0': 'minimalist',
'Corporate Clean': 'minimalist', 'Startup Vibrant': 'minimalist', 'Fintech Trust': 'minimalist',
'Health Medical': 'minimalist', 'Luxury Silver': 'minimalist', 'Minimalist Serif': 'minimalist',
'E-ink Paper': 'minimalist', 'Data Dashboard': 'minimalist',
'Mondrian / De Stijl': 'geometric', 'Bauhaus Modernism': 'geometric',
'Brutalist': 'bold', 'Memphis': 'bold', 'Industrial': 'bold', 'Abstract Memphis': 'bold',
'Brutalist Color': 'bold', 'Graffiti': 'bold', 'Kids Playful': 'bold',
'Cyberpunk': 'futuristic', 'Aurora Borealis': 'futuristic', 'Solarpunk': 'futuristic',
'Liquid Metal': 'futuristic', 'Holographic': 'futuristic', 'Cybernetic': 'futuristic',
'Alien': 'futuristic', 'Starship': 'futuristic', 'SciFi HUD': 'futuristic', 'The Ultimate': 'futuristic',
'Retro 80s (Synthwave)': 'retro', 'Retro 60s–70s (Print Grain)': 'retro', 'Retro Pixel UI': 'retro',
'Y2K Aesthetic': 'retro', 'Skeuomorphic': 'retro', 'Windows 95': 'retro',
'Steampunk': 'retro', 'Polaroid': 'retro', 'Postcard': 'retro', 'Terminal Retro': 'retro',
'Nature Organic': 'organic', 'Eco Green': 'organic',
'Luxury Editorial': 'editorial', 'Newspaper': 'editorial', 'Magazine': 'editorial',
'Japanese Minimal': 'zen',
'Material-ish': 'material', 'Glassmorphism': 'material', 'Neumorphism': 'material',
'Leather': 'material', 'Denim': 'material', 'Brushed Steel': 'material',
'Carbon Fiber': 'material', 'Knitwear': 'material', 'Frosted Glass': 'material',
'Acrylic Fluid': 'material', 'Material You': 'material',
'Terminal / Hacker': 'dark', 'Dark Mode Elegance': 'dark', 'Enterprise Blue': 'dark',
'Gamer RGB': 'dark', 'Luxury Gold': 'dark', 'OLED Black': 'dark', 'Code Editor': 'dark', 'Gothic': 'dark',
'Claymorphism': '3d', 'Low Poly': '3d', 'Isometric': '3d', 'Voxel': '3d',
'Brutalist 3D': '3d', 'Fluid 3D': '3d',
'Art Deco': 'artistic', 'Paper Craft': 'artistic', 'Doodle Sketch': 'artistic',
'Watercolor': 'artistic', 'Collage': 'artistic', 'Hand Drawn': 'artistic',
'Pop Art': 'artistic', 'Art Nouveau': 'artistic', 'Stained Glass': 'artistic',
'Impressionist': 'artistic', 'Cubist': 'artistic', 'Surrealist': 'artistic',
'Renaissance': 'artistic', 'Ukiyo-e': 'artistic', 'Comic Book': 'artistic',
'Blueprint': 'themed', 'Chalkboard': 'themed', 'Ticket Stub': 'themed',
'Oceanic': 'themed', 'Forest': 'themed', 'Desert': 'themed', 'Polar': 'themed',
'Jungle': 'themed', 'Volcanic': 'themed', 'Fantasy': 'themed', 'Wasteland': 'themed',
'Mesh Gradient': 'bold'
};
const categoryLabels = {
minimalist: '🔲 Minimalista', bold: '💥 Bold/Audaz', retro: '📻 Retro',
futuristic: '🚀 Futurista', organic: '🌿 Orgánico', geometric: '🔷 Geométrico',
artistic: '🎨 Artístico', material: '🧱 Material/Textura', dark: '🌑 Dark/Oscuro',
'3d': '🧊 3D', editorial: '📰 Editorial', themed: '🌍 Temático', zen: '☯️ Zen'
};
const stylesForHtml = styles.map(s => {
const cat = categoryMap[s.name] || 'other';
return {
id: s.id,
name: s.name,
category: cat,
categoryLabel: categoryLabels[cat] || cat,
palette: s.styleDNA.palette,
typo: s.styleDNA.typo,
radius: s.styleDNA.radius,
shadow: s.styleDNA.shadow,
motion: s.styleDNA.motion,
dos: s.dos.slice(0, 4),
donts: s.donts.slice(0, 3),
url: `https://styleprompt.zeabur.app/pro/${s.id}`,
previewUrl: `https://styleprompt.zeabur.app/styles/pro/${s.id}`
};
});
const html = `<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>StylePrompts Pro - 100 Estilos UI para WebForge</title>
<style>
:root{--bg:#0a0a0a;--card:#141414;--border:#222;--text:#fff;--muted:#888;--accent:#6366f1}
*{margin:0;padding:0;box-sizing:border-box}
body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;background:var(--bg);color:var(--text);padding:1.5rem;line-height:1.5}
.header{text-align:center;padding:2rem 0;border-bottom:1px solid var(--border);margin-bottom:2rem}
.header h1{font-size:2.2rem;background:linear-gradient(135deg,#6366f1,#a855f7,#ec4899);-webkit-background-clip:text;-webkit-text-fill-color:transparent;margin-bottom:.5rem}
.header p{color:var(--muted);font-size:.95rem}
.stats{display:flex;justify-content:center;gap:2rem;margin-top:1rem}
.stat-val{font-size:1.8rem;font-weight:700;color:var(--accent)}
.stat-lbl{font-size:.75rem;color:var(--muted)}
.filters{display:flex;flex-wrap:wrap;gap:.75rem;margin-bottom:1.5rem;padding:1rem;background:var(--card);border-radius:10px;border:1px solid var(--border)}
.filter-group{display:flex;flex-direction:column;gap:.3rem}
.filter-group label{font-size:.7rem;text-transform:uppercase;letter-spacing:.05em;color:var(--muted)}
select,input[type=text]{padding:.6rem .8rem;border:1px solid var(--border);border-radius:6px;background:var(--bg);color:var(--text);font-size:.85rem;min-width:180px}
.count{font-size:.85rem;color:var(--muted);margin-bottom:1rem}
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(380px,1fr));gap:1rem}
.card{background:var(--card);border:1px solid var(--border);border-radius:12px;overflow:hidden;transition:transform .15s,box-shadow .15s}
.card:hover{transform:translateY(-3px);box-shadow:0 12px 30px rgba(0,0,0,.4)}
.card-top{padding:1rem;display:flex;align-items:center;gap:.75rem;border-bottom:1px solid var(--border)}
.card-id{font-size:.7rem;font-weight:700;background:var(--accent);color:#fff;padding:.2rem .5rem;border-radius:5px;white-space:nowrap}
.card-cat{font-size:.65rem;padding:.15rem .4rem;border-radius:4px;background:rgba(99,102,241,.12);color:var(--accent);border:1px solid rgba(99,102,241,.25)}
.card-name{flex:1;font-size:1rem;font-weight:600}
.card-body{padding:1rem;font-size:.8rem}
.card-body h4{font-size:.7rem;text-transform:uppercase;color:var(--muted);letter-spacing:.04em;margin:0 0 .3rem}
.dna{color:var(--muted);margin-bottom:.75rem}
.dna span{display:block;margin-bottom:.2rem}
.dna strong{color:#ccc}
.lists{display:grid;grid-template-columns:1fr 1fr;gap:.5rem;margin-bottom:.75rem}
.do,.dont{font-size:.72rem;padding:.5rem;border-radius:6px}
.do{background:rgba(16,185,129,.08);border:1px solid rgba(16,185,129,.2)}
.dont{background:rgba(239,68,68,.08);border:1px solid rgba(239,68,68,.2)}
.do h5{color:#10b981;font-size:.65rem;margin-bottom:.3rem}
.dont h5{color:#ef4444;font-size:.65rem;margin-bottom:.3rem}
.do li,.dont li{list-style:none;margin-bottom:.15rem}
.card-footer{padding:.75rem 1rem;background:rgba(0,0,0,.3);display:flex;justify-content:space-between;align-items:center}
.btn{display:inline-flex;align-items:center;gap:.3rem;padding:.4rem .8rem;background:var(--accent);color:#fff;text-decoration:none;border-radius:6px;font-size:.8rem;font-weight:500;transition:background .15s}
.btn:hover{background:#818cf8}
.btn-ghost{background:transparent;border:1px solid var(--border);color:var(--muted)}
.btn-ghost:hover{border-color:var(--accent);color:var(--accent)}
@media(max-width:768px){body{padding:.75rem}.grid{grid-template-columns:1fr}.filters{flex-direction:column}select,input{width:100%}}
</style>
</head>
<body>
<div class="header">
<h1>🎨 StylePrompts Pro — Catálogo Completo</h1>
<p>100 estilos de diseño UI extraídos con prompts, tokens y especificaciones completas</p>
<p style="color:#6366f1;font-size:.8rem;margin-top:.5rem">Para WebForge · Fuente: styleprompt.zeabur.app</p>
<div class="stats">
<div><div class="stat-val">100</div><div class="stat-lbl">Estilos</div></div>
<div><div class="stat-val">13</div><div class="stat-lbl">Categorías</div></div>
<div><div class="stat-val">232KB</div><div class="stat-lbl">Datos extraídos</div></div>
</div>
</div>
<div class="filters">
<div class="filter-group"><label>Buscar</label><input type="text" id="search" placeholder="Nombre, estilo, color..."></div>
<div class="filter-group"><label>Categoría</label><select id="cat">
<option value="">Todas</option>
${Object.entries(categoryLabels).map(([k,v]) => `<option value="${k}">${v}</option>`).join('\n')}
</select></div>
</div>
<div class="count" id="count"></div>
<div class="grid" id="grid"></div>
<script>
const S=${JSON.stringify(stylesForHtml)};
function render(list){
document.getElementById('count').textContent='Mostrando '+list.length+' de 100 estilos';
document.getElementById('grid').innerHTML=list.map(s=>\`
<div class="card" data-cat="\${s.category}">
<div class="card-top">
<span class="card-id">\${s.id}</span>
<span class="card-name">\${s.name}</span>
<span class="card-cat">\${s.categoryLabel}</span>
</div>
<div class="card-body">
<h4>Style DNA</h4>
<div class="dna">
<span><strong>Paleta:</strong> \${s.palette}</span>
<span><strong>Tipografía:</strong> \${s.typo}</span>
<span><strong>Motion:</strong> \${s.motion}</span>
</div>
<div class="lists">
<div class="do"><h5>✅ DO</h5><ul>\${s.dos.map(d=>'<li>'+d+'</li>').join('')}</ul></div>
<div class="dont"><h5>❌ DON'T</h5><ul>\${s.donts.map(d=>'<li>'+d+'</li>').join('')}</ul></div>
</div>
</div>
<div class="card-footer">
<a href="\${s.url}" target="_blank" class="btn">Editor →</a>
<a href="\${s.previewUrl}" target="_blank" class="btn btn-ghost">Preview</a>
</div>
</div>\`).join('');
}
function filter(){
const q=document.getElementById('search').value.toLowerCase();
const c=document.getElementById('cat').value;
render(S.filter(s=>{
const mq=!q||s.name.toLowerCase().includes(q)||s.palette.toLowerCase().includes(q)||s.typo.toLowerCase().includes(q);
const mc=!c||s.category===c;
return mq&&mc;
}));
}
document.getElementById('search').addEventListener('input',filter);
document.getElementById('cat').addEventListener('change',filter);
render(S);
</script>
</body>
</html>`;
fs.writeFileSync(path.join(__dirname, 'index.html'), html);
console.log('HTML catalog generated: index.html (' + Math.round(html.length/1024) + 'KB)');