4sp-dv 1.0.48 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/4simpleproblems_v5.html +138 -196
  2. package/README.md +86 -0
  3. package/logged-in/securly-tester.html +156 -370
  4. package/logged-in/soundboard.html +6 -23
  5. package/logged-in/velium.html +70 -0
  6. package/package.json +1 -1
  7. package/CMTT/airline-manager-tycoon/airplane-images/aa330.png +0 -0
  8. package/CMTT/airline-manager-tycoon/airplane-images/aa340.png +0 -0
  9. package/CMTT/airline-manager-tycoon/airplane-images/aa350.png +0 -0
  10. package/CMTT/airline-manager-tycoon/airplane-images/aa380.png +0 -0
  11. package/CMTT/airline-manager-tycoon/airplane-images/b737.png +0 -0
  12. package/CMTT/airline-manager-tycoon/airplane-images/b747.png +0 -0
  13. package/CMTT/airline-manager-tycoon/airplane-images/b757.png +0 -0
  14. package/CMTT/airline-manager-tycoon/airplane-images/b767.png +0 -0
  15. package/CMTT/airline-manager-tycoon/airplane-images/b777.png +0 -0
  16. package/CMTT/airline-manager-tycoon/airplane-images/b787.png +0 -0
  17. package/CMTT/airline-manager-tycoon/airplane-images/hi.txt +0 -1
  18. package/CMTT/airline-manager-tycoon/index.html +0 -31
  19. package/CMTT/airline-manager-tycoon/script.js +0 -569
  20. package/CMTT/airline-manager-tycoon/style.css +0 -79
  21. package/CMTT/ez-money-1/icon.png +0 -0
  22. package/CMTT/ez-money-1/index.html +0 -1064
  23. package/CMTT/ez-money-1/script.js +0 -3221
  24. package/CMTT/ez-money-1/style.css +0 -381
  25. package/CMTT/ez-money-2/index.html +0 -22
  26. package/CMTT/ez-money-2/script.js +0 -460
  27. package/CMTT/ez-money-2/style.css +0 -103
  28. package/CMTT/ez-money-3/font.otf +0 -0
  29. package/CMTT/ez-money-3/index.html +0 -62
  30. package/CMTT/ez-money-3/script.js +0 -562
  31. package/CMTT/ez-money-3/style.css +0 -253
  32. package/CMTT/slots/index.html +0 -33
  33. package/CMTT/slots/script.js +0 -134
  34. package/CMTT/slots/style.css +0 -54
@@ -6,11 +6,14 @@
6
6
  <title>4SP - VERSION 5 CLIENT</title>
7
7
  <link rel="icon" type="image/png" href="https://cdn.jsdelivr.net/npm/4sp-dv@latest/images/logo.png">
8
8
 
9
- <base href="https://cdn.jsdelivr.net/npm/4sp-dv@1.0.47/logged-in/">
9
+ <base href="https://cdn.jsdelivr.net/npm/4sp-dv@1.0.44/logged-in/">
10
10
  <script src="https://cdn.tailwindcss.com"></script>
11
11
  <link href="https://fonts.googleapis.com/css2?family=Geist:wght@100..900&display=swap" rel="stylesheet">
12
12
 
13
13
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css">
14
+
15
+ <script src="https://cdn.jsdelivr.net/npm/fireworks-js@2.x/dist/index.umd.js"></script>
16
+
14
17
  <style>
15
18
  body {
16
19
  background-color: #040404;
@@ -45,6 +48,27 @@
45
48
  z-index: 60;
46
49
  transition: background-color 0.3s ease, border-color 0.3s ease;
47
50
  position: relative;
51
+ overflow: visible;
52
+ }
53
+
54
+ /* --- FIREWORKS CONTAINER --- */
55
+ #fireworks-container {
56
+ position: absolute;
57
+ top: 0;
58
+ left: 0;
59
+ width: 100%;
60
+ height: 100%;
61
+ pointer-events: none; /* Let clicks pass through */
62
+ z-index: 1; /* Sit above background */
63
+ opacity: 0;
64
+ transition: opacity 0.5s ease;
65
+ overflow: hidden;
66
+ }
67
+
68
+ /* Ensure navbar content sits ABOVE the fireworks */
69
+ #navbar-container > *:not(#fireworks-container) {
70
+ position: relative;
71
+ z-index: 10;
48
72
  }
49
73
 
50
74
  /* --- FIXED OVERLAY LOGIC --- */
@@ -171,15 +195,15 @@
171
195
  z-index: 50;
172
196
  }
173
197
 
174
- /* --- DISABLE ANIMATIONS FOR AUTH BTN --- */
175
198
  #auth-btn, #auth-btn:hover, #auth-btn:active {
176
199
  transform: none !important;
177
200
  transition: none !important;
178
201
  background-color: transparent !important;
