Boobs00 commited on
Commit
b71c87f
·
verified ·
1 Parent(s): 6857c5a

Add 2 files

Browse files
Files changed (2) hide show
  1. index.html +191 -679
  2. prompts.txt +2 -1
index.html CHANGED
@@ -3,9 +3,22 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
 
 
6
  <title>CipherEcstasy - Algorithmic Ecstasy</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
  <style>
10
  @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;500;600;700&family=Inter:wght@300;400;500;600;700&display=swap');
11
 
@@ -25,258 +38,70 @@
25
  color: #e0e0ff;
26
  }
27
 
28
- /* ... (keep all previous CSS styles) ... */
29
 
30
- /* New styles for auth modal */
31
- .auth-modal {
32
  position: fixed;
33
- top: 0;
34
- left: 0;
35
- right: 0;
36
- bottom: 0;
37
- background: rgba(15, 15, 26, 0.9);
38
- display: flex;
39
- justify-content: center;
40
- align-items: center;
41
- z-index: 1000;
42
- backdrop-filter: blur(5px);
43
- }
44
-
45
- .auth-container {
46
- background: linear-gradient(145deg, rgba(30, 30, 45, 0.95), rgba(20, 20, 35, 0.95));
47
- border-radius: 12px;
48
- padding: 40px;
49
- width: 100%;
50
- max-width: 400px;
51
- box-shadow: 0 15px 40px rgba(0, 0, 0, 0.4);
52
- border: 1px solid rgba(56, 189, 248, 0.3);
53
- text-align: center;
54
- }
55
-
56
- .auth-container h2 {
57
- font-family: 'Orbitron', sans-serif;
58
- color: var(--cool-blue);
59
- margin-bottom: 20px;
60
- font-size: 1.8rem;
61
- }
62
-
63
- .auth-input {
64
- width: 100%;
65
- padding: 12px 15px;
66
- margin-bottom: 20px;
67
- background: rgba(15, 15, 26, 0.7);
68
- border: 1px solid rgba(56, 189, 248, 0.2);
69
- border-radius: 6px;
70
- color: white;
71
- font-size: 1rem;
72
- transition: all 0.3s ease;
73
- }
74
-
75
- .auth-input:focus {
76
- outline: none;
77
- border-color: var(--warm-amber);
78
- box-shadow: 0 0 10px rgba(245, 158, 11, 0.2);
79
- }
80
-
81
- .auth-btn {
82
- background: linear-gradient(135deg, rgba(56, 189, 248, 0.2), rgba(139, 92, 246, 0.2));
83
- border: 1px solid rgba(56, 189, 248, 0.3);
84
- color: var(--cool-blue);
85
- padding: 12px 25px;
86
- border-radius: 6px;
87
- font-family: 'Orbitron', sans-serif;
88
- text-transform: uppercase;
89
- letter-spacing: 1px;
90
- cursor: pointer;
91
- transition: all 0.3s ease;
92
- width: 100%;
93
- margin-top: 10px;
94
- }
95
-
96
- .auth-btn:hover {
97
- background: linear-gradient(135deg, rgba(245, 158, 11, 0.2), rgba(139, 92, 246, 0.2));
98
- color: var(--warm-amber);
99
- border-color: rgba(245, 158, 11, 0.3);
100
- }
101
-
102
- .magic-link-sent {
103
- color: var(--cool-blue);
104
- margin-top: 20px;
105
- font-size: 0.9rem;
106
- display: none;
107
- }
108
-
109
- /* Sensory journey styles */
110
- .journey-container {
111
- position: fixed;
112
- top: 20px;
113
- right: 20px;
114
- z-index: 1000;
115
- background: rgba(15, 15, 26, 0.8);
116
  border-radius: 8px;
117
  padding: 15px;
118
- width: 300px;
 
 
 
119
  backdrop-filter: blur(5px);
120
- border: 1px solid rgba(56, 189, 248, 0.2);
121
- transform: translateX(calc(100% + 20px));
122
- transition: transform 0.3s ease;
123
- }
124
-
125
- .journey-container.active {
126
- transform: translateX(0);
127
- }
128
-
129
- .journey-header {
130
- display: flex;
131
- justify-content: space-between;
132
- align-items: center;
133
- margin-bottom: 15px;
134
- color: var(--warm-amber);
135
- font-family: 'Orbitron', sans-serif;
136
  }
