Files

49 lines
5.3 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>The Gauntlet Overlay</title>
<style>
*{box-sizing:border-box;margin:0;padding:0}
html,body{width:100%;min-height:100%;background:transparent;color:#f8ead2;font-family:Georgia,'Times New Roman',serif;overflow:hidden}
body{display:grid;place-items:center;padding:18px}
.ledger{width:min(1120px,96vw);min-height:142px;max-height:350px;border-radius:18px;background:linear-gradient(90deg,#2b1b12,#49301c 48%,#2a1b13);box-shadow:0 26px 80px rgba(0,0,0,.75),inset 0 0 60px rgba(255,214,148,.08);padding:16px;border:1px solid rgba(255,222,162,.28);position:relative;overflow:hidden}
.ledger:before{content:"";position:absolute;inset:10px;border:1px solid rgba(255,226,170,.18);border-radius:12px;pointer-events:none}.paper{height:100%;border-radius:12px;background:radial-gradient(circle at 30% 5%,rgba(255,248,213,.18),transparent 25%),linear-gradient(120deg,#3d2819,#1f1711);padding:22px;position:relative;overflow:hidden}.paper:after{content:"";position:absolute;inset:0;background:repeating-linear-gradient(0deg,rgba(255,255,255,.025),rgba(255,255,255,.025) 1px,transparent 1px,transparent 5px);mix-blend-mode:screen;pointer-events:none}
.quests{position:relative;z-index:1;height:100%;display:flex;flex-direction:column}.top{display:flex;justify-content:space-between;align-items:center;border-bottom:1px solid rgba(255,226,170,.22);padding-bottom:10px;margin-bottom:12px;gap:16px}.top h2{font-size:30px;letter-spacing:.01em;white-space:nowrap}.rule{font-family:Segoe UI,Arial,sans-serif;color:#d9bd88;font-size:13px;text-align:right}.list{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;flex:1}.quest{min-height:66px;display:grid;grid-template-columns:46px minmax(0,1fr) auto;align-items:center;gap:12px;padding:10px 12px;border-radius:12px;background:rgba(0,0,0,.20);border:1px solid rgba(255,226,170,.16);font-family:Segoe UI,Arial,sans-serif;transition:opacity .2s ease, transform .2s ease, box-shadow .2s ease}.quest.active{background:linear-gradient(90deg,rgba(182,43,43,.60),rgba(192,139,56,.24));border-color:#e1b15f;box-shadow:0 0 24px rgba(218,153,61,.20),inset 0 0 22px rgba(255,218,141,.08);transform:translateY(-1px)}.icon{width:42px;height:42px;border-radius:10px;background:#2f2117;display:grid;place-items:center;font-size:22px;box-shadow:inset 0 0 12px rgba(255,222,162,.08)}.name{font-weight:850;color:#fff3d8;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-size:16px}.sub{font-size:12px;color:#d7c098;margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.tag{font-size:11px;text-transform:uppercase;letter-spacing:.12em;border:1px solid rgba(255,226,170,.22);padding:5px 8px;border-radius:999px;color:#d8bf91;white-space:nowrap}.active .tag{color:#1b110b;background:#f0c36d;border-color:#ffe0a0;font-weight:900}.cleared{opacity:.62}.cleared .tag{background:#28351f;color:#bbdea4}.failed .tag{background:#452020;color:#ffb2a8}.paused .tag{background:#2d3145;color:#bcc9ff}.empty-state{padding:22px;font-family:Segoe UI,Arial,sans-serif;color:#d9bd88;text-align:center}
@media (max-width:760px){body{padding:10px}.top{align-items:flex-start;flex-direction:column}.rule{text-align:left}.list{grid-template-columns:1fr}.ledger{max-height:95vh}.top h2{font-size:25px}}
</style>
</head>
<body>
<div class="ledger"><div class="paper"><main class="quests"><div class="top"><h2>The Gauntlet Ledger</h2><div class="rule" id="summary">Loading gauntlet...</div></div><div class="list" id="list"></div></main></div></div>
<script>
const list = document.getElementById('list');
const summary = document.getElementById('summary');
const labels = {active:'Active', queued:'Queued', cleared:'Cleared', paused:'Paused', failed:'Failed'};
const statusSub = {active:'Current game', queued:'In the gauntlet', cleared:'Cleared', paused:'Paused', failed:'Failed'};
function escapeHtml(s){return String(s ?? '').replace(/[&<>'"]/g, c => ({'&':'&amp;','<':'&lt;','>':'&gt;',"'":'&#39;','"':'&quot;'}[c]));}
function render(data){
const games = Array.isArray(data.games) ? data.games.filter(g => g && g.title) : [];
list.innerHTML = '';
if(!games.length){list.innerHTML = '<div class="empty-state">No games added yet. Use the editor to build your gauntlet.</div>'; summary.textContent = 'Waiting for games'; return;}
const active = games.find(g => g.status === 'active');
const cleared = games.filter(g => g.status === 'cleared').length;
summary.textContent = `${cleared}/${games.length} cleared${active ? ' · Active: ' + active.title : ' · No active game'}`;
for(const game of games){
const status = labels[game.status] ? game.status : 'queued';
const subtitle = game.subtitle || statusSub[status] || '';
const div = document.createElement('div');
div.className = `quest ${status}`;
div.innerHTML = `<div class="icon">${escapeHtml(game.icon || '◆')}</div><div><div class="name">${escapeHtml(game.title)}</div><div class="sub">${escapeHtml(subtitle)}</div></div><div class="tag">${labels[status]}</div>`;
list.appendChild(div);
}
}
async function load(){
try{const res = await fetch('gauntlet.json?cache=' + Date.now(), {cache:'no-store'}); render(await res.json());}
catch(err){summary.textContent = 'Could not load gauntlet.json';}
}
load(); setInterval(load, 2000);
</script>
</body>
</html>