179
- z-index: auto !important;
202
+ z-index: 65 !important;
203
+ cursor: pointer !important;
180
204
  }
181
205
 
182
- /* Auth Menu & Settings */
206
+ /* --- Auth Menu & Settings (Updated for dynamic theming) --- */
183
207
  .auth-menu {
184
208
  position: absolute;
185
209
  right: 0;
@@ -192,7 +216,7 @@
192
216
  display: none;
193
217
  flex-direction: column;
194
218
  gap: 0.5rem;
195
- z-index: 50;
219
+ z-index: 70;
196
220
  box-shadow: 0 10px 30px rgba(0,0,0,0.6);
197
221
  transform-origin: top right;
198
222
  }
@@ -213,9 +237,10 @@
213
237
  align-items: center;
214
238
  gap: 0.75rem;
215
239
  padding: 0.75rem 1rem;
216
- color: var(--menu-text, #d1d5db);
217
- background: #0a0a0a;
218
- border: 1px solid #333;
240
+ /* UPDATED: Uses variables for dynamic theme support */
241
+ color: var(--menu-item-text, #d1d5db);
242
+ background: var(--menu-item-bg, #0a0a0a);
243
+ border: 1px solid var(--menu-item-border, #333);
219
244
  border-radius: 1rem;
220
245
  text-decoration: none;
221
246
  font-size: 0.9rem;
@@ -225,9 +250,10 @@
225
250
  }
226
251
 
227
252
  .auth-menu-item:hover {
228
- background-color: #000;
229
- border-color: #fff;
230
- color: #fff;
253
+ /* UPDATED: Uses variables for dynamic theme support */
254
+ background-color: var(--menu-item-hover-bg, #000);
255
+ border-color: var(--menu-item-hover-border, #fff);
256
+ color: var(--menu-item-hover-text, #fff);
231
257
  transform: translateY(-2px) scale(1.02);
232
258
  box-shadow: 0 5px 15px rgba(255,255,255,0.05);
233
259
  }
@@ -236,13 +262,6 @@
236
262
  transform: translateY(0) scale(0.98);
237
263
  }
238
264
 
239
- .auth-menu-item .fa-gear, .nav-tab .fa-gear {
240
- display: inline-block;
241
- transform-origin: center;
242
- /* Quick transition for each "click" step */
243
- transition: transform 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
244
- }
245
-
246
265
  .auth-header {
247
266
  padding: 0.5rem 1rem;
248
267
  border-bottom: 1px solid var(--menu-divider, #333);
@@ -312,13 +331,13 @@
312
331
  }
313
332
 
314
333
  .settings-box {
315
- border: 1px solid #333; border-radius: 1.5rem;
334
+ border: 1px solid #333; border-radius: 1rem;
316
335
  background-color: #000000; padding: 1.5rem; margin-bottom: 1.5rem;
317
336
  }
318
337
 
319
338
  .input-text-style, .input-select-style {
320
339
  width: 100%; padding: 0.75rem; border: 1px solid #252525;
321
- background-color: #111111; border-radius: 1rem; color: #c0c0c0; transition: all 0.2s;
340
+ background-color: #111111; border-radius: 0.5rem; color: #c0c0c0; transition: all 0.2s;
322
341
  }
323
342
  .input-text-style:focus, .input-select-style:focus {
324
343
  border-color: #505050; outline: none; box-shadow: 0 0 0 2px rgba(80, 80, 80, 0.5);
@@ -326,24 +345,13 @@
326
345
 
327
346
  .input-key-style {
328
347
  width: 4rem; padding: 0.75rem; border: 1px solid #252525;
329
- background-color: #111111; border-radius: 1rem; color: #c0c0c0;
348
+ background-color: #111111; border-radius: 0.5rem; color: #c0c0c0;
330
349
  transition: all 0.2s; font-size: 1.1rem; text-align: center;
331
350
  font-weight: 500; text-transform: uppercase; caret-color: transparent;
332
351
  }
333
352
  .input-key-style:focus {
334
353
  border-color: #505050; outline: none; box-shadow: 0 0 0 2px rgba(80, 80, 80, 0.5);
335
354
  }
336
-
337
- /* Preference Toggles */
338
- .icon-btn.off {
339
- border-color: #ef4444;
340
- color: #ef4444;
341
- background-color: rgba(239, 68, 68, 0.05);
342
- }
343
- .icon-btn.off:hover {
344
- background-color: rgba(239, 68, 68, 0.1);
345
- border-color: #f87171;
346
- }
347
355
  .input-key-style::placeholder { font-size: 1rem; text-transform: none; }
348
356
 
349
357
  .general-message-area { min-height: 20px; margin-top: 1rem; font-weight: 400; }
@@ -398,21 +406,8 @@
398
406
  }
399
407
  .shake-anim { animation: shake 0.4s cubic-bezier(.36,.07,.19,.97) both; }
400
408
 
401
- /* Animation Control */
402
- body.no-animations *,
403
- body.no-animations *:hover,
404
- body.no-animations *:active,
405
- body.no-animations *:focus {
406
- transition: none !important;
407
- animation: none !important;
408
- transform: none !important;
409
- box-shadow: none !important;
410
- }
411
-
412
- body.no-animations .auth-menu-item .fa-gear,
413
- body.no-animations .nav-tab .fa-gear {
414
- transition: none !important;
415
- transform: none !important;
409
+ body.no-animations * {
410
+ transition: none !important; animation: none !important; transform: none !important;
416
411
  }
417
412
 
418
413
  /* Bubbly Spring Transition */
@@ -579,6 +574,8 @@
579
574
  </div>
580
575
 
581
576
  <div id="navbar-container">
577
+ <div id="fireworks-container"></div>
578
+
582
579
  <img src="https://cdn.jsdelivr.net/npm/4sp-asset-library@latest/logo.png" id="navbar-logo" class="navbar-logo" alt="Logo">
583
580
 
584
581
  <div class="tab-wrapper">
@@ -635,29 +632,13 @@
635
632
  <h3 class="text-3xl font-bold text-white mb-6">General Settings</h3>
636
633
 
637
634
  <div class="settings-box">
638
- <h3 class="text-xl font-bold text-white mb-2">Account Details & Preferences</h3>
639
-
635
+ <h3 class="text-xl font-bold text-white mb-2">Account Username</h3>
640
636
  <label class="block text-gray-400 text-sm mb-2 font-light">New Username</label>
641
- <div class="flex gap-2 mb-6">
637
+ <div class="flex gap-2">
642
638
  <input type="text" id="settings-username-input" class="input-text-style" placeholder="Enter username">
643
639
  <button id="save-username-btn" class="btn-toolbar-style btn-primary-override">Save</button>
644
640
  </div>
645
641
  <p id="username-msg" class="general-message-area text-sm mt-2"></p>
646
-
647
- <div class="flex gap-8 items-center pt-4 border-t border-[#1a1a1a]">
648
- <div class="flex flex-col items-center gap-2">
649
- <button id="toggle-animations-btn" class="icon-btn" title="Toggle Navbar Animations">
650
- <i class="fa-solid fa-wand-magic-sparkles"></i>
651
- </button>
652
- <span class="text-xs text-gray-500">Animations</span>
653
- </div>
654
- <div class="flex flex-col items-center gap-2">
655
- <button id="toggle-sounds-btn" class="icon-btn" title="Toggle UI Sounds">
656
- <i class="fa-solid fa-volume-high"></i>
657
- </button>
658
- <span class="text-xs text-gray-500">Sounds</span>
659
- </div>
660
- </div>
661
642
  </div>
662
643
 
663
644
  <h3 class="text-xl font-bold text-white mb-2 mt-6">Organization</h3>
@@ -710,8 +691,7 @@
710
691
 
711
692
  <label class="block text-gray-400 text-xs mb-2 font-light">Background Color</label>
712
693
  <div class="flex flex-wrap gap-2 mb-6" id="pfp-color-grid">
713
- <!-- Colors generated by JS -->
714
- </div>
694
+ </div>
715
695
 
716
696
  <button id="save-letter-pfp-btn" class="btn-toolbar-style btn-primary-override w-full justify-center">Set Letter Avatar</button>
717
697
  </div>
@@ -732,8 +712,7 @@
732
712
 
733
713
  <h3 class="text-xl font-bold text-white mb-2">Navigation Bar Theme</h3>
734
714
  <div class="settings-box p-4">
735
- <div id="theme-picker-container">
736
- </div>
715
+ <div id="theme-picker-container"></div>
737
716
  </div>
738
717
  </div>
739
718
 
@@ -872,7 +851,7 @@
872
851
  const displayUsername = document.getElementById('display-username');
873
852
  const displayEmail = document.getElementById('display-email');
874
853
 
875
- const BASE_URL = 'https://cdn.jsdelivr.net/npm/4sp-dv@1.0.47/logged-in/';
854
+ const BASE_URL = 'https://cdn.jsdelivr.net/npm/4sp-dv@1.0.44/logged-in/';
876
855
 
877
856
  // Preload Logos
878
857
  const preloadImgs = [
@@ -886,8 +865,10 @@
886
865
  const USER_DATA_KEY = 'local_user_data';
887
866
  const LAST_PAGE_KEY = 'local_last_page';
888
867
  const OWNER_EMAIL = "4simpleproblems@gmail.com"; // For admin checks
868
+ const FIREWORKS_SETTINGS_KEY = 'fireworks_settings';
889
869
 
890
- const PAGE_DATA = {
870
+ // RENAMED TO AVOID CONFLICTS
871
+ const CLIENT_PAGE_DATA = {
891
872
  "dashboard": { "name": "Dashboard", "icon": "fa-solid fa-house-user", "url": "dashboard.html" },
892
873
  "soundboard": { "name": "Soundboard", "icon": "fa-solid fa-volume-up", "url": "soundboard.html" },
893
874
  "notes": { "name": "Notes", "icon": "fa-solid fa-sticky-note", "url": "notes.html" },
@@ -897,12 +878,34 @@
897
878
  "dictionary": { "name": "Dictionary", "icon": "fa-solid fa-book", "url": "dictionary.html" },
898
879
  "messenger-v2": { "name": "Messenger", "icon": "fa-solid fa-comments", "url": "messenger-v2.html" },
899
880
  "games": { "name": "GAMES", "icon": "fa-solid fa-gamepad", "url": "games.html" },
881
+ "velium": { "name": "Velium", "icon": "fa-solid fa-music", "url": "velium.html" },
900
882
  "settings": { "name": "Settings", "icon": "fa-solid fa-gear", "url": "settings.html" }
901
883
  };
902
884
 
903
885
  let currentUser = null;
904
886
  let userDataUnsubscribe = null;
905
887
 
888
+ // --- FIREWORKS ENGINE INITIALIZATION ---
889
+ const fwContainer = document.getElementById('fireworks-container');
890
+
891
+ // HARDCODED SETTINGS AS REQUESTED
892
+ const fireworks = new Fireworks.default(fwContainer, {
893
+ autoresize: true,
894
+ opacity: 1.0, // Hardcoded
895
+ acceleration: 1.05,
896
+ friction: 0.97,
897
+ gravity: 1.5,
898
+ particles: 50, // Hardcoded
899
+ traceLength: 3,
900
+ traceSpeed: 10,
901
+ explosion: 5,
902
+ intensity: 5, // Hardcoded
903
+ flickering: 50,
904
+ lineStyle: 'round',
905
+ rocketsPoint: { min: 50, max: 50 }
906
+ });
907
+
908
+
906
909
  // --- ADMIN KEYBINDS LOGIC (Updated to Match admin_keybinds.js exactly) ---
907
910
  function initAdminKeybinds(db, auth, user) {
908
911
  console.log("[Admin Keybinds] Initializing for", user.uid);
@@ -1163,7 +1166,7 @@
1163
1166
 
1164
1167
  let currentPath = activePageUrl.replace(BASE_URL, '');
1165
1168
 
1166
- Object.entries(PAGE_DATA).forEach(([key, page]) => {
1169
+ Object.entries(CLIENT_PAGE_DATA).forEach(([key, page]) => {
1167
1170
  const isAuth = page.url === currentPath;
1168
1171
  const tab = document.createElement('a');
1169
1172
  tab.className = `nav-tab ${isAuth ? 'active' : ''}`;
@@ -1239,7 +1242,7 @@
1239
1242
  }, 50);
1240
1243
  }
1241
1244
 
1242
- // Auth Menu
1245
+ // Auth Menu (Wait for DOMContentLoaded equivalent in module)
1243
1246
  if (authBtn) {
1244
1247
  authBtn.addEventListener('click', (e) => {
1245
1248
  e.stopPropagation();
@@ -1362,9 +1365,6 @@
1362
1365
  }
1363
1366
 
1364
1367
  authBtn.innerHTML = pfpHtml;
1365
- authBtn.style.padding = '0'; // Remove padding to let avatar fill
1366
- authBtn.style.overflow = 'hidden'; // Ensure roundness
1367
- authBtn.style.border = '1px solid #4b5563'; // Maintain border
1368
1368
  }
1369
1369
 
1370
1370
  // --- Auto-Login Logic ---
@@ -1487,7 +1487,7 @@
1487
1487
 
1488
1488
  // Priority: Last Page > > Default
1489
1489
  if (lastPage) {
1490
- const isValid = Object.values(PAGE_DATA).some(p => p.url === lastPage);
1490
+ const isValid = Object.values(CLIENT_PAGE_DATA).some(p => p.url === lastPage);
1491
1491
  if (isValid) startPage = lastPage;
1492
1492
  }
1493
1493
 
@@ -1543,7 +1543,7 @@
1543
1543
  if (loader && loaderTitle && loaderBar) {
1544
1544
  // Determine Title
1545
1545
  let pageTitle = "Loading...";
1546
- const pageEntry = Object.values(PAGE_DATA).find(p => p.url === cleanPageName || p.url.includes(lookupName));
1546
+ const pageEntry = Object.values(CLIENT_PAGE_DATA).find(p => p.url === cleanPageName || p.url.includes(lookupName));
1547
1547
  if (pageEntry) pageTitle = pageEntry.name;
1548
1548
 
1549
1549
  loaderTitle.textContent = pageTitle;
@@ -2148,8 +2148,42 @@
2148
2148
  if (!res.ok) return;
2149
2149
  let themes = await res.json();
2150
2150
 
2151
+ // --- INJECT CUSTOM "THE NEW YEAR" THEME & REMOVE ROYAL ---
2152
+ // 1. Filter out Royal
2153
+ themes = themes.filter(t => t.name !== 'Royal');
2154
+
2155
+ // 2. Inject The New Year (Deep Blue)
2156
+ const newYearTheme = {
2157
+ "name": "The New Year",
2158
+ "navbar-bg": "#020617", // Very deep blue (Slate-950)
2159
+ "navbar-border": "#1e293b",
2160
+ "navbar-text": "#e2e8f0",
2161
+ "tab-text": "#94a3b8",
2162
+ "tab-hover-text": "#ffffff",
2163
+ "tab-hover-bg": "rgba(255, 255, 255, 0.1)",
2164
+ "tab-active-text": "#fcd34d", // Gold accent for festive feel
2165
+ "tab-active-bg": "rgba(252, 211, 77, 0.15)",
2166
+ "tab-active-border": "#fcd34d",
2167
+ "accent-color": "#fcd34d",
2168
+ "logo-src": "https://cdn.jsdelivr.net/npm/4sp-asset-library@latest/logo.png",
2169
+
2170
+ // --- UPDATED: AUTH MENU SPECIFIC THEME COLORS ---
2171
+ "menu-bg": "#020617",
2172
+ "menu-border": "#fcd34d", // Gold border for menu
2173
+ "menu-divider": "#1e293b",
2174
+ "menu-username-text": "#fcd34d", // Gold Username
2175
+ "menu-email-text": "#94a3b8",
2176
+ "menu-item-bg": "#0f172a", // Dark Slate for items
2177
+ "menu-item-text": "#cbd5e1",
2178
+ "menu-item-hover-bg": "rgba(252, 211, 77, 0.1)", // Gold tint on hover
2179
+ "menu-item-hover-text": "#fcd34d"
2180
+ };
2181
+
2182
+ themes.push(newYearTheme);
2183
+ // --------------------------------------------------------
2184
+
2151
2185
  // --- Sorting Logic from settings.js ---
2152
- const orderedThemeNames = ['Dark', 'Light', 'Christmas'];
2186
+ const orderedThemeNames = ['Dark', 'Light', 'Christmas', 'The New Year']; // Prioritize New Year
2153
2187
  const sortedThemes = [];
2154
2188
 
2155
2189
  orderedThemeNames.forEach(name => {
@@ -2214,22 +2248,33 @@
2214
2248
  function applyTheme(theme) {
2215
2249
  const root = document.documentElement;
2216
2250
 
2251
+ // --- FIREWORKS LOGIC ---
2252
+ if (theme.name === 'The New Year') {
2253
+ document.getElementById('fireworks-container').style.opacity = '1';
2254
+ fireworks.start();
2255
+ } else {
2256
+ document.getElementById('fireworks-container').style.opacity = '0';
2257
+ fireworks.stop();
2258
+ }
2259
+ // -----------------------
2260
+
2217
2261
  // --- Logo Path Modification ---
2218
2262
  let logoSrc;
2219
2263
  const isLightTheme = lightThemeNames.includes(theme.name);
2220
2264
 
2221
2265
  if (isLightTheme) {
2222
2266
  logoSrc = 'https://cdn.jsdelivr.net/npm/4sp-dv@latest/images/logo-dark.png';
2223
- root.style.setProperty('--menu-username-text', '#000000');
2224
- root.style.setProperty('--menu-email-text', '#444444');
2267
+ // Default light theme variables if not specified in theme
2268
+ if(!theme['menu-username-text']) root.style.setProperty('--menu-username-text', '#000000');
2269
+ if(!theme['menu-email-text']) root.style.setProperty('--menu-email-text', '#444444');
2225
2270
  } else if (theme.name === 'Christmas') {
2226
2271
  logoSrc = 'https://cdn.jsdelivr.net/npm/4sp-dv@latest/images/logo-christmas.png';
2227
- root.style.setProperty('--menu-username-text', 'white');
2228
- root.style.setProperty('--menu-email-text', '#9ca3af');
2272
+ if(!theme['menu-username-text']) root.style.setProperty('--menu-username-text', 'white');
2273
+ if(!theme['menu-email-text']) root.style.setProperty('--menu-email-text', '#9ca3af');
2229
2274
  } else {
2230
2275
  logoSrc = 'https://cdn.jsdelivr.net/npm/4sp-asset-library@latest/logo.png';
2231
- root.style.setProperty('--menu-username-text', 'white');
2232
- root.style.setProperty('--menu-email-text', '#9ca3af');
2276
+ if(!theme['menu-username-text']) root.style.setProperty('--menu-username-text', 'white');
2277
+ if(!theme['menu-email-text']) root.style.setProperty('--menu-email-text', '#9ca3af');
2233
2278
  }
2234
2279
 
2235
2280
  // Apply CSS Variables from theme object (overrides defaults if present)
@@ -2278,7 +2323,8 @@
2278
2323
  localStorage.setItem('user-navbar-theme', JSON.stringify(theme));
2279
2324
 
2280
2325
  // Apply Glide Button Color Sync
2281
- root.style.setProperty('--glide-btn-color', 'var(--tab-text)');
2326
+ const glideColor = theme['tab-active-text'] || theme['accent-color'] || '#ffffff';
2327
+ root.style.setProperty('--glide-btn-color', glideColor);
2282
2328
 
2283
2329
  // Also update user doc if logged in
2284
2330
  if (currentUser) {
@@ -2542,41 +2588,6 @@
2542
2588
 
2543
2589
  loadThemes();
2544
2590
  loadPanicKeys();
2545
-
2546
- // --- App Preference Toggles Init ---
2547
- const animBtn = document.getElementById('toggle-animations-btn');
2548
- const soundBtn = document.getElementById('toggle-sounds-btn');
2549
-
2550
- const updateToggleUI = () => {
2551
- const isEnabled = window.areAnimationsEnabled;
2552
- animBtn.classList.toggle('off', !isEnabled);
2553
- animBtn.innerHTML = isEnabled ? '<i class="fa-solid fa-wand-magic-sparkles"></i>' : '<i class="fa-solid fa-wand-magic"></i>';
2554
-
2555
- // Apply to body
2556
- if (isEnabled) document.body.classList.remove('no-animations');
2557
- else document.body.classList.add('no-animations');
2558
-
2559
- soundBtn.classList.toggle('off', window.isMuted);
2560
- soundBtn.innerHTML = window.isMuted ? '<i class="fa-solid fa-volume-xmark"></i>' : '<i class="fa-solid fa-volume-high"></i>';
2561
- };
2562
-
2563
- if (animBtn) {
2564
- animBtn.onclick = () => {
2565
- window.areAnimationsEnabled = !window.areAnimationsEnabled;
2566
- localStorage.setItem('app_animations_enabled', window.areAnimationsEnabled);
2567
- updateToggleUI();
2568
- };
2569
- }
2570
-
2571
- if (soundBtn) {
2572
- soundBtn.onclick = () => {
2573
- window.isMuted = !window.isMuted;
2574
- localStorage.setItem('app_is_muted', window.isMuted);
2575
- updateToggleUI();
2576
- };
2577
- }
2578
-
2579
- updateToggleUI();
2580
2591
  }
2581
2592
 
2582
2593
  checkAutoLogin();
@@ -2588,26 +2599,14 @@
2588
2599
  <script>
2589
2600
  // --- Sound & Notification Logic ---
2590
2601
  const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
2591
-
2592
- // Sync with global state
2593
- Object.defineProperty(window, 'isMuted', {
2594
- get: () => localStorage.getItem('app_is_muted') === 'true',
2595
- set: (v) => localStorage.setItem('app_is_muted', v)
2596
- });
2597
-
2598
- Object.defineProperty(window, 'areAnimationsEnabled', {
2599
- get: () => localStorage.getItem('app_animations_enabled') !== 'false',
2600
- set: (v) => localStorage.setItem('app_animations_enabled', v)
2601
- });
2602
-
2603
- // Initial Class Set
2604
- if (!window.areAnimationsEnabled) document.body.classList.add('no-animations');
2602
+ let isMuted = false;
2603
+ let areAnimationsEnabled = true;
2605
2604
 
2606
2605
  // EXPOSE PlayTypeSound GLOBALLY
2607
2606
  // Debounce to prevent rapid-fire stuttering if called too fast
2608
2607
  let typeSoundTimeout = null;
2609
2608
  window.playTypeSound = function() {
2610
- if (window.isMuted) return;
2609
+ if (isMuted) return;
2611
2610
  if (audioCtx.state === 'suspended') audioCtx.resume();
2612
2611
 
2613
2612
  // Small debounce
@@ -2648,7 +2647,7 @@
2648
2647
  };
2649
2648
 
2650
2649
  function playClickSound() {
2651
- if (window.isMuted) return;
2650
+ if (isMuted) return;
2652
2651
  if (audioCtx.state === 'suspended') audioCtx.resume();
2653
2652
 
2654
2653
  const osc = audioCtx.createOscillator();
@@ -2663,12 +2662,8 @@
2663
2662
  osc.stop(audioCtx.currentTime + 0.015);
2664
2663
  }
2665
2664
 
2666
- // --- App Preferences State ---
2667
- window.isMuted = localStorage.getItem('app_is_muted') === 'true';
2668
- window.areAnimationsEnabled = localStorage.getItem('app_animations_enabled') !== 'false'; // Default true
2669
-
2670
2665
  window.playMechClick = function(isReverse = false) {
2671
- if (window.isMuted || !window.areAnimationsEnabled) return;
2666
+ if (isMuted) return;
2672
2667
  if (audioCtx.state === 'suspended') audioCtx.resume();
2673
2668
  const now = audioCtx.currentTime;
2674
2669
 
@@ -2709,60 +2704,7 @@
2709
2704
  osc.stop(now + 0.02);
2710
2705
  };
2711
2706
 
2712
- // Gear Clicking Sequence
2713
- let gearHoverStartTime = 0;
2714
- let currentGearRotation = 0;
2715
- let currentAnimatingGear = null;
2716
- const gearClickDelays = [0, 120, 240, 360]; // Adjusted for 0.5s total
2717
-
2718
- const handleGearMouseOver = (e) => {
2719
- const target = e.target.closest('#auth-settings-btn, #nav-settings-tab');
2720
- if (target && currentAnimatingGear !== target) {
2721
- currentAnimatingGear = target;
2722
- const icon = target.querySelector('.fa-gear');
2723
- if (!icon) return;
2724
-
2725
- gearHoverStartTime = Date.now();
2726
- gearClickDelays.forEach((delay, index) => {
2727
- setTimeout(() => {
2728
- if (target.matches(':hover')) {
2729
- if (window.areAnimationsEnabled) {
2730
- currentGearRotation = (index + 1) * 45;
2731
- icon.style.transform = `rotate(${currentGearRotation}deg)`;
2732
- }
2733
- window.playMechClick(false);
2734
- }
2735
- }, delay);
2736
- });
2737
- }
2738
- };
2739
-
2740
- const handleGearMouseOut = (e) => {
2741
- const target = e.target.closest('#auth-settings-btn, #nav-settings-tab');
2742
- if (target && !target.contains(e.relatedTarget)) {
2743
- currentAnimatingGear = null;
2744
- const icon = target.querySelector('.fa-gear');
2745
- if (!icon) return;
2746
-
2747
- const elapsed = Date.now() - gearHoverStartTime;
2748
- const clickCount = gearClickDelays.filter(d => d <= elapsed).length;
2749
-
2750
- for (let i = 0; i < clickCount; i++) {
2751
- setTimeout(() => {
2752
- if (!target.matches(':hover')) {
2753
- if (window.areAnimationsEnabled) {
2754
- currentGearRotation -= 45;
2755
- icon.style.transform = `rotate(${currentGearRotation}deg)`;
2756
- }
2757
- window.playMechClick(true);
2758
- }
2759
- }, gearClickDelays[i]);
2760
- }
2761
- }
2762
- };
2763
-
2764
- document.addEventListener('mouseover', handleGearMouseOver);
2765
- document.addEventListener('mouseout', handleGearMouseOut);
2707
+ // Removed Gear Animation Logic
2766
2708
 
2767
2709
  const notificationContainer = document.getElementById('notification-container');
2768
2710
  function showNotification(message, iconClass = 'fa-solid fa-info-circle', type = 'info') {
package/README.md ADDED
@@ -0,0 +1,86 @@
1
+ <div align="center">
2
+ <img src="https://raw.githubusercontent.com/4simpleproblems-v5/4simpleproblems-v5.github.io/main/images/logo.png" width="120" />
3
+
4
+ <h1 style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif; font-weight: 400; color: #888; margin-bottom: 0;">
5
+ The platform for everyone. Even you.
6
+ </h1>
7
+ <h1 style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif; font-weight: 800; font-size: 3rem; margin-top: 0; color: #fff;">
8
+ The 4SP Organization.
9
+ </h1>
10
+
11
+ <p style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif; font-size: 1.2rem; color: #9ca3af; max-width: 600px;">
12
+ Official organizational home for <strong>4simpleproblems</strong>. Version 5 DV is built for unblockable access, full local security, and zero dependencies.
13
+ </p>
14
+
15
+ <div style="margin: 20px 0;">
16
+ <a href="https://4sp-organization.github.io/connection.html" style="text-decoration: none;">
17
+ <span style="background-color: rgba(147, 51, 234, 0.1); color: #c084fc; border: 1px solid rgba(192, 132, 252, 0.5); padding: 12px 24px; border-radius: 12px; font-family: sans-serif; font-weight: 500; margin-right: 10px;">
18
+ Connect to 4SP →
19
+ </span>
20
+ </a>
21
+ <a href="https://4sp-organization.github.io/create_link.html" style="text-decoration: none;">
22
+ <span style="background-color: rgba(249, 115, 22, 0.1); color: #fb923c; border: 1px solid rgba(253, 186, 116, 0.5); padding: 12px 24px; border-radius: 12px; font-family: sans-serif; font-weight: 500;">
23
+ Create a Link →
24
+ </span>
25
+ </a>
26
+ </div>
27
+
28
+ <div style="margin-top: 20px;">
29
+ <a href="https://discord.gg/A798ZZUgca"><img src="https://img.shields.io/badge/Discord-5865F2?style=for-the-badge&logo=discord&logoColor=white" /></a>
30
+ <a href="https://linktr.ee/4simpleproblems"><img src="https://img.shields.io/badge/Linktree-39E09B?style=for-the-badge&logo=linktree&logoColor=white" /></a>
31
+ </div>
32
+ </div>
33
+
34
+ <hr style="border: 1px solid #1a1a1a; margin: 40px 0;" />
35
+
36
+ <table style="width: 100%; border-collapse: collapse; border: none; font-family: sans-serif;">
37
+ <tr>
38
+ <td style="width: 33%; padding: 10px; border: none;">
39
+ <div style="background-color: #0d0d0d; border: 1px solid #1a1a1a; border-radius: 12px; padding: 20px; min-height: 150px;">
40
+ <h3 style="color: #c084fc; margin-top: 0;">Creation</h3>
41
+ <p style="color: #9ca3af; font-size: 14px;">Founded March 13, 2025. Started as a basic student soundboard and utility tool.</p>
42
+ </div>
43
+ </td>
44
+ <td style="width: 33%; padding: 10px; border: none;">
45
+ <div style="background-color: #0d0d0d; border: 1px solid #1a1a1a; border-radius: 12px; padding: 20px; min-height: 150px;">
46
+ <h3 style="color: #3b82f6; margin-top: 0;">The Shift (V4)</h3>
47
+ <p style="color: #9ca3af; font-size: 14px;">Introduced dashboard layouts, Tab Disguising, and the famous Panic Key system.</p>
48
+ </div>
49
+ </td>
50
+ <td style="width: 33%; padding: 10px; border: none;">
51
+ <div style="background-color: #0d0d0d; border: 1px solid #1a1a1a; border-radius: 12px; padding: 20px; min-height: 150px;">
52
+ <h3 style="color: #22c55e; margin-top: 0;">Rebuild (V5)</h3>
53
+ <p style="color: #9ca3af; font-size: 14px;">A complete rewrite focusing on security, 1,600+ games, and student utility.</p>
54
+ </div>
55
+ </td>
56
+ </tr>
57
+ </table>
58
+
59
+ <br />
60
+
61
+ <div style="background-color: #0d0d0d; border: 1px solid #1a1a1a; border-radius: 12px; padding: 30px; font-family: sans-serif;">
62
+
63
+ <p style="color: #c0c0c0;">4SP is a student-made web project built for bored school days. It mixes utilities, games, and tools that feel fast and local instead of corporate.</p>
64
+
65
+ <div align="center" style="margin: 20px 0;">
66
+ <img src="https://img.shields.io/badge/HTML5-E34F26?style=flat-square&logo=html5&logoColor=white" />
67
+ <img src="https://img.shields.io/badge/CSS3-1572B6?style=flat-square&logo=css3&logoColor=white" />
68
+ <img src="https://img.shields.io/badge/JavaScript-F7DF1E?style=flat-square&logo=javascript&logoColor=black" />
69
+ <img src="https://img.shields.io/badge/Firebase-FFCA28?style=flat-square&logo=firebase&logoColor=black" />
70
+ </div>
71
+
72
+ <h3 style="color: #fff; border-left: 3px solid #333; padding-left: 10px;">Deployment</h3>
73
+ <p style="color: #9ca3af;">Deploy your own instance of 4SP v5 instantly:</p>
74
+
75
+ <div align="center">
76
+ <a href="https://vercel.com/new/import?framework=other&s=https%3A%2F%2Fgithub.com%2F4simpleproblems-v5%2F4simpleproblems-v5.github.io"><img src="https://img.shields.io/badge/Deploy_to_Vercel-000000?style=for-the-badge&logo=vercel&logoColor=white" /></a>
77
+ <a href="https://app.netlify.com/start/deploy?repository=https://github.com/4simpleproblems-v5/4simpleproblems-v5.github.io"><img src="https://img.shields.io/badge/Deploy_to_Netlify-00C7B7?style=for-the-badge&logo=netlify&logoColor=white" /></a>
78
+ </div>
79
+ </div>
80
+
81
+ <br />
82
+
83
+ <div align="center" style="font-family: sans-serif; color: #606060; font-size: 12px;">
84
+ Developed and Maintained by the 4SP Organization <br />
85
+ &copy; 2025 4SP Organization. Built using modern web standards.
86
+ </div>