-
Notifications
You must be signed in to change notification settings - Fork 78
Expand file tree
/
Copy pathapps.html
More file actions
82 lines (73 loc) · 3.49 KB
/
apps.html
File metadata and controls
82 lines (73 loc) · 3.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Unblocked Apps & Sites — OutRed</title>
<meta name="description" content="Access popular websites and apps unblocked through OutRed. Works on school Chromebooks and filtered networks." />
<meta name="theme-color" content="#e63946" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="/css/style.css" />
<link id="favicon" rel="shortcut icon" href="/assets/favicon.png" type="image/x-icon" />
<script src="/js/tabcloak.js"></script>
<link rel="manifest" href="/assets/json/manifest.json" />
</head>
<body>
<div class="page">
<div class="container" style="padding-top:40px; padding-bottom:80px;">
<!-- ── AD: Leaderboard ───────────────────────────────────── -->
<div class="ad-slot ad-leaderboard" id="ad-apps-top" style="margin-bottom:36px; margin-left:auto; margin-right:auto;">
<!-- REPLACE with ad tag (728×90) -->
</div>
<div style="margin-bottom:28px;">
<h1 style="font-size:clamp(1.6rem,4vw,2.4rem); margin-bottom:6px;">Apps & Sites</h1>
<p style="color:var(--text-muted); font-size:0.9rem;">Quick access to popular sites and web apps.</p>
</div>
<div class="apps-grid" id="apps-grid">
<!-- Populated by JS -->
<div class="skeleton" style="height:130px; border-radius:var(--radius);"></div>
<div class="skeleton" style="height:130px; border-radius:var(--radius);"></div>
<div class="skeleton" style="height:130px; border-radius:var(--radius);"></div>
<div class="skeleton" style="height:130px; border-radius:var(--radius);"></div>
<div class="skeleton" style="height:130px; border-radius:var(--radius);"></div>
<div class="skeleton" style="height:130px; border-radius:var(--radius);"></div>
</div>
<!-- ── AD: mid ─────────────────────────────────────────── -->
<div class="ad-slot ad-full-banner" id="ad-apps-mid" style="margin-top:40px; margin-bottom:0;">
<!-- REPLACE with ad tag -->
</div>
</div>
</div>
<script src="/js/core.js"></script>
<script>
document.addEventListener('DOMContentLoaded', async () => {
const grid = document.getElementById('apps-grid');
try {
const res = await fetch('/assets/json/apps.json');
const apps = await res.json();
grid.innerHTML = '';
apps.forEach(app => {
const card = document.createElement('div');
card.className = 'app-card';
card.innerHTML = `
<img
src="/assets/img/apps/${app.img || 'no-img.jpg'}"
alt="${app.title}"
onerror="this.onerror=null;this.src='/assets/img/no-img.jpg'"
/>
<div class="app-card-name">${app.title}</div>
`;
card.addEventListener('click', () => {
if (app.url) window.open(app.url, '_blank', 'noopener');
});
grid.appendChild(card);
});
} catch (e) {
grid.innerHTML = `<p style="color:var(--text-muted); grid-column:1/-1; text-align:center; padding:40px;">Could not load apps.</p>`;
}
});
</script>
</body>
</html>