137
-
138
- .journey-toggle {
139
- background: none;
140
- border: none;
141
- color: var(--cool-blue);
142
- cursor: pointer;
143
- font-size: 1.2rem;
144
- }
145
-
146
- .journey-toggle:hover {
147
- color: var(--warm-amber);
148
- }
149
-
150
- .journey-form input {
151
- width: 100%;
152
- padding: 10px;
153
  margin-bottom: 10px;
154
- background: rgba(15, 15, 26, 0.7);
155
- border: 1px solid rgba(56, 189, 248, 0.2);
156
- border-radius: 4px;
157
- color: white;
158
- }
159
-
160
- .journey-form button {
161
- background: rgba(56, 189, 248, 0.1);
162
- border: 1px solid rgba(56, 189, 248, 0.3);
163
  color: var(--cool-blue);
164
- padding: 8px 15px;
165
- border-radius: 4px;
166
- cursor: pointer;
167
- transition: all 0.3s ease;
168
- width: 100%;
169
  }
170
-
171
- .journey-form button:hover {
172
- background: rgba(245, 158, 11, 0.1);
173
- color: var(--warm-amber);
174
  }
175
-
176
- .journey-result {
177
- margin-top: 15px;
178
- padding: 10px;
179
- background: rgba(15, 15, 26, 0.5);
180
  border-radius: 4px;
181
- border-left: 3px solid var(--electric-purple);
182
- display: none;
183
- }
184
-
185
- .journey-loading {
186
- display: none;
187
- text-align: center;
188
- margin: 15px 0;
189
- color: var(--cool-blue);
190
- }
191
-
192
- .journey-loading i {
193
- animation: spin 1s linear infinite;
194
- }
195
-
196
- @keyframes spin {
197
- 0% { transform: rotate(0deg); }
198
- 100% { transform: rotate(360deg); }
199
- }
200
-
201
- /* User profile indicator */
202
- .user-profile {
203
- position: fixed;
204
- top: 20px;
205
- left: 20px;
206
- z-index: 1000;
207
- background: rgba(15, 15, 26, 0.8);
208
- border-radius: 50%;
209
- width: 50px;
210
- height: 50px;
211
- display: flex;
212
- justify-content: center;
213
- align-items: center;
214
  cursor: pointer;
215
- border: 1px solid rgba(56, 189, 248, 0.3);
216
- transition: all 0.3s ease;
217
- }
218
-
219
- .user-profile:hover {
220
- border-color: var(--warm-amber);
221
- box-shadow: 0 0 15px rgba(245, 158, 11, 0.3);
222
- }
223
-
224
- .user-profile i {
225
- color: var(--cool-blue);
226
- font-size: 1.2rem;
227
  }
228
-
229
- .user-profile.active {
230
  background: rgba(56, 189, 248, 0.2);
 
 
231
  }
232
-
233
- .user-menu {
234
- position: absolute;
235
- top: 70px;
236
- left: 0;
237
- background: rgba(15, 15, 26, 0.9);
238
- border-radius: 8px;
239
- padding: 15px;
240
- width: 200px;
241
- border: 1px solid rgba(56, 189, 248, 0.3);
242
- display: none;
243
- backdrop-filter: blur(5px);
244
- }
245
-
246
- .user-profile.active .user-menu {
247
- display: block;
248
- }
249
-
250
- .user-menu button {
251
- background: none;
252
- border: none;
253
- color: #e0e0ff;
254
- width: 100%;
255
- text-align: left;
256
- padding: 8px 0;
257
- cursor: pointer;
258
- transition: all 0.2s ease;
259
- }
260
-
261
- .user-menu button:hover {
262
  color: var(--warm-amber);
263
  }
264
-
265
- .user-menu button i {
266
- margin-right: 8px;
267
- width: 20px;
268
- text-align: center;
269
- }
270
-
271
- .user-email {
272
- font-size: 0.8rem;
273
- color: var(--cool-blue);
274
- margin-bottom: 10px;
275
- word-break: break-all;
276
- }
277
  </style>
278
  </head>
279
  <body>
 
 
 
 
 
 
 
 
 
280
  <!-- User Profile Indicator -->
281
  <div class="user-profile" id="user-profile">
282
  <i class="fas fa-user"></i>
@@ -324,467 +149,154 @@
324
  </div>
325
  </div>
326
 
327
- <!-- ... (keep all previous HTML content) ... -->
 
 
 
328
 
 
329
  <script>
