// in the ), OR by editing the fallback string on the next line.
// If left as-is with no backend reachable, the game safely falls back to a per-device board.
const LB_API = (typeof window!=='undefined' && window.TANKMAN_LB_API)
? window.TANKMAN_LB_API
: ('port/8000'.startsWith('__') ? 'http://localhost:8000' : 'port/8000');
// In a standalone / offline build there is no backend, so use a local
// (this-browser-only) leaderboard stored in localStorage.
let LB_LOCAL = !!window.__STANDALONE;
let lbRange = 'week';
let lbLastId = null; // row id of the score this player just submitted (to highlight)
function esc(s){ return String(s==null?'':s).replace(/[&<>"']/g, c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c])); }
/* ---- local (offline) leaderboard store ---- */
const LB_KEY = 'tankman_leaderboard_v1';
function lbLocalAll(){ try{ return JSON.parse(localStorage.getItem(LB_KEY)||'[]'); }catch(e){ return []; } }
function lbLocalSave(rows){ try{ localStorage.setItem(LB_KEY, JSON.stringify(rows)); }catch(e){} }
function lbLocalTop(range){
let rows = lbLocalAll();
if(range === 'week'){
const wk = Date.now() - 7*24*60*60*1000;
rows = rows.filter(r => (r.ts||0) >= wk);
}
// best score per username
const best = {};
for(const r of rows){
if(!best[r.username] || r.score > best[r.username].score) best[r.username] = r;
}
return Object.values(best).sort((a,b)=> b.score - a.score).slice(0,20);
}
function lbLocalInsert(rec){
const rows = lbLocalAll();
rec.id = 'l' + Date.now() + '_' + Math.floor(Math.random()*1e4);
rec.ts = Date.now();
rows.push(rec);
lbLocalSave(rows);
return rec.id;
}
function lbRender(rows){
const list = document.getElementById('lbList');
if(!rows.length){ list.innerHTML = '