Skip to content

Commit 98114f5

Browse files
authored
Update index.html
1 parent b522a82 commit 98114f5

1 file changed

Lines changed: 3 additions & 282 deletions

File tree

index.html

Lines changed: 3 additions & 282 deletions
Original file line numberDiff line numberDiff line change
@@ -1,289 +1,10 @@
11
<!DOCTYPE html>
22
<html lang="en">
33
<head>
4-
<meta charset="utf-8" />
5-
<meta name="viewport" content="width=device-width, initial-scale=1" />
6-
<title>Stephen's Apps</title>
7-
<meta name="description" content="A collection of Stephen B's apps — StikDebug, StikBridge beta, and more." />
8-
<meta name="theme-color" content="#0E1218">
9-
<link rel="preconnect" href="https://stikdebug.xyz" crossorigin>
10-
<style>
11-
:root{
12-
--bg: #0E1218; /* solid site background */
13-
--panel: #141b22; /* solid cards */
14-
--panel-2: #10171e; /* alt panel */
15-
--stroke: rgba(255,255,255,0.08);
16-
--shadow: rgba(0,0,0,0.28);
17-
--tint: #293B45;
18-
--fg: #ffffff;
19-
--fg-muted: rgba(255,255,255,0.72);
20-
--chip-bg: rgba(255,255,255,0.08);
21-
--chip-stroke: rgba(255,255,255,0.18);
22-
--radius: 16px;
23-
--gap: 14px;
24-
--maxw: 1200px;
25-
26-
/* Responsive type scale */
27-
--h1: clamp(22px, 4vw, 32px);
28-
--h2: clamp(18px, 2.6vw, 22px);
29-
--body: 16px;
30-
--small: 14px;
31-
}
32-
33-
html, body {
34-
height: 100%;
35-
margin: 0;
36-
color: var(--fg);
37-
background: var(--bg); /* SOLID */
38-
font: var(--body)/1.5 ui-rounded, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, Apple Color Emoji, Segoe UI Emoji;
39-
-webkit-text-size-adjust: 100%;
40-
text-rendering: optimizeLegibility;
41-
}
42-
43-
.page { min-height: 100%; display: grid; grid-template-rows: auto 1fr auto; }
44-
.container { max-width: var(--maxw); margin: 0 auto; padding: 20px 16px; }
45-
@media (min-width: 720px){ .container { padding: 28px 20px; } }
46-
47-
.card {
48-
position: relative;
49-
border-radius: var(--radius);
50-
background: var(--panel); /* SOLID panels */
51-
border: 1px solid var(--stroke);
52-
box-shadow: 0 8px 18px var(--shadow);
53-
}
54-
.card.alt { background: var(--panel-2); }
55-
.card.pad { padding: 14px; }
56-
@media (min-width: 720px){ .card.pad { padding: 18px; } }
57-
58-
.hero { display:flex; gap:16px; align-items:flex-start; flex-wrap: wrap; }
59-
.hero-title { font-size: var(--h1); font-weight: 800; letter-spacing:.2px; margin:0; }
60-
.hero-sub { color: var(--fg-muted); margin: 4px 0 0; font-weight: 600; }
61-
62-
.tags { display:flex; gap:8px; flex-wrap: wrap; margin-top: 10px; }
63-
.chip { display:inline-flex; align-items:center; gap:6px; padding: 6px 10px; border-radius: 999px; background: var(--chip-bg); border: 1px solid var(--chip-stroke); font-weight: 700; font-size: var(--small); }
64-
.chip.beta { color: #ffd166; }
65-
66-
.toolbar { display:flex; gap:10px; align-items:center; flex-wrap: wrap; margin-left: auto; }
67-
.btn {
68-
padding: 10px 12px;
69-
border-radius: 12px;
70-
border: 1px solid var(--stroke);
71-
background: var(--panel-2);
72-
cursor: pointer;
73-
color: var(--fg);
74-
font-weight: 700; letter-spacing:.2px;
75-
transition: transform .12s ease, background-color .12s ease, border-color .12s ease;
76-
touch-action: manipulation;
77-
}
78-
.btn:hover { transform: translateY(-1px); }
79-
.btn:focus-visible { outline: 2px solid var(--tint); outline-offset: 2px; }
80-
.btn[aria-pressed="true"] { border-color: var(--tint); box-shadow: 0 0 0 2px color-mix(in oklab, var(--tint), transparent 70%); }
81-
82-
.grid { display:grid; gap: var(--gap); }
83-
/* 1 col mobile → 2 cols tablet → 3 cols desktop */
84-
.grid.apps { grid-template-columns: 1fr; }
85-
@media (min-width: 700px){ .grid.apps { grid-template-columns: repeat(2, minmax(0,1fr)); } }
86-
@media (min-width: 1040px){ .grid.apps { grid-template-columns: repeat(3, minmax(0,1fr)); } }
87-
88-
.app-card { display:flex; flex-direction:column; gap:12px; }
89-
.app-head { display:flex; gap:12px; align-items:center; }
90-
.app-icon {
91-
width:64px; height:64px; border-radius:14px; object-fit: cover; border: 1px solid var(--stroke);
92-
flex: 0 0 auto;
93-
}
94-
.app-title { margin:0; font-size: clamp(16px, 1.8vw, 18px); font-weight: 800; }
95-
.app-sub { margin:2px 0 0; color: var(--fg-muted); font-weight:600; font-size: var(--small); }
96-
97-
.kv { display:grid; grid-template-columns: 120px 1fr; gap: 6px 12px; }
98-
@media (min-width: 720px){ .kv { grid-template-columns: 130px 1fr; } }
99-
.kv .k { color: var(--fg-muted); }
100-
101-
.actions { display:flex; gap:8px; flex-wrap: wrap; }
102-
.cta {
103-
display:inline-flex; align-items:center; gap:8px; padding:10px 12px; border-radius: 12px; text-decoration:none;
104-
color: var(--fg); border: 1px solid var(--stroke); background: var(--panel-2); font-weight: 800;
105-
transition: transform .12s ease, background-color .12s ease;
106-
}
107-
.cta:hover { transform: translateY(-1px); }
108-
.cta:focus-visible { outline: 2px solid var(--tint); outline-offset: 2px; }
109-
110-
/* Screenshot rail: efficient + mobile-friendly */
111-
.screens { display:grid; grid-auto-flow: column; gap: 10px; overflow-x:auto; padding-bottom:6px; scrollbar-width: thin; }
112-
.screens img {
113-
height: clamp(280px, 60vh, 420px);
114-
width: auto;
115-
border-radius: 12px;
116-
border: 1px solid var(--stroke);
117-
box-shadow: 0 8px 16px var(--shadow);
118-
object-fit: cover;
119-
}
120-
121-
.section-title { font-size: var(--h2); font-weight: 800; margin: 0 0 6px; }
122-
.section-sub { margin: 0 0 14px; color: var(--fg-muted); font-weight: 600; }
123-
124-
header, footer { padding: 20px 0; }
125-
footer { color: var(--fg-muted); font-weight:600; }
126-
127-
.muted { color: var(--fg-muted); }
128-
.hidden { display:none; }
129-
.divider { height:1px; background: var(--stroke); margin: 8px 0; }
130-
131-
/* Reduce motion for users who prefer it */
132-
@media (prefers-reduced-motion: reduce) {
133-
.btn, .cta { transition: none; }
134-
}
135-
136-
/* Improve tap targets on small screens */
137-
@media (max-width: 420px){
138-
.btn, .cta { padding: 12px 14px; }
139-
.app-icon { width:56px; height:56px; }
140-
.kv { grid-template-columns: 100px 1fr; }
141-
}
142-
</style>
4+
<meta charset="UTF-8">
5+
<title>Site 2.0 Coming Soon</title>
1436
</head>
1447
<body>
145-
<div class="page">
146-
<header class="container">
147-
<div class="card pad">
148-
<div class="hero">
149-
<div style="flex:1 1 auto; min-width:260px;">
150-
<h1 class="hero-title" id="siteTitle">Stephen's Apps</h1>
151-
<p class="hero-sub" id="siteSubtitle">A collection of apps</p>
152-
<div class="tags">
153-
<span class="chip" id="siteUrl"></span>
154-
</div>
155-
</div>
156-
<div class="toolbar">
157-
<button class="btn" id="filterFeatured" aria-pressed="true">Featured</button>
158-
<button class="btn" id="filterAll" aria-pressed="false">All Apps</button>
159-
</div>
160-
</div>
161-
</div>
162-
</header>
163-
164-
<main class="container" id="main">
165-
<section id="featuredSection" class="card pad">
166-
<h2 class="section-title">Featured</h2>
167-
<p class="section-sub">Curated picks from Stephen’s toolkit.</p>
168-
<div id="featuredGrid" class="grid apps" aria-live="polite"></div>
169-
</section>
170-
171-
<div style="height:18px"></div>
172-
173-
<section id="allSection" class="card pad hidden">
174-
<h2 class="section-title">All Apps</h2>
175-
<p class="section-sub">Explore every app in the Stik ecosystem.</p>
176-
<div id="appsGrid" class="grid apps"></div>
177-
</section>
178-
</main>
179-
180-
<footer class="container">
181-
<div class="card pad" style="text-align:center">
182-
<div>© <span id="year"></span> Stephen B</div>
183-
</div>
184-
</footer>
185-
</div>
186-
187-
<script>
188-
const ENDPOINT = 'https://stikdebug.xyz/apps.json';
189-
let STATE = null;
190-
const $ = s => document.querySelector(s);
191-
192-
function fmtBytes(b){
193-
if(!b||b<=0) return "";
194-
const u=["B","KB","MB","GB","TB"]; let i=0,v=b;
195-
while(v>=1024 && i<u.length-1){ v/=1024; i++; }
196-
return `${v.toFixed(i?1:0)} ${u[i]}`;
197-
}
198-
function isUpcoming(iso){ if(!iso) return false; return new Date(iso).getTime() > Date.now(); }
199-
200-
function renderSite(){
201-
const DATA = STATE; if(!DATA) return;
202-
document.title = DATA.name || "Stephen's Apps";
203-
$('#siteTitle').textContent = DATA.name || "Stephen's Apps";
204-
$('#siteSubtitle').textContent = DATA.subtitle || '';
205-
$('#siteUrl').textContent = (DATA.website||'').replace(/^https?:\/\//,'');
206-
document.documentElement.style.setProperty('--tint', DATA.tintColor || '#293B45');
207-
$('#year').textContent = new Date().getFullYear();
208-
209-
const byId = Object.fromEntries((DATA.apps||[]).map(a => [a.bundleIdentifier, a]));
210-
const feat = document.getElementById('featuredGrid'); feat.innerHTML='';
211-
(DATA.featuredApps||[]).forEach(id => { const a = byId[id]; if(a) feat.appendChild(renderAppCard(a)); });
212-
213-
const all = document.getElementById('appsGrid'); all.innerHTML='';
214-
(DATA.apps||[]).forEach(a => all.appendChild(renderAppCard(a)));
215-
}
216-
217-
function renderAppCard(app){
218-
const v = (app.versions && app.versions[0]) || {};
219-
const isBeta = !!app.beta || /beta/i.test(v.version||'') || /\.beta/.test(app.bundleIdentifier||'');
220-
const upcoming = isUpcoming(v.date);
221-
222-
const wrap = document.createElement('article');
223-
wrap.className = 'card pad app-card';
224-
wrap.innerHTML = `
225-
<div class="app-head">
226-
<img class="app-icon" src="${app.iconURL}" alt="${app.name} icon" loading="lazy" decoding="async" />
227-
<div style="flex:1 1 auto">
228-
<h3 class="app-title">${app.name}</h3>
229-
<p class="app-sub">${app.subtitle||''}</p>
230-
<div class="tags">
231-
${isBeta?'<span class="chip beta">Beta</span>':''}
232-
${upcoming?`<span class="chip">Launches ${new Date(v.date).toLocaleDateString('en-US',{month:'short',day:'numeric'})}</span>`:''}
233-
${app.minOSVersion?`<span class="chip">iOS ${app.minOSVersion}+</span>`:''}
234-
</div>
235-
</div>
236-
</div>
237-
238-
<div class="kv" style="margin-top:8px">
239-
<div class="k">Version</div><div>${v.version||'—'}</div>
240-
<div class="k">Updated</div><div>${v.date?new Date(v.date).toLocaleDateString():'—'}</div>
241-
<div class="k">Build</div><div>${v.buildVersion||'—'}</div>
242-
<div class="k">Size</div><div>${fmtBytes(v.size)||'—'}</div>
243-
</div>
244-
<div class="divider"></div>
245-
<p class="muted" style="margin:0">${app.localizedDescription||''}</p>
246-
<div class="screens" style="margin-top:10px">
247-
${(app.screenshots?.iphone||[])
248-
.map(s=>`<img src="${s.imageURL}" alt="${app.name} screenshot" loading="lazy" decoding="async">`)
249-
.join('')}
250-
</div>
251-
<div class="actions" style="margin-top:12px">
252-
${app.name==="StikDebug"
253-
? `<a class="cta" href="https://apps.apple.com/us/app/stikdebug/id6744045754" rel="noopener">App Store</a>`
254-
: ``}
255-
</div>`;
256-
return wrap;
257-
}
258-
259-
function setupInteractions(){
260-
const featBtn=$('#filterFeatured'), allBtn=$('#filterAll');
261-
const feat=$('#featuredSection'), all=$('#allSection');
262-
function setMode(m){
263-
const f = (m==='featured');
264-
feat.classList.toggle('hidden', !f);
265-
all.classList.toggle('hidden', f);
266-
featBtn.setAttribute('aria-pressed', f?'true':'false');
267-
allBtn.setAttribute('aria-pressed', f?'false':'true');
268-
localStorage.setItem('mode', m);
269-
document.getElementById('main').scrollIntoView({behavior:'smooth', block:'start'});
270-
}
271-
featBtn.onclick = () => setMode('featured');
272-
allBtn.onclick = () => setMode('all');
273-
setMode(localStorage.getItem('mode') || 'featured');
274-
}
275-
276-
(async function(){
277-
try{
278-
const res = await fetch(ENDPOINT, { cache: 'no-cache' });
279-
if(!res.ok) throw new Error(res.status);
280-
STATE = await res.json();
281-
renderSite();
282-
setupInteractions();
283-
}catch(e){
284-
console.error(e);
285-
}
286-
})();
287-
</script>
8+
<h1>Site 2.0 Coming Soon</h1>
2889
</body>
28910
</html>

0 commit comments

Comments
 (0)