Source identity
| Field | Recorded value |
|---|---|
| Source type | archive member |
| Original record | ch13-playground.html |
| Date | Not specified in source |
| Path or archive member | archives/libsrc-1c3f88063121/NETLIFY_AI_RECOVERY_2026-10-14_21-10-49/sites/janady13__megamind-258b-neurons__d5baa307-3c60-4504-827c-c9c4449caf31/originals/deploy_698104b5fbe3d9e6d8e3f3e0/ch13-playground.html |
| Original SHA-256 | a5e452ef71147ff3b8e06baa764346b00ae56752336bb1f7864733bbd337168f |
| Reading-copy SHA-256 | a5e452ef71147ff3b8e06baa764346b00ae56752336bb1f7864733bbd337168f |
| Archive source | {"sourceId": "libsrc-1c3f88063121", "member": "NETLIFY_AI_RECOVERY_2026-10-14_21-10-49/sites/janady13__megamind-258b-neurons__d5baa307-3c60-4504-827c-c9c4449caf31/originals/deploy_698104b5fbe3d9e6d8e3f3e0/ch13-playground.html"} |
Every recorded occurrence
These 4 records contain identical original source bytes. Their paths and revisions remain part of the archive.
| Original record | Branch or archive | Revision / identifier | Original location |
|---|---|---|---|
| ch13-playground.html | {"sourceId": "libsrc-1c3f88063121", "member": "NETLIFY_AI_RECOVERY_2026-10-14_21-10-49/sites/janady13__megamind-258b-neurons__d5baa307-3c60-4504-827c-c9c4449caf31/originals/deploy_698104b5fbe3d9e6d8e3f3e0/ch13-playground.html"} | libsrc-fa9d43391985 | archives/libsrc-1c3f88063121/NETLIFY_AI_RECOVERY_2026-10-14_21-10-49/sites/janady13__megamind-258b-neurons__d5baa307-3c60-4504-827c-c9c4449caf31/originals/deploy_698104b5fbe3d9e6d8e3f3e0/ch13-playground.html |
| ch13-playground.html | {"sourceId": "libsrc-1c3f88063121", "member": "NETLIFY_AI_RECOVERY_2026-10-14_21-10-49/sites/janady13__feed-the-joe__8de87f1b-a5a4-4d10-9d82-4e8f27729768/originals/deploy_6980fcb4ca86308cf2464bcd/ch13-playground.html"} | libsrc-85b9389918d4 | archives/libsrc-1c3f88063121/NETLIFY_AI_RECOVERY_2026-10-14_21-10-49/sites/janady13__feed-the-joe__8de87f1b-a5a4-4d10-9d82-4e8f27729768/originals/deploy_6980fcb4ca86308cf2464bcd/ch13-playground.html |
| 81f22abe1225add0a7a9d355ca23b6406a93a7e7 | {"sourceId": "libsrc-1c3f88063121", "member": "NETLIFY_AI_RECOVERY_2026-10-14_21-10-49/sites/janady13__megamind-258b-neurons__d5baa307-3c60-4504-827c-c9c4449caf31/originals/.content_store/81/81f22abe1225add0a7a9d355ca23b6406a93a7e7"} | libsrc-327bb342a716 | archives/libsrc-1c3f88063121/NETLIFY_AI_RECOVERY_2026-10-14_21-10-49/sites/janady13__megamind-258b-neurons__d5baa307-3c60-4504-827c-c9c4449caf31/originals/.content_store/81/81f22abe1225add0a7a9d355ca23b6406a93a7e7 |
| 81f22abe1225add0a7a9d355ca23b6406a93a7e7 | {"sourceId": "libsrc-1c3f88063121", "member": "NETLIFY_AI_RECOVERY_2026-10-14_21-10-49/sites/janady13__feed-the-joe__8de87f1b-a5a4-4d10-9d82-4e8f27729768/originals/.content_store/81/81f22abe1225add0a7a9d355ca23b6406a93a7e7"} | libsrc-adfdc4955f02 | archives/libsrc-1c3f88063121/NETLIFY_AI_RECOVERY_2026-10-14_21-10-49/sites/janady13__feed-the-joe__8de87f1b-a5a4-4d10-9d82-4e8f27729768/originals/.content_store/81/81f22abe1225add0a7a9d355ca23b6406a93a7e7 |
Recovered source transcript
Download complete source text ↓1,583 lines · 44.3 KB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MEGAMIND | Neural Playground</title>
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
<style>
:root {
--bg: #050508;
--surface: #0d0d12;
--surface-light: #16161d;
--text: #f0f0f5;
--muted: #5a5a6e;
--primary: #00ff88;
--primary-dim: #00cc6a;
--secondary: #00aaff;
--accent: #ff6b35;
--purple: #a855f7;
--pink: #ec4899;
--cyan: #22d3ee;
--yellow: #facc15;
--sans: 'Space Grotesk', sans-serif;
--mono: 'JetBrains Mono', monospace;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
html, body {
font-family: var(--sans);
background: var(--bg);
color: var(--text);
min-height: 100vh;
overflow: hidden;
}
/* Custom Cursor */
.cursor {
position: fixed;
width: 20px;
height: 20px;
border: 2px solid var(--primary);
border-radius: 50%;
pointer-events: none;
z-index: 10000;
transition: transform 0.1s ease, border-color 0.2s ease, width 0.2s ease, height 0.2s ease;
transform: translate(-50%, -50%);
mix-blend-mode: difference;
}
.cursor-dot {
position: fixed;
width: 6px;
height: 6px;
background: var(--primary);
border-radius: 50%;
pointer-events: none;
z-index: 10001;
transform: translate(-50%, -50%);
}
.cursor.active {
width: 50px;
height: 50px;
border-color: var(--cyan);
}
.cursor.clicking {
transform: translate(-50%, -50%) scale(0.8);
border-color: var(--pink);
}
/* Navigation */
.nav {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0.75rem 2rem;
background: linear-gradient(180deg, rgba(13,13,18,0.95) 0%, rgba(13,13,18,0.8) 100%);
border-bottom: 1px solid rgba(0,255,136,0.1);
backdrop-filter: blur(10px);
position: relative;
z-index: 100;
}
.nav-logo {
font-family: var(--mono);
font-size: 0.7rem;
letter-spacing: 0.3em;
color: var(--primary);
text-shadow: 0 0 20px rgba(0,255,136,0.5);
}
.nav-chapter {
font-family: var(--mono);
font-size: 0.6rem;
color: var(--muted);
letter-spacing: 0.15em;
}
.nav-chapter span {
color: var(--cyan);
}
/* Layout */
.playground {
display: grid;
grid-template-columns: 320px 1fr;
height: calc(100vh - 52px);
}
/* Sidebar */
.sidebar {
background: linear-gradient(180deg, var(--surface) 0%, var(--bg) 100%);
padding: 1.5rem;
border-right: 1px solid rgba(0,255,136,0.1);
overflow-y: auto;
position: relative;
}
.sidebar::before {
content: '';
position: absolute;
top: 0;
right: 0;
width: 1px;
height: 100%;
background: linear-gradient(180deg, var(--primary) 0%, transparent 50%, var(--cyan) 100%);
opacity: 0.3;
}
.sidebar-section {
margin-bottom: 2rem;
}
.sidebar h2 {
font-size: 0.6rem;
letter-spacing: 0.25em;
color: var(--muted);
margin-bottom: 1.25rem;
display: flex;
align-items: center;
gap: 0.5rem;
}
.sidebar h2::before {
content: '';
width: 8px;
height: 8px;
background: var(--primary);
border-radius: 2px;
box-shadow: 0 0 10px var(--primary);
}
.control-group {
margin-bottom: 1.25rem;
padding: 1rem;
background: rgba(255,255,255,0.02);
border-radius: 12px;
border: 1px solid rgba(255,255,255,0.05);
transition: all 0.3s ease;
}
.control-group:hover {
background: rgba(0,255,136,0.03);
border-color: rgba(0,255,136,0.15);
}
.control-label {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 0.8rem;
margin-bottom: 0.75rem;
color: var(--text);
}
.control-value {
font-family: var(--mono);
font-size: 0.85rem;
color: var(--primary);
background: rgba(0,255,136,0.1);
padding: 0.2rem 0.6rem;
border-radius: 4px;
text-shadow: 0 0 10px rgba(0,255,136,0.5);
}
/* Custom Range Slider */
input[type="range"] {
width: 100%;
height: 8px;
-webkit-appearance: none;
background: rgba(255,255,255,0.08);
border-radius: 4px;
outline: none;
position: relative;
cursor: pointer;
}
input[type="range"]::-webkit-slider-track {
height: 8px;
border-radius: 4px;
}
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 22px;
height: 22px;
background: linear-gradient(135deg, var(--primary) 0%, var(--cyan) 100%);
border-radius: 50%;
cursor: pointer;
box-shadow: 0 0 20px rgba(0,255,136,0.6), 0 0 40px rgba(0,255,136,0.3);
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
input[type="range"]::-webkit-slider-thumb:hover {
transform: scale(1.15);
box-shadow: 0 0 30px rgba(0,255,136,0.8), 0 0 60px rgba(0,255,136,0.4);
}
input[type="range"]:active::-webkit-slider-thumb {
transform: scale(0.95);
}
/* Buttons */
.btn-group {
display: flex;
flex-direction: column;
gap: 0.75rem;
margin-bottom: 1.5rem;
}
.btn {
width: 100%;
padding: 1rem 1.25rem;
font-family: var(--sans);
font-size: 0.85rem;
font-weight: 600;
border: none;
border-radius: 10px;
cursor: pointer;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
text-transform: uppercase;
letter-spacing: 0.1em;
}
.btn::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
transition: left 0.5s ease;
}
.btn:hover::before {
left: 100%;
}
.btn-primary {
background: linear-gradient(135deg, var(--primary) 0%, var(--cyan) 100%);
color: var(--bg);
box-shadow: 0 4px 20px rgba(0,255,136,0.3);
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 6px 30px rgba(0,255,136,0.5);
}
.btn-primary:active {
transform: translateY(0);
}
.btn-secondary {
background: rgba(255,255,255,0.05);
color: var(--text);
border: 1px solid rgba(255,255,255,0.1);
}
.btn-secondary:hover {
background: rgba(255,255,255,0.1);
border-color: var(--primary);
color: var(--primary);
}
.btn-accent {
background: linear-gradient(135deg, var(--purple) 0%, var(--pink) 100%);
color: white;
box-shadow: 0 4px 20px rgba(168,85,247,0.3);
}
.btn-accent:hover {
transform: translateY(-2px);
box-shadow: 0 6px 30px rgba(168,85,247,0.5);
}
/* Stats Panel */
.stats-panel {
background: linear-gradient(135deg, rgba(0,255,136,0.05) 0%, rgba(0,170,255,0.05) 100%);
border: 1px solid rgba(0,255,136,0.2);
border-radius: 16px;
padding: 1.25rem;
position: relative;
overflow: hidden;
}
.stats-panel::before {
content: '';
position: absolute;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: conic-gradient(from 0deg, transparent, rgba(0,255,136,0.1), transparent 30%);
animation: rotate 10s linear infinite;
}
@keyframes rotate {
100% { transform: rotate(360deg); }
}
.stats-panel-inner {
position: relative;
z-index: 1;
}
.stats-panel h3 {
font-size: 0.55rem;
letter-spacing: 0.25em;
color: var(--primary);
margin-bottom: 1rem;
text-shadow: 0 0 10px rgba(0,255,136,0.5);
}
.stat-row {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 0.75rem;
padding: 0.6rem 0;
border-bottom: 1px solid rgba(255,255,255,0.05);
}
.stat-row:last-child { border-bottom: none; }
.stat-label {
color: var(--muted);
}
.stat-value {
font-family: var(--mono);
font-size: 0.9rem;
font-weight: 500;
color: var(--primary);
text-shadow: 0 0 15px rgba(0,255,136,0.6);
}
.stat-value.highlight {
color: var(--cyan);
text-shadow: 0 0 15px rgba(34,211,238,0.6);
}
.stat-value.warning {
color: var(--yellow);
text-shadow: 0 0 15px rgba(250,204,21,0.6);
}
.stat-value.accent {
color: var(--pink);
text-shadow: 0 0 15px rgba(236,72,153,0.6);
}
/* Activity Bar */
.activity-bar {
height: 4px;
background: rgba(255,255,255,0.1);
border-radius: 2px;
margin-top: 0.5rem;
overflow: hidden;
}
.activity-bar-fill {
height: 100%;
background: linear-gradient(90deg, var(--primary), var(--cyan));
border-radius: 2px;
transition: width 0.3s ease;
box-shadow: 0 0 10px var(--primary);
}
/* Canvas Area */
.canvas-area {
position: relative;
display: flex;
flex-direction: column;
background: var(--bg);
overflow: hidden;
}
.canvas-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0.75rem 1.5rem;
background: linear-gradient(90deg, rgba(0,255,136,0.03) 0%, transparent 50%, rgba(0,170,255,0.03) 100%);
border-bottom: 1px solid rgba(255,255,255,0.05);
position: relative;
z-index: 10;
}
.canvas-title {
font-size: 0.85rem;
font-weight: 600;
color: var(--text);
display: flex;
align-items: center;
gap: 0.75rem;
}
.canvas-title .live-indicator {
width: 8px;
height: 8px;
background: var(--primary);
border-radius: 50%;
animation: pulse 2s ease-in-out infinite;
box-shadow: 0 0 10px var(--primary);
}
@keyframes pulse {
0%, 100% { opacity: 1; transform: scale(1); }
50% { opacity: 0.5; transform: scale(1.2); }
}
.view-modes {
display: flex;
gap: 0.5rem;
background: rgba(255,255,255,0.03);
padding: 0.35rem;
border-radius: 8px;
}
.view-mode {
padding: 0.5rem 1rem;
font-family: var(--mono);
font-size: 0.65rem;
background: transparent;
border: none;
color: var(--muted);
border-radius: 6px;
cursor: pointer;
transition: all 0.3s ease;
letter-spacing: 0.05em;
}
.view-mode:hover {
color: var(--text);
background: rgba(255,255,255,0.05);
}
.view-mode.active {
background: var(--primary);
color: var(--bg);
box-shadow: 0 0 20px rgba(0,255,136,0.4);
}
.canvas-container {
flex: 1;
position: relative;
}
#simulationCanvas {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
cursor: none;
}
/* Canvas Overlay Effects */
.canvas-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
background:
radial-gradient(ellipse at 20% 20%, rgba(0,255,136,0.03) 0%, transparent 50%),
radial-gradient(ellipse at 80% 80%, rgba(0,170,255,0.03) 0%, transparent 50%),
radial-gradient(ellipse at 50% 50%, rgba(168,85,247,0.02) 0%, transparent 70%);
}
.vignette {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
background: radial-gradient(ellipse at center, transparent 40%, rgba(0,0,0,0.6) 100%);
}
/* Floating Info Panel */
.info-panel {
position: absolute;
top: 1rem;
right: 1rem;
background: rgba(13,13,18,0.9);
backdrop-filter: blur(10px);
border: 1px solid rgba(0,255,136,0.2);
border-radius: 12px;
padding: 1rem 1.25rem;
font-size: 0.7rem;
color: var(--muted);
z-index: 20;
max-width: 200px;
}
.info-panel h4 {
color: var(--primary);
font-size: 0.6rem;
letter-spacing: 0.15em;
margin-bottom: 0.5rem;
}
.info-panel p {
line-height: 1.5;
}
/* Tooltip */
.tooltip {
position: absolute;
background: rgba(13,13,18,0.95);
backdrop-filter: blur(10px);
border: 1px solid rgba(0,255,136,0.3);
border-radius: 10px;
padding: 0.75rem 1rem;
font-size: 0.75rem;
pointer-events: none;
opacity: 0;
transition: opacity 0.2s ease, transform 0.2s ease;
z-index: 100;
transform: translateY(10px);
box-shadow: 0 10px 40px rgba(0,0,0,0.5);
}
.tooltip.visible {
opacity: 1;
transform: translateY(0);
}
.tooltip-title {
color: var(--primary);
font-weight: 600;
margin-bottom: 0.25rem;
}
.tooltip-content {
color: var(--muted);
}
/* Click Ripple Effect */
.ripple {
position: absolute;
border-radius: 50%;
background: radial-gradient(circle, rgba(0,255,136,0.4) 0%, transparent 70%);
animation: ripple-expand 0.8s ease-out forwards;
pointer-events: none;
}
@keyframes ripple-expand {
0% {
width: 0;
height: 0;
opacity: 1;
}
100% {
width: 200px;
height: 200px;
opacity: 0;
}
}
/* Neuron Add Animation */
.neuron-add-effect {
position: absolute;
width: 60px;
height: 60px;
border: 2px solid var(--cyan);
border-radius: 50%;
animation: neuron-spawn 0.5s ease-out forwards;
pointer-events: none;
}
@keyframes neuron-spawn {
0% {
transform: translate(-50%, -50%) scale(0);
opacity: 1;
}
100% {
transform: translate(-50%, -50%) scale(2);
opacity: 0;
}
}
/* Chapter Navigation */
.chapter-nav {
position: fixed;
bottom: 0;
left: 0;
right: 0;
display: flex;
justify-content: space-between;
padding: 0.75rem 2rem;
background: linear-gradient(180deg, transparent 0%, rgba(5,5,8,0.95) 50%);
z-index: 50;
}
.chapter-nav a {
font-family: var(--mono);
font-size: 0.6rem;
letter-spacing: 0.1em;
color: var(--muted);
text-decoration: none;
transition: all 0.3s ease;
padding: 0.5rem 1rem;
border-radius: 6px;
background: rgba(255,255,255,0.03);
border: 1px solid rgba(255,255,255,0.05);
}
.chapter-nav a:hover {
color: var(--primary);
background: rgba(0,255,136,0.1);
border-color: rgba(0,255,136,0.3);
}
/* Mobile Responsive */
@media (max-width: 900px) {
.playground {
grid-template-columns: 1fr;
}
.sidebar {
position: fixed;
left: -320px;
top: 52px;
height: calc(100vh - 52px);
width: 320px;
z-index: 1000;
transition: left 0.3s ease;
}
.sidebar.open {
left: 0;
}
.mobile-toggle {
display: block;
position: fixed;
bottom: 60px;
left: 1rem;
z-index: 1001;
padding: 0.75rem;
background: var(--primary);
border: none;
border-radius: 50%;
color: var(--bg);
cursor: pointer;
box-shadow: 0 4px 20px rgba(0,255,136,0.4);
}
.cursor, .cursor-dot {
display: none;
}
}
@media (min-width: 901px) {
.mobile-toggle {
display: none;
}
}
/* Scrollbar */
::-webkit-scrollbar {
width: 6px;
}
::-webkit-scrollbar-track {
background: var(--bg);
}
::-webkit-scrollbar-thumb {
background: var(--primary);
border-radius: 3px;
}
::-webkit-scrollbar-thumb:hover {
background: var(--cyan);
}
</style>
</head>
<body>
<!-- Custom Cursor -->
<div class="cursor" id="cursor"></div>
<div class="cursor-dot" id="cursorDot"></div>
<nav class="nav">
<div class="nav-logo">MEGAMIND</div>
<div class="nav-chapter"><span>13</span> / NEURAL PLAYGROUND</div>
</nav>
<div class="playground">
<aside class="sidebar" id="sidebar">
<div class="sidebar-section">
<h2>NETWORK PARAMETERS</h2>
<div class="control-group">
<div class="control-label">
<span>Neuron Count</span>
<span class="control-value" id="neuronValue">150</span>
</div>
<input type="range" id="neuronCount" min="50" max="500" value="150">
</div>
<div class="control-group">
<div class="control-label">
<span>Connection Density</span>
<span class="control-value" id="densityValue">40%</span>
</div>
<input type="range" id="connectionDensity" min="10" max="100" value="40">
</div>
<div class="control-group">
<div class="control-label">
<span>Firing Threshold</span>
<span class="control-value" id="thresholdValue">0.65</span>
</div>
<input type="range" id="firingThreshold" min="30" max="95" value="65">
</div>
<div class="control-group">
<div class="control-label">
<span>Signal Decay</span>
<span class="control-value" id="decayValue">0.92</span>
</div>
<input type="range" id="decayRate" min="80" max="99" value="92">
</div>
<div class="control-group">
<div class="control-label">
<span>Propagation Speed</span>
<span class="control-value" id="speedValue">1.0x</span>
</div>
<input type="range" id="propagationSpeed" min="25" max="200" value="100">
</div>
</div>
<div class="sidebar-section">
<h2>ACTIONS</h2>
<div class="btn-group">
<button class="btn btn-primary" id="stimulateBtn">Stimulate Region</button>
<button class="btn btn-accent" id="randomizeBtn">Randomize Network</button>
<button class="btn btn-secondary" id="resetBtn">Reset Simulation</button>
</div>
</div>
<div class="sidebar-section">
<div class="stats-panel">
<div class="stats-panel-inner">
<h3>LIVE STATISTICS</h3>
<div class="stat-row">
<span class="stat-label">Total Neurons</span>
<span class="stat-value" id="totalNeurons">150</span>
</div>
<div class="stat-row">
<span class="stat-label">Active Neurons</span>
<span class="stat-value highlight" id="activeCount">0</span>
</div>
<div class="stat-row">
<span class="stat-label">Connections</span>
<span class="stat-value" id="connectionCount">0</span>
</div>
<div class="stat-row">
<span class="stat-label">Spikes/sec</span>
<span class="stat-value warning" id="spikeRate">0</span>
</div>
<div class="stat-row">
<span class="stat-label">Network Energy</span>
<span class="stat-value accent" id="energyValue">0.00</span>
</div>
<div class="stat-row">
<span class="stat-label">Avg Potential</span>
<span class="stat-value" id="avgPotential">0.00</span>
</div>
<div class="activity-bar">
<div class="activity-bar-fill" id="activityBar" style="width: 0%"></div>
</div>
</div>
</div>
</div>
</aside>
<main class="canvas-area">
<div class="canvas-header">
<span class="canvas-title">
<span class="live-indicator"></span>
Neural Network Simulation
</span>
<div class="view-modes">
<button class="view-mode active" data-mode="network">Network</button>
<button class="view-mode" data-mode="activity">Activity</button>
<button class="view-mode" data-mode="heatmap">Heatmap</button>
</div>
</div>
<div class="canvas-container">
<canvas id="simulationCanvas"></canvas>
<div class="canvas-overlay"></div>
<div class="vignette"></div>
<div class="info-panel">
<h4>INSTRUCTIONS</h4>
<p>Click anywhere to add neurons. Click on neurons to stimulate them. Adjust parameters to see network behavior change in real-time.</p>
</div>
</div>
<div class="tooltip" id="tooltip">
<div class="tooltip-title" id="tooltipTitle">Neuron #0</div>
<div class="tooltip-content" id="tooltipContent">Potential: 0.00</div>
</div>
</main>
</div>
<button class="mobile-toggle" id="mobileToggle">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="3" y1="12" x2="21" y2="12"></line>
<line x1="3" y1="6" x2="21" y2="6"></line>
<line x1="3" y1="18" x2="21" y2="18"></line>
</svg>
</button>
<nav class="chapter-nav">
<a href="ch12-experiments.html">Previous: Experiments</a>
<a href="ch14-human.html">Next: The Human Layer</a>
</nav>
<script>
// ==========================================
// NEURAL PLAYGROUND - Interactive Simulation
// ==========================================
const canvas = document.getElementById('simulationCanvas');
const ctx = canvas.getContext('2d');
const tooltip = document.getElementById('tooltip');
const cursor = document.getElementById('cursor');
const cursorDot = document.getElementById('cursorDot');
// State
let neurons = [];
let connections = [];
let viewMode = 'network';
let spikeCount = 0;
let lastSpikeReset = Date.now();
let animationId = null;
let mousePos = { x: 0, y: 0 };
let hoveredNeuron = null;
let isMouseDown = false;
// Color Palettes
const neuronColors = {
resting: '#1a1a2e',
active: '#00ff88',
firing: '#22d3ee',
refractory: '#a855f7'
};
const connectionColors = {
inactive: 'rgba(100, 100, 120, 0.08)',
active: 'rgba(0, 255, 136, 0.6)',
propagating: 'rgba(34, 211, 238, 0.8)'
};
// Region colors for network view
const regionColors = [
{ base: '#ff6b6b', glow: 'rgba(255, 107, 107, 0.3)' },
{ base: '#4ecdc4', glow: 'rgba(78, 205, 196, 0.3)' },
{ base: '#a855f7', glow: 'rgba(168, 85, 247, 0.3)' },
{ base: '#f59e0b', glow: 'rgba(245, 158, 11, 0.3)' },
{ base: '#ec4899', glow: 'rgba(236, 72, 153, 0.3)' },
{ base: '#22d3ee', glow: 'rgba(34, 211, 238, 0.3)' },
{ base: '#84cc16', glow: 'rgba(132, 204, 22, 0.3)' }
];
// ==========================================
// CANVAS SETUP
// ==========================================
function resizeCanvas() {
const container = canvas.parentElement;
const rect = container.getBoundingClientRect();
canvas.width = rect.width;
canvas.height = rect.height;
}
resizeCanvas();
window.addEventListener('resize', () => {
resizeCanvas();
redistributeNeurons();
});
function redistributeNeurons() {
neurons.forEach(n => {
n.x = Math.min(n.x, canvas.width - 20);
n.y = Math.min(n.y, canvas.height - 20);
});
}
// ==========================================
// CUSTOM CURSOR
// ==========================================
document.addEventListener('mousemove', (e) => {
mousePos.x = e.clientX;
mousePos.y = e.clientY;
cursor.style.left = e.clientX + 'px';
cursor.style.top = e.clientY + 'px';
cursorDot.style.left = e.clientX + 'px';
cursorDot.style.top = e.clientY + 'px';
});
document.addEventListener('mousedown', () => {
isMouseDown = true;
cursor.classList.add('clicking');
});
document.addEventListener('mouseup', () => {
isMouseDown = false;
cursor.classList.remove('clicking');
});
canvas.addEventListener('mouseenter', () => {
cursor.classList.add('active');
});
canvas.addEventListener('mouseleave', () => {
cursor.classList.remove('active');
hideTooltip();
});
// ==========================================
// NEURON CLASS
// ==========================================
class Neuron {
constructor(x, y, id) {
this.id = id;
this.x = x;
this.y = y;
this.potential = Math.random() * 0.2;
this.active = false;
this.refractory = 0;
this.region = Math.floor(Math.random() * regionColors.length);
this.radius = 4 + Math.random() * 3;
this.baseRadius = this.radius;
this.pulsePhase = Math.random() * Math.PI * 2;
this.connections = [];
this.lastFired = 0;
this.fireCount = 0;
}
update(threshold, decay, speed) {
// Pulse animation
this.pulsePhase += 0.05 * speed;
if (this.refractory > 0) {
this.refractory -= speed;
this.active = false;
this.potential *= 0.5;
} else if (this.potential > threshold) {
this.fire(speed);
} else {
this.active = false;
this.potential *= decay;
// Small random noise
this.potential += (Math.random() - 0.5) * 0.01;
this.potential = Math.max(0, Math.min(1, this.potential));
}
// Visual radius based on state
if (this.active) {
this.radius = this.baseRadius * 2.5;
} else if (this.refractory > 0) {
this.radius = this.baseRadius * 1.5;
} else {
this.radius = this.baseRadius + Math.sin(this.pulsePhase) * 0.5 + this.potential * 3;
}
}
fire(speed) {
this.active = true;
this.refractory = 8;
this.lastFired = Date.now();
this.fireCount++;
spikeCount++;
// Propagate signal to connected neurons
this.connections.forEach(conn => {
const target = conn.target;
const signal = conn.weight * (0.15 + Math.random() * 0.1);
// Create signal propagation animation
conn.signalProgress = 0;
conn.signalActive = true;
setTimeout(() => {
if (target.refractory <= 0) {
target.potential += signal;
}
}, 50 / speed);
});
this.potential = 0;
}
draw(ctx, viewMode) {
const color = regionColors[this.region];
// Draw glow for active neurons
if (this.active) {
const gradient = ctx.createRadialGradient(this.x, this.y, 0, this.x, this.y, this.radius * 4);
gradient.addColorStop(0, 'rgba(0, 255, 136, 0.8)');
gradient.addColorStop(0.5, 'rgba(0, 255, 136, 0.2)');
gradient.addColorStop(1, 'transparent');
ctx.fillStyle = gradient;
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius * 4, 0, Math.PI * 2);
ctx.fill();
} else if (this.potential > 0.3) {
const gradient = ctx.createRadialGradient(this.x, this.y, 0, this.x, this.y, this.radius * 2);
gradient.addColorStop(0, `rgba(34, 211, 238, ${this.potential * 0.5})`);
gradient.addColorStop(1, 'transparent');
ctx.fillStyle = gradient;
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius * 2, 0, Math.PI * 2);
ctx.fill();
}
// Draw neuron body
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
if (viewMode === 'activity') {
if (this.active) {
ctx.fillStyle = neuronColors.active;
} else if (this.refractory > 0) {
ctx.fillStyle = neuronColors.refractory;
} else {
const intensity = Math.min(1, this.potential * 2);
ctx.fillStyle = `rgba(34, 211, 238, ${0.3 + intensity * 0.7})`;
}
} else if (viewMode === 'heatmap') {
const heat = this.potential + (this.active ? 0.5 : 0);
const r = Math.floor(heat * 255);
const g = Math.floor((1 - heat) * 100);
const b = Math.floor((1 - heat) * 255);
ctx.fillStyle = `rgb(${r}, ${g}, ${b})`;
} else {
if (this.active) {
ctx.fillStyle = neuronColors.active;
} else {
ctx.fillStyle = color.base;
}
}
ctx.fill();
// Inner highlight
if (!this.active && viewMode !== 'heatmap') {
ctx.beginPath();
ctx.arc(this.x - this.radius * 0.3, this.y - this.radius * 0.3, this.radius * 0.3, 0, Math.PI * 2);
ctx.fillStyle = 'rgba(255, 255, 255, 0.2)';
ctx.fill();
}
}
}
// ==========================================
// CONNECTION CLASS
// ==========================================
class Connection {
constructor(source, target, weight) {
this.source = source;
this.target = target;
this.weight = weight;
this.signalProgress = 0;
this.signalActive = false;
}
update(speed) {
if (this.signalActive) {
this.signalProgress += 0.1 * speed;
if (this.signalProgress >= 1) {
this.signalActive = false;
this.signalProgress = 0;
}
}
}
draw(ctx, viewMode) {
const active = this.source.active || this.target.active || this.signalActive;
ctx.beginPath();
ctx.moveTo(this.source.x, this.source.y);
ctx.lineTo(this.target.x, this.target.y);
if (this.signalActive) {
// Animated signal propagation
const gradient = ctx.createLinearGradient(
this.source.x, this.source.y,
this.target.x, this.target.y
);
const progress = this.signalProgress;
gradient.addColorStop(Math.max(0, progress - 0.2), 'transparent');
gradient.addColorStop(progress, 'rgba(0, 255, 136, 0.9)');
gradient.addColorStop(Math.min(1, progress + 0.1), 'rgba(34, 211, 238, 0.9)');
gradient.addColorStop(Math.min(1, progress + 0.2), 'transparent');
ctx.strokeStyle = gradient;
ctx.lineWidth = 3;
} else if (active) {
ctx.strokeStyle = connectionColors.active;
ctx.lineWidth = 2;
} else {
ctx.strokeStyle = connectionColors.inactive;
ctx.lineWidth = 1;
}
ctx.stroke();
}
}
// ==========================================
// NETWORK INITIALIZATION
// ==========================================
function initNetwork() {
const count = parseInt(document.getElementById('neuronCount').value);
const densityPercent = parseInt(document.getElementById('connectionDensity').value);
neurons = [];
connections = [];
// Create neurons with spacing
const margin = 50;
for (let i = 0; i < count; i++) {
const x = margin + Math.random() * (canvas.width - margin * 2);
const y = margin + Math.random() * (canvas.height - margin * 2);
neurons.push(new Neuron(x, y, i));
}
// Create connections based on distance and density
const maxDistance = 150;
const connectionProbability = densityPercent / 100;
for (let i = 0; i < neurons.length; i++) {
for (let j = i + 1; j < neurons.length; j++) {
const dx = neurons[i].x - neurons[j].x;
const dy = neurons[i].y - neurons[j].y;
const dist = Math.sqrt(dx * dx + dy * dy);
if (dist < maxDistance) {
const distFactor = 1 - (dist / maxDistance);
if (Math.random() < connectionProbability * distFactor) {
const weight = 0.1 + Math.random() * 0.2;
const conn = new Connection(neurons[i], neurons[j], weight);
connections.push(conn);
neurons[i].connections.push({ target: neurons[j], weight, connection: conn });
neurons[j].connections.push({ target: neurons[i], weight, connection: conn });
}
}
}
}
updateStats();
}
// ==========================================
// SIMULATION UPDATE
// ==========================================
function update() {
const threshold = parseInt(document.getElementById('firingThreshold').value) / 100;
const decay = parseInt(document.getElementById('decayRate').value) / 100;
const speed = parseInt(document.getElementById('propagationSpeed').value) / 100;
// Update neurons
neurons.forEach(n => n.update(threshold, decay, speed));
// Update connections
connections.forEach(c => c.update(speed));
// Update statistics
updateStats();
}
function updateStats() {
const activeCount = neurons.filter(n => n.active).length;
const totalPotential = neurons.reduce((sum, n) => sum + n.potential, 0);
const avgPotential = neurons.length > 0 ? totalPotential / neurons.length : 0;
const energy = neurons.reduce((sum, n) => sum + n.potential + (n.active ? 0.5 : 0), 0);
document.getElementById('totalNeurons').textContent = neurons.length;
document.getElementById('activeCount').textContent = activeCount;
document.getElementById('connectionCount').textContent = connections.length;
document.getElementById('avgPotential').textContent = avgPotential.toFixed(3);
document.getElementById('energyValue').textContent = energy.toFixed(2);
// Activity bar
const activityPercent = (activeCount / Math.max(1, neurons.length)) * 100;
document.getElementById('activityBar').style.width = Math.min(100, activityPercent * 5) + '%';
// Spike rate (per second)
const now = Date.now();
if (now - lastSpikeReset > 1000) {
document.getElementById('spikeRate').textContent = spikeCount;
spikeCount = 0;
lastSpikeReset = now;
}
}
// ==========================================
// RENDERING
// ==========================================
function render() {
// Clear with fade effect for trails
ctx.fillStyle = 'rgba(5, 5, 8, 0.2)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Full clear every few frames to prevent artifacts
if (Math.random() < 0.1) {
ctx.fillStyle = '#050508';
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
// Draw grid background
drawGrid();
// Draw connections
connections.forEach(c => c.draw(ctx, viewMode));
// Draw neurons
neurons.forEach(n => n.draw(ctx, viewMode));
// Draw hovered neuron highlight
if (hoveredNeuron) {
ctx.beginPath();
ctx.arc(hoveredNeuron.x, hoveredNeuron.y, hoveredNeuron.radius + 8, 0, Math.PI * 2);
ctx.strokeStyle = 'rgba(255, 255, 255, 0.5)';
ctx.lineWidth = 2;
ctx.stroke();
}
}
function drawGrid() {
const gridSize = 40;
ctx.strokeStyle = 'rgba(255, 255, 255, 0.02)';
ctx.lineWidth = 1;
for (let x = 0; x < canvas.width; x += gridSize) {
ctx.beginPath();
ctx.moveTo(x, 0);
ctx.lineTo(x, canvas.height);
ctx.stroke();
}
for (let y = 0; y < canvas.height; y += gridSize) {
ctx.beginPath();
ctx.moveTo(0, y);
ctx.lineTo(canvas.width, y);
ctx.stroke();
}
}
// ==========================================
// ANIMATION LOOP
// ==========================================
function animate() {
update();
render();
animationId = requestAnimationFrame(animate);
}
// ==========================================
// INTERACTIONS
// ==========================================
function addNeuron(x, y) {
const newNeuron = new Neuron(x, y, neurons.length);
newNeuron.potential = 0.8; // Start with high potential
neurons.push(newNeuron);
// Connect to nearby neurons
const density = parseInt(document.getElementById('connectionDensity').value) / 100;
const maxDist = 120;
neurons.forEach((n, i) => {
if (n === newNeuron) return;
const dx = n.x - newNeuron.x;
const dy = n.y - newNeuron.y;
const dist = Math.sqrt(dx * dx + dy * dy);
if (dist < maxDist && Math.random() < density) {
const weight = 0.1 + Math.random() * 0.2;
const conn = new Connection(newNeuron, n, weight);
connections.push(conn);
newNeuron.connections.push({ target: n, weight, connection: conn });
n.connections.push({ target: newNeuron, weight, connection: conn });
}
});
// Visual feedback
createSpawnEffect(x, y);
updateStats();
}
function stimulateArea(x, y, radius = 100) {
neurons.forEach(n => {
const dx = n.x - x;
const dy = n.y - y;
const dist = Math.sqrt(dx * dx + dy * dy);
if (dist < radius) {
const intensity = 1 - (dist / radius);
n.potential = Math.min(1, n.potential + intensity * 0.8);
}
});
createRippleEffect(x, y);
}
function stimulateNeuron(neuron) {
neuron.potential = 1;
createRippleEffect(neuron.x, neuron.y);
}
function createRippleEffect(x, y) {
const rect = canvas.getBoundingClientRect();
const ripple = document.createElement('div');
ripple.className = 'ripple';
ripple.style.left = (x + rect.left - 100) + 'px';
ripple.style.top = (y + rect.top - 100) + 'px';
document.body.appendChild(ripple);
setTimeout(() => ripple.remove(), 800);
}
function createSpawnEffect(x, y) {
const rect = canvas.getBoundingClientRect();
const effect = document.createElement('div');
effect.className = 'neuron-add-effect';
effect.style.left = (x + rect.left) + 'px';
effect.style.top = (y + rect.top) + 'px';
document.body.appendChild(effect);
setTimeout(() => effect.remove(), 500);
}
function findNeuronAt(x, y) {
for (let i = neurons.length - 1; i >= 0; i--) {
const n = neurons[i];
const dx = n.x - x;
const dy = n.y - y;
const dist = Math.sqrt(dx * dx + dy * dy);
if (dist < n.radius + 10) {
return n;
}
}
return null;
}
function showTooltip(neuron, x, y) {
const rect = canvas.getBoundingClientRect();
tooltip.style.left = (x + rect.left + 20) + 'px';
tooltip.style.top = (y + rect.top - 20) + 'px';
document.getElementById('tooltipTitle').textContent = `Neuron #${neuron.id}`;
document.getElementById('tooltipContent').innerHTML = `
Potential: ${neuron.potential.toFixed(3)}<br>
State: ${neuron.active ? 'Firing' : neuron.refractory > 0 ? 'Refractory' : 'Resting'}<br>
Connections: ${neuron.connections.length}<br>
Fire Count: ${neuron.fireCount}
`;
tooltip.classList.add('visible');
}
function hideTooltip() {
tooltip.classList.remove('visible');
}
// ==========================================
// EVENT LISTENERS
// ==========================================
// Canvas interactions
canvas.addEventListener('click', (e) => {
const rect = canvas.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
const neuron = findNeuronAt(x, y);
if (neuron) {
stimulateNeuron(neuron);
} else {
addNeuron(x, y);
}
});
canvas.addEventListener('mousemove', (e) => {
const rect = canvas.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
hoveredNeuron = findNeuronAt(x, y);
if (hoveredNeuron) {
showTooltip(hoveredNeuron, x, y);
} else {
hideTooltip();
}
});
// Control sliders
document.getElementById('neuronCount').addEventListener('input', (e) => {
document.getElementById('neuronValue').textContent = e.target.value;
});
document.getElementById('neuronCount').addEventListener('change', () => {
initNetwork();
});
document.getElementById('connectionDensity').addEventListener('input', (e) => {
document.getElementById('densityValue').textContent = e.target.value + '%';
});
document.getElementById('connectionDensity').addEventListener('change', () => {
initNetwork();
});
document.getElementById('firingThreshold').addEventListener('input', (e) => {
document.getElementById('thresholdValue').textContent = (e.target.value / 100).toFixed(2);
});
document.getElementById('decayRate').addEventListener('input', (e) => {
document.getElementById('decayValue').textContent = (e.target.value / 100).toFixed(2);
});
document.getElementById('propagationSpeed').addEventListener('input', (e) => {
document.getElementById('speedValue').textContent = (e.target.value / 100).toFixed(1) + 'x';
});
// Buttons
document.getElementById('stimulateBtn').addEventListener('click', () => {
const x = 100 + Math.random() * (canvas.width - 200);
const y = 100 + Math.random() * (canvas.height - 200);
stimulateArea(x, y, 150);
});
document.getElementById('randomizeBtn').addEventListener('click', () => {
// Randomize parameters
const neuronSlider = document.getElementById('neuronCount');
const densitySlider = document.getElementById('connectionDensity');
const thresholdSlider = document.getElementById('firingThreshold');
neuronSlider.value = 80 + Math.floor(Math.random() * 200);
densitySlider.value = 20 + Math.floor(Math.random() * 60);
thresholdSlider.value = 40 + Math.floor(Math.random() * 40);
document.getElementById('neuronValue').textContent = neuronSlider.value;
document.getElementById('densityValue').textContent = densitySlider.value + '%';
document.getElementById('thresholdValue').textContent = (thresholdSlider.value / 100).toFixed(2);
initNetwork();