`;
}
function blackFull(){ return ``; }
function clubPenguinWhite(){
return `
`;
}
function spaceHey(){
return `
`;
}
/* Routes:
- home -> Google
- site/ -> catalog entry
- web/ -> arbitrary URL
*/
function renderHome(){
renderWeb("https://www.google.com", "Google");
addr.value = "web/https://www.google.com";
}
function renderSite(id){
const s = SITES.find(x=>x.id===id);
if(!s){ content.innerHTML = siteChrome("Not found", `Unknown site.
`); return; }
if(s.mode === "black-full"){ content.innerHTML = siteChrome(s.name, blackFull(), s.live); return; }
if(s.mode === "club-white"){ content.innerHTML = siteChrome(s.name, clubPenguinWhite(), s.live); return; }
if(s.mode === "spacehey"){ content.innerHTML = spaceHey(); return; }
// Default: try to embed live
content.innerHTML = siteChrome(s.name, renderLiveEmbed(s.live), s.live);
}
function renderWeb(url, label){
const safe = ensureHttp(url);
const title = label || safe;
content.innerHTML = siteChrome(title, renderLiveEmbed(safe), safe);
}
/* ======= Router ======= */
function go(path){ location.hash = "#" + path; }
function parseHash(){
const h = (location.hash || "#home").slice(1);
const [route, rest] = h.split("/",2);
if(route==="site" && rest){ renderSite(rest); addr.value = `site/${rest}`; }
else if(route==="web" && rest){
const url = decodeURIComponent(rest);
renderWeb(url);
addr.value = `web/${url}`;
} else { renderHome(); }
}
/* ======= Address bar behavior ======= */
addr.addEventListener("keydown", e=>{
if(e.key==="Enter"){
const val = addr.value.trim();
if(!val){ return; }
// direct commands
if(val==="home"){ go("home"); return; }
// site/ route
if(val.startsWith("site/")){ go(val); return; }
// web/ route
if(val.startsWith("web/")){
const raw = val.slice(4);
go("web/" + encodeURIComponent(raw));
return;
}
// If it looks like a URL, load it; else search Google
if(isLikelyUrl(val)){
go("web/" + encodeURIComponent(ensureHttp(val)));
}else{
const q = encodeURIComponent(val);
go("web/" + encodeURIComponent("https://www.google.com/search?q=" + q));
}
}
});
/* Toolbar buttons */
$("#btnBack").onclick = ()=> history.back();
$("#btnFwd").onclick = ()=> history.forward();
$("#btnRef").onclick = ()=> parseHash();
$("#btnHome").onclick = ()=> go("home");
window.addEventListener("hashchange", parseHash);
/* Start at Google home by default */
if(!location.hash){ go("home"); } else { parseHash(); }
/* ======= Helpers ======= */
function isLikelyUrl(input){
try{
if(/^https?:\/\//i.test(input)) return true;
if(/^[a-z]+:\/\//i.test(input)) return true;
// domain.tld[/path]
const m = input.match(/^[a-z0-9\-_.]+\.[a-z]{2,}([/:?#].*)?$/i);
return !!m;
}catch{ return false; }
}
function ensureHttp(u){
if(/^https?:\/\//i.test(u)) return u;
return "https://" + u;
}
function escapeHtml(s){ return String(s).replace(/[&<>"']/g, c=>({"&":"&","<":"<",">":">",'"':""","'":"'"}[c])); }