330
- // Backend API URL (in a real app, this would be your actual backend URL)
331
- const API_URL = 'https://api.cipherecstasy.example.com';
332
-
333
- // Mock backend functions (in a real app, these would be actual API calls)
334
- class BackendService {
335
- static async sendMagicLink(email) {
336
- // In a real app, this would be a fetch() call to your backend
337
- console.log(`Sending magic link to ${email}`);
338
-
339
- // Simulate network delay
340
- await new Promise(resolve => setTimeout(resolve, 1000));
341
-
342
- // Return a mock response
343
- return {
344
- success: true,
345
- message: "Magic link sent"
346
- };
347
- }
348
-
349
- static async verifyMagicLink(token) {
350
- // In a real app, this would verify the token with your backend
351
- console.log(`Verifying magic link token: ${token}`);
352
-
353
- // Simulate network delay
354
- await new Promise(resolve => setTimeout(resolve, 800));
355
-
356
- // Return a mock user
357
- return {
358
- success: true,
359
- user: {
360
- id: 'user_123',
361
- email: 'user@example.com',
362
- preferences: {
363
- pulseRate: 0.5,
364
- colors: ['cool-blue', 'electric-purple'],
365
- sounds: ['hum', 'heartbeat']
366
- }
367
- }
368
- };
369
- }
370
-
371
- static async savePreferences(userId, preferences) {
372
- // In a real app, this would save to your database
373
- console.log(`Saving preferences for user ${userId}:`, preferences);
374
-
375
- // Simulate network delay
376
- await new Promise(resolve => setTimeout(resolve, 500));
377
-
378
- return {
379
- success: true
380
- };
381
- }
382
-
383
- static async generateSensoryJourney(descriptors) {
384
- // In a real app, this would call your GPT microservice
385
- console.log(`Generating sensory journey for: ${descriptors}`);
386
-
387
- // Simulate API delay
388
- await new Promise(resolve => setTimeout(resolve, 2000));
389
-
390
- // Mock GPT response
391
- const responses = [
392
- {
393
- description: "A warm, pulsating experience with deep amber hues and a slow, rhythmic heartbeat. Thunder rumbles in the distance as silky textures flow across your senses.",
394
- settings: {
395
- pulseRate: 0.7,
396
- colors: ['warm-amber', 'electric-purple'],
397
- sounds: ['heartbeat', 'thunder'],
398
- intensity: 0.8
399
- }
400
- },
401
- {
402
- description: "Cool blue electric currents with rapid pulses and high-frequency hums. The sensation of silk brushing against your skin as the system synchronizes with your breath.",
403
- settings: {
404
- pulseRate: 0.9,
405
- colors: ['cool-blue', 'deep-space'],
406
- sounds: ['hum', 'heartbeat'],
407
- intensity: 0.6
408
- }
409
- },
410
- {
411
- description: "A balanced journey between warmth and coolness, with medium-paced pulses and occasional thunder strikes. The colors shift gradually from amber to purple, creating a mesmerizing effect.",
412
- settings: {
413
- pulseRate: 0.5,
414
- colors: ['warm-amber', 'electric-purple'],
415
- sounds: ['hum', 'thunder'],
416
- intensity: 0.5
417
- }
418
- }
419
- ];
420
-
421
- return {
422
- success: true,
423
- journey: responses[Math.floor(Math.random() * responses.length)]
424
- };
425
- }
426
  }
427
 
