Pp commited on
Commit
8554b18
·
verified ·
1 Parent(s): c4d90af

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +551 -18
index.html CHANGED
@@ -1,19 +1,552 @@
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>Interactive Water Cycle!</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/tone/14.8.49/Tone.min.js"></script>
9
+ <script type="module" src="https://unpkg.com/lucide@latest"></script>
10
+ <style>
11
+ /* Use Inter font */
12
+ body {
13
+ font-family: 'Inter', sans-serif;
14
+ overscroll-behavior: none; /* Prevent pull-to-refresh */
15
+ background: linear-gradient(to bottom, #87CEEB 0%, #ADD8E6 100%); /* Sky gradient */
16
+ display: flex;
17
+ justify-content: center;
18
+ align-items: center;
19
+ min-height: 100vh;
20
+ overflow: hidden; /* Hide overflow to prevent scrollbars from animations */
21
+ }
22
+
23
+ /* Scene container */
24
+ .scene {
25
+ position: relative;
26
+ width: 90vw;
27
+ max-width: 800px;
28
+ height: 500px; /* Fixed height for scene elements */
29
+ background: linear-gradient(to bottom, #ADD8E6 0%, #F0F8FF 60%, #90EE90 60%, #3CB371 100%); /* Sky/Land gradient */
30
+ border-radius: 1rem;
31
+ overflow: hidden;
32
+ box-shadow: 0 10px 20px rgba(0,0,0,0.2);
33
+ cursor: default; /* Default cursor for the scene */
34
+ }
35
+
36
+ /* Sun element */
37
+ .sun {
38
+ position: absolute;
39
+ top: 30px;
40
+ left: 50px;
41
+ width: 80px;
42
+ height: 80px;
43
+ background-color: #FFD700; /* Gold */
44
+ border-radius: 50%;
45
+ box-shadow: 0 0 20px #FFD700;
46
+ cursor: pointer;
47
+ transition: transform 0.3s ease, box-shadow 0.3s ease;
48
+ z-index: 10;
49
+ }
50
+ .sun:hover {
51
+ transform: scale(1.1);
52
+ box-shadow: 0 0 30px #FFA500; /* Orange glow */
53
+ }
54
+
55
+ /* Ocean element */
56
+ .ocean {
57
+ position: absolute;
58
+ bottom: 0;
59
+ left: 0;
60
+ width: 60%;
61
+ height: 100px; /* Approx 20% of scene height */
62
+ background: linear-gradient(to bottom, #1E90FF, #00008B); /* Blue gradient */
63
+ border-top-left-radius: 50% 20px; /* Wavy top */
64
+ border-top-right-radius: 50% 20px;
65
+ cursor: pointer;
66
+ z-index: 5;
67
+ }
68
+ .ocean:hover .wave { /* Subtle wave animation on hover */
69
+ transform: scaleY(1.1);
70
+ }
71
+
72
+ /* Simple wave effect */
73
+ .wave {
74
+ position: absolute;
75
+ top: -5px;
76
+ left: 0;
77
+ width: 100%;
78
+ height: 10px;
79
+ background: rgba(255, 255, 255, 0.3);
80
+ border-radius: 50%;
81
+ transform-origin: bottom;
82
+ transition: transform 0.5s ease-in-out;
83
+ }
84
+
85
+
86
+ /* Land element */
87
+ .land {
88
+ position: absolute;
89
+ bottom: 0;
90
+ right: 0;
91
+ width: 40%;
92
+ height: 200px; /* Taller than ocean */
93
+ background: #8FBC8F; /* Dark Sea Green */
94
+ border-top-left-radius: 30% 50px;
95
+ z-index: 1;
96
+ }
97
+
98
+ /* Tree element */
99
+ .tree {
100
+ position: absolute;
101
+ bottom: 100px; /* Base on the land */
102
+ right: 100px;
103
+ cursor: pointer;
104
+ z-index: 6;
105
+ }
106
+ .trunk {
107
+ width: 15px;
108
+ height: 50px;
109
+ background-color: #8B4513; /* Saddle Brown */
110
+ margin: 0 auto;
111
+ }
112
+ .leaves {
113
+ width: 50px;
114
+ height: 50px;
115
+ background-color: #228B22; /* Forest Green */
116
+ border-radius: 50%;
117
+ position: relative;
118
+ bottom: 10px; /* Overlap trunk slightly */
119
+ transition: transform 0.3s ease;
120
+ }
121
+ .tree:hover .leaves {
122
+ transform: scale(1.1);
123
+ }
124
+
125
+
126
+ /* Cloud element */
127
+ .cloud {
128
+ position: absolute;
129
+ top: 60px;
130
+ width: 100px;
131
+ height: 40px;
132
+ background-color: white;
133
+ border-radius: 50px;
134
+ opacity: 0.8;
135
+ transition: background-color 1s ease, transform 0.5s ease, opacity 1s ease;
136
+ cursor: pointer;
137
+ z-index: 15;
138
+ filter: drop-shadow(0 4px 6px rgba(0,0,0,0.1));
139
+ }
140
+ .cloud::before, .cloud::after { /* Cloud puffs */
141
+ content: '';
142
+ position: absolute;
143
+ background-color: white;
144
+ border-radius: 50%;
145
+ width: 50px;
146
+ height: 50px;
147
+ top: -20px;
148
+ transition: background-color 1s ease;
149
+ }
150
+ .cloud::before { left: 15px; }
151
+ .cloud::after { right: 15px; top: -15px; width: 60px; height: 45px;}
152
+
153
+ .cloud.condensing {
154
+ background-color: #D3D3D3; /* Light grey */
155
+ }
156
+ .cloud.condensing::before, .cloud.condensing::after {
157
+ background-color: #D3D3D3;
158
+ }
159
+
160
+ .cloud.ready {
161
+ background-color: #778899; /* Light Slate Gray */
162
+ transform: scale(1.1);
163
+ opacity: 1;
164
+ }
165
+ .cloud.ready::before, .cloud.ready::after {
166
+ background-color: #778899;
167
+ }
168
+ .cloud.ready:hover {
169
+ background-color: #708090; /* Slate Gray */
170
+ }
171
+ .cloud.ready:hover::before, .cloud.ready:hover::after {
172
+ background-color: #708090;
173
+ }
174
+
175
+ /* Evaporation animation */
176
+ @keyframes evaporate {
177
+ 0% { transform: translateY(0) scale(1); opacity: 0.6; }
178
+ 100% { transform: translateY(-100px) scale(0.5); opacity: 0; }
179
+ }
180
+ .vapor {
181
+ position: absolute;
182
+ width: 5px;
183
+ height: 20px;
184
+ background: linear-gradient(to top, rgba(255,255,255,0.1), rgba(255,255,255,0.6));
185
+ border-radius: 50%;
186
+ animation: evaporate 2s ease-out infinite;
187
+ opacity: 0; /* Start hidden */
188
+ pointer-events: none; /* Don't interfere with clicks */
189
+ z-index: 7;
190
+ }
191
+
192
+ /* Precipitation animation */
193
+ @keyframes fall {
194
+ 0% { transform: translateY(0); opacity: 1; }
195
+ 100% { transform: translateY(150px); opacity: 0; } /* Fall towards ocean/land */
196
+ }
197
+ .raindrop {
198
+ position: absolute;
199
+ width: 3px;
200
+ height: 10px;
201
+ background: linear-gradient(to bottom, rgba(173, 216, 230, 0.1), rgba(70, 130, 180, 1)); /* Light to Steel Blue */
202
+ border-radius: 50%;
203
+ animation: fall 1s linear infinite;
204
+ opacity: 0; /* Start hidden */
205
+ pointer-events: none;
206
+ z-index: 14;
207
+ }
208
+
209
+ /* Info text */
210
+ #info-text {
211
+ position: absolute;
212
+ bottom: 10px;
213
+ left: 50%;
214
+ transform: translateX(-50%);
215
+ background-color: rgba(0, 0, 0, 0.6);
216
+ color: white;
217
+ padding: 8px 15px;
218
+ border-radius: 20px;
219
+ font-size: 0.9rem;
220
+ z-index: 20;
221
+ text-align: center;
222
+ opacity: 0;
223
+ transition: opacity 0.5s ease;
224
+ pointer-events: none; /* Don't block clicks */
225
+ }
226
+ #info-text.visible {
227
+ opacity: 1;
228
+ }
229
+
230
+ /* Control buttons */
231
+ .controls {
232
+ position: absolute;
233
+ top: 10px;
234
+ right: 10px;
235
+ display: flex;
236
+ gap: 10px;
237
+ z-index: 25;
238
+ }
239
+ .control-btn {
240
+ background-color: rgba(255, 255, 255, 0.8);
241
+ border: none;
242
+ border-radius: 50%;
243
+ padding: 8px;
244
+ cursor: pointer;
245
+ display: flex;
246
+ justify-content: center;
247
+ align-items: center;
248
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
249
+ transition: background-color 0.2s ease, transform 0.2s ease;
250
+ }
251
+ .control-btn:hover {
252
+ background-color: white;
253
+ transform: scale(1.1);
254
+ }
255
+ .control-btn svg {
256
+ width: 20px;
257
+ height: 20px;
258
+ stroke: #333;
259
+ }
260
+
261
+ </style>
262
+ </head>
263
+ <body>
264
+ <div class="scene">
265
+ <div id="sun" class="sun" title="Click the Sun to start Evaporation"></div>
266
+
267
+ <div id="ocean" class="ocean" title="Click the Ocean for Evaporation">
268
+ <div class="wave"></div>
269
+ </div>
270
+
271
+ <div class="land"></div>
272
+
273
+ <div id="tree" class="tree" title="Click the Tree for Transpiration">
274
+ <div class="leaves"></div>
275
+ <div class="trunk"></div>
276
+ </div>
277
+
278
+
279
+ <div id="cloud-container"></div>
280
+
281
+ <div id="rain-container"></div>
282
+
283
+ <div id="info-text">Water Cycle Stage</div>
284
+
285
+ <div class="controls">
286
+ <button id="sound-toggle" class="control-btn" title="Toggle Sound">
287
+ <i data-lucide="volume-2"></i> </button>
288
+ <button id="share-twitter" class="control-btn" title="Share on Twitter">
289
+ <i data-lucide="twitter"></i>
290
+ </button>
291
+ </div>
292
+
293
+ </div>
294
+
295
+ <script>
296
+ // --- DOM Elements ---
297
+ const sun = document.getElementById('sun');
298
+ const ocean = document.getElementById('ocean');
299
+ const tree = document.getElementById('tree');
300
+ const cloudContainer = document.getElementById('cloud-container');
301
+ const rainContainer = document.getElementById('rain-container');
302
+ const infoText = document.getElementById('info-text');
303
+ const soundToggleButton = document.getElementById('sound-toggle');
304
+ const shareTwitterButton = document.getElementById('share-twitter');
305
+ const scene = document.querySelector('.scene'); // Get scene dimensions
306
+
307
+ // --- State Variables ---
308
+ let evaporationRate = 0; // How much water vapor is generated
309
+ let condensationLevel = 0; // How much vapor is in clouds
310
+ let clouds = []; // Array to hold cloud elements
311
+ let isRaining = false;
312
+ let soundEnabled = true;
313
+ let rainSynth; // Tone.js synth for rain sound
314
+
315
+ // --- Sound Setup (Tone.js) ---
316
+ function setupSound() {
317
+ // Simple rain sound using noise synth
318
+ rainSynth = new Tone.NoiseSynth({
319
+ noise: { type: 'pink' },
320
+ envelope: { attack: 0.1, decay: 0.1, sustain: 0.5, release: 0.2 }
321
+ }).toDestination();
322
+ // Adjust volume
323
+ rainSynth.volume.value = -20; // Quieter volume in dB
324
+ }
325
+
326
+ function playRainSound() {
327
+ if (soundEnabled && rainSynth && !rainSynth.triggered) {
328
+ // Start the noise envelope - simulates continuous rain drops
329
+ rainSynth.triggerAttack();
330
+ // We need to manually stop it when rain stops
331
+ }
332
+ }
333
+
334
+ function stopRainSound() {
335
+ if (rainSynth && rainSynth.signal.value > 0) { // Check if it's playing
336
+ rainSynth.triggerRelease();
337
+ }
338
+ }
339
+
340
+ // Initialize sound on first interaction (required by browsers)
341
+ document.body.addEventListener('click', () => {
342
+ if (Tone.context.state !== 'running') {
343
+ Tone.start();
344
+ console.log('AudioContext started');
345
+ }
346
+ if (!rainSynth) {
347
+ setupSound(); // Setup synth after user interaction
348
+ }
349
+ }, { once: true }); // Run only once
350
+
351
+ // --- Helper Functions ---
352
+ function showInfo(text, duration = 3000) {
353
+ infoText.textContent = text;
354
+ infoText.classList.add('visible');
355
+ setTimeout(() => {
356
+ infoText.classList.remove('visible');
357
+ }, duration);
358
+ }
359
+
360
+ function getRandomPosition(containerWidth, containerHeight, elementWidth, elementHeight) {
361
+ const x = Math.random() * (containerWidth - elementWidth);
362
+ const y = Math.random() * (containerHeight - elementHeight);
363
+ return { x, y };
364
+ }
365
+
366
+ // --- Simulation Logic ---
367
+
368
+ // 1. Evaporation / Transpiration
369
+ function triggerEvaporation(sourceElement, intensity = 1) {
370
+ if (isRaining) return; // Don't evaporate while raining
371
+
372
+ showInfo('Evaporation: Water turns into vapor and rises!');
373
+ evaporationRate += intensity;
374
+
375
+ // Create vapor particles rising from the source
376
+ const sourceRect = sourceElement.getBoundingClientRect();
377
+ const sceneRect = scene.getBoundingClientRect(); // Use scene for positioning
378
+ const startX = sourceRect.left - sceneRect.left + (sourceRect.width / 2);
379
+ let startY = sourceRect.top - sceneRect.top + 5; // Start slightly above surface
380
+
381
+ // Adjust startY for tree transpiration to come from leaves
382
+ if (sourceElement.id === 'tree') {
383
+ const leaves = sourceElement.querySelector('.leaves');
384
+ const leavesRect = leaves.getBoundingClientRect();
385
+ startY = leavesRect.top - sceneRect.top;
386
+ }
387
+
388
+
389
+ for (let i = 0; i < intensity * 2; i++) {
390
+ const vapor = document.createElement('div');
391
+ vapor.classList.add('vapor');
392
+ vapor.style.left = `${startX + (Math.random() * 40 - 20)}px`; // Spread horizontally
393
+ vapor.style.top = `${startY}px`;
394
+ vapor.style.animationDelay = `${Math.random() * 0.5}s`; // Stagger animation
395
+ scene.appendChild(vapor);
396
+
397
+ // Remove vapor after animation ends
398
+ vapor.addEventListener('animationiteration', () => {
399
+ vapor.remove();
400
+ }, { once: true });
401
+ }
402
+
403
+ // Increase condensation level (with a cap)
404
+ condensationLevel = Math.min(condensationLevel + intensity, 100); // Cap at 100
405
+ updateClouds();
406
+ }
407
+
408
+ // 2. Condensation (Updating Clouds)
409
+ function updateClouds() {
410
+ // Create initial clouds if none exist
411
+ if (clouds.length === 0 && condensationLevel > 5) {
412
+ createCloud();
413
+ createCloud(); // Start with a couple
414
+ }
415
+
416
+ // Update existing clouds based on condensation level
417
+ clouds.forEach(cloud => {
418
+ const cloudElement = document.getElementById(cloud.id);
419
+ if (!cloudElement) return; // Skip if somehow removed
420
+
421
+ if (condensationLevel > 70 && !cloudElement.classList.contains('ready')) {
422
+ cloudElement.classList.remove('condensing');
423
+ cloudElement.classList.add('ready');
424
+ cloudElement.title = "Click the Cloud to make it Rain!";
425
+ } else if (condensationLevel > 30 && !cloudElement.classList.contains('condensing') && !cloudElement.classList.contains('ready')) {
426
+ cloudElement.classList.add('condensing');
427
+ cloudElement.title = "Cloud is forming...";
428
+ } else if (condensationLevel <= 30) {
429
+ cloudElement.classList.remove('condensing', 'ready');
430
+ cloudElement.title = "Just a little cloud";
431
+ }
432
+ });
433
+ }
434
+
435
+ function createCloud() {
436
+ const cloudId = `cloud-${Date.now()}-${Math.random()}`;
437
+ const cloudElement = document.createElement('div');
438
+ cloudElement.id = cloudId;
439
+ cloudElement.classList.add('cloud');
440
+ cloudElement.title = "Just a little cloud";
441
+
442
+ // Position randomly in the upper part of the scene
443
+ const sceneWidth = scene.offsetWidth;
444
+ const cloudWidth = 100;
445
+ const cloudHeight = 40; // Base height
446
+ const maxCloudY = 150; // Don't go too low initially
447
+
448
+ const { x, y } = getRandomPosition(sceneWidth, maxCloudY, cloudWidth, cloudHeight);
449
+ cloudElement.style.left = `${x}px`;
450
+ cloudElement.style.top = `${y + 20}px`; // Add offset from top
451
+
452
+ cloudElement.addEventListener('click', () => triggerPrecipitation(cloudElement));
453
+
454
+ cloudContainer.appendChild(cloudElement);
455
+ clouds.push({ id: cloudId, element: cloudElement });
456
+ updateClouds(); // Apply initial state based on condensationLevel
457
+ }
458
+
459
+
460
+ // 3. Precipitation
461
+ function triggerPrecipitation(cloudElement) {
462
+ if (!cloudElement.classList.contains('ready') || isRaining) {
463
+ showInfo(cloudElement.classList.contains('ready') ? 'It\'s already raining!' : 'Cloud isn\'t full enough for rain yet!');
464
+ return;
465
+ }
466
+
467
+ showInfo('Precipitation: Water falls back to Earth as rain!');
468
+ isRaining = true;
469
+ playRainSound(); // Start rain sound
470
+
471
+ // Make it rain from under the cloud
472
+ const cloudRect = cloudElement.getBoundingClientRect();
473
+ const sceneRect = scene.getBoundingClientRect();
474
+ const startX = cloudRect.left - sceneRect.left;
475
+ const startY = cloudRect.bottom - sceneRect.top - 10; // Start below cloud puffs
476
+ const cloudWidth = cloudRect.width;
477
+
478
+ const rainDuration = 3000; // Rain for 3 seconds
479
+ const intervalId = setInterval(() => {
480
+ for (let i = 0; i < 5; i++) { // Number of drops per interval
481
+ const drop = document.createElement('div');
482
+ drop.classList.add('raindrop');
483
+ drop.style.left = `${startX + Math.random() * cloudWidth}px`;
484
+ drop.style.top = `${startY + Math.random() * 10}px`; // Slight vertical spread
485
+ drop.style.animationDuration = `${0.5 + Math.random() * 0.5}s`; // Vary fall speed
486
+ rainContainer.appendChild(drop);
487
+
488
+ // Remove drop after animation
489
+ drop.addEventListener('animationiteration', () => {
490
+ drop.remove();
491
+ }, { once: true });
492
+ }
493
+ }, 100); // Create drops every 100ms
494
+
495
+ // Stop raining after duration
496
+ setTimeout(() => {
497
+ clearInterval(intervalId);
498
+ isRaining = false;
499
+ stopRainSound(); // Stop rain sound
500
+ condensationLevel = 0; // Reset condensation
501
+ evaporationRate = 0; // Reset evaporation
502
+ updateClouds(); // Reset cloud appearance
503
+ // Optionally remove clouds or make them fade
504
+ cloudElement.classList.remove('ready', 'condensing');
505
+ cloudElement.title = "Just a little cloud";
506
+ showInfo('Collection: Water gathers in oceans and lakes.');
507
+ }, rainDuration);
508
+ }
509
+
510
+ // --- Event Listeners ---
511
+ sun.addEventListener('click', () => triggerEvaporation(ocean, 5)); // More intense from sun
512
+ ocean.addEventListener('click', () => triggerEvaporation(ocean, 2));
513
+ tree.addEventListener('click', () => triggerEvaporation(tree, 1)); // Transpiration is less intense
514
+
515
+ // Sound Toggle Button
516
+ soundToggleButton.addEventListener('click', () => {
517
+ soundEnabled = !soundEnabled;
518
+ const icon = soundToggleButton.querySelector('i');
519
+ if (soundEnabled) {
520
+ icon.setAttribute('data-lucide', 'volume-2');
521
+ showInfo('Sound On', 1000);
522
+ // If it was raining and sound was off, start sound now
523
+ if (isRaining && !rainSynth.triggered) playRainSound();
524
+ } else {
525
+ icon.setAttribute('data-lucide', 'volume-x');
526
+ showInfo('Sound Off', 1000);
527
+ stopRainSound(); // Stop sound immediately if disabled
528
+ }
529
+ // Re-render the icon using Lucide's library function
530
+ lucide.createIcons();
531
+ });
532
+
533
+ // Twitter Share Button
534
+ shareTwitterButton.addEventListener('click', () => {
535
+ const text = encodeURIComponent("Look! I made it rain 🌧️ exploring the water cycle with this cool simulation! #WaterCycle #ScienceForKids #EdTech");
536
+ // Get current URL - replace with actual deployed URL if needed
537
+ const url = encodeURIComponent(window.location.href || "https://your-deployed-space-url.com"); // Replace placeholder
538
+ window.open(`https://twitter.com/intent/tweet?text=${text}&url=${url}`, '_blank');
539
+ });
540
+
541
+ // --- Initial Setup ---
542
+ // Create a couple of initial placeholder clouds (optional)
543
+ // createCloud();
544
+ // createCloud();
545
+ showInfo("Click the Sun, Ocean, or Tree to start the water cycle!", 5000);
546
+
547
+ // Ensure Lucide icons render initially
548
+ lucide.createIcons();
549
+
550
+ </script>
551
+ </body>
552
  </html>