mlv2boii 1.0.7 → 1.0.8
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 +46 -74
- package/package.json +1 -1
package/index.html
CHANGED
|
@@ -78,6 +78,37 @@
|
|
|
78
78
|
/* game icons: 10% edge so dark art never melts into the canvas */
|
|
79
79
|
.tile-img { outline: 1px solid rgba(255,255,255,0.1); outline-offset: -1px; }
|
|
80
80
|
|
|
81
|
+
|
|
82
|
+
/* Liquid glass: translucent fill, blur + saturation, bright top edge, light rim.
|
|
83
|
+
Used only on floating layers (header, sheets, toasts, controls). */
|
|
84
|
+
.glass {
|
|
85
|
+
background: rgba(255,255,255,0.06);
|
|
86
|
+
-webkit-backdrop-filter: blur(24px) saturate(180%);
|
|
87
|
+
backdrop-filter: blur(24px) saturate(180%);
|
|
88
|
+
box-shadow: inset 0 1px 0 rgba(255,255,255,0.22), inset 0 -1px 0 rgba(255,255,255,0.04), 0 10px 32px rgba(0,0,0,0.45);
|
|
89
|
+
}
|
|
90
|
+
.glass-sheet {
|
|
91
|
+
background: rgba(28,28,31,0.55);
|
|
92
|
+
-webkit-backdrop-filter: blur(40px) saturate(180%);
|
|
93
|
+
backdrop-filter: blur(40px) saturate(180%);
|
|
94
|
+
}
|
|
95
|
+
.glass::before {
|
|
96
|
+
content: ""; position: absolute; inset: 0; border-radius: inherit; padding: 1px; pointer-events: none;
|
|
97
|
+
background: linear-gradient(135deg, rgba(255,255,255,0.4), rgba(255,255,255,0.05) 40%, rgba(255,255,255,0.05) 60%, rgba(255,255,255,0.22));
|
|
98
|
+
-webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
|
|
99
|
+
-webkit-mask-composite: xor; mask-composite: exclude;
|
|
100
|
+
}
|
|
101
|
+
/* small controls: same edge light, no blur (nothing behind them to blur) */
|
|
102
|
+
.glass-lite { background: rgba(255,255,255,0.07); box-shadow: inset 0 1px 0 rgba(255,255,255,0.18), inset 0 0 0 1px rgba(255,255,255,0.08); }
|
|
103
|
+
.glass-lite:hover { background: rgba(255,255,255,0.12); }
|
|
104
|
+
.chip-on { background: rgba(232,20,47,0.92); box-shadow: inset 0 1px 0 rgba(255,255,255,0.35), inset 0 0 0 1px rgba(255,255,255,0.12); }
|
|
105
|
+
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
|
|
106
|
+
.glass { background: rgba(22,22,24,0.94); } .glass-sheet { background: rgba(18,18,20,0.97); }
|
|
107
|
+
}
|
|
108
|
+
@media (prefers-reduced-transparency: reduce) {
|
|
109
|
+
.glass, .glass-sheet { -webkit-backdrop-filter: none; backdrop-filter: none; background: #161618; }
|
|
110
|
+
}
|
|
111
|
+
|
|
81
112
|
.no-scrollbar { scrollbar-width: none; }
|
|
82
113
|
.no-scrollbar::-webkit-scrollbar { display: none; }
|
|
83
114
|
* { scrollbar-width: thin; scrollbar-color: #2c2c30 transparent; }
|
|
@@ -89,31 +120,15 @@
|
|
|
89
120
|
.rise { animation: rise 0.7s cubic-bezier(0.25, 0.46, 0.45, 0.94) both; animation-delay: var(--d, 0s); }
|
|
90
121
|
@media (prefers-reduced-motion: reduce) { .rise { animation: none; } }
|
|
91
122
|
|
|
92
|
-
/* Blank Overlay Lock Screen */
|
|
93
|
-
#blank-overlay {
|
|
94
|
-
position: fixed;
|
|
95
|
-
inset: 0;
|
|
96
|
-
background-color: #000000;
|
|
97
|
-
z-index: 99999;
|
|
98
|
-
display: flex;
|
|
99
|
-
transition: opacity 0.4s ease, visibility 0.4s ease;
|
|
100
|
-
}
|
|
101
|
-
#blank-overlay.unlocked {
|
|
102
|
-
opacity: 0;
|
|
103
|
-
visibility: hidden;
|
|
104
|
-
pointer-events: none;
|
|
105
|
-
}
|
|
106
123
|
</style>
|
|
107
124
|
</head>
|
|
108
125
|
|
|
109
126
|
<body class="min-h-screen bg-ink-950 font-sans text-ink-50 antialiased">
|
|
110
127
|
|
|
111
|
-
<!-- Blank Overlay Screen -->
|
|
112
|
-
<div id="blank-overlay"></div>
|
|
113
|
-
|
|
114
128
|
<!-- ================= HEADER ================= -->
|
|
115
|
-
<header class="sticky top-0 z-40
|
|
116
|
-
<div class="page-x mx-auto
|
|
129
|
+
<header class="pointer-events-none sticky top-0 z-40 pt-[calc(env(safe-area-inset-top)+0.75rem)]">
|
|
130
|
+
<div class="page-x mx-auto max-w-5xl">
|
|
131
|
+
<div class="glass pointer-events-auto relative flex h-14 items-center gap-4 rounded-full pl-5 pr-2">
|
|
117
132
|
<a href="#" class="flex shrink-0 items-center gap-2" aria-label="mlv2 home">
|
|
118
133
|
<span class="h-2.5 w-2.5 rounded-full bg-red-500"></span>
|
|
119
134
|
<span class="text-[17px] font-semibold tracking-[-0.02em]">mlv2</span>
|
|
@@ -123,10 +138,11 @@
|
|
|
123
138
|
<span id="count-badge" class="hidden shrink-0 text-[13px] tabular-nums text-ink-400 sm:block"><span id="count-num">0</span> games</span>
|
|
124
139
|
<div class="relative w-full max-w-[16rem]">
|
|
125
140
|
<svg class="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-ink-400" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><circle cx="11" cy="11" r="7"/><path d="m21 21-4.3-4.3"/></svg>
|
|
126
|
-
<input id="search" type="text" placeholder="Search games" aria-label="Search games" autocomplete="off" enterkeyhint="search" class="field pl-9" />
|
|
141
|
+
<input id="search" type="text" placeholder="Search games" aria-label="Search games" autocomplete="off" enterkeyhint="search" class="field rounded-full pl-9" />
|
|
127
142
|
</div>
|
|
128
143
|
</div>
|
|
129
144
|
</div>
|
|
145
|
+
</div>
|
|
130
146
|
</header>
|
|
131
147
|
|
|
132
148
|
<!-- ================= MAIN ================= -->
|
|
@@ -179,10 +195,10 @@
|
|
|
179
195
|
<p id="player-title" class="truncate text-[15px] font-semibold"></p>
|
|
180
196
|
</div>
|
|
181
197
|
<div class="flex shrink-0 items-center gap-2">
|
|
182
|
-
<a id="player-newtab" target="_blank" rel="noopener" title="Open in new tab" aria-label="Open in new tab" class="icon-btn">
|
|
198
|
+
<a id="player-newtab" target="_blank" rel="noopener" title="Open in new tab" aria-label="Open in new tab" class="glass-lite icon-btn">
|
|
183
199
|
<svg class="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><path d="M15 3h6v6"/><path d="M10 14 21 3"/></svg>
|
|
184
200
|
</a>
|
|
185
|
-
<button id="player-close" title="Close" aria-label="Close" class="icon-btn">
|
|
201
|
+
<button id="player-close" title="Close" aria-label="Close" class="glass-lite icon-btn">
|
|
186
202
|
<svg class="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M18 6 6 18M6 6l12 12"/></svg>
|
|
187
203
|
</button>
|
|
188
204
|
</div>
|
|
@@ -196,9 +212,9 @@
|
|
|
196
212
|
|
|
197
213
|
<!-- ================= ADMIN: PIN GATE ================= -->
|
|
198
214
|
<div id="admin-login-modal" class="fixed inset-0 z-50 hidden">
|
|
199
|
-
<div class="absolute inset-0 bg-black/
|
|
215
|
+
<div class="absolute inset-0 bg-black/50 backdrop-blur-md" data-admin-login-close></div>
|
|
200
216
|
<div class="absolute inset-0 flex items-center justify-center p-4">
|
|
201
|
-
<form id="admin-login-form" class="w-full max-w-[340px] rounded-[28px]
|
|
217
|
+
<form id="admin-login-form" class="glass glass-sheet relative w-full max-w-[340px] rounded-[28px] p-6 opacity-0" data-fx>
|
|
202
218
|
<p class="text-[19px] font-semibold">Enter PIN</p>
|
|
203
219
|
<p class="mt-1.5 text-pretty text-[14px] text-ink-400">This unlocks the admin screen on this device. Write access is controlled by your Appwrite permissions.</p>
|
|
204
220
|
|
|
@@ -217,9 +233,9 @@
|
|
|
217
233
|
|
|
218
234
|
<!-- ================= ADMIN: PANEL ================= -->
|
|
219
235
|
<div id="admin-panel" class="fixed inset-0 z-50 hidden">
|
|
220
|
-
<div class="absolute inset-0 bg-black/
|
|
236
|
+
<div class="absolute inset-0 bg-black/50 backdrop-blur-md" data-admin-panel-close></div>
|
|
221
237
|
<div class="absolute inset-0 flex items-start justify-center p-0 sm:items-center sm:p-4">
|
|
222
|
-
<div id="admin-panel-card" class="relative flex h-full w-full flex-col
|
|
238
|
+
<div id="admin-panel-card" class="glass glass-sheet relative flex h-full w-full flex-col opacity-0 sm:h-[85vh] sm:max-w-2xl sm:rounded-[32px]" data-fx>
|
|
223
239
|
|
|
224
240
|
<div class="flex h-14 shrink-0 items-center justify-between border-b border-white/[0.08] px-5 pt-[env(safe-area-inset-top)] box-content">
|
|
225
241
|
<div>
|
|
@@ -228,7 +244,7 @@
|
|
|
228
244
|
</div>
|
|
229
245
|
<div class="flex items-center gap-2">
|
|
230
246
|
<button id="admin-logout" class="btn btn-ghost">Lock</button>
|
|
231
|
-
<button data-admin-panel-close aria-label="Close" class="icon-btn">
|
|
247
|
+
<button data-admin-panel-close aria-label="Close" class="glass-lite icon-btn">
|
|
232
248
|
<svg class="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M18 6 6 18M6 6l12 12"/></svg>
|
|
233
249
|
</button>
|
|
234
250
|
</div>
|
|
@@ -278,50 +294,6 @@
|
|
|
278
294
|
<!-- ================= TOASTS ================= -->
|
|
279
295
|
<div id="toast-root" class="fixed bottom-4 right-4 z-[60] flex flex-col items-end gap-2 pb-[env(safe-area-inset-bottom)]"></div>
|
|
280
296
|
|
|
281
|
-
<!-- Konami Code Script with 1-Hour Expiration -->
|
|
282
|
-
<script>
|
|
283
|
-
(function() {
|
|
284
|
-
const STORAGE_KEY = 'mlv2_unlocked_expiry';
|
|
285
|
-
const ONE_HOUR_MS = 60 * 60 * 1000; // 1 hour in milliseconds
|
|
286
|
-
const overlay = document.getElementById('blank-overlay');
|
|
287
|
-
|
|
288
|
-
// Check on page load if unlock session is still valid
|
|
289
|
-
const savedExpiry = localStorage.getItem(STORAGE_KEY);
|
|
290
|
-
if (savedExpiry && Date.now() < parseInt(savedExpiry, 10)) {
|
|
291
|
-
overlay.classList.add('unlocked');
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
const konamiCode = [
|
|
295
|
-
'ArrowUp', 'ArrowUp',
|
|
296
|
-
'ArrowDown', 'ArrowDown',
|
|
297
|
-
'ArrowLeft', 'ArrowRight',
|
|
298
|
-
'ArrowLeft', 'ArrowRight',
|
|
299
|
-
'b', 'a', 'Enter'
|
|
300
|
-
];
|
|
301
|
-
let konamiIndex = 0;
|
|
302
|
-
|
|
303
|
-
document.addEventListener('keydown', (e) => {
|
|
304
|
-
const key = e.key.length === 1 ? e.key.toLowerCase() : e.key;
|
|
305
|
-
const targetKey = konamiCode[konamiIndex].length === 1
|
|
306
|
-
? konamiCode[konamiIndex].toLowerCase()
|
|
307
|
-
: konamiCode[konamiIndex];
|
|
308
|
-
|
|
309
|
-
if (key === targetKey) {
|
|
310
|
-
konamiIndex++;
|
|
311
|
-
if (konamiIndex === konamiCode.length) {
|
|
312
|
-
// Unlock website and save expiration time for 1 hour
|
|
313
|
-
overlay.classList.add('unlocked');
|
|
314
|
-
const expiryTime = Date.now() + ONE_HOUR_MS;
|
|
315
|
-
localStorage.setItem(STORAGE_KEY, expiryTime.toString());
|
|
316
|
-
konamiIndex = 0;
|
|
317
|
-
}
|
|
318
|
-
} else {
|
|
319
|
-
konamiIndex = 0;
|
|
320
|
-
}
|
|
321
|
-
});
|
|
322
|
-
})();
|
|
323
|
-
</script>
|
|
324
|
-
|
|
325
297
|
<script src="https://cdn.jsdelivr.net/npm/appwrite@26.2.0"></script>
|
|
326
298
|
<script type="module">
|
|
327
299
|
import { animate, stagger, inView } from "https://cdn.jsdelivr.net/npm/motion@12/+esm";
|
|
@@ -389,7 +361,7 @@ function toast(message, tone = "default") {
|
|
|
389
361
|
const root = el("toast-root");
|
|
390
362
|
const node = document.createElement("div");
|
|
391
363
|
const toneClasses = tone === "error" ? "text-red-300" : "text-ink-50";
|
|
392
|
-
node.className = `rounded-full ${toneClasses}
|
|
364
|
+
node.className = `glass glass-sheet relative rounded-full ${toneClasses} px-4 py-2.5 text-[14px] opacity-0`;
|
|
393
365
|
node.textContent = message;
|
|
394
366
|
root.appendChild(node);
|
|
395
367
|
fx(node, { opacity: [0, 1], y: [8, 0] }, { duration: 0.25, ease: "easeOut" });
|
|
@@ -422,7 +394,7 @@ function renderCategoryBar() {
|
|
|
422
394
|
.map((c) => {
|
|
423
395
|
const active = c === activeCategory;
|
|
424
396
|
return `<button data-cat="${escapeHtml(c)}" aria-pressed="${active}" class="chip ${
|
|
425
|
-
active ? "
|
|
397
|
+
active ? "chip-on text-white" : "glass-lite text-ink-300 hover:text-ink-50"
|
|
426
398
|
}">${escapeHtml(c)}</button>`;
|
|
427
399
|
})
|
|
428
400
|
.join("");
|
|
@@ -673,7 +645,7 @@ async function renderAdminList() {
|
|
|
673
645
|
<label class="hidden shrink-0 items-center gap-2 text-[13px] text-ink-300 sm:flex">
|
|
674
646
|
<input type="checkbox" data-field="enabled" data-id="${g.$id}" ${g.enabled === false ? "" : "checked"} class="h-4 w-4 accent-red-500" /> On
|
|
675
647
|
</label>
|
|
676
|
-
<button data-delete="${g.$id}" title="Delete" aria-label="Delete" class="icon-btn hover:!text-red-400">
|
|
648
|
+
<button data-delete="${g.$id}" title="Delete" aria-label="Delete" class="glass-lite icon-btn hover:!text-red-400">
|
|
677
649
|
<svg class="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 6h18M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2m3 0-1 14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2L4 6"/></svg>
|
|
678
650
|
</button>
|
|
679
651
|
</div>`
|