LukasBe commited on
Commit
dcdc8d7
·
verified ·
1 Parent(s): 23e823a

Add 2 files

Browse files
Files changed (2) hide show
  1. README.md +7 -5
  2. index.html +1337 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: 3d Effects
3
- emoji: 💻
4
- colorFrom: pink
5
- colorTo: pink
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: 3d-effects
3
+ emoji: 🐳
4
+ colorFrom: gray
5
+ colorTo: green
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,1337 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Quantum Nexus™ 3D Energy Matrix</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
10
+ <script src="https://cdn.jsdelivr.net/npm/three@0.132.2/build/three.min.js"></script>
11
+ <script src="https://cdn.jsdelivr.net/npm/three@0.132.2/examples/js/controls/OrbitControls.js"></script>
12
+ <script src="https://cdn.jsdelivr.net/npm/three@0.132.2/examples/js/loaders/GLTFLoader.js"></script>
13
+ <script src="https://cdn.jsdelivr.net/npm/gsap@3.11.4/dist/gsap.min.js"></script>
14
+ <script src="https://cdn.jsdelivr.net/npm/three@0.132.2/examples/js/postprocessing/EffectComposer.js"></script>
15
+ <script src="https://cdn.jsdelivr.net/npm/three@0.132.2/examples/js/postprocessing/RenderPass.js"></script>
16
+ <script src="https://cdn.jsdelivr.net/npm/three@0.132.2/examples/js/postprocessing/ShaderPass.js"></script>
17
+ <script src="https://cdn.jsdelivr.net/npm/three@0.132.2/examples/js/postprocessing/UnrealBloomPass.js"></script>
18
+ <script src="https://cdn.jsdelivr.net/npm/three@0.132.2/examples/js/shaders/CopyShader.js"></script>
19
+ <script src="https://cdn.jsdelivr.net/npm/three@0.132.2/examples/js/shaders/LuminosityHighPassShader.js"></script>
20
+ <script src="https://cdn.jsdelivr.net/npm/three@0.132.2/examples/js/shaders/HorizontalBlurShader.js"></script>
21
+ <script src="https://cdn.jsdelivr.net/npm/three@0.132.2/examples/js/shaders/VerticalBlurShader.js"></script>
22
+ <style>
23
+ body {
24
+ margin: 0;
25
+ padding: 0;
26
+ overflow: hidden;
27
+ font-family: 'Inter', sans-serif;
28
+ }
29
+
30
+ #three-container {
31
+ position: fixed;
32
+ top: 0;
33
+ left: 0;
34
+ width: 100%;
35
+ height: 100%;
36
+ z-index: -1;
37
+ }
38
+
39
+ #ui-container {
40
+ position: absolute;
41
+ top: 0;
42
+ left: 0;
43
+ width: 100%;
44
+ height: 100%;
45
+ pointer-events: none;
46
+ }
47
+
48
+ .ui-panel {
49
+ pointer-events: all;
50
+ background: rgba(15, 23, 42, 0.7);
51
+ backdrop-filter: blur(16px);
52
+ -webkit-backdrop-filter: blur(16px);
53
+ border: 1px solid rgba(255, 255, 255, 0.08);
54
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
55
+ border-radius: 16px;
56
+ transition: all 0.3s ease;
57
+ }
58
+
59
+ .ui-panel:hover {
60
+ transform: translateY(-3px);
61
+ box-shadow: 0 10px 20px rgba(0, 0, 0, 0.4);
62
+ }
63
+
64
+ .energy-cell {
65
+ background: linear-gradient(145deg, rgba(30, 41, 59, 0.8), rgba(15, 23, 42, 0.9));
66
+ border-radius: 12px;
67
+ transition: all 0.3s ease;
68
+ }
69
+
70
+ .energy-cell:hover {
71
+ transform: translateY(-3px) scale(1.02);
72
+ box-shadow: 0 10px 20px rgba(0, 0, 0, 0.4);
73
+ }
74
+
75
+ .flow-line {
76
+ position: relative;
77
+ overflow: hidden;
78
+ }
79
+
80
+ .flow-line::after {
81
+ content: '';
82
+ position: absolute;
83
+ top: 0;
84
+ left: 0;
85
+ right: 0;
86
+ bottom: 0;
87
+ background: linear-gradient(90deg, transparent, currentColor, transparent);
88
+ background-size: 200% 100%;
89
+ animation: energy-flow 2s linear infinite;
90
+ opacity: 0.5;
91
+ }
92
+
93
+ @keyframes energy-flow {
94
+ 0% { background-position: 0% 50%; }
95
+ 100% { background-position: 100% 50%; }
96
+ }
97
+
98
+ .pulse-glow {
99
+ animation: pulse-glow 2s ease-in-out infinite;
100
+ }
101
+
102
+ @keyframes pulse-glow {
103
+ 0% { opacity: 0.7; box-shadow: 0 0 5px currentColor; }
104
+ 50% { opacity: 1; box-shadow: 0 0 15px currentColor; }
105
+ 100% { opacity: 0.7; box-shadow: 0 0 5px currentColor; }
106
+ }
107
+
108
+ .gradient-text {
109
+ background-clip: text;
110
+ -webkit-background-clip: text;
111
+ color: transparent;
112
+ }
113
+
114
+ .glow-border {
115
+ position: relative;
116
+ }
117
+
118
+ .glow-border::after {
119
+ content: '';
120
+ position: absolute;
121
+ inset: 0;
122
+ border-radius: inherit;
123
+ padding: 1px;
124
+ background: linear-gradient(135deg, rgba(59, 130, 246, 0.5), rgba(14, 165, 233, 0.5));
125
+ -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
126
+ -webkit-mask-composite: xor;
127
+ mask-composite: exclude;
128
+ pointer-events: none;
129
+ }
130
+
131
+ .energy-badge {
132
+ transition: all 0.3s ease;
133
+ }
134
+
135
+ .energy-badge:hover {
136
+ transform: scale(1.05);
137
+ box-shadow: 0 0 15px currentColor;
138
+ }
139
+
140
+ .grid-node {
141
+ position: absolute;
142
+ width: 60px;
143
+ height: 60px;
144
+ border-radius: 50%;
145
+ display: flex;
146
+ align-items: center;
147
+ justify-content: center;
148
+ font-size: 24px;
149
+ color: white;
150
+ cursor: pointer;
151
+ transition: all 0.3s ease;
152
+ z-index: 10;
153
+ }
154
+
155
+ .grid-node:hover {
156
+ transform: scale(1.2);
157
+ }
158
+
159
+ /* New styles for advanced effects */
160
+ .particle-trail {
161
+ position: absolute;
162
+ width: 100%;
163
+ height: 100%;
164
+ pointer-events: none;
165
+ }
166
+
167
+ .energy-pulse {
168
+ position: absolute;
169
+ border-radius: 50%;
170
+ background: rgba(59, 130, 246, 0.5);
171
+ transform: scale(0);
172
+ animation: energy-pulse 3s infinite;
173
+ pointer-events: none;
174
+ }
175
+
176
+ @keyframes energy-pulse {
177
+ 0% { transform: scale(0); opacity: 1; }
178
+ 100% { transform: scale(3); opacity: 0; }
179
+ }
180
+ </style>
181
+ </head>
182
+ <body class="bg-slate-950 text-slate-100">
183
+ <!-- Three.js Container -->
184
+ <div id="three-container"></div>
185
+
186
+ <!-- Particle Trails -->
187
+ <div id="particle-trail" class="particle-trail"></div>
188
+
189
+ <!-- UI Container -->
190
+ <div id="ui-container">
191
+ <!-- Header -->
192
+ <header class="flex flex-col md:flex-row justify-between items-start md:items-center p-6">
193
+ <div class="mb-6 md:mb-0">
194
+ <div class="flex items-center">
195
+ <div class="w-12 h-12 rounded-xl bg-gradient-to-br from-blue-500 to-cyan-400 flex items-center justify-center mr-4 shadow-lg">
196
+ <i class="fas fa-bolt text-white text-xl"></i>
197
+ </div>
198
+ <div>
199
+ <h1 class="text-4xl font-bold bg-gradient-to-r from-blue-400 to-cyan-300 gradient-text">
200
+ Quantum Nexus™
201
+ </h1>
202
+ <p class="text-slate-400 font-medium">3D Energy Matrix Intelligence</p>
203
+ </div>
204
+ </div>
205
+ </div>
206
+
207
+ <div class="flex flex-col md:flex-row items-start md:items-center space-y-4 md:space-y-0 md:space-x-6 w-full md:w-auto">
208
+ <div class="flex items-center space-x-4">
209
+ <div class="ui-panel p-3 rounded-xl shadow-sm flex items-center">
210
+ <div class="w-3 h-3 rounded-full bg-green-500 mr-2 pulse-glow"></div>
211
+ <div>
212
+ <p class="text-xs text-slate-400">Matrix Status</p>
213
+ <p class="font-medium">Live: <span id="update-time" class="text-slate-100">Just now</span></p>
214
+ </div>
215
+ </div>
216
+ <button class="ui-panel bg-gradient-to-r from-blue-600 to-cyan-500 hover:from-blue-700 hover:to-cyan-600 text-white px-6 py-3 rounded-xl flex items-center shadow-lg transition-all duration-300 hover:shadow-xl">
217
+ <i class="fas fa-network-wired mr-2"></i> Matrix Control
218
+ </button>
219
+ </div>
220
+ </div>
221
+ </header>
222
+
223
+ <!-- Main Dashboard -->
224
+ <div class="absolute bottom-0 left-0 right-0 p-6">
225
+ <div class="ui-panel p-6 rounded-2xl max-w-4xl mx-auto">
226
+ <div class="flex justify-between items-center mb-6">
227
+ <h2 class="text-2xl font-semibold flex items-center">
228
+ <i class="fas fa-project-diagram text-blue-400 mr-3 pulse-glow"></i>
229
+ Quantum Energy Matrix
230
+ </h2>
231
+ <div class="bg-slate-800/70 px-4 py-1 rounded-full text-sm border border-slate-700/50">
232
+ <span class="text-green-400 font-medium">Optimal</span> Performance
233
+ </div>
234
+ </div>
235
+
236
+ <!-- Grid Layout -->
237
+ <div class="grid grid-cols-3 gap-4">
238
+ <!-- Solar -->
239
+ <div class="col-span-1 flex flex-col items-center">
240
+ <div class="energy-cell w-full h-32 bg-yellow-900/20 border border-yellow-500/30 flex flex-col items-center justify-center p-4 glow-border" id="solar-cell">
241
+ <div class="w-16 h-16 rounded-full bg-gradient-to-br from-yellow-400 to-yellow-600 flex items-center justify-center mb-2 shadow-lg">
242
+ <i class="fas fa-solar-panel text-white text-2xl"></i>
243
+ </div>
244
+ <h3 class="font-bold text-yellow-400 text-center">Solar Array</h3>
245
+ <p class="text-sm text-yellow-300" id="solar-value">5.2 kW</p>
246
+ </div>
247
+ </div>
248
+
249
+ <!-- Battery -->
250
+ <div class="col-span-1 flex flex-col items-center">
251
+ <div class="energy-cell w-full h-32 bg-orange-900/20 border border-orange-500/30 flex flex-col items-center justify-center p-4 glow-border" id="battery-cell">
252
+ <div class="w-16 h-16 rounded-lg bg-gradient-to-br from-orange-400 to-orange-600 flex items-center justify-center mb-2 shadow-lg">
253
+ <i class="fas fa-battery-three-quarters text-white text-2xl"></i>
254
+ </div>
255
+ <h3 class="font-bold text-orange-400 text-center">Battery Bank</h3>
256
+ <p class="text-sm text-orange-300" id="battery-value">78%</p>
257
+ </div>
258
+ </div>
259
+
260
+ <!-- Grid -->
261
+ <div class="col-span-1 flex flex-col items-center">
262
+ <div class="energy-cell w-full h-32 bg-slate-800/20 border border-slate-500/30 flex flex-col items-center justify-center p-4 glow-border" id="grid-cell">
263
+ <div class="w-16 h-16 rounded-lg bg-gradient-to-br from-slate-400 to-slate-600 flex items-center justify-center mb-2 shadow-lg">
264
+ <i class="fas fa-plug text-white text-2xl"></i>
265
+ </div>
266
+ <h3 class="font-bold text-slate-300 text-center">Grid</h3>
267
+ <p class="text-sm text-slate-300" id="grid-value">1.9 kW</p>
268
+ </div>
269
+ </div>
270
+
271
+ <!-- Status -->
272
+ <div class="col-span-3 mt-4 text-center">
273
+ <p class="text-slate-400 text-sm">Matrix Status</p>
274
+ <p class="text-xl font-bold text-green-400" id="flow-mode">Solar Exporting (1.9 kW to grid)</p>
275
+ </div>
276
+ </div>
277
+ </div>
278
+ </div>
279
+
280
+ <!-- Side Panels -->
281
+ <div class="absolute top-24 right-6 w-80 space-y-6">
282
+ <!-- System Overview -->
283
+ <div class="ui-panel p-6 rounded-2xl">
284
+ <h2 class="text-xl font-semibold mb-6 flex items-center">
285
+ <i class="fas fa-chart-network text-blue-400 mr-3"></i>
286
+ System Overview
287
+ </h2>
288
+
289
+ <div class="space-y-4">
290
+ <div class="flex justify-between items-center">
291
+ <div class="flex items-center">
292
+ <div class="w-10 h-10 rounded-lg bg-blue-900/50 flex items-center justify-center mr-3">
293
+ <i class="fas fa-solar-panel text-yellow-400"></i>
294
+ </div>
295
+ <div>
296
+ <p class="text-sm text-slate-400">Solar Production</p>
297
+ <p class="font-bold text-yellow-400">5.2 kW</p>
298
+ </div>
299
+ </div>
300
+ <div class="text-right">
301
+ <p class="text-sm text-slate-400">Today</p>
302
+ <p class="font-bold text-yellow-400">24.8 kWh</p>
303
+ </div>
304
+ </div>
305
+
306
+ <div class="flex justify-between items-center">
307
+ <div class="flex items-center">
308
+ <div class="w-10 h-10 rounded-lg bg-orange-900/50 flex items-center justify-center mr-3">
309
+ <i class="fas fa-battery-three-quarters text-orange-400"></i>
310
+ </div>
311
+ <div>
312
+ <p class="text-sm text-slate-400">Battery Storage</p>
313
+ <p class="font-bold text-orange-400">78%</p>
314
+ </div>
315
+ </div>
316
+ <div class="text-right">
317
+ <p class="text-sm text-slate-400">Capacity</p>
318
+ <p class="font-bold text-orange-400">14.2 kWh</p>
319
+ </div>
320
+ </div>
321
+
322
+ <div class="flex justify-between items-center">
323
+ <div class="flex items-center">
324
+ <div class="w-10 h-10 rounded-lg bg-blue-900/50 flex items-center justify-center mr-3">
325
+ <i class="fas fa-home text-blue-400"></i>
326
+ </div>
327
+ <div>
328
+ <p class="text-sm text-slate-400">Home Usage</p>
329
+ <p class="font-bold text-blue-400">3.3 kW</p>
330
+ </div>
331
+ </div>
332
+ <div class="text-right">
333
+ <p class="text-sm text-slate-400">Today</p>
334
+ <p class="font-bold text-blue-400">18.6 kWh</p>
335
+ </div>
336
+ </div>
337
+
338
+ <div class="flex justify-between items-center">
339
+ <div class="flex items-center">
340
+ <div class="w-10 h-10 rounded-lg bg-slate-700/50 flex items-center justify-center mr-3">
341
+ <i class="fas fa-plug text-slate-300"></i>
342
+ </div>
343
+ <div>
344
+ <p class="text-sm text-slate-400">Grid Export</p>
345
+ <p class="font-bold text-green-400">1.9 kW</p>
346
+ </div>
347
+ </div>
348
+ <div class="text-right">
349
+ <p class="text-sm text-slate-400">Today</p>
350
+ <p class="font-bold text-green-400">6.2 kWh</p>
351
+ </div>
352
+ </div>
353
+ </div>
354
+ </div>
355
+
356
+ <!-- Efficiency Metrics -->
357
+ <div class="ui-panel p-6 rounded-2xl">
358
+ <h2 class="text-xl font-semibold mb-6 flex items-center">
359
+ <i class="fas fa-tachometer-alt text-cyan-400 mr-3"></i>
360
+ Efficiency Metrics
361
+ </h2>
362
+
363
+ <div class="space-y-6">
364
+ <div>
365
+ <div class="flex justify-between mb-2">
366
+ <span class="text-sm text-slate-400">Solar Utilization</span>
367
+ <span class="text-sm font-medium text-yellow-400">92%</span>
368
+ </div>
369
+ <div class="w-full bg-slate-800/50 rounded-full h-2">
370
+ <div class="bg-gradient-to-r from-yellow-500 to-yellow-300 h-2 rounded-full" style="width: 92%"></div>
371
+ </div>
372
+ </div>
373
+
374
+ <div>
375
+ <div class="flex justify-between mb-2">
376
+ <span class="text-sm text-slate-400">Battery Efficiency</span>
377
+ <span class="text-sm font-medium text-orange-400">88%</span>
378
+ </div>
379
+ <div class="w-full bg-slate-800/50 rounded-full h-2">
380
+ <div class="bg-gradient-to-r from-orange-500 to-orange-300 h-2 rounded-full" style="width: 88%"></div>
381
+ </div>
382
+ </div>
383
+
384
+ <div>
385
+ <div class="flex justify-between mb-2">
386
+ <span class="text-sm text-slate-400">Energy Independence</span>
387
+ <span class="text-sm font-medium text-green-400">94%</span>
388
+ </div>
389
+ <div class="w-full bg-slate-800/50 rounded-full h-2">
390
+ <div class="bg-gradient-to-r from-green-500 to-green-300 h-2 rounded-full" style="width: 94%"></div>
391
+ </div>
392
+ </div>
393
+ </div>
394
+ </div>
395
+ </div>
396
+
397
+ <!-- 3D Grid Nodes -->
398
+ <div class="grid-node" style="top: 30%; left: 20%; background: rgba(245, 158, 11, 0.2); border: 2px solid rgba(245, 158, 11, 0.5);" data-type="solar">
399
+ <i class="fas fa-solar-panel text-yellow-400"></i>
400
+ </div>
401
+ <div class="grid-node" style="top: 40%; left: 70%; background: rgba(59, 130, 246, 0.2); border: 2px solid rgba(59, 130, 246, 0.5);" data-type="home">
402
+ <i class="fas fa-home text-blue-400"></i>
403
+ </div>
404
+ <div class="grid-node" style="top: 60%; left: 30%; background: rgba(249, 115, 22, 0.2); border: 2px solid rgba(249, 115, 22, 0.5);" data-type="battery">
405
+ <i class="fas fa-battery-three-quarters text-orange-400"></i>
406
+ </div>
407
+ <div class="grid-node" style="top: 70%; left: 80%; background: rgba(156, 163, 175, 0.2); border: 2px solid rgba(156, 163, 175, 0.5);" data-type="grid">
408
+ <i class="fas fa-plug text-slate-300"></i>
409
+ </div>
410
+ </div>
411
+
412
+ <script>
413
+ // Three.js Scene Setup
414
+ let scene, camera, renderer, controls, composer;
415
+ let energyLines = [];
416
+ let energyParticles = [];
417
+ let bloomPass;
418
+ let energyNodes = [];
419
+ let floatingTexts = [];
420
+ let floatingIcons = [];
421
+ let particleSystems = [];
422
+ let holographicGrid;
423
+ let energyPulseEffects = [];
424
+ let floatingEnergyOrbs = [];
425
+
426
+ // Post-processing effects
427
+ function initPostProcessing() {
428
+ const renderScene = new THREE.RenderPass(scene, camera);
429
+
430
+ bloomPass = new THREE.UnrealBloomPass(
431
+ new THREE.Vector2(window.innerWidth, window.innerHeight),
432
+ 1.5, // strength
433
+ 0.4, // radius
434
+ 0.85 // threshold
435
+ );
436
+
437
+ composer = new THREE.EffectComposer(renderer);
438
+ composer.addPass(renderScene);
439
+ composer.addPass(bloomPass);
440
+ }
441
+
442
+ // Create a holographic grid floor
443
+ function createHolographicGrid() {
444
+ const size = 50;
445
+ const divisions = 50;
446
+ const gridHelper = new THREE.GridHelper(size, divisions, 0x3b82f6, 0x1e293b);
447
+ gridHelper.position.y = 0.01;
448
+ gridHelper.material.transparent = true;
449
+ gridHelper.material.opacity = 0.3;
450
+ scene.add(gridHelper);
451
+ holographicGrid = gridHelper;
452
+
453
+ // Add pulsing center point
454
+ const centerGeometry = new THREE.CircleGeometry(1, 32);
455
+ const centerMaterial = new THREE.MeshBasicMaterial({
456
+ color: 0x3b82f6,
457
+ transparent: true,
458
+ opacity: 0.5,
459
+ blending: THREE.AdditiveBlending
460
+ });
461
+ const centerCircle = new THREE.Mesh(centerGeometry, centerMaterial);
462
+ centerCircle.rotation.x = -Math.PI / 2;
463
+ centerCircle.position.y = 0.02;
464
+ scene.add(centerCircle);
465
+
466
+ // Animation
467
+ gsap.to(centerCircle.scale, {
468
+ x: 1.5,
469
+ y: 1.5,
470
+ z: 1.5,
471
+ duration: 3,
472
+ repeat: -1,
473
+ yoyo: true,
474
+ ease: "sine.inOut"
475
+ });
476
+
477
+ gsap.to(centerCircle.material, {
478
+ opacity: 0.8,
479
+ duration: 3,
480
+ repeat: -1,
481
+ yoyo: true,
482
+ ease: "sine.inOut"
483
+ });
484
+ }
485
+
486
+ // Create floating energy orbs
487
+ function createFloatingEnergyOrbs() {
488
+ const orbCount = 15;
489
+ const orbGeometry = new THREE.SphereGeometry(0.3, 32, 32);
490
+
491
+ for (let i = 0; i < orbCount; i++) {
492
+ const color = new THREE.Color(
493
+ Math.random() * 0.5 + 0.5,
494
+ Math.random() * 0.5 + 0.5,
495
+ Math.random() * 0.5 + 0.5
496
+ );
497
+
498
+ const orbMaterial = new THREE.MeshStandardMaterial({
499
+ color: color,
500
+ emissive: color,
501
+ emissiveIntensity: 0.5,
502
+ roughness: 0.2,
503
+ metalness: 0.7,
504
+ transparent: true,
505
+ opacity: 0.8
506
+ });
507
+
508
+ const orb = new THREE.Mesh(orbGeometry, orbMaterial);
509
+
510
+ // Random position in a sphere
511
+ const radius = 15;
512
+ const theta = Math.random() * Math.PI * 2;
513
+ const phi = Math.random() * Math.PI;
514
+ orb.position.x = radius * Math.sin(phi) * Math.cos(theta);
515
+ orb.position.y = radius * Math.cos(phi) + 5;
516
+ orb.position.z = radius * Math.sin(phi) * Math.sin(theta);
517
+
518
+ // Random velocity
519
+ orb.userData = {
520
+ velocity: new THREE.Vector3(
521
+ (Math.random() - 0.5) * 0.02,
522
+ (Math.random() - 0.5) * 0.02,
523
+ (Math.random() - 0.5) * 0.02
524
+ ),
525
+ origin: orb.position.clone()
526
+ };
527
+
528
+ scene.add(orb);
529
+ floatingEnergyOrbs.push(orb);
530
+
531
+ // Add glow
532
+ const glowGeometry = new THREE.SphereGeometry(0.5, 32, 32);
533
+ const glowMaterial = new THREE.MeshBasicMaterial({
534
+ color: color,
535
+ transparent: true,
536
+ opacity: 0.3,
537
+ blending: THREE.AdditiveBlending
538
+ });
539
+ const glow = new THREE.Mesh(glowGeometry, glowMaterial);
540
+ glow.position.copy(orb.position);
541
+ scene.add(glow);
542
+
543
+ // Animation
544
+ gsap.to(orb.scale, {
545
+ x: 1.5,
546
+ y: 1.5,
547
+ z: 1.5,
548
+ duration: 2 + Math.random() * 3,
549
+ repeat: -1,
550
+ yoyo: true,
551
+ ease: "sine.inOut"
552
+ });
553
+ }
554
+ }
555
+
556
+ // Create particle system
557
+ function createParticleSystem() {
558
+ const particleCount = 2000;
559
+ const particles = new THREE.BufferGeometry();
560
+ const positions = new Float32Array(particleCount * 3);
561
+ const colors = new Float32Array(particleCount * 3);
562
+ const sizes = new Float32Array(particleCount);
563
+
564
+ const radius = 30;
565
+
566
+ for (let i = 0; i < particleCount; i++) {
567
+ // Position particles in a sphere
568
+ const theta = Math.random() * Math.PI * 2;
569
+ const phi = Math.random() * Math.PI;
570
+
571
+ positions[i * 3] = radius * Math.sin(phi) * Math.cos(theta);
572
+ positions[i * 3 + 1] = radius * Math.cos(phi);
573
+ positions[i * 3 + 2] = radius * Math.sin(phi) * Math.sin(theta);
574
+
575
+ // Random colors
576
+ colors[i * 3] = 0.5 + Math.random() * 0.5; // R
577
+ colors[i * 3 + 1] = 0.5 + Math.random() * 0.5; // G
578
+ colors[i * 3 + 2] = 0.5 + Math.random() * 0.5; // B
579
+
580
+ // Random sizes
581
+ sizes[i] = 0.1 + Math.random() * 0.5;
582
+ }
583
+
584
+ particles.setAttribute('position', new THREE.BufferAttribute(positions, 3));
585
+ particles.setAttribute('color', new THREE.BufferAttribute(colors, 3));
586
+ particles.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
587
+
588
+ const particleMaterial = new THREE.PointsMaterial({
589
+ size: 0.2,
590
+ vertexColors: true,
591
+ transparent: true,
592
+ opacity: 0.8,
593
+ blending: THREE.AdditiveBlending,
594
+ sizeAttenuation: true
595
+ });
596
+
597
+ const particleSystem = new THREE.Points(particles, particleMaterial);
598
+ scene.add(particleSystem);
599
+ particleSystems.push(particleSystem);
600
+ }
601
+
602
+ // Create energy pulse effects
603
+ function createEnergyPulseEffects() {
604
+ const pulseCount = 5;
605
+
606
+ for (let i = 0; i < pulseCount; i++) {
607
+ const geometry = new THREE.SphereGeometry(1, 32, 32);
608
+ const material = new THREE.MeshBasicMaterial({
609
+ color: 0x3b82f6,
610
+ transparent: true,
611
+ opacity: 0,
612
+ blending: THREE.AdditiveBlending
613
+ });
614
+
615
+ const pulse = new THREE.Mesh(geometry, material);
616
+ pulse.position.set(
617
+ (Math.random() - 0.5) * 20,
618
+ Math.random() * 5,
619
+ (Math.random() - 0.5) * 20
620
+ );
621
+
622
+ scene.add(pulse);
623
+ energyPulseEffects.push({
624
+ mesh: pulse,
625
+ speed: 0.5 + Math.random(),
626
+ maxSize: 5 + Math.random() * 10,
627
+ delay: Math.random() * 5
628
+ });
629
+ }
630
+ }
631
+
632
+ // Create floating text
633
+ function createFloatingText(text, position, color) {
634
+ const canvas = document.createElement('canvas');
635
+ canvas.width = 512;
636
+ canvas.height = 256;
637
+ const context = canvas.getContext('2d');
638
+
639
+ context.font = "Bold 48px Arial";
640
+ context.fillStyle = `rgba(${color.r * 255}, ${color.g * 255}, ${color.b * 255}, 0.8)`;
641
+ context.textAlign = 'center';
642
+ context.textBaseline = 'middle';
643
+ context.fillText(text, canvas.width / 2, canvas.height / 2);
644
+
645
+ const texture = new THREE.CanvasTexture(canvas);
646
+ const material = new THREE.SpriteMaterial({
647
+ map: texture,
648
+ transparent: true,
649
+ blending: THREE.AdditiveBlending
650
+ });
651
+
652
+ const sprite = new THREE.Sprite(material);
653
+ sprite.scale.set(5, 2.5, 1);
654
+ sprite.position.copy(position);
655
+ scene.add(sprite);
656
+
657
+ floatingTexts.push({
658
+ sprite: sprite,
659
+ originalPosition: position.clone(),
660
+ offset: Math.random() * Math.PI * 2
661
+ });
662
+ }
663
+
664
+ // Create floating icons
665
+ function createFloatingIcons() {
666
+ const iconTypes = [
667
+ { icon: 'fa-bolt', color: 0xf59e0b },
668
+ { icon: 'fa-charging-station', color: 0x3b82f6 },
669
+ { icon: 'fa-leaf', color: 0x10b981 },
670
+ { icon: 'fa-fire', color: 0xf97316 },
671
+ { icon: 'fa-water', color: 0x0ea5e9 }
672
+ ];
673
+
674
+ const iconCount = 10;
675
+
676
+ for (let i = 0; i < iconCount; i++) {
677
+ const type = iconTypes[Math.floor(Math.random() * iconTypes.length)];
678
+ const canvas = document.createElement('canvas');
679
+ canvas.width = 128;
680
+ canvas.height = 128;
681
+ const context = canvas.getContext('2d');
682
+
683
+ // Draw icon
684
+ context.font = "Normal 72px FontAwesome";
685
+ context.fillStyle = `rgba(${(type.color >> 16) & 0xff}, ${(type.color >> 8) & 0xff}, ${type.color & 0xff}, 0.8)`;
686
+ context.textAlign = 'center';
687
+ context.textBaseline = 'middle';
688
+
689
+ // Get icon character from FontAwesome
690
+ const iconChar = String.fromCharCode(parseInt(getIconUnicode(type.icon), 16));
691
+ context.fillText(iconChar, canvas.width / 2, canvas.height / 2);
692
+
693
+ const texture = new THREE.CanvasTexture(canvas);
694
+ const material = new THREE.SpriteMaterial({
695
+ map: texture,
696
+ transparent: true,
697
+ blending: THREE.AdditiveBlending
698
+ });
699
+
700
+ const sprite = new THREE.Sprite(material);
701
+ sprite.scale.set(2, 2, 1);
702
+
703
+ // Position in a sphere
704
+ const radius = 10 + Math.random() * 10;
705
+ const theta = Math.random() * Math.PI * 2;
706
+ const phi = Math.random() * Math.PI;
707
+ sprite.position.set(
708
+ radius * Math.sin(phi) * Math.cos(theta),
709
+ radius * Math.cos(phi) + 5,
710
+ radius * Math.sin(phi) * Math.sin(theta)
711
+ );
712
+
713
+ scene.add(sprite);
714
+ floatingIcons.push({
715
+ sprite: sprite,
716
+ originalPosition: sprite.position.clone(),
717
+ speed: 0.01 + Math.random() * 0.02,
718
+ offset: Math.random() * Math.PI * 2
719
+ });
720
+ }
721
+ }
722
+
723
+ // Helper function to get FontAwesome unicode
724
+ function getIconUnicode(iconName) {
725
+ const icons = {
726
+ 'fa-bolt': 'f0e7',
727
+ 'fa-charging-station': 'f5e7',
728
+ 'fa-leaf': 'f06c',
729
+ 'fa-fire': 'f06d',
730
+ 'fa-water': 'f773'
731
+ };
732
+ return icons[iconName] || 'f111'; // default circle
733
+ }
734
+
735
+ function initThreeJS() {
736
+ // Create scene
737
+ scene = new THREE.Scene();
738
+ scene.background = new THREE.Color(0x0f172a);
739
+ scene.fog = new THREE.FogExp2(0x0f172a, 0.002);
740
+
741
+ // Create camera
742
+ camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
743
+ camera.position.set(0, 10, 20);
744
+
745
+ // Create renderer
746
+ renderer = new THREE.WebGLRenderer({ antialias: true });
747
+ renderer.setSize(window.innerWidth, window.innerHeight);
748
+ renderer.shadowMap.enabled = true;
749
+ renderer.shadowMap.type = THREE.PCFSoftShadowMap;
750
+ renderer.outputEncoding = THREE.sRGBEncoding;
751
+ document.getElementById('three-container').appendChild(renderer.domElement);
752
+
753
+ // Add controls
754
+ controls = new THREE.OrbitControls(camera, renderer.domElement);
755
+ controls.enableDamping = true;
756
+ controls.dampingFactor = 0.05;
757
+ controls.minDistance = 5;
758
+ controls.maxDistance = 50;
759
+ controls.maxPolarAngle = Math.PI * 0.9;
760
+ controls.minPolarAngle = Math.PI * 0.2;
761
+
762
+ // Add lights
763
+ const ambientLight = new THREE.AmbientLight(0x404040, 2);
764
+ scene.add(ambientLight);
765
+
766
+ const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
767
+ directionalLight.position.set(5, 10, 7);
768
+ directionalLight.castShadow = true;
769
+ directionalLight.shadow.mapSize.width = 2048;
770
+ directionalLight.shadow.mapSize.height = 2048;
771
+ scene.add(directionalLight);
772
+
773
+ const pointLight = new THREE.PointLight(0x4fd1ff, 3, 20);
774
+ pointLight.position.set(0, 5, 0);
775
+ pointLight.castShadow = true;
776
+ scene.add(pointLight);
777
+
778
+ // Add hemisphere light for more natural lighting
779
+ const hemisphereLight = new THREE.HemisphereLight(0x3b82f6, 0xf59e0b, 0.5);
780
+ scene.add(hemisphereLight);
781
+
782
+ // Initialize post-processing
783
+ initPostProcessing();
784
+
785
+ // Create complex environment
786
+ createHolographicGrid();
787
+ createParticleSystem();
788
+ createFloatingEnergyOrbs();
789
+ createEnergyPulseEffects();
790
+ createFloatingIcons();
791
+
792
+ // Create floating text
793
+ createFloatingText("QUANTUM NEXUS", new THREE.Vector3(0, 15, 0), new THREE.Color(0x3b82f6));
794
+ createFloatingText("ENERGY MATRIX", new THREE.Vector3(0, 12, 0), new THREE.Color(0xf59e0b));
795
+
796
+ // Create energy nodes
797
+ createEnergyNode('solar', new THREE.Vector3(-10, 2, -8), 0xf59e0b);
798
+ createEnergyNode('battery', new THREE.Vector3(0, 2, 8), 0xf97316);
799
+ createEnergyNode('home', new THREE.Vector3(10, 2, -8), 0x3b82f6);
800
+ createEnergyNode('grid', new THREE.Vector3(0, 2, -15), 0x9ca3af);
801
+
802
+ // Create energy connections
803
+ createEnergyConnection('solar', 'home', 0xf59e0b);
804
+ createEnergyConnection('solar', 'battery', 0xf59e0b);
805
+ createEnergyConnection('battery', 'home', 0xf97316);
806
+ createEnergyConnection('home', 'grid', 0x3b82f6);
807
+
808
+ // Create secondary connections
809
+ createEnergyConnection('solar', 'grid', 0xf59e0b);
810
+ createEnergyConnection('battery', 'grid', 0xf97316);
811
+
812
+ // Create decorative connections
813
+ createDecorativeConnections();
814
+
815
+ // Handle window resize
816
+ window.addEventListener('resize', onWindowResize);
817
+
818
+ // Start animation loop
819
+ animate();
820
+ }
821
+
822
+ // Create decorative connections between floating orbs
823
+ function createDecorativeConnections() {
824
+ for (let i = 0; i < floatingEnergyOrbs.length; i++) {
825
+ for (let j = i + 1; j < Math.min(i + 3, floatingEnergyOrbs.length); j++) {
826
+ const fromOrb = floatingEnergyOrbs[i];
827
+ const toOrb = floatingEnergyOrbs[j];
828
+
829
+ // Only connect if within certain distance
830
+ if (fromOrb.position.distanceTo(toOrb.position) < 15) {
831
+ const lineGeometry = new THREE.BufferGeometry().setFromPoints([
832
+ fromOrb.position,
833
+ toOrb.position
834
+ ]);
835
+
836
+ const lineMaterial = new THREE.LineBasicMaterial({
837
+ color: 0x3b82f6,
838
+ transparent: true,
839
+ opacity: 0.1,
840
+ linewidth: 1
841
+ });
842
+
843
+ const line = new THREE.Line(lineGeometry, lineMaterial);
844
+ scene.add(line);
845
+
846
+ // Store reference to update positions
847
+ energyLines.push({
848
+ line: line,
849
+ from: fromOrb,
850
+ to: toOrb
851
+ });
852
+ }
853
+ }
854
+ }
855
+ }
856
+
857
+ function createEnergyNode(type, position, color) {
858
+ // Main sphere
859
+ const geometry = new THREE.SphereGeometry(1.5, 32, 32);
860
+ const material = new THREE.MeshStandardMaterial({
861
+ color: color,
862
+ emissive: color,
863
+ emissiveIntensity: 0.5,
864
+ roughness: 0.2,
865
+ metalness: 0.8
866
+ });
867
+ const sphere = new THREE.Mesh(geometry, material);
868
+ sphere.position.copy(position);
869
+ sphere.castShadow = true;
870
+ sphere.receiveShadow = true;
871
+ sphere.userData = { type: type };
872
+ scene.add(sphere);
873
+ energyNodes.push(sphere);
874
+
875
+ // Pulsing animation
876
+ gsap.to(sphere.scale, {
877
+ x: 1.3,
878
+ y: 1.3,
879
+ z: 1.3,
880
+ duration: 2,
881
+ repeat: -1,
882
+ yoyo: true,
883
+ ease: "sine.inOut"
884
+ });
885
+
886
+ // Glow effect
887
+ const glowGeometry = new THREE.SphereGeometry(2, 32, 32);
888
+ const glowMaterial = new THREE.MeshBasicMaterial({
889
+ color: color,
890
+ transparent: true,
891
+ opacity: 0.3,
892
+ blending: THREE.AdditiveBlending
893
+ });
894
+ const glow = new THREE.Mesh(glowGeometry, glowMaterial);
895
+ glow.position.copy(position);
896
+ scene.add(glow);
897
+
898
+ // Ring around the sphere
899
+ const ringGeometry = new THREE.TorusGeometry(2.2, 0.1, 16, 100);
900
+ const ringMaterial = new THREE.MeshBasicMaterial({
901
+ color: color,
902
+ transparent: true,
903
+ opacity: 0.5,
904
+ blending: THREE.AdditiveBlending
905
+ });
906
+ const ring = new THREE.Mesh(ringGeometry, ringMaterial);
907
+ ring.position.copy(position);
908
+ ring.rotation.x = Math.PI / 2;
909
+ scene.add(ring);
910
+
911
+ // Rotate ring
912
+ gsap.to(ring.rotation, {
913
+ y: Math.PI * 2,
914
+ duration: 20,
915
+ repeat: -1,
916
+ ease: "none"
917
+ });
918
+
919
+ // Floating particles around node
920
+ createNodeParticles(position, color);
921
+
922
+ return sphere;
923
+ }
924
+
925
+ // Create particles swirling around energy nodes
926
+ function createNodeParticles(position, color) {
927
+ const particleCount = 50;
928
+ const particlesGeometry = new THREE.BufferGeometry();
929
+ const positions = new Float32Array(particleCount * 3);
930
+ const colors = new Float32Array(particleCount * 3);
931
+
932
+ for (let i = 0; i < particleCount; i++) {
933
+ // Position particles in a sphere around the node
934
+ const radius = 3;
935
+ const theta = Math.random() * Math.PI * 2;
936
+ const phi = Math.random() * Math.PI;
937
+
938
+ positions[i * 3] = position.x + radius * Math.sin(phi) * Math.cos(theta);
939
+ positions[i * 3 + 1] = position.y + radius * Math.cos(phi);
940
+ positions[i * 3 + 2] = position.z + radius * Math.sin(phi) * Math.sin(theta);
941
+
942
+ // Color particles
943
+ colors[i * 3] = (color >> 16 & 255) / 255;
944
+ colors[i * 3 + 1] = (color >> 8 & 255) / 255;
945
+ colors[i * 3 + 2] = (color & 255) / 255;
946
+ }
947
+
948
+ particlesGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
949
+ particlesGeometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
950
+
951
+ const particleMaterial = new THREE.PointsMaterial({
952
+ size: 0.2,
953
+ vertexColors: true,
954
+ transparent: true,
955
+ opacity: 0.8,
956
+ blending: THREE.AdditiveBlending,
957
+ sizeAttenuation: true
958
+ });
959
+
960
+ const particleSystem = new THREE.Points(particlesGeometry, particleMaterial);
961
+ particleSystem.userData = {
962
+ center: position.clone(),
963
+ time: Math.random() * 100,
964
+ speed: 0.01 + Math.random() * 0.02
965
+ };
966
+
967
+ scene.add(particleSystem);
968
+ particleSystems.push(particleSystem);
969
+ }
970
+
971
+ function createEnergyConnection(fromType, toType, color) {
972
+ const fromNode = scene.children.find(obj => obj.userData && obj.userData.type === fromType);
973
+ const toNode = scene.children.find(obj => obj.userData && obj.userData.type === toType);
974
+
975
+ if (!fromNode || !toNode) return;
976
+
977
+ // Create curved line
978
+ const curve = new THREE.QuadraticBezierCurve3(
979
+ fromNode.position,
980
+ new THREE.Vector3(
981
+ (fromNode.position.x + toNode.position.x) / 2 + (Math.random() - 0.5) * 3,
982
+ (fromNode.position.y + toNode.position.y) / 2 + 3 + Math.random() * 3,
983
+ (fromNode.position.z + toNode.position.z) / 2 + (Math.random() - 0.5) * 3
984
+ ),
985
+ toNode.position
986
+ );
987
+
988
+ const points = curve.getPoints(50);
989
+ const lineGeometry = new THREE.BufferGeometry().setFromPoints(points);
990
+
991
+ // Create line material with gradient
992
+ const lineMaterial = new THREE.LineBasicMaterial({
993
+ color: color,
994
+ transparent: true,
995
+ opacity: 0.5,
996
+ linewidth: 3
997
+ });
998
+
999
+ const line = new THREE.Line(lineGeometry, lineMaterial);
1000
+ scene.add(line);
1001
+
1002
+ // Create particles along the line
1003
+ const particleCount = 30;
1004
+ const particlesGeometry = new THREE.BufferGeometry();
1005
+ const particlesMaterial = new THREE.PointsMaterial({
1006
+ color: color,
1007
+ size: 0.3,
1008
+ transparent: true,
1009
+ opacity: 0.8,
1010
+ blending: THREE.AdditiveBlending
1011
+ });
1012
+
1013
+ const particles = new Float32Array(particleCount * 3);
1014
+ for (let i = 0; i < particleCount; i++) {
1015
+ const t = i / (particleCount - 1);
1016
+ const point = curve.getPoint(t);
1017
+ particles[i * 3] = point.x;
1018
+ particles[i * 3 + 1] = point.y;
1019
+ particles[i * 3 + 2] = point.z;
1020
+ }
1021
+
1022
+ particlesGeometry.setAttribute('position', new THREE.BufferAttribute(particles, 3));
1023
+ const particleSystem = new THREE.Points(particlesGeometry, particlesMaterial);
1024
+ scene.add(particleSystem);
1025
+
1026
+ // Store for animation
1027
+ energyLines.push({
1028
+ line: line,
1029
+ curve: curve,
1030
+ from: fromNode.position,
1031
+ to: toNode.position
1032
+ });
1033
+
1034
+ energyParticles.push({
1035
+ system: particleSystem,
1036
+ curve: curve,
1037
+ speed: 0.01 + Math.random() * 0.02,
1038
+ offset: Math.random() * 100
1039
+ });
1040
+
1041
+ // Create energy pulses along the connection
1042
+ createConnectionPulses(curve, color);
1043
+ }
1044
+
1045
+ // Create pulsing energy spheres along connections
1046
+ function createConnectionPulses(curve, color) {
1047
+ const pulseCount = 5;
1048
+
1049
+ for (let i = 0; i < pulseCount; i++) {
1050
+ const geometry = new THREE.SphereGeometry(0.5, 16, 16);
1051
+ const material = new THREE.MeshBasicMaterial({
1052
+ color: color,
1053
+ transparent: true,
1054
+ opacity: 0.8,
1055
+ blending: THREE.AdditiveBlending
1056
+ });
1057
+
1058
+ const pulse = new THREE.Mesh(geometry, material);
1059
+
1060
+ // Position along curve
1061
+ const t = i / pulseCount;
1062
+ const point = curve.getPoint(t);
1063
+ pulse.position.copy(point);
1064
+
1065
+ scene.add(pulse);
1066
+
1067
+ // Animation
1068
+ gsap.to(pulse.scale, {
1069
+ x: 1.5,
1070
+ y: 1.5,
1071
+ z: 1.5,
1072
+ duration: 2 + Math.random(),
1073
+ repeat: -1,
1074
+ yoyo: true,
1075
+ ease: "sine.inOut",
1076
+ delay: i * 0.3
1077
+ });
1078
+
1079
+ gsap.to(pulse.position, {
1080
+ x: curve.getPoint((t + 0.1) % 1).x,
1081
+ y: curve.getPoint((t + 0.1) % 1).y,
1082
+ z: curve.getPoint((t + 0.1) % 1).z,
1083
+ duration: 5,
1084
+ repeat: -1,
1085
+ ease: "none",
1086
+ delay: i * 0.3
1087
+ });
1088
+ }
1089
+ }
1090
+
1091
+ function onWindowResize() {
1092
+ camera.aspect = window.innerWidth / window.innerHeight;
1093
+ camera.updateProjectionMatrix();
1094
+ renderer.setSize(window.innerWidth, window.innerHeight);
1095
+ bloomPass.setSize(window.innerWidth, window.innerHeight);
1096
+ composer.setSize(window.innerWidth, window.innerHeight);
1097
+ }
1098
+
1099
+ function animate() {
1100
+ requestAnimationFrame(animate);
1101
+
1102
+ // Update controls
1103
+ controls.update();
1104
+
1105
+ // Animate energy particles along connections
1106
+ energyParticles.forEach((particle) => {
1107
+ const positions = particle.system.geometry.attributes.position.array;
1108
+ const time = Date.now() * particle.speed + particle.offset;
1109
+
1110
+ for (let i = 0; i < positions.length / 3; i++) {
1111
+ const t = (i / (positions.length / 3 - 1) + time * 0.001) % 1;
1112
+ const point = particle.curve.getPoint(t);
1113
+ positions[i * 3] = point.x;
1114
+ positions[i * 3 + 1] = point.y;
1115
+ positions[i * 3 + 2] = point.z;
1116
+ }
1117
+
1118
+ particle.system.geometry.attributes.position.needsUpdate = true;
1119
+ });
1120
+
1121
+ // Animate decorative connections
1122
+ energyLines.forEach((connection) => {
1123
+ if (connection.curve && connection.line) {
1124
+ const points = connection.curve.getPoints(50);
1125
+ connection.line.geometry.setFromPoints(points);
1126
+ connection.line.geometry.attributes.position.needsUpdate = true;
1127
+ } else if (connection.from && connection.to && connection.line) {
1128
+ // Update line between moving objects
1129
+ connection.line.geometry.setFromPoints([connection.from, connection.to]);
1130
+ connection.line.geometry.attributes.position.needsUpdate = true;
1131
+ }
1132
+ });
1133
+
1134
+ // Animate floating energy orbs
1135
+ floatingEnergyOrbs.forEach((orb) => {
1136
+ // Move orb with slight randomness
1137
+ orb.position.x += orb.userData.velocity.x;
1138
+ orb.position.y += orb.userData.velocity.y;
1139
+ orb.position.z += orb.userData.velocity.z;
1140
+
1141
+ // Add some randomness to movement
1142
+ orb.userData.velocity.x += (Math.random() - 0.5) * 0.001;
1143
+ orb.userData.velocity.y += (Math.random() - 0.5) * 0.001;
1144
+ orb.userData.velocity.z += (Math.random() - 0.5) * 0.001;
1145
+
1146
+ // Keep orbs within bounds
1147
+ const distance = orb.position.distanceTo(orb.userData.origin);
1148
+ if (distance > 20) {
1149
+ orb.userData.velocity.x = -orb.userData.velocity.x * 0.5;
1150
+ orb.userData.velocity.y = -orb.userData.velocity.y * 0.5;
1151
+ orb.userData.velocity.z = -orb.userData.velocity.z * 0.5;
1152
+ }
1153
+ });
1154
+
1155
+ // Animate node particles
1156
+ particleSystems.forEach((system) => {
1157
+ if (system.userData && system.userData.center) {
1158
+ const positions = system.geometry.attributes.position.array;
1159
+ const center = system.userData.center;
1160
+ const time = system.userData.time += system.userData.speed;
1161
+
1162
+ for (let i = 0; i < positions.length / 3; i++) {
1163
+ const radius = 2 + Math.sin(time + i * 0.1) * 0.5;
1164
+ const angle = time * 0.1 + i * 0.1;
1165
+
1166
+ positions[i * 3] = center.x + radius * Math.cos(angle);
1167
+ positions[i * 3 + 1] = center.y + radius * Math.sin(angle * 0.7);
1168
+ positions[i * 3 + 2] = center.z + radius * Math.sin(angle);
1169
+ }
1170
+
1171
+ system.geometry.attributes.position.needsUpdate = true;
1172
+ }
1173
+ });
1174
+
1175
+ // Animate energy pulse effects
1176
+ const now = Date.now();
1177
+ energyPulseEffects.forEach((effect) => {
1178
+ const elapsed = (now * 0.001 - effect.delay) % 5;
1179
+ if (elapsed >= 0) {
1180
+ const progress = elapsed / 5;
1181
+ effect.mesh.scale.setScalar(progress * effect.maxSize);
1182
+ effect.mesh.material.opacity = 1 - progress;
1183
+ }
1184
+ });
1185
+
1186
+ // Animate floating text
1187
+ floatingTexts.forEach((text) => {
1188
+ text.sprite.position.y = text.originalPosition.y + Math.sin(now * 0.001 + text.offset) * 0.5;
1189
+ });
1190
+
1191
+ // Animate floating icons
1192
+ floatingIcons.forEach((icon) => {
1193
+ const time = now * 0.001 + icon.offset;
1194
+ icon.sprite.position.x = icon.originalPosition.x + Math.sin(time * icon.speed) * 2;
1195
+ icon.sprite.position.z = icon.originalPosition.z + Math.cos(time * icon.speed) * 2;
1196
+ icon.sprite.position.y = icon.originalPosition.y + Math.sin(time * icon.speed * 0.7) * 1;
1197
+
1198
+ // Make icons face camera
1199
+ icon.sprite.lookAt(camera.position);
1200
+ });
1201
+
1202
+ // Rotate energy nodes
1203
+ energyNodes.forEach((node) => {
1204
+ node.rotation.y += 0.005;
1205
+ });
1206
+
1207
+ // Render with post-processing
1208
+ composer.render();
1209
+ }
1210
+
1211
+ // Update timestamp
1212
+ function updateTimestamp() {
1213
+ const now = new Date();
1214
+ const timeString = now.toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'});
1215
+ const dateString = now.toLocaleDateString([], {month: 'short', day: 'numeric'});
1216
+ document.getElementById('update-time').textContent = `${timeString}`;
1217
+ }
1218
+
1219
+ // Update energy grid visualization
1220
+ function updateEnergyGrid() {
1221
+ // Get current flow values (simulated)
1222
+ const solarProduction = 5.2;
1223
+ const homeConsumption = 3.3;
1224
+ const batteryLevel = 78;
1225
+ const gridExport = 1.9;
1226
+ const gridImport = 0;
1227
+
1228
+ // Update numeric values with slight variations
1229
+ const solarVariation = (Math.random() * 0.5 - 0.25);
1230
+ const newSolarValue = Math.max(0, solarProduction + solarVariation).toFixed(1);
1231
+ document.getElementById('solar-value').textContent = `${newSolarValue} kW`;
1232
+
1233
+ const homeVariation = (Math.random() * 0.3 - 0.15);
1234
+ const newHomeValue = Math.max(0, homeConsumption + homeVariation).toFixed(1);
1235
+
1236
+ // Update battery percentage with small random change
1237
+ let batteryChange = (Math.random() * 3 - 1.5);
1238
+ if (solarProduction > homeConsumption && batteryLevel < 95) {
1239
+ batteryChange = Math.abs(batteryChange); // More likely to charge
1240
+ } else if (solarProduction < homeConsumption && batteryLevel > 5) {
1241
+ batteryChange = -Math.abs(batteryChange); // More likely to discharge
1242
+ }
1243
+
1244
+ const newBatteryLevel = Math.max(0, Math.min(100, batteryLevel + batteryChange));
1245
+ document.getElementById('battery-value').textContent = `${Math.round(newBatteryLevel)}%`;
1246
+
1247
+ // Update grid value based on other changes
1248
+ const newGridValue = (newSolarValue - newHomeValue).toFixed(1);
1249
+ if (newGridValue > 0) {
1250
+ document.getElementById('grid-value').textContent = `${Math.abs(newGridValue)} kW`;
1251
+ } else {
1252
+ document.getElementById('grid-value').textContent = `${Math.abs(newGridValue)} kW`;
1253
+ }
1254
+
1255
+ // Update flow mode text
1256
+ let flowMode = '';
1257
+ if (newGridValue > 0) {
1258
+ flowMode = `Solar Exporting (${Math.abs(newGridValue)} kW to grid)`;
1259
+ document.getElementById('flow-mode').className = 'text-xl font-bold text-green-400';
1260
+ } else if (newGridValue < 0) {
1261
+ flowMode = `Grid Importing (${Math.abs(newGridValue)} kW from grid)`;
1262
+ document.getElementById('flow-mode').className = 'text-xl font-bold text-yellow-400';
1263
+ } else if (newSolarValue >= newHomeValue) {
1264
+ flowMode = 'Solar Powering Home';
1265
+ document.getElementById('flow-mode').className = 'text-xl font-bold text-blue-400';
1266
+ } else {
1267
+ flowMode = 'Mixed Power Sources';
1268
+ document.getElementById('flow-mode').className = 'text-xl font-bold text-purple-400';
1269
+ }
1270
+
1271
+ document.getElementById('flow-mode').textContent = flowMode;
1272
+
1273
+ // Visual feedback for UI elements
1274
+ if (newGridValue > 0) {
1275
+ gsap.to(document.getElementById('grid-cell'), {
1276
+ boxShadow: '0 0 20px rgba(16, 185, 129, 0.7)',
1277
+ duration: 0.5,
1278
+ yoyo: true,
1279
+ repeat: 1
1280
+ });
1281
+ } else {
1282
+ gsap.to(document.getElementById('grid-cell'), {
1283
+ boxShadow: '0 0 20px rgba(245, 158, 11, 0.7)',
1284
+ duration: 0.5,
1285
+ yoyo: true,
1286
+ repeat: 1
1287
+ });
1288
+ }
1289
+ }
1290
+
1291
+ // Initialize
1292
+ document.addEventListener('DOMContentLoaded', () => {
1293
+ initThreeJS();
1294
+ updateTimestamp();
1295
+
1296
+ // Initial energy grid setup
1297
+ updateEnergyGrid();
1298
+
1299
+ // Update data every 2 seconds
1300
+ setInterval(() => {
1301
+ updateTimestamp();
1302
+ updateEnergyGrid();
1303
+ }, 2000);
1304
+
1305
+ // Add click handlers for grid nodes
1306
+ document.querySelectorAll('.grid-node').forEach(node => {
1307
+ node.addEventListener('click', () => {
1308
+ const type = node.dataset.type;
1309
+ // Focus camera on the corresponding 3D node
1310
+ const targetNode = scene.children.find(obj => obj.userData && obj.userData.type === type);
1311
+ if (targetNode) {
1312
+ gsap.to(camera.position, {
1313
+ x: targetNode.position.x * 1.5,
1314
+ y: targetNode.position.y + 5,
1315
+ z: targetNode.position.z * 1.5,
1316
+ duration: 1,
1317
+ ease: "power2.inOut"
1318
+ });
1319
+
1320
+ // Create pulse effect in the UI
1321
+ const pulse = document.createElement('div');
1322
+ pulse.className = 'energy-pulse';
1323
+ pulse.style.left = `${node.offsetLeft + node.offsetWidth / 2}px`;
1324
+ pulse.style.top = `${node.offsetTop + node.offsetHeight / 2}px`;
1325
+ document.getElementById('particle-trail').appendChild(pulse);
1326
+
1327
+ // Remove after animation
1328
+ setTimeout(() => {
1329
+ pulse.remove();
1330
+ }, 3000);
1331
+ }
1332
+ });
1333
+ });
1334
+ });
1335
+ </script>
1336
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=LukasBe/3d-effects" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
1337
+ </html>