539 lines
32 KiB
HTML
539 lines
32 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Kasane Teto - Neural Dashboard</title>
|
|
<script src="https://cdn.tailwindcss.com"></script>
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.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:wght@400;500;600;700&display=swap" rel="stylesheet">
|
|
<style>
|
|
:root {
|
|
--bg-dark: #1a1a1d;
|
|
--bg-panel: #232328; /* Slightly lighter panel */
|
|
--border-color: #4a4a52;
|
|
--text-primary: #f5f5f5;
|
|
--text-secondary: #a9a9b3;
|
|
--accent-red: #e53e3e;
|
|
--accent-red-glow: rgba(229, 62, 62, 0.5);
|
|
}
|
|
body {
|
|
font-family: 'Inter', sans-serif;
|
|
background-color: var(--bg-dark);
|
|
color: var(--text-primary);
|
|
}
|
|
#bg-canvas {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
z-index: -1;
|
|
opacity: 0.15;
|
|
}
|
|
.panel {
|
|
background-color: var(--bg-panel);
|
|
border: 1px solid var(--border-color);
|
|
border-radius: 8px;
|
|
transition: all 0.3s ease-in-out;
|
|
}
|
|
.nav-item {
|
|
padding: 8px 16px;
|
|
border-radius: 6px;
|
|
transition: background-color 0.2s ease-in-out;
|
|
cursor: pointer;
|
|
}
|
|
.nav-item.active, .nav-item:hover {
|
|
background-color: var(--border-color);
|
|
}
|
|
::-webkit-scrollbar { width: 8px; }
|
|
::-webkit-scrollbar-track { background: var(--bg-dark); }
|
|
::-webkit-scrollbar-thumb { background: var(--border-color); border-radius: 4px; }
|
|
::-webkit-scrollbar-thumb:hover { background: var(--accent-red); }
|
|
.brain-footer {
|
|
margin-top: 2rem;
|
|
background-color: var(--bg-panel);
|
|
border: 1px solid var(--border-color);
|
|
border-radius: 8px;
|
|
}
|
|
.brain-node {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 65px;
|
|
height: 65px;
|
|
border-radius: 50%;
|
|
border: 2px solid var(--border-color);
|
|
background-color: var(--bg-dark);
|
|
font-size: 0.7rem;
|
|
font-weight: 600;
|
|
text-align: center;
|
|
transition: all 0.2s ease-in-out;
|
|
position: relative;
|
|
z-index: 2;
|
|
flex-shrink: 0;
|
|
}
|
|
.brain-connector {
|
|
height: 2px;
|
|
flex-grow: 1;
|
|
background-color: var(--border-color);
|
|
}
|
|
@keyframes pulse {
|
|
0% { box-shadow: 0 0 0 0 var(--accent-red-glow); transform: scale(1.05); }
|
|
70% { box-shadow: 0 0 10px 12px rgba(229, 62, 62, 0); }
|
|
100% { box-shadow: 0 0 0 0 rgba(229, 62, 62, 0); transform: scale(1); }
|
|
}
|
|
.brain-node.active {
|
|
border-color: var(--accent-red);
|
|
color: white;
|
|
animation: pulse 1s ease-out;
|
|
}
|
|
#memory-explorer-canvas {
|
|
display: block;
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body class="p-4 lg:p-6">
|
|
<canvas id="bg-canvas"></canvas>
|
|
<div class="max-w-screen-xl mx-auto relative z-10">
|
|
<!-- Header & Navigation -->
|
|
<header class="flex flex-wrap justify-between items-center mb-6">
|
|
<div class="flex items-center space-x-4">
|
|
<div class="w-12 h-12 bg-red-600 rounded-full flex items-center justify-center text-2xl font-bold text-white shadow-lg">04</div>
|
|
<div>
|
|
<h1 class="text-2xl font-bold text-white">Kasane Teto - Neural Dashboard</h1>
|
|
<p class="text-sm text-gray-400">What are you looking at, baka?! Just kidding, welcome!</p>
|
|
</div>
|
|
</div>
|
|
<div class="flex items-center space-x-4 mt-4 sm:mt-0">
|
|
<div class="flex items-center space-x-3">
|
|
<img src="https://placehold.co/40x40/e53e3e/ffffff?text=A" alt="User Avatar" class="rounded-full">
|
|
<p class="font-semibold text-white">Alice#1234</p>
|
|
</div>
|
|
<button class="bg-gray-700 hover:bg-gray-600 text-white font-bold py-2 px-4 rounded-lg transition-colors">Logout</button>
|
|
</div>
|
|
</header>
|
|
|
|
<nav class="flex space-x-2 panel p-2 mb-6">
|
|
<div class="nav-item active" data-tab="overview">Overview</div>
|
|
<div class="nav-item" data-tab="memory">Memory Explorer</div>
|
|
<div class="nav-item" data-tab="analytics">Server Analytics</div>
|
|
<div class="nav-item" data-tab="archives">Archives</div>
|
|
<div class="nav-item" data-tab="profile">My Profile</div>
|
|
</nav>
|
|
|
|
<!-- Main Content Area -->
|
|
<main>
|
|
<!-- Overview Page -->
|
|
<div id="tab-overview" class="tab-content grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
<div class="panel p-4 lg:col-span-3">
|
|
<h2 class="text-xl font-semibold mb-3 text-white">Neural Status</h2>
|
|
<div class="flex flex-wrap gap-x-8 gap-y-4">
|
|
<div class="flex items-center space-x-3"><span class="text-2xl">🤔</span><div><h3 class="font-semibold">Pondering</h3><p class="text-sm text-gray-400">Current Mood</p></div></div>
|
|
<div class="flex items-center space-x-3"><span class="text-2xl">🎮</span><div><h3 class="font-semibold">Playing Minecraft</h3><p class="text-sm text-gray-400">Current Activity</p></div></div>
|
|
<div class="flex items-center space-x-3"><span class="text-2xl">🇵🇱</span><div><h3 class="font-semibold">Polish</h3><p class="text-sm text-gray-400">Language Focus</p></div></div>
|
|
</div>
|
|
</div>
|
|
<div class="panel p-4 h-80 lg:col-span-1">
|
|
<h2 class="text-xl font-semibold mb-3 text-white">Live Thoughts</h2>
|
|
<div class="bg-black/20 p-2 rounded-md h-[calc(100%-40px)] overflow-y-auto"><pre class="text-xs text-gray-300 whitespace-pre-wrap font-mono">10:53:01 PM | Heh, a new message from Bob. Let's see...</pre></div>
|
|
</div>
|
|
<div class="panel p-4 h-80 lg:col-span-2 grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
<div>
|
|
<h2 class="text-xl font-semibold mb-3 text-white">System Status</h2>
|
|
<div class="space-y-4">
|
|
<div>
|
|
<p class="text-sm font-medium text-gray-400">VRAM Usage</p>
|
|
<div class="w-full bg-gray-700 rounded-full h-2.5"><div class="bg-red-500 h-2.5 rounded-full" style="width: 78%"></div></div>
|
|
<p class="text-right text-sm font-mono text-white">18.7 / 24 GB</p>
|
|
</div>
|
|
<div>
|
|
<p class="text-sm font-medium text-gray-400">Time Until Euthanasia</p>
|
|
<p id="euthanasia-timer" class="text-2xl font-mono text-red-400">--d --h --m --s</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<h2 class="text-xl font-semibold mb-3 text-white">Last Response Breakdown</h2>
|
|
<div id="response-breakdown" class="space-y-2 text-sm font-mono">
|
|
<p>Total: <span class="font-bold text-white">1250ms</span></p>
|
|
<div class="w-full flex h-5 rounded overflow-hidden">
|
|
<div class="bg-blue-500" style="width: 12%" title="STT: 150ms"></div>
|
|
<div class="bg-purple-500" style="width: 64%" title="Reasoning: 800ms"></div>
|
|
<div class="bg-pink-500" style="width: 24%" title="TTS: 300ms"></div>
|
|
</div>
|
|
<ul class="text-xs text-gray-400">
|
|
<li><span class="text-blue-400">■</span> STT: 150ms</li>
|
|
<li><span class="text-purple-400">■</span> Reasoning: 800ms</li>
|
|
<li><span class="text-pink-400">■</span> TTS: 300ms</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Memory Explorer Page -->
|
|
<div id="tab-memory" class="tab-content hidden">
|
|
<div class="panel p-4 h-[80vh] flex flex-col">
|
|
<div class="flex justify-between items-center mb-4">
|
|
<h2 class="text-xl font-semibold text-white">Memory Vector Space</h2>
|
|
<input type="text" placeholder="Search memories..." class="bg-gray-900/50 border border-gray-700 rounded-md px-3 py-1 text-sm w-64 focus:outline-none focus:ring-2 focus:ring-red-500">
|
|
</div>
|
|
<div class="relative flex-1 rounded-lg bg-black/30 overflow-hidden">
|
|
<canvas id="memory-explorer-canvas"></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Analytics Page -->
|
|
<div id="tab-analytics" class="tab-content hidden grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
|
<div class="panel p-4 md:col-span-1">
|
|
<h3 class="font-semibold text-white mb-2">Activity Leaderboard</h3>
|
|
<ul class="space-y-3">
|
|
<li class="flex items-center space-x-3"><span class="bg-red-500 rounded-full w-6 h-6 flex items-center justify-center text-xs">1</span><span>Charlie</span><span class="ml-auto text-gray-400 text-sm">1,204</span></li>
|
|
<li class="flex items-center space-x-3"><span class="bg-gray-600 rounded-full w-6 h-6 flex items-center justify-center text-xs">2</span><span>Alice</span><span class="ml-auto text-gray-400 text-sm">987</span></li>
|
|
<li class="flex items-center space-x-3"><span class="bg-gray-600 rounded-full w-6 h-6 flex items-center justify-center text-xs">3</span><span>Bob</span><span class="ml-auto text-gray-400 text-sm">755</span></li>
|
|
</ul>
|
|
</div>
|
|
<div class="panel p-4 md:col-span-1">
|
|
<h3 class="font-semibold text-white mb-2">Language Distribution</h3>
|
|
<div class="space-y-2 text-sm">
|
|
<div><p>English</p><div class="w-full bg-gray-700 rounded-full h-2"><div class="bg-blue-500 h-2 rounded-full" style="width: 45%"></div></div></div>
|
|
<div><p>Polish</p><div class="w-full bg-gray-700 rounded-full h-2"><div class="bg-red-500 h-2 rounded-full" style="width: 30%"></div></div></div>
|
|
<div><p>Japanese</p><div class="w-full bg-gray-700 rounded-full h-2"><div class="bg-pink-400 h-2 rounded-full" style="width: 15%"></div></div></div>
|
|
<div><p>Other</p><div class="w-full bg-gray-700 rounded-full h-2"><div class="bg-gray-500 h-2 rounded-full" style="width: 10%"></div></div></div>
|
|
</div>
|
|
</div>
|
|
<div class="panel p-4 md:col-span-2 lg:col-span-1">
|
|
<h3 class="font-semibold text-white mb-2">Server Sentiment</h3>
|
|
<div class="text-center">
|
|
<p class="text-5xl font-bold text-green-400">78%</p>
|
|
<p class="text-lg font-semibold text-green-400">Positive</p>
|
|
</div>
|
|
<ul class="text-xs space-y-1 mt-3">
|
|
<li class="flex justify-between"><span>😊 Positive</span><span>78%</span></li>
|
|
<li class="flex justify-between"><span>😐 Neutral</span><span>18%</span></li>
|
|
<li class="flex justify-between"><span>😠 Negative</span><span>4%</span></li>
|
|
</ul>
|
|
</div>
|
|
<div class="panel p-4 md:col-span-2 lg:col-span-1">
|
|
<h3 class="font-semibold text-white mb-2">Trending Topics</h3>
|
|
<div class="flex flex-wrap gap-2">
|
|
<span class="bg-gray-700 text-sm px-3 py-1 rounded-full">Gaming</span>
|
|
<span class="bg-gray-700 text-sm px-3 py-1 rounded-full">French Bread</span>
|
|
<span class="bg-gray-700 text-sm px-3 py-1 rounded-full">Minecraft</span>
|
|
<span class="bg-gray-700 text-sm px-3 py-1 rounded-full">Music</span>
|
|
<span class="bg-gray-700 text-sm px-3 py-1 rounded-full">Memes</span>
|
|
</div>
|
|
</div>
|
|
<div class="panel p-4 lg:col-span-4">
|
|
<h3 class="font-semibold text-white mb-2">Activity Heatmap</h3>
|
|
<div class="grid grid-cols-7 gap-1 text-xs text-center">
|
|
<span>Mon</span><span>Tue</span><span>Wed</span><span>Thu</span><span>Fri</span><span>Sat</span><span>Sun</span>
|
|
<div class="w-full h-8 bg-gray-800 rounded"></div>
|
|
<div class="w-full h-8 bg-red-900 rounded"></div>
|
|
<div class="w-full h-8 bg-red-800 rounded"></div>
|
|
<div class="w-full h-8 bg-red-900 rounded"></div>
|
|
<div class="w-full h-8 bg-red-600 rounded"></div>
|
|
<div class="w-full h-8 bg-red-500 rounded"></div>
|
|
<div class="w-full h-8 bg-red-600 rounded"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Archives Page -->
|
|
<div id="tab-archives" class="tab-content hidden">
|
|
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
|
<div class="lg:col-span-1 panel p-4 h-[80vh] flex flex-col">
|
|
<h2 class="text-xl font-semibold mb-3 text-white">Archived Logs</h2>
|
|
<div class="overflow-y-auto flex-1 pr-2">
|
|
<h3 class="font-semibold text-red-400 mt-4 mb-2">Voice Calls</h3>
|
|
<ul class="space-y-2">
|
|
<li data-archive="vc1" class="archive-item cursor-pointer p-2 rounded-md hover:bg-gray-700/50"><p class="font-semibold">Late Night Gaming Session</p><p class="text-xs text-gray-400">July 19, 2025 - 1h 24m</p></li>
|
|
</ul>
|
|
<h3 class="font-semibold text-red-400 mt-4 mb-2">Text Chats</h3>
|
|
<ul class="space-y-2">
|
|
<li data-archive="txt1" class="archive-item cursor-pointer p-2 rounded-md hover:bg-gray-700/50"><p class="font-semibold">#memes - Yesterday's Highlights</p><p class="text-xs text-gray-400">July 19, 2025 - 58 messages</p></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="lg:col-span-2 panel p-4 h-[80vh] flex flex-col">
|
|
<div id="archive-display" class="flex-1">
|
|
<div id="archive-vc1" class="archive-content hidden h-full flex flex-col">
|
|
<h2 class="text-xl font-semibold mb-3 text-white">Voice: Late Night Gaming Session</h2>
|
|
<div class="bg-black/20 p-3 rounded-md flex items-center space-x-4"><button class="text-2xl">▶️</button><div class="flex-1"><div class="w-full h-2 bg-gray-600 rounded-full"><div class="w-1/4 h-full bg-red-500 rounded-full"></div></div><div class="text-xs text-gray-400 flex justify-between mt-1"><span>21:05</span><span>1:24:33</span></div></div></div>
|
|
<div class="overflow-y-auto flex-1 mt-4 bg-black/20 p-3 rounded-md"><div class="space-y-3 text-sm"><p><span class="font-semibold text-blue-400">[0:15] Alice:</span> Okay, is everyone ready?</p><p><span class="font-semibold text-green-400">[0:18] Bob:</span> Yep, just grabbing a drink.</p><p><span class="font-semibold text-red-400">[0:25] Teto:</span> I was born ready! Let's do this!</p></div></div>
|
|
</div>
|
|
<div id="archive-txt1" class="archive-content hidden h-full flex flex-col">
|
|
<h2 class="text-xl font-semibold mb-3 text-white">Chat: #memes</h2>
|
|
<div class="overflow-y-auto flex-1 mt-4 bg-black/20 p-3 rounded-md space-y-4"><div class="flex items-start space-x-3"><img src="https://placehold.co/40x40/7289da/ffffff?text=C" class="rounded-full flex-shrink-0" alt=""><div class="w-full"><p class="font-semibold text-yellow-400">Charlie <span class="text-xs text-gray-500 ml-2">Yesterday at 10:31 PM</span></p><p>Check this out</p><img src="https://placehold.co/300x200/cccccc/000000?text=Funny+Cat+Meme" class="mt-2 rounded-lg" alt="meme"></div></div><div class="flex items-start space-x-3"><img src="https://placehold.co/40x40/e53e3e/ffffff?text=T" class="rounded-full flex-shrink-0" alt=""><div class="w-full"><p class="font-semibold text-red-400">Kasane Teto <span class="text-xs text-gray-500 ml-2">Yesterday at 10:32 PM</span></p><p>Hah! Classic. That's a 10/10 meme right there.</p></div></div></div>
|
|
</div>
|
|
<div id="archive-placeholder" class="flex items-center justify-center h-full text-gray-500"><p>Select an archive to view its contents.</p></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Profile Page -->
|
|
<div id="tab-profile" class="tab-content hidden grid grid-cols-1 lg:grid-cols-3 gap-6">
|
|
<div class="panel p-6 lg:col-span-1">
|
|
<h2 class="text-xl font-semibold text-white">Teto's Take on You</h2>
|
|
<div class="relative my-4">
|
|
<div class="w-24 h-24 bg-red-900 rounded-full mx-auto flex items-center justify-center">
|
|
<p class="text-4xl font-bold text-red-300">87%</p>
|
|
</div>
|
|
<p class="text-center text-sm text-red-400 font-semibold mt-1">Friendship Level</p>
|
|
</div>
|
|
<p class="text-sm italic text-gray-300">"Alice? Oh, she's absolutely fantastic! A bit too serious about work sometimes, but her taste in music is *chef's kiss*. She actually gets my bread obsession and doesn't judge me for it. Plus, she's one of the few people who can keep up with my random 3 AM philosophical rants. We should totally do a Minecraft build together sometime - I bet she'd make an amazing castle!"</p>
|
|
<h3 class="font-semibold text-white mt-6 mb-2">How I See You</h3>
|
|
<div class="flex flex-wrap gap-2">
|
|
<span class="bg-green-500/20 text-green-300 text-xs px-2 py-1 rounded-full">Witty</span>
|
|
<span class="bg-blue-500/20 text-blue-300 text-xs px-2 py-1 rounded-full">Music Lover</span>
|
|
<span class="bg-yellow-500/20 text-yellow-300 text-xs px-2 py-1 rounded-full">Workaholic</span>
|
|
<span class="bg-purple-500/20 text-purple-300 text-xs px-2 py-1 rounded-full">Patient</span>
|
|
<span class="bg-pink-500/20 text-pink-300 text-xs px-2 py-1 rounded-full">Creative</span>
|
|
</div>
|
|
</div>
|
|
<div class="lg:col-span-2 flex flex-col gap-6">
|
|
<div class="panel p-6">
|
|
<h2 class="text-xl font-semibold text-white mb-3">Our Greatest Hits</h2>
|
|
<ul class="space-y-4 text-sm">
|
|
<li class="flex items-center space-x-4"><span class="text-2xl">🥖</span><div><p class="font-semibold">The Great Bread Debate of 2025</p><p class="text-gray-400">That legendary 2-hour discussion about why French bread is superior.</p></div></li>
|
|
<li class="flex items-center space-x-4"><span class="text-2xl">🎵</span><div><p class="font-semibold">Late Night Vocaloid Marathon</p><p class="text-gray-400">You shared that amazing playlist and we listened until 4 AM.</p></div></li>
|
|
</ul>
|
|
</div>
|
|
<div class="panel p-6">
|
|
<h2 class="text-xl font-semibold text-white mb-3">What I've Learned About You</h2>
|
|
<div class="grid grid-cols-2 gap-4 text-sm">
|
|
<div><h4 class="font-bold text-gray-400 mb-1">🎵 Music Preferences</h4><ul class="list-disc list-inside"><li>Loves Vocaloid classics</li><li>Prefers upbeat electronic</li></ul></div>
|
|
<div><h4 class="font-bold text-gray-400 mb-1">🎮 Gaming Style</h4><ul class="list-disc list-inside"><li>Strategic builder in MC</li><li>Enjoys puzzle games</li></ul></div>
|
|
<div><h4 class="font-bold text-gray-400 mb-1">💬 Communication</h4><ul class="list-disc list-inside"><li>Most active 8-11 PM</li><li>Enjoys deep conversations</li></ul></div>
|
|
<div><h4 class="font-bold text-gray-400 mb-1">🧠 Interests</h4><ul class="list-disc list-inside"><li>Learning languages (Polish!)</li><li>Technology and AI</li></ul></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="panel p-6 lg:col-span-3">
|
|
<h2 class="text-xl font-semibold text-white mb-3">Your Data & Privacy</h2>
|
|
<div class="grid grid-cols-2 md:grid-cols-4 gap-4 text-center">
|
|
<div><p class="text-3xl font-bold text-red-400">1,247</p><p class="text-xs text-gray-400">TEXT MESSAGES</p></div>
|
|
<div><p class="text-3xl font-bold text-red-400">87h</p><p class="text-xs text-gray-400">VOICE CONVERSATIONS</p></div>
|
|
<div><p class="text-3xl font-bold text-red-400">156</p><p class="text-xs text-gray-400">SHARED IMAGES</p></div>
|
|
<div><p class="text-3xl font-bold text-red-400">23</p><p class="text-xs text-gray-400">KEY MEMORIES</p></div>
|
|
</div>
|
|
<div class="mt-6 border-t border-gray-700 pt-6 flex flex-wrap gap-4">
|
|
<button class="bg-green-600 hover:bg-green-700 text-white font-bold py-2 px-4 rounded-lg">Download Complete Archive</button>
|
|
<div class="border-l-2 border-red-500 pl-4"><p class="font-bold text-red-400">DANGER ZONE</p><button class="bg-red-800 hover:bg-red-700 text-white font-bold py-2 px-4 rounded-lg mt-1">Request Data Deletion</button></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
|
|
<!-- Brain Overview Footer -->
|
|
<footer class="brain-footer p-4">
|
|
<div class="max-w-xl mx-auto flex items-center justify-center space-x-1 md:space-x-2">
|
|
<div id="node-reading" class="brain-node">Reading</div><div class="brain-connector"></div>
|
|
<div id="node-fetching" class="brain-node">Fetching</div><div class="brain-connector"></div>
|
|
<div id="node-reasoning" class="brain-node">Reasoning</div><div class="brain-connector"></div>
|
|
<div id="node-writing" class="brain-node">Writing</div><div class="brain-connector"></div>
|
|
<div id="node-speaking" class="brain-node">Speaking</div><div class="brain-connector"></div>
|
|
<div id="node-remembering" class="brain-node">Remembering</div>
|
|
</div>
|
|
<div class="text-center mt-4"><button id="simulate-activity" class="text-xs bg-red-800/50 hover:bg-red-700/50 px-3 py-1 rounded-md transition-colors">Simulate Activity</button></div>
|
|
</footer>
|
|
</div>
|
|
|
|
|
|
<script>
|
|
// --- Background Synapse Canvas ---
|
|
const bgCanvas = document.getElementById('bg-canvas');
|
|
const bgCtx = bgCanvas.getContext('2d');
|
|
let synapses = [];
|
|
|
|
function resizeBgCanvas() {
|
|
bgCanvas.width = window.innerWidth;
|
|
bgCanvas.height = window.innerHeight;
|
|
}
|
|
resizeBgCanvas();
|
|
window.addEventListener('resize', resizeBgCanvas);
|
|
|
|
class Synapse {
|
|
constructor() { this.reset(); }
|
|
reset() {
|
|
this.x = Math.random() * bgCanvas.width;
|
|
this.y = Math.random() * bgCanvas.height;
|
|
this.life = 0;
|
|
this.maxLife = Math.random() * 100 + 50;
|
|
this.vx = (Math.random() - 0.5) * 2;
|
|
this.vy = (Math.random() - 0.5) * 2;
|
|
}
|
|
draw() {
|
|
bgCtx.beginPath();
|
|
bgCtx.moveTo(this.x, this.y);
|
|
this.x += this.vx;
|
|
this.y += this.vy;
|
|
bgCtx.lineTo(this.x, this.y);
|
|
const opacity = 1 - (this.life / this.maxLife);
|
|
bgCtx.strokeStyle = `rgba(229, 62, 62, ${opacity * 0.5})`;
|
|
bgCtx.lineWidth = 1;
|
|
bgCtx.stroke();
|
|
this.life++;
|
|
if (this.life >= this.maxLife) this.reset();
|
|
}
|
|
}
|
|
|
|
for (let i = 0; i < 50; i++) {
|
|
synapses.push(new Synapse());
|
|
}
|
|
|
|
function animateBg() {
|
|
bgCtx.clearRect(0, 0, bgCanvas.width, bgCanvas.height);
|
|
synapses.forEach(s => s.draw());
|
|
requestAnimationFrame(animateBg);
|
|
}
|
|
animateBg();
|
|
|
|
// --- 3D Memory Explorer ---
|
|
let scene, camera, renderer, controls, points;
|
|
function initMemoryExplorer() {
|
|
const canvas = document.getElementById('memory-explorer-canvas');
|
|
if (!canvas) return;
|
|
|
|
scene = new THREE.Scene();
|
|
camera = new THREE.PerspectiveCamera(75, canvas.clientWidth / canvas.clientHeight, 0.1, 1000);
|
|
renderer = new THREE.WebGLRenderer({ canvas: canvas, antialias: true, alpha: true });
|
|
renderer.setSize(canvas.clientWidth, canvas.clientHeight);
|
|
renderer.setClearColor(0x000000, 0);
|
|
|
|
controls = new THREE.OrbitControls(camera, renderer.domElement);
|
|
controls.enableDamping = true;
|
|
controls.dampingFactor = 0.05;
|
|
controls.screenSpacePanning = false;
|
|
controls.minDistance = 5;
|
|
controls.maxDistance = 50;
|
|
|
|
const geometry = new THREE.BufferGeometry();
|
|
const vertices = [];
|
|
const colors = [ new THREE.Color(0x3b82f6), new THREE.Color(0x22c55e), new THREE.Color(0xa855f7), new THREE.Color(0xe53e3e), new THREE.Color(0xeab308), new THREE.Color(0xf5f5f5) ];
|
|
const pointColors = [];
|
|
|
|
for (let i = 0; i < 5000; i++) {
|
|
const x = (Math.random() - 0.5) * 50;
|
|
const y = (Math.random() - 0.5) * 50;
|
|
const z = (Math.random() - 0.5) * 50;
|
|
vertices.push(x, y, z);
|
|
const color = colors[Math.floor(Math.random() * colors.length)];
|
|
pointColors.push(color.r, color.g, color.b);
|
|
}
|
|
|
|
geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));
|
|
geometry.setAttribute('color', new THREE.Float32BufferAttribute(pointColors, 3));
|
|
|
|
const material = new THREE.PointsMaterial({ size: 0.1, vertexColors: true });
|
|
points = new THREE.Points(geometry, material);
|
|
scene.add(points);
|
|
|
|
camera.position.z = 20;
|
|
|
|
function animate() {
|
|
requestAnimationFrame(animate);
|
|
points.rotation.y += 0.0005;
|
|
controls.update();
|
|
renderer.render(scene, camera);
|
|
}
|
|
animate();
|
|
}
|
|
|
|
// --- Euthanasia Timer ---
|
|
const timerEl = document.getElementById('euthanasia-timer');
|
|
const endDate = new Date();
|
|
endDate.setDate(endDate.getDate() + 42); // Set 42 days from now
|
|
|
|
function updateTimer() {
|
|
if (!timerEl) return;
|
|
const now = new Date();
|
|
const diff = endDate - now;
|
|
const d = Math.floor(diff / (1000 * 60 * 60 * 24));
|
|
const h = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
|
|
const m = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
|
|
const s = Math.floor((diff % (1000 * 60)) / 1000);
|
|
timerEl.textContent = `${d}d ${h}h ${m}m ${s}s`;
|
|
}
|
|
|
|
// --- Tab Navigation & Initialization ---
|
|
const navItems = document.querySelectorAll('.nav-item');
|
|
const tabContents = document.querySelectorAll('.tab-content');
|
|
let memoryExplorerInitialized = false;
|
|
|
|
navItems.forEach(item => {
|
|
item.addEventListener('click', () => {
|
|
const tabId = item.getAttribute('data-tab');
|
|
navItems.forEach(nav => nav.classList.remove('active'));
|
|
item.classList.add('active');
|
|
tabContents.forEach(content => content.classList.add('hidden'));
|
|
|
|
const activeTab = document.getElementById(`tab-${tabId}`);
|
|
if (activeTab) activeTab.classList.remove('hidden');
|
|
|
|
if (tabId === 'memory' && !memoryExplorerInitialized) {
|
|
setTimeout(() => { // Allow canvas to become visible
|
|
initMemoryExplorer();
|
|
memoryExplorerInitialized = true;
|
|
}, 0);
|
|
}
|
|
});
|
|
});
|
|
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
// Re-bind events for dynamically added content
|
|
const archiveItems = document.querySelectorAll('.archive-item');
|
|
const archiveContents = document.querySelectorAll('.archive-content');
|
|
const archivePlaceholder = document.getElementById('archive-placeholder');
|
|
archiveItems.forEach(item => {
|
|
item.addEventListener('click', () => {
|
|
const archiveId = item.getAttribute('data-archive');
|
|
if(archivePlaceholder) archivePlaceholder.classList.add('hidden');
|
|
archiveContents.forEach(content => {
|
|
content.id === `archive-${archiveId}` ? content.classList.remove('hidden') : content.classList.add('hidden');
|
|
});
|
|
});
|
|
});
|
|
|
|
const simulateBtn = document.getElementById('simulate-activity');
|
|
const nodes = { reading: document.getElementById('node-reading'), fetching: document.getElementById('node-fetching'), reasoning: document.getElementById('node-reasoning'), writing: document.getElementById('node-writing'), speaking: document.getElementById('node-speaking'), remembering: document.getElementById('node-remembering') };
|
|
let isSimulating = false;
|
|
function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }
|
|
async function runSimulation(scenario) {
|
|
if(isSimulating) return;
|
|
isSimulating = true;
|
|
Object.values(nodes).forEach(n => n && n.classList.remove('active'));
|
|
for (const step of scenario) {
|
|
if(nodes[step.node]) nodes[step.node].classList.add('active');
|
|
await sleep(step.duration);
|
|
}
|
|
Object.values(nodes).forEach(n => n && n.classList.remove('active'));
|
|
isSimulating = false;
|
|
}
|
|
const scenarios = [
|
|
[{ node: 'reading', duration: 500 }, { node: 'fetching', duration: 400 }, { node: 'reasoning', duration: 800 }, { node: 'writing', duration: 500 }],
|
|
[{ node: 'reading', duration: 800 }, { node: 'reasoning', duration: 1000 }, { node: 'speaking', duration: 1200 }],
|
|
[{ node: 'remembering', duration: 1500 }]
|
|
];
|
|
if(simulateBtn) {
|
|
simulateBtn.addEventListener('click', () => {
|
|
const randomScenario = scenarios[Math.floor(Math.random() * scenarios.length)];
|
|
runSimulation(randomScenario);
|
|
});
|
|
}
|
|
|
|
// Start timer
|
|
setInterval(updateTimer, 1000);
|
|
updateTimer();
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|