NeoPy commited on
Commit
a555ac2
·
verified ·
1 Parent(s): 0fbdadb

Rename apoty5.js to app.js

Browse files
Files changed (2) hide show
  1. apoty5.js +0 -274
  2. app.js +540 -0
apoty5.js DELETED
@@ -1,274 +0,0 @@
1
- // ==UserScript==
2
- // @name Persona 5 Spotify Theme
3
- // @namespace http://tampermonkey.net/
4
- // @version 1.0
5
- // @description Transform Spotify web interface with Persona 5 aesthetic styling
6
- // @author You
7
- // @match https://open.spotify.com/*
8
- // @grant GM_addStyle
9
- // @run-at document-start
10
- // ==/UserScript==
11
-
12
- (function() {
13
- 'use strict';
14
-
15
- // Persona 5 color scheme and styling
16
- const persona5CSS = `
17
- /* Global variables */
18
- :root {
19
- --persona-red: #D42426;
20
- --persona-black: #222222;
21
- --persona-white: #F8F6EF;
22
- --persona-gold: #E6C555;
23
- --persona-light-red: #FF5555;
24
- }
25
-
26
- /* Overall page styling */
27
- body, html {
28
- background-color: var(--persona-black) !important;
29
- color: var(--persona-white) !important;
30
- font-family: 'Arial', sans-serif !important;
31
- }
32
-
33
- /* Header styling */
34
- .main-topBar-container,
35
- .main-topBar-background,
36
- .main-navBar-navBar {
37
- background: linear-gradient(135deg, var(--persona-black) 0%, #333333 100%) !important;
38
- border-bottom: 2px solid var(--persona-red) !important;
39
- box-shadow: 0 4px 15px rgba(212, 36, 38, 0.5) !important;
40
- }
41
-
42
- /* Navigation bar styling */
43
- .main-navBar-navBarLink {
44
- color: var(--persona-white) !important;
45
- font-weight: bold !important;
46
- text-transform: uppercase !important;
47
- letter-spacing: 1px !important;
48
- position: relative !important;
49
- padding: 8px 16px !important;
50
- }
51
-
52
- .main-navBar-navBarLink:hover {
53
- color: var(--persona-red) !important;
54
- }
55
-
56
- .main-navBar-navBarLink::after {
57
- content: '' !important;
58
- position: absolute !important;
59
- bottom: 0 !important;
60
- left: 0 !important;
61
- width: 100% !important;
62
- height: 2px !important;
63
- background: var(--persona-red) !important;
64
- transform: scaleX(0) !important;
65
- transform-origin: right !important;
66
- transition: transform 0.3s ease !important;
67
- }
68
-
69
- .main-navBar-navBarLink:hover::after {
70
- transform: scaleX(1) !important;
71
- transform-origin: left !important;
72
- }
73
-
74
- /* Content area styling */
75
- .main-view-container__scrollNode,
76
- .main-view-container__scrollNodeChild {
77
- background: rgba(34, 34, 34, 0.95) !important;
78
- backdrop-filter: blur(10px) !important;
79
- border: 1px solid var(--persona-red) !important;
80
- border-radius: 8px !important;
81
- margin: 16px !important;
82
- }
83
-
84
- /* Card styling */
85
- .main-card-card,
86
- .main-card-card:hover {
87
- background: linear-gradient(135deg, var(--persona-black) 0%, #444444 100%) !important;
88
- border: 2px solid var(--persona-red) !important;
89
- border-radius: 12px !important;
90
- box-shadow: 0 8px 25px rgba(212, 36, 38, 0.4) !important;
91
- transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
92
- }
93
-
94
- .main-card-card:hover {
95
- transform: translateY(-5px) !important;
96
- box-shadow: 0 12px 30px rgba(212, 36, 38, 0.6) !important;
97
- }
98
-
99
- /* Text and typography */
100
- h1, h2, h3, h4, h5, h6, .main-type-heading,
101
- .main-type-subheading, .main-type-balladBold {
102
- color: var(--persona-white) !important;
103
- text-shadow: 2px 2px 4px rgba(212, 36, 38, 0.7) !important;
104
- font-weight: bold !important;
105
- }
106
-
107
- .main-type-mesto, .main-type-finale {
108
- color: var(--persona-gold) !important;
109
- font-weight: bold !important;
110
- }
111
-
112
- /* Button styling */
113
- .main-button-button {
114
- background: var(--persona-red) !important;
115
- color: var(--persona-white) !important;
116
- border: 2px solid var(--persona-white) !important;
117
- border-radius: 6px !important;
118
- font-weight: bold !important;
119
- text-transform: uppercase !important;
120
- letter-spacing: 1px !important;
121
- transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
122
- }
123
-
124
- .main-button-button:hover {
125
- background: var(--persona-light-red) !important;
126
- transform: scale(1.05) !important;
127
- box-shadow: 0 0 15px rgba(212, 36, 38, 0.8) !important;
128
- }
129
-
130
- /* Player bar styling */
131
- .main-nowPlayingBar-container {
132
- background: linear-gradient(90deg, var(--persona-black) 0%, #333333 100%) !important;
133
- border-top: 3px solid var(--persona-red) !important;
134
- box-shadow: 0 -4px 15px rgba(212, 36, 38, 0.5) !important;
135
- }
136
-
137
- .main-nowPlayingBar-progressBar {
138
- background-color: var(--persona-red) !important;
139
- }
140
-
141
- /* Play button styling */
142
- .main-playButton-PlayButton {
143
- background-color: var(--persona-red) !important;
144
- border: 2px solid var(--persona-white) !important;
145
- }
146
-
147
- .main-playButton-PlayButton:hover {
148
- background-color: var(--persona-light-red) !important;
149
- transform: scale(1.1) !important;
150
- }
151
-
152
- /* Album art frame */
153
- .main-image-image {
154
- border: 3px solid var(--persona-red) !important;
155
- border-radius: 8px !important;
156
- box-shadow: 0 0 15px rgba(212, 36, 38, 0.7) !important;
157
- }
158
-
159
- /* Sidebar styling */
160
- .main-buddyFeed-container {
161
- background: rgba(34, 34, 34, 0.9) !important;
162
- border-left: 2px solid var(--persona-red) !important;
163
- }
164
-
165
- /* Persona 5 style diagonal elements */
166
- .main-topBar-container::before {
167
- content: '' !important;
168
- position: absolute !important;
169
- top: 0 !important;
170
- left: 0 !important;
171
- width: 100% !important;
172
- height: 120px !important;
173
- background: linear-gradient(45deg, transparent 50%, rgba(212, 36, 38, 0.2) 50%) !important;
174
- z-index: 0 !important;
175
- }
176
-
177
- /* Custom scrollbar */
178
- ::-webkit-scrollbar {
179
- width: 12px !important;
180
- }
181
-
182
- ::-webkit-scrollbar-track {
183
- background: var(--persona-black) !important;
184
- border: 1px solid var(--persona-red) !important;
185
- }
186
-
187
- ::-webkit-scrollbar-thumb {
188
- background: var(--persona-red) !important;
189
- border: 2px solid var(--persona-black) !important;
190
- border-radius: 6px !important;
191
- }
192
-
193
- /* Persona 5 style notification */
194
- .main-notificationNotification {
195
- background: linear-gradient(135deg, var(--persona-red) 0%, #FF5555 100%) !important;
196
- border: 2px solid var(--persona-white) !important;
197
- color: var(--persona-white) !important;
198
- box-shadow: 0 0 20px rgba(212, 36, 38, 0.8) !important;
199
- }
200
-
201
- /* Search input styling */
202
- .main-searchBox-input {
203
- background: rgba(51, 51, 51, 0.8) !important;
204
- border: 2px solid var(--persona-red) !important;
205
- color: var(--persona-white) !important;
206
- border-radius: 6px !important;
207
- }
208
-
209
- .main-searchBox-input:focus {
210
- box-shadow: 0 0 10px var(--persona-red) !important;
211
- }
212
-
213
- /* Persona 5 style typography */
214
- .main-type-mestoBold, .main-type-ballad {
215
- font-family: 'Arial', sans-serif !important;
216
- font-weight: bold !important;
217
- letter-spacing: 0.5px !important;
218
- }
219
-
220
- /* Loading animation */
221
- .main-loadingSpinner-loadingSpinner {
222
- border-top-color: var(--persona-red) !important;
223
- border-left-color: var(--persona-red) !important;
224
- }
225
-
226
- /* Context menu styling */
227
- .main-contextMenu-menu {
228
- background: linear-gradient(135deg, var(--persona-black) 0%, #444444 100%) !important;
229
- border: 2px solid var(--persona-red) !important;
230
- box-shadow: 0 8px 25px rgba(212, 36, 38, 0.6) !important;
231
- }
232
-
233
- .main-contextMenu-menuItemButton {
234
- color: var(--persona-white) !important;
235
- }
236
-
237
- .main-contextMenu-menuItemButton:hover {
238
- background: rgba(212, 36, 38, 0.2) !important;
239
- }
240
-
241
- /* Persona 5 style overlay effect */
242
- body::after {
243
- content: '' !important;
244
- position: fixed !important;
245
- top: 0 !important;
246
- left: 0 !important;
247
- width: 100% !important;
248
- height: 100% !important;
249
- background: radial-gradient(circle at 10% 20%, rgba(212, 36, 38, 0.1) 0%, transparent 20%) !important;
250
- pointer-events: none !important;
251
- z-index: 9999 !important;
252
- }
253
- `;
254
-
255
- // Add the CSS to the page
256
- GM_addStyle(persona5CSS);
257
-
258
- // Add Persona 5 style font loading
259
- const fontLink = document.createElement('link');
260
- fontLink.href = 'https://fonts.googleapis.com/css2?family=Orbitron:wght@700&display=swap';
261
- fontLink.rel = 'stylesheet';
262
- document.head.appendChild(fontLink);
263
-
264
- // Add custom font to key elements
265
- setTimeout(() => {
266
- const style = document.createElement('style');
267
- style.textContent = `
268
- .main-type-heading, .main-type-subheading, .main-navBar-navBarLink {
269
- font-family: 'Orbitron', sans-serif !important;
270
- }
271
- `;
272
- document.head.appendChild(style);
273
- }, 1000);
274
- })();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app.js ADDED
@@ -0,0 +1,540 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // ==UserScript==
2
+ // @name Dynamic UI/UX Enhancement Suite
3
+ // @namespace http://tampermonkey.net/
4
+ // @version 1.2.5
5
+ // @description Transforms website UI/UX with stylish animations, modern styling, and dynamic interactions
6
+ // @author UXMaster
7
+ // @match *://*/*
8
+ // @exclude *://*.google.com/*
9
+ // @exclude *://*.facebook.com/*
10
+ // @exclude *://*.youtube.com/*
11
+ // @grant GM_addStyle
12
+ // @grant GM_getValue
13
+ // @grant GM_setValue
14
+ // @grant GM_registerMenuCommand
15
+ // @run-at document-start
16
+ // @icon https://www.example.com/icon.png
17
+ // ==/UserScript==
18
+
19
+ (function() {
20
+ 'use strict';
21
+
22
+ // Configuration - customizable via ViolentMonkey UI
23
+ const config = {
24
+ animations: {
25
+ enabled: true,
26
+ duration: 0.3,
27
+ easing: 'cubic-bezier(0.16, 1, 0.3, 1)',
28
+ scrollSmooth: true,
29
+ hoverEffects: true,
30
+ fadeIns: true
31
+ },
32
+ styling: {
33
+ enabled: true,
34
+ modernShadows: true,
35
+ roundedCorners: true,
36
+ vibrantHoverStates: true,
37
+ readableText: true,
38
+ accentColor: '#6c63ff',
39
+ darkMode: false
40
+ },
41
+ performance: {
42
+ lazyLoadImages: true,
43
+ intersectionObserverThreshold: 0.1
44
+ }
45
+ };
46
+
47
+ // Initialize the enhancement suite
48
+ class DynamicUIEnhancer {
49
+ constructor() {
50
+ this.elements = new WeakMap();
51
+ this.animationFrame = null;
52
+ this.observer = null;
53
+ this.init();
54
+ }
55
+
56
+ init() {
57
+ // Wait for DOM to be interactive
58
+ if (document.readyState === 'loading') {
59
+ document.addEventListener('DOMContentLoaded', () => this.startEnhancement());
60
+ } else {
61
+ this.startEnhancement();
62
+ }
63
+
64
+ // Setup configuration menu in ViolentMonkey UI
65
+ this.setupConfigMenu();
66
+ }
67
+
68
+ setupConfigMenu() {
69
+ try {
70
+ GM_registerMenuCommand('Configure UI Enhancer', () => {
71
+ this.showConfigDialog();
72
+ });
73
+ } catch (e) {
74
+ console.warn('GM_registerMenuCommand not available, using console config');
75
+ }
76
+ }
77
+
78
+ startEnhancement() {
79
+ if (config.styling.enabled) this.applyModernStyling();
80
+ if (config.animations.enabled) this.setupAnimations();
81
+ this.setupPerformanceOptimizations();
82
+ this.setupDynamicInteractions();
83
+
84
+ // Handle dynamic content loading
85
+ this.setupMutationObserver();
86
+ }
87
+
88
+ applyModernStyling() {
89
+ const css = `
90
+ :root {
91
+ --accent-color: ${config.styling.accentColor};
92
+ --shadow-sm: 0 1px 3px rgba(0,0,0,0.08), 0 1px 2px rgba(0,0,0,0.05);
93
+ --shadow-md: 0 4px 6px rgba(0,0,0,0.1), 0 1px 3px rgba(0,0,0,0.08);
94
+ --shadow-lg: 0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -2px rgba(0,0,0,0.05);
95
+ --transition: all ${config.animations.duration}s ${config.animations.easing};
96
+ --radius-sm: 4px;
97
+ --radius-md: 8px;
98
+ --radius-lg: 12px;
99
+ --radius-full: 9999px;
100
+ }
101
+
102
+ * {
103
+ transition: background-color 0.2s ease, color 0.2s ease !important;
104
+ }
105
+
106
+ body {
107
+ ${config.styling.readableText ? `
108
+ line-height: 1.6;
109
+ color: ${config.styling.darkMode ? '#e0e0e0' : '#333'};
110
+ background: ${config.styling.darkMode ? '#1a1a1a' : '#fafafa'};
111
+ ` : ''}
112
+ }
113
+
114
+ button, .button, input[type="submit"], input[type="button"],
115
+ a.button, a.btn, .btn, .button-like {
116
+ ${config.styling.modernShadows ? 'box-shadow: var(--shadow-sm);' : ''}
117
+ ${config.styling.roundedCorners ? 'border-radius: var(--radius-md);' : ''}
118
+ background: var(--accent-color);
119
+ color: white;
120
+ border: none;
121
+ padding: 8px 16px;
122
+ cursor: pointer;
123
+ font-weight: 500;
124
+ transition: var(--transition) !important;
125
+ position: relative;
126
+ overflow: hidden;
127
+ }
128
+
129
+ button:hover, .button:hover, input[type="submit"]:hover,
130
+ input[type="button"]:hover, a.button:hover, a.btn:hover,
131
+ .btn:hover, .button-like:hover {
132
+ transform: translateY(-2px);
133
+ ${config.styling.modernShadows ? 'box-shadow: var(--shadow-md);' : ''}
134
+ ${config.styling.vibrantHoverStates ? `
135
+ background: linear-gradient(135deg, var(--accent-color), #4a44ff);
136
+ ` : ''}
137
+ }
138
+
139
+ button:active, .button:active {
140
+ transform: translateY(0);
141
+ }
142
+
143
+ button::after {
144
+ content: '';
145
+ position: absolute;
146
+ top: 0;
147
+ left: -100%;
148
+ width: 100%;
149
+ height: 100%;
150
+ background: rgba(255,255,255,0.2);
151
+ transition: left ${config.animations.duration}s ease;
152
+ }
153
+
154
+ button:hover::after {
155
+ left: 100%;
156
+ }
157
+
158
+ input[type="text"], input[type="email"], input[type="password"],
159
+ textarea, select {
160
+ ${config.styling.modernShadows ? 'box-shadow: var(--shadow-sm);' : ''}
161
+ ${config.styling.roundedCorners ? 'border-radius: var(--radius-sm);' : ''}
162
+ border: 1px solid #ddd;
163
+ padding: 8px 12px;
164
+ transition: var(--transition) !important;
165
+ }
166
+
167
+ input[type="text"]:focus, input[type="email"]:focus,
168
+ input[type="password"]:focus, textarea:focus, select:focus {
169
+ outline: none;
170
+ border-color: var(--accent-color);
171
+ ${config.styling.modernShadows ? 'box-shadow: 0 0 0 3px rgba(108, 99, 255, 0.2);' : ''}
172
+ }
173
+
174
+ .card, .panel, .box, .container {
175
+ ${config.styling.modernShadows ? 'box-shadow: var(--shadow-sm);' : ''}
176
+ ${config.styling.roundedCorners ? 'border-radius: var(--radius-md);' : ''}
177
+ background: ${config.styling.darkMode ? '#2d2d2d' : 'white'};
178
+ transition: var(--transition) !important;
179
+ }
180
+
181
+ .card:hover, .panel:hover {
182
+ ${config.styling.modernShadows ? 'box-shadow: var(--shadow-md);' : ''}
183
+ }
184
+
185
+ a {
186
+ color: var(--accent-color);
187
+ text-decoration: none;
188
+ transition: var(--transition) !important;
189
+ }
190
+
191
+ a:hover {
192
+ text-decoration: underline;
193
+ color: #4a44ff;
194
+ }
195
+
196
+ .fade-in {
197
+ opacity: 0;
198
+ transform: translateY(20px);
199
+ animation: fadeInUp ${config.animations.duration * 1.5}s ${config.animations.easing} forwards;
200
+ }
201
+
202
+ @keyframes fadeInUp {
203
+ to {
204
+ opacity: 1;
205
+ transform: translateY(0);
206
+ }
207
+ }
208
+ `;
209
+
210
+ GM_addStyle(css);
211
+ }
212
+
213
+ setupAnimations() {
214
+ if (config.animations.scrollSmooth) {
215
+ document.documentElement.style.scrollBehavior = 'smooth';
216
+ }
217
+
218
+ if (config.animations.fadeIns) {
219
+ this.setupFadeInAnimations();
220
+ }
221
+
222
+ if (config.animations.hoverEffects) {
223
+ this.setupHoverEffects();
224
+ }
225
+ }
226
+
227
+ setupFadeInAnimations() {
228
+ const animateElements = () => {
229
+ const elements = document.querySelectorAll(`
230
+ .card, .panel, .box, article, section, header, footer,
231
+ nav, .menu, .list-item, .grid-item, .product, .post,
232
+ .comment, .card-container, .widget, .feature, .testimonial
233
+ `);
234
+
235
+ elements.forEach(element => {
236
+ if (!this.elements.has(element)) {
237
+ this.elements.set(element, {
238
+ animated: false,
239
+ observer: null
240
+ });
241
+ }
242
+
243
+ const elementData = this.elements.get(element);
244
+ if (!elementData.animated) {
245
+ const rect = element.getBoundingClientRect();
246
+ if (rect.top < window.innerHeight * 1.2 && rect.bottom > -rect.height * 0.2) {
247
+ element.classList.add('fade-in');
248
+ elementData.animated = true;
249
+ }
250
+ }
251
+ });
252
+ };
253
+
254
+ // Initial animation
255
+ animateElements();
256
+
257
+ // Animation on scroll
258
+ window.addEventListener('scroll', () => {
259
+ if (this.animationFrame) return;
260
+ this.animationFrame = requestAnimationFrame(() => {
261
+ animateElements();
262
+ this.animationFrame = null;
263
+ });
264
+ });
265
+
266
+ // Recheck on window resize
267
+ window.addEventListener('resize', animateElements);
268
+ }
269
+
270
+ setupHoverEffects() {
271
+ document.addEventListener('mouseover', (e) => {
272
+ const target = e.target;
273
+ if (target.matches('button, .button, a.button, .btn, .card, .panel, .box, .menu-item, .nav-link')) {
274
+ target.style.transform = 'translateY(-2px)';
275
+ }
276
+ }, true);
277
+
278
+ document.addEventListener('mouseout', (e) => {
279
+ const target = e.target;
280
+ if (target.matches('button, .button, a.button, .btn, .card, .panel, .box, .menu-item, .nav-link')) {
281
+ target.style.transform = 'translateY(0)';
282
+ }
283
+ }, true);
284
+ }
285
+
286
+ setupPerformanceOptimizations() {
287
+ if (config.performance.lazyLoadImages) {
288
+ this.setupLazyLoading();
289
+ }
290
+ }
291
+
292
+ setupLazyLoading() {
293
+ const lazyImages = document.querySelectorAll('img[data-src], img.lazy');
294
+ if (lazyImages.length === 0) return;
295
+
296
+ const lazyLoad = (entries, observer) => {
297
+ entries.forEach(entry => {
298
+ if (entry.isIntersecting) {
299
+ const img = entry.target;
300
+ const src = img.dataset.src || img.src;
301
+ img.src = src;
302
+ img.classList.remove('lazy');
303
+ img.removeAttribute('data-src');
304
+ observer.unobserve(img);
305
+ }
306
+ });
307
+ };
308
+
309
+ this.observer = new IntersectionObserver(lazyLoad, {
310
+ rootMargin: '50px 0px',
311
+ threshold: config.performance.intersectionObserverThreshold
312
+ });
313
+
314
+ lazyImages.forEach(img => {
315
+ this.observer.observe(img);
316
+ });
317
+ }
318
+
319
+ setupDynamicInteractions() {
320
+ // Micro-interactions for buttons and inputs
321
+ document.addEventListener('click', (e) => {
322
+ const target = e.target;
323
+ if (target.matches('button, .button, a.button, .btn')) {
324
+ this.createRippleEffect(target, e);
325
+ }
326
+ }, true);
327
+
328
+ // Form interactions
329
+ document.addEventListener('focusin', (e) => {
330
+ const target = e.target;
331
+ if (target.matches('input, textarea, select')) {
332
+ target.parentElement?.classList?.add('focused');
333
+ }
334
+ });
335
+
336
+ document.addEventListener('focusout', (e) => {
337
+ const target = e.target;
338
+ if (target.matches('input, textarea, select')) {
339
+ target.parentElement?.classList?.remove('focused');
340
+ }
341
+ });
342
+ }
343
+
344
+ createRippleEffect(element, event) {
345
+ const rect = element.getBoundingClientRect();
346
+ const size = Math.max(rect.width, rect.height);
347
+ const x = event.clientX - rect.left - size / 2;
348
+ const y = event.clientY - rect.top - size / 2;
349
+
350
+ const ripple = document.createElement('span');
351
+ ripple.style.cssText = `
352
+ position: absolute;
353
+ width: ${size}px;
354
+ height: ${size}px;
355
+ left: ${x}px;
356
+ top: ${y}px;
357
+ border-radius: 50%;
358
+ background: rgba(255,255,255,0.3);
359
+ transform: scale(0);
360
+ animation: ripple ${config.animations.duration}s ease-out forwards;
361
+ pointer-events: none;
362
+ z-index: 1;
363
+ `;
364
+
365
+ element.style.overflow = 'hidden';
366
+ element.style.position = 'relative';
367
+ element.appendChild(ripple);
368
+
369
+ setTimeout(() => {
370
+ ripple.remove();
371
+ }, config.animations.duration * 1000 + 100);
372
+ }
373
+
374
+ setupMutationObserver() {
375
+ const observer = new MutationObserver((mutations) => {
376
+ mutations.forEach(mutation => {
377
+ if (mutation.type === 'childList') {
378
+ mutation.addedNodes.forEach(node => {
379
+ if (node.nodeType === 1) { // Element node
380
+ this.enhanceNewElements(node);
381
+ }
382
+ });
383
+ }
384
+ });
385
+ });
386
+
387
+ observer.observe(document.body, {
388
+ childList: true,
389
+ subtree: true
390
+ });
391
+ }
392
+
393
+ enhanceNewElements(element) {
394
+ // Apply styling to new elements
395
+ if (element.querySelectorAll) {
396
+ const buttons = element.querySelectorAll('button, .button, .btn');
397
+ buttons.forEach(btn => {
398
+ if (!btn.dataset.enhanced) {
399
+ btn.dataset.enhanced = 'true';
400
+ // Add hover effects
401
+ btn.addEventListener('mouseenter', () => {
402
+ btn.style.transform = 'translateY(-2px)';
403
+ });
404
+ btn.addEventListener('mouseleave', () => {
405
+ btn.style.transform = 'translateY(0)';
406
+ });
407
+ }
408
+ });
409
+
410
+ // Apply fade-in to new cards/containers
411
+ const containers = element.querySelectorAll('.card, .panel, .box');
412
+ containers.forEach(container => {
413
+ if (!container.dataset.enhanced) {
414
+ container.dataset.enhanced = 'true';
415
+ container.classList.add('fade-in');
416
+ }
417
+ });
418
+ }
419
+ }
420
+
421
+ showConfigDialog() {
422
+ const dialog = document.createElement('div');
423
+ dialog.style.cssText = `
424
+ position: fixed;
425
+ top: 50%;
426
+ left: 50%;
427
+ transform: translate(-50%, -50%);
428
+ background: white;
429
+ border-radius: 12px;
430
+ box-shadow: 0 20px 25px -5px rgba(0,0,0,0.1), 0 10px 10px -5px rgba(0,0,0,0.04);
431
+ z-index: 99999;
432
+ padding: 24px;
433
+ max-width: 500px;
434
+ width: 90%;
435
+ max-height: 80vh;
436
+ overflow-y: auto;
437
+ `;
438
+
439
+ dialog.innerHTML = `
440
+ <h2 style="margin-top: 0; color: #333;">UI/UX Enhancement Settings</h2>
441
+ <div style="margin-bottom: 20px;">
442
+ <label style="display: block; margin-bottom: 8px;">
443
+ <input type="checkbox" id="animations-enabled" ${config.animations.enabled ? 'checked' : ''}>
444
+ Enable Animations
445
+ </label>
446
+ <label style="display: block; margin-bottom: 8px;">
447
+ <input type="checkbox" id="styling-enabled" ${config.styling.enabled ? 'checked' : ''}>
448
+ Enable Modern Styling
449
+ </label>
450
+ <label style="display: block; margin-bottom: 8px;">
451
+ <input type="color" id="accent-color" value="${config.styling.accentColor}" style="width: 50px; vertical-align: middle;">
452
+ Accent Color
453
+ </label>
454
+ </div>
455
+ <button id="save-config" style="background: #6c63ff; color: white; border: none; padding: 8px 16px; border-radius: 6px; cursor: pointer;">
456
+ Save & Apply
457
+ </button>
458
+ <button id="reset-config" style="background: #e5e7eb; color: #333; border: none; padding: 8px 16px; border-radius: 6px; margin-left: 8px; cursor: pointer;">
459
+ Reset to Defaults
460
+ </button>
461
+ `;
462
+
463
+ document.body.appendChild(dialog);
464
+
465
+ document.getElementById('save-config').addEventListener('click', () => {
466
+ config.animations.enabled = document.getElementById('animations-enabled').checked;
467
+ config.styling.enabled = document.getElementById('styling-enabled').checked;
468
+ config.styling.accentColor = document.getElementById('accent-color').value;
469
+
470
+ // Reinitialize with new config
471
+ this.reinitialize();
472
+ dialog.remove();
473
+ });
474
+
475
+ document.getElementById('reset-config').addEventListener('click', () => {
476
+ // Reset to defaults
477
+ Object.assign(config, {
478
+ animations: { enabled: true, duration: 0.3, easing: 'cubic-bezier(0.16, 1, 0.3, 1)', scrollSmooth: true, hoverEffects: true, fadeIns: true },
479
+ styling: { enabled: true, modernShadows: true, roundedCorners: true, vibrantHoverStates: true, readableText: true, accentColor: '#6c63ff', darkMode: false }
480
+ });
481
+ this.reinitialize();
482
+ dialog.remove();
483
+ });
484
+
485
+ // Close dialog on outside click
486
+ dialog.addEventListener('click', (e) => {
487
+ if (e.target === dialog) {
488
+ dialog.remove();
489
+ }
490
+ });
491
+ }
492
+
493
+ reinitialize() {
494
+ // Clear existing styles and reapply
495
+ const existingStyles = document.querySelectorAll('style[data-enhancer]');
496
+ existingStyles.forEach(style => style.remove());
497
+
498
+ // Reapply styling
499
+ this.applyModernStyling();
500
+
501
+ // Reapply animations to visible elements
502
+ if (config.animations.enabled) {
503
+ this.setupAnimations();
504
+ }
505
+
506
+ // Show notification
507
+ this.showNotification('Settings applied successfully!');
508
+ }
509
+
510
+ showNotification(message) {
511
+ const notification = document.createElement('div');
512
+ notification.style.cssText = `
513
+ position: fixed;
514
+ bottom: 20px;
515
+ right: 20px;
516
+ background: #4CAF50;
517
+ color: white;
518
+ padding: 12px 24px;
519
+ border-radius: 8px;
520
+ box-shadow: 0 4px 6px rgba(0,0,0,0.1);
521
+ z-index: 99999;
522
+ animation: slideIn 0.3s ease, fadeOut 0.5s ease 2.5s forwards;
523
+ `;
524
+ notification.innerHTML = `<strong>✓</strong> ${message}`;
525
+ document.body.appendChild(notification);
526
+
527
+ setTimeout(() => {
528
+ notification.remove();
529
+ }, 3000);
530
+ }
531
+ }
532
+
533
+ // Initialize the enhancer
534
+ const uiEnhancer = new DynamicUIEnhancer();
535
+
536
+ // Expose for debugging and external access
537
+ window.UIEnhancer = uiEnhancer;
538
+ console.log('Dynamic UI/UX Enhancement Suite loaded successfully!');
539
+
540
+ })();