428
- // Auth and User Management
429
- class AuthManager {
430
- constructor() {
431
- this.currentUser = null;
432
- this.initAuth();
433
- }
434
-
435
- initAuth() {
436
- // Check for existing session (in a real app, this would check cookies/localStorage)
437
- const token = this.getMagicLinkToken();
438
-
439
- if (token) {
440
- this.verifyToken(token);
441
- } else {
442
- this.showAuthModal();
443
- }
444
- }
445
-
446
- getMagicLinkToken() {
447
- // In a real app, this would parse the URL for a magic link token
448
- const params = new URLSearchParams(window.location.search);
449
- return params.get('token');
450
- }
451
-
452
- async verifyToken(token) {
453
- try {
454
- const response = await BackendService.verifyMagicLink(token);
455
-
456
- if (response.success) {
457
- this.currentUser = response.user;
458
- this.handleAuthenticated();
459
-
460
- // Remove token from URL
461
- window.history.replaceState({}, document.title, window.location.pathname);
462
- } else {
463
- this.showAuthModal();
464
- }
465
- } catch (error) {
466
- console.error("Token verification failed:", error);
467
- this.showAuthModal();
468
- }
469
- }
470
-
471
- async sendMagicLink(email) {
472
- try {
473
- const response = await BackendService.sendMagicLink(email);
474
-
475
- if (response.success) {
476
- document.getElementById('magic-link-sent').style.display = 'block';
477
- document.getElementById('auth-email').value = '';
478
-
479
- // Hide after 3 seconds
480
- setTimeout(() => {
481
- document.getElementById('magic-link-sent').style.display = 'none';
482
- }, 3000);
483
- }
484
- } catch (error) {
485
- console.error("Failed to send magic link:", error);
486
- alert("Failed to send magic link. Please try again.");
487
- }
488
- }
489
-
490
- handleAuthenticated() {
491
- this.hideAuthModal();
492
- this.updateUI();
493
-
494
- // Initialize audio manager with user preferences
495
- if (window.audioManager) {
496
- window.audioManager.updateFromPreferences(this.currentUser.preferences);
497
- }
498
- }
499
-
500
- showAuthModal() {
501
- document.getElementById('auth-modal').style.display = 'flex';
502
- }
503
-
504
- hideAuthModal() {
505
- document.getElementById('auth-modal').style.display = 'none';
506
- }
507
-
508
- updateUI() {
509
- if (this.currentUser) {
510
- document.getElementById('user-email').textContent = this.currentUser.email;
511
- document.getElementById('user-profile').classList.add('active');
512
- } else {
513
- document.getElementById('user-email').textContent = 'Not logged in';
514
- document.getElementById('user-profile').classList.remove('active');
515
- }
516
- }
517
-
518
- logout() {
519
- this.currentUser = null;
520
- this.updateUI();
521
- this.showAuthModal();
522
-
523
- // In a real app, you would also clear cookies/localStorage
524
- console.log("User logged out");
525
- }
526
- }
527
 
528
- // Extended Audio Manager with Preferences
529
- class AudioManagerWithPreferences extends AudioManager {
530
- updateFromPreferences(preferences) {
531
- // Update pleasure dial based on saved preferences
532
- const pleasureDial = document.getElementById('pleasure-dial');
533
- const intensity = preferences.pulseRate * 100;
534
- pleasureDial.value = intensity;
535
- this.pleasureIntensity = preferences.pulseRate;
536
- document.getElementById('pleasure-value').textContent = `${intensity}%`;
537
-
538
- // Update colors
539
- this.updateColorScheme(preferences.colors);
540
-
541
- // Update audio toggles
542
- this.updateAudioToggles(preferences.sounds);
543
-
544
- // Apply all changes
545
- this.updatePleasureEffects();
546
- }
547
 
548
- updateColorScheme(colors) {
549
- // In a real app, this would update the color scheme based on preferences
550
- console.log("Updating color scheme to:", colors);
551
-
552
- // Example: Update CSS variables based on selected colors
553
- if (colors.includes('warm-amber')) {
554
- document.documentElement.style.setProperty('--warm-amber', 'rgba(245, 158, 11, 0.8)');
555
- }
556
-
557
- if (colors.includes('cool-blue')) {
558
- document.documentElement.style.setProperty('--cool-blue', 'rgba(56, 189, 248, 0.8)');
559
- }
560
-
561
- if (colors.includes('electric-purple')) {
562
- document.documentElement.style.setProperty('--electric-purple', 'rgba(139, 92, 246, 0.8)');
563
- }
564
- }
565
-
566
- updateAudioToggles(sounds) {
567
- // Toggle audio tracks based on preferences
568
- const toggles = {
569
- 'hum': document.getElementById('toggle-hum'),
570
- 'heartbeat': document.getElementById('toggle-heartbeat'),
571
- 'thunder': document.getElementById('toggle-thunder')
572
- };
573
-
574
- // Reset all toggles
575
- Object.values(toggles).forEach(toggle => {
576
- toggle.classList.remove('active');
577
- });
578
-
579
- // Activate preferred sounds
580
- sounds.forEach(sound => {
581
- if (toggles[sound]) {
582
- toggles[sound].classList.add('active');
583
-
584
- // Play the audio if it's preferred
585
- const audioElement = document.getElementById(`${sound}-audio`);
586
- if (audioElement) {
587
- audioElement.play().catch(e => console.log("Audio play error:", e));
588
- }
589
- }
590
- });
591
- }
592
-
593
- async saveCurrentPreferences() {
594
- if (!window.authManager.currentUser) return;
595
-
596
- const preferences = {
597
- pulseRate: this.pleasureIntensity,
598
- colors: this.getCurrentColors(),
599
- sounds: this.getActiveSounds()
600
- };
601
-
602
- try {
603
- await BackendService.savePreferences(
604
- window.authManager.currentUser.id,
605
- preferences
606
- );
607
-
608
- console.log("Preferences saved successfully");
609
- } catch (error) {
610
- console.error("Failed to save preferences:", error);
611
- }
612
- }
613
-
614
- getCurrentColors() {
615
- // In a real app, this would detect current color scheme
616
- return ['cool-blue', 'electric-purple'];
617
- }
618
-
619
- getActiveSounds() {
620
- const activeSounds = [];
621
-
622
- if (document.getElementById('toggle-hum').classList.contains('active')) {
623
- activeSounds.push('hum');
624
- }
625
-
626
- if (document.getElementById('toggle-heartbeat').classList.contains('active')) {
627
- activeSounds.push('heartbeat');
628
- }
629
-
630
- if (document.getElementById('toggle-thunder').classList.contains('active')) {
631
- activeSounds.push('thunder');
632
- }
633
-
634
- return activeSounds;
635
- }
636
- }
637
 
