class-studys 2.0.0 → 4.0.0
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.
- package/index.html +533 -214
- package/package.json +1 -1
package/index.html
CHANGED
|
@@ -5,19 +5,226 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<title>IGNITE OS — the unblocked dashboard</title>
|
|
7
7
|
<meta name="description" content="IGNITE OS: games, movies from Drive and a real web tunnel. Dark, orange, clean.">
|
|
8
|
+
<meta property="og:title" content="IGNITE OS — the unblocked dashboard">
|
|
9
|
+
<meta property="og:description" content="IGNITE OS: games, movies from Drive and a real web tunnel. Dark, orange, clean.">
|
|
10
|
+
<meta property="og:type" content="website">
|
|
11
|
+
<meta name="twitter:card" content="summary_large_image">
|
|
8
12
|
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Crect width='64' height='64' rx='14' fill='%230d0906'/%3E%3Ccircle cx='32' cy='32' r='17' fill='%23ff6b1a'/%3E%3Ccircle cx='26' cy='26' r='5' fill='%230d0906'/%3E%3C/svg%3E">
|
|
9
13
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
10
14
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
11
15
|
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700;800;900&family=Space+Grotesk:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;600&display=swap" rel="stylesheet">
|
|
12
|
-
<
|
|
16
|
+
<style id="main-styles">
|
|
17
|
+
/* Enhanced security protection styles */
|
|
18
|
+
body {
|
|
19
|
+
-webkit-user-select: none !important;
|
|
20
|
+
-moz-user-select: none !important;
|
|
21
|
+
user-select: none !important;
|
|
22
|
+
-webkit-touch-callout: none !important;
|
|
23
|
+
-webkit-tap-highlight-color: transparent !important;
|
|
24
|
+
position: relative;
|
|
25
|
+
}
|
|
13
26
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
27
|
+
/* Anti-inspection overlay */
|
|
28
|
+
body::before {
|
|
29
|
+
content: '';
|
|
30
|
+
position: fixed;
|
|
31
|
+
top: 0; left: 0; right: 0; bottom: 0;
|
|
32
|
+
background: transparent;
|
|
33
|
+
z-index: 9999;
|
|
34
|
+
pointer-events: none;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/* Make text selection impossible */
|
|
38
|
+
* {
|
|
39
|
+
-webkit-user-select: none !important;
|
|
40
|
+
-moz-user-select: none !important;
|
|
41
|
+
-ms-user-select: none !important;
|
|
42
|
+
user-select: none !important;
|
|
43
|
+
-webkit-touch-callout: none !important;
|
|
44
|
+
-webkit-tap-highlight-color: transparent !important;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/* Allow selection only for inputs */
|
|
48
|
+
input, textarea, [contenteditable] {
|
|
49
|
+
-webkit-user-select: text !important;
|
|
50
|
+
-moz-user-select: text !important;
|
|
51
|
+
user-select: text !important;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/* Hide scroll bars to prevent inspection */
|
|
55
|
+
::-webkit-scrollbar { display: none; }
|
|
56
|
+
html { -ms-overflow-style: none; scrollbar-width: none; }
|
|
57
|
+
|
|
58
|
+
/* Disable text cursor */
|
|
59
|
+
* { cursor: default !important; }
|
|
60
|
+
a, button { cursor: pointer !important; }
|
|
61
|
+
input, textarea { cursor: text !important; }
|
|
62
|
+
|
|
63
|
+
/* Security warning overlay for dev tools */
|
|
64
|
+
#security-warning {
|
|
65
|
+
position: fixed;
|
|
66
|
+
top: 0; left: 0; right: 0; bottom: 0;
|
|
67
|
+
background: rgba(0,0,0,0.95);
|
|
68
|
+
color: #ff4444;
|
|
69
|
+
display: none;
|
|
70
|
+
align-items: center;
|
|
71
|
+
justify-content: center;
|
|
72
|
+
z-index: 99999;
|
|
73
|
+
font-family: monospace;
|
|
74
|
+
font-size: 24px;
|
|
75
|
+
text-align: center;
|
|
76
|
+
}
|
|
77
|
+
/* IGNITE OS styles — dark orange engine */
|
|
78
|
+
:root {
|
|
79
|
+
--bg0: #0a0705; --bg1: #140d08; --bg2: #1c130c;
|
|
80
|
+
--panel: rgba(20, 13, 9, 0.55);
|
|
81
|
+
--panel-solid: #151009;
|
|
82
|
+
--panel-2: rgba(28, 19, 13, 0.85);
|
|
83
|
+
--line: rgba(255, 255, 255, 0.08);
|
|
84
|
+
--line-2: rgba(255, 255, 255, 0.16);
|
|
85
|
+
--text: #f4eee6; --muted: #a29588; --dim: #6f635a;
|
|
86
|
+
--accent: #ff6b1a; --accent2: #ffb26b;
|
|
87
|
+
--on-accent: #140600;
|
|
88
|
+
--glow: 0.7; --blur: 14px; --radius: 18px; --saturate: 1;
|
|
89
|
+
--font: 'Outfit', 'Segoe UI', system-ui, sans-serif;
|
|
90
|
+
--hero-size: clamp(2.6rem, 6.4vw, 5rem);
|
|
91
|
+
--ease: cubic-bezier(.22, .8, .3, 1);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
95
|
+
html { scroll-behavior: smooth; }
|
|
96
|
+
|
|
97
|
+
body {
|
|
98
|
+
background: var(--bg0); color: var(--text);
|
|
99
|
+
font-family: var(--font); font-weight: 400;
|
|
100
|
+
min-height: 100vh; overflow-x: hidden; line-height: 1.55;
|
|
101
|
+
}
|
|
102
|
+
body[data-font='grotesk'] { --font: 'Space Grotesk', 'Outfit', sans-serif; }
|
|
103
|
+
body[data-font='mono'] { --font: 'JetBrains Mono', 'Consolas', monospace; }
|
|
104
|
+
body[data-font='system'] { --font: 'Segoe UI', system-ui, sans-serif; }
|
|
105
|
+
|
|
106
|
+
::selection { background: var(--accent); color: var(--on-accent); }
|
|
107
|
+
::-webkit-scrollbar { width: 11px; height: 11px; }
|
|
108
|
+
::-webkit-scrollbar-track { background: #0b0706; }
|
|
109
|
+
::-webkit-scrollbar-thumb {
|
|
110
|
+
background: linear-gradient(var(--accent), var(--accent2));
|
|
111
|
+
border-radius: 9px; border: 3px solid #0b0706;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
a { color: inherit; text-decoration: none; }
|
|
115
|
+
button { font-family: inherit; cursor: pointer; }
|
|
116
|
+
input, select { font-family: inherit; color: inherit; }
|
|
117
|
+
.hidden { display: none !important; }
|
|
118
|
+
|
|
119
|
+
code, kbd {
|
|
120
|
+
font-family: 'JetBrains Mono', monospace;
|
|
121
|
+
background: rgba(255, 255, 255, 0.07);
|
|
122
|
+
border: 1px solid var(--line); padding: 1px 6px;
|
|
123
|
+
border-radius: 6px; font-size: 0.85em; color: var(--accent2);
|
|
124
|
+
}
|
|
125
|
+
/* Background engine styles */
|
|
126
|
+
.bg-wrap {
|
|
127
|
+
position: fixed; inset: 0; z-index: -2;
|
|
128
|
+
background:
|
|
129
|
+
radial-gradient(1200px 600px at 80% -10%, color-mix(in srgb, var(--accent) 14%, transparent), transparent 60%),
|
|
130
|
+
radial-gradient(900px 500px at 10% 110%, color-mix(in srgb, var(--accent2) 10%, transparent), transparent 60%),
|
|
131
|
+
linear-gradient(180deg, var(--bg1), var(--bg0) 60%, var(--bg0));
|
|
132
|
+
filter: saturate(var(--saturate));
|
|
133
|
+
transition: background 0.8s var(--ease);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.blob {
|
|
137
|
+
position: absolute; border-radius: 50%;
|
|
138
|
+
filter: blur(95px); opacity: calc(var(--glow) * 0.85);
|
|
139
|
+
mix-blend-mode: screen; pointer-events: none;
|
|
140
|
+
animation: drift 26s ease-in-out infinite alternate;
|
|
141
|
+
will-change: transform;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
@keyframes drift {
|
|
145
|
+
0% { transform: translate3d(0, 0, 0) scale(1); }
|
|
146
|
+
50% { transform: translate3d(6vw, -5vh, 0) scale(1.18); }
|
|
147
|
+
100% { transform: translate3d(-5vw, 4vh, 0) scale(0.94); }
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/* Navigation styles */
|
|
151
|
+
.nav {
|
|
152
|
+
position: sticky; top: 0; z-index: 90;
|
|
153
|
+
background: rgba(10, 7, 5, 0.62);
|
|
154
|
+
backdrop-filter: blur(calc(var(--blur) * 1.4)) saturate(1.4);
|
|
155
|
+
border-bottom: 1px solid var(--line);
|
|
156
|
+
}
|
|
157
|
+
.nav-inner {
|
|
158
|
+
max-width: 1220px; margin: 0 auto; padding: 14px 22px;
|
|
159
|
+
display: flex; align-items: center; gap: 18px;
|
|
160
|
+
}
|
|
161
|
+
.brand { display: flex; align-items: center; gap: 10px; }
|
|
162
|
+
.brand-mark {
|
|
163
|
+
width: 34px; height: 34px; border-radius: 10px;
|
|
164
|
+
display: grid; place-items: center;
|
|
165
|
+
background: linear-gradient(135deg, var(--accent), var(--accent2));
|
|
166
|
+
color: var(--on-accent); font-size: 15px;
|
|
167
|
+
box-shadow: 0 0 22px color-mix(in srgb, var(--accent) 55%, transparent);
|
|
168
|
+
}
|
|
169
|
+
/* Component styles - panels, buttons, etc */
|
|
170
|
+
.panel {
|
|
171
|
+
background: var(--panel);
|
|
172
|
+
border: 1px solid var(--line);
|
|
173
|
+
border-radius: calc(var(--radius) + 4px);
|
|
174
|
+
padding: 26px;
|
|
175
|
+
backdrop-filter: blur(var(--blur)) saturate(1.3);
|
|
176
|
+
box-shadow: 0 18px 60px rgba(0, 0, 0, 0.35);
|
|
177
|
+
transition: border-color 0.3s var(--ease), transform 0.3s var(--ease);
|
|
178
|
+
scroll-margin-top: 90px;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.btn {
|
|
182
|
+
border: none; border-radius: 12px; padding: 11px 20px;
|
|
183
|
+
font-weight: 700; font-size: 0.92rem; letter-spacing: 0.2px;
|
|
184
|
+
transition: 0.22s var(--ease);
|
|
185
|
+
}
|
|
186
|
+
.btn-accent {
|
|
187
|
+
background: linear-gradient(135deg, var(--accent), var(--accent2));
|
|
188
|
+
color: var(--on-accent);
|
|
189
|
+
box-shadow: 0 6px 24px color-mix(in srgb, var(--accent) 40%, transparent);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.game-grid {
|
|
193
|
+
display: grid; gap: 16px;
|
|
194
|
+
grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
|
|
195
|
+
}
|
|
196
|
+
.game-card {
|
|
197
|
+
position: relative; border-radius: var(--radius); overflow: hidden;
|
|
198
|
+
background: var(--panel-2); border: 1px solid var(--line);
|
|
199
|
+
transition: 0.3s var(--ease); cursor: pointer;
|
|
200
|
+
}
|
|
201
|
+
.game-card:hover {
|
|
202
|
+
transform: translateY(-5px); border-color: var(--accent);
|
|
203
|
+
box-shadow: 0 16px 44px rgba(0, 0, 0, 0.5), 0 0 30px color-mix(in srgb, var(--accent) 18%, transparent);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/* Modal styles */
|
|
207
|
+
.modal {
|
|
208
|
+
position: fixed; inset: 0; z-index: 150;
|
|
209
|
+
background: rgba(5, 3, 2, 0.82);
|
|
210
|
+
backdrop-filter: blur(14px);
|
|
211
|
+
display: grid; place-items: center;
|
|
212
|
+
animation: fadeIn 0.25s var(--ease);
|
|
213
|
+
}
|
|
214
|
+
</style>
|
|
17
215
|
</head>
|
|
18
216
|
<body data-bg="aurora">
|
|
19
217
|
|
|
20
|
-
<!--
|
|
218
|
+
<!-- Security warning overlay -->
|
|
219
|
+
<div id="security-warning">
|
|
220
|
+
<div>
|
|
221
|
+
<h2>⚠️ UNAUTHORIZED ACCESS DETECTED ⚠️</h2>
|
|
222
|
+
<p>Developer tools usage is not permitted.</p>
|
|
223
|
+
<p>This activity has been logged.</p>
|
|
224
|
+
</div>
|
|
225
|
+
</div>
|
|
226
|
+
|
|
227
|
+
<!-- Background layers -->
|
|
21
228
|
<div class="bg-wrap" aria-hidden="true">
|
|
22
229
|
<canvas id="bg-canvas"></canvas>
|
|
23
230
|
<div class="blob blob-a"></div>
|
|
@@ -27,7 +234,7 @@
|
|
|
27
234
|
<div class="bg-noise"></div>
|
|
28
235
|
</div>
|
|
29
236
|
|
|
30
|
-
<!--
|
|
237
|
+
<!-- Boot splash -->
|
|
31
238
|
<div id="boot" class="boot">
|
|
32
239
|
<div class="boot-inner">
|
|
33
240
|
<div class="boot-logo">▲</div>
|
|
@@ -38,7 +245,7 @@
|
|
|
38
245
|
</div>
|
|
39
246
|
</div>
|
|
40
247
|
|
|
41
|
-
<!--
|
|
248
|
+
<!-- Navigation -->
|
|
42
249
|
<header class="nav" id="nav">
|
|
43
250
|
<div class="nav-inner">
|
|
44
251
|
<a class="brand" href="#top">
|
|
@@ -49,244 +256,356 @@
|
|
|
49
256
|
<nav class="nav-links" id="nav-links">
|
|
50
257
|
<a href="#games" class="nav-link">Games</a>
|
|
51
258
|
<a href="#movies" class="nav-link">Movies</a>
|
|
52
|
-
<button class="nav-link btn-link" id="nav-work" type="button"
|
|
259
|
+
<button class="nav-link btn-link" id="nav-work" type="button">Work</button>
|
|
53
260
|
<button class="nav-link btn-link" id="nav-customize" type="button">Customize</button>
|
|
54
261
|
</nav>
|
|
55
262
|
<div class="nav-side">
|
|
56
263
|
<span class="nav-clock" id="nav-clock">--:--</span>
|
|
57
|
-
<span class="profile-pill" id="profile-pill"
|
|
264
|
+
<span class="profile-pill" id="profile-pill">DRIVER</span>
|
|
58
265
|
</div>
|
|
59
266
|
</div>
|
|
60
267
|
</header>
|
|
61
268
|
|
|
62
269
|
<main id="top">
|
|
63
|
-
<!--
|
|
64
|
-
<!-- work mode view -->
|
|
65
|
-
<section class="panel hidden" id="work-view">
|
|
66
|
-
<div class="panel-head">
|
|
67
|
-
<div><h3 class="panel-title">📖 Study Focus</h3>
|
|
68
|
-
<p class="panel-sub">Focus timer + task list. Work Mode hides the rest of the vault — press <kbd>H</kbd> to switch.</p></div>
|
|
69
|
-
<div class="focus-timer" id="focus-timer">25:00</div>
|
|
70
|
-
</div>
|
|
71
|
-
<div class="work-grid">
|
|
72
|
-
<div class="work-card">
|
|
73
|
-
<h4>Focus timer</h4>
|
|
74
|
-
<div class="timer-controls">
|
|
75
|
-
<button class="btn ghost btn-sm" id="timer-start" type="button">▶ start</button>
|
|
76
|
-
<button class="btn ghost btn-sm" id="timer-pause" type="button">⏸ pause</button>
|
|
77
|
-
<button class="btn ghost btn-sm" id="timer-reset" type="button">⟳ reset</button>
|
|
78
|
-
</div>
|
|
79
|
-
<select id="timer-length" class="select-mini">
|
|
80
|
-
<option value="1500">25:00 pomodoro</option>
|
|
81
|
-
<option value="600">10:00</option>
|
|
82
|
-
<option value="1800">30:00</option>
|
|
83
|
-
<option value="3600">60:00</option>
|
|
84
|
-
</select>
|
|
85
|
-
</div>
|
|
86
|
-
<div class="work-card">
|
|
87
|
-
<h4>Task list</h4>
|
|
88
|
-
<form class="tunnel-form" id="todo-form">
|
|
89
|
-
<input id="todo-input" class="tunnel-input" type="text" placeholder="add a task…" maxlength="90">
|
|
90
|
-
<button class="btn btn-accent btn-sm" type="submit">+</button>
|
|
91
|
-
</form>
|
|
92
|
-
<ul class="todo-list" id="todo-list"></ul>
|
|
93
|
-
<p class="cz-note">saved in your browser</p>
|
|
94
|
-
</div>
|
|
95
|
-
</div>
|
|
96
|
-
</section>
|
|
97
|
-
<section class="hero">
|
|
98
|
-
<div class="hero-eyebrow"><span class="pulse-dot"></span> systems online</div>
|
|
99
|
-
<h2 class="hero-title">Everything, <span class="accent-text gradient-text">unlocked.</span></h2>
|
|
100
|
-
<p class="hero-sub">IGNITE OS is a dashboard for browser games and movies streamed straight from your Google Drive.</p>
|
|
101
|
-
<div class="stat-strip" id="stat-strip">
|
|
102
|
-
<div class="stat"><b id="stat-games">0</b><span>games</span></div>
|
|
103
|
-
<div class="stat"><b id="stat-movies">0</b><span>movies</span></div>
|
|
104
|
-
<div class="stat"><b id="stat-local">0</b><span>local</span></div>
|
|
105
|
-
<div class="stat"><b id="stat-last">—</b><span>last launch</span></div>
|
|
106
|
-
</div>
|
|
107
|
-
</section>
|
|
108
|
-
|
|
109
|
-
<!-- games -->
|
|
270
|
+
<!-- Games section -->
|
|
110
271
|
<section class="panel" id="games">
|
|
111
272
|
<div class="panel-head">
|
|
112
|
-
<div
|
|
113
|
-
|
|
273
|
+
<div>
|
|
274
|
+
<h3 class="panel-title">🎮 Game Vault</h3>
|
|
275
|
+
<p class="panel-sub">Play proxied web games.</p>
|
|
276
|
+
</div>
|
|
114
277
|
<span class="badge" id="games-edit-badge">+ new</span>
|
|
115
278
|
</div>
|
|
116
|
-
<div id="local-hint" class="local-hint hidden">
|
|
117
|
-
📁 no local games yet — drop any HTML5 game folder into <code>public/local-games/</code> and hit refresh. They run fully offline.
|
|
118
|
-
</div>
|
|
119
279
|
<div class="game-grid" id="game-grid"></div>
|
|
120
280
|
</section>
|
|
121
|
-
|
|
122
|
-
<!-- movies -->
|
|
123
|
-
<section class="panel" id="movies">
|
|
124
|
-
<div class="panel-head">
|
|
125
|
-
<div><h3 class="panel-title">🍿 Movies · from your Drive</h3>
|
|
126
|
-
<p class="panel-sub">Paste any Google Drive share link (file <em>or</em> folder) — IGNITE OS streams it in a full player.</p></div>
|
|
127
|
-
<span class="badge" id="movies-add">+ movie</span>
|
|
128
|
-
</div>
|
|
129
|
-
<div class="movie-toolbar">
|
|
130
|
-
<input id="movie-search" class="search-input" type="text" placeholder="search movies…">
|
|
131
|
-
<div class="genre-chips" id="genre-chips"></div>
|
|
132
|
-
<select id="movie-sort" class="select-mini">
|
|
133
|
-
<option value="added">newest first</option>
|
|
134
|
-
<option value="title">title A→Z</option>
|
|
135
|
-
<option value="watched">unwatched first</option>
|
|
136
|
-
</select>
|
|
137
|
-
</div>
|
|
138
|
-
<div class="movie-grid" id="movie-grid"></div>
|
|
139
|
-
<div class="empty-state hidden" id="movies-empty">
|
|
140
|
-
<div class="empty-art">🍻</div>
|
|
141
|
-
<h4>Your library is empty</h4>
|
|
142
|
-
<p>Hit <b>+ movie</b> and paste a Google Drive link, or load the demo shelf to see the player in action.</p>
|
|
143
|
-
<button class="btn ghost" id="demo-movies">load demo shelf</button>
|
|
144
|
-
</div>
|
|
145
|
-
</section>
|
|
146
|
-
|
|
147
|
-
<!-- continue watching -->
|
|
148
|
-
<section class="panel hidden" id="continue-panel">
|
|
149
|
-
<div class="panel-head"><div><h3 class="panel-title">▶ Continue watching</h3></div></div>
|
|
150
|
-
<div class="movie-grid" id="continue-grid"></div>
|
|
151
|
-
</section>
|
|
152
|
-
|
|
153
281
|
</main>
|
|
154
282
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
<span id="foot-clock"></span>
|
|
158
|
-
<span class="foot-hint"><kbd>/</kbd> search movies <kbd>G</kbd> games <kbd>M</kbd> movies <kbd>C</kbd> customize</span>
|
|
159
|
-
</footer>
|
|
160
|
-
<!-- customizer -->
|
|
161
|
-
<aside class="customizer" id="customizer" aria-label="Customizer">
|
|
162
|
-
<div class="customizer-head">
|
|
163
|
-
<h4>Customizer</h4>
|
|
164
|
-
<button class="icon-btn" id="cz-close" title="close">✕</button>
|
|
165
|
-
</div>
|
|
166
|
-
<div class="cz-scroll">
|
|
167
|
-
<label class="cz-label">theme preset</label>
|
|
168
|
-
<div class="swatches" id="cz-swatches">
|
|
169
|
-
<button class="swatch" data-preset="ember" style="--sw:#ff6b1a" title="Ember"></button>
|
|
170
|
-
<button class="swatch" data-preset="cobalt" style="--sw:#3b82f6" title="Cobalt"></button>
|
|
171
|
-
<button class="swatch" data-preset="violet" style="--sw:#a855f7" title="Violet"></button>
|
|
172
|
-
<button class="swatch" data-preset="inferno" style="--sw:#ff3d3d" title="Inferno"></button>
|
|
173
|
-
<button class="swatch" data-preset="ocean" style="--sw:#22d3ee" title="Ocean"></button>
|
|
174
|
-
<button class="swatch" data-preset="mint" style="--sw:#34d399" title="Mint"></button>
|
|
175
|
-
</div>
|
|
176
|
-
<label class="cz-label" for="cz-accent">accent color</label>
|
|
177
|
-
<div class="cz-row">
|
|
178
|
-
<input type="color" id="cz-accent" value="#ff6b1a">
|
|
179
|
-
<span class="cz-hex" id="cz-accent-hex">#ff6b1a</span>
|
|
180
|
-
</div>
|
|
181
|
-
<label class="cz-label" for="cz-accent2">secondary accent</label>
|
|
182
|
-
<div class="cz-row">
|
|
183
|
-
<input type="color" id="cz-accent2" value="#ffb26b">
|
|
184
|
-
<span class="cz-hex" id="cz-accent2-hex">#ffb26b</span>
|
|
185
|
-
</div>
|
|
186
|
-
<label class="cz-label" for="cz-bgtype">background</label>
|
|
187
|
-
<select id="cz-bgtype" class="select-mini">
|
|
188
|
-
<option value="aurora">aurora · animated</option>
|
|
189
|
-
<option value="grid">glow grid</option>
|
|
190
|
-
<option value="stars">night sky</option>
|
|
191
|
-
<option value="mesh">static mesh</option>
|
|
192
|
-
<option value="custom">custom image</option>
|
|
193
|
-
</select>
|
|
194
|
-
<div class="cz-row hidden" id="cz-bgurl-row">
|
|
195
|
-
<input id="cz-bgurl" class="search-input" type="text" placeholder="https://… background image URL">
|
|
196
|
-
</div>
|
|
197
|
-
<label class="cz-label" for="cz-bg-hue">background hue</label>
|
|
198
|
-
<input type="range" id="cz-bg-hue" min="0" max="360" value="28">
|
|
199
|
-
<label class="cz-label" for="cz-glow">glow intensity</label>
|
|
200
|
-
<input type="range" id="cz-glow" min="0" max="100" value="70">
|
|
201
|
-
<label class="cz-label" for="cz-blur">card blur</label>
|
|
202
|
-
<input type="range" id="cz-blur" min="0" max="30" value="14">
|
|
203
|
-
<label class="cz-label" for="cz-radius">card radius</label>
|
|
204
|
-
<input type="range" id="cz-radius" min="4" max="32" value="18">
|
|
205
|
-
<label class="cz-label" for="cz-font">font</label>
|
|
206
|
-
<select id="cz-font" class="select-mini">
|
|
207
|
-
<option value="outfit">Outfit</option>
|
|
208
|
-
<option value="grotesk">Space Grotesk</option>
|
|
209
|
-
<option value="mono">JetBrains Mono</option>
|
|
210
|
-
<option value="system">System</option>
|
|
211
|
-
</select>
|
|
212
|
-
<label class="cz-label">effects</label>
|
|
213
|
-
<div class="cz-toggles">
|
|
214
|
-
<label class="cz-toggle"><input type="checkbox" id="cz-particles" checked><span>particles</span></label>
|
|
215
|
-
<label class="cz-toggle"><input type="checkbox" id="cz-grid" checked><span>grid</span></label>
|
|
216
|
-
<label class="cz-toggle"><input type="checkbox" id="cz-noise" checked><span>noise</span></label>
|
|
217
|
-
<label class="cz-toggle"><input type="checkbox" id="cz-anim" checked><span>animations</span></label>
|
|
218
|
-
<label class="cz-toggle"><input type="checkbox" id="cz-sound"><span>sound fx</span></label>
|
|
219
|
-
<label class="cz-toggle"><input type="checkbox" id="cz-work"><span>work mode (H)</span></label>
|
|
220
|
-
</div>
|
|
221
|
-
<input id="cz-name" class="search-input" type="text" maxlength="20" placeholder="DRIVER">
|
|
222
|
-
<button class="btn ghost btn-block" id="cz-reset">reset everything</button>
|
|
223
|
-
<p class="cz-note">everything saves to your browser automatically</p>
|
|
224
|
-
</div>
|
|
225
|
-
</aside>
|
|
226
|
-
<!-- modals -->
|
|
227
|
-
<div class="modal hidden" id="launcher-modal" role="dialog" aria-modal="true">
|
|
283
|
+
<!-- Modals -->
|
|
284
|
+
<div class="modal hidden" id="launcher-modal">
|
|
228
285
|
<div class="launcher-bar">
|
|
229
286
|
<button class="icon-btn" id="launcher-back">←</button>
|
|
230
287
|
<span class="launcher-title" id="launcher-title">—</span>
|
|
231
288
|
<div class="launcher-actions">
|
|
232
|
-
<button class="btn ghost btn-sm" id="launcher-ext">open in new tab</button>
|
|
233
289
|
<button class="btn ghost btn-sm" id="launcher-refresh">⟳</button>
|
|
234
|
-
<button class="btn ghost btn-sm" id="launcher-fs">⚬ fullscreen</button>
|
|
235
290
|
<button class="icon-btn" id="launcher-close">✕</button>
|
|
236
291
|
</div>
|
|
237
292
|
</div>
|
|
238
293
|
<div class="launcher-frame-wrap">
|
|
239
|
-
<iframe id="launcher-frame" sandbox="allow-scripts allow-same-origin allow-popups
|
|
294
|
+
<iframe id="launcher-frame" sandbox="allow-scripts allow-same-origin allow-popups"></iframe>
|
|
240
295
|
</div>
|
|
241
296
|
</div>
|
|
242
297
|
|
|
243
|
-
<
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
<div class="launcher-actions">
|
|
248
|
-
<button class="btn ghost btn-sm" id="player-toggle" title="switch player engine">⇤ engine</button>
|
|
249
|
-
<button class="btn ghost btn-sm" id="player-mark">✓ watched</button>
|
|
250
|
-
<button class="icon-btn" id="player-close">✕</button>
|
|
251
|
-
</div>
|
|
252
|
-
</div>
|
|
253
|
-
<div class="player-stage" id="player-stage"></div>
|
|
254
|
-
</div>
|
|
298
|
+
<script>
|
|
299
|
+
// Enhanced Security Protection System
|
|
300
|
+
(function() {
|
|
301
|
+
'use strict';
|
|
255
302
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
303
|
+
// Anti-debugging and protection systems
|
|
304
|
+
let devtoolsOpen = false;
|
|
305
|
+
const protectionActive = true;
|
|
306
|
+
// Comprehensive DevTools Detection
|
|
307
|
+
function detectDevTools() {
|
|
308
|
+
const threshold = 160;
|
|
309
|
+
|
|
310
|
+
// Method 1: Console detection
|
|
311
|
+
let devtools = { open: false };
|
|
312
|
+
const consoleMethods = ['debug', 'clear', 'error', 'info', 'log', 'warn', 'dir', 'dirxml', 'table', 'trace', 'group', 'groupCollapsed', 'groupEnd', 'time', 'timeEnd', 'profile', 'profileEnd', 'assert', 'count', 'exception'];
|
|
313
|
+
for (let method of consoleMethods) {
|
|
314
|
+
console[method] = function() {};
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// Method 2: Timing-based detection
|
|
318
|
+
let start = performance.now();
|
|
319
|
+
debugger;
|
|
320
|
+
let end = performance.now();
|
|
321
|
+
if (end - start > 100) {
|
|
322
|
+
triggerSecurity();
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// Method 3: Size-based detection
|
|
326
|
+
setInterval(() => {
|
|
327
|
+
if (window.outerHeight - window.innerHeight > threshold ||
|
|
328
|
+
window.outerWidth - window.innerWidth > threshold) {
|
|
329
|
+
triggerSecurity();
|
|
330
|
+
}
|
|
331
|
+
}, 500);
|
|
332
|
+
|
|
333
|
+
// Method 4: toString detection
|
|
334
|
+
let element = new Image();
|
|
335
|
+
Object.defineProperty(element, 'id', {
|
|
336
|
+
get: function() { triggerSecurity(); }
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
// Method 5: Function toString detection
|
|
340
|
+
let re = /./;
|
|
341
|
+
re.toString = re.toString.toString();
|
|
342
|
+
try { console.log('%c', re); } catch (e) { triggerSecurity(); }
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// Enhanced keyboard and context menu blocking
|
|
346
|
+
function initSecurityProtection() {
|
|
347
|
+
// Block all inspection shortcuts
|
|
348
|
+
document.addEventListener('keydown', function(e) {
|
|
349
|
+
const forbidden = [
|
|
350
|
+
e.key === 'F12',
|
|
351
|
+
(e.ctrlKey || e.metaKey) && e.shiftKey && ['I', 'C', 'J', 'K'].includes(e.key.toUpperCase()),
|
|
352
|
+
(e.ctrlKey || e.metaKey) && ['U', 'S', 'A', 'F', 'G', 'H', 'P'].includes(e.key.toUpperCase()),
|
|
353
|
+
e.ctrlKey && e.shiftKey && e.key.toUpperCase() === 'C',
|
|
354
|
+
e.key === 'F1' || e.key === 'F3' || e.key === 'F5',
|
|
355
|
+
(e.ctrlKey || e.metaKey) && e.key === 'r'
|
|
356
|
+
];
|
|
357
|
+
|
|
358
|
+
if (forbidden.some(Boolean)) {
|
|
359
|
+
e.preventDefault();
|
|
360
|
+
e.stopPropagation();
|
|
361
|
+
e.stopImmediatePropagation();
|
|
362
|
+
triggerSecurity();
|
|
363
|
+
return false;
|
|
364
|
+
}
|
|
365
|
+
}, true);
|
|
366
|
+
|
|
367
|
+
// Block context menu
|
|
368
|
+
document.addEventListener('contextmenu', function(e) {
|
|
369
|
+
e.preventDefault();
|
|
370
|
+
e.stopPropagation();
|
|
371
|
+
triggerSecurity();
|
|
372
|
+
return false;
|
|
373
|
+
}, true);
|
|
374
|
+
|
|
375
|
+
// Block text selection
|
|
376
|
+
document.addEventListener('selectstart', function(e) {
|
|
377
|
+
if (!['INPUT', 'TEXTAREA'].includes(e.target.tagName)) {
|
|
378
|
+
e.preventDefault();
|
|
379
|
+
return false;
|
|
380
|
+
}
|
|
381
|
+
}, true);
|
|
382
|
+
|
|
383
|
+
// Block drag operations
|
|
384
|
+
document.addEventListener('dragstart', function(e) {
|
|
385
|
+
e.preventDefault();
|
|
386
|
+
return false;
|
|
387
|
+
}, true);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
function triggerSecurity() {
|
|
391
|
+
if (!devtoolsOpen) {
|
|
392
|
+
devtoolsOpen = true;
|
|
393
|
+
document.getElementById('security-warning').style.display = 'flex';
|
|
394
|
+
|
|
395
|
+
// Clear the page content
|
|
396
|
+
setTimeout(() => {
|
|
397
|
+
document.body.innerHTML = '<div style="color:#ff4444; text-align:center; padding:50px; font-size:24px;">Access Denied</div>';
|
|
398
|
+
}, 3000);
|
|
399
|
+
|
|
400
|
+
// Infinite alert loop (commented out to avoid user annoyance)
|
|
401
|
+
// setInterval(() => alert('Unauthorized access detected!'), 100);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
// Encrypted and obfuscated game data
|
|
405
|
+
// This data is base64 encoded and ROT13 encrypted to hide the URLs
|
|
406
|
+
const encryptedGameData = 'W3siaWQiOiJDb29raWUgQ2xpY2tlciIsIm5hbWUiOiJDb29raWUgQ2xpY2tlciBURVNUIiwidXJsIjoiaHR0cHM6XC9cL2hhY2tmZ2cuY29tXC9lZGN1YmUtY29va2llLWNsaWNrZXJANS4wLjBcL2luZGV4Lmh0bWwiLCJjb3ZlciI6ImRhdGE6aW1hZ2VcL2pwZWc7YmFzZTY0LFwvOWpcLzRBQVFTa1pKUmdBQkFRQUFBUUFCQUFEXC8yd0NFQUFrR0J4TVRFaFVURXhNVkZoVVhHQmdZR0JnWEdCZ1lHQm9WRnhnWUZ4b2VHaDNZSUNnZ0dob2xIUmNkSVRFaEpTa3JMaTR1R0I4ek9ETXROeWd0TGlCQ2dvS0RnME9NeEFRR2kwbElDWXRMUzh2THkwdExTMHRMUzB0TFMwdExTMHRMUzB0TFMwdExTMHRMUzB0TFMwdExTMHRMUzB0TFMwdExTMHRMUzB0TFMwdExTMHRMUzB0TGZcL0FBQUVJQU9FQTRRTUJJZ0FDRVEEREE9UUhcL3hBQWNBQUFDSWdNQkFRQUFBQUFBQUFBQUFBQUJBZ01EQkFVR0J3Y0pDZ3NGXC9FQUI0SUJEUUVEQWdRSUJBNVRVbE1TQUFBQkFnVWdCWGpMXC9BQlI0aUJCUUVGQndnS0RCQUZHaEVJSHhJRUNRc0xFZzhSRml3OUloUVVIQ3dPRnhvZkRoOFFKekZMTGlwUVFBZ3hCQWNIQnhJUERoOFNIUzBzSlI0akxUZzRLemNnRkNRc1JWaFNjQjhqRndNdUV4UWNGZzlcL0FSb2VHUUVGR3dVSURCZ1FKand3aERDZ3dCRVJCRUNnVUxGQkVCQndNSEl4TVJOUzlSUERnNExTOXJLelVzTXpQQkFRRWRBZ1VBUVhJSURnWkFSUUVGQndNREFBQUFBQUFBQUFBQUFBQUJBQUlCQXdBRUJRY0FDQUFBQUFBQUFBQUFBQUFBZ01CQkFBRkJnY0lDUW9MXC9BQWNBUUpHQVNBeEhBTUJFVWNIQVVnS0J3RWJBeFlTSkVGSkVsUWJlaG9pRnhSWUZDSW9HWG9jRmg4akhoWWJFaFNjXC9BREFBQUFBQUFBQUFBQUFBQUJBQUlCQXdBRUJRY0lCaHNcL0FBZ0FBZ0lJQndnQ0JBRWNBUUlGQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBIiwiZGVzYyI6ImNvb2wiLCJ0YWdzIjpbImNvb2tpZSIsIjJEIl0sImNvbG9yIjoiIzIyZDNlZSJ9LHsiaWQiOiJyZWNvaWwiLCJuYW1lIjoiUmVjb2lsIiwidXJsIjoiaHR0cHM6XC9cL3R2cWVldnAtbnlybnB4LTMyNTMyMS5senZudmUubnBwXC8iLCJjb3ZlciI6Imh0dHBzOlwvXC92bmFwbnFyLnBienZcL3Z6bnR2ZlwvNUU5RjQwREE3RjlDOUZBOC5qY3QiLCJkZXNjIjoicmVjb2lsIGxpa2UgZHJpdnZlIG1hZCIsInRhZ3MiOlsiY2xvc2VkLXdvcmxkIiwiYWN0aW9uIiwiMkQiXSwiY29sb3IiOiIjZmY2YjFhIn0seyJpZCI6InJldHJvIGJhbGwiLCJuYW1lIjoiUmV0cm8gQmFsbCIsInVybCI6Imh0dHBzOlwvXC9ianpwcGZmZXZ0dGZvbS5oZi1uZnN1bnJuLTEub2VucHBsc2ticHFudWYuYnpuXC9hXC92cXpwZm5kdy1pMjMxMDAxLTE1MTgtb3IxLjBcL2JcL29ocGJwZi0yMDIzMTAwMS0xNTE4LXJvMS4wXC9iXC92YXFyaC5hZ3p5IiwiY292ZXIiOiJodHRwczpcL1wvcmFwZWxjZ3JxLTA6Ly93d3cuTG5nem4uZ3F3LnBieVwvZnJucHByZlwvcT1nYWE5UmNUZkVFVWJYb3BROTVWMzBicnUyVWRnZHlzdE1EOEVsekNERnpINms2X3BVUSZzPTEwIiwiZGVzYyI6InRvdWNoZG93biIsInRhZ3MiOlsic3BvcnRzIiwiYWN0aW9uIl0sImNvbG9yIjoiI2E4NTVmNyJ9XQ==';
|
|
407
|
+
|
|
408
|
+
// Decryption functions
|
|
409
|
+
function rot13(str) {
|
|
410
|
+
return str.replace(/[a-zA-Z]/g, function(c) {
|
|
411
|
+
return String.fromCharCode((c <= 'Z' ? 90 : 122) >= (c = c.charCodeAt(0) + 13) ? c : c - 26);
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
function decodeGameData() {
|
|
416
|
+
try {
|
|
417
|
+
// First decode base64, then apply ROT13
|
|
418
|
+
let decoded = atob(encryptedGameData);
|
|
419
|
+
let decrypted = rot13(decoded);
|
|
420
|
+
return JSON.parse(decrypted);
|
|
421
|
+
} catch (e) {
|
|
422
|
+
// Return empty array if decryption fails
|
|
423
|
+
return [];
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// Additional URL obfuscation
|
|
428
|
+
function deobfuscateUrl(url) {
|
|
429
|
+
// Replace obfuscated domains back to real ones
|
|
430
|
+
return url
|
|
431
|
+
.replace(/hackfgg\.com/g, 'unpkg.com')
|
|
432
|
+
.replace(/tvqeevp-nyrnpx-325321\.lzvave\.npp/g, 'generic-alpaca-325321.framer.app')
|
|
433
|
+
.replace(/vnpnqr\.pbz/g, 'fancade.com')
|
|
434
|
+
.replace(/byppfggentr\.hf-nfuoeha-1\.benpsyrhqqpybhq\.pbz/g, 'objectstorage.us-ashburn-1.oraclecloud.com');
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// Safe game loading with additional protection
|
|
438
|
+
function loadGames() {
|
|
439
|
+
if (!protectionActive) return [];
|
|
440
|
+
|
|
441
|
+
const games = decodeGameData();
|
|
442
|
+
return games.map(game => ({
|
|
443
|
+
...game,
|
|
444
|
+
url: deobfuscateUrl(game.url),
|
|
445
|
+
// Add timestamp to prevent caching of URLs
|
|
446
|
+
_loaded: Date.now()
|
|
447
|
+
}));
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
// Game rendering with obfuscated data access
|
|
451
|
+
function renderGames() {
|
|
452
|
+
const gameGrid = document.getElementById('game-grid');
|
|
453
|
+
if (!gameGrid) return;
|
|
454
|
+
|
|
455
|
+
const games = loadGames();
|
|
456
|
+
gameGrid.innerHTML = '';
|
|
457
|
+
|
|
458
|
+
games.forEach((game, index) => {
|
|
459
|
+
const card = document.createElement('div');
|
|
460
|
+
card.className = 'game-card';
|
|
461
|
+
card.style.setProperty('--gcolor', game.color || '#ff6b1a');
|
|
462
|
+
card.setAttribute('data-game-index', index);
|
|
463
|
+
|
|
464
|
+
card.innerHTML = `
|
|
465
|
+
<div class="game-cover">
|
|
466
|
+
${game.cover ? `<img src="${game.cover}" alt="" loading="lazy">` : `<div class="cover-fallback">${game.name.slice(0, 2).toUpperCase()}</div>`}
|
|
467
|
+
<button class="game-play" onclick="launchGame(${index})">▶</button>
|
|
468
|
+
</div>
|
|
469
|
+
<div class="game-body">
|
|
470
|
+
<div class="game-name">${game.name}</div>
|
|
471
|
+
<div class="game-tags">${(game.tags || []).map(tag => `<span class="game-tag">${tag}</span>`).join('')}</div>
|
|
472
|
+
<div class="game-desc">${game.desc || ''}</div>
|
|
473
|
+
</div>
|
|
474
|
+
`;
|
|
475
|
+
|
|
476
|
+
gameGrid.appendChild(card);
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
// Secure game launcher
|
|
480
|
+
window.launchGame = function(index) {
|
|
481
|
+
if (!protectionActive) return;
|
|
482
|
+
|
|
483
|
+
const games = loadGames();
|
|
484
|
+
if (!games[index]) return;
|
|
485
|
+
|
|
486
|
+
const game = games[index];
|
|
487
|
+
const modal = document.getElementById('launcher-modal');
|
|
488
|
+
const frame = document.getElementById('launcher-frame');
|
|
489
|
+
const title = document.getElementById('launcher-title');
|
|
490
|
+
|
|
491
|
+
if (modal && frame && title) {
|
|
492
|
+
title.textContent = game.name;
|
|
493
|
+
// Add additional URL obfuscation at runtime
|
|
494
|
+
frame.src = game.url + '?t=' + Date.now();
|
|
495
|
+
modal.classList.remove('hidden');
|
|
496
|
+
document.body.style.overflow = 'hidden';
|
|
497
|
+
}
|
|
498
|
+
};
|
|
499
|
+
|
|
500
|
+
// Modal controls
|
|
501
|
+
function initModalControls() {
|
|
502
|
+
const closeBtn = document.getElementById('launcher-close');
|
|
503
|
+
const backBtn = document.getElementById('launcher-back');
|
|
504
|
+
const refreshBtn = document.getElementById('launcher-refresh');
|
|
505
|
+
const modal = document.getElementById('launcher-modal');
|
|
506
|
+
const frame = document.getElementById('launcher-frame');
|
|
507
|
+
|
|
508
|
+
if (closeBtn) {
|
|
509
|
+
closeBtn.addEventListener('click', () => {
|
|
510
|
+
if (frame) frame.src = 'about:blank';
|
|
511
|
+
if (modal) modal.classList.add('hidden');
|
|
512
|
+
document.body.style.overflow = '';
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
if (backBtn) {
|
|
517
|
+
backBtn.addEventListener('click', () => {
|
|
518
|
+
try {
|
|
519
|
+
frame.contentWindow.history.back();
|
|
520
|
+
} catch (e) {
|
|
521
|
+
// Ignore cross-origin errors
|
|
522
|
+
}
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
if (refreshBtn) {
|
|
527
|
+
refreshBtn.addEventListener('click', () => {
|
|
528
|
+
if (frame) frame.src = frame.src;
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
if (modal) {
|
|
533
|
+
modal.addEventListener('click', (e) => {
|
|
534
|
+
if (e.target === modal) {
|
|
535
|
+
if (frame) frame.src = 'about:blank';
|
|
536
|
+
modal.classList.add('hidden');
|
|
537
|
+
document.body.style.overflow = '';
|
|
538
|
+
}
|
|
539
|
+
});
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
// Initialize everything with security
|
|
544
|
+
function initSecureSystem() {
|
|
545
|
+
// Initialize security first
|
|
546
|
+
initSecurityProtection();
|
|
547
|
+
detectDevTools();
|
|
548
|
+
|
|
549
|
+
// Initialize UI components
|
|
550
|
+
initModalControls();
|
|
551
|
+
renderGames();
|
|
552
|
+
|
|
553
|
+
// Hide security warning after a delay if no threats detected
|
|
554
|
+
setTimeout(() => {
|
|
555
|
+
if (!devtoolsOpen) {
|
|
556
|
+
const warning = document.getElementById('security-warning');
|
|
557
|
+
if (warning) warning.style.display = 'none';
|
|
558
|
+
}
|
|
559
|
+
}, 2000);
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
// Anti-tampering protection
|
|
563
|
+
Object.defineProperty(window, 'loadGames', {
|
|
564
|
+
value: loadGames,
|
|
565
|
+
writable: false,
|
|
566
|
+
configurable: false
|
|
567
|
+
});
|
|
568
|
+
|
|
569
|
+
Object.defineProperty(window, 'decodeGameData', {
|
|
570
|
+
value: function() { triggerSecurity(); },
|
|
571
|
+
writable: false,
|
|
572
|
+
configurable: false
|
|
573
|
+
});
|
|
574
|
+
|
|
575
|
+
// Initialize when DOM is ready
|
|
576
|
+
if (document.readyState === 'loading') {
|
|
577
|
+
document.addEventListener('DOMContentLoaded', initSecureSystem);
|
|
578
|
+
} else {
|
|
579
|
+
initSecureSystem();
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
// Prevent console access to sensitive functions
|
|
583
|
+
window.console = new Proxy(console, {
|
|
584
|
+
get: function(target, prop) {
|
|
585
|
+
if (['log', 'warn', 'error', 'info', 'debug'].includes(prop)) {
|
|
586
|
+
return function() {};
|
|
587
|
+
}
|
|
588
|
+
return target[prop];
|
|
589
|
+
}
|
|
590
|
+
});
|
|
591
|
+
|
|
592
|
+
// Additional runtime protection
|
|
593
|
+
setInterval(() => {
|
|
594
|
+
// Check for common debugging patterns
|
|
595
|
+
if (window.outerWidth - window.innerWidth > 200 ||
|
|
596
|
+
window.outerHeight - window.innerHeight > 200) {
|
|
597
|
+
triggerSecurity();
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
// Check for modified functions
|
|
601
|
+
if (typeof renderGames !== 'function' ||
|
|
602
|
+
typeof loadGames !== 'function') {
|
|
603
|
+
triggerSecurity();
|
|
604
|
+
}
|
|
605
|
+
}, 1000);
|
|
286
606
|
|
|
287
|
-
|
|
607
|
+
})();
|
|
608
|
+
</script>
|
|
288
609
|
|
|
289
|
-
<script src="js/data.js"></script>
|
|
290
|
-
<script src="js/app.js"></script>
|
|
291
610
|
</body>
|
|
292
611
|
</html>
|