🐳 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
Browse files- dashboard.html +22 -8
- generator.html +15 -2
- index.html +0 -0
- models.html +51 -30
dashboard.html
CHANGED
|
@@ -35,6 +35,16 @@
|
|
| 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">
|
|
@@ -101,12 +111,14 @@
|
|
| 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: '
|
| 106 |
-
{ title: '
|
| 107 |
-
{ title: '
|
| 108 |
-
{ title: '
|
| 109 |
-
{ title: '
|
| 110 |
];
|
| 111 |
|
| 112 |
const activity = [
|
|
@@ -159,10 +171,12 @@
|
|
| 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-
|
|
|
|
|
|
|
| 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-
|
| 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>
|
|
|
|
| 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 |
+
.card-3d { transition: transform 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94), box-shadow 0.4s ease; }
|
| 39 |
+
.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); }
|
| 40 |
+
.hover-lift { transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1), box-shadow 0.3s ease; }
|
| 41 |
+
.hover-lift:hover { transform: translateY(-6px) scale(1.02); box-shadow: 0 15px 30px rgba(0,0,0,0.3); }
|
| 42 |
+
.gradient-border-animated { position: relative; isolation: isolate; }
|
| 43 |
+
.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; }
|
| 44 |
+
.gradient-border-animated:hover::before { opacity: 1; }
|
| 45 |
+
@keyframes slideUp { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } }
|
| 46 |
+
.animate-slide-up { animation: slideUp 0.5s ease-out forwards; }
|
| 47 |
+
.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); }
|
| 48 |
</style>
|
| 49 |
</head>
|
| 50 |
<body class="antialiased">
|
|
|
|
| 111 |
{ label: 'API Calls', value: '284K', change: '+31.5%', icon: 'activity', color: 'text-accent', bg: 'bg-accent/10' },
|
| 112 |
];
|
| 113 |
|
| 114 |
+
const [hoveredStat, setHoveredStat] = useState(null);
|
| 115 |
+
|
| 116 |
const recentGens = [
|
| 117 |
+
{ title: 'Crimson Seductress', model: 'EroticDream XL', time: '2m ago', status: 'completed', img: 'http://static.photos/cyberpunk/200x200/5' },
|
| 118 |
+
{ title: 'Dark Temptation', model: 'SinfulAnime XL', time: '5m ago', status: 'completed', img: 'http://static.photos/people/200x200/6' },
|
| 119 |
+
{ title: 'Velvet Dungeon', model: 'Fantasy Flesh XL', time: '8m ago', status: 'completed', img: 'http://static.photos/nature/200x200/7' },
|
| 120 |
+
{ title: 'Neon Curves', model: 'PhotoReal Erotica', time: '12m ago', status: 'completed', img: 'http://static.photos/technology/200x200/8' },
|
| 121 |
+
{ title: 'Shibari Art', model: 'DarkSeduction v3', time: '15m ago', status: 'processing', img: 'http://static.photos/people/200x200/9' },
|
| 122 |
];
|
| 123 |
|
| 124 |
const activity = [
|
|
|
|
| 171 |
{/* Stats */}
|
| 172 |
<div className="grid grid-cols-2 lg:grid-cols-4 gap-4 mb-8">
|
| 173 |
{stats.map((s, i) => (
|
| 174 |
+
<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"
|
| 175 |
+
style={{animationDelay: `${i * 0.1}s`, animation: 'slideUp 0.5s ease-out forwards', opacity: 0}}
|
| 176 |
+
onMouseEnter={() => setHoveredStat(i)} onMouseLeave={() => setHoveredStat(null)}>
|
| 177 |
<div className="flex items-center justify-between mb-3">
|
| 178 |
+
<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>
|
| 179 |
+
<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>
|
| 180 |
</div>
|
| 181 |
<div className="text-2xl font-bold text-fg tabular-nums">{s.value}</div>
|
| 182 |
<div className="text-xs text-muted mt-1">{s.label}</div>
|
generator.html
CHANGED
|
@@ -21,6 +21,14 @@
|
|
| 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">
|
|
@@ -139,8 +147,13 @@
|
|
| 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-
|
| 143 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 144 |
<p className="text-sm text-muted mt-1">This usually takes 10-30 seconds</p>
|
| 145 |
</div>
|
| 146 |
) : generated ? (
|
|
|
|
| 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 |
+
.card-3d { transition: transform 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94), box-shadow 0.4s ease; }
|
| 25 |
+
.card-3d:hover { transform: perspective(1000px) rotateY(-3deg) rotateX(2deg) translateZ(15px); box-shadow: 0 20px 40px rgba(0,0,0,0.35); }
|
| 26 |
+
.hover-lift { transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1), box-shadow 0.3s ease; }
|
| 27 |
+
.hover-lift:hover { transform: translateY(-4px) scale(1.02); box-shadow: 0 12px 24px rgba(0,0,0,0.3); }
|
| 28 |
+
@keyframes shimmer { 0% { background-position: -200% 0; } 100% { background-position: 200% 0; } }
|
| 29 |
+
@keyframes pulse-glow { 0%, 100% { box-shadow: 0 0 20px oklch(0.70 0.28 350 / 0.2); } 50% { box-shadow: 0 0 40px oklch(0.70 0.28 350 / 0.4); } }
|
| 30 |
+
.generating-glow { animation: pulse-glow 2s ease-in-out infinite; }
|
| 31 |
+
@keyframes morph-bg { 0%, 100% { border-radius: 60% 40% 30% 70% / 60% 30% 70% 40%; } 50% { border-radius: 30% 60% 70% 40% / 50% 60% 30% 60%; } }
|
| 32 |
</style>
|
| 33 |
</head>
|
| 34 |
<body class="antialiased">
|
|
|
|
| 147 |
<div className="flex-1 flex items-center justify-center p-4 sm:p-8">
|
| 148 |
{isGenerating ? (
|
| 149 |
<div className="text-center">
|
| 150 |
+
<div className="w-20 h-20 mx-auto mb-6 relative">
|
| 151 |
+
<div className="absolute inset-0 border-4 border-primary/30 border-t-primary rounded-full animate-spin" />
|
| 152 |
+
<div className="absolute inset-2 border-4 border-secondary/30 border-b-secondary rounded-full animate-spin" style={{animationDirection:'reverse', animationDuration:'1.5s'}} />
|
| 153 |
+
<div className="absolute inset-4 border-4 border-accent/30 border-t-accent rounded-full animate-spin" style={{animationDuration:'3s'}} />
|
| 154 |
+
<div className="absolute inset-8 bg-primary/20 rounded-full generating-glow" style={{borderRadius:'60% 40% 30% 70%', animation:'morph-bg 3s ease-in-out infinite'}} />
|
| 155 |
+
</div>
|
| 156 |
+
<p className="text-fg font-bold text-lg">Generating your fantasy...</p>
|
| 157 |
<p className="text-sm text-muted mt-1">This usually takes 10-30 seconds</p>
|
| 158 |
</div>
|
| 159 |
) : generated ? (
|
index.html
CHANGED
|
The diff for this file is too large to render.
See raw diff
|
|
|
models.html
CHANGED
|
@@ -18,10 +18,21 @@
|
|
| 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">
|
|
@@ -55,7 +66,7 @@
|
|
| 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="
|
| 59 |
</aside>
|
| 60 |
</>
|
| 61 |
);
|
|
@@ -63,22 +74,21 @@
|
|
| 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: '
|
| 70 |
-
{ name: '
|
| 71 |
-
{ name: '
|
| 72 |
-
{ name: '
|
| 73 |
];
|
| 74 |
|
| 75 |
const exploreModels = [
|
| 76 |
-
{ name: '
|
| 77 |
-
{ name: '
|
| 78 |
-
{ name: 'Fantasy
|
| 79 |
-
{ name: 'Ink &
|
| 80 |
-
{ name: '
|
| 81 |
-
{ name: '
|
| 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' };
|
|
@@ -95,36 +105,36 @@
|
|
| 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-
|
| 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-
|
| 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-
|
| 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-
|
| 125 |
-
<span className={`px-2.5 py-0.5 rounded-full text-xs font-
|
| 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>
|
|
@@ -137,9 +147,9 @@
|
|
| 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-
|
| 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-
|
| 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-
|
| 143 |
</div>
|
| 144 |
</div>
|
| 145 |
</div>
|
|
@@ -151,16 +161,16 @@
|
|
| 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-
|
| 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-
|
| 157 |
-
<div className="absolute inset-0 bg-gradient-to-t from-black/
|
| 158 |
-
<span className="absolute top-3 right-3 px-2.5 py-1 rounded-lg bg-black/50 backdrop-blur-sm text-xs font-
|
| 159 |
</div>
|
| 160 |
<div className="p-4">
|
| 161 |
<div className="flex items-start justify-between mb-2">
|
| 162 |
<div>
|
| 163 |
-
<h3 className="font-
|
| 164 |
<p className="text-xs text-muted">{m.author}</p>
|
| 165 |
</div>
|
| 166 |
<span className="text-sm font-bold text-primary">{m.price}</span>
|
|
@@ -177,7 +187,18 @@
|
|
| 177 |
|
| 178 |
{activeTab === 'training' && (
|
| 179 |
<div className="text-center py-16">
|
| 180 |
-
<div className="w-20 h-20 rounded-2xl bg-
|
| 181 |
-
<h2 className="text-xl font-
|
| 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-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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); }
|
| 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 |
+
.card-3d { transition: transform 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94), box-shadow 0.4s ease; }
|
| 27 |
+
.card-3d:hover { transform: perspective(1000px) rotateY(-3deg) rotateX(2deg) translateZ(20px); box-shadow: 0 25px 50px rgba(0,0,0,0.4), 0 0 0 1px oklch(0.70 0.28 350 / 0.2); }
|
| 28 |
+
.hover-lift { transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1), box-shadow 0.3s ease; }
|
| 29 |
+
.hover-lift:hover { transform: translateY(-6px) scale(1.02); box-shadow: 0 20px 40px rgba(0,0,0,0.3), 0 0 0 1px oklch(0.70 0.28 350 / 0.2); }
|
| 30 |
+
.gradient-border-animated { position: relative; isolation: isolate; }
|
| 31 |
+
.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; }
|
| 32 |
+
.gradient-border-animated:hover::before { opacity: 1; }
|
| 33 |
+
.glow-border { position: relative; isolation: isolate; }
|
| 34 |
+
.glow-border::after { content: ''; position: absolute; inset: -2px; border-radius: inherit; background: linear-gradient(135deg, oklch(0.70 0.28 350), oklch(0.75 0.15 215)); z-index: -1; opacity: 0; transition: opacity 0.3s ease; filter: blur(10px); }
|
| 35 |
+
.glow-border:hover::after { opacity: 0.6; }
|
| 36 |
</style>
|
| 37 |
</head>
|
| 38 |
<body class="antialiased">
|
|
|
|
| 66 |
<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'}`}>
|
| 67 |
<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>
|
| 68 |
<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>
|
| 69 |
+
<div className="p-4 border-t border-border"><a href="#" 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="#" 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>
|
| 70 |
</aside>
|
| 71 |
</>
|
| 72 |
);
|
|
|
|
| 74 |
const App = () => {
|
| 75 |
const [sidebarOpen, setSidebarOpen] = useState(false);
|
| 76 |
const [activeTab, setActiveTab] = useState('my-models');
|
|
|
|
| 77 |
|
| 78 |
const myModels = [
|
| 79 |
+
{ name: 'EroticDream XL', type: 'NSFW Image Generation', status: 'published', runs: '45.2K', rating: 4.9, revenue: '$2,340', updated: '2 days ago', img: 'http://static.photos/cyberpunk/400x300/20', desc: 'Ultra-realistic erotic art model with advanced anatomy and lighting' },
|
| 80 |
+
{ name: 'DarkSeduction v3', type: 'Fantasy Erotic', status: 'published', runs: '28.1K', rating: 4.8, revenue: '$1,890', updated: '1 week ago', img: 'http://static.photos/red/400x300/21', desc: 'Dark fantasy and fetish art with stunning detail and mood' },
|
| 81 |
+
{ name: 'MorphX Body v2', type: 'Body Morph', status: 'draft', runs: '0', rating: '-', revenue: '$0', updated: '3 days ago', img: 'http://static.photos/abstract/400x300/22', desc: 'Advanced body transformation and morphing model' },
|
| 82 |
+
{ name: 'Pleasure Enhance Pro', type: 'Upscaling', status: 'review', runs: '12.8K', rating: 4.7, revenue: '$890', updated: '5 days ago', img: 'http://static.photos/nature/400x300/23', desc: '4K upscaling optimized for adult content with detail recovery' },
|
| 83 |
];
|
| 84 |
|
| 85 |
const exploreModels = [
|
| 86 |
+
{ name: 'SinfulAnime XL', type: 'Hentai / Anime', author: '@velvet_sin', runs: '52K', rating: 4.9, price: '$7.99', img: 'http://static.photos/people/400x300/24' },
|
| 87 |
+
{ name: 'PhotoReal Erotica', type: 'Photorealistic', author: '@kink_architect', runs: '67K', rating: 4.9, price: '$14.99', img: 'http://static.photos/travel/400x300/25' },
|
| 88 |
+
{ name: 'Fantasy Flesh XL', type: 'Fantasy / Furry', author: '@fantasy_weaver', runs: '19.4K', rating: 4.8, price: '$5.99', img: 'http://static.photos/nature/400x300/26' },
|
| 89 |
+
{ name: 'Ink & Skink', type: 'Tattoo / Alt', author: '@dark_desires', runs: '15.3K', rating: 4.7, price: 'Free', img: 'http://static.photos/minimal/400x300/27' },
|
| 90 |
+
{ name: 'FutureBods', type: 'Sci-Fi Body', author: '@cosmic_ai', runs: '8.7K', rating: 4.6, price: '$3.99', img: 'http://static.photos/aerial/400x300/28' },
|
| 91 |
+
{ name: 'RetroPinup', type: 'Vintage Nude', author: '@retro_vibes', runs: '22.1K', rating: 4.8, price: 'Free', img: 'http://static.photos/vintage/400x300/29' },
|
| 92 |
];
|
| 93 |
|
| 94 |
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' };
|
|
|
|
| 105 |
</div>
|
| 106 |
<div className="flex items-center gap-3">
|
| 107 |
<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>
|
| 108 |
+
<a href="#" className="px-4 py-2 rounded-lg bg-primary text-primary-foreground text-sm font-semibold hover:brightness-110 transition-all hover:scale-105 shadow-lg shadow-primary/20 flex items-center gap-2"><Icon name="plus" size={16} />Train Model</a>
|
| 109 |
<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>
|
| 110 |
</div>
|
| 111 |
</div>
|
| 112 |
</header>
|
| 113 |
|
| 114 |
<main className="p-4 sm:p-6 lg:p-8">
|
|
|
|
| 115 |
<div className="flex items-center gap-2 mb-6 border-b border-border">
|
| 116 |
{[{ id: 'my-models', label: 'My Models' }, { id: 'explore', label: 'Explore' }, { id: 'training', label: 'Training' }].map(t => (
|
| 117 |
+
<button key={t.id} onClick={() => setActiveTab(t.id)} className={`px-4 py-3 border-b-2 text-sm font-semibold transition-all duration-300 -mb-px ${activeTab === t.id ? 'border-primary text-primary' : 'border-transparent text-muted hover:text-fg'}`}>{t.label}</button>
|
| 118 |
))}
|
| 119 |
</div>
|
| 120 |
|
| 121 |
{activeTab === 'my-models' && (
|
| 122 |
<div className="space-y-4">
|
| 123 |
{myModels.map((m, i) => (
|
| 124 |
+
<div key={i} className="group rounded-2xl bg-surface border border-border hover:border-primary/30 transition-all duration-500 overflow-hidden card-3d gradient-border-animated">
|
| 125 |
<div className="flex flex-col sm:flex-row">
|
| 126 |
<div className="sm:w-48 h-32 sm:h-auto shrink-0 overflow-hidden">
|
| 127 |
+
<img src={m.img} alt={m.name} className="w-full h-full object-cover group-hover:scale-110 transition-transform duration-700" />
|
| 128 |
</div>
|
| 129 |
<div className="flex-1 p-5">
|
| 130 |
<div className="flex items-start justify-between gap-3 mb-3">
|
| 131 |
<div>
|
| 132 |
<div className="flex items-center gap-2 mb-1">
|
| 133 |
+
<h3 className="font-bold text-fg group-hover:text-primary transition-colors duration-300">{m.name}</h3>
|
| 134 |
+
<span className={`px-2.5 py-0.5 rounded-full text-xs font-bold border ${statusColors[m.status]}`}>{m.status}</span>
|
| 135 |
</div>
|
| 136 |
<p className="text-sm text-muted">{m.type}</p>
|
| 137 |
+
<p className="text-xs text-muted/70 mt-1">{m.desc}</p>
|
| 138 |
</div>
|
| 139 |
<div className="text-right">
|
| 140 |
<div className="text-lg font-bold text-fg tabular-nums">{m.revenue}</div>
|
|
|
|
| 147 |
<span className="flex items-center gap-1"><Icon name="clock" size={14} />{m.updated}</span>
|
| 148 |
</div>
|
| 149 |
<div className="flex items-center gap-2 mt-4">
|
| 150 |
+
<button className="px-3 py-1.5 rounded-lg bg-primary text-primary-foreground text-sm font-semibold hover:brightness-110 transition-all duration-200 hover:scale-105">Manage</button>
|
| 151 |
+
<button className="px-3 py-1.5 rounded-lg border border-border text-sm text-muted hover:text-fg hover:bg-surface-2 transition-all duration-200">Analytics</button>
|
| 152 |
+
<button className="px-3 py-1.5 rounded-lg border border-border text-sm text-muted hover:text-fg hover:bg-surface-2 transition-all duration-200">Edit</button>
|
| 153 |
</div>
|
| 154 |
</div>
|
| 155 |
</div>
|
|
|
|
| 161 |
{activeTab === 'explore' && (
|
| 162 |
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
|
| 163 |
{exploreModels.map((m, i) => (
|
| 164 |
+
<div key={i} className="group rounded-2xl bg-surface border border-border hover:border-primary/30 overflow-hidden transition-all duration-500 hover:-translate-y-2 hover:shadow-2xl hover:shadow-primary/10 card-3d shine gradient-border-animated">
|
| 165 |
<div className="aspect-[4/3] overflow-hidden relative">
|
| 166 |
+
<img src={m.img} alt={m.name} className="w-full h-full object-cover group-hover:scale-110 transition-transform duration-700" />
|
| 167 |
+
<div className="absolute inset-0 bg-gradient-to-t from-black/70 to-transparent" />
|
| 168 |
+
<span className="absolute top-3 right-3 px-2.5 py-1 rounded-lg bg-black/50 backdrop-blur-sm text-xs font-bold border border-white/10">{m.type}</span>
|
| 169 |
</div>
|
| 170 |
<div className="p-4">
|
| 171 |
<div className="flex items-start justify-between mb-2">
|
| 172 |
<div>
|
| 173 |
+
<h3 className="font-bold text-fg group-hover:text-primary transition-colors duration-300">{m.name}</h3>
|
| 174 |
<p className="text-xs text-muted">{m.author}</p>
|
| 175 |
</div>
|
| 176 |
<span className="text-sm font-bold text-primary">{m.price}</span>
|
|
|
|
| 187 |
|
| 188 |
{activeTab === 'training' && (
|
| 189 |
<div className="text-center py-16">
|
| 190 |
+
<div className="w-20 h-20 rounded-2xl bg-primary/10 flex items-center justify-center mx-auto mb-4 hover-lift"><Icon name="cpu" size={32} className="text-primary" /></div>
|
| 191 |
+
<h2 className="text-xl font-bold mb-2">No Active Training</h2>
|
| 192 |
<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>
|
| 193 |
+
<a href="#" className="inline-flex items-center gap-2 px-6 py-3 rounded-xl bg-primary text-primary-foreground font-bold hover:brightness-110 transition-all duration-300 hover:scale-105 shadow-lg shadow-primary/20"><Icon name="plus" size={18} />Start Training</a>
|
| 194 |
+
</div>
|
| 195 |
+
)}
|
| 196 |
+
</main>
|
| 197 |
+
</div>
|
| 198 |
+
</div>
|
| 199 |
+
);
|
| 200 |
+
};
|
| 201 |
+
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
|
| 202 |
+
</script>
|
| 203 |
+
</body>
|
| 204 |
+
</html>
|