VibeCodingStudio commited on
Commit
07381d2
·
verified ·
1 Parent(s): 91ea6d8

Initial DeepSite commit

Browse files
Files changed (10) hide show
  1. README.md +9 -6
  2. api-keys.html +189 -0
  3. dashboard.html +263 -0
  4. generator.html +193 -0
  5. index.html +826 -19
  6. marketplace.html +169 -0
  7. models.html +183 -0
  8. playground.html +191 -0
  9. signin.html +180 -0
  10. workflows.html +171 -0
README.md CHANGED
@@ -1,10 +1,13 @@
1
  ---
2
- title: Deepsite Project 41uyr
3
- emoji: 🌍
4
- colorFrom: indigo
5
- colorTo: green
6
  sdk: static
7
- pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
1
  ---
2
+ title: DeepSite Project
3
+ colorFrom: green
4
+ colorTo: pink
 
5
  sdk: static
6
+ emoji: 🖥️
7
+ tags:
8
+ - deepsite-v4
9
  ---
10
 
11
+ # DeepSite Project
12
+
13
+ This project has been created with [DeepSite](https://deepsite.hf.co) AI Vibe Coding.
api-keys.html ADDED
@@ -0,0 +1,189 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>API Keys — NSFWStudio</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <script src="https://unpkg.com/lucide@latest"></script>
9
+ <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
10
+ <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
11
+ <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
12
+ <link rel="preconnect" href="https://fonts.googleapis.com">
13
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
14
+ <link href="https://fonts.googleapis.com/css2?family=Inter:opsz,wght@14..32,300..800&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
15
+ <script>
16
+ tailwind.config = { theme: { extend: { fontFamily: { sans: ['Inter','system-ui','sans-serif'], mono: ['JetBrains Mono','monospace'] }, colors: { bg: 'oklch(0.07 0.006 285)', surface: 'oklch(0.12 0.02 285)', 'surface-2': 'oklch(0.16 0.025 285)', 'surface-3': 'oklch(0.20 0.028 285)', fg: 'oklch(0.97 0.005 285)', muted: 'oklch(0.55 0.02 285)', primary: 'oklch(0.70 0.28 350)', 'primary-foreground': 'oklch(0.98 0.005 285)', secondary: 'oklch(0.75 0.15 215)', accent: 'oklch(0.80 0.18 85)', border: 'oklch(0.22 0.02 285)', ring: 'oklch(0.70 0.28 350)', destructive: 'oklch(0.55 0.22 25)', success: 'oklch(0.65 0.2 145)' } } } }
17
+ </script>
18
+ <style>
19
+ body { background-color: oklch(0.07 0.006 285); color: oklch(0.97 0.005 285); font-family: 'Inter', system-ui, sans-serif; -webkit-font-smoothing: antialiased; }
20
+ .glass { background: oklch(0.14 0.015 285 / 0.6); backdrop-filter: blur(24px) saturate(1.2); -webkit-backdrop-filter: blur(24px) saturate(1.2); border: 1px solid oklch(0.25 0.02 285 / 0.5); }
21
+ ::selection { background: oklch(0.70 0.28 350 / 0.3); }
22
+ body::after { content:''; position:fixed; inset:0; pointer-events:none; z-index:9999; opacity:0.025; background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); background-repeat:repeat; background-size:256px 256px; }
23
+ .no-scrollbar::-webkit-scrollbar { display: none; } .no-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }
24
+ .tabular-nums { font-variant-numeric: tabular-nums; }
25
+ </style>
26
+ </head>
27
+ <body class="antialiased">
28
+ <div id="root"></div>
29
+ <script type="text/babel">
30
+ const { useState } = React;
31
+ const Icon = ({ name, size = 20, className = "", strokeWidth = 2 }) => {
32
+ const ref = React.useRef(null);
33
+ React.useEffect(() => { if (ref.current) { const existing = ref.current.querySelector('svg'); if (existing) existing.remove(); const svg = lucide.createElement(lucide.icons[name]); if (svg) { svg.setAttribute('width',size); svg.setAttribute('height',size); svg.setAttribute('stroke-width',strokeWidth); ref.current.appendChild(svg); } } }, [name, size, className, strokeWidth]);
34
+ return <span ref={ref} className={`inline-flex items-center justify-center ${className}`} style={{ width: size, height: size }} />;
35
+ };
36
+
37
+ const navItems = [
38
+ { name: 'Dashboard', icon: 'layout-dashboard', href: 'dashboard.html' },
39
+ { name: 'Generator', icon: 'sparkles', href: 'generator.html' },
40
+ { name: 'Playground', icon: 'code', href: 'playground.html' },
41
+ { name: 'Models', icon: 'box', href: 'models.html' },
42
+ { name: 'Workflows', icon: 'workflow', href: 'workflows.html' },
43
+ { name: 'Marketplace', icon: 'shopping-bag', href: 'marketplace.html' },
44
+ { name: 'API Keys', icon: 'key', href: 'api-keys.html', active: true },
45
+ { divider: true },
46
+ { name: 'Profile', icon: 'user', href: 'profile.html' },
47
+ { name: 'Settings', icon: 'settings', href: 'settings.html' },
48
+ ];
49
+
50
+ const Sidebar = ({ isOpen, setIsOpen }) => (
51
+ <>
52
+ <div className={`fixed inset-0 z-40 lg:hidden transition-all ${isOpen ? 'opacity-100 pointer-events-auto' : 'opacity-0 pointer-events-none'}`}>
53
+ <div className="absolute inset-0 bg-black/60 backdrop-blur-sm" onClick={() => setIsOpen(false)} />
54
+ </div>
55
+ <aside className={`fixed top-0 left-0 bottom-0 z-50 w-64 bg-surface border-r border-border flex flex-col transition-transform duration-300 lg:translate-x-0 ${isOpen ? 'translate-x-0' : '-translate-x-full'}`}>
56
+ <div className="p-4 flex items-center gap-2.5 border-b border-border"><div className="w-8 h-8 rounded-lg bg-primary flex items-center justify-center"><Icon name="sparkles" size={16} className="text-primary-foreground" /></div><span className="text-lg font-bold tracking-tight">NSFW<span className="text-muted">Studio</span></span></div>
57
+ <nav className="flex-1 p-3 space-y-1 overflow-y-auto no-scrollbar">{navItems.map((item, i) => item.divider ? <div key={i} className="my-3 border-t border-border" /> : <a key={i} href={item.href} className={`flex items-center gap-3 px-3 py-2.5 rounded-xl text-sm font-medium transition-colors ${item.active ? 'bg-primary/10 text-primary border border-primary/20' : 'text-muted hover:text-fg hover:bg-surface-2 border border-transparent'}`}><Icon name={item.icon} size={18} />{item.name}</a>)}</nav>
58
+ <div className="p-4 border-t border-border"><a href="documentation.html" className="flex items-center gap-3 px-3 py-2.5 rounded-xl text-sm text-muted hover:text-fg hover:bg-surface-2 transition-colors"><Icon name="book-open" size={18} />Documentation</a><a href="api-reference.html" className="flex items-center gap-3 px-3 py-2.5 rounded-xl text-sm text-muted hover:text-fg hover:bg-surface-2 transition-colors"><Icon name="file-code" size={18} />API Reference</a></div>
59
+ </aside>
60
+ </>
61
+ );
62
+
63
+ const App = () => {
64
+ const [sidebarOpen, setSidebarOpen] = useState(false);
65
+ const [keys, setKeys] = useState([
66
+ { id: 1, name: 'Production Key', key: 'nfw_prod_sk_7f3a9b2c4d5e6f1a8b9c0d1e', created: 'Jan 15, 2025', lastUsed: '2 min ago', status: 'active' },
67
+ { id: 2, name: 'Development Key', key: 'nfw_dev_sk_2e4b6c8d0f1a3b5c7d9e1f2a', created: 'Feb 3, 2025', lastUsed: '3 days ago', status: 'active' },
68
+ { id: 3, name: 'Staging Environment', key: 'nfw_stg_sk_9a1b2c3d4e5f6a7b8c9d0e1f', created: 'Mar 22, 2025', lastUsed: 'Never', status: 'inactive' },
69
+ ]);
70
+ const [showKey, setShowKey] = useState({});
71
+ const [showCreate, setShowCreate] = useState(false);
72
+ const [newKeyName, setNewKeyName] = useState('');
73
+
74
+ const toggleShowKey = (id) => setShowKey(prev => ({ ...prev, [id]: !prev[id] }));
75
+
76
+ const maskKey = (key) => key.substring(0, 12) + '••••••••••••••••••••';
77
+
78
+ return (
79
+ <div className="min-h-screen bg-bg">
80
+ <Sidebar isOpen={sidebarOpen} setIsOpen={setSidebarOpen} />
81
+ <div className="lg:ml-64">
82
+ <header className="sticky top-0 z-30 glass border-b border-border">
83
+ <div className="flex items-center justify-between px-4 sm:px-6 h-16">
84
+ <div className="flex items-center gap-4">
85
+ <button onClick={() => setSidebarOpen(true)} className="lg:hidden p-2 rounded-lg hover:bg-surface-2 text-muted"><Icon name="menu" size={20} /></button>
86
+ <h1 className="text-xl font-bold">API Keys</h1>
87
+ </div>
88
+ <div className="flex items-center gap-3">
89
+ <a href="profile.html" className="w-9 h-9 rounded-lg overflow-hidden border border-border"><img src="http://static.photos/people/100x100/10" alt="" className="w-full h-full object-cover" /></a>
90
+ </div>
91
+ </div>
92
+ </header>
93
+
94
+ <main className="p-4 sm:p-6 lg:p-8 max-w-5xl">
95
+ {/* Danger Zone Notice */}
96
+ <div className="rounded-xl p-4 bg-destructive/10 border border-destructive/20 mb-6 flex items-start gap-3">
97
+ <Icon name="alert-triangle" size={20} className="text-destructive shrink-0 mt-0.5" />
98
+ <div>
99
+ <h3 className="font-semibold text-fg text-sm">Keep your API keys secure</h3>
100
+ <p className="text-xs text-muted mt-0.5">Never share your secret keys in public repositories, client-side code, or public forums. If a key is compromised, revoke it immediately.</p>
101
+ </div>
102
+ </div>
103
+
104
+ <div className="flex items-center justify-between mb-6">
105
+ <div>
106
+ <p className="text-sm text-muted">Manage your API keys for programmatic access.</p>
107
+ </div>
108
+ <button onClick={() => setShowCreate(true)} className="px-4 py-2.5 rounded-xl bg-primary text-primary-foreground font-semibold text-sm hover:brightness-110 transition-all flex items-center gap-2">
109
+ <Icon name="plus" size={16} />Create Key
110
+ </button>
111
+ </div>
112
+
113
+ {/* Create dialog */}
114
+ {showCreate && (
115
+ <div className="rounded-2xl p-6 bg-surface border border-border mb-6">
116
+ <h3 className="font-semibold mb-4">Create New API Key</h3>
117
+ <div className="space-y-4">
118
+ <div>
119
+ <label className="block text-sm font-medium text-fg mb-2">Key Name</label>
120
+ <input type="text" value={newKeyName} onChange={e => setNewKeyName(e.target.value)} placeholder="e.g., Production Key" className="w-full max-w-md px-4 py-2.5 rounded-xl bg-surface-2 border border-border text-sm text-fg placeholder:text-muted focus:outline-none focus:ring-2 focus:ring-primary/50" />
121
+ </div>
122
+ <div className="flex gap-3">
123
+ <button className="px-4 py-2.5 rounded-xl bg-primary text-primary-foreground font-semibold text-sm hover:brightness-110 transition-all" onClick={() => { if(newKeyName.trim()) { setKeys([...keys, { id: Date.now(), name: newKeyName, key: 'nfw_new_sk_' + Math.random().toString(36).substring(2, 18), created: 'Just now', lastUsed: 'Never', status: 'active' }]); setNewKeyName(''); setShowCreate(false); } }}>Create</button>
124
+ <button onClick={() => { setShowCreate(false); setNewKeyName(''); }} className="px-4 py-2.5 rounded-xl border border-border text-sm font-medium text-muted hover:text-fg hover:bg-surface-2 transition-colors">Cancel</button>
125
+ </div>
126
+ </div>
127
+ </div>
128
+ )}
129
+
130
+ {/* Keys list */}
131
+ <div className="space-y-4">
132
+ {keys.map(k => (
133
+ <div key={k.id} className="rounded-2xl p-5 bg-surface border border-border hover:border-surface-3 transition-colors">
134
+ <div className="flex flex-col sm:flex-row sm:items-center justify-between gap-3 mb-4">
135
+ <div className="flex items-center gap-3">
136
+ <div className="w-10 h-10 rounded-xl bg-primary/10 flex items-center justify-center"><Icon name="key" size={18} className="text-primary" /></div>
137
+ <div>
138
+ <div className="font-semibold text-fg">{k.name}</div>
139
+ <div className="text-xs text-muted">Created {k.created}</div>
140
+ </div>
141
+ </div>
142
+ <span className={`inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-semibold border ${k.status === 'active' ? 'bg-success/10 text-success border-success/20' : 'bg-muted/10 text-muted border-border'}`}>
143
+ <span className="w-1.5 h-1.5 rounded-full bg-current" />
144
+ {k.status === 'active' ? 'Active' : 'Inactive'}
145
+ </span>
146
+ </div>
147
+ <div className="flex items-center gap-2 p-3 rounded-xl bg-surface-2 border border-border mb-4">
148
+ <code className="flex-1 text-sm font-mono text-muted truncate">{showKey[k.id] ? k.key : maskKey(k.key)}</code>
149
+ <button onClick={() => toggleShowKey(k.id)} className="p-1.5 rounded-lg hover:bg-surface-3 text-muted hover:text-fg transition-colors shrink-0"><Icon name={showKey[k.id] ? 'eye-off' : 'eye'} size={16} /></button>
150
+ <button onClick={() => { navigator.clipboard?.writeText(k.key); }} className="p-1.5 rounded-lg hover:bg-surface-3 text-muted hover:text-fg transition-colors shrink-0"><Icon name="copy" size={16} /></button>
151
+ </div>
152
+ <div className="flex items-center justify-between text-xs text-muted">
153
+ <span>Last used: {k.lastUsed}</span>
154
+ <div className="flex items-center gap-2">
155
+ <button className="px-3 py-1.5 rounded-lg border border-border text-muted hover:text-fg hover:bg-surface-2 transition-colors">Regenerate</button>
156
+ <button className="px-3 py-1.5 rounded-lg border border-destructive/30 text-destructive hover:bg-destructive/10 transition-colors">Revoke</button>
157
+ </div>
158
+ </div>
159
+ </div>
160
+ ))}
161
+ </div>
162
+
163
+ {/* Usage Stats */}
164
+ <div className="mt-8 rounded-2xl p-6 bg-surface border border-border">
165
+ <h2 className="font-semibold mb-4">Usage This Month</h2>
166
+ <div className="grid grid-cols-2 sm:grid-cols-4 gap-4">
167
+ {[
168
+ { label: 'Total Requests', value: '1.2M', change: '+23%' },
169
+ { label: 'Tokens Used', value: '45.8M', change: '+18%' },
170
+ { label: 'Avg Latency', value: '142ms', change: '-5%' },
171
+ { label: 'Error Rate', value: '0.03%', change: '-12%' },
172
+ ].map((s, i) => (
173
+ <div key={i} className="p-4 rounded-xl bg-surface-2 border border-border">
174
+ <div className="text-xs text-muted mb-1">{s.label}</div>
175
+ <div className="text-xl font-bold text-fg tabular-nums">{s.value}</div>
176
+ <div className="text-xs text-success mt-1">{s.change}</div>
177
+ </div>
178
+ ))}
179
+ </div>
180
+ </div>
181
+ </main>
182
+ </div>
183
+ </div>
184
+ );
185
+ };
186
+ ReactDOM.createRoot(document.getElementById('root')).render(<App />);
187
+ </script>
188
+ </body>
189
+ </html>
dashboard.html ADDED
@@ -0,0 +1,263 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Dashboard — NSFWStudio</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <script src="https://unpkg.com/lucide@latest"></script>
9
+ <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
10
+ <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
11
+ <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
12
+ <link rel="preconnect" href="https://fonts.googleapis.com">
13
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
14
+ <link href="https://fonts.googleapis.com/css2?family=Inter:opsz,wght@14..32,300..800&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
15
+ <script>
16
+ tailwind.config = {
17
+ theme: {
18
+ extend: {
19
+ fontFamily: { sans: ['Inter','system-ui','sans-serif'], mono: ['JetBrains Mono','monospace'] },
20
+ colors: {
21
+ bg: 'oklch(0.07 0.006 285)', surface: 'oklch(0.12 0.02 285)', 'surface-2': 'oklch(0.16 0.025 285)', 'surface-3': 'oklch(0.20 0.028 285)',
22
+ fg: 'oklch(0.97 0.005 285)', muted: 'oklch(0.55 0.02 285)', primary: 'oklch(0.70 0.28 350)', 'primary-foreground': 'oklch(0.98 0.005 285)',
23
+ secondary: 'oklch(0.75 0.15 215)', accent: 'oklch(0.80 0.18 85)', border: 'oklch(0.22 0.02 285)', ring: 'oklch(0.70 0.28 350)',
24
+ destructive: 'oklch(0.55 0.22 25)', success: 'oklch(0.65 0.2 145)',
25
+ },
26
+ },
27
+ },
28
+ }
29
+ </script>
30
+ <style>
31
+ body { background-color: oklch(0.07 0.006 285); color: oklch(0.97 0.005 285); font-family: 'Inter', system-ui, sans-serif; -webkit-font-smoothing: antialiased; }
32
+ .glass { background: oklch(0.14 0.015 285 / 0.6); backdrop-filter: blur(24px) saturate(1.2); -webkit-backdrop-filter: blur(24px) saturate(1.2); border: 1px solid oklch(0.25 0.02 285 / 0.5); }
33
+ .gradient-text { background: linear-gradient(135deg, oklch(0.70 0.28 350), oklch(0.75 0.15 215)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; }
34
+ ::selection { background: oklch(0.70 0.28 350 / 0.3); color: white; }
35
+ body::after { content:''; position:fixed; inset:0; pointer-events:none; z-index:9999; opacity:0.025; background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); background-repeat:repeat; background-size:256px 256px; }
36
+ .no-scrollbar::-webkit-scrollbar { display: none; } .no-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }
37
+ .tabular-nums { font-variant-numeric: tabular-nums; }
38
+ </style>
39
+ </head>
40
+ <body class="antialiased">
41
+ <div id="root"></div>
42
+ <script type="text/babel">
43
+ const { useState } = React;
44
+
45
+ const Icon = ({ name, size = 20, className = "", strokeWidth = 2 }) => {
46
+ const ref = React.useRef(null);
47
+ React.useEffect(() => { if (ref.current) { const existing = ref.current.querySelector('svg'); if (existing) existing.remove(); const svg = lucide.createElement(lucide.icons[name]); if (svg) { svg.setAttribute('width',size); svg.setAttribute('height',size); svg.setAttribute('stroke-width',strokeWidth); ref.current.appendChild(svg); } } }, [name, size, className, strokeWidth]);
48
+ return <span ref={ref} className={`inline-flex items-center justify-center ${className}`} style={{ width: size, height: size }} />;
49
+ };
50
+
51
+ const navItems = [
52
+ { name: 'Dashboard', icon: 'layout-dashboard', href: 'dashboard.html', active: true },
53
+ { name: 'Generator', icon: 'sparkles', href: 'generator.html' },
54
+ { name: 'Playground', icon: 'code', href: 'playground.html' },
55
+ { name: 'Models', icon: 'box', href: 'models.html' },
56
+ { name: 'Workflows', icon: 'workflow', href: 'workflows.html' },
57
+ { name: 'Marketplace', icon: 'shopping-bag', href: 'marketplace.html' },
58
+ { name: 'API Keys', icon: 'key', href: 'api-keys.html' },
59
+ { divider: true },
60
+ { name: 'Profile', icon: 'user', href: 'profile.html' },
61
+ { name: 'Settings', icon: 'settings', href: 'settings.html' },
62
+ ];
63
+
64
+ const Sidebar = ({ isOpen, setIsOpen }) => (
65
+ <>
66
+ {/* Mobile overlay */}
67
+ <div className={`fixed inset-0 z-40 lg:hidden transition-all ${isOpen ? 'opacity-100 pointer-events-auto' : 'opacity-0 pointer-events-none'}`}>
68
+ <div className="absolute inset-0 bg-black/60 backdrop-blur-sm" onClick={() => setIsOpen(false)} />
69
+ </div>
70
+ <aside className={`fixed top-0 left-0 bottom-0 z-50 w-64 bg-surface border-r border-border flex flex-col transition-transform duration-300 lg:translate-x-0 ${isOpen ? 'translate-x-0' : '-translate-x-full'}`}>
71
+ <div className="p-4 flex items-center gap-2.5 border-b border-border">
72
+ <div className="w-8 h-8 rounded-lg bg-primary flex items-center justify-center"><Icon name="sparkles" size={16} className="text-primary-foreground" /></div>
73
+ <span className="text-lg font-bold tracking-tight">NSFW<span className="text-muted">Studio</span></span>
74
+ </div>
75
+ <nav className="flex-1 p-3 space-y-1 overflow-y-auto no-scrollbar">
76
+ {navItems.map((item, i) => item.divider ? <div key={i} className="my-3 border-t border-border" /> : (
77
+ <a key={i} href={item.href} className={`flex items-center gap-3 px-3 py-2.5 rounded-xl text-sm font-medium transition-colors ${item.active ? 'bg-primary/10 text-primary border border-primary/20' : 'text-muted hover:text-fg hover:bg-surface-2 border border-transparent'}`}>
78
+ <Icon name={item.icon} size={18} />{item.name}
79
+ </a>
80
+ ))}
81
+ </nav>
82
+ <div className="p-4 border-t border-border">
83
+ <a href="documentation.html" className="flex items-center gap-3 px-3 py-2.5 rounded-xl text-sm text-muted hover:text-fg hover:bg-surface-2 transition-colors">
84
+ <Icon name="book-open" size={18} />Documentation
85
+ </a>
86
+ <a href="api-reference.html" className="flex items-center gap-3 px-3 py-2.5 rounded-xl text-sm text-muted hover:text-fg hover:bg-surface-2 transition-colors">
87
+ <Icon name="file-code" size={18} />API Reference
88
+ </a>
89
+ </div>
90
+ </aside>
91
+ </>
92
+ );
93
+
94
+ const App = () => {
95
+ const [sidebarOpen, setSidebarOpen] = useState(false);
96
+
97
+ const stats = [
98
+ { label: 'Generations', value: '12,847', change: '+14.2%', icon: 'image', color: 'text-primary', bg: 'bg-primary/10' },
99
+ { label: 'Revenue', value: '$8,492', change: '+23.1%', icon: 'dollar-sign', color: 'text-success', bg: 'bg-success/10' },
100
+ { label: 'Followers', value: '2,341', change: '+8.7%', icon: 'users', color: 'text-secondary', bg: 'bg-secondary/10' },
101
+ { label: 'API Calls', value: '284K', change: '+31.5%', icon: 'activity', color: 'text-accent', bg: 'bg-accent/10' },
102
+ ];
103
+
104
+ const recentGens = [
105
+ { title: 'Neon Cityscape', model: 'DreamVision XL', time: '2m ago', status: 'completed', img: 'http://static.photos/cyberpunk/200x200/5' },
106
+ { title: 'Cyberpunk Girl', model: 'SDXL 1.0', time: '5m ago', status: 'completed', img: 'http://static.photos/people/200x200/6' },
107
+ { title: 'Dark Forest', model: 'MidJourney v6', time: '8m ago', status: 'completed', img: 'http://static.photos/nature/200x200/7' },
108
+ { title: 'Sci-Fi Portrait', model: 'DreamVision XL', time: '12m ago', status: 'completed', img: 'http://static.photos/technology/200x200/8' },
109
+ { title: 'Anime Warrior', model: 'Anime Diffusion', time: '15m ago', status: 'processing', img: 'http://static.photos/people/200x200/9' },
110
+ ];
111
+
112
+ const activity = [
113
+ { text: 'New follower: @dark_pixel', time: '1m ago', icon: 'user-plus', color: 'text-secondary' },
114
+ { text: 'Your model earned $49.00', time: '3m ago', icon: 'dollar-sign', color: 'text-success' },
115
+ { text: 'Workflow "Auto Tag" completed', time: '7m ago', icon: 'check-circle', color: 'text-primary' },
116
+ { text: 'Comment on "Neon Cityscape"', time: '10m ago', icon: 'message-circle', color: 'text-accent' },
117
+ { text: 'API key rotation reminder', time: '1h ago', icon: 'key', color: 'text-muted' },
118
+ ];
119
+
120
+ const topModels = [
121
+ { name: 'DreamVision XL', runs: '45.2K', revenue: '$2,340', trend: '+12%' },
122
+ { name: 'CyberPunk v3', runs: '28.1K', revenue: '$1,890', trend: '+8%' },
123
+ { name: 'Anime Diffusion', runs: '19.7K', revenue: '$1,230', trend: '+21%' },
124
+ ];
125
+
126
+ return (
127
+ <div className="min-h-screen bg-bg">
128
+ <Sidebar isOpen={sidebarOpen} setIsOpen={setSidebarOpen} />
129
+ <div className="lg:ml-64">
130
+ {/* Top bar */}
131
+ <header className="sticky top-0 z-30 glass border-b border-border">
132
+ <div className="flex items-center justify-between px-4 sm:px-6 h-16">
133
+ <div className="flex items-center gap-4">
134
+ <button onClick={() => setSidebarOpen(true)} className="lg:hidden p-2 rounded-lg hover:bg-surface-2 text-muted"><Icon name="menu" size={20} /></button>
135
+ <div className="hidden sm:flex items-center gap-2 px-4 py-2 rounded-xl bg-surface-2 border border-border text-muted text-sm w-72">
136
+ <Icon name="search" size={16} />
137
+ <span>Search anything...</span>
138
+ </div>
139
+ </div>
140
+ <div className="flex items-center gap-3">
141
+ <button className="p-2 rounded-lg hover:bg-surface-2 text-muted hover:text-fg transition-colors relative">
142
+ <Icon name="bell" size={20} />
143
+ <span className="absolute top-1.5 right-1.5 w-2 h-2 rounded-full bg-primary" />
144
+ </button>
145
+ <a href="generator.html" className="px-4 py-2 rounded-lg bg-primary text-primary-foreground text-sm font-semibold hover:brightness-110 transition-all">+ New</a>
146
+ <a href="profile.html" className="w-9 h-9 rounded-lg overflow-hidden border border-border">
147
+ <img src="http://static.photos/people/100x100/10" alt="" className="w-full h-full object-cover" />
148
+ </a>
149
+ </div>
150
+ </div>
151
+ </header>
152
+
153
+ <main className="p-4 sm:p-6 lg:p-8">
154
+ <div className="mb-8">
155
+ <h1 className="text-2xl sm:text-3xl font-bold mb-1">Welcome back, <span className="gradient-text">Neon</span></h1>
156
+ <p className="text-muted">Here's what's happening with your creations today.</p>
157
+ </div>
158
+
159
+ {/* Stats */}
160
+ <div className="grid grid-cols-2 lg:grid-cols-4 gap-4 mb-8">
161
+ {stats.map((s, i) => (
162
+ <div key={i} className="rounded-2xl p-5 bg-surface border border-border hover:border-surface-3 transition-colors">
163
+ <div className="flex items-center justify-between mb-3">
164
+ <div className={`w-10 h-10 rounded-xl ${s.bg} flex items-center justify-center`}><Icon name={s.icon} size={18} className={s.color} /></div>
165
+ <span className="text-xs font-medium text-success bg-success/10 px-2 py-0.5 rounded-full">{s.change}</span>
166
+ </div>
167
+ <div className="text-2xl font-bold text-fg tabular-nums">{s.value}</div>
168
+ <div className="text-xs text-muted mt-1">{s.label}</div>
169
+ </div>
170
+ ))}
171
+ </div>
172
+
173
+ <div className="grid lg:grid-cols-3 gap-6">
174
+ {/* Recent Generations */}
175
+ <div className="lg:col-span-2 rounded-2xl p-6 bg-surface border border-border">
176
+ <div className="flex items-center justify-between mb-5">
177
+ <h2 className="text-lg font-semibold">Recent Generations</h2>
178
+ <a href="generator.html" className="text-sm text-primary hover:underline flex items-center gap-1">View all <Icon name="arrow-right" size={14} /></a>
179
+ </div>
180
+ <div className="space-y-3">
181
+ {recentGens.map((g, i) => (
182
+ <div key={i} className="flex items-center gap-4 p-3 rounded-xl hover:bg-surface-2/50 transition-colors cursor-pointer group">
183
+ <img src={g.img} alt="" className="w-12 h-12 rounded-xl object-cover border border-border" />
184
+ <div className="flex-1 min-w-0">
185
+ <div className="text-sm font-medium text-fg truncate">{g.title}</div>
186
+ <div className="text-xs text-muted">{g.model} · {g.time}</div>
187
+ </div>
188
+ <span className={`px-2.5 py-1 rounded-full text-xs font-semibold ${g.status === 'completed' ? 'bg-success/10 text-success border border-success/20' : 'bg-primary/10 text-primary border border-primary/20'}`}>
189
+ {g.status}
190
+ </span>
191
+ </div>
192
+ ))}
193
+ </div>
194
+ </div>
195
+
196
+ {/* Right column */}
197
+ <div className="space-y-6">
198
+ {/* Activity */}
199
+ <div className="rounded-2xl p-6 bg-surface border border-border">
200
+ <h2 className="text-lg font-semibold mb-4">Activity</h2>
201
+ <div className="space-y-4">
202
+ {activity.map((a, i) => (
203
+ <div key={i} className="flex items-start gap-3">
204
+ <div className={`mt-0.5 ${a.color}`}><Icon name={a.icon} size={16} /></div>
205
+ <div className="flex-1 min-w-0">
206
+ <div className="text-sm text-fg/90">{a.text}</div>
207
+ <div className="text-xs text-muted mt-0.5">{a.time}</div>
208
+ </div>
209
+ </div>
210
+ ))}
211
+ </div>
212
+ </div>
213
+
214
+ {/* Top Models */}
215
+ <div className="rounded-2xl p-6 bg-surface border border-border">
216
+ <div className="flex items-center justify-between mb-4">
217
+ <h2 className="text-lg font-semibold">Top Models</h2>
218
+ <a href="models.html" className="text-xs text-primary hover:underline">See all</a>
219
+ </div>
220
+ <div className="space-y-3">
221
+ {topModels.map((m, i) => (
222
+ <div key={i} className="flex items-center justify-between p-3 rounded-xl hover:bg-surface-2/50 transition-colors cursor-pointer">
223
+ <div className="flex items-center gap-3">
224
+ <span className="w-6 h-6 rounded-full bg-surface-2 flex items-center justify-center text-xs font-bold text-muted">{i+1}</span>
225
+ <div>
226
+ <div className="text-sm font-medium text-fg">{m.name}</div>
227
+ <div className="text-xs text-muted">{m.runs} runs</div>
228
+ </div>
229
+ </div>
230
+ <div className="text-right">
231
+ <div className="text-sm font-semibold text-fg">{m.revenue}</div>
232
+ <div className="text-xs text-success">{m.trend}</div>
233
+ </div>
234
+ </div>
235
+ ))}
236
+ </div>
237
+ </div>
238
+ </div>
239
+ </div>
240
+
241
+ {/* Quick Actions */}
242
+ <div className="mt-8 grid grid-cols-2 sm:grid-cols-4 gap-3">
243
+ {[
244
+ { label: 'Generate Image', icon: 'image', color: 'text-primary', bg: 'bg-primary/10', href: 'generator.html' },
245
+ { label: 'Create Workflow', icon: 'workflow', color: 'text-secondary', bg: 'bg-secondary/10', href: 'workflows.html' },
246
+ { label: 'Train Model', icon: 'box', color: 'text-success', bg: 'bg-success/10', href: 'models.html' },
247
+ { label: 'Explore Marketplace', icon: 'shopping-bag', color: 'text-accent', bg: 'bg-accent/10', href: 'marketplace.html' },
248
+ ].map((a, i) => (
249
+ <a key={i} href={a.href} className="group flex flex-col items-center gap-3 p-5 rounded-2xl bg-surface border border-border hover:border-surface-3 transition-all hover:-translate-y-0.5">
250
+ <div className={`w-12 h-12 rounded-xl ${a.bg} flex items-center justify-center group-hover:scale-110 transition-transform`}><Icon name={a.icon} size={22} className={a.color} /></div>
251
+ <span className="text-sm font-medium text-fg">{a.label}</span>
252
+ </a>
253
+ ))}
254
+ </div>
255
+ </main>
256
+ </div>
257
+ </div>
258
+ );
259
+ };
260
+ ReactDOM.createRoot(document.getElementById('root')).render(<App />);
261
+ </script>
262
+ </body>
263
+ </html>
generator.html ADDED
@@ -0,0 +1,193 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Generator — NSFWStudio</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <script src="https://unpkg.com/lucide@latest"></script>
9
+ <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
10
+ <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
11
+ <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
12
+ <link rel="preconnect" href="https://fonts.googleapis.com">
13
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
14
+ <link href="https://fonts.googleapis.com/css2?family=Inter:opsz,wght@14..32,300..800&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
15
+ <script>
16
+ tailwind.config = { theme: { extend: { fontFamily: { sans: ['Inter','system-ui','sans-serif'], mono: ['JetBrains Mono','monospace'] }, colors: { bg: 'oklch(0.07 0.006 285)', surface: 'oklch(0.12 0.02 285)', 'surface-2': 'oklch(0.16 0.025 285)', 'surface-3': 'oklch(0.20 0.028 285)', fg: 'oklch(0.97 0.005 285)', muted: 'oklch(0.55 0.02 285)', primary: 'oklch(0.70 0.28 350)', 'primary-foreground': 'oklch(0.98 0.005 285)', secondary: 'oklch(0.75 0.15 215)', accent: 'oklch(0.80 0.18 85)', border: 'oklch(0.22 0.02 285)', ring: 'oklch(0.70 0.28 350)', destructive: 'oklch(0.55 0.22 25)', success: 'oklch(0.65 0.2 145)' } } } }
17
+ </script>
18
+ <style>
19
+ body { background-color: oklch(0.07 0.006 285); color: oklch(0.97 0.005 285); font-family: 'Inter', system-ui, sans-serif; -webkit-font-smoothing: antialiased; }
20
+ .glass { background: oklch(0.14 0.015 285 / 0.6); backdrop-filter: blur(24px) saturate(1.2); -webkit-backdrop-filter: blur(24px) saturate(1.2); border: 1px solid oklch(0.25 0.02 285 / 0.5); }
21
+ ::selection { background: oklch(0.70 0.28 350 / 0.3); }
22
+ body::after { content:''; position:fixed; inset:0; pointer-events:none; z-index:9999; opacity:0.025; background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); background-repeat:repeat; background-size:256px 256px; }
23
+ .no-scrollbar::-webkit-scrollbar { display: none; } .no-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }
24
+ </style>
25
+ </head>
26
+ <body class="antialiased">
27
+ <div id="root"></div>
28
+ <script type="text/babel">
29
+ const { useState } = React;
30
+ const Icon = ({ name, size = 20, className = "", strokeWidth = 2 }) => {
31
+ const ref = React.useRef(null);
32
+ React.useEffect(() => { if (ref.current) { const existing = ref.current.querySelector('svg'); if (existing) existing.remove(); const svg = lucide.createElement(lucide.icons[name]); if (svg) { svg.setAttribute('width',size); svg.setAttribute('height',size); svg.setAttribute('stroke-width',strokeWidth); ref.current.appendChild(svg); } } }, [name, size, className, strokeWidth]);
33
+ return <span ref={ref} className={`inline-flex items-center justify-center ${className}`} style={{ width: size, height: size }} />;
34
+ };
35
+
36
+ const navItems = [
37
+ { name: 'Dashboard', icon: 'layout-dashboard', href: 'dashboard.html' },
38
+ { name: 'Generator', icon: 'sparkles', href: 'generator.html', active: true },
39
+ { name: 'Playground', icon: 'code', href: 'playground.html' },
40
+ { name: 'Models', icon: 'box', href: 'models.html' },
41
+ { name: 'Workflows', icon: 'workflow', href: 'workflows.html' },
42
+ { name: 'Marketplace', icon: 'shopping-bag', href: 'marketplace.html' },
43
+ { name: 'API Keys', icon: 'key', href: 'api-keys.html' },
44
+ { divider: true },
45
+ { name: 'Profile', icon: 'user', href: 'profile.html' },
46
+ { name: 'Settings', icon: 'settings', href: 'settings.html' },
47
+ ];
48
+
49
+ const Sidebar = ({ isOpen, setIsOpen }) => (
50
+ <>
51
+ <div className={`fixed inset-0 z-40 lg:hidden transition-all ${isOpen ? 'opacity-100 pointer-events-auto' : 'opacity-0 pointer-events-none'}`}>
52
+ <div className="absolute inset-0 bg-black/60 backdrop-blur-sm" onClick={() => setIsOpen(false)} />
53
+ </div>
54
+ <aside className={`fixed top-0 left-0 bottom-0 z-50 w-64 bg-surface border-r border-border flex flex-col transition-transform duration-300 lg:translate-x-0 ${isOpen ? 'translate-x-0' : '-translate-x-full'}`}>
55
+ <div className="p-4 flex items-center gap-2.5 border-b border-border"><div className="w-8 h-8 rounded-lg bg-primary flex items-center justify-center"><Icon name="sparkles" size={16} className="text-primary-foreground" /></div><span className="text-lg font-bold tracking-tight">NSFW<span className="text-muted">Studio</span></span></div>
56
+ <nav className="flex-1 p-3 space-y-1 overflow-y-auto no-scrollbar">{navItems.map((item, i) => item.divider ? <div key={i} className="my-3 border-t border-border" /> : <a key={i} href={item.href} className={`flex items-center gap-3 px-3 py-2.5 rounded-xl text-sm font-medium transition-colors ${item.active ? 'bg-primary/10 text-primary border border-primary/20' : 'text-muted hover:text-fg hover:bg-surface-2 border border-transparent'}`}><Icon name={item.icon} size={18} />{item.name}</a>)}</nav>
57
+ <div className="p-4 border-t border-border"><a href="documentation.html" className="flex items-center gap-3 px-3 py-2.5 rounded-xl text-sm text-muted hover:text-fg hover:bg-surface-2 transition-colors"><Icon name="book-open" size={18} />Documentation</a><a href="api-reference.html" className="flex items-center gap-3 px-3 py-2.5 rounded-xl text-sm text-muted hover:text-fg hover:bg-surface-2 transition-colors"><Icon name="file-code" size={18} />API Reference</a></div>
58
+ </aside>
59
+ </>
60
+ );
61
+
62
+ const App = () => {
63
+ const [sidebarOpen, setSidebarOpen] = useState(false);
64
+ const [model, setModel] = useState('DreamVision XL');
65
+ const [prompt, setPrompt] = useState('');
66
+ const [negativePrompt, setNegativePrompt] = useState('');
67
+ const [isGenerating, setIsGenerating] = useState(false);
68
+ const [generated, setGenerated] = useState(false);
69
+ const [aspectRatio, setAspectRatio] = useState('1:1');
70
+
71
+ const handleGenerate = () => { if (!prompt.trim()) return; setIsGenerating(true); setGenerated(false); setTimeout(() => { setIsGenerating(false); setGenerated(true); }, 2500); };
72
+
73
+ return (
74
+ <div className="min-h-screen bg-bg">
75
+ <Sidebar isOpen={sidebarOpen} setIsOpen={setSidebarOpen} />
76
+ <div className="lg:ml-64">
77
+ <header className="sticky top-0 z-30 glass border-b border-border">
78
+ <div className="flex items-center justify-between px-4 sm:px-6 h-16">
79
+ <div className="flex items-center gap-4">
80
+ <button onClick={() => setSidebarOpen(true)} className="lg:hidden p-2 rounded-lg hover:bg-surface-2 text-muted"><Icon name="menu" size={20} /></button>
81
+ <h1 className="text-xl font-bold">Generator</h1>
82
+ </div>
83
+ <div className="flex items-center gap-3">
84
+ <button className="p-2 rounded-lg hover:bg-surface-2 text-muted relative"><Icon name="bell" size={20} /><span className="absolute top-1.5 right-1.5 w-2 h-2 rounded-full bg-primary" /></button>
85
+ <a href="profile.html" className="w-9 h-9 rounded-lg overflow-hidden border border-border"><img src="http://static.photos/people/100x100/10" alt="" className="w-full h-full object-cover" /></a>
86
+ </div>
87
+ </div>
88
+ </header>
89
+
90
+ <div className="flex flex-col lg:flex-row h-[calc(100vh-64px)]">
91
+ {/* Settings Panel */}
92
+ <div className="w-full lg:w-80 border-b lg:border-b-0 lg:border-r border-border overflow-y-auto no-scrollbar p-4 space-y-5">
93
+ <div>
94
+ <label className="text-xs font-medium text-muted uppercase tracking-wider mb-2 block">Model</label>
95
+ <select value={model} onChange={e => setModel(e.target.value)} className="w-full px-3 py-2.5 rounded-xl bg-surface-2 border border-border text-sm text-fg focus:outline-none focus:ring-2 focus:ring-primary/50">
96
+ {['DreamVision XL', 'SDXL 1.0', 'CyberPunk v3', 'Anime Diffusion'].map(m => <option key={m}>{m}</option>)}
97
+ </select>
98
+ </div>
99
+ <div>
100
+ <label className="text-xs font-medium text-muted uppercase tracking-wider mb-2 block">Aspect Ratio</label>
101
+ <div className="grid grid-cols-4 gap-2">
102
+ {['1:1', '4:3', '16:9', '9:16'].map(r => (
103
+ <button key={r} onClick={() => setAspectRatio(r)} className={`py-2 rounded-lg text-xs font-medium transition-colors ${aspectRatio === r ? 'bg-primary text-primary-foreground' : 'bg-surface-2 border border-border text-muted hover:text-fg'}`}>{r}</button>
104
+ ))}
105
+ </div>
106
+ </div>
107
+ {[
108
+ { label: 'Steps', val: '30', desc: 'Number of denoising steps' },
109
+ ].map(p => (
110
+ <div key={p.label}>
111
+ <label className="text-xs font-medium text-muted uppercase tracking-wider mb-2 block">{p.label}: {p.val}</label>
112
+ <input type="range" min="1" max="50" defaultValue="30" className="w-full accent-primary" />
113
+ <p className="text-xs text-muted mt-1">{p.desc}</p>
114
+ </div>
115
+ ))}
116
+ <div>
117
+ <label className="text-xs font-medium text-muted uppercase tracking-wider mb-2 block">Guidance Scale: 7.5</label>
118
+ <input type="range" min="1" max="20" defaultValue="7.5" step="0.5" className="w-full accent-primary" />
119
+ </div>
120
+ <div>
121
+ <label className="text-xs font-medium text-muted uppercase tracking-wider mb-2 block">Seed</label>
122
+ <div className="flex gap-2">
123
+ <input type="text" defaultValue="Random" className="flex-1 px-3 py-2.5 rounded-xl bg-surface-2 border border-border text-sm text-fg focus:outline-none focus:ring-2 focus:ring-primary/50" />
124
+ <button className="px-3 rounded-xl bg-surface-2 border border-border text-muted hover:text-fg"><Icon name="shuffle" size={16} /></button>
125
+ </div>
126
+ </div>
127
+ <div className="pt-2 border-t border-border">
128
+ <h3 className="text-xs font-medium text-muted uppercase tracking-wider mb-2">Quick Styles</h3>
129
+ <div className="flex flex-wrap gap-2">
130
+ {['Photorealistic', 'Anime', 'Fantasy', 'Cinematic', 'Oil Painting', '3D Render'].map(s => (
131
+ <button key={s} className="px-3 py-1.5 rounded-lg bg-surface-2 border border-border text-xs text-muted hover:text-fg hover:border-surface-3 transition-colors">{s}</button>
132
+ ))}
133
+ </div>
134
+ </div>
135
+ </div>
136
+
137
+ {/* Main Canvas */}
138
+ <div className="flex-1 flex flex-col">
139
+ <div className="flex-1 flex items-center justify-center p-4 sm:p-8">
140
+ {isGenerating ? (
141
+ <div className="text-center">
142
+ <div className="w-16 h-16 border-4 border-primary border-t-transparent rounded-full animate-spin mx-auto mb-4" />
143
+ <p className="text-fg font-medium">Generating your masterpiece...</p>
144
+ <p className="text-sm text-muted mt-1">This usually takes 10-30 seconds</p>
145
+ </div>
146
+ ) : generated ? (
147
+ <div className="max-w-2xl w-full">
148
+ <div className="rounded-2xl overflow-hidden border border-border shadow-2xl shadow-black/40">
149
+ <img src={`http://static.photos/cyberpunk/1024x576/1`} alt="Generated" className="w-full" />
150
+ </div>
151
+ <div className="flex items-center justify-between mt-4">
152
+ <div className="flex gap-2">
153
+ {['Download', 'Upscale', 'Variations', 'Add to Collection'].map(a => (
154
+ <button key={a} className="px-4 py-2 rounded-lg bg-surface border border-border text-sm text-fg hover:bg-surface-2 transition-colors flex items-center gap-1.5"><Icon name={a === 'Download' ? 'download' : a === 'Upscale' ? 'maximize' : a === 'Variations' ? 'copy' : 'bookmark'} size={14} />{a}</button>
155
+ ))}
156
+ </div>
157
+ <span className="text-xs text-muted">DreamVision XL · 1024×1024 · 30 steps</span>
158
+ </div>
159
+ </div>
160
+ ) : (
161
+ <div className="text-center max-w-md">
162
+ <div className="w-20 h-20 rounded-2xl bg-surface-2 flex items-center justify-center mx-auto mb-6"><Icon name="sparkles" size={32} className="text-muted" /></div>
163
+ <h2 className="text-xl font-semibold mb-2">Ready to Create</h2>
164
+ <p className="text-muted text-sm">Enter a prompt below and click Generate to bring your vision to life.</p>
165
+ </div>
166
+ )}
167
+ </div>
168
+
169
+ {/* Prompt Input */}
170
+ <div className="p-4 border-t border-border">
171
+ <div className="max-w-4xl mx-auto space-y-3">
172
+ <textarea value={negativePrompt} onChange={e => setNegativePrompt(e.target.value)} placeholder="Negative prompt (optional)..." className="w-full px-4 py-2.5 rounded-xl bg-surface border border-border text-sm text-fg placeholder:text-muted focus:outline-none focus:ring-2 focus:ring-primary/50 resize-none h-16" />
173
+ <div className="flex gap-3">
174
+ <div className="flex-1 flex items-center gap-2 px-4 py-3 rounded-xl bg-surface border border-border focus-within:ring-2 focus-within:ring-primary/50">
175
+ <Icon name="sparkles" size={18} className="text-muted shrink-0" />
176
+ <input type="text" value={prompt} onChange={e => setPrompt(e.target.value)} onKeyDown={e => e.key === 'Enter' && handleGenerate()} placeholder="Describe what you want to create..." className="flex-1 bg-transparent text-fg placeholder:text-muted outline-none text-sm" />
177
+ </div>
178
+ <button onClick={handleGenerate} disabled={isGenerating} className="px-6 py-3 rounded-xl bg-primary text-primary-foreground font-semibold hover:brightness-110 transition-all shadow-lg shadow-primary/25 flex items-center gap-2 shrink-0">
179
+ <Icon name="zap" size={18} />Generate
180
+ </button>
181
+ </div>
182
+ </div>
183
+ </div>
184
+ </div>
185
+ </div>
186
+ </div>
187
+ </div>
188
+ );
189
+ };
190
+ ReactDOM.createRoot(document.getElementById('root')).render(<App />);
191
+ </script>
192
+ </body>
193
+ </html>
index.html CHANGED
@@ -1,19 +1,826 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en" class="scroll-smooth">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>NSFWStudio The AI Creation Platform</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <script src="https://unpkg.com/lucide@latest"></script>
9
+ <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
10
+ <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
11
+ <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
12
+ <link rel="preconnect" href="https://fonts.googleapis.com">
13
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
14
+ <link href="https://fonts.googleapis.com/css2?family=Inter:opsz,wght@14..32,300..800&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
15
+ <script>
16
+ tailwind.config = {
17
+ theme: {
18
+ extend: {
19
+ fontFamily: { sans: ['Inter', 'system-ui', 'sans-serif'], mono: ['JetBrains Mono', 'monospace'] },
20
+ colors: {
21
+ bg: 'oklch(0.07 0.006 285)', surface: 'oklch(0.12 0.02 285)', 'surface-2': 'oklch(0.16 0.025 285)', 'surface-3': 'oklch(0.20 0.028 285)',
22
+ fg: 'oklch(0.97 0.005 285)', muted: 'oklch(0.55 0.02 285)', primary: 'oklch(0.70 0.28 350)', 'primary-foreground': 'oklch(0.98 0.005 285)',
23
+ secondary: 'oklch(0.75 0.15 215)', accent: 'oklch(0.80 0.18 85)', border: 'oklch(0.22 0.02 285)', ring: 'oklch(0.70 0.28 350)',
24
+ destructive: 'oklch(0.55 0.22 25)', success: 'oklch(0.65 0.2 145)',
25
+ },
26
+ keyframes: {
27
+ 'fade-up': { 'from': { opacity: '0', transform: 'translateY(20px)' }, 'to': { opacity: '1', transform: 'translateY(0)' } },
28
+ 'fade-in': { 'from': { opacity: '0' }, 'to': { opacity: '1' } },
29
+ 'marquee': { 'from': { transform: 'translateX(0)' }, 'to': { transform: 'translateX(-50%)' } },
30
+ 'pulse-glow': { '0%, 100%': { opacity: '0.4' }, '50%': { opacity: '0.8' } },
31
+ shimmer: { '0%': { backgroundPosition: '-200% 0' }, '100%': { backgroundPosition: '200% 0' } },
32
+ },
33
+ animation: {
34
+ 'fade-up': 'fade-up 0.6s ease-out forwards',
35
+ 'fade-in': 'fade-in 0.5s ease-out forwards',
36
+ 'marquee': 'marquee 30s linear infinite',
37
+ 'pulse-glow': 'pulse-glow 3s ease-in-out infinite',
38
+ shimmer: 'shimmer 2s linear infinite',
39
+ },
40
+ },
41
+ },
42
+ }
43
+ </script>
44
+ <style>
45
+ body { background-color: oklch(0.07 0.006 285); color: oklch(0.97 0.005 285); font-family: 'Inter', system-ui, sans-serif; -webkit-font-smoothing: antialiased; }
46
+ .glass { background: oklch(0.14 0.015 285 / 0.6); backdrop-filter: blur(24px) saturate(1.2); -webkit-backdrop-filter: blur(24px) saturate(1.2); border: 1px solid oklch(0.25 0.02 285 / 0.5); }
47
+ .glass-strong { background: oklch(0.14 0.015 285 / 0.85); backdrop-filter: blur(32px) saturate(1.4); -webkit-backdrop-filter: blur(32px) saturate(1.4); border: 1px solid oklch(0.25 0.02 285 / 0.6); }
48
+ .gradient-text { background: linear-gradient(135deg, oklch(0.70 0.28 350), oklch(0.75 0.15 215)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; }
49
+ .gradient-text-warm { background: linear-gradient(135deg, oklch(0.70 0.28 350), oklch(0.75 0.18 60)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; }
50
+ .grid-pattern { background-image: linear-gradient(oklch(0.22 0.02 285 / 0.3) 1px, transparent 1px), linear-gradient(90deg, oklch(0.22 0.02 285 / 0.3) 1px, transparent 1px); background-size: 64px 64px; }
51
+ .dot-pattern { background-image: radial-gradient(oklch(0.25 0.02 285 / 0.4) 1px, transparent 1px); background-size: 24px 24px; }
52
+ .reveal { opacity: 0; transform: translateY(24px); transition: opacity 0.7s cubic-bezier(0.16, 1, 0.3, 1), transform 0.7s cubic-bezier(0.16, 1, 0.3, 1); }
53
+ .reveal.visible { opacity: 1; transform: translateY(0); }
54
+ .reveal-delay-1 { transition-delay: 0.1s; }
55
+ .reveal-delay-2 { transition-delay: 0.2s; }
56
+ .reveal-delay-3 { transition-delay: 0.3s; }
57
+ .reveal-delay-4 { transition-delay: 0.4s; }
58
+ .reveal-delay-5 { transition-delay: 0.5s; }
59
+ .typing-cursor::after { content: '|'; animation: blink 1s step-end infinite; color: oklch(0.70 0.28 350); font-weight: 300; }
60
+ @keyframes blink { 0%, 100% { opacity: 1; } 50% { opacity: 0; } }
61
+ @keyframes float { 0%, 100% { transform: translateY(0px); } 50% { transform: translateY(-8px); } }
62
+ .animate-float { animation: float 4s ease-in-out infinite; }
63
+ .animate-float-delay { animation: float 4s ease-in-out 1s infinite; }
64
+ .animate-float-slow { animation: float 6s ease-in-out infinite; }
65
+ .card-highlight { position: relative; }
66
+ .card-highlight::before { content: ''; position: absolute; inset: -1px; border-radius: inherit; background: linear-gradient(135deg, oklch(0.70 0.28 350 / 0.4), oklch(0.75 0.15 215 / 0.1), transparent, transparent); z-index: -1; opacity: 0; transition: opacity 0.3s ease; }
67
+ .card-highlight:hover::before { opacity: 1; }
68
+ .card-tilt { transition: transform 0.3s ease, box-shadow 0.3s ease; }
69
+ .card-tilt:hover { transform: translateY(-4px); box-shadow: 0 20px 40px rgba(0,0,0,0.3), 0 0 0 1px oklch(0.25 0.02 285 / 0.5); }
70
+ .tabular-nums { font-variant-numeric: tabular-nums; }
71
+ ::selection { background: oklch(0.70 0.28 350 / 0.3); color: white; }
72
+ body::after { content: ''; position: fixed; inset: 0; pointer-events: none; z-index: 9999; opacity: 0.025; background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); background-repeat: repeat; background-size: 256px 256px; }
73
+ .scroll-progress { position: fixed; top: 0; left: 0; height: 3px; background: linear-gradient(90deg, oklch(0.70 0.28 350), oklch(0.75 0.15 215)); z-index: 100; transition: width 0.1s linear; box-shadow: 0 0 10px oklch(0.70 0.28 350 / 0.5); }
74
+ .faq-content { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 0.35s ease-out; }
75
+ .faq-content.open { grid-template-rows: 1fr; }
76
+ .faq-content > div { overflow: hidden; }
77
+ .stat-number { background: linear-gradient(135deg, oklch(0.97 0.005 285), oklch(0.70 0.28 350)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; }
78
+ .no-scrollbar::-webkit-scrollbar { display: none; } .no-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }
79
+ </style>
80
+ </head>
81
+ <body class="antialiased overflow-x-hidden">
82
+ <div id="root"></div>
83
+
84
+ <script type="text/babel">
85
+ const { useState, useEffect, useRef, useCallback } = React;
86
+
87
+ const useScrollReveal = () => {
88
+ useEffect(() => {
89
+ const observer = new IntersectionObserver(
90
+ (entries) => { entries.forEach(entry => { if (entry.isIntersecting) entry.target.classList.add('visible'); }); },
91
+ { threshold: 0.1, rootMargin: '0px 0px -40px 0px' }
92
+ );
93
+ document.querySelectorAll('.reveal').forEach(el => observer.observe(el));
94
+ return () => observer.disconnect();
95
+ }, []);
96
+ };
97
+
98
+ const useCountUp = (end, duration = 2000) => {
99
+ const [count, setCount] = useState(0);
100
+ const ref = useRef(null);
101
+ const isInView = useRef(false);
102
+ useEffect(() => {
103
+ const observer = new IntersectionObserver(([entry]) => {
104
+ if (entry.isIntersecting && !isInView.current) {
105
+ isInView.current = true;
106
+ const startTime = performance.now();
107
+ const animate = (now) => {
108
+ const elapsed = now - startTime;
109
+ const progress = Math.min(elapsed / duration, 1);
110
+ const eased = 1 - Math.pow(1 - progress, 3);
111
+ setCount(Math.floor(eased * end));
112
+ if (progress < 1) requestAnimationFrame(animate);
113
+ };
114
+ requestAnimationFrame(animate);
115
+ }
116
+ }, { threshold: 0.5 });
117
+ if (ref.current) observer.observe(ref.current);
118
+ return () => observer.disconnect();
119
+ }, [end, duration]);
120
+ return [count, ref];
121
+ };
122
+
123
+ const Icon = ({ name, size = 20, className = "", strokeWidth = 2 }) => {
124
+ const ref = useRef(null);
125
+ useEffect(() => {
126
+ if (ref.current) {
127
+ const existing = ref.current.querySelector('svg');
128
+ if (existing) existing.remove();
129
+ const svg = lucide.createElement(lucide.icons[name]);
130
+ if (svg) {
131
+ svg.setAttribute('width', size);
132
+ svg.setAttribute('height', size);
133
+ svg.setAttribute('stroke-width', strokeWidth);
134
+ ref.current.appendChild(svg);
135
+ }
136
+ }
137
+ }, [name, size, className, strokeWidth]);
138
+ return <span ref={ref} className={`inline-flex items-center justify-center ${className}`} style={{ width: size, height: size }} />;
139
+ };
140
+
141
+ const TopBar = () => (
142
+ <div className="fixed top-0 left-0 right-0 z-[60] h-8 bg-surface border-b border-border flex items-center justify-center px-4">
143
+ <div className="flex items-center gap-6 text-xs text-muted">
144
+ <a href="dashboard.html" className="hover:text-fg transition-colors">Dashboard</a>
145
+ <a href="generator.html" className="hover:text-fg transition-colors">Generator</a>
146
+ <a href="models.html" className="hover:text-fg transition-colors">Models</a>
147
+ <a href="marketplace.html" className="hover:text-fg transition-colors">Marketplace</a>
148
+ <a href="api-keys.html" className="hover:text-fg transition-colors">API</a>
149
+ <a href="signin.html" className="text-primary font-medium hover:underline">Sign In</a>
150
+ </div>
151
+ </div>
152
+ );
153
+
154
+ const ScrollProgress = () => {
155
+ const [progress, setProgress] = useState(0);
156
+ useEffect(() => {
157
+ const onScroll = () => {
158
+ const scrollTop = window.scrollY;
159
+ const docHeight = document.documentElement.scrollHeight - window.innerHeight;
160
+ setProgress(docHeight > 0 ? (scrollTop / docHeight) * 100 : 0);
161
+ };
162
+ window.addEventListener('scroll', onScroll, { passive: true });
163
+ return () => window.removeEventListener('scroll', onScroll);
164
+ }, []);
165
+ return <div className="scroll-progress" style={{ width: `${progress}%` }} />;
166
+ };
167
+
168
+ const BackToTop = () => {
169
+ const [visible, setVisible] = useState(false);
170
+ useEffect(() => {
171
+ const onScroll = () => setVisible(window.scrollY > 600);
172
+ window.addEventListener('scroll', onScroll, { passive: true });
173
+ return () => window.removeEventListener('scroll', onScroll);
174
+ }, []);
175
+ return (
176
+ <button
177
+ onClick={() => window.scrollTo({ top: 0, behavior: 'smooth' })}
178
+ className={`fixed bottom-6 right-6 z-50 w-12 h-12 rounded-xl bg-primary text-primary-foreground flex items-center justify-center shadow-lg shadow-primary/25 hover:brightness-110 transition-all duration-300 ${visible ? 'opacity-100 translate-y-0 pointer-events-auto' : 'opacity-0 translate-y-4 pointer-events-none'}`}
179
+ >
180
+ <Icon name="arrow-up" size={20} />
181
+ </button>
182
+ );
183
+ };
184
+
185
+ const Navbar = () => {
186
+ const [isScrolled, setIsScrolled] = useState(false);
187
+ const [mobileOpen, setMobileOpen] = useState(false);
188
+ useEffect(() => {
189
+ const onScroll = () => setIsScrolled(window.scrollY > 40);
190
+ window.addEventListener('scroll', onScroll, { passive: true });
191
+ return () => window.removeEventListener('scroll', onScroll);
192
+ }, []);
193
+ useEffect(() => {
194
+ document.body.style.overflow = mobileOpen ? 'hidden' : '';
195
+ return () => { document.body.style.overflow = ''; };
196
+ }, [mobileOpen]);
197
+ const links = [
198
+ { name: 'Studio', href: 'generator.html' },
199
+ { name: 'Models', href: 'models.html' },
200
+ { name: 'Agents', href: 'dashboard.html' },
201
+ { name: 'Workflows', href: 'workflows.html' },
202
+ { name: 'Marketplace', href: 'marketplace.html' },
203
+ { name: 'Pricing', href: '#pricing' },
204
+ { name: 'Docs', href: 'playground.html' },
205
+ ];
206
+ return (
207
+ <>
208
+ <nav className={`fixed top-8 w-full z-50 transition-all duration-300 ${isScrolled ? 'glass-strong shadow-lg shadow-black/20' : 'bg-transparent'}`}>
209
+ <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
210
+ <div className="flex items-center justify-between h-16">
211
+ <a href="#" className="flex items-center gap-2.5 group">
212
+ <div className="w-8 h-8 rounded-lg bg-primary flex items-center justify-center"><Icon name="sparkles" size={16} className="text-primary-foreground" /></div>
213
+ <span className="text-lg font-bold tracking-tight">NSFW<span className="text-muted">Studio</span></span>
214
+ </a>
215
+ <div className="hidden lg:flex items-center gap-1">
216
+ {links.map(l => <a key={l.name} href={l.href} className="px-3 py-2 text-sm font-medium text-muted hover:text-fg transition-colors rounded-lg hover:bg-surface-2">{l.name}</a>)}
217
+ </div>
218
+ <div className="hidden lg:flex items-center gap-3">
219
+ <a href="signin.html" className="text-sm font-medium text-muted hover:text-fg transition-colors px-3 py-2">Sign in</a>
220
+ <a href="signin.html" className="px-5 py-2.5 rounded-lg bg-primary text-primary-foreground text-sm font-semibold hover:brightness-110 transition-all shadow-lg shadow-primary/25">Get Started Free</a>
221
+ </div>
222
+ <button onClick={() => setMobileOpen(!mobileOpen)} className="lg:hidden p-2 rounded-lg hover:bg-surface-2 text-muted hover:text-fg transition-colors">
223
+ <Icon name={mobileOpen ? 'x' : 'menu'} size={22} />
224
+ </button>
225
+ </div>
226
+ </div>
227
+ </nav>
228
+ <div className={`fixed inset-0 z-40 lg:hidden transition-all duration-300 ${mobileOpen ? 'opacity-100 pointer-events-auto' : 'opacity-0 pointer-events-none'}`}>
229
+ <div className="absolute inset-0 bg-black/60 backdrop-blur-sm" onClick={() => setMobileOpen(false)} />
230
+ <div className={`absolute right-0 top-0 bottom-0 w-80 max-w-[85vw] bg-surface border-l border-border p-6 pt-20 transition-transform duration-300 ${mobileOpen ? 'translate-x-0' : 'translate-x-full'}`}>
231
+ <div className="flex flex-col gap-1">
232
+ {links.map(l => <a key={l.name} href={l.href} onClick={() => setMobileOpen(false)} className="px-4 py-3 text-base font-medium text-muted hover:text-fg hover:bg-surface-2 rounded-lg transition-colors">{l.name}</a>)}
233
+ </div>
234
+ <div className="mt-6 pt-6 border-t border-border flex flex-col gap-3">
235
+ <a href="signin.html" className="px-4 py-3 text-base font-medium text-muted hover:text-fg text-center rounded-lg hover:bg-surface-2 transition-colors">Sign in</a>
236
+ <a href="signin.html" className="px-4 py-3 bg-primary text-primary-foreground font-semibold text-center rounded-lg hover:brightness-110 transition-all">Get Started Free</a>
237
+ </div>
238
+ </div>
239
+ </div>
240
+ </>
241
+ );
242
+ };
243
+
244
+ const Hero = () => {
245
+ const words = ['Images', 'Videos', 'Agents', 'Workflows', 'Models'];
246
+ const [typedWord, setTypedWord] = useState('');
247
+ const [wordIndex, setWordIndex] = useState(0);
248
+ const [isDeleting, setIsDeleting] = useState(false);
249
+ useEffect(() => {
250
+ const currentWord = words[wordIndex];
251
+ let timeout;
252
+ if (!isDeleting) {
253
+ if (typedWord.length < currentWord.length) {
254
+ timeout = setTimeout(() => setTypedWord(currentWord.slice(0, typedWord.length + 1)), 80 + Math.random() * 40);
255
+ } else {
256
+ timeout = setTimeout(() => setIsDeleting(true), 2000);
257
+ }
258
+ } else {
259
+ if (typedWord.length > 0) {
260
+ timeout = setTimeout(() => setTypedWord(typedWord.slice(0, -1)), 40);
261
+ } else {
262
+ setIsDeleting(false);
263
+ setWordIndex((prev) => (prev + 1) % words.length);
264
+ }
265
+ }
266
+ return () => clearTimeout(timeout);
267
+ }, [typedWord, isDeleting, wordIndex]);
268
+ const stats = [
269
+ { label: 'Creators', value: '2.8M+', icon: 'users' },
270
+ { label: 'AI Models', value: '45.8K+', icon: 'box' },
271
+ { label: 'Workflows', value: '1.2M+', icon: 'workflow' },
272
+ { label: 'Uptime', value: '99.9%', icon: 'activity' },
273
+ ];
274
+ return (
275
+ <section className="relative pt-36 pb-8 lg:pt-44 lg:pb-12 overflow-hidden">
276
+ <div className="absolute inset-0 grid-pattern opacity-40 pointer-events-none" />
277
+ <div className="absolute top-0 right-0 w-[900px] h-[900px] bg-primary/15 rounded-full blur-[160px] -translate-y-1/2 translate-x-1/3 pointer-events-none animate-pulse-glow" />
278
+ <div className="absolute bottom-0 left-0 w-[600px] h-[600px] bg-secondary/10 rounded-full blur-[140px] translate-y-1/3 -translate-x-1/3 pointer-events-none" />
279
+ <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 relative z-10">
280
+ <div className="grid lg:grid-cols-2 gap-8 lg:gap-16 items-center">
281
+ <div className="space-y-8">
282
+ <div className="inline-flex items-center gap-2 px-3.5 py-1.5 rounded-full border border-border bg-surface/80 backdrop-blur-sm reveal">
283
+ <span className="w-2 h-2 rounded-full bg-primary animate-pulse" />
284
+ <span className="text-xs font-semibold tracking-wider uppercase text-muted">Now in Public Beta — v3.0</span>
285
+ </div>
286
+ <h1 className="text-4xl sm:text-5xl md:text-6xl lg:text-7xl font-bold leading-[1.05] tracking-tight reveal reveal-delay-1">
287
+ Create <span className="gradient-text">Without</span><br />Limits.<br />
288
+ <span className="relative inline-flex min-w-[200px] sm:min-w-[260px]">
289
+ <span className="gradient-text-warm typing-cursor">{typedWord}</span>
290
+ </span>
291
+ </h1>
292
+ <p className="text-base lg:text-lg text-muted max-w-lg leading-relaxed reveal reveal-delay-2">
293
+ The all-in-one platform for AI creators. Build, automate, and monetize with the most powerful AI tools — from text to image to autonomous agents.
294
+ </p>
295
+ <div className="flex flex-wrap gap-3 reveal reveal-delay-3">
296
+ <a href="signin.html" className="group inline-flex items-center gap-2.5 px-7 py-4 rounded-xl bg-primary text-primary-foreground font-semibold hover:brightness-110 transition-all shadow-xl shadow-primary/25 hover:shadow-primary/40">
297
+ Start Creating <Icon name="arrow-right" size={16} className="group-hover:translate-x-0.5 transition-transform" />
298
+ </a>
299
+ <a href="playground.html" className="inline-flex items-center gap-2.5 px-7 py-4 rounded-xl border border-border bg-surface/50 text-fg font-semibold hover:bg-surface-2 hover:border-surface-3 transition-all">
300
+ <Icon name="play" size={16} /> Watch Demo
301
+ </a>
302
+ </div>
303
+ <div className="grid grid-cols-2 sm:grid-cols-4 gap-6 pt-8 border-t border-border reveal reveal-delay-4">
304
+ {stats.map((s, i) => (
305
+ <div key={i} className="group">
306
+ <div className="flex items-center gap-1.5 mb-1.5">
307
+ <Icon name={s.icon} size={14} className="text-muted group-hover:text-primary transition-colors" />
308
+ <span className="text-xs text-muted uppercase tracking-wider font-medium">{s.label}</span>
309
+ </div>
310
+ <div className="text-xl sm:text-2xl font-bold text-fg tabular-nums">{s.value}</div>
311
+ </div>
312
+ ))}
313
+ </div>
314
+ </div>
315
+ <div className="relative lg:h-[620px] flex items-center justify-center reveal reveal-delay-2">
316
+ <div className="absolute inset-0 rounded-3xl overflow-hidden opacity-40 pointer-events-none">
317
+ <img src="http://static.photos/cyberpunk/800x1000/1" alt="" className="w-full h-full object-cover" />
318
+ <div className="absolute inset-0 bg-gradient-to-t from-bg via-bg/60 to-transparent" />
319
+ <div className="absolute inset-0 bg-gradient-to-r from-bg/80 to-transparent" />
320
+ </div>
321
+ <div className="relative w-full max-w-md glass rounded-2xl p-5 shadow-2xl shadow-black/40">
322
+ <div className="flex items-center justify-between mb-4">
323
+ <div className="flex items-center gap-2">
324
+ <div className="w-2 h-2 rounded-full bg-success animate-pulse" />
325
+ <span className="text-sm font-medium text-fg">Real-time Generation</span>
326
+ </div>
327
+ <span className="px-2.5 py-1 rounded-md bg-success/10 text-success text-xs font-semibold border border-success/20">LIVE</span>
328
+ </div>
329
+ <div className="relative rounded-xl overflow-hidden mb-4 aspect-video bg-surface-3 group cursor-pointer">
330
+ <img src="http://static.photos/cyberpunk/640x360/2" alt="Generated preview" className="w-full h-full object-cover opacity-90 group-hover:scale-105 transition-transform duration-700" />
331
+ <div className="absolute inset-0 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity bg-black/30">
332
+ <div className="w-14 h-14 rounded-full bg-white/20 backdrop-blur-sm flex items-center justify-center border border-white/20">
333
+ <Icon name="play" size={24} className="text-white ml-1" />
334
+ </div>
335
+ </div>
336
+ </div>
337
+ <div className="space-y-3">
338
+ <div className="flex justify-between items-end">
339
+ <div>
340
+ <h3 className="font-semibold text-fg text-sm">Cyberpunk Cityscape</h3>
341
+ <p className="text-xs text-muted">4K Ultra — DreamVision XL</p>
342
+ </div>
343
+ <span className="text-sm font-bold text-primary tabular-nums">72%</span>
344
+ </div>
345
+ <div className="h-1.5 w-full bg-surface-3 rounded-full overflow-hidden">
346
+ <div className="h-full w-[72%] bg-gradient-to-r from-primary to-secondary rounded-full relative overflow-hidden">
347
+ <div className="absolute inset-y-0 right-0 w-8 bg-gradient-to-r from-transparent to-white/30 animate-shimmer" />
348
+ </div>
349
+ </div>
350
+ <div className="flex items-center gap-3 text-xs text-muted">
351
+ <span className="flex items-center gap-1"><Icon name="clock" size={12} /> ~12s remaining</span>
352
+ <span className="flex items-center gap-1"><Icon name="cpu" size={12} /> GPU: A100</span>
353
+ </div>
354
+ </div>
355
+ </div>
356
+ <div className="absolute top-6 -left-4 glass rounded-xl px-3 py-2 flex items-center gap-2 shadow-lg shadow-black/20 animate-float">
357
+ <div className="w-6 h-6 rounded-md bg-primary/20 flex items-center justify-center"><Icon name="box" size={12} className="text-primary" /></div>
358
+ <div><div className="text-xs font-semibold text-fg">45.8K+ Models</div></div>
359
+ </div>
360
+ <div className="absolute bottom-12 -left-4 glass rounded-xl px-3 py-2 flex items-center gap-2 shadow-lg shadow-black/20 animate-float-delay">
361
+ <div className="w-6 h-6 rounded-md bg-secondary/20 flex items-center justify-center"><Icon name="zap" size={12} className="text-secondary" /></div>
362
+ <div><div className="text-xs font-semibold text-fg">99.9% Uptime</div></div>
363
+ </div>
364
+ <div className="absolute top-1/2 -right-4 glass rounded-xl px-3 py-2 flex items-center gap-2 shadow-lg shadow-black/20 animate-float-slow hidden lg:flex">
365
+ <div className="w-6 h-6 rounded-md bg-success/20 flex items-center justify-center"><Icon name="dollar-sign" size={12} className="text-success" /></div>
366
+ <div><div className="text-xs font-semibold text-fg">$12M+ Earned</div></div>
367
+ </div>
368
+ </div>
369
+ </div>
370
+ </div>
371
+ </section>
372
+ );
373
+ };
374
+
375
+ const TrustedBy = () => {
376
+ const brands = [
377
+ { name: 'Stability AI', icon: 'hexagon' }, { name: 'Hugging Face', icon: 'smile' }, { name: 'Replicate', icon: 'copy' },
378
+ { name: 'Comfy UI', icon: 'layout-dashboard' }, { name: 'Automatic1111', icon: 'terminal' }, { name: 'Ollama', icon: 'server' },
379
+ { name: 'LangChain', icon: 'link' }, { name: 'LlamaIndex', icon: 'book-open' }, { name: 'CrewAI', icon: 'users' },
380
+ { name: 'AutoGen', icon: 'bot' }, { name: 'Vercel', icon: 'triangle' }, { name: 'Cloudflare', icon: 'cloud' },
381
+ ];
382
+ return (
383
+ <section className="py-12 border-y border-border/50 relative overflow-hidden">
384
+ <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 mb-6">
385
+ <p className="text-center text-xs font-semibold uppercase tracking-widest text-muted">Integrated with the tools you love</p>
386
+ </div>
387
+ <div className="relative">
388
+ <div className="absolute left-0 top-0 bottom-0 w-32 bg-gradient-to-r from-bg to-transparent z-10 pointer-events-none" />
389
+ <div className="absolute right-0 top-0 bottom-0 w-32 bg-gradient-to-l from-bg to-transparent z-10 pointer-events-none" />
390
+ <div className="flex animate-marquee whitespace-nowrap">
391
+ {[...brands, ...brands].map((b, i) => (
392
+ <div key={i} className="mx-8 flex items-center gap-2.5 text-muted/50 hover:text-muted transition-colors duration-300">
393
+ <Icon name={b.icon} size={18} /><span className="text-sm font-semibold tracking-wide">{b.name}</span>
394
+ </div>
395
+ ))}
396
+ </div>
397
+ </div>
398
+ </section>
399
+ );
400
+ };
401
+
402
+ const HowItWorks = () => {
403
+ const steps = [
404
+ { icon: 'pencil', title: '1. Describe', desc: 'Write your prompt or upload a reference image to guide the AI generation.' },
405
+ { icon: 'sparkles', title: '2. Generate', desc: 'Choose from 45K+ models and watch your creation come to life in seconds.' },
406
+ { icon: 'wand', title: '3. Refine', desc: "Upscale, edit, and fine-tune with our built-in tools until it's perfect." },
407
+ { icon: 'rocket', title: '4. Publish & Earn', desc: 'Share to the marketplace or deploy via API and start earning revenue.' },
408
+ ];
409
+ return (
410
+ <section className="py-24 relative">
411
+ <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
412
+ <div className="text-center mb-16 reveal">
413
+ <span className="inline-block px-3 py-1.5 rounded-full border border-border bg-surface/50 text-xs font-semibold uppercase tracking-widest text-muted mb-4">How It Works</span>
414
+ <h2 className="text-3xl md:text-5xl font-bold mb-4">From Idea to <span className="gradient-text">Creation</span> in Seconds</h2>
415
+ <p className="text-muted max-w-2xl mx-auto text-lg">Four simple steps to bring your vision to life.</p>
416
+ </div>
417
+ <div className="grid grid-cols-1 md:grid-cols-4 gap-8 reveal reveal-delay-2">
418
+ {steps.map((step, i) => (
419
+ <div key={i} className="relative text-center group">
420
+ <div className="w-16 h-16 rounded-2xl bg-primary/10 flex items-center justify-center mx-auto mb-5 group-hover:scale-110 transition-transform">
421
+ <Icon name={step.icon} size={28} className="text-primary" />
422
+ </div>
423
+ <h3 className="text-lg font-semibold text-fg mb-2">{step.title}</h3>
424
+ <p className="text-sm text-muted leading-relaxed">{step.desc}</p>
425
+ {i < steps.length - 1 && (
426
+ <div className="hidden md:block absolute top-8 right-0 translate-x-1/2 w-8 border-t-2 border-dashed border-border/50" />
427
+ )}
428
+ </div>
429
+ ))}
430
+ </div>
431
+ </div>
432
+ </section>
433
+ );
434
+ };
435
+
436
+ const Features = () => {
437
+ const features = [
438
+ { icon: 'hexagon', title: 'Studio', desc: 'Generate images, videos, audio, text, and code with state-of-the-art AI models. Multi-modal creation in one place.', color: 'text-primary', bg: 'bg-primary/10', link: 'Open Studio →', href: 'generator.html', span: 'lg:col-span-2 lg:row-span-2' },
439
+ { icon: 'box', title: 'Models', desc: 'Access 45K+ AI models across every modality. Train, fine-tune, and deploy.', color: 'text-secondary', bg: 'bg-secondary/10', link: 'Browse Models →', href: 'models.html', span: '' },
440
+ { icon: 'bot', title: 'Agents', desc: 'Create autonomous AI agents that think, plan, and execute for you.', color: 'text-success', bg: 'bg-success/10', link: 'Manage Agents →', href: 'dashboard.html', span: '' },
441
+ { icon: 'workflow', title: 'Workflows', desc: 'Build powerful automation pipelines with visual tools and smart triggers.', color: 'text-purple-400', bg: 'bg-purple-500/10', link: 'Create Workflow →', href: 'workflows.html', span: '' },
442
+ { icon: 'shopping-bag', title: 'Marketplace', desc: 'Discover, buy, and sell models, agents, prompts, and workflows.', color: 'text-accent', bg: 'bg-accent/10', link: 'Explore Marketplace →', href: 'marketplace.html', span: '' },
443
+ ];
444
+ return (
445
+ <section className="py-24 relative">
446
+ <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
447
+ <div className="text-center mb-16 reveal">
448
+ <span className="inline-block px-3 py-1.5 rounded-full border border-border bg-surface/50 text-xs font-semibold uppercase tracking-widest text-muted mb-4">Platform</span>
449
+ <h2 className="text-3xl md:text-5xl font-bold mb-4">Everything You Need to <span className="gradient-text">Build, Scale & Earn</span></h2>
450
+ <p className="text-muted max-w-2xl mx-auto text-lg">One platform for all your AI creation needs. From generation to monetization.</p>
451
+ </div>
452
+ <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
453
+ {features.map((f, i) => (
454
+ <div key={i} className={`${f.span || ''} group relative rounded-2xl p-6 lg:p-8 bg-surface border border-border hover:border-surface-3 transition-all duration-300 cursor-pointer card-highlight card-tilt reveal reveal-delay-${i + 1}`}>
455
+ {i === 0 && (
456
+ <div className="hidden lg:block absolute bottom-6 right-6 w-48 h-32 rounded-xl overflow-hidden opacity-50 group-hover:opacity-70 transition-opacity">
457
+ <img src="http://static.photos/cyberpunk/400x200/3" alt="" className="w-full h-full object-cover" />
458
+ </div>
459
+ )}
460
+ <div className={`w-10 h-10 rounded-xl ${f.bg} flex items-center justify-center mb-4 group-hover:scale-110 transition-transform`}>
461
+ <Icon name={f.icon} size={20} className={f.color} />
462
+ </div>
463
+ <h3 className="text-xl font-semibold mb-2 text-fg">{f.title}</h3>
464
+ <p className="text-sm text-muted leading-relaxed mb-6">{f.desc}</p>
465
+ <a href={f.href} className={`text-sm font-semibold ${f.color} flex items-center gap-1 group-hover:gap-2 transition-all`}>{f.link}</a>
466
+ </div>
467
+ ))}
468
+ </div>
469
+ </div>
470
+ </section>
471
+ );
472
+ };
473
+
474
+ const NumberStats = () => {
475
+ const [c1, r1] = useCountUp(2800000);
476
+ const [c2, r2] = useCountUp(45800);
477
+ const [c3, r3] = useCountUp(1200000);
478
+ const [c4, r4] = useCountUp(99);
479
+
480
+ const format = (n) => {
481
+ if (n >= 1000000) return (n / 1000000).toFixed(1) + 'M';
482
+ if (n >= 1000) return (n / 1000).toFixed(1) + 'K';
483
+ return n.toString();
484
+ };
485
+
486
+ const stats = [
487
+ { label: 'Creators', count: c1, ref: r1, display: format(c1), suffix: '+', icon: 'users', color: 'text-primary' },
488
+ { label: 'AI Models', count: c2, ref: r2, display: format(c2), suffix: '+', icon: 'box', color: 'text-secondary' },
489
+ { label: 'Workflows Run', count: c3, ref: r3, display: format(c3), suffix: '+', icon: 'workflow', color: 'text-success' },
490
+ { label: 'Uptime', count: c4, ref: r4, display: c4, suffix: '.9%', icon: 'activity', color: 'text-accent' },
491
+ ];
492
+
493
+ return (
494
+ <section className="py-16 border-y border-border/50 bg-surface/30">
495
+ <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
496
+ <div className="grid grid-cols-2 lg:grid-cols-4 gap-8">
497
+ {stats.map((s, i) => (
498
+ <div key={i} ref={s.ref} className="text-center">
499
+ <div className="w-10 h-10 rounded-xl bg-surface-2 flex items-center justify-center mx-auto mb-3">
500
+ <Icon name={s.icon} size={20} className={s.color} />
501
+ </div>
502
+ <div className="text-3xl md:text-4xl font-bold stat-number tabular-nums">
503
+ {s.display}{s.suffix}
504
+ </div>
505
+ <div className="text-sm text-muted mt-1">{s.label}</div>
506
+ </div>
507
+ ))}
508
+ </div>
509
+ </div>
510
+ </section>
511
+ );
512
+ };
513
+
514
+ const LiveActivity = () => {
515
+ const activities = [
516
+ { user: '@neon_dreamer', action: 'generated Cyberpunk Girl', time: '2s', avatar: 'http://static.photos/people/100x100/1', type: 'image' },
517
+ { user: '@ai_architect', action: 'created a new workflow', time: '5s', avatar: 'http://static.photos/people/100x100/2', type: 'workflow' },
518
+ { user: '@prompt_master', action: 'trained DreamVision XL', time: '8s', avatar: 'http://static.photos/people/100x100/3', type: 'model' },
519
+ { user: '@digital_ghost', action: 'sold a model for $49', time: '12s', avatar: 'http://static.photos/people/100x100/4', type: 'sale' },
520
+ { user: '@luna_vfx', action: 'rendered 4K video', time: '18s', avatar: 'http://static.photos/people/100x100/15', type: 'video' },
521
+ ];
522
+ const creations = [
523
+ { title: 'Neon Metropolis', type: 'Text to Image', image: 'http://static.photos/cyberpunk/400x300/3', likes: 128, views: '1.2K', user: '@neon_dreamer' },
524
+ { title: 'Anime Cinematic', type: 'Image to Video', image: 'http://static.photos/people/400x300/5', likes: 95, views: '843', user: '@creative_chaos' },
525
+ { title: 'Future Soldier', type: 'Text to Video', image: 'http://static.photos/technology/400x300/6', likes: 73, views: '612', user: '@ai_architect' },
526
+ { title: 'Space Horizon', type: 'Text to Image', image: 'http://static.photos/nature/400x300/7', likes: 66, views: '512', user: '@galactic_prompt' },
527
+ ];
528
+ const typeIcons = { image: 'image', workflow: 'workflow', model: 'box', sale: 'dollar-sign', video: 'video' };
529
+ return (
530
+ <section className="py-24 bg-surface/40 border-y border-border/50">
531
+ <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
532
+ <div className="flex flex-col lg:flex-row gap-10">
533
+ <div className="lg:w-[340px] flex-shrink-0 reveal">
534
+ <div className="flex items-center justify-between mb-6">
535
+ <div><h3 className="text-2xl font-bold mb-1">Live Activity</h3><p className="text-sm text-muted">Real-time creator activity</p></div>
536
+ <span className="flex items-center gap-1.5 px-2.5 py-1 rounded-full bg-success/10 border border-success/20 text-xs font-semibold text-success">
537
+ <span className="relative flex h-2 w-2"><span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-success opacity-75"></span><span className="relative inline-flex rounded-full h-2 w-2 bg-success"></span></span>Live
538
+ </span>
539
+ </div>
540
+ <div className="space-y-2 mb-6">
541
+ {activities.map((act, i) => (
542
+ <div key={i} className="flex items-center gap-3 p-3 rounded-xl hover:bg-surface-2/50 transition-colors cursor-pointer group">
543
+ <img src={act.avatar} alt="" className="w-9 h-9 rounded-full border border-border object-cover" />
544
+ <div className="flex-1 min-w-0"><p className="text-sm text-fg/80 truncate"><span className="text-fg font-medium">{act.user}</span> {act.action}</p></div>
545
+ <div className="flex items-center gap-1.5 text-xs text-muted shrink-0"><Icon name={typeIcons[act.type]} size={12} />{act.time}</div>
546
+ </div>
547
+ ))}
548
+ </div>
549
+ <a href="dashboard.html" className="w-full py-2.5 rounded-xl border border-border text-sm font-medium text-muted hover:text-fg hover:bg-surface-2 transition-colors text-center block">View Full Feed</a>
550
+ </div>
551
+ <div className="flex-1 grid grid-cols-1 sm:grid-cols-2 gap-4 reveal reveal-delay-2">
552
+ {creations.map((item, i) => (
553
+ <div key={i} className="group relative rounded-2xl overflow-hidden aspect-[4/3] cursor-pointer">
554
+ <img src={item.image} alt={item.title} className="w-full h-full object-cover transition-transform duration-700 group-hover:scale-110" />
555
+ <div className="absolute inset-0 bg-gradient-to-t from-black/90 via-black/30 to-transparent opacity-80 group-hover:opacity-100 transition-opacity" />
556
+ <div className="absolute top-3 left-3"><span className="px-2.5 py-1 rounded-lg bg-black/60 backdrop-blur-sm text-xs font-medium text-fg border border-white/10">{item.type}</span></div>
557
+ <div className="absolute bottom-0 left-0 right-0 p-4">
558
+ <h4 className="font-semibold text-fg mb-1.5">{item.title}</h4>
559
+ <div className="flex items-center justify-between text-xs text-muted">
560
+ <span>{item.user}</span>
561
+ <div className="flex items-center gap-3">
562
+ <span className="flex items-center gap-1"><Icon name="heart" size={12} /> {item.likes}</span>
563
+ <span className="flex items-center gap-1"><Icon name="eye" size={12} /> {item.views}</span>
564
+ </div>
565
+ </div>
566
+ </div>
567
+ </div>
568
+ ))}
569
+ </div>
570
+ </div>
571
+ </div>
572
+ </section>
573
+ );
574
+ };
575
+
576
+ const TopCreators = () => {
577
+ const creators = [
578
+ { name: 'neon_dreamer', handle: '@neon_dreamer', followers: '24.1K', likes: '1.2M', badge: 'Top Creator', badgeColor: 'bg-primary/15 text-primary border-primary/20', img: 'http://static.photos/people/200x200/10', verified: false },
579
+ { name: 'ai_architect', handle: '@ai_architect', followers: '18.7K', likes: '982K', badge: 'Verified', badgeColor: 'bg-secondary/15 text-secondary border-secondary/20', img: 'http://static.photos/people/200x200/11', verified: true },
580
+ { name: 'creative_chaos', handle: '@creative_chaos', followers: '16.3K', likes: '872K', badge: 'Top Creator', badgeColor: 'bg-primary/15 text-primary border-primary/20', img: 'http://static.photos/people/200x200/12', verified: false },
581
+ { name: 'digital_ghost', handle: '@digital_ghost', followers: '13.9K', likes: '745K', badge: 'Verified', badgeColor: 'bg-secondary/15 text-secondary border-secondary/20', img: 'http://static.photos/people/200x200/13', verified: true },
582
+ { name: 'prompt_master', handle: '@prompt_master', followers: '12.2K', likes: '612K', badge: 'Rising Star', badgeColor: 'bg-accent/15 text-accent border-accent/20', img: 'http://static.photos/people/200x200/14', verified: false },
583
+ ];
584
+ return (
585
+ <section className="py-24">
586
+ <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
587
+ <div className="flex items-center justify-between mb-12 reveal">
588
+ <div><h2 className="text-3xl md:text-4xl font-bold mb-2">Top Creators</h2><p className="text-muted">Meet the community shaping the future.</p></div>
589
+ <a href="marketplace.html" className="hidden sm:inline-flex items-center gap-2 px-4 py-2.5 rounded-xl border border-border text-sm font-medium text-muted hover:text-fg hover:bg-surface-2 transition-colors">Explore All <Icon name="arrow-right" size={14} /></a>
590
+ </div>
591
+ <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-5 gap-4 reveal reveal-delay-2">
592
+ {creators.map((c, i) => (
593
+ <div key={i} className="group relative rounded-2xl p-6 bg-surface border border-border hover:border-surface-3 text-center transition-all duration-300 hover:-translate-y-1">
594
+ <div className="relative w-20 h-20 mx-auto mb-4">
595
+ <img src={c.img} alt={c.name} className="w-full h-full rounded-full object-cover border-2 border-border" />
596
+ {c.verified && <div className="absolute -bottom-0.5 -right-0.5 bg-secondary text-white p-1 rounded-full border-2 border-surface"><Icon name="check" size={10} /></div>}
597
+ </div>
598
+ <h3 className="font-bold text-fg mb-0.5">{c.name}</h3>
599
+ <p className="text-xs text-muted mb-4">{c.handle}</p>
600
+ <div className="flex justify-center gap-4 mb-4 text-xs">
601
+ <div><div className="font-bold text-fg tabular-nums">{c.followers}</div><div className="text-muted">Followers</div></div>
602
+ <div><div className="font-bold text-fg tabular-nums">{c.likes}</div><div className="text-muted">Likes</div></div>
603
+ </div>
604
+ <span className={`inline-block px-3 py-1 rounded-full text-xs font-semibold border ${c.badgeColor}`}>{c.badge}</span>
605
+ </div>
606
+ ))}
607
+ </div>
608
+ </div>
609
+ </section>
610
+ );
611
+ };
612
+
613
+ const Pricing = () => {
614
+ const [isYearly, setIsYearly] = useState(false);
615
+ const plans = [
616
+ { name: 'Free', desc: 'Get started with basic features.', price: 0, period: '/mo', features: ['10 generations / day', 'Basic models access', 'Community support', 'Standard queue'], cta: 'Get Started', highlight: false },
617
+ { name: 'Creator', desc: 'Perfect for content creators.', price: 19, period: '/mo', features: ['1,000 generations / mo', 'Advanced models', 'Priority support', 'Commercial use', 'Custom workflows'], cta: 'Choose Plan', highlight: false },
618
+ { name: 'Pro', desc: 'Best for power users.', price: 49, period: '/mo', features: ['10,000 generations / mo', 'All models access', 'Fast queue', 'Early access features', 'API access', 'Team collaboration'], cta: 'Choose Plan', highlight: true },
619
+ { name: 'Team', desc: 'For teams and studios.', price: 149, period: '/mo', features: ['50,000 generations / mo', 'Team collaboration', 'Shared assets', 'Advanced analytics', 'API access', 'Priority queue'], cta: 'Choose Plan', highlight: false },
620
+ { name: 'Enterprise', desc: 'For large scale operations.', price: null, period: '', features: ['Unlimited generations', 'Custom integrations', 'Dedicated support', 'SLA & uptime guarantee', 'On-premise option'], cta: 'Contact Sales', highlight: false },
621
+ ];
622
+ return (
623
+ <section id="pricing" className="py-24 relative">
624
+ <div className="absolute inset-0 dot-pattern opacity-20 pointer-events-none" />
625
+ <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 relative z-10">
626
+ <div className="text-center mb-12 reveal">
627
+ <span className="inline-block px-3 py-1.5 rounded-full border border-border bg-surface/50 text-xs font-semibold uppercase tracking-widest text-muted mb-4">Pricing</span>
628
+ <h2 className="text-3xl md:text-5xl font-bold mb-4">Simple, Transparent Pricing</h2>
629
+ <p className="text-muted text-lg mb-8">Start free. Scale when you're ready.</p>
630
+ <div className="inline-flex items-center p-1 rounded-full border border-border bg-surface">
631
+ <button onClick={() => setIsYearly(false)} className={`px-6 py-2.5 rounded-full text-sm font-medium transition-all ${!isYearly ? 'bg-fg text-bg shadow-sm' : 'text-muted hover:text-fg'}`}>Monthly</button>
632
+ <button onClick={() => setIsYearly(true)} className={`px-6 py-2.5 rounded-full text-sm font-medium transition-all flex items-center gap-2 ${isYearly ? 'bg-fg text-bg shadow-sm' : 'text-muted hover:text-fg'}`}>
633
+ Yearly <span className="px-2 py-0.5 rounded-full bg-success/15 text-success text-xs font-semibold border border-success/20">20% off</span>
634
+ </button>
635
+ </div>
636
+ </div>
637
+ <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-5 gap-4 reveal reveal-delay-2">
638
+ {plans.map((plan, i) => (
639
+ <div key={i} className={`relative rounded-2xl p-6 flex flex-col h-full transition-all duration-300 ${plan.highlight ? 'bg-gradient-to-b from-primary/10 to-surface border-2 border-primary/40 shadow-xl shadow-primary/10' : 'bg-surface border border-border hover:border-surface-3'}`}>
640
+ {plan.highlight && <div className="absolute -top-3.5 left-1/2 -translate-x-1/2 px-4 py-1 bg-primary text-primary-foreground text-xs font-bold rounded-full shadow-lg shadow-primary/30">MOST POPULAR</div>}
641
+ <div className="mb-5"><h3 className="text-lg font-semibold text-fg mb-1">{plan.name}</h3><p className="text-xs text-muted">{plan.desc}</p></div>
642
+ <div className="mb-5"><span className="text-4xl font-bold text-fg tabular-nums">{plan.price === null ? 'Custom' : `$${isYearly ? Math.round(plan.price * 0.8) : plan.price}`}</span>{plan.period && <span className="text-muted text-sm">{plan.period}</span>}</div>
643
+ <ul className="space-y-3 mb-8 flex-grow">
644
+ {plan.features.map((feat, j) => <li key={j} className="flex items-start gap-2.5 text-sm text-fg/80"><Icon name="check" size={16} className="text-primary shrink-0 mt-0.5" /><span>{feat}</span></li>)}
645
+ </ul>
646
+ <button className={`w-full py-3 rounded-xl text-sm font-semibold transition-all ${plan.highlight ? 'bg-primary text-primary-foreground hover:brightness-110 shadow-lg shadow-primary/25' : 'border border-border text-fg hover:bg-surface-2 hover:border-surface-3'}`}>{plan.cta}</button>
647
+ </div>
648
+ ))}
649
+ </div>
650
+ </div>
651
+ </section>
652
+ );
653
+ };
654
+
655
+ const Testimonials = () => {
656
+ const testimonials = [
657
+ { text: "NSFWStudio changed the way I create. The tools are insane and the community is next level.", author: "Luna Mist", role: "AI Artist", img: "http://static.photos/people/100x100/20" },
658
+ { text: "The workflow builder and agents saved me hundreds of hours. Absolute game changer for my studio.", author: "Dark Pixel", role: "Workflow Engineer", img: "http://static.photos/people/100x100/21" },
659
+ { text: "Best platform for AI creation. The model quality is unmatched and the API is a breeze.", author: "Echo Nova", role: "Content Creator", img: "http://static.photos/people/100x100/22" },
660
+ { text: "Finally, a platform that gives creators freedom and powerful tools in one place. Outstanding.", author: "Nyx Reality", role: "Digital Creator", img: "http://static.photos/people/100x100/23" },
661
+ ];
662
+ return (
663
+ <section className="py-24 bg-surface/40 border-y border-border/50">
664
+ <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
665
+ <div className="text-center mb-12 reveal">
666
+ <span className="inline-block px-3 py-1.5 rounded-full border border-border bg-surface/50 text-xs font-semibold uppercase tracking-widest text-muted mb-4">Testimonials</span>
667
+ <h2 className="text-3xl md:text-4xl font-bold mb-2">Loved by Creators</h2>
668
+ <p className="text-muted">See what our community is saying.</p>
669
+ </div>
670
+ <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 reveal reveal-delay-2">
671
+ {testimonials.map((t, i) => (
672
+ <div key={i} className="group rounded-2xl p-6 bg-surface border border-border hover:border-surface-3 transition-all duration-300 hover:-translate-y-1 relative">
673
+ <div className="absolute top-4 right-4 text-primary/10 group-hover:text-primary/20 transition-colors"><Icon name="quote" size={32} /></div>
674
+ <div className="flex gap-0.5 mb-4 text-primary">{[...Array(5)].map((_, j) => <Icon key={j} name="star" size={14} />)}</div>
675
+ <p className="text-fg/80 text-sm leading-relaxed mb-6">"{t.text}"</p>
676
+ <div className="flex items-center gap-3 mt-auto">
677
+ <img src={t.img} alt={t.author} className="w-10 h-10 rounded-full border border-border object-cover" />
678
+ <div><div className="text-sm font-semibold text-fg">{t.author}</div><div className="text-xs text-muted">{t.role}</div></div>
679
+ </div>
680
+ </div>
681
+ ))}
682
+ </div>
683
+ </div>
684
+ </section>
685
+ );
686
+ };
687
+
688
+ const FAQ = () => {
689
+ const [openIndex, setOpenIndex] = useState(null);
690
+ const faqs = [
691
+ { q: 'What is NSFWStudio?', a: "NSFWStudio is an all-in-one AI creation platform that lets you generate images, videos, agents, and workflows. Whether you're a solo creator or part of a team, our tools help you build, automate, and monetize your AI-powered content." },
692
+ { q: 'Is there a free tier?', a: 'Yes! Our Free tier gives you 10 generations per day, access to basic models, and community support. No credit card required to start. Upgrade anytime as your needs grow.' },
693
+ { q: 'What kind of models are available?', a: 'We offer over 45,000+ AI models across all modalities — text to image, image to video, style transfer, upscaling, and more. You can also train and deploy your own custom models on the platform.' },
694
+ { q: 'Can I use generated content commercially?', a: 'Absolutely. On the Creator plan and above, all content you generate comes with full commercial usage rights. You own what you create and can use it for any purpose.' },
695
+ { q: 'What are AI Agents and Workflows?', a: 'Agents are autonomous AI programs that can think, plan, and execute tasks on your behalf. Workflows let you chain multiple steps together — from generation to post-processing — into automated pipelines.' },
696
+ { q: 'How does the marketplace work?', a: 'The marketplace lets you buy and sell models, agents, prompts, and workflow templates. Creators earn revenue from their work, and buyers get access to production-ready AI tools. We handle payments, licensing, and distribution.' },
697
+ ];
698
+ return (
699
+ <section className="py-24">
700
+ <div className="max-w-3xl mx-auto px-4 sm:px-6 lg:px-8">
701
+ <div className="text-center mb-12 reveal">
702
+ <span className="inline-block px-3 py-1.5 rounded-full border border-border bg-surface/50 text-xs font-semibold uppercase tracking-widest text-muted mb-4">FAQ</span>
703
+ <h2 className="text-3xl md:text-4xl font-bold mb-2">Frequently Asked Questions</h2>
704
+ <p className="text-muted">Got questions? We've got answers.</p>
705
+ </div>
706
+ <div className="space-y-3 reveal reveal-delay-1">
707
+ {faqs.map((faq, i) => (
708
+ <div key={i} className="rounded-xl border border-border bg-surface overflow-hidden">
709
+ <button onClick={() => setOpenIndex(openIndex === i ? null : i)} className="w-full flex items-center justify-between p-5 text-left hover:bg-surface-2/50 transition-colors">
710
+ <span className="font-semibold text-fg pr-4">{faq.q}</span>
711
+ <Icon name={openIndex === i ? 'minus' : 'plus'} size={20} className="text-muted shrink-0" />
712
+ </button>
713
+ <div className={`faq-content ${openIndex === i ? 'open' : ''}`}>
714
+ <div><p className="px-5 pb-5 text-sm text-muted leading-relaxed">{faq.a}</p></div>
715
+ </div>
716
+ </div>
717
+ ))}
718
+ </div>
719
+ </div>
720
+ </section>
721
+ );
722
+ };
723
+
724
+ const CTA = () => (
725
+ <section className="py-24 relative overflow-hidden">
726
+ <div className="absolute inset-0 grid-pattern opacity-20 pointer-events-none" />
727
+ <div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[800px] h-[800px] bg-primary/10 rounded-full blur-[200px] pointer-events-none" />
728
+ <div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 relative z-10 text-center reveal">
729
+ <h2 className="text-3xl md:text-5xl font-bold mb-6">Ready to Create <span className="gradient-text">Without Limits</span>?</h2>
730
+ <p className="text-muted text-lg max-w-2xl mx-auto mb-10">Join 2.8 million creators who are already building the future with AI. Start free, no credit card required.</p>
731
+ <div className="flex flex-col sm:flex-row items-center justify-center gap-4 mb-8">
732
+ <input type="email" placeholder="Enter your email" className="w-full sm:w-auto flex-1 max-w-md px-5 py-4 rounded-xl bg-surface border border-border text-fg placeholder:text-muted focus:outline-none focus:ring-2 focus:ring-primary/50 focus:border-primary/50 transition-all text-base" />
733
+ <a href="signin.html" className="group inline-flex items-center justify-center gap-2.5 px-8 py-4 rounded-xl bg-primary text-primary-foreground font-semibold hover:brightness-110 transition-all shadow-xl shadow-primary/25 hover:shadow-primary/40 whitespace-nowrap">
734
+ Start Creating <Icon name="arrow-right" size={18} className="group-hover:translate-x-1 transition-transform" />
735
+ </a>
736
+ </div>
737
+ <div className="flex flex-wrap items-center justify-center gap-6 text-sm text-muted">
738
+ {['No credit card required', 'Free tier available', 'Cancel anytime'].map((text, i) => (
739
+ <span key={i} className="flex items-center gap-1.5"><Icon name="check-circle" size={16} className="text-success" />{text}</span>
740
+ ))}
741
+ </div>
742
+ </div>
743
+ </section>
744
+ );
745
+
746
+ const Footer = () => {
747
+ const columns = [
748
+ { title: 'Platform', links: ['Studio', 'Models', 'Agents', 'Workflows', 'Marketplace', 'Pricing'], hrefs: ['generator.html', 'models.html', 'dashboard.html', 'workflows.html', 'marketplace.html', '#pricing'] },
749
+ { title: 'Resources', links: ['Documentation', 'API Reference', 'Cookbook', 'Guides', 'Blog', 'Changelog'], hrefs: ['#', '#', '#', '#', '#', '#'] },
750
+ { title: 'Company', links: ['About Us', 'Careers', 'Contact', 'Partners', 'Brand Kit', 'Press'], hrefs: ['#', '#', '#', '#', '#', '#'] },
751
+ { title: 'Legal', links: ['Terms of Service', 'Privacy Policy', 'Acceptable Use', 'Content Policy', 'DMCA', 'Cookie Settings'], hrefs: ['#', '#', '#', '#', '#', '#'] },
752
+ ];
753
+ return (
754
+ <footer className="pt-20 pb-10 border-t border-border bg-[oklch(0.04_0.005_285)]">
755
+ <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
756
+ <div className="grid grid-cols-2 md:grid-cols-4 lg:grid-cols-6 gap-8 mb-16">
757
+ <div className="col-span-2">
758
+ <a href="#" className="flex items-center gap-2.5 mb-4">
759
+ <div className="w-8 h-8 rounded-lg bg-primary flex items-center justify-center"><Icon name="sparkles" size={16} className="text-primary-foreground" /></div>
760
+ <span className="text-lg font-bold tracking-tight">NSFW<span className="text-muted">Studio</span></span>
761
+ </a>
762
+ <p className="text-sm text-muted mb-6 max-w-xs leading-relaxed">The ultimate AI platform for creators. Build, automate, and monetize without limits.</p>
763
+ <div className="mb-6">
764
+ <p className="text-sm font-medium text-fg mb-3">Stay in the loop</p>
765
+ <div className="flex gap-2">
766
+ <input type="email" placeholder="you@example.com" className="flex-1 px-4 py-2.5 rounded-lg bg-surface-2 border border-border text-sm text-fg placeholder:text-muted focus:outline-none focus:ring-2 focus:ring-primary/50 focus:border-primary/50 transition-all min-w-0" />
767
+ <button className="px-4 py-2.5 rounded-lg bg-primary text-primary-foreground text-sm font-semibold hover:brightness-110 transition-all shrink-0">Subscribe</button>
768
+ </div>
769
+ </div>
770
+ <div className="flex gap-3">
771
+ {[{ name: 'github' }, { name: 'twitter' }, { name: 'youtube' }, { name: 'instagram' }].map((s) => (
772
+ <a key={s.name} href="#" className="w-9 h-9 rounded-lg bg-surface-2 flex items-center justify-center text-muted hover:text-fg hover:bg-surface-3 transition-colors border border-border"><Icon name={s.name} size={16} /></a>
773
+ ))}
774
+ </div>
775
+ </div>
776
+ {columns.map((col, i) => (
777
+ <div key={i}>
778
+ <h4 className="font-semibold text-fg mb-4 text-sm">{col.title}</h4>
779
+ <ul className="space-y-2.5">{col.links.map((link, j) => <li key={j}><a href={col.hrefs[j]} className="text-sm text-muted hover:text-fg transition-colors">{link}</a></li>)}</ul>
780
+ </div>
781
+ ))}
782
+ </div>
783
+ <div className="flex flex-col md:flex-row items-center justify-between pt-8 border-t border-border/50 gap-4">
784
+ <div className="flex flex-col sm:flex-row items-center gap-4 sm:gap-6 text-xs text-muted">
785
+ <span>© 2025 NSFWStudio. All rights reserved.</span>
786
+ <span className="hidden sm:inline text-border">·</span>
787
+ <span>18 U.S.C. § 2257 Compliance</span>
788
+ </div>
789
+ <div className="flex items-center gap-2 text-xs text-muted"><span className="w-2 h-2 rounded-full bg-success" /> All Systems Operational</div>
790
+ </div>
791
+ </div>
792
+ </footer>
793
+ );
794
+ };
795
+
796
+ const App = () => {
797
+ useScrollReveal();
798
+ return (
799
+ <div className="min-h-screen bg-bg text-fg overflow-x-hidden">
800
+ <TopBar />
801
+ <ScrollProgress />
802
+ <Navbar />
803
+ <main>
804
+ <Hero />
805
+ <TrustedBy />
806
+ <HowItWorks />
807
+ <Features />
808
+ <NumberStats />
809
+ <LiveActivity />
810
+ <TopCreators />
811
+ <Pricing />
812
+ <Testimonials />
813
+ <FAQ />
814
+ <CTA />
815
+ </main>
816
+ <Footer />
817
+ <BackToTop />
818
+ </div>
819
+ );
820
+ };
821
+
822
+ ReactDOM.createRoot(document.getElementById('root')).render(<App />);
823
+ </script>
824
+ <script src="https://deepsite.hf.co/deepsite-badge.js"></script>
825
+ </body>
826
+ </html>
marketplace.html ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Marketplace — NSFWStudio</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <script src="https://unpkg.com/lucide@latest"></script>
9
+ <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
10
+ <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
11
+ <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
12
+ <link rel="preconnect" href="https://fonts.googleapis.com">
13
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
14
+ <link href="https://fonts.googleapis.com/css2?family=Inter:opsz,wght@14..32,300..800&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
15
+ <script>
16
+ tailwind.config = { theme: { extend: { fontFamily: { sans: ['Inter','system-ui','sans-serif'], mono: ['JetBrains Mono','monospace'] }, colors: { bg: 'oklch(0.07 0.006 285)', surface: 'oklch(0.12 0.02 285)', 'surface-2': 'oklch(0.16 0.025 285)', 'surface-3': 'oklch(0.20 0.028 285)', fg: 'oklch(0.97 0.005 285)', muted: 'oklch(0.55 0.02 285)', primary: 'oklch(0.70 0.28 350)', 'primary-foreground': 'oklch(0.98 0.005 285)', secondary: 'oklch(0.75 0.15 215)', accent: 'oklch(0.80 0.18 85)', border: 'oklch(0.22 0.02 285)', ring: 'oklch(0.70 0.28 350)', destructive: 'oklch(0.55 0.22 25)', success: 'oklch(0.65 0.2 145)' } } } }
17
+ </script>
18
+ <style>
19
+ body { background-color: oklch(0.07 0.006 285); color: oklch(0.97 0.005 285); font-family: 'Inter', system-ui, sans-serif; -webkit-font-smoothing: antialiased; }
20
+ .glass { background: oklch(0.14 0.015 285 / 0.6); backdrop-filter: blur(24px) saturate(1.2); -webkit-backdrop-filter: blur(24px) saturate(1.2); border: 1px solid oklch(0.25 0.02 285 / 0.5); }
21
+ .gradient-text { background: linear-gradient(135deg, oklch(0.70 0.28 350), oklch(0.75 0.15 215)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; }
22
+ ::selection { background: oklch(0.70 0.28 350 / 0.3); color: white; }
23
+ body::after { content:''; position:fixed; inset:0; pointer-events:none; z-index:9999; opacity:0.025; background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); background-repeat:repeat; background-size:256px 256px; }
24
+ .no-scrollbar::-webkit-scrollbar { display: none; } .no-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }
25
+ .tabular-nums { font-variant-numeric: tabular-nums; }
26
+ </style>
27
+ </head>
28
+ <body class="antialiased">
29
+ <div id="root"></div>
30
+ <script type="text/babel">
31
+ const { useState } = React;
32
+ const Icon = ({ name, size = 20, className = "", strokeWidth = 2 }) => {
33
+ const ref = React.useRef(null);
34
+ React.useEffect(() => { if (ref.current) { const existing = ref.current.querySelector('svg'); if (existing) existing.remove(); const svg = lucide.createElement(lucide.icons[name]); if (svg) { svg.setAttribute('width',size); svg.setAttribute('height',size); svg.setAttribute('stroke-width',strokeWidth); ref.current.appendChild(svg); } } }, [name, size, className, strokeWidth]);
35
+ return <span ref={ref} className={`inline-flex items-center justify-center ${className}`} style={{ width: size, height: size }} />;
36
+ };
37
+
38
+ const navItems = [
39
+ { name: 'Dashboard', icon: 'layout-dashboard', href: 'dashboard.html' },
40
+ { name: 'Generator', icon: 'sparkles', href: 'generator.html' },
41
+ { name: 'Playground', icon: 'code', href: 'playground.html' },
42
+ { name: 'Models', icon: 'box', href: 'models.html' },
43
+ { name: 'Workflows', icon: 'workflow', href: 'workflows.html' },
44
+ { name: 'Marketplace', icon: 'shopping-bag', href: 'marketplace.html', active: true },
45
+ { name: 'API Keys', icon: 'key', href: 'api-keys.html' },
46
+ { divider: true },
47
+ { name: 'Profile', icon: 'user', href: 'profile.html' },
48
+ { name: 'Settings', icon: 'settings', href: 'settings.html' },
49
+ ];
50
+
51
+ const Sidebar = ({ isOpen, setIsOpen }) => (
52
+ <>
53
+ <div className={`fixed inset-0 z-40 lg:hidden transition-all ${isOpen ? 'opacity-100 pointer-events-auto' : 'opacity-0 pointer-events-none'}`}>
54
+ <div className="absolute inset-0 bg-black/60 backdrop-blur-sm" onClick={() => setIsOpen(false)} />
55
+ </div>
56
+ <aside className={`fixed top-0 left-0 bottom-0 z-50 w-64 bg-surface border-r border-border flex flex-col transition-transform duration-300 lg:translate-x-0 ${isOpen ? 'translate-x-0' : '-translate-x-full'}`}>
57
+ <div className="p-4 flex items-center gap-2.5 border-b border-border">
58
+ <div className="w-8 h-8 rounded-lg bg-primary flex items-center justify-center"><Icon name="sparkles" size={16} className="text-primary-foreground" /></div>
59
+ <span className="text-lg font-bold tracking-tight">NSFW<span className="text-muted">Studio</span></span>
60
+ </div>
61
+ <nav className="flex-1 p-3 space-y-1 overflow-y-auto no-scrollbar">
62
+ {navItems.map((item, i) => item.divider ? <div key={i} className="my-3 border-t border-border" /> : (
63
+ <a key={i} href={item.href} className={`flex items-center gap-3 px-3 py-2.5 rounded-xl text-sm font-medium transition-colors ${item.active ? 'bg-primary/10 text-primary border border-primary/20' : 'text-muted hover:text-fg hover:bg-surface-2 border border-transparent'}`}><Icon name={item.icon} size={18} />{item.name}</a>
64
+ ))}
65
+ </nav>
66
+ <div className="p-4 border-t border-border">
67
+ <a href="documentation.html" className="flex items-center gap-3 px-3 py-2.5 rounded-xl text-sm text-muted hover:text-fg hover:bg-surface-2 transition-colors"><Icon name="book-open" size={18} />Documentation</a>
68
+ <a href="api-reference.html" className="flex items-center gap-3 px-3 py-2.5 rounded-xl text-sm text-muted hover:text-fg hover:bg-surface-2 transition-colors"><Icon name="file-code" size={18} />API Reference</a>
69
+ </div>
70
+ </aside>
71
+ </>
72
+ );
73
+
74
+ const App = () => {
75
+ const [sidebarOpen, setSidebarOpen] = useState(false);
76
+ const [activeTab, setActiveTab] = useState('All');
77
+ const tabs = ['All', 'Models', 'Agents', 'Prompts', 'Workflows', 'Templates'];
78
+
79
+ const items = [
80
+ { name: 'DreamVision XL', author: '@neon_dreamer', price: '$9.99', rating: 4.9, reviews: '2.4K', category: 'Models', downloads: '45.2K', img: 'http://static.photos/cyberpunk/400x300/10', hot: true },
81
+ { name: 'CyberPunk v3', author: '@ai_architect', price: '$4.99', rating: 4.8, reviews: '1.8K', category: 'Models', downloads: '28.1K', img: 'http://static.photos/technology/400x300/11', hot: false },
82
+ { name: 'Auto Tagger Agent', author: '@prompt_master', price: 'Free', rating: 4.7, reviews: '892', category: 'Agents', downloads: '12.3K', img: 'http://static.photos/abstract/400x300/12', hot: false },
83
+ { name: 'Anime Diffusion', author: '@creative_chaos', price: '$7.99', rating: 4.9, reviews: '3.1K', category: 'Models', downloads: '52K', img: 'http://static.photos/people/400x300/13', hot: true },
84
+ { name: 'Smart Prompt Pack', author: '@luna_vfx', price: '$2.99', rating: 4.6, reviews: '456', category: 'Prompts', downloads: '8.2K', img: 'http://static.photos/minimal/400x300/14', hot: false },
85
+ { name: 'Batch Processor', author: '@digital_ghost', price: 'Free', rating: 4.5, reviews: '234', category: 'Workflows', downloads: '5.1K', img: 'http://static.photos/workspace/400x300/15', hot: false },
86
+ { name: 'Fantasy Art XL', author: '@galactic_prompt', price: '$5.99', rating: 4.8, reviews: '1.2K', category: 'Models', downloads: '19.4K', img: 'http://static.photos/nature/400x300/16', hot: false },
87
+ { name: 'Content Filter Agent', author: '@dark_pixel', price: 'Free', rating: 4.4, reviews: '178', category: 'Agents', downloads: '3.7K', img: 'http://static.photos/red/400x300/17', hot: false },
88
+ { name: 'Photo Real v2', author: '@echo_nova', price: '$14.99', rating: 4.9, reviews: '4.2K', category: 'Models', downloads: '67K', img: 'http://static.photos/travel/400x300/18', hot: true },
89
+ ];
90
+
91
+ const filtered = activeTab === 'All' ? items : items.filter(i => i.category === activeTab);
92
+
93
+ return (
94
+ <div className="min-h-screen bg-bg">
95
+ <Sidebar isOpen={sidebarOpen} setIsOpen={setSidebarOpen} />
96
+ <div className="lg:ml-64">
97
+ <header className="sticky top-0 z-30 glass border-b border-border">
98
+ <div className="flex items-center justify-between px-4 sm:px-6 h-16">
99
+ <div className="flex items-center gap-4">
100
+ <button onClick={() => setSidebarOpen(true)} className="lg:hidden p-2 rounded-lg hover:bg-surface-2 text-muted"><Icon name="menu" size={20} /></button>
101
+ <h1 className="text-xl font-bold">Marketplace</h1>
102
+ </div>
103
+ <div className="flex items-center gap-3">
104
+ <div className="hidden sm:flex items-center gap-2 px-4 py-2 rounded-xl bg-surface-2 border border-border text-muted text-sm w-64">
105
+ <Icon name="search" size={16} /><span>Search marketplace...</span>
106
+ </div>
107
+ <button className="p-2 rounded-lg hover:bg-surface-2 text-muted relative"><Icon name="bell" size={20} /><span className="absolute top-1.5 right-1.5 w-2 h-2 rounded-full bg-primary" /></button>
108
+ <a href="profile.html" className="w-9 h-9 rounded-lg overflow-hidden border border-border"><img src="http://static.photos/people/100x100/10" alt="" className="w-full h-full object-cover" /></a>
109
+ </div>
110
+ </div>
111
+ </header>
112
+
113
+ <main className="p-4 sm:p-6 lg:p-8">
114
+ {/* Hero Banner */}
115
+ <div className="relative rounded-2xl overflow-hidden mb-8 p-8 lg:p-12 bg-surface border border-border">
116
+ <div className="absolute inset-0 opacity-20"><img src="http://static.photos/cyberpunk/1200x400/1" alt="" className="w-full h-full object-cover" /><div className="absolute inset-0 bg-gradient-to-r from-bg via-bg/80 to-transparent" /></div>
117
+ <div className="relative z-10 max-w-lg">
118
+ <span className="inline-flex items-center gap-1.5 px-3 py-1 rounded-full bg-primary/20 border border-primary/30 text-primary text-xs font-semibold mb-4"><Icon name="zap" size={12} /> Featured</span>
119
+ <h2 className="text-2xl lg:text-3xl font-bold mb-3">Discover & Sell AI <span className="gradient-text">Creations</span></h2>
120
+ <p className="text-muted mb-6">Browse thousands of models, agents, prompts, and workflows from top creators.</p>
121
+ <div className="flex gap-3">
122
+ <a href="#" className="px-6 py-3 rounded-xl bg-primary text-primary-foreground font-semibold hover:brightness-110 transition-all">Sell Your Work</a>
123
+ <a href="#" className="px-6 py-3 rounded-xl border border-border text-fg font-semibold hover:bg-surface-2 transition-colors">Learn More</a>
124
+ </div>
125
+ </div>
126
+ </div>
127
+
128
+ {/* Tabs */}
129
+ <div className="flex items-center gap-2 mb-6 overflow-x-auto no-scrollbar pb-1">
130
+ {tabs.map(tab => (
131
+ <button key={tab} onClick={() => setActiveTab(tab)} className={`px-4 py-2 rounded-lg text-sm font-medium whitespace-nowrap transition-colors ${activeTab === tab ? 'bg-primary text-primary-foreground' : 'text-muted hover:text-fg hover:bg-surface-2'}`}>{tab}</button>
132
+ ))}
133
+ </div>
134
+
135
+ {/* Grid */}
136
+ <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
137
+ {filtered.map((item, i) => (
138
+ <div key={i} className="group rounded-2xl bg-surface border border-border hover:border-surface-3 overflow-hidden transition-all hover:-translate-y-0.5">
139
+ <div className="relative aspect-[4/3] overflow-hidden">
140
+ <img src={item.img} alt={item.name} className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-700" />
141
+ <div className="absolute inset-0 bg-gradient-to-t from-black/60 to-transparent" />
142
+ {item.hot && <span className="absolute top-3 left-3 px-2.5 py-1 rounded-lg bg-primary text-primary-foreground text-xs font-bold flex items-center gap-1"><Icon name="flame" size={12} /> Hot</span>}
143
+ <span className="absolute top-3 right-3 px-2.5 py-1 rounded-lg bg-black/50 backdrop-blur-sm text-xs font-medium text-fg border border-white/10">{item.category}</span>
144
+ </div>
145
+ <div className="p-4">
146
+ <div className="flex items-start justify-between gap-2 mb-2">
147
+ <div>
148
+ <h3 className="font-semibold text-fg">{item.name}</h3>
149
+ <p className="text-xs text-muted">{item.author}</p>
150
+ </div>
151
+ <span className="text-sm font-bold text-primary whitespace-nowrap">{item.price}</span>
152
+ </div>
153
+ <div className="flex items-center justify-between text-xs text-muted">
154
+ <div className="flex items-center gap-1"><Icon name="star" size={12} className="text-accent" /> <span className="text-fg">{item.rating}</span> ({item.reviews})</div>
155
+ <div className="flex items-center gap-1"><Icon name="download" size={12} /> {item.downloads}</div>
156
+ </div>
157
+ </div>
158
+ </div>
159
+ ))}
160
+ </div>
161
+ </main>
162
+ </div>
163
+ </div>
164
+ );
165
+ };
166
+ ReactDOM.createRoot(document.getElementById('root')).render(<App />);
167
+ </script>
168
+ </body>
169
+ </html>
models.html ADDED
@@ -0,0 +1,183 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Models — NSFWStudio</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <script src="https://unpkg.com/lucide@latest"></script>
9
+ <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
10
+ <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
11
+ <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
12
+ <link rel="preconnect" href="https://fonts.googleapis.com">
13
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
14
+ <link href="https://fonts.googleapis.com/css2?family=Inter:opsz,wght@14..32,300..800&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
15
+ <script>
16
+ tailwind.config = { theme: { extend: { fontFamily: { sans: ['Inter','system-ui','sans-serif'], mono: ['JetBrains Mono','monospace'] }, colors: { bg: 'oklch(0.07 0.006 285)', surface: 'oklch(0.12 0.02 285)', 'surface-2': 'oklch(0.16 0.025 285)', 'surface-3': 'oklch(0.20 0.028 285)', fg: 'oklch(0.97 0.005 285)', muted: 'oklch(0.55 0.02 285)', primary: 'oklch(0.70 0.28 350)', 'primary-foreground': 'oklch(0.98 0.005 285)', secondary: 'oklch(0.75 0.15 215)', accent: 'oklch(0.80 0.18 85)', border: 'oklch(0.22 0.02 285)', ring: 'oklch(0.70 0.28 350)', destructive: 'oklch(0.55 0.22 25)', success: 'oklch(0.65 0.2 145)' } } } }
17
+ </script>
18
+ <style>
19
+ body { background-color: oklch(0.07 0.006 285); color: oklch(0.97 0.005 285); font-family: 'Inter', system-ui, sans-serif; -webkit-font-smoothing: antialiased; }
20
+ .glass { background: oklch(0.14 0.015 285 / 0.6); backdrop-filter: blur(24px) saturate(1.2); -webkit-backdrop-filter: blur(24px) saturate(1.2); border: 1px solid oklch(0.25 0.02 285 / 0.5); }
21
+ ::selection { background: oklch(0.70 0.28 350 / 0.3); }
22
+ body::after { content:''; position:fixed; inset:0; pointer-events:none; z-index:9999; opacity:0.025; background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); background-repeat:repeat; background-size:256px 256px; }
23
+ .no-scrollbar::-webkit-scrollbar { display: none; } .no-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }
24
+ .tabular-nums { font-variant-numeric: tabular-nums; }
25
+ </style>
26
+ </head>
27
+ <body class="antialiased">
28
+ <div id="root"></div>
29
+ <script type="text/babel">
30
+ const { useState } = React;
31
+ const Icon = ({ name, size = 20, className = "", strokeWidth = 2 }) => {
32
+ const ref = React.useRef(null);
33
+ React.useEffect(() => { if (ref.current) { const existing = ref.current.querySelector('svg'); if (existing) existing.remove(); const svg = lucide.createElement(lucide.icons[name]); if (svg) { svg.setAttribute('width',size); svg.setAttribute('height',size); svg.setAttribute('stroke-width',strokeWidth); ref.current.appendChild(svg); } } }, [name, size, className, strokeWidth]);
34
+ return <span ref={ref} className={`inline-flex items-center justify-center ${className}`} style={{ width: size, height: size }} />;
35
+ };
36
+
37
+ const navItems = [
38
+ { name: 'Dashboard', icon: 'layout-dashboard', href: 'dashboard.html' },
39
+ { name: 'Generator', icon: 'sparkles', href: 'generator.html' },
40
+ { name: 'Playground', icon: 'code', href: 'playground.html' },
41
+ { name: 'Models', icon: 'box', href: 'models.html', active: true },
42
+ { name: 'Workflows', icon: 'workflow', href: 'workflows.html' },
43
+ { name: 'Marketplace', icon: 'shopping-bag', href: 'marketplace.html' },
44
+ { name: 'API Keys', icon: 'key', href: 'api-keys.html' },
45
+ { divider: true },
46
+ { name: 'Profile', icon: 'user', href: 'profile.html' },
47
+ { name: 'Settings', icon: 'settings', href: 'settings.html' },
48
+ ];
49
+
50
+ const Sidebar = ({ isOpen, setIsOpen }) => (
51
+ <>
52
+ <div className={`fixed inset-0 z-40 lg:hidden transition-all ${isOpen ? 'opacity-100 pointer-events-auto' : 'opacity-0 pointer-events-none'}`}>
53
+ <div className="absolute inset-0 bg-black/60 backdrop-blur-sm" onClick={() => setIsOpen(false)} />
54
+ </div>
55
+ <aside className={`fixed top-0 left-0 bottom-0 z-50 w-64 bg-surface border-r border-border flex flex-col transition-transform duration-300 lg:translate-x-0 ${isOpen ? 'translate-x-0' : '-translate-x-full'}`}>
56
+ <div className="p-4 flex items-center gap-2.5 border-b border-border"><div className="w-8 h-8 rounded-lg bg-primary flex items-center justify-center"><Icon name="sparkles" size={16} className="text-primary-foreground" /></div><span className="text-lg font-bold tracking-tight">NSFW<span className="text-muted">Studio</span></span></div>
57
+ <nav className="flex-1 p-3 space-y-1 overflow-y-auto no-scrollbar">{navItems.map((item, i) => item.divider ? <div key={i} className="my-3 border-t border-border" /> : <a key={i} href={item.href} className={`flex items-center gap-3 px-3 py-2.5 rounded-xl text-sm font-medium transition-colors ${item.active ? 'bg-primary/10 text-primary border border-primary/20' : 'text-muted hover:text-fg hover:bg-surface-2 border border-transparent'}`}><Icon name={item.icon} size={18} />{item.name}</a>)}</nav>
58
+ <div className="p-4 border-t border-border"><a href="documentation.html" className="flex items-center gap-3 px-3 py-2.5 rounded-xl text-sm text-muted hover:text-fg hover:bg-surface-2 transition-colors"><Icon name="book-open" size={18} />Documentation</a><a href="api-reference.html" className="flex items-center gap-3 px-3 py-2.5 rounded-xl text-sm text-muted hover:text-fg hover:bg-surface-2 transition-colors"><Icon name="file-code" size={18} />API Reference</a></div>
59
+ </aside>
60
+ </>
61
+ );
62
+
63
+ const App = () => {
64
+ const [sidebarOpen, setSidebarOpen] = useState(false);
65
+ const [activeTab, setActiveTab] = useState('my-models');
66
+ const [viewMode, setViewMode] = useState('grid');
67
+
68
+ const myModels = [
69
+ { name: 'DreamVision XL', type: 'Image Generation', status: 'published', runs: '45.2K', rating: 4.9, revenue: '$2,340', updated: '2 days ago', img: 'http://static.photos/cyberpunk/400x300/20' },
70
+ { name: 'CyberPunk v3', type: 'Image Generation', status: 'published', runs: '28.1K', rating: 4.8, revenue: '$1,890', updated: '1 week ago', img: 'http://static.photos/technology/400x300/21' },
71
+ { name: 'MorphGAN v2', type: 'Style Transfer', status: 'draft', runs: '0', rating: '-', revenue: '$0', updated: '3 days ago', img: 'http://static.photos/abstract/400x300/22' },
72
+ { name: 'Photo Enhancer Pro', type: 'Upscaling', status: 'review', runs: '12.8K', rating: 4.7, revenue: '$890', updated: '5 days ago', img: 'http://static.photos/nature/400x300/23' },
73
+ ];
74
+
75
+ const exploreModels = [
76
+ { name: 'Anime Diffusion', type: 'Image Generation', author: '@anime_king', runs: '52K', rating: 4.9, price: '$7.99', img: 'http://static.photos/people/400x300/24' },
77
+ { name: 'Photo Real v2', type: 'Photorealistic', author: '@real_photo', runs: '67K', rating: 4.9, price: '$14.99', img: 'http://static.photos/travel/400x300/25' },
78
+ { name: 'Fantasy Art XL', type: 'Fantasy', author: '@fantasy_art', runs: '19.4K', rating: 4.8, price: '$5.99', img: 'http://static.photos/nature/400x300/26' },
79
+ { name: 'Ink & Wash', type: 'Art Style', author: '@ink_master', runs: '15.3K', rating: 4.7, price: 'Free', img: 'http://static.photos/minimal/400x300/27' },
80
+ { name: 'FutureCosmos', type: 'Sci-Fi', author: '@cosmic_ai', runs: '8.7K', rating: 4.6, price: '$3.99', img: 'http://static.photos/aerial/400x300/28' },
81
+ { name: 'Vintagify', type: 'Style Transfer', author: '@retro_vibes', runs: '22.1K', rating: 4.8, price: 'Free', img: 'http://static.photos/vintage/400x300/29' },
82
+ ];
83
+
84
+ const statusColors = { published: 'bg-success/10 text-success border-success/20', draft: 'bg-muted/10 text-muted border-border', review: 'bg-accent/10 text-accent border-accent/20' };
85
+
86
+ return (
87
+ <div className="min-h-screen bg-bg">
88
+ <Sidebar isOpen={sidebarOpen} setIsOpen={setSidebarOpen} />
89
+ <div className="lg:ml-64">
90
+ <header className="sticky top-0 z-30 glass border-b border-border">
91
+ <div className="flex items-center justify-between px-4 sm:px-6 h-16">
92
+ <div className="flex items-center gap-4">
93
+ <button onClick={() => setSidebarOpen(true)} className="lg:hidden p-2 rounded-lg hover:bg-surface-2 text-muted"><Icon name="menu" size={20} /></button>
94
+ <h1 className="text-xl font-bold">Models</h1>
95
+ </div>
96
+ <div className="flex items-center gap-3">
97
+ <div className="hidden sm:flex items-center gap-2 px-3 py-2 rounded-xl bg-surface-2 border border-border text-muted text-sm w-56"><Icon name="search" size={16} /><span>Search models...</span></div>
98
+ <a href="#" className="px-4 py-2 rounded-lg bg-primary text-primary-foreground text-sm font-semibold hover:brightness-110 transition-all flex items-center gap-2"><Icon name="plus" size={16} />Train Model</a>
99
+ <a href="profile.html" className="w-9 h-9 rounded-lg overflow-hidden border border-border"><img src="http://static.photos/people/100x100/10" alt="" className="w-full h-full object-cover" /></a>
100
+ </div>
101
+ </div>
102
+ </header>
103
+
104
+ <main className="p-4 sm:p-6 lg:p-8">
105
+ {/* Tabs */}
106
+ <div className="flex items-center gap-2 mb-6 border-b border-border">
107
+ {[{ id: 'my-models', label: 'My Models' }, { id: 'explore', label: 'Explore' }, { id: 'training', label: 'Training' }].map(t => (
108
+ <button key={t.id} onClick={() => setActiveTab(t.id)} className={`px-4 py-3 border-b-2 text-sm font-medium transition-colors -mb-px ${activeTab === t.id ? 'border-primary text-primary' : 'border-transparent text-muted hover:text-fg'}`}>{t.label}</button>
109
+ ))}
110
+ </div>
111
+
112
+ {activeTab === 'my-models' && (
113
+ <div className="space-y-4">
114
+ {myModels.map((m, i) => (
115
+ <div key={i} className="group rounded-2xl bg-surface border border-border hover:border-surface-3 transition-all overflow-hidden">
116
+ <div className="flex flex-col sm:flex-row">
117
+ <div className="sm:w-48 h-32 sm:h-auto shrink-0 overflow-hidden">
118
+ <img src={m.img} alt={m.name} className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-700" />
119
+ </div>
120
+ <div className="flex-1 p-5">
121
+ <div className="flex items-start justify-between gap-3 mb-3">
122
+ <div>
123
+ <div className="flex items-center gap-2 mb-1">
124
+ <h3 className="font-semibold text-fg">{m.name}</h3>
125
+ <span className={`px-2.5 py-0.5 rounded-full text-xs font-semibold border ${statusColors[m.status]}`}>{m.status}</span>
126
+ </div>
127
+ <p className="text-sm text-muted">{m.type}</p>
128
+ </div>
129
+ <div className="text-right">
130
+ <div className="text-lg font-bold text-fg tabular-nums">{m.revenue}</div>
131
+ <div className="text-xs text-muted">Revenue</div>
132
+ </div>
133
+ </div>
134
+ <div className="flex items-center gap-6 text-sm text-muted">
135
+ <span className="flex items-center gap-1"><Icon name="play" size={14} />{m.runs} runs</span>
136
+ <span className="flex items-center gap-1"><Icon name="star" size={14} className="text-accent" />{m.rating}</span>
137
+ <span className="flex items-center gap-1"><Icon name="clock" size={14} />{m.updated}</span>
138
+ </div>
139
+ <div className="flex items-center gap-2 mt-4">
140
+ <button className="px-3 py-1.5 rounded-lg bg-primary text-primary-foreground text-sm font-medium hover:brightness-110 transition-all">Manage</button>
141
+ <button className="px-3 py-1.5 rounded-lg border border-border text-sm text-muted hover:text-fg hover:bg-surface-2 transition-colors">Analytics</button>
142
+ <button className="px-3 py-1.5 rounded-lg border border-border text-sm text-muted hover:text-fg hover:bg-surface-2 transition-colors">Edit</button>
143
+ </div>
144
+ </div>
145
+ </div>
146
+ </div>
147
+ ))}
148
+ </div>
149
+ )}
150
+
151
+ {activeTab === 'explore' && (
152
+ <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
153
+ {exploreModels.map((m, i) => (
154
+ <div key={i} className="group rounded-2xl bg-surface border border-border hover:border-surface-3 overflow-hidden transition-all hover:-translate-y-0.5">
155
+ <div className="aspect-[4/3] overflow-hidden relative">
156
+ <img src={m.img} alt={m.name} className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-700" />
157
+ <div className="absolute inset-0 bg-gradient-to-t from-black/60 to-transparent" />
158
+ <span className="absolute top-3 right-3 px-2.5 py-1 rounded-lg bg-black/50 backdrop-blur-sm text-xs font-medium border border-white/10">{m.type}</span>
159
+ </div>
160
+ <div className="p-4">
161
+ <div className="flex items-start justify-between mb-2">
162
+ <div>
163
+ <h3 className="font-semibold text-fg">{m.name}</h3>
164
+ <p className="text-xs text-muted">{m.author}</p>
165
+ </div>
166
+ <span className="text-sm font-bold text-primary">{m.price}</span>
167
+ </div>
168
+ <div className="flex items-center gap-4 text-xs text-muted">
169
+ <span className="flex items-center gap-1"><Icon name="star" size={12} className="text-accent" />{m.rating}</span>
170
+ <span className="flex items-center gap-1"><Icon name="download" size={12} />{m.runs}</span>
171
+ </div>
172
+ </div>
173
+ </div>
174
+ ))}
175
+ </div>
176
+ )}
177
+
178
+ {activeTab === 'training' && (
179
+ <div className="text-center py-16">
180
+ <div className="w-20 h-20 rounded-2xl bg-surface-2 flex items-center justify-center mx-auto mb-4"><Icon name="cpu" size={32} className="text-muted" /></div>
181
+ <h2 className="text-xl font-semibold mb-2">No Active Training</h2>
182
+ <p className="text-muted mb-6 max-w-md mx-auto">Start training a new model by uploading your dataset and configuring your training parameters.</p>
183
+ <a href="#" className="inline-flex items-center gap-2 px-6 py-3 rounded-xl bg-primary text-primary-foreground font-semibold hover:brightness-110 transition-all"><Icon name="plus" size={18} />Start Training</a>
playground.html ADDED
@@ -0,0 +1,191 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Playground — NSFWStudio</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <script src="https://unpkg.com/lucide@latest"></script>
9
+ <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
10
+ <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
11
+ <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
12
+ <link rel="preconnect" href="https://fonts.googleapis.com">
13
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
14
+ <link href="https://fonts.googleapis.com/css2?family=Inter:opsz,wght@14..32,300..800&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
15
+ <script>
16
+ tailwind.config = { theme: { extend: { fontFamily: { sans: ['Inter','system-ui','sans-serif'], mono: ['JetBrains Mono','monospace'] }, colors: { bg: 'oklch(0.07 0.006 285)', surface: 'oklch(0.12 0.02 285)', 'surface-2': 'oklch(0.16 0.025 285)', 'surface-3': 'oklch(0.20 0.028 285)', fg: 'oklch(0.97 0.005 285)', muted: 'oklch(0.55 0.02 285)', primary: 'oklch(0.70 0.28 350)', 'primary-foreground': 'oklch(0.98 0.005 285)', secondary: 'oklch(0.75 0.15 215)', accent: 'oklch(0.80 0.18 85)', border: 'oklch(0.22 0.02 285)', ring: 'oklch(0.70 0.28 350)', destructive: 'oklch(0.55 0.22 25)', success: 'oklch(0.65 0.2 145)' } } } }
17
+ </script>
18
+ <style>
19
+ body { background-color: oklch(0.07 0.006 285); color: oklch(0.97 0.005 285); font-family: 'Inter', system-ui, sans-serif; -webkit-font-smoothing: antialiased; }
20
+ .glass { background: oklch(0.14 0.015 285 / 0.6); backdrop-filter: blur(24px) saturate(1.2); -webkit-backdrop-filter: blur(24px) saturate(1.2); border: 1px solid oklch(0.25 0.02 285 / 0.5); }
21
+ ::selection { background: oklch(0.70 0.28 350 / 0.3); }
22
+ body::after { content:''; position:fixed; inset:0; pointer-events:none; z-index:9999; opacity:0.025; background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); background-repeat:repeat; background-size:256px 256px; }
23
+ .no-scrollbar::-webkit-scrollbar { display: none; } .no-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }
24
+ </style>
25
+ </head>
26
+ <body class="antialiased">
27
+ <div id="root"></div>
28
+ <script type="text/babel">
29
+ const { useState } = React;
30
+ const Icon = ({ name, size = 20, className = "", strokeWidth = 2 }) => {
31
+ const ref = React.useRef(null);
32
+ React.useEffect(() => { if (ref.current) { const existing = ref.current.querySelector('svg'); if (existing) existing.remove(); const svg = lucide.createElement(lucide.icons[name]); if (svg) { svg.setAttribute('width',size); svg.setAttribute('height',size); svg.setAttribute('stroke-width',strokeWidth); ref.current.appendChild(svg); } } }, [name, size, className, strokeWidth]);
33
+ return <span ref={ref} className={`inline-flex items-center justify-center ${className}`} style={{ width: size, height: size }} />;
34
+ };
35
+
36
+ const navItems = [
37
+ { name: 'Dashboard', icon: 'layout-dashboard', href: 'dashboard.html' },
38
+ { name: 'Generator', icon: 'sparkles', href: 'generator.html' },
39
+ { name: 'Playground', icon: 'code', href: 'playground.html', active: true },
40
+ { name: 'Models', icon: 'box', href: 'models.html' },
41
+ { name: 'Workflows', icon: 'workflow', href: 'workflows.html' },
42
+ { name: 'Marketplace', icon: 'shopping-bag', href: 'marketplace.html' },
43
+ { name: 'API Keys', icon: 'key', href: 'api-keys.html' },
44
+ { divider: true },
45
+ { name: 'Profile', icon: 'user', href: 'profile.html' },
46
+ { name: 'Settings', icon: 'settings', href: 'settings.html' },
47
+ ];
48
+
49
+ const Sidebar = ({ isOpen, setIsOpen }) => (
50
+ <>
51
+ <div className={`fixed inset-0 z-40 lg:hidden transition-all ${isOpen ? 'opacity-100 pointer-events-auto' : 'opacity-0 pointer-events-none'}`}>
52
+ <div className="absolute inset-0 bg-black/60 backdrop-blur-sm" onClick={() => setIsOpen(false)} />
53
+ </div>
54
+ <aside className={`fixed top-0 left-0 bottom-0 z-50 w-64 bg-surface border-r border-border flex flex-col transition-transform duration-300 lg:translate-x-0 ${isOpen ? 'translate-x-0' : '-translate-x-full'}`}>
55
+ <div className="p-4 flex items-center gap-2.5 border-b border-border"><div className="w-8 h-8 rounded-lg bg-primary flex items-center justify-center"><Icon name="sparkles" size={16} className="text-primary-foreground" /></div><span className="text-lg font-bold tracking-tight">NSFW<span className="text-muted">Studio</span></span></div>
56
+ <nav className="flex-1 p-3 space-y-1 overflow-y-auto no-scrollbar">{navItems.map((item, i) => item.divider ? <div key={i} className="my-3 border-t border-border" /> : <a key={i} href={item.href} className={`flex items-center gap-3 px-3 py-2.5 rounded-xl text-sm font-medium transition-colors ${item.active ? 'bg-primary/10 text-primary border border-primary/20' : 'text-muted hover:text-fg hover:bg-surface-2 border border-transparent'}`}><Icon name={item.icon} size={18} />{item.name}</a>)}</nav>
57
+ <div className="p-4 border-t border-border"><a href="documentation.html" className="flex items-center gap-3 px-3 py-2.5 rounded-xl text-sm text-muted hover:text-fg hover:bg-surface-2 transition-colors"><Icon name="book-open" size={18} />Documentation</a><a href="api-reference.html" className="flex items-center gap-3 px-3 py-2.5 rounded-xl text-sm text-muted hover:text-fg hover:bg-surface-2 transition-colors"><Icon name="file-code" size={18} />API Reference</a></div>
58
+ </aside>
59
+ </>
60
+ );
61
+
62
+ const App = () => {
63
+ const [sidebarOpen, setSidebarOpen] = useState(false);
64
+ const [selectedModel, setSelectedModel] = useState('DreamVision XL');
65
+ const [prompt, setPrompt] = useState('');
66
+ const [isRunning, setIsRunning] = useState(false);
67
+
68
+ const models = ['DreamVision XL', 'SDXL 1.0', 'CyberPunk v3', 'Anime Diffusion', 'Photo Real v2', 'Fantasy Art XL'];
69
+ const history = [
70
+ { prompt: 'A neon cityscape at night with rain', model: 'DreamVision XL', time: '2 min ago', status: 'success' },
71
+ { prompt: 'Cyberpunk anime girl with glowing eyes', model: 'Anime Diffusion', time: '8 min ago', status: 'success' },
72
+ { prompt: 'Dark forest with mystical creatures', model: 'Fantasy Art XL', time: '15 min ago', status: 'error' },
73
+ { prompt: 'Futuristic soldier in power armor', model: 'SDXL 1.0', time: '22 min ago', status: 'success' },
74
+ ];
75
+
76
+ const handleRun = () => { setIsRunning(true); setTimeout(() => setIsRunning(false), 3000); };
77
+
78
+ return (
79
+ <div className="min-h-screen bg-bg">
80
+ <Sidebar isOpen={sidebarOpen} setIsOpen={setSidebarOpen} />
81
+ <div className="lg:ml-64">
82
+ <header className="sticky top-0 z-30 glass border-b border-border">
83
+ <div className="flex items-center justify-between px-4 sm:px-6 h-16">
84
+ <div className="flex items-center gap-4">
85
+ <button onClick={() => setSidebarOpen(true)} className="lg:hidden p-2 rounded-lg hover:bg-surface-2 text-muted"><Icon name="menu" size={20} /></button>
86
+ <h1 className="text-xl font-bold">API Playground</h1>
87
+ </div>
88
+ <div className="flex items-center gap-3">
89
+ <select className="px-3 py-2 rounded-lg bg-surface-2 border border-border text-sm text-fg" value={selectedModel} onChange={e => setSelectedModel(e.target.value)}>
90
+ {models.map(m => <option key={m} value={m}>{m}</option>)}
91
+ </select>
92
+ <a href="profile.html" className="w-9 h-9 rounded-lg overflow-hidden border border-border"><img src="http://static.photos/people/100x100/10" alt="" className="w-full h-full object-cover" /></a>
93
+ </div>
94
+ </div>
95
+ </header>
96
+
97
+ <div className="flex h-[calc(100vh-64px)]">
98
+ {/* Left Panel - Config */}
99
+ <div className="w-80 border-r border-border flex flex-col overflow-y-auto no-scrollbar hidden md:flex">
100
+ <div className="p-4 border-b border-border">
101
+ <h3 className="font-semibold text-sm mb-3">Parameters</h3>
102
+ <div className="space-y-4">
103
+ <div>
104
+ <label className="text-xs text-muted mb-1.5 block">Model</label>
105
+ <select className="w-full px-3 py-2.5 rounded-xl bg-surface-2 border border-border text-sm text-fg" value={selectedModel} onChange={e => setSelectedModel(e.target.value)}>
106
+ {models.map(m => <option key={m} value={m}>{m}</option>)}
107
+ </select>
108
+ </div>
109
+ {[
110
+ { label: 'Width', value: '1024', id: 'w' },
111
+ { label: 'Height', value: '1024', id: 'h' },
112
+ { label: 'Steps', value: '30', id: 's' },
113
+ ].map(p => (
114
+ <div key={p.id}>
115
+ <label className="text-xs text-muted mb-1.5 block">{p.label}</label>
116
+ <input type="text" defaultValue={p.value} className="w-full px-3 py-2.5 rounded-xl bg-surface-2 border border-border text-sm text-fg focus:outline-none focus:ring-2 focus:ring-primary/50" />
117
+ </div>
118
+ ))}
119
+ <div>
120
+ <label className="text-xs text-muted mb-1.5 block">Guidance Scale</label>
121
+ <input type="range" min="1" max="20" defaultValue="7.5" className="w-full accent-primary" />
122
+ <div className="flex justify-between text-xs text-muted mt-1"><span>1</span><span>7.5</span><span>20</span></div>
123
+ </div>
124
+ <div>
125
+ <label className="text-xs text-muted mb-1.5 block">Seed</label>
126
+ <div className="flex gap-2">
127
+ <input type="text" defaultValue="Random" className="flex-1 px-3 py-2.5 rounded-xl bg-surface-2 border border-border text-sm text-fg focus:outline-none focus:ring-2 focus:ring-primary/50" />
128
+ <button className="px-3 py-2.5 rounded-xl bg-surface-2 border border-border text-muted hover:text-fg transition-colors"><Icon name="shuffle" size={16} /></button>
129
+ </div>
130
+ </div>
131
+ <div>
132
+ <label className="text-xs text-muted mb-1.5 block">Negative Prompt</label>
133
+ <textarea className="w-full px-3 py-2.5 rounded-xl bg-surface-2 border border-border text-sm text-fg focus:outline-none focus:ring-2 focus:ring-primary/50 h-20 resize-none" placeholder="blurry, low quality, watermark..." />
134
+ </div>
135
+ </div>
136
+ </div>
137
+ <div className="p-4">
138
+ <h3 className="font-semibold text-sm mb-3">History</h3>
139
+ <div className="space-y-2">
140
+ {history.map((h, i) => (
141
+ <div key={i} className="p-3 rounded-xl hover:bg-surface-2/50 cursor-pointer transition-colors">
142
+ <div className="flex items-center justify-between mb-1">
143
+ <span className={`w-2 h-2 rounded-full ${h.status === 'success' ? 'bg-success' : 'bg-destructive'}`} />
144
+ <span className="text-xs text-muted">{h.time}</span>
145
+ </div>
146
+ <p className="text-xs text-fg/80 truncate">{h.prompt}</p>
147
+ <p className="text-xs text-muted mt-0.5">{h.model}</p>
148
+ </div>
149
+ ))}
150
+ </div>
151
+ </div>
152
+ </div>
153
+
154
+ {/* Main Content */}
155
+ <div className="flex-1 flex flex-col">
156
+ {/* Code & Result tabs */}
157
+ <div className="flex-1 flex flex-col overflow-hidden">
158
+ <div className="flex items-center gap-1 px-4 pt-4 pb-2">
159
+ <button className="px-4 py-2 rounded-lg text-sm font-medium bg-primary text-primary-foreground">Request</button>
160
+ <button className="px-4 py-2 rounded-lg text-sm font-medium text-muted hover:text-fg hover:bg-surface-2 transition-colors">Response</button>
161
+ <button className="px-4 py-2 rounded-lg text-sm font-medium text-muted hover:text-fg hover:bg-surface-2 transition-colors">cURL</button>
162
+ <button className="px-4 py-2 rounded-lg text-sm font-medium text-muted hover:text-fg hover:bg-surface-2 transition-colors">Python</button>
163
+ </div>
164
+
165
+ <div className="flex-1 px-4">
166
+ <textarea className="w-full h-full min-h-[200px] px-4 py-3 rounded-xl bg-surface border border-border text-sm text-fg font-mono focus:outline-none focus:ring-2 focus:ring-primary/50 resize-none" value={`{\n "model": "${selectedModel}",\n "prompt": "A stunning neon cityscape...",\n "width": 1024,\n "height": 1024,\n "steps": 30,\n "guidance_scale": 7.5,\n "seed": null\n}`} readOnly />
167
+ </div>
168
+ </div>
169
+
170
+ {/* Prompt bar */}
171
+ <div className="p-4 border-t border-border">
172
+ <div className="flex gap-3">
173
+ <div className="flex-1 flex items-center gap-2 px-4 py-3 rounded-xl bg-surface border border-border focus-within:ring-2 focus-within:ring-primary/50">
174
+ <Icon name="terminal" size={18} className="text-muted" />
175
+ <input type="text" value={prompt} onChange={e => setPrompt(e.target.value)} placeholder="Enter your prompt..." className="flex-1 bg-transparent text-fg placeholder:text-muted outline-none text-sm" />
176
+ </div>
177
+ <button onClick={handleRun} disabled={isRunning} className={`px-6 py-3 rounded-xl font-semibold transition-all flex items-center gap-2 ${isRunning ? 'bg-surface-2 border border-border text-muted' : 'bg-primary text-primary-foreground hover:brightness-110 shadow-lg shadow-primary/25'}`}>
178
+ {isRunning ? <><span className="w-4 h-4 border-2 border-muted border-t-transparent rounded-full animate-spin" />Running...</> : <><Icon name="play" size={18} />Run</>}
179
+ </button>
180
+ </div>
181
+ </div>
182
+ </div>
183
+ </div>
184
+ </div>
185
+ </div>
186
+ );
187
+ };
188
+ ReactDOM.createRoot(document.getElementById('root')).render(<App />);
189
+ </script>
190
+ </body>
191
+ </html>
signin.html ADDED
@@ -0,0 +1,180 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Sign In — NSFWStudio</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <script src="https://unpkg.com/lucide@latest"></script>
9
+ <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
10
+ <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
11
+ <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
12
+ <link rel="preconnect" href="https://fonts.googleapis.com">
13
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
14
+ <link href="https://fonts.googleapis.com/css2?family=Inter:opsz,wght@14..32,300..800&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
15
+ <script>
16
+ tailwind.config = {
17
+ theme: {
18
+ extend: {
19
+ fontFamily: { sans: ['Inter','system-ui','sans-serif'], mono: ['JetBrains Mono','monospace'] },
20
+ colors: {
21
+ bg: 'oklch(0.07 0.006 285)', surface: 'oklch(0.12 0.02 285)', 'surface-2': 'oklch(0.16 0.025 285)', 'surface-3': 'oklch(0.20 0.028 285)',
22
+ fg: 'oklch(0.97 0.005 285)', muted: 'oklch(0.55 0.02 285)', primary: 'oklch(0.70 0.28 350)', 'primary-foreground': 'oklch(0.98 0.005 285)',
23
+ secondary: 'oklch(0.75 0.15 215)', accent: 'oklch(0.80 0.18 85)', border: 'oklch(0.22 0.02 285)', ring: 'oklch(0.70 0.28 350)',
24
+ destructive: 'oklch(0.55 0.22 25)', success: 'oklch(0.65 0.2 145)',
25
+ },
26
+ },
27
+ },
28
+ }
29
+ </script>
30
+ <style>
31
+ body { background-color: oklch(0.07 0.006 285); color: oklch(0.97 0.005 285); font-family: 'Inter', system-ui, sans-serif; -webkit-font-smoothing: antialiased; }
32
+ .glass { background: oklch(0.14 0.015 285 / 0.6); backdrop-filter: blur(24px) saturate(1.2); -webkit-backdrop-filter: blur(24px) saturate(1.2); border: 1px solid oklch(0.25 0.02 285 / 0.5); }
33
+ .gradient-text { background: linear-gradient(135deg, oklch(0.70 0.28 350), oklch(0.75 0.15 215)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; }
34
+ ::selection { background: oklch(0.70 0.28 350 / 0.3); color: white; }
35
+ body::after { content:''; position:fixed; inset:0; pointer-events:none; z-index:9999; opacity:0.025; background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); background-repeat:repeat; background-size:256px 256px; }
36
+ </style>
37
+ </head>
38
+ <body class="antialiased">
39
+ <div id="root"></div>
40
+ <script type="text/babel">
41
+ const { useState } = React;
42
+ const Icon = ({ name, size = 20, className = "", strokeWidth = 2 }) => {
43
+ const ref = React.useRef(null);
44
+ React.useEffect(() => {
45
+ if (ref.current) { const existing = ref.current.querySelector('svg'); if (existing) existing.remove(); const svg = lucide.createElement(lucide.icons[name]); if (svg) { svg.setAttribute('width',size); svg.setAttribute('height',size); svg.setAttribute('stroke-width',strokeWidth); ref.current.appendChild(svg); } }
46
+ }, [name, size, className, strokeWidth]);
47
+ return <span ref={ref} className={`inline-flex items-center justify-center ${className}`} style={{ width: size, height: size }} />;
48
+ };
49
+
50
+ const App = () => {
51
+ const [isSignUp, setIsSignUp] = useState(false);
52
+ const [showPassword, setShowPassword] = useState(false);
53
+ const [email, setEmail] = useState('');
54
+ const [password, setPassword] = useState('');
55
+ const [name, setName] = useState('');
56
+
57
+ return (
58
+ <div className="min-h-screen flex">
59
+ {/* Left Panel - Visual */}
60
+ <div className="hidden lg:flex lg:w-1/2 relative overflow-hidden bg-surface items-center justify-center">
61
+ <div className="absolute inset-0">
62
+ <img src="http://static.photos/cyberpunk/1200x630/1" alt="" className="w-full h-full object-cover opacity-40" />
63
+ <div className="absolute inset-0 bg-gradient-to-r from-bg via-bg/60 to-transparent" />
64
+ <div className="absolute inset-0 bg-gradient-to-t from-bg via-transparent to-transparent" />
65
+ </div>
66
+ <div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[600px] h-[600px] bg-primary/20 rounded-full blur-[160px] pointer-events-none" />
67
+ <div className="relative z-10 max-w-md px-12">
68
+ <a href="index.html" className="flex items-center gap-2.5 mb-8">
69
+ <div className="w-10 h-10 rounded-xl bg-primary flex items-center justify-center"><Icon name="sparkles" size={20} className="text-primary-foreground" /></div>
70
+ <span className="text-2xl font-bold tracking-tight">NSFW<span className="text-muted">Studio</span></span>
71
+ </a>
72
+ <h2 className="text-3xl font-bold mb-4 leading-tight">Create <span className="gradient-text">Without Limits</span></h2>
73
+ <p className="text-muted leading-relaxed mb-8">The all-in-one AI platform for creators. Generate images, videos, agents, and workflows — all in one place.</p>
74
+ <div className="flex items-center gap-4">
75
+ {['2.8M+ Creators', '45.8K+ Models', '99.9% Uptime'].map((s, i) => (
76
+ <div key={i} className="glass rounded-xl px-4 py-3">
77
+ <div className="text-sm font-bold text-fg">{s.split(' ')[0]}</div>
78
+ <div className="text-xs text-muted">{s.split(' ').slice(1).join(' ')}</div>
79
+ </div>
80
+ ))}
81
+ </div>
82
+ </div>
83
+ </div>
84
+
85
+ {/* Right Panel - Form */}
86
+ <div className="flex-1 flex items-center justify-center p-6 sm:p-12">
87
+ <div className="w-full max-w-md">
88
+ <div className="lg:hidden flex items-center gap-2.5 mb-10">
89
+ <div className="w-8 h-8 rounded-lg bg-primary flex items-center justify-center"><Icon name="sparkles" size={16} className="text-primary-foreground" /></div>
90
+ <span className="text-lg font-bold tracking-tight">NSFW<span className="text-muted">Studio</span></span>
91
+ </div>
92
+
93
+ <h1 className="text-3xl font-bold mb-2">{isSignUp ? 'Create your account' : 'Welcome back'}</h1>
94
+ <p className="text-muted mb-8">{isSignUp ? 'Start creating for free. No credit card required.' : 'Sign in to continue to your dashboard.'}</p>
95
+
96
+ {/* Social Buttons */}
97
+ <div className="grid grid-cols-3 gap-3 mb-6">
98
+ {[
99
+ { name: 'Google', icon: 'chrome' },
100
+ { name: 'GitHub', icon: 'github' },
101
+ { name: 'Discord', icon: 'message-circle' },
102
+ ].map(p => (
103
+ <button key={p.name} className="flex items-center justify-center gap-2 px-4 py-3 rounded-xl border border-border bg-surface hover:bg-surface-2 transition-colors text-sm font-medium">
104
+ <Icon name={p.icon} size={18} />
105
+ <span className="hidden sm:inline">{p.name}</span>
106
+ </button>
107
+ ))}
108
+ </div>
109
+
110
+ <div className="flex items-center gap-3 mb-6">
111
+ <div className="flex-1 h-px bg-border" />
112
+ <span className="text-xs text-muted uppercase tracking-wider">or</span>
113
+ <div className="flex-1 h-px bg-border" />
114
+ </div>
115
+
116
+ <div className="space-y-4">
117
+ {isSignUp && (
118
+ <div>
119
+ <label className="block text-sm font-medium text-fg mb-2">Full Name</label>
120
+ <div className="relative">
121
+ <div className="absolute left-3.5 top-1/2 -translate-y-1/2 text-muted"><Icon name="user" size={16} /></div>
122
+ <input type="text" value={name} onChange={e => setName(e.target.value)} placeholder="John Doe" className="w-full pl-10 pr-4 py-3 rounded-xl bg-surface border border-border text-fg placeholder:text-muted focus:outline-none focus:ring-2 focus:ring-primary/50 focus:border-primary/50 transition-all" />
123
+ </div>
124
+ </div>
125
+ )}
126
+ <div>
127
+ <label className="block text-sm font-medium text-fg mb-2">Email</label>
128
+ <div className="relative">
129
+ <div className="absolute left-3.5 top-1/2 -translate-y-1/2 text-muted"><Icon name="mail" size={16} /></div>
130
+ <input type="email" value={email} onChange={e => setEmail(e.target.value)} placeholder="you@example.com" className="w-full pl-10 pr-4 py-3 rounded-xl bg-surface border border-border text-fg placeholder:text-muted focus:outline-none focus:ring-2 focus:ring-primary/50 focus:border-primary/50 transition-all" />
131
+ </div>
132
+ </div>
133
+ <div>
134
+ <div className="flex items-center justify-between mb-2">
135
+ <label className="block text-sm font-medium text-fg">Password</label>
136
+ {!isSignUp && <a href="#" className="text-xs text-primary hover:underline">Forgot password?</a>}
137
+ </div>
138
+ <div className="relative">
139
+ <div className="absolute left-3.5 top-1/2 -translate-y-1/2 text-muted"><Icon name="lock" size={16} /></div>
140
+ <input type={showPassword ? 'text' : 'password'} value={password} onChange={e => setPassword(e.target.value)} placeholder="••••••••" className="w-full pl-10 pr-12 py-3 rounded-xl bg-surface border border-border text-fg placeholder:text-muted focus:outline-none focus:ring-2 focus:ring-primary/50 focus:border-primary/50 transition-all" />
141
+ <button type="button" onClick={() => setShowPassword(!showPassword)} className="absolute right-3.5 top-1/2 -translate-y-1/2 text-muted hover:text-fg transition-colors">
142
+ <Icon name={showPassword ? 'eye-off' : 'eye'} size={16} />
143
+ </button>
144
+ </div>
145
+ </div>
146
+
147
+ {isSignUp && (
148
+ <label className="flex items-start gap-3 cursor-pointer">
149
+ <input type="checkbox" className="mt-1 w-4 h-4 rounded border-border bg-surface text-primary focus:ring-primary/50 accent-primary" />
150
+ <span className="text-xs text-muted leading-relaxed">I agree to the <a href="#" className="text-fg underline">Terms of Service</a> and <a href="#" className="text-fg underline">Privacy Policy</a></span>
151
+ </label>
152
+ )}
153
+
154
+ {!isSignUp && (
155
+ <label className="flex items-center gap-3 cursor-pointer">
156
+ <input type="checkbox" className="w-4 h-4 rounded border-border bg-surface text-primary focus:ring-primary/50 accent-primary" />
157
+ <span className="text-sm text-muted">Remember me</span>
158
+ </label>
159
+ )}
160
+
161
+ <button className="w-full py-3.5 rounded-xl bg-primary text-primary-foreground font-semibold hover:brightness-110 transition-all shadow-lg shadow-primary/25 text-base">
162
+ {isSignUp ? 'Create Account' : 'Sign In'}
163
+ </button>
164
+ </div>
165
+
166
+ <p className="text-center text-sm text-muted mt-8">
167
+ {isSignUp ? 'Already have an account?' : "Don't have an account?"}{' '}
168
+ <button onClick={() => setIsSignUp(!isSignUp)} className="text-primary font-medium hover:underline">{isSignUp ? 'Sign in' : 'Sign up'}</button>
169
+ </p>
170
+
171
+ <p className="text-center text-xs text-muted/60 mt-6">By continuing, you agree to our Terms of Service and Privacy Policy.</p>
172
+ </div>
173
+ </div>
174
+ </div>
175
+ );
176
+ };
177
+ ReactDOM.createRoot(document.getElementById('root')).render(<App />);
178
+ </script>
179
+ </body>
180
+ </html>
workflows.html ADDED
@@ -0,0 +1,171 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Workflows — NSFWStudio</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <script src="https://unpkg.com/lucide@latest"></script>
9
+ <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
10
+ <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
11
+ <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
12
+ <link rel="preconnect" href="https://fonts.googleapis.com">
13
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
14
+ <link href="https://fonts.googleapis.com/css2?family=Inter:opsz,wght@14..32,300..800&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
15
+ <script>
16
+ tailwind.config = { theme: { extend: { fontFamily: { sans: ['Inter','system-ui','sans-serif'], mono: ['JetBrains Mono','monospace'] }, colors: { bg: 'oklch(0.07 0.006 285)', surface: 'oklch(0.12 0.02 285)', 'surface-2': 'oklch(0.16 0.025 285)', 'surface-3': 'oklch(0.20 0.028 285)', fg: 'oklch(0.97 0.005 285)', muted: 'oklch(0.55 0.02 285)', primary: 'oklch(0.70 0.28 350)', 'primary-foreground': 'oklch(0.98 0.005 285)', secondary: 'oklch(0.75 0.15 215)', accent: 'oklch(0.80 0.18 85)', border: 'oklch(0.22 0.02 285)', ring: 'oklch(0.70 0.28 350)', destructive: 'oklch(0.55 0.22 25)', success: 'oklch(0.65 0.2 145)' } } } }
17
+ </script>
18
+ <style>
19
+ body { background-color: oklch(0.07 0.006 285); color: oklch(0.97 0.005 285); font-family: 'Inter', system-ui, sans-serif; -webkit-font-smoothing: antialiased; }
20
+ .glass { background: oklch(0.14 0.015 285 / 0.6); backdrop-filter: blur(24px) saturate(1.2); -webkit-backdrop-filter: blur(24px) saturate(1.2); border: 1px solid oklch(0.25 0.02 285 / 0.5); }
21
+ ::selection { background: oklch(0.70 0.28 350 / 0.3); }
22
+ body::after { content:''; position:fixed; inset:0; pointer-events:none; z-index:9999; opacity:0.025; background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); background-repeat:repeat; background-size:256px 256px; }
23
+ .no-scrollbar::-webkit-scrollbar { display: none; } .no-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }
24
+ </style>
25
+ </head>
26
+ <body class="antialiased">
27
+ <div id="root"></div>
28
+ <script type="text/babel">
29
+ const { useState } = React;
30
+ const Icon = ({ name, size = 20, className = "", strokeWidth = 2 }) => {
31
+ const ref = React.useRef(null);
32
+ React.useEffect(() => { if (ref.current) { const existing = ref.current.querySelector('svg'); if (existing) existing.remove(); const svg = lucide.createElement(lucide.icons[name]); if (svg) { svg.setAttribute('width',size); svg.setAttribute('height',size); svg.setAttribute('stroke-width',strokeWidth); ref.current.appendChild(svg); } } }, [name, size, className, strokeWidth]);
33
+ return <span ref={ref} className={`inline-flex items-center justify-center ${className}`} style={{ width: size, height: size }} />;
34
+ };
35
+
36
+ const navItems = [
37
+ { name: 'Dashboard', icon: 'layout-dashboard', href: 'dashboard.html' },
38
+ { name: 'Generator', icon: 'sparkles', href: 'generator.html' },
39
+ { name: 'Playground', icon: 'code', href: 'playground.html' },
40
+ { name: 'Models', icon: 'box', href: 'models.html' },
41
+ { name: 'Workflows', icon: 'workflow', href: 'workflows.html', active: true },
42
+ { name: 'Marketplace', icon: 'shopping-bag', href: 'marketplace.html' },
43
+ { name: 'API Keys', icon: 'key', href: 'api-keys.html' },
44
+ { divider: true },
45
+ { name: 'Profile', icon: 'user', href: 'profile.html' },
46
+ { name: 'Settings', icon: 'settings', href: 'settings.html' },
47
+ ];
48
+
49
+ const Sidebar = ({ isOpen, setIsOpen }) => (
50
+ <>
51
+ <div className={`fixed inset-0 z-40 lg:hidden transition-all ${isOpen ? 'opacity-100 pointer-events-auto' : 'opacity-0 pointer-events-none'}`}>
52
+ <div className="absolute inset-0 bg-black/60 backdrop-blur-sm" onClick={() => setIsOpen(false)} />
53
+ </div>
54
+ <aside className={`fixed top-0 left-0 bottom-0 z-50 w-64 bg-surface border-r border-border flex flex-col transition-transform duration-300 lg:translate-x-0 ${isOpen ? 'translate-x-0' : '-translate-x-full'}`}>
55
+ <div className="p-4 flex items-center gap-2.5 border-b border-border"><div className="w-8 h-8 rounded-lg bg-primary flex items-center justify-center"><Icon name="sparkles" size={16} className="text-primary-foreground" /></div><span className="text-lg font-bold tracking-tight">NSFW<span className="text-muted">Studio</span></span></div>
56
+ <nav className="flex-1 p-3 space-y-1 overflow-y-auto no-scrollbar">{navItems.map((item, i) => item.divider ? <div key={i} className="my-3 border-t border-border" /> : <a key={i} href={item.href} className={`flex items-center gap-3 px-3 py-2.5 rounded-xl text-sm font-medium transition-colors ${item.active ? 'bg-primary/10 text-primary border border-primary/20' : 'text-muted hover:text-fg hover:bg-surface-2 border border-transparent'}`}><Icon name={item.icon} size={18} />{item.name}</a>)}</nav>
57
+ <div className="p-4 border-t border-border"><a href="documentation.html" className="flex items-center gap-3 px-3 py-2.5 rounded-xl text-sm text-muted hover:text-fg hover:bg-surface-2 transition-colors"><Icon name="book-open" size={18} />Documentation</a><a href="api-reference.html" className="flex items-center gap-3 px-3 py-2.5 rounded-xl text-sm text-muted hover:text-fg hover:bg-surface-2 transition-colors"><Icon name="file-code" size={18} />API Reference</a></div>
58
+ </aside>
59
+ </>
60
+ );
61
+
62
+ const App = () => {
63
+ const [sidebarOpen, setSidebarOpen] = useState(false);
64
+ const [filter, setFilter] = useState('all');
65
+
66
+ const workflows = [
67
+ { name: 'Auto Tag & Categorize', desc: 'Automatically tag and categorize generated content using AI', steps: 4, runs: '12.4K', lastRun: '2 min ago', status: 'active', trigger: 'On Generation', icon: 'tag' },
68
+ { name: 'Batch Upscale Pipeline', desc: 'Upscale images in batch with quality enhancement', steps: 3, runs: '8.2K', lastRun: '1 hour ago', status: 'active', trigger: 'Manual', icon: 'maximize' },
69
+ { name: 'Content Moderation', desc: 'Auto-moderate content before publishing', steps: 5, runs: '45.1K', lastRun: '5 min ago', status: 'active', trigger: 'On Upload', icon: 'shield' },
70
+ { name: 'Social Media Scheduler', desc: 'Generate and schedule social media content', steps: 6, runs: '3.7K', lastRun: '3 days ago', status: 'paused', trigger: 'Scheduled', icon: 'calendar' },
71
+ { name: 'Model Fine-Tuner', desc: 'Automated fine-tuning workflow with dataset preparation', steps: 7, runs: '1.2K', lastRun: '1 week ago', status: 'draft', trigger: 'Manual', icon: 'cpu' },
72
+ { name: 'Video Frame Extractor', desc: 'Extract and enhance key frames from video generations', steps: 3, runs: '6.8K', lastRun: '30 min ago', status: 'active', trigger: 'On Video Gen', icon: 'film' },
73
+ ];
74
+
75
+ const filtered = filter === 'all' ? workflows : workflows.filter(w => w.status === filter);
76
+ const statusColors = { active: 'bg-success/10 text-success border-success/20', paused: 'bg-accent/10 text-accent border-accent/20', draft: 'bg-muted/10 text-muted border-border' };
77
+
78
+ return (
79
+ <div className="min-h-screen bg-bg">
80
+ <Sidebar isOpen={sidebarOpen} setIsOpen={setSidebarOpen} />
81
+ <div className="lg:ml-64">
82
+ <header className="sticky top-0 z-30 glass border-b border-border">
83
+ <div className="flex items-center justify-between px-4 sm:px-6 h-16">
84
+ <div className="flex items-center gap-4">
85
+ <button onClick={() => setSidebarOpen(true)} className="lg:hidden p-2 rounded-lg hover:bg-surface-2 text-muted"><Icon name="menu" size={20} /></button>
86
+ <h1 className="text-xl font-bold">Workflows</h1>
87
+ </div>
88
+ <div className="flex items-center gap-3">
89
+ <a href="#" className="px-4 py-2 rounded-lg bg-primary text-primary-foreground text-sm font-semibold hover:brightness-110 transition-all flex items-center gap-2"><Icon name="plus" size={16} />Create Workflow</a>
90
+ <a href="profile.html" className="w-9 h-9 rounded-lg overflow-hidden border border-border"><img src="http://static.photos/people/100x100/10" alt="" className="w-full h-full object-cover" /></a>
91
+ </div>
92
+ </div>
93
+ </header>
94
+
95
+ <main className="p-4 sm:p-6 lg:p-8">
96
+ {/* Stats */}
97
+ <div className="grid grid-cols-2 lg:grid-cols-4 gap-4 mb-8">
98
+ {[
99
+ { label: 'Total Workflows', value: '6', icon: 'workflow', color: 'text-primary', bg: 'bg-primary/10' },
100
+ { label: 'Active', value: '4', icon: 'play-circle', color: 'text-success', bg: 'bg-success/10' },
101
+ { label: 'Total Runs', value: '77.4K', icon: 'activity', color: 'text-secondary', bg: 'bg-secondary/10' },
102
+ { label: 'Avg Duration', value: '2.4s', icon: 'clock', color: 'text-accent', bg: 'bg-accent/10' },
103
+ ].map((s, i) => (
104
+ <div key={i} className="rounded-2xl p-5 bg-surface border border-border">
105
+ <div className="flex items-center gap-3 mb-3">
106
+ <div className={`w-9 h-9 rounded-lg ${s.bg} flex items-center justify-center`}><Icon name={s.icon} size={16} className={s.color} /></div>
107
+ <span className="text-xs text-muted">{s.label}</span>
108
+ </div>
109
+ <div className="text-2xl font-bold text-fg">{s.value}</div>
110
+ </div>
111
+ ))}
112
+ </div>
113
+
114
+ {/* Filters */}
115
+ <div className="flex items-center gap-2 mb-6">
116
+ {['all', 'active', 'paused', 'draft'].map(f => (
117
+ <button key={f} onClick={() => setFilter(f)} className={`px-4 py-2 rounded-lg text-sm font-medium capitalize transition-colors ${filter === f ? 'bg-primary text-primary-foreground' : 'text-muted hover:text-fg hover:bg-surface-2'}`}>{f}</button>
118
+ ))}
119
+ </div>
120
+
121
+ {/* Workflow list */}
122
+ <div className="space-y-4">
123
+ {filtered.map((w, i) => (
124
+ <div key={i} className="group rounded-2xl p-5 bg-surface border border-border hover:border-surface-3 transition-all">
125
+ <div className="flex flex-col sm:flex-row sm:items-center justify-between gap-4">
126
+ <div className="flex items-start gap-4">
127
+ <div className="w-12 h-12 rounded-xl bg-primary/10 flex items-center justify-center shrink-0"><Icon name={w.icon} size={22} className="text-primary" /></div>
128
+ <div>
129
+ <div className="flex items-center gap-2 mb-1">
130
+ <h3 className="font-semibold text-fg">{w.name}</h3>
131
+ <span className={`px-2.5 py-0.5 rounded-full text-xs font-semibold border ${statusColors[w.status]}`}>{w.status}</span>
132
+ </div>
133
+ <p className="text-sm text-muted mb-2">{w.desc}</p>
134
+ <div className="flex items-center gap-4 text-xs text-muted">
135
+ <span className="flex items-center gap-1"><Icon name="git-branch" size={12} />{w.steps} steps</span>
136
+ <span className="flex items-center gap-1"><Icon name="play" size={12} />{w.runs} runs</span>
137
+ <span className="flex items-center gap-1"><Icon name="zap" size={12} />{w.trigger}</span>
138
+ </div>
139
+ </div>
140
+ </div>
141
+ <div className="flex items-center gap-2">
142
+ <button className="px-3 py-2 rounded-lg border border-border text-sm text-muted hover:text-fg hover:bg-surface-2 transition-colors flex items-center gap-1.5"><Icon name="play" size={14} />Run</button>
143
+ <button className="px-3 py-2 rounded-lg border border-border text-sm text-muted hover:text-fg hover:bg-surface-2 transition-colors flex items-center gap-1.5"><Icon name="pencil" size={14} />Edit</button>
144
+ <button className="p-2 rounded-lg border border-border text-muted hover:text-fg hover:bg-surface-2 transition-colors"><Icon name="more-vertical" size={16} /></button>
145
+ </div>
146
+ </div>
147
+
148
+ {/* Mini flow visualization */}
149
+ <div className="mt-4 flex items-center gap-2 overflow-x-auto no-scrollbar pb-1">
150
+ {Array.from({length: w.steps}).map((_, j) => (
151
+ <React.Fragment key={j}>
152
+ <div className="flex items-center gap-2 px-3 py-2 rounded-lg bg-surface-2 border border-border shrink-0">
153
+ <div className={`w-2 h-2 rounded-full ${j < 3 ? 'bg-success' : j === 3 ? 'bg-primary' : 'bg-muted'}`} />
154
+ <span className="text-xs text-muted">Step {j + 1}</span>
155
+ </div>
156
+ {j < w.steps - 1 && <Icon name="chevron-right" size={14} className="text-muted shrink-0" />}
157
+ </React.Fragment>
158
+ ))}
159
+ </div>
160
+ </div>
161
+ ))}
162
+ </div>
163
+ </main>
164
+ </div>
165
+ </div>
166
+ );
167
+ };
168
+ ReactDOM.createRoot(document.getElementById('root')).render(<App />);
169
+ </script>
170
+ </body>
171
+ </html>