🐳 19/05 - 17:17 - I want you to go through every page, and I want you to add smooth transitions and interactive elements and better looking elements as well as 3D elements and designs. As well as Exp
b94499a verified | <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Dashboard — NSFWStudio</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <script src="https://unpkg.com/lucide@latest"></script> | |
| <script src="https://unpkg.com/react@18/umd/react.development.js"></script> | |
| <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script> | |
| <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script> | |
| <link rel="preconnect" href="https://fonts.googleapis.com"> | |
| <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> | |
| <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"> | |
| <script> | |
| 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)', | |
| }, | |
| }, | |
| }, | |
| } | |
| </script> | |
| <style> | |
| 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; } | |
| .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); } | |
| .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; } | |
| ::selection { background: oklch(0.70 0.28 350 / 0.3); color: white; } | |
| 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; } | |
| .no-scrollbar::-webkit-scrollbar { display: none; } .no-scrollbar { -ms-overflow-style: none; scrollbar-width: none; } | |
| .tabular-nums { font-variant-numeric: tabular-nums; } | |
| .card-3d { transition: transform 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94), box-shadow 0.4s ease; } | |
| .card-3d:hover { transform: perspective(1000px) rotateY(-3deg) rotateX(2deg) translateZ(15px); box-shadow: 0 20px 40px rgba(0,0,0,0.35), 0 0 0 1px oklch(0.70 0.28 350 / 0.2); } | |
| .hover-lift { transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1), box-shadow 0.3s ease; } | |
| .hover-lift:hover { transform: translateY(-6px) scale(1.02); box-shadow: 0 15px 30px rgba(0,0,0,0.3); } | |
| .gradient-border-animated { position: relative; isolation: isolate; } | |
| .gradient-border-animated::before { content: ''; position: absolute; inset: 0; border-radius: inherit; padding: 1.5px; background: linear-gradient(270deg, oklch(0.70 0.28 350), oklch(0.75 0.15 215), oklch(0.80 0.18 85), oklch(0.70 0.28 350)); background-size: 300% 100%; -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); -webkit-mask-composite: xor; mask-composite: exclude; opacity: 0; transition: opacity 0.3s ease; } | |
| .gradient-border-animated:hover::before { opacity: 1; } | |
| @keyframes slideUp { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } | |
| .animate-slide-up { animation: slideUp 0.5s ease-out forwards; } | |
| .glow-ring:hover { box-shadow: 0 0 0 2px oklch(0.70 0.28 350 / 0.3), 0 0 20px oklch(0.70 0.28 350 / 0.1); } | |
| </style> | |
| </head> | |
| <body class="antialiased"> | |
| <div id="root"></div> | |
| <script type="text/babel"> | |
| const { useState } = React; | |
| const Icon = ({ name, size = 20, className = "", strokeWidth = 2 }) => { | |
| const ref = React.useRef(null); | |
| 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]); | |
| return <span ref={ref} className={`inline-flex items-center justify-center ${className}`} style={{ width: size, height: size }} />; | |
| }; | |
| const navItems = [ | |
| { name: 'Dashboard', icon: 'layout-dashboard', href: 'dashboard.html', active: true }, | |
| { name: 'Generator', icon: 'sparkles', href: 'generator.html' }, | |
| { name: 'Playground', icon: 'code', href: 'playground.html' }, | |
| { name: 'Models', icon: 'box', href: 'models.html' }, | |
| { name: 'Workflows', icon: 'workflow', href: 'workflows.html' }, | |
| { name: 'Marketplace', icon: 'shopping-bag', href: 'marketplace.html' }, | |
| { name: 'API Keys', icon: 'key', href: 'api-keys.html' }, | |
| { divider: true }, | |
| { name: 'Profile', icon: 'user', href: 'profile.html' }, | |
| { name: 'Settings', icon: 'settings', href: 'settings.html' }, | |
| ]; | |
| const Sidebar = ({ isOpen, setIsOpen }) => ( | |
| <> | |
| {/* Mobile overlay */} | |
| <div className={`fixed inset-0 z-40 lg:hidden transition-all ${isOpen ? 'opacity-100 pointer-events-auto' : 'opacity-0 pointer-events-none'}`}> | |
| <div className="absolute inset-0 bg-black/60 backdrop-blur-sm" onClick={() => setIsOpen(false)} /> | |
| </div> | |
| <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'}`}> | |
| <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> | |
| <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> | |
| <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> | |
| </aside> | |
| </> | |
| ); | |
| const App = () => { | |
| const [sidebarOpen, setSidebarOpen] = useState(false); | |
| const stats = [ | |
| { label: 'Generations', value: '12,847', change: '+14.2%', icon: 'image', color: 'text-primary', bg: 'bg-primary/10' }, | |
| { label: 'Revenue', value: '$8,492', change: '+23.1%', icon: 'dollar-sign', color: 'text-success', bg: 'bg-success/10' }, | |
| { label: 'Followers', value: '2,341', change: '+8.7%', icon: 'users', color: 'text-secondary', bg: 'bg-secondary/10' }, | |
| { label: 'API Calls', value: '284K', change: '+31.5%', icon: 'activity', color: 'text-accent', bg: 'bg-accent/10' }, | |
| ]; | |
| const [hoveredStat, setHoveredStat] = useState(null); | |
| const recentGens = [ | |
| { title: 'Crimson Seductress', model: 'EroticDream XL', time: '2m ago', status: 'completed', img: 'http://static.photos/cyberpunk/200x200/5' }, | |
| { title: 'Dark Temptation', model: 'SinfulAnime XL', time: '5m ago', status: 'completed', img: 'http://static.photos/people/200x200/6' }, | |
| { title: 'Velvet Dungeon', model: 'Fantasy Flesh XL', time: '8m ago', status: 'completed', img: 'http://static.photos/nature/200x200/7' }, | |
| { title: 'Neon Curves', model: 'PhotoReal Erotica', time: '12m ago', status: 'completed', img: 'http://static.photos/technology/200x200/8' }, | |
| { title: 'Shibari Art', model: 'DarkSeduction v3', time: '15m ago', status: 'processing', img: 'http://static.photos/people/200x200/9' }, | |
| ]; | |
| const activity = [ | |
| { text: 'New follower: @dark_pixel', time: '1m ago', icon: 'user-plus', color: 'text-secondary' }, | |
| { text: 'Your model earned $49.00', time: '3m ago', icon: 'dollar-sign', color: 'text-success' }, | |
| { text: 'Workflow "Auto Tag" completed', time: '7m ago', icon: 'check-circle', color: 'text-primary' }, | |
| { text: 'Comment on "Neon Cityscape"', time: '10m ago', icon: 'message-circle', color: 'text-accent' }, | |
| { text: 'API key rotation reminder', time: '1h ago', icon: 'key', color: 'text-muted' }, | |
| ]; | |
| const topModels = [ | |
| { name: 'DreamVision XL', runs: '45.2K', revenue: '$2,340', trend: '+12%' }, | |
| { name: 'CyberPunk v3', runs: '28.1K', revenue: '$1,890', trend: '+8%' }, | |
| { name: 'Anime Diffusion', runs: '19.7K', revenue: '$1,230', trend: '+21%' }, | |
| ]; | |
| return ( | |
| <div className="min-h-screen bg-bg"> | |
| <Sidebar isOpen={sidebarOpen} setIsOpen={setSidebarOpen} /> | |
| <div className="lg:ml-64"> | |
| {/* Top bar */} | |
| <header className="sticky top-0 z-30 glass border-b border-border"> | |
| <div className="flex items-center justify-between px-4 sm:px-6 h-16"> | |
| <div className="flex items-center gap-4"> | |
| <button onClick={() => setSidebarOpen(true)} className="lg:hidden p-2 rounded-lg hover:bg-surface-2 text-muted"><Icon name="menu" size={20} /></button> | |
| <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"> | |
| <Icon name="search" size={16} /> | |
| <span>Search anything...</span> | |
| </div> | |
| </div> | |
| <div className="flex items-center gap-3"> | |
| <button className="p-2 rounded-lg hover:bg-surface-2 text-muted hover:text-fg transition-colors relative"> | |
| <Icon name="bell" size={20} /> | |
| <span className="absolute top-1.5 right-1.5 w-2 h-2 rounded-full bg-primary" /> | |
| </button> | |
| <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> | |
| <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> | |
| </div> | |
| </div> | |
| </header> | |
| <main className="p-4 sm:p-6 lg:p-8"> | |
| <div className="mb-8"> | |
| <h1 className="text-2xl sm:text-3xl font-bold mb-1">Welcome back, <span className="gradient-text">Neon</span></h1> | |
| <p className="text-muted">Here's what's happening with your creations today.</p> | |
| </div> | |
| {/* Stats */} | |
| <div className="grid grid-cols-2 lg:grid-cols-4 gap-4 mb-8"> | |
| {stats.map((s, i) => ( | |
| <div key={i} className="rounded-2xl p-5 bg-surface border border-border hover:border-primary/30 transition-all duration-500 card-3d gradient-border-animated" | |
| style={{animationDelay: `${i * 0.1}s`, animation: 'slideUp 0.5s ease-out forwards', opacity: 0}} | |
| onMouseEnter={() => setHoveredStat(i)} onMouseLeave={() => setHoveredStat(null)}> | |
| <div className="flex items-center justify-between mb-3"> | |
| <div className={`w-10 h-10 rounded-xl ${s.bg} flex items-center justify-center transition-transform duration-300 ${hoveredStat === i ? 'scale-110' : ''}`}><Icon name={s.icon} size={18} className={s.color} /></div> | |
| <span className="text-xs font-bold text-success bg-success/10 px-2.5 py-1 rounded-full border border-success/20">{s.change}</span> | |
| </div> | |
| <div className="text-2xl font-bold text-fg tabular-nums">{s.value}</div> | |
| <div className="text-xs text-muted mt-1">{s.label}</div> | |
| </div> | |
| ))} | |
| </div> | |
| <div className="grid lg:grid-cols-3 gap-6"> | |
| {/* Recent Generations */} | |
| <div className="lg:col-span-2 rounded-2xl p-6 bg-surface border border-border"> | |
| <div className="flex items-center justify-between mb-5"> | |
| <h2 className="text-lg font-semibold">Recent Generations</h2> | |
| <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> | |
| </div> | |
| <div className="space-y-3"> | |
| {recentGens.map((g, i) => ( | |
| <div key={i} className="flex items-center gap-4 p-3 rounded-xl hover:bg-surface-2/50 transition-colors cursor-pointer group"> | |
| <img src={g.img} alt="" className="w-12 h-12 rounded-xl object-cover border border-border" /> | |
| <div className="flex-1 min-w-0"> | |
| <div className="text-sm font-medium text-fg truncate">{g.title}</div> | |
| <div className="text-xs text-muted">{g.model} · {g.time}</div> | |
| </div> | |
| <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'}`}> | |
| {g.status} | |
| </span> | |
| </div> | |
| ))} | |
| </div> | |
| </div> | |
| {/* Right column */} | |
| <div className="space-y-6"> | |
| {/* Activity */} | |
| <div className="rounded-2xl p-6 bg-surface border border-border"> | |
| <h2 className="text-lg font-semibold mb-4">Activity</h2> | |
| <div className="space-y-4"> | |
| {activity.map((a, i) => ( | |
| <div key={i} className="flex items-start gap-3"> | |
| <div className={`mt-0.5 ${a.color}`}><Icon name={a.icon} size={16} /></div> | |
| <div className="flex-1 min-w-0"> | |
| <div className="text-sm text-fg/90">{a.text}</div> | |
| <div className="text-xs text-muted mt-0.5">{a.time}</div> | |
| </div> | |
| </div> | |
| ))} | |
| </div> | |
| </div> | |
| {/* Top Models */} | |
| <div className="rounded-2xl p-6 bg-surface border border-border"> | |
| <div className="flex items-center justify-between mb-4"> | |
| <h2 className="text-lg font-semibold">Top Models</h2> | |
| <a href="models.html" className="text-xs text-primary hover:underline">See all</a> | |
| </div> | |
| <div className="space-y-3"> | |
| {topModels.map((m, i) => ( | |
| <div key={i} className="flex items-center justify-between p-3 rounded-xl hover:bg-surface-2/50 transition-colors cursor-pointer"> | |
| <div className="flex items-center gap-3"> | |
| <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> | |
| <div> | |
| <div className="text-sm font-medium text-fg">{m.name}</div> | |
| <div className="text-xs text-muted">{m.runs} runs</div> | |
| </div> | |
| </div> | |
| <div className="text-right"> | |
| <div className="text-sm font-semibold text-fg">{m.revenue}</div> | |
| <div className="text-xs text-success">{m.trend}</div> | |
| </div> | |
| </div> | |
| ))} | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| {/* Quick Actions */} | |
| <div className="mt-8 grid grid-cols-2 sm:grid-cols-4 gap-3"> | |
| {[ | |
| { label: 'Generate Image', icon: 'image', color: 'text-primary', bg: 'bg-primary/10', href: 'generator.html' }, | |
| { label: 'Create Workflow', icon: 'workflow', color: 'text-secondary', bg: 'bg-secondary/10', href: 'workflows.html' }, | |
| { label: 'Train Model', icon: 'box', color: 'text-success', bg: 'bg-success/10', href: 'models.html' }, | |
| { label: 'Explore Marketplace', icon: 'shopping-bag', color: 'text-accent', bg: 'bg-accent/10', href: 'marketplace.html' }, | |
| ].map((a, i) => ( | |
| <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"> | |
| <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> | |
| <span className="text-sm font-medium text-fg">{a.label}</span> | |
| </a> | |
| ))} | |
| </div> | |
| </main> | |
| </div> | |
| </div> | |
| ); | |
| }; | |
| ReactDOM.createRoot(document.getElementById('root')).render(<App />); | |
| </script> | |
| </body> | |
| </html> |