638
- // Sensory Journey Manager
639
- class SensoryJourneyManager {
640
- constructor() {
641
- this.initJourneyPanel();
642
- }
643
-
644
- initJourneyPanel() {
645
- document.getElementById('show-journey').addEventListener('click', () => {
646
- this.showJourneyPanel();
647
- });
648
-
649
- document.getElementById('hide-journey').addEventListener('click', () => {
650
- this.hideJourneyPanel();
651
- });
652
-
653
- document.getElementById('generate-journey').addEventListener('click', () => {
654
- this.generateJourney();
655
- });
656
-
657
- document.getElementById('apply-journey').addEventListener('click', () => {
658
- this.applyJourneySettings();
659
- });
660
- }
661
-
662
- showJourneyPanel() {
663
- document.getElementById('journey-container').classList.add('active');
664
- document.getElementById('user-profile').classList.remove('active');
665
- }
666
 
667
- hideJourneyPanel() {
668
- document.getElementById('journey-container').classList.remove('active');
669
- }
670
 
671
- async generateJourney() {
672
- const input = document.getElementById('journey-input').value.trim();
673
-
674
- if (!input) {
675
- alert("Please describe your desired journey");
676
- return;
677
- }
678
-
679
- // Show loading state
680
- document.getElementById('journey-loading').style.display = 'block';
681
- document.getElementById('journey-result').style.display = 'none';
682
-
683
- try {
684
- const response = await BackendService.generateSensoryJourney(input);
685
-
686
- if (response.success) {
687
- this.displayJourneyResult(response.journey);
688
- } else {
689
- alert("Failed to generate journey. Please try again.");
690
- }
691
- } catch (error) {
692
- console.error("Journey generation error:", error);
693
- alert("An error occurred while generating your journey");
694
- } finally {
695
- document.getElementById('journey-loading').style.display = 'none';
696
- }
697
- }
698
 
699
- displayJourneyResult(journey) {
700
- document.getElementById('journey-text').textContent = journey.description;
701
- document.getElementById('journey-result').style.display = 'block';
702
-
703
- // Store the settings for later application
704
- this.currentJourneySettings = journey.settings;
705
- }
706
 
707
- applyJourneySettings() {
708
- if (!this.currentJourneySettings || !window.authManager.currentUser) return;
709
-
710
- // Update audio manager with journey settings
711
- if (window.audioManager) {
712
- // Convert pulse rate to 0-1 scale if needed
713
- const pulseRate = this.currentJourneySettings.pulseRate;
714
-
715
- // Update UI
716
- const pleasureDial = document.getElementById('pleasure-dial');
717
- pleasureDial.value = pulseRate * 100;
718
- document.getElementById('pleasure-value').textContent = `${Math.round(pulseRate * 100)}%`;
719
-
720
- // Update audio manager
721
- window.audioManager.pleasureIntensity = pulseRate;
722
- window.audioManager.updatePleasureEffects();
723
-
724
- // Update colors
725
- window.audioManager.updateColorScheme(this.currentJourneySettings.colors);
726
-
727
- // Update sounds
728
- window.audioManager.updateAudioToggles(this.currentJourneySettings.sounds);
729
-
730
- // Save preferences if user is logged in
731
- window.audioManager.saveCurrentPreferences();
732
-
733
- // Show confirmation
734
- alert("Journey settings applied successfully!");
735
- }
736
- }
737
- }
738
 
739
- // Initialize everything when DOM is loaded
740
- window.addEventListener('DOMContentLoaded', () => {
741
- // Initialize auth manager
742
- window.authManager = new AuthManager();
743
-
744
- // Initialize audio manager with preferences support
745
- window.audioManager = new AudioManagerWithPreferences();
746
-
747
- // Initialize sensory journey manager
748
- new SensoryJourneyManager();
749
-
750
- // Set up event listeners
751
- document.getElementById('send-magic-link').addEventListener('click', () => {
752
- const email = document.getElementById('auth-email').value.trim();
753
- if (email) {
754
- window.authManager.sendMagicLink(email);
755
- } else {
756
- alert("Please enter your email address");
757
- }
758
- });
759
-
760
- document.getElementById('logout-btn').addEventListener('click', () => {
761
- window.authManager.logout();
762
- });
763
-
764
- // Allow Enter key to send magic link
765
- document.getElementById('auth-email').addEventListener('keypress', (e) => {
766
- if (e.key === 'Enter') {
767
- document.getElementById('send-magic-link').click();
768
- }
769
- });
770
-
771
- // Create electric elements
772
- createElectricElements();
773
-
774
- // Initialize WebGL particle system
775
- const canvas = document.getElementById('webgl-canvas');
776
- if (canvas) {
777
- new ParticleSystem(canvas);
778
- }
779
-
780
- // Recreate elements periodically for variety
781
- setInterval(() => {
782
- document.getElementById('electric-nodes').innerHTML = '';
783
- createElectricElements();
784
- }, 10000);
785
  });
786
 
787
- // ... (keep all remaining JavaScript functions like createElectricElements, ParticleSystem, etc.) ...
 
 
 
 
 
 
 
 
788
  </script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
789
  <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=Boobs00/cipherecstasy" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
790
  </html>
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <meta name="theme-color" content="#0f0f1a">
7
+ <meta name="description" content="Algorithmic Ecstasy - A sensory experience combining visuals, sound, and rhythm">
8
  <title>CipherEcstasy - Algorithmic Ecstasy</title>
9
+
10
+ <!-- PWA Manifest -->
11
+ <link rel="manifest" href="/manifest.json">
12
+
13
+ <!-- Favicon -->
14
+ <link rel="icon" href="/favicon.ico" sizes="any">
15
+ <link rel="icon" href="/icon.svg" type="image/svg+xml">
16
+ <link rel="apple-touch-icon" href="/apple-touch-icon.png">
17
+
18
+ <!-- Tailwind CSS -->
19
  <script src="https://cdn.tailwindcss.com"></script>
20
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
21
+
22
  <style>
23
  @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;500;600;700&family=Inter:wght@300;400;500;600;700&display=swap');
24
 
 
38
  color: #e0e0ff;
39
  }
40
 
41
+ /* ... (all previous CSS styles remain unchanged) ... */
42
 
43
+ /* PWA Install Prompt */
44
+ .pwa-install-prompt {
45
  position: fixed;
46
+ bottom: 20px;
47
+ left: 50%;
48
+ transform: translateX(-50%);
49
+ background: rgba(15, 15, 26, 0.95);
50
+ border: 1px solid var(--electric-purple);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  border-radius: 8px;
52
  padding: 15px;
53
+ width: 90%;
54
+ max-width: 400px;
55
+ z-index: 1001;
56
+ display: none;
57
  backdrop-filter: blur(5px);
58
+ box-shadow: 0 5px 20px rgba(0, 0, 0, 0.5);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  }
60
+
61
+ .pwa-install-prompt p {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  margin-bottom: 10px;
 
 
 
 
 
 
 
 
 
63
  color: var(--cool-blue);
 
 
 
 
 
64
  }
65
+
66
+ .pwa-install-buttons {
67
+ display: flex;
68
+ gap: 10px;
69
  }
70
+
71
+ .pwa-install-btn {
72
+ flex: 1;
73
+ padding: 8px;
 
74
  border-radius: 4px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  cursor: pointer;
76
+ font-family: 'Orbitron', sans-serif;
77
+ font-size: 0.8rem;
78
+ text-transform: uppercase;
79
+ letter-spacing: 1px;
 
 
 
 
 
 
 
 
80
  }
81
+
82
+ .pwa-install-confirm {
83
  background: rgba(56, 189, 248, 0.2);
84
+ border: 1px solid var(--cool-blue);
85
+ color: var(--cool-blue);
86
  }
87
+
88
+ .pwa-install-cancel {
89
+ background: rgba(30, 30, 45, 0.8);
90
+ border: 1px solid var(--warm-amber);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  color: var(--warm-amber);
92
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
93
  </style>
94
  </head>
95
  <body>
96
+ <!-- PWA Install Prompt -->
97
+ <div class="pwa-install-prompt" id="pwa-install-prompt">
98
+ <p>Install CipherEcstasy for full immersive experience?</p>
99
+ <div class="pwa-install-buttons">
100
+ <button class="pwa-install-btn pwa-install-confirm" id="pwa-install-confirm">Install</button>
101
+ <button class="pwa-install-btn pwa-install-cancel" id="pwa-install-cancel">Later</button>
102
+ </div>
103
+ </div>
104
+
105
  <!-- User Profile Indicator -->
106
  <div class="user-profile" id="user-profile">
107
  <i class="fas fa-user"></i>
 
149
  </div>
150
  </div>
151
 
152
+ <!-- Main Content (keep all your existing content) -->
153
+ <div class="container mx-auto px-4 py-12">
154
+ <!-- ... (your existing content remains unchanged) ... -->
155
+ </div>
156
 
157
+ <!-- Service Worker Registration -->
158
  <script>
159
+ // Register Service Worker for PWA
160
+ if ('serviceWorker' in navigator) {
161
+ window.addEventListener('load', () => {
162
+ navigator.serviceWorker.register('/sw.js')
163
+ .then(registration => {
164
+ console.log('ServiceWorker registration successful with scope: ', registration.scope);
165
+ })
166
+ .catch(err => {
167
+ console.log('ServiceWorker registration failed: ', err);
168
+ });
169
+ });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
  }
171
 
172
+ // PWA Install Prompt Logic
173
+ let deferredPrompt;
174
+ const pwaInstallPrompt = document.getElementById('pwa-install-prompt');
175
+ const pwaInstallConfirm = document.getElementById('pwa-install-confirm');
176
+ const pwaInstallCancel = document.getElementById('pwa-install-cancel');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
 
178
+ window.addEventListener('beforeinstallprompt', (e) => {
179
+ // Prevent the mini-infobar from appearing on mobile
180
+ e.preventDefault();
181
+ // Stash the event so it can be triggered later
182
+ deferredPrompt = e;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
183
 
184
+ // Show our custom install prompt
185
+ pwaInstallPrompt.style.display = 'block';
186
+ });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
187
 
188
+ pwaInstallConfirm.addEventListener('click', async () => {
189
+ if (!deferredPrompt) return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
190
 
191
+ // Show the install prompt
192
+ deferredPrompt.prompt();
 
193
 
194
+ // Wait for the user to respond to the prompt
195
+ const { outcome } = await deferredPrompt.userChoice;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
196
 
197
+ // Hide our custom prompt
198
+ pwaInstallPrompt.style.display = 'none';
 
 
 
 
 
199
 
200
+ // We've used the prompt, and can't use it again
201
+ deferredPrompt = null;
202
+ });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
203
 
204
+ pwaInstallCancel.addEventListener('click', () => {
205
+ pwaInstallPrompt.style.display = 'none';
206
+ });
207
+
208
+ // Track PWA installation
209
+ window.addEventListener('appinstalled', () => {
210
+ console.log('PWA was installed');
211
+ pwaInstallPrompt.style.display = 'none';
212
+ deferredPrompt = null;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
213
  });
214
 
215
+ // Check if running as PWA
216
+ function isRunningAsPWA() {
217
+ return window.matchMedia('(display-mode: standalone)').matches ||
218
+ window.navigator.standalone ||
219
+ document.referrer.includes('android-app://');
220
+ }
221
+
222
+ // All previous JavaScript remains unchanged
223
+ // ... (keep all your existing JavaScript code) ...
224
  </script>
225
+
226
+ <!-- Docker and Kubernetes deployment instructions (commented out in HTML) -->
227
+ <!--
228
+ Dockerfile:
229
+ ===========
230
+ # Use Node.js as base image
231
+ FROM node:18-alpine as builder
232
+
233
+ # Create app directory
234
+ WORKDIR /app
235
+
236
+ # Install dependencies
237
+ COPY package*.json ./
238
+ RUN npm install
239
+
240
+ # Bundle app source
241
+ COPY . .
242
+
243
+ # Build the app
244
+ RUN npm run build
245
+
246
+ # Production stage
247
+ FROM nginx:alpine
248
+ COPY --from=builder /app/dist /usr/share/nginx/html
249
+ COPY nginx.conf /etc/nginx/nginx.conf
250
+
251
+ EXPOSE 80
252
+ CMD ["nginx", "-g", "daemon off;"]
253
+
254
+
255
+ Kubernetes Deployment (deployment.yaml):
256
+ =======================================
257
+ apiVersion: apps/v1
258
+ kind: Deployment
259
+ metadata:
260
+ name: cipherecstasy
261
+ labels:
262
+ app: cipherecstasy
263
+ spec:
264
+ replicas: 3
265
+ selector:
266
+ matchLabels:
267
+ app: cipherecstasy
268
+ template:
269
+ metadata:
270
+ labels:
271
+ app: cipherecstasy
272
+ spec:
273
+ containers:
274
+ - name: cipherecstasy
275
+ image: your-registry/cipherecstasy:latest
276
+ ports:
277
+ - containerPort: 80
278
+ resources:
279
+ requests:
280
+ cpu: "100m"
281
+ memory: "128Mi"
282
+ limits:
283
+ cpu: "500m"
284
+ memory: "512Mi"
285
+ restartPolicy: Always
286
+
287
+ ---
288
+ apiVersion: v1
289
+ kind: Service
290
+ metadata:
291
+ name: cipherecstasy-service
292
+ spec:
293
+ selector:
294
+ app: cipherecstasy
295
+ ports:
296
+ - protocol: TCP
297
+ port: 80
298
+ targetPort: 80
299
+ type: LoadBalancer
300
+ -->
301
  <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=Boobs00/cipherecstasy" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
302
  </html>
prompts.txt CHANGED
@@ -4,4 +4,5 @@ Enhance CSS interactions: - On hover, elements should shift between cool blues
4
  Add a background canvas: - Render kaleidoscopic bursts of color and silent fireworks on a WebGL canvas behind the UI. - Synchronize patterns with user scroll and cursor movement—each pulse triggering a new bloom. - Ensure smooth 60 fps animation and fallback to CSS keyframes on low‑power devices.
5
  Integrate audio assets: - Embed a looping ambient “electric hum” track. - Layer in heartbeat thumps and distant thunder hits that crescendo on user interaction. - Expose volume controls and allow users to toggle individual stems (hum, heartbeat, thunder).
6
  Build interactive modules: - Create a “Pleasure Dial” slider that amplifies pulse speed, color intensity, and audio volume simultaneously. - Add haptic feedback support for compatible devices—vibrations pulsing in time with the dial. - Log each interaction server‑side to drive future personalization.
7
- Wire up the backend: - Use a simple user login (email + magic link) and store preferences for pulse rate, colors, and sounds. - Generate personalized “sensory journeys” using a small GPT‑powered microservice: provide seed descriptors (“warmth,” “thunder,” “silk”) and return custom animations and text overlays.
 
 
4
  Add a background canvas: - Render kaleidoscopic bursts of color and silent fireworks on a WebGL canvas behind the UI. - Synchronize patterns with user scroll and cursor movement—each pulse triggering a new bloom. - Ensure smooth 60 fps animation and fallback to CSS keyframes on low‑power devices.
5
  Integrate audio assets: - Embed a looping ambient “electric hum” track. - Layer in heartbeat thumps and distant thunder hits that crescendo on user interaction. - Expose volume controls and allow users to toggle individual stems (hum, heartbeat, thunder).
6
  Build interactive modules: - Create a “Pleasure Dial” slider that amplifies pulse speed, color intensity, and audio volume simultaneously. - Add haptic feedback support for compatible devices—vibrations pulsing in time with the dial. - Log each interaction server‑side to drive future personalization.
7
+ Wire up the backend: - Use a simple user login (email + magic link) and store preferences for pulse rate, colors, and sounds. - Generate personalized “sensory journeys” using a small GPT‑powered microservice: provide seed descriptors (“warmth,” “thunder,” “silk”) and return custom animations and text overlays.
8
+ Finalize and deploy: - Configure Vercel or Netlify for CI/CD. - Enable PWA features: offline cache, “Add to Home Screen,” and a custom splash screen. - Write Dockerfile and Kubernetes manifest for scalable